diff options
author | smitsohu <smitsohu@gmail.com> | 2022-06-08 12:12:04 +0200 |
---|---|---|
committer | smitsohu <smitsohu@gmail.com> | 2022-06-08 12:12:04 +0200 |
commit | 27cde3d7d1e4e16d4190932347c7151dc2a84c50 (patch) | |
tree | 0da23ef1269411abd2621847e55392712b7e2cf8 /src/lib | |
parent | RELNOTES: add feature/bugfix (diff) | |
download | firejail-27cde3d7d1e4e16d4190932347c7151dc2a84c50.tar.gz firejail-27cde3d7d1e4e16d4190932347c7151dc2a84c50.tar.zst firejail-27cde3d7d1e4e16d4190932347c7151dc2a84c50.zip |
fixing CVE-2022-31214
Diffstat (limited to 'src/lib')
-rw-r--r-- | src/lib/common.c | 77 |
1 files changed, 69 insertions, 8 deletions
diff --git a/src/lib/common.c b/src/lib/common.c index 8e84fab26..111366782 100644 --- a/src/lib/common.c +++ b/src/lib/common.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <sys/types.h> | 22 | #include <sys/types.h> |
23 | #include <sys/stat.h> | 23 | #include <sys/stat.h> |
24 | #include <sys/wait.h> | 24 | #include <sys/wait.h> |
25 | #include <fcntl.h> | ||
26 | #include <sys/syscall.h> | 25 | #include <sys/syscall.h> |
27 | #include <errno.h> | 26 | #include <errno.h> |
28 | #include <unistd.h> | 27 | #include <unistd.h> |
@@ -32,32 +31,94 @@ | |||
32 | #include <string.h> | 31 | #include <string.h> |
33 | #include <time.h> | 32 | #include <time.h> |
34 | #include <limits.h> | 33 | #include <limits.h> |
34 | #include <sched.h> | ||
35 | #include "../include/common.h" | 35 | #include "../include/common.h" |
36 | |||
37 | #include <fcntl.h> | ||
38 | #ifndef O_PATH | ||
39 | #define O_PATH 010000000 | ||
40 | #endif | ||
41 | |||
42 | #include <sys/ioctl.h> | ||
43 | #ifndef NSIO | ||
44 | #define NSIO 0xb7 | ||
45 | #endif | ||
46 | #ifndef NS_GET_USERNS | ||
47 | #define NS_GET_USERNS _IO(NSIO, 0x1) | ||
48 | #endif | ||
49 | |||
36 | #define BUFLEN 4096 | 50 | #define BUFLEN 4096 |
37 | 51 | ||
38 | int join_namespace(pid_t pid, char *type) { | 52 | |
53 | int join_namespace_by_fd(int dirfd, char *typestr) { | ||
54 | int type; | ||
55 | if (strcmp(typestr, "net") == 0) | ||
56 | type = CLONE_NEWNET; | ||
57 | else if (strcmp(typestr, "mnt") == 0) | ||
58 | type = CLONE_NEWNS; | ||
59 | else if (strcmp(typestr, "ipc") == 0) | ||
60 | type = CLONE_NEWIPC; | ||
61 | else if (strcmp(typestr, "pid") == 0) | ||
62 | type = CLONE_NEWPID; | ||
63 | else if (strcmp(typestr, "uts") == 0) | ||
64 | type = CLONE_NEWUTS; | ||
65 | else if (strcmp(typestr, "user") == 0) | ||
66 | type = CLONE_NEWUSER; | ||
67 | else | ||
68 | assert(0); | ||
69 | |||
39 | char *path; | 70 | char *path; |
40 | if (asprintf(&path, "/proc/%u/ns/%s", pid, type) == -1) | 71 | if (asprintf(&path, "ns/%s", typestr) == -1) |
41 | errExit("asprintf"); | 72 | errExit("asprintf"); |
42 | 73 | ||
43 | int fd = open(path, O_RDONLY); | 74 | int fd = openat(dirfd, path, O_RDONLY|O_CLOEXEC); |
75 | free(path); | ||
44 | if (fd < 0) | 76 | if (fd < 0) |
45 | goto errout; | 77 | goto errout; |
46 | 78 | ||
47 | if (syscall(__NR_setns, fd, 0) < 0) { | 79 | // require that target namespace is owned by |
80 | // the current user namespace (Linux >= 4.9) | ||
81 | struct stat self_userns; | ||
82 | if (stat("/proc/self/ns/user", &self_userns) == 0) { | ||
83 | int usernsfd = ioctl(fd, NS_GET_USERNS); | ||
84 | if (usernsfd != -1) { | ||
85 | struct stat dest_userns; | ||
86 | if (fstat(usernsfd, &dest_userns) < 0) | ||
87 | errExit("fstat"); | ||
88 | close(usernsfd); | ||
89 | if (dest_userns.st_ino != self_userns.st_ino || | ||
90 | dest_userns.st_dev != self_userns.st_dev) { | ||
91 | close(fd); | ||
92 | goto errout; | ||
93 | } | ||
94 | } | ||
95 | } | ||
96 | |||
97 | if (syscall(__NR_setns, fd, type) < 0) { | ||
48 | close(fd); | 98 | close(fd); |
49 | goto errout; | 99 | goto errout; |
50 | } | 100 | } |
51 | 101 | ||
52 | close(fd); | 102 | close(fd); |
53 | free(path); | ||
54 | return 0; | 103 | return 0; |
55 | 104 | ||
56 | errout: | 105 | errout: |
57 | free(path); | 106 | fprintf(stderr, "Error: cannot join namespace %s\n", typestr); |
58 | fprintf(stderr, "Error: cannot join namespace %s\n", type); | ||
59 | return -1; | 107 | return -1; |
108 | } | ||
60 | 109 | ||
110 | int join_namespace(pid_t pid, char *typestr) { | ||
111 | char path[64]; | ||
112 | snprintf(path, sizeof(path), "/proc/%d", pid); | ||
113 | int fd = open(path, O_PATH|O_CLOEXEC); | ||
114 | if (fd < 0) { | ||
115 | fprintf(stderr, "Error: cannot open %s: %s\n", path, strerror(errno)); | ||
116 | exit(1); | ||
117 | } | ||
118 | |||
119 | int rv = join_namespace_by_fd(fd, typestr); | ||
120 | close(fd); | ||
121 | return rv; | ||
61 | } | 122 | } |
62 | 123 | ||
63 | // return 1 if error | 124 | // return 1 if error |