1
0
mirror of https://github.com/systemd/systemd.git synced 2025-03-31 14:50:15 +03:00

Merge pull request #7886 from gdamjan/fix-ptmx

namespace: make /dev/ptmx a copy of the host not a symlink
This commit is contained in:
Alan Jenkins 2018-01-17 09:24:00 +00:00 committed by GitHub
commit e41090db89
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -496,6 +496,38 @@ 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) {
_cleanup_free_ char *dn = NULL;
struct stat st;
int r;
if (stat(d, &st) < 0) {
if (errno == ENOENT)
return 0;
return -errno;
}
if (!S_ISBLK(st.st_mode) &&
!S_ISCHR(st.st_mode))
return -EINVAL;
if (st.st_rdev == 0)
return 0;
dn = strappend(temporary_mount, d);
if (!dn)
return -ENOMEM;
mac_selinux_create_file_prepare(d, st.st_mode);
r = mknod(dn, st.st_mode, st.st_rdev);
mac_selinux_create_file_clear();
if (r < 0)
return -errno;
return 0;
}
static int mount_private_dev(MountEntry *m) {
static const char devnodes[] =
"/dev/null\0"
@ -508,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);
@ -531,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);
@ -557,42 +606,9 @@ static int mount_private_dev(MountEntry *m) {
(void) symlink("/run/systemd/journal/dev-log", devlog);
NULSTR_FOREACH(d, devnodes) {
_cleanup_free_ char *dn = NULL;
struct stat st;
r = stat(d, &st);
if (r < 0) {
if (errno == ENOENT)
continue;
r = -errno;
r = clone_device_node(d, temporary_mount);
if (r < 0)
goto fail;
}
if (!S_ISBLK(st.st_mode) &&
!S_ISCHR(st.st_mode)) {
r = -EINVAL;
goto fail;
}
if (st.st_rdev == 0)
continue;
dn = strappend(temporary_mount, d);
if (!dn) {
r = -ENOMEM;
goto fail;
}
mac_selinux_create_file_prepare(d, st.st_mode);
r = mknod(dn, st.st_mode, st.st_rdev);
mac_selinux_create_file_clear();
if (r < 0) {
r = -errno;
goto fail;
}
}
dev_setup(temporary_mount, UID_INVALID, GID_INVALID);