summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDave Reisner <dreisner@archlinux.org>2013-09-19 14:30:07 -0400
committerDave Reisner <dreisner@archlinux.org>2013-09-19 14:48:43 -0400
commitd2421337f6e7d5a6730599e929232689acb09394 (patch)
tree19668cce0ff30f84e15484b3e161bc86e4574957
parente7363c59d69b71a4327429719e24cab9020e2796 (diff)
nspawn: be less liberal about creating bind mount destinations
Previously, if a file's bind mount destination didn't exist, nspawn would blindly create a directory, and the subsequent bind mount would fail. Examine the filetype of the source and ensure that, if the destination does not exist, that it is created appropriately. Also go one step further and ensure that the filetypes of the source and destination match.
-rw-r--r--src/nspawn/nspawn.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index f8208607ce..a0809da743 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -411,12 +411,39 @@ static int mount_binds(const char *dest, char **l, unsigned long flags) {
STRV_FOREACH_PAIR(x, y, l) {
_cleanup_free_ char *where = NULL;
+ struct stat source_st, dest_st;
+
+ if (stat(*x, &source_st) < 0) {
+ log_error("failed to stat %s: %m", *x);
+ return -errno;
+ }
where = strjoin(dest, "/", *y, NULL);
if (!where)
return log_oom();
- mkdir_p_label(where, 0755);
+ if (stat(where, &dest_st) == 0) {
+ if ((source_st.st_mode & S_IFMT) != (dest_st.st_mode & S_IFMT)) {
+ log_error("The file types of %s and %s do not matching. Refusing bind mount",
+ *x, where);
+ return -EINVAL;
+ }
+ } else {
+ /* Create the mount point, but be conservative -- refuse to create block
+ * and char devices. */
+ if (S_ISDIR(source_st.st_mode))
+ mkdir_p_label(where, 0755);
+ else if (S_ISFIFO(source_st.st_mode))
+ mkfifo(where, 0644);
+ else if (S_ISSOCK(source_st.st_mode))
+ mknod(where, 0644 | S_IFSOCK, 0);
+ else if (S_ISREG(source_st.st_mode))
+ touch(where);
+ else {
+ log_error("Refusing to create mountpoint for file: %s", *x);
+ return -ENOTSUP;
+ }
+ }
if (mount(*x, where, "bind", MS_BIND, NULL) < 0) {
log_error("mount(%s) failed: %m", where);