aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2018-12-14 03:04:07 +0100
committerLibravatar smitsohu <smitsohu@gmail.com>2018-12-14 03:04:07 +0100
commite56c09e19f34a0dd6d6d442cc0d2782409a0b53e (patch)
tree36d286616a0b9efe3beaec1d3ea3a10e70efa863
parentfirecfg: improve error string (diff)
downloadfirejail-e56c09e19f34a0dd6d6d442cc0d2782409a0b53e.tar.gz
firejail-e56c09e19f34a0dd6d6d442cc0d2782409a0b53e.tar.zst
firejail-e56c09e19f34a0dd6d6d442cc0d2782409a0b53e.zip
add explicit nonewprivs support to join option; accompanying small improvements
-rw-r--r--src/firejail/firejail.h1
-rw-r--r--src/firejail/join.c49
-rw-r--r--src/firejail/sandbox.c32
3 files changed, 68 insertions, 14 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index bd392846a..245ea5bde 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -46,6 +46,7 @@
46#define RUN_CPU_CFG "/run/firejail/mnt/cpu" 46#define RUN_CPU_CFG "/run/firejail/mnt/cpu"
47#define RUN_GROUPS_CFG "/run/firejail/mnt/groups" 47#define RUN_GROUPS_CFG "/run/firejail/mnt/groups"
48#define RUN_PROTOCOL_CFG "/run/firejail/mnt/protocol" 48#define RUN_PROTOCOL_CFG "/run/firejail/mnt/protocol"
49#define RUN_NONEWPRIVS_CFG "/run/firejail/mnt/nonewprivs"
49#define RUN_HOME_DIR "/run/firejail/mnt/home" 50#define RUN_HOME_DIR "/run/firejail/mnt/home"
50#define RUN_ETC_DIR "/run/firejail/mnt/etc" 51#define RUN_ETC_DIR "/run/firejail/mnt/etc"
51#define RUN_OPT_DIR "/run/firejail/mnt/opt" 52#define RUN_OPT_DIR "/run/firejail/mnt/opt"
diff --git a/src/firejail/join.c b/src/firejail/join.c
index c849b200c..50ef58f4b 100644
--- a/src/firejail/join.c
+++ b/src/firejail/join.c
@@ -100,21 +100,40 @@ static void extract_nogroups(pid_t pid) {
100 errExit("asprintf"); 100 errExit("asprintf");
101 101
102 struct stat s; 102 struct stat s;
103 if (stat(fname, &s) == -1) 103 if (stat(fname, &s) == -1) {
104 free(fname);
104 return; 105 return;
106 }
105 107
106 arg_nogroups = 1; 108 arg_nogroups = 1;
107 free(fname); 109 free(fname);
108} 110}
109 111
112static void extract_nonewprivs(pid_t pid) {
113 char *fname;
114 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_NONEWPRIVS_CFG) == -1)
115 errExit("asprintf");
116
117 struct stat s;
118 if (stat(fname, &s) == -1) {
119 free(fname);
120 return;
121 }
122
123 arg_nonewprivs = 1;
124 free(fname);
125}
126
110static void extract_cpu(pid_t pid) { 127static void extract_cpu(pid_t pid) {
111 char *fname; 128 char *fname;
112 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_CPU_CFG) == -1) 129 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_CPU_CFG) == -1)
113 errExit("asprintf"); 130 errExit("asprintf");
114 131
115 struct stat s; 132 struct stat s;
116 if (stat(fname, &s) == -1) 133 if (stat(fname, &s) == -1) {
134 free(fname);
117 return; 135 return;
136 }
118 137
119 // there is a CPU_CFG file, load it! 138 // there is a CPU_CFG file, load it!
120 load_cpu(fname); 139 load_cpu(fname);
@@ -127,8 +146,10 @@ static void extract_cgroup(pid_t pid) {
127 errExit("asprintf"); 146 errExit("asprintf");
128 147
129 struct stat s; 148 struct stat s;
130 if (stat(fname, &s) == -1) 149 if (stat(fname, &s) == -1) {
150 free(fname);
131 return; 151 return;
152 }
132 153
133 // there is a cgroup file CGROUP_CFG, load it! 154 // there is a cgroup file CGROUP_CFG, load it!
134 load_cgroup(fname); 155 load_cgroup(fname);
@@ -154,7 +175,10 @@ static void extract_caps_seccomp(pid_t pid) {
154 if (strncmp(buf, "Seccomp:", 8) == 0) { 175 if (strncmp(buf, "Seccomp:", 8) == 0) {
155 char *ptr = buf + 8; 176 char *ptr = buf + 8;
156 int val; 177 int val;
157 sscanf(ptr, "%d", &val); 178 if (sscanf(ptr, "%d", &val) != 1) {
179 fprintf(stderr, "Error: cannot read stat file for process %u\n", pid);
180 exit(1);
181 }
158 if (val == 2) 182 if (val == 2)
159 apply_seccomp = 1; 183 apply_seccomp = 1;
160 break; 184 break;
@@ -162,7 +186,10 @@ static void extract_caps_seccomp(pid_t pid) {
162 else if (strncmp(buf, "CapBnd:", 7) == 0) { 186 else if (strncmp(buf, "CapBnd:", 7) == 0) {
163 char *ptr = buf + 7; 187 char *ptr = buf + 7;
164 unsigned long long val; 188 unsigned long long val;
165 sscanf(ptr, "%llx", &val); 189 if (sscanf(ptr, "%llx", &val) != 1) {
190 fprintf(stderr, "Error: cannot read stat file for process %u\n", pid);
191 exit(1);
192 }
166 apply_caps = 1; 193 apply_caps = 1;
167 caps = val; 194 caps = val;
168 } 195 }
@@ -229,7 +256,7 @@ pid_t switch_to_child(pid_t pid) {
229 char *comm = pid_proc_comm(pid); 256 char *comm = pid_proc_comm(pid);
230 if (!comm) { 257 if (!comm) {
231 if (errno == ENOENT) { 258 if (errno == ENOENT) {
232 fprintf(stderr, "Error: cannot find process with id %d\n", pid); 259 fprintf(stderr, "Error: cannot find process with pid %d\n", pid);
233 exit(1); 260 exit(1);
234 } 261 }
235 else { 262 else {
@@ -285,6 +312,7 @@ void join(pid_t pid, int argc, char **argv, int index) {
285 EUID_ROOT(); 312 EUID_ROOT();
286 // in user mode set caps seccomp, cpu, cgroup, etc 313 // in user mode set caps seccomp, cpu, cgroup, etc
287 if (getuid() != 0) { 314 if (getuid() != 0) {
315 extract_nonewprivs(pid);
288 extract_caps_seccomp(pid); 316 extract_caps_seccomp(pid);
289 extract_cpu(pid); 317 extract_cpu(pid);
290 extract_cgroup(pid); 318 extract_cgroup(pid);
@@ -296,7 +324,7 @@ void join(pid_t pid, int argc, char **argv, int index) {
296 if (cfg.cgroup) // not available for uid 0 324 if (cfg.cgroup) // not available for uid 0
297 set_cgroup(cfg.cgroup); 325 set_cgroup(cfg.cgroup);
298 326
299 // get umask, it will be set by start_application() 327 // set umask, also uid 0
300 extract_umask(pid); 328 extract_umask(pid);
301 329
302 // join namespaces 330 // join namespaces
@@ -383,6 +411,13 @@ void join(pid_t pid, int argc, char **argv, int index) {
383 caps_set(caps); 411 caps_set(caps);
384 } 412 }
385 413
414 // set nonewprivs
415 if (arg_nonewprivs == 1) { // not available for uid 0
416 prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
417 if (arg_debug)
418 printf("NO_NEW_PRIVS set\n");
419 }
420
386 EUID_USER(); 421 EUID_USER();
387 // set nice 422 // set nice
388 if (arg_nice) { 423 if (arg_nice) {
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index 95732b95e..2113ef70f 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -109,7 +109,7 @@ static void set_caps(void) {
109 caps_drop_dac_override(); 109 caps_drop_dac_override();
110} 110}
111 111
112void save_nogroups(void) { 112static void save_nogroups(void) {
113 if (arg_nogroups == 0) 113 if (arg_nogroups == 0)
114 return; 114 return;
115 115
@@ -126,7 +126,23 @@ void save_nogroups(void) {
126 126
127} 127}
128 128
129void save_umask(void) { 129static void save_nonewprivs(void) {
130 if (arg_nonewprivs == 0)
131 return;
132
133 FILE *fp = fopen(RUN_NONEWPRIVS_CFG, "wxe");
134 if (fp) {
135 fprintf(fp, "\n");
136 SET_PERMS_STREAM(fp, 0, 0, 0644); // assume mode 0644
137 fclose(fp);
138 }
139 else {
140 fprintf(stderr, "Error: cannot save nonewprivs state\n");
141 exit(1);
142 }
143}
144
145static void save_umask(void) {
130 FILE *fp = fopen(RUN_UMASK_FILE, "wxe"); 146 FILE *fp = fopen(RUN_UMASK_FILE, "wxe");
131 if (fp) { 147 if (fp) {
132 fprintf(fp, "%o\n", orig_umask); 148 fprintf(fp, "%o\n", orig_umask);
@@ -597,11 +613,6 @@ int sandbox(void* sandbox_arg) {
597 fs_logger("install mount namespace"); 613 fs_logger("install mount namespace");
598 614
599 //**************************** 615 //****************************
600 // save the umask
601 //****************************
602 save_umask();
603
604 //****************************
605 // netfilter 616 // netfilter
606 //**************************** 617 //****************************
607 if (arg_netfilter && any_bridge_configured()) { // assuming by default the client filter 618 if (arg_netfilter && any_bridge_configured()) { // assuming by default the client filter
@@ -750,10 +761,17 @@ int sandbox(void* sandbox_arg) {
750 need_preload = arg_trace || arg_tracelog; 761 need_preload = arg_trace || arg_tracelog;
751 arg_seccomp = 1; 762 arg_seccomp = 1;
752 } 763 }
764
753 // trace pre-install 765 // trace pre-install
754 if (need_preload) 766 if (need_preload)
755 fs_trace_preload(); 767 fs_trace_preload();
756 768
769 // state of nonewprivs
770 save_nonewprivs();
771
772 // save original umask
773 save_umask();
774
757 // store hosts file 775 // store hosts file
758 if (cfg.hosts_file) 776 if (cfg.hosts_file)
759 fs_store_hosts_file(); 777 fs_store_hosts_file();