On Mar 29, 2015 5:18 PM, "Alban Crequy" <alban.cre...@gmail.com> wrote: > > From: Alban Crequy <al...@endocode.com> > > Some systems abusively restrict mknod, even when the device node already > exists in /dev. This is unfortunate because it prevents systemd-nspawn > from creating the basic devices in /dev in the container. > > This patch implements a workaround: when mknod fails, fallback on bind > mounts.
Could we just always use bind mounts and avoid the two code paths? Tom > Additionally, /dev/console was created with a mknod with the same > major/minor as /dev/null before bind mounting a pts on it. This patch > removes the mknod and creates an empty regular file instead. > > In order to test this patch, I used the following configuration, which I > think should replicate the system with the abusive restriction on mknod: > > # grep devices /proc/self/cgroup > 4:devices:/user.slice/restrict > # cat /sys/fs/cgroup/devices/user.slice/restrict/devices.list > c 1:9 r > c 5:2 rw > c 136:* rw > # systemd-nspawn --register=false -D . > --- > src/nspawn/nspawn.c | 27 ++++++++++++++------------- > 1 file changed, 14 insertions(+), 13 deletions(-) > > diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c > index 300b6df..09fff38 100644 > --- a/src/nspawn/nspawn.c > +++ b/src/nspawn/nspawn.c > @@ -1449,8 +1449,17 @@ static int copy_devnodes(const char *dest) { > return -r; > } > > - if (mknod(to, st.st_mode, st.st_rdev) < 0) > - return log_error_errno(errno, "mknod(%s) failed: %m", to); > + if (mknod(to, st.st_mode, st.st_rdev) < 0) { > + if (errno != EPERM) > + return log_error_errno(errno, "mknod(%s) failed: %m", to); > + > + /* Some systems abusively restrict mknod but > + * allow bind mounts. */ > + if (touch(to) < 0) > + return log_error_errno(errno, "touch (%s) failed: %m", to); > + if (mount(from, to, "bind", MS_BIND, NULL) < 0) > + return log_error_errno(errno, "both mknod and bind mount (%s) failed: %m", to); > + } > > if (arg_userns && arg_uid_shift != UID_INVALID) > if (lchown(to, arg_uid_shift, arg_uid_shift) < 0) > @@ -1481,7 +1490,6 @@ static int setup_ptmx(const char *dest) { > static int setup_dev_console(const char *dest, const char *console) { > _cleanup_umask_ mode_t u; > const char *to; > - struct stat st; > int r; > > assert(dest); > @@ -1489,24 +1497,17 @@ static int setup_dev_console(const char *dest, const char *console) { > > u = umask(0000); > > - if (stat("/dev/null", &st) < 0) > - return log_error_errno(errno, "Failed to stat /dev/null: %m"); > - > r = chmod_and_chown(console, 0600, 0, 0); > if (r < 0) > return log_error_errno(r, "Failed to correct access mode for TTY: %m"); > > /* We need to bind mount the right tty to /dev/console since > * ptys can only exist on pts file systems. To have something > - * to bind mount things on we create a device node first, and > - * use /dev/null for that since we the cgroups device policy > - * allows us to create that freely, while we cannot create > - * /dev/console. (Note that the major minor doesn't actually > - * matter here, since we mount it over anyway). */ > + * to bind mount things on we create a empty regular file. */ > > to = strjoina(dest, "/dev/console"); > - if (mknod(to, (st.st_mode & ~07777) | 0600, st.st_rdev) < 0) > - return log_error_errno(errno, "mknod() for /dev/console failed: %m"); > + if (touch(to) < 0) > + return log_error_errno(errno, "touch() for /dev/console failed: %m"); > > if (mount(console, to, "bind", MS_BIND, NULL) < 0) > return log_error_errno(errno, "Bind mount for /dev/console failed: %m"); > -- > 2.1.4 > > _______________________________________________ > systemd-devel mailing list > systemd-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/systemd-devel
_______________________________________________ systemd-devel mailing list systemd-devel@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/systemd-devel