Commit 0c547523 by Serge Hallyn Committed by Daniel Lezcano

pin container's rootfs to prevent read-only remount

parent ce5dbd82
...@@ -452,6 +452,51 @@ static int mount_rootfs_block(const char *rootfs, const char *target) ...@@ -452,6 +452,51 @@ static int mount_rootfs_block(const char *rootfs, const char *target)
return mount_unknow_fs(rootfs, target, 0); return mount_unknow_fs(rootfs, target, 0);
} }
/*
* pin_rootfs
* if rootfs is a directory, then open ${rootfs}.hold for writing for the
* duration of the container run, to prevent the container from marking the
* underlying fs readonly on shutdown.
* return -1 on error.
* return -2 if nothing needed to be pinned.
* return an open fd (>=0) if we pinned it.
*/
int pin_rootfs(const char *rootfs)
{
char absrootfs[MAXPATHLEN];
char absrootfspin[MAXPATHLEN];
struct stat s;
int ret, fd;
if (!realpath(rootfs, absrootfs)) {
SYSERROR("failed to get real path for '%s'", rootfs);
return -1;
}
if (access(absrootfs, F_OK)) {
SYSERROR("'%s' is not accessible", absrootfs);
return -1;
}
if (stat(absrootfs, &s)) {
SYSERROR("failed to stat '%s'", absrootfs);
return -1;
}
if (!__S_ISTYPE(s.st_mode, S_IFDIR))
return -2;
ret = snprintf(absrootfspin, MAXPATHLEN, "%s%s", absrootfs, ".hold");
if (ret >= MAXPATHLEN) {
SYSERROR("pathname too long for rootfs hold file");
return -1;
}
fd = open(absrootfspin, O_CREAT | O_RDWR, S_IWUSR|S_IRUSR);
INFO("opened %s as fd %d\n", absrootfspin, fd);
return fd;
}
static int mount_rootfs(const char *rootfs, const char *target) static int mount_rootfs(const char *rootfs, const char *target)
{ {
char absrootfs[MAXPATHLEN]; char absrootfs[MAXPATHLEN];
......
...@@ -223,6 +223,8 @@ struct lxc_conf { ...@@ -223,6 +223,8 @@ struct lxc_conf {
*/ */
extern struct lxc_conf *lxc_conf_init(void); extern struct lxc_conf *lxc_conf_init(void);
extern int pin_rootfs(const char *rootfs);
extern int lxc_create_network(struct lxc_handler *handler); extern int lxc_create_network(struct lxc_handler *handler);
extern void lxc_delete_network(struct lxc_list *networks); extern void lxc_delete_network(struct lxc_list *networks);
extern int lxc_assign_network(struct lxc_list *networks, pid_t pid); extern int lxc_assign_network(struct lxc_list *networks, pid_t pid);
......
...@@ -534,6 +534,7 @@ int lxc_spawn(struct lxc_handler *handler) ...@@ -534,6 +534,7 @@ int lxc_spawn(struct lxc_handler *handler)
int clone_flags; int clone_flags;
int failed_before_rename = 0; int failed_before_rename = 0;
const char *name = handler->name; const char *name = handler->name;
int pinfd;
if (lxc_sync_init(handler)) if (lxc_sync_init(handler))
return -1; return -1;
...@@ -563,6 +564,17 @@ int lxc_spawn(struct lxc_handler *handler) ...@@ -563,6 +564,17 @@ int lxc_spawn(struct lxc_handler *handler)
} }
} }
/*
* if the rootfs is not a blockdev, prevent the container from
* marking it readonly.
*/
pinfd = pin_rootfs(handler->conf->rootfs.path);
if (pinfd == -1) {
ERROR("failed to pin the container's rootfs");
goto out_abort;
}
/* Create a process in a new set of namespaces */ /* Create a process in a new set of namespaces */
handler->pid = lxc_clone(do_start, handler, clone_flags); handler->pid = lxc_clone(do_start, handler, clone_flags);
if (handler->pid < 0) { if (handler->pid < 0) {
...@@ -605,6 +617,10 @@ int lxc_spawn(struct lxc_handler *handler) ...@@ -605,6 +617,10 @@ int lxc_spawn(struct lxc_handler *handler)
} }
lxc_sync_fini(handler); lxc_sync_fini(handler);
if (pinfd >= 0)
close(pinfd);
return 0; return 0;
out_delete_net: out_delete_net:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment