conf: use bind-mount for /dev/ptmx

AppArmor will refuse on /dev/ptmx being a symlink.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
This commit is contained in:
Christian Brauner 2017-04-22 00:14:15 +02:00
parent 70761e5ee2
commit d5cb35d636
No known key found for this signature in database
GPG Key ID: 8EB056D53EECB12D

View File

@ -1456,8 +1456,7 @@ static int setup_pivot_root(const struct lxc_rootfs *rootfs)
static int lxc_setup_devpts(int num_pts) static int lxc_setup_devpts(int num_pts)
{ {
int ret; int ret;
char target[PATH_MAX]; const char *devpts_mntopts = "newinstance,ptmxmode=0666,mode=0620,gid=5";
char *devpts_mntopts = "newinstance,ptmxmode=0666,mode=0620,gid=5";
if (!num_pts) { if (!num_pts) {
DEBUG("no new devpts instance will be mounted since no pts " DEBUG("no new devpts instance will be mounted since no pts "
@ -1465,9 +1464,9 @@ static int lxc_setup_devpts(int num_pts)
return 0; return 0;
} }
/* Unmount old devpts instance. */
ret = access("/dev/pts/ptmx", F_OK); ret = access("/dev/pts/ptmx", F_OK);
if (!ret) { if (!ret) {
/* Unmount old devpts instance. */
ret = umount("/dev/pts"); ret = umount("/dev/pts");
if (ret < 0) { if (ret < 0) {
SYSERROR("failed to unmount old devpts instance"); SYSERROR("failed to unmount old devpts instance");
@ -1490,30 +1489,50 @@ static int lxc_setup_devpts(int num_pts)
return -1; return -1;
} }
/* Remove any pre-existing /dev/ptmx file. */
ret = access("/dev/ptmx", F_OK); ret = access("/dev/ptmx", F_OK);
if (ret < 0) { if (!ret) {
ret = symlink("/dev/pts/ptmx", "/dev/ptmx"); ret = remove("/dev/ptmx");
if (!ret) { if (ret < 0) {
DEBUG("created symlink \"/dev/ptmx\" -> \"/dev/pts/ptmx\""); SYSERROR("failed to remove existing \"/dev/ptmx\"");
goto success; return -1;
} }
DEBUG("removed existing \"/dev/ptmx\"");
}
/* Create dummy /dev/ptmx file as bind mountpoint for /dev/pts/ptmx. */
ret = open("/dev/ptmx", O_CREAT, 0666);
if (ret < 0) {
SYSERROR("failed to create dummy \"/dev/ptmx\" file as bind mount target");
return -1;
}
DEBUG("created dummy \"/dev/ptmx\" file as bind mount target");
/* Fallback option: create symlink /dev/ptmx -> /dev/pts/ptmx */
ret = mount("/dev/pts/ptmx", "/dev/ptmx", "none", MS_BIND, 0);
if (!ret) {
DEBUG("bind mounted \"/dev/pts/ptmx\" to \"/dev/ptmx\"");
return 0;
} else {
/* Fallthrough and try to create a symlink. */
ERROR("failed to bind mount \"/dev/pts/ptmx\" to \"/dev/ptmx\"");
}
/* Remove the dummy /dev/ptmx file we created above. */
ret = remove("/dev/ptmx");
if (ret < 0) {
SYSERROR("failed to remove existing \"/dev/ptmx\"");
return -1;
}
/* Fallback option: Create symlink /dev/ptmx -> /dev/pts/ptmx. */
ret = symlink("/dev/pts/ptmx", "/dev/ptmx");
if (ret < 0) {
SYSERROR("failed to create symlink \"/dev/ptmx\" -> \"/dev/pts/ptmx\""); SYSERROR("failed to create symlink \"/dev/ptmx\" -> \"/dev/pts/ptmx\"");
return -1; return -1;
} }
DEBUG("created symlink \"/dev/ptmx\" -> \"/dev/pts/ptmx\"");
/* Check if any existing symlink is valid. */
if (realpath("/dev/ptmx", target) && !strcmp(target, "/dev/pts/ptmx"))
goto success;
/* Fallback here, /dev/pts/ptmx exists so just bind mount it. */
ret = mount("/dev/pts/ptmx", "/dev/ptmx", "none", MS_BIND, 0);
if (ret < 0) {
SYSERROR("failed to bind mount \"/dev/pts/ptmx\" to \"/dev/ptmx\"");
return -1;
}
success:
INFO("created new devpts instance");
return 0; return 0;
} }