Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Curious about how does balena etcher get permission to unmount disks? #78

Closed
ForestJohnson opened this issue Aug 29, 2020 · 4 comments
Closed

Comments

@ForestJohnson
Copy link

ForestJohnson commented Aug 29, 2020

Hello, forgive my ignorance as I am primarily a web developer and not as familiar with Node.js C++ modules. However I believe that really these things should be documented for "the rest of us".


I am developing an application using https://github.com/balena-io-modules/etcher-sdk

when I run

    MOUNTUTILS_DEBUG=1 npm start

and my code runs

    etcherSDK.multiWrite.decompressThenFlash({...})

then I see in the log

    [mountutils] Reading /proc/mounts
    [mountutils] Mount point /dev/sdc2 belongs to drive /dev/sdc
    [mountutils] Mount point /dev/sdc1 belongs to drive /dev/sdc
    [mountutils] Closing /proc/mounts
    [mountutils] Unmounting /media/forest/rootfs...
    [mountutils] Unmount MNT_EXPIRE /media/forest/rootfs: EAGAIN
    [mountutils] Unmount MNT_EXPIRE /media/forest/rootfs failed: Operation not permitted
    [mountutils] Unmount MNT_DETACH /media/forest/rootfs failed: Operation not permitted
    [mountutils] Unmount MNT_FORCE /media/forest/rootfs failed: Operation not permitted
    [mountutils] Unmounting /media/forest/boot...
    [mountutils] Unmount MNT_EXPIRE /media/forest/boot: EAGAIN
    [mountutils] Unmount MNT_EXPIRE /media/forest/boot failed: Operation not permitted
    [mountutils] Unmount MNT_DETACH /media/forest/boot failed: Operation not permitted
    [mountutils] Unmount MNT_FORCE /media/forest/boot failed: Operation not permitted
    [mountutils] Unmount complete

and onFail() gets called with "Unmount failed". This seems weird to me because according to the C code it should return "Unmount failed, access denied" when its a permissions issue: https://github.com/balena-io-modules/mountutils/blob/master/src/worker-unmount.cpp#L28

I am curious how does this work in production for balena etcher? currently I am just debugging on linux but of course I want this to work cross platform later on... how to get permission to unmount disks should be documented on https://github.com/balena-io-modules/etcher-sdk or https://github.com/balena-io-modules/mountutils!

is something like CAP_NET but for unmounting disks in linux ? (a way to allow a process to unmount disks even though its not running as root) or a way to trigger a "please enter your admin password to elevate privilege" prompt for a process ??

@ForestJohnson
Copy link
Author

ForestJohnson commented Aug 29, 2020

OK so I'm a dummy, I thought I remembered that Etcher worked in Linux without asking for admin password but now I am starting to learn, it looks like on linux it spawns a privileged process:

auth

and I am suspicious that this is related: https://github.com/balena-io/etcher/blob/master/afterPack.js

@ForestJohnson
Copy link
Author

ForestJohnson commented Aug 29, 2020

This looks related, how it reaches inside the AppImage on linux to spawn a sub-process

https://github.com/balena-io/etcher/blob/master/lib/gui/app/modules/image-writer.ts#L95

function writerArgv(): string[] {
	let entryPoint = path.join(
		electron.remote.app.getAppPath(),
		'generated',
		'child-writer.js',
	);
	// AppImages run over FUSE, so the files inside the mount point
	// can only be accessed by the user that mounted the AppImage.
	// This means we can't re-spawn Etcher as root from the same
	// mount-point, and as a workaround, we re-mount the original
	// AppImage as root.
	if (os.platform() === 'linux' && process.env.APPIMAGE && process.env.APPDIR) {
		entryPoint = entryPoint.replace(process.env.APPDIR, '');
		return [
			process.env.APPIMAGE,
			'-e',
			`require(\`\${process.env.APPDIR}${entryPoint}\`)`,
		];
	} else {
		return [process.argv[0], entryPoint];
	}
}

@ForestJohnson
Copy link
Author

ForestJohnson commented Aug 29, 2020

Here is the rest of the story, how it spawns a privileged sub process differently depending on the OS:

https://github.com/balena-io/etcher/blob/master/lib/gui/app/modules/image-writer.ts#L216

https://github.com/balena-io/etcher/blob/master/lib/shared/permissions.ts#L154

@ForestJohnson
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant