aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2022-06-08 12:12:04 +0200
committerLibravatar smitsohu <smitsohu@gmail.com>2022-06-08 12:12:04 +0200
commit27cde3d7d1e4e16d4190932347c7151dc2a84c50 (patch)
tree0da23ef1269411abd2621847e55392712b7e2cf8 /src/lib
parentRELNOTES: add feature/bugfix (diff)
downloadfirejail-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.c77
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
38int join_namespace(pid_t pid, char *type) { 52
53int 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
56errout: 105errout:
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
110int 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