diff options
-rw-r--r-- | src/firejail/firejail.h | 3 | ||||
-rw-r--r-- | src/firejail/main.c | 70 | ||||
-rw-r--r-- | src/firejail/util.c | 70 |
3 files changed, 74 insertions, 69 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 49d19e33d..85139d75f 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -528,6 +528,9 @@ void disable_file_path(const char *path, const char *file); | |||
528 | int safe_fd(const char *path, int flags); | 528 | int safe_fd(const char *path, int flags); |
529 | int has_handler(pid_t pid, int signal); | 529 | int has_handler(pid_t pid, int signal); |
530 | void enter_network_namespace(pid_t pid); | 530 | void enter_network_namespace(pid_t pid); |
531 | int read_pid(const char *name, pid_t *pid); | ||
532 | pid_t require_pid(const char *name); | ||
533 | void check_homedir(void); | ||
531 | 534 | ||
532 | // Get info regarding the last kernel mount operation from /proc/self/mountinfo | 535 | // Get info regarding the last kernel mount operation from /proc/self/mountinfo |
533 | // The return value points to a static area, and will be overwritten by subsequent calls. | 536 | // The return value points to a static area, and will be overwritten by subsequent calls. |
diff --git a/src/firejail/main.c b/src/firejail/main.c index 072651c4d..df890ecea 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <dirent.h> | 31 | #include <dirent.h> |
32 | #include <pwd.h> | 32 | #include <pwd.h> |
33 | #include <errno.h> | 33 | #include <errno.h> |
34 | #include <limits.h> | 34 | //#include <limits.h> |
35 | #include <sys/file.h> | 35 | #include <sys/file.h> |
36 | #include <sys/prctl.h> | 36 | #include <sys/prctl.h> |
37 | #include <signal.h> | 37 | #include <signal.h> |
@@ -215,74 +215,6 @@ static void install_handler(void) { | |||
215 | sigaction(SIGTERM, &sga, NULL); | 215 | sigaction(SIGTERM, &sga, NULL); |
216 | } | 216 | } |
217 | 217 | ||
218 | // return 1 if error, 0 if a valid pid was found | ||
219 | static int extract_pid(const char *name, pid_t *pid) { | ||
220 | int retval = 0; | ||
221 | EUID_ASSERT(); | ||
222 | if (!name || strlen(name) == 0) { | ||
223 | fprintf(stderr, "Error: invalid sandbox name\n"); | ||
224 | exit(1); | ||
225 | } | ||
226 | |||
227 | EUID_ROOT(); | ||
228 | if (name2pid(name, pid)) { | ||
229 | retval = 1; | ||
230 | } | ||
231 | EUID_USER(); | ||
232 | return retval; | ||
233 | } | ||
234 | |||
235 | // return 1 if error, 0 if a valid pid was found | ||
236 | static int read_pid(const char *name, pid_t *pid) { | ||
237 | char *endptr; | ||
238 | errno = 0; | ||
239 | long int pidtmp = strtol(name, &endptr, 10); | ||
240 | if ((errno == ERANGE && (pidtmp == LONG_MAX || pidtmp == LONG_MIN)) | ||
241 | || (errno != 0 && pidtmp == 0)) { | ||
242 | return extract_pid(name,pid); | ||
243 | } | ||
244 | // endptr points to '\0' char in name if the entire string is valid | ||
245 | if (endptr == NULL || endptr[0]!='\0') { | ||
246 | return extract_pid(name,pid); | ||
247 | } | ||
248 | *pid =(pid_t)pidtmp; | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static pid_t require_pid(const char *name) { | ||
253 | pid_t pid; | ||
254 | if (read_pid(name,&pid)) { | ||
255 | fprintf(stderr, "Error: cannot find sandbox %s\n", name); | ||
256 | exit(1); | ||
257 | } | ||
258 | return pid; | ||
259 | } | ||
260 | |||
261 | // return 1 if there is a link somewhere in path of directory | ||
262 | static int has_link(const char *dir) { | ||
263 | assert(dir); | ||
264 | int fd = safe_fd(dir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); | ||
265 | if (fd == -1) { | ||
266 | if (errno == ENOTDIR && is_dir(dir)) | ||
267 | return 1; | ||
268 | } | ||
269 | else | ||
270 | close(fd); | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static void check_homedir(void) { | ||
275 | assert(cfg.homedir); | ||
276 | if (cfg.homedir[0] != '/') { | ||
277 | fprintf(stderr, "Error: invalid user directory \"%s\"\n", cfg.homedir); | ||
278 | exit(1); | ||
279 | } | ||
280 | // symlinks are rejected in many places | ||
281 | if (has_link(cfg.homedir)) { | ||
282 | fprintf(stderr, "No full support for symbolic links in path of user directory.\n" | ||
283 | "Please provide resolved path in password database (/etc/passwd).\n\n"); | ||
284 | } | ||
285 | } | ||
286 | 218 | ||
287 | // init configuration | 219 | // init configuration |
288 | static void init_cfg(int argc, char **argv) { | 220 | static void init_cfg(int argc, char **argv) { |
diff --git a/src/firejail/util.c b/src/firejail/util.c index 3aa0584d6..d65ac0071 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <sys/ioctl.h> | 29 | #include <sys/ioctl.h> |
30 | #include <termios.h> | 30 | #include <termios.h> |
31 | #include <sys/wait.h> | 31 | #include <sys/wait.h> |
32 | #include <limits.h> | ||
32 | 33 | ||
33 | #include <fcntl.h> | 34 | #include <fcntl.h> |
34 | #ifndef O_PATH | 35 | #ifndef O_PATH |
@@ -1265,3 +1266,72 @@ void enter_network_namespace(pid_t pid) { | |||
1265 | exit(1); | 1266 | exit(1); |
1266 | } | 1267 | } |
1267 | } | 1268 | } |
1269 | |||
1270 | // return 1 if error, 0 if a valid pid was found | ||
1271 | static int extract_pid(const char *name, pid_t *pid) { | ||
1272 | int retval = 0; | ||
1273 | EUID_ASSERT(); | ||
1274 | if (!name || strlen(name) == 0) { | ||
1275 | fprintf(stderr, "Error: invalid sandbox name\n"); | ||
1276 | exit(1); | ||
1277 | } | ||
1278 | |||
1279 | EUID_ROOT(); | ||
1280 | if (name2pid(name, pid)) { | ||
1281 | retval = 1; | ||
1282 | } | ||
1283 | EUID_USER(); | ||
1284 | return retval; | ||
1285 | } | ||
1286 | |||
1287 | // return 1 if error, 0 if a valid pid was found | ||
1288 | int read_pid(const char *name, pid_t *pid) { | ||
1289 | char *endptr; | ||
1290 | errno = 0; | ||
1291 | long int pidtmp = strtol(name, &endptr, 10); | ||
1292 | if ((errno == ERANGE && (pidtmp == LONG_MAX || pidtmp == LONG_MIN)) | ||
1293 | || (errno != 0 && pidtmp == 0)) { | ||
1294 | return extract_pid(name,pid); | ||
1295 | } | ||
1296 | // endptr points to '\0' char in name if the entire string is valid | ||
1297 | if (endptr == NULL || endptr[0]!='\0') { | ||
1298 | return extract_pid(name,pid); | ||
1299 | } | ||
1300 | *pid =(pid_t)pidtmp; | ||
1301 | return 0; | ||
1302 | } | ||
1303 | |||
1304 | pid_t require_pid(const char *name) { | ||
1305 | pid_t pid; | ||
1306 | if (read_pid(name,&pid)) { | ||
1307 | fprintf(stderr, "Error: cannot find sandbox %s\n", name); | ||
1308 | exit(1); | ||
1309 | } | ||
1310 | return pid; | ||
1311 | } | ||
1312 | |||
1313 | // return 1 if there is a link somewhere in path of directory | ||
1314 | static int has_link(const char *dir) { | ||
1315 | assert(dir); | ||
1316 | int fd = safe_fd(dir, O_PATH|O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC); | ||
1317 | if (fd == -1) { | ||
1318 | if (errno == ENOTDIR && is_dir(dir)) | ||
1319 | return 1; | ||
1320 | } | ||
1321 | else | ||
1322 | close(fd); | ||
1323 | return 0; | ||
1324 | } | ||
1325 | |||
1326 | void check_homedir(void) { | ||
1327 | assert(cfg.homedir); | ||
1328 | if (cfg.homedir[0] != '/') { | ||
1329 | fprintf(stderr, "Error: invalid user directory \"%s\"\n", cfg.homedir); | ||
1330 | exit(1); | ||
1331 | } | ||
1332 | // symlinks are rejected in many places | ||
1333 | if (has_link(cfg.homedir)) { | ||
1334 | fprintf(stderr, "No full support for symbolic links in path of user directory.\n" | ||
1335 | "Please provide resolved path in password database (/etc/passwd).\n\n"); | ||
1336 | } | ||
1337 | } | ||