diff options
-rw-r--r-- | src/firejail/fs_etc.c | 61 |
1 files changed, 47 insertions, 14 deletions
diff --git a/src/firejail/fs_etc.c b/src/firejail/fs_etc.c index abec25d45..8cb25a1ff 100644 --- a/src/firejail/fs_etc.c +++ b/src/firejail/fs_etc.c | |||
@@ -76,6 +76,44 @@ void fs_machineid(void) { | |||
76 | } | 76 | } |
77 | } | 77 | } |
78 | 78 | ||
79 | // Duplicate directory structure from src to dst by creating empty directories. | ||
80 | // The paths _must_ be identical after their respective prefixes. | ||
81 | // When finished, dst will point to the target directory. That is, if | ||
82 | // it starts out pointing to a file, it will instead be truncated so | ||
83 | // that it contains the parent directory instead. | ||
84 | static void build_dirs(char *src, char *dst, size_t src_prefix_len, size_t dst_prefix_len) { | ||
85 | char *p = src + src_prefix_len + 1; | ||
86 | char *q = dst + dst_prefix_len + 1; | ||
87 | char *r = dst + dst_prefix_len; | ||
88 | struct stat s; | ||
89 | bool last = false; | ||
90 | *r = '\0'; | ||
91 | for (; !last; p++, q++) { | ||
92 | if (*p == '\0') { | ||
93 | last = true; | ||
94 | } | ||
95 | if (*p == '\0' || (*p == '/' && *(p - 1) != '/')) { | ||
96 | // We found a new component of our src path. | ||
97 | // Null-terminate it temporarily here so that we can work | ||
98 | // with it. | ||
99 | *p = '\0'; | ||
100 | if (stat(src, &s) == 0 && S_ISDIR(s.st_mode)) { | ||
101 | // Null-terminate the dst path and undo its previous | ||
102 | // termination. | ||
103 | *q = '\0'; | ||
104 | *r = '/'; | ||
105 | r = q; | ||
106 | create_empty_dir_as_root(dst, s.st_mode); | ||
107 | } | ||
108 | if (!last) { | ||
109 | // If we're not at the final terminating null, restore | ||
110 | // the slash so that we can continue our traversal. | ||
111 | *p = '/'; | ||
112 | } | ||
113 | } | ||
114 | } | ||
115 | } | ||
116 | |||
79 | // return 0 if file not found, 1 if found | 117 | // return 0 if file not found, 1 if found |
80 | static int check_dir_or_file(const char *fname) { | 118 | static int check_dir_or_file(const char *fname) { |
81 | assert(fname); | 119 | assert(fname); |
@@ -103,7 +141,7 @@ errexit: | |||
103 | static void duplicate(const char *fname, const char *private_dir, const char *private_run_dir) { | 141 | static void duplicate(const char *fname, const char *private_dir, const char *private_run_dir) { |
104 | assert(fname); | 142 | assert(fname); |
105 | 143 | ||
106 | if (*fname == '~' || strchr(fname, '/') || strcmp(fname, "..") == 0) { | 144 | if (*fname == '~' || *fname == '/' || strncmp(fname, "..", 2) == 0) { |
107 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", fname); | 145 | fprintf(stderr, "Error: \"%s\" is an invalid filename\n", fname); |
108 | exit(1); | 146 | exit(1); |
109 | } | 147 | } |
@@ -119,21 +157,16 @@ static void duplicate(const char *fname, const char *private_dir, const char *pr | |||
119 | } | 157 | } |
120 | 158 | ||
121 | if (arg_debug) | 159 | if (arg_debug) |
122 | printf("copying %s to private %s\n", src, private_dir); | 160 | printf("Copying %s to private %s\n", src, private_dir); |
123 | 161 | ||
124 | struct stat s; | 162 | char *dst; |
125 | if (stat(src, &s) == 0 && S_ISDIR(s.st_mode)) { | 163 | if (asprintf(&dst, "%s/%s", private_run_dir, fname) == -1) |
126 | // create the directory in RUN_ETC_DIR | 164 | errExit("asprintf"); |
127 | char *dirname; | 165 | |
128 | if (asprintf(&dirname, "%s/%s", private_run_dir, fname) == -1) | 166 | build_dirs(src, dst, strlen(private_dir), strlen(private_run_dir)); |
129 | errExit("asprintf"); | 167 | sbox_run(SBOX_ROOT | SBOX_SECCOMP, 3, PATH_FCOPY, src, dst); |
130 | create_empty_dir_as_root(dirname, s.st_mode); | ||
131 | sbox_run(SBOX_ROOT| SBOX_SECCOMP, 3, PATH_FCOPY, src, dirname); | ||
132 | free(dirname); | ||
133 | } | ||
134 | else | ||
135 | sbox_run(SBOX_ROOT| SBOX_SECCOMP, 3, PATH_FCOPY, src, private_run_dir); | ||
136 | 168 | ||
169 | free(dst); | ||
137 | fs_logger2("clone", src); | 170 | fs_logger2("clone", src); |
138 | free(src); | 171 | free(src); |
139 | } | 172 | } |