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

cat: /dev/null: Permission denied #66

Open
lvml opened this issue Jun 6, 2017 · 21 comments
Open

cat: /dev/null: Permission denied #66

lvml opened this issue Jun 6, 2017 · 21 comments

Comments

@lvml
Copy link

lvml commented Jun 6, 2017

[I just realized the problem is much easier to reproduce, so here is my edited report:]

When creating any kind of unionfs on top of the root file system, it is not possible to access device files like /dev/null or /dev/zero, even if those are permitted for access by the user:

> unionfs -o use_ino,suid,dev,nonempty,allow_other  -o relaxed_permissions /=RW  union_root
>
> cat union_root/dev/null
cat: union_root/dev/null: Permission denied

I also tried with/without -o relaxed_permissions, with -o nodev and -o dev etc. - but that does not change the symptom.

When I look into the output when using unionfs with "-d", I find the following references to /dev/null in it:

LOOKUP /dev/null
getattr /dev/null
   NODEID: 59
   unique: 341, success, outsize: 144

An "strace" on the unionfs process does not reveal any good hint, either - the process will "lstat" /dev/null successfully, and there is no system call with regards to /dev/null that fails with ENOPERM.

@rpodgorny
Copy link
Owner

hmmm, this seems to be an issue deeper in fuse itself. the passthrough example from the libfuse examples behaves the same...

@lvml
Copy link
Author

lvml commented Jun 15, 2017

Should we submit an issue report to the libfuse maintainers?

@rpodgorny
Copy link
Owner

not sure, yet. maybe it's some kind of internal limitation that fuse is unable to work with character devices (or maybe no special files at all?)... or maybe i'm just doing something wrong.

but i guess it won't be that fatal to open an issue - the worst thing that can happen is it to be closed as invalid so feel free to go ahead... ;-)

@mrvn
Copy link

mrvn commented Jun 23, 2017

Does this only happen with /dev/null or all character devices?

On a practical side though: Most systems nowadays use a tmpfs or devtmpfs for /dev and you could use

mount --move /dev /union_root/dev

and keep /dev out of the unionfs.

@lvml
Copy link
Author

lvml commented Jun 23, 2017 via email

@mrvn
Copy link

mrvn commented Jun 27, 2017

unionfs as / without root? You are not going to be able to set that up.

The normal way to do this is to have /sbin/init a script that starts unionfs and then pivot_root + chroot. You are very much root there.

You might be able to fake it using fakechroot but that would be a special use case.

@lvml
Copy link
Author

lvml commented Jun 27, 2017

Using a unionfs-fuse mounted filesystem as / works very well without root privileges, as long as user namespaces are supported by the kernel - see AppImage/AppImageKit#406 for details.
You can just use unshare -r chroot ... to use it.

@lvml
Copy link
Author

lvml commented Jun 29, 2017

In case you want to try the use-case I described: Find my "makeaoi" software here:

https://github.com/lvml/makeaoi

@Nikratio
Copy link

I have my doubts about that makeaoi idea. Why is the overlay needed in the first place? Either the "bundle" really contains everything the application needs (in which case you could just chroot into it), or it does not - but in that case whatever functionality is pulled from the underlying filesystem will be mightily confused by the environment that it finds.

Seems like a much easier solution would be chroot, or an LD_PRELOAD that adds a prefix to each open() and exec() call.

@lvml
Copy link
Author

lvml commented Jul 13, 2017 via email

@lvml
Copy link
Author

lvml commented Jul 16, 2017

Good news: I was able to implement exemplary ioctl() support (starting with TCGETS and TCSETS, as those are used by bash and may other programs indirectly).

See https://github.com/lvml/unionfs-fuse/tree/fake_dev for a version of unionfs-fuse that supports a new option "-o fake_devices", which exposes devices as if they were regular files - but still allows the client application to perform ioctls() on it.

Another feature enabled by "-o fake_devices" is support for accessing files under /proc/, which unionfs-fuse so far did not allow to read/write.

This feature is now used in my https://github.com/lvml/makeaoi tool.

If anyone wants to test how this works: Compile the following into an executable named "test_ioctl":

#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <errno.h>

int main(int argc, char **argv) {

        struct termios t;
        memset(&t, 0, sizeof(t));

        fprintf(stderr, "doing TCGETS\n");

        if (0 != ioctl(0, TCGETS, &t)) {
                fprintf(stderr, "ioctl failed: %s\n", strerror(errno));
        }

        fprintf(stderr, "t.c_lflag = %d \n", t.c_lflag);
        fprintf(stderr, "t.c_lflag & ECHO = %d \n", t.c_lflag & ECHO);

        t.c_lflag ^= ECHO;

        fprintf(stderr, "doing TCSETS\n");

        if (0 != ioctl(0, TCSETS, &t)) {
                fprintf(stderr, "ioctl failed: %s\n", strerror(errno));
        }

        fprintf(stderr, "doing tcgetattr\n");
        if (0 != tcgetattr(0, &t)) {
                fprintf(stderr, "tcgetattr() failed: %s\n", strerror(errno));
        }

        return 0;
}

Then call it via this script:

#!/bin/bash

test_ioctl </dev/tty

This just toggles the echoing of characters to the terminal you started the script from.

(I'm intending to add support for more ioctl()s when I see them used by other applications I would like to pack into "application overlay images".)

@Nikratio
Copy link

Nikratio commented Jul 17, 2017 via email

@lvml
Copy link
Author

lvml commented Jul 17, 2017 via email

@Nikratio
Copy link

Nikratio commented Jul 18, 2017 via email

@lvml
Copy link
Author

lvml commented Jul 18, 2017 via email

@rpodgorny
Copy link
Owner

rpodgorny commented Jul 18, 2017 via email

@Nikratio
Copy link

Nikratio commented Jul 18, 2017 via email

@Nikratio
Copy link

Nikratio commented Jul 18, 2017 via email

@lvml
Copy link
Author

lvml commented Jul 18, 2017 via email

@lvml
Copy link
Author

lvml commented Jul 18, 2017 via email

@lvml
Copy link
Author

lvml commented Jul 30, 2017

BTW: I succeded to package "subsurface" using "makeaoi" such that subsurface can communicate with dive computers attached to serial ports - Proof of Concept example: https://transfer.sh/2tLny/subsurface-4.6.4-2-x86_64.AppImage

In addition to some ioctl() support I also had to implement poll() for unionfs-fuse - see https://github.com/lvml/unionfs-fuse/blob/fake_dev/src/fuse_ops.c#L665 for the bulk of relevant changes.

@rpodgorny: Maybe we can talk about whether/how to contribute my unionfs-fuse changes upstream - I guess others could possibly use the poll() support, too, and the "-o fake_devices" option should not disturb those who do not need it...

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

4 participants