]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
namespace: only make the symlink /dev/ptmx if it was already a symlink 7886/head
authorДамјан Георгиевски <gdamjan@gmail.com>
Tue, 16 Jan 2018 20:50:36 +0000 (21:50 +0100)
committerДамјан Георгиевски <gdamjan@gmail.com>
Wed, 17 Jan 2018 00:19:46 +0000 (01:19 +0100)
…otherwise try to clone it as a device node

On most contemporary distros /dev/ptmx is a device node, and
/dev/pts/ptmx has 000 inaccessible permissions. In those cases
the symlink /dev/ptmx -> /dev/pts/ptmx breaks the pseudo tty support.

In that case we better clone the device node.

OTOH, in nspawn containers (and possibly others), /dev/pts/ptmx has
normal permissions, and /dev/ptmx is a symlink. In that case make the
same symlink.

fixes #7878

src/core/namespace.c

index d5b050fadc8cc0879e0c18857d9c21ec016e5ddb..d6c1b1b2fc1f628f4dcaeec628ab8e2fd262ef3d 100644 (file)
@@ -496,14 +496,12 @@ static void drop_outside_root(const char *root_directory, MountEntry *m, unsigne
         *n = t - m;
 }
 
-static int clone_device_node(const char *d, const char *temporary_mount)
-{
+static int clone_device_node(const char *d, const char *temporary_mount) {
         _cleanup_free_ char *dn = NULL;
         struct stat st;
         int r;
 
-        r = stat(d, &st);
-        if (r < 0) {
+        if (stat(d, &st) < 0) {
                 if (errno == ENOENT)
                         return 0;
                 return -errno;
@@ -542,6 +540,7 @@ static int mount_private_dev(MountEntry *m) {
         char temporary_mount[] = "/tmp/namespace-dev-XXXXXX";
         const char *d, *dev = NULL, *devpts = NULL, *devshm = NULL, *devhugepages = NULL, *devmqueue = NULL, *devlog = NULL, *devptmx = NULL;
         _cleanup_umask_ mode_t u;
+        struct stat st;
         int r;
 
         assert(m);
@@ -565,11 +564,27 @@ static int mount_private_dev(MountEntry *m) {
                 goto fail;
         }
 
-        devptmx = strjoina(temporary_mount, "/dev/ptmx");
-        if (symlink("pts/ptmx", devptmx) < 0) {
+        /* /dev/ptmx can either be a device node or a symlink to /dev/pts/ptmx
+         * when /dev/ptmx a device node, /dev/pts/ptmx has 000 permissions making it inaccessible
+         * thus, in that case make a clone
+         *
+         * in nspawn and other containers it will be a symlink, in that case make it a symlink
+         */
+        if (lstat("/dev/ptmx", &st) < 0) {
                 r = -errno;
                 goto fail;
         }
+        if (S_ISLNK(st.st_mode)) {
+                devptmx = strjoina(temporary_mount, "/dev/ptmx");
+                if (symlink("pts/ptmx", devptmx) < 0) {
+                        r = -errno;
+                        goto fail;
+                }
+        } else {
+                r = clone_device_node("/dev/ptmx", temporary_mount);
+                if (r < 0)
+                        goto fail;
+        }
 
         devshm = strjoina(temporary_mount, "/dev/shm");
         (void) mkdir(devshm, 01777);