Browse Source

jail: fs: add support for asymmetric mount bind

Allow mounting absolute path on host to defined mountpoint inside
container using ':' character in argument of '-r' and '-w' parameters.

Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Daniel Golle 2 years ago
parent
commit
324ebd0a3c
3 changed files with 33 additions and 8 deletions
  1. 11 5
      jail/fs.c
  2. 7 1
      jail/fs.h
  3. 15 2
      jail/jail.c

+ 11 - 5
jail/fs.c

@@ -206,14 +206,19 @@ int add_mount_inner(const char *source, const char *target, const char *filesyst
 	return _add_mount(source, target, filesystemtype, mountflags, propflags, optstr, error, true);
 }
 
-int add_mount_bind(const char *path, int readonly, int error)
+static int _add_mount_bind(const char *path, const char *path2, int readonly, int error)
 {
 	unsigned long mountflags = MS_BIND;
 
 	if (readonly)
 		mountflags |= MS_RDONLY;
 
-	return add_mount(path, path, NULL, mountflags, 0, NULL, error);
+	return add_mount(path, path2, NULL, mountflags, 0, NULL, error);
+}
+
+int add_mount_bind(const char *path, int readonly, int error)
+{
+	return _add_mount_bind(path, path, readonly, error);
 }
 
 enum {
@@ -478,9 +483,10 @@ static int add_script_interp(const char *path, const char *map, int size)
 	return add_path_and_deps(buf, 1, -1, 0);
 }
 
-int add_path_and_deps(const char *path, int readonly, int error, int lib)
+int add_2paths_and_deps(const char *path, const char *path2, int readonly, int error, int lib)
 {
 	assert(path != NULL);
+	assert(path2 != NULL);
 
 	if (lib == 0 && path[0] != '/') {
 		ERROR("%s is not an absolute path\n", path);
@@ -490,12 +496,12 @@ int add_path_and_deps(const char *path, int readonly, int error, int lib)
 	char *map = NULL;
 	int fd, ret = -1;
 	if (path[0] == '/') {
-		if (avl_find(&mounts, path))
+		if (avl_find(&mounts, path2))
 			return 0;
 		fd = open(path, O_RDONLY|O_CLOEXEC);
 		if (fd < 0)
 			return error;
-		add_mount_bind(path, readonly, error);
+		_add_mount_bind(path, path2, readonly, error);
 	} else {
 		if (avl_find(&libraries, path))
 			return 0;

+ 7 - 1
jail/fs.h

@@ -22,7 +22,13 @@ int add_mount_inner(const char *source, const char *target, const char *filesyst
 	      unsigned long mountflags, unsigned long propflags, const char *optstr, int error);
 int add_mount_bind(const char *path, int readonly, int error);
 int parseOCImount(struct blob_attr *msg);
-int add_path_and_deps(const char *path, int readonly, int error, int lib);
+int add_2paths_and_deps(const char *path, const char *path2, int readonly, int error, int lib);
+
+static inline int add_path_and_deps(const char *path, int readonly, int error, int lib)
+{
+	return add_2paths_and_deps(path, path, readonly, error, lib);
+}
+
 int mount_all(const char *jailroot);
 void mount_list_init(void);
 void mount_free(void);

+ 15 - 2
jail/jail.c

@@ -2568,6 +2568,7 @@ int main(int argc, char **argv)
 	const char ubus[] = "/var/run/ubus/ubus.sock";
 	int ret = EXIT_FAILURE;
 	int ch;
+	char *tmp;
 
 	if (uid) {
 		ERROR("not root, aborting: %m\n");
@@ -2643,11 +2644,23 @@ int main(int argc, char **argv)
 			break;
 		case 'r':
 			opts.namespace |= CLONE_NEWNS;
-			add_path_and_deps(optarg, 1, 0, 0);
+			tmp = strchr(optarg, ':');
+			if (tmp) {
+				*(tmp++) = '\0';
+				add_2paths_and_deps(optarg, tmp, 1, 0, 0);
+			} else {
+				add_path_and_deps(optarg, 1, 0, 0);
+			}
 			break;
 		case 'w':
 			opts.namespace |= CLONE_NEWNS;
-			add_path_and_deps(optarg, 0, 0, 0);
+			tmp = strchr(optarg, ':');
+			if (tmp) {
+				*(tmp++) = '\0';
+				add_2paths_and_deps(optarg, tmp, 0, 0, 0);
+			} else {
+				add_path_and_deps(optarg, 0, 0, 0);
+			}
 			break;
 		case 'u':
 			opts.namespace |= CLONE_NEWNS;