aboutsummaryrefslogtreecommitdiffstats
path: root/src/jailcheck/noexec.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/jailcheck/noexec.c')
-rw-r--r--src/jailcheck/noexec.c113
1 files changed, 113 insertions, 0 deletions
diff --git a/src/jailcheck/noexec.c b/src/jailcheck/noexec.c
new file mode 100644
index 000000000..7f994d6a1
--- /dev/null
+++ b/src/jailcheck/noexec.c
@@ -0,0 +1,113 @@
1/*
2 * Copyright (C) 2014-2021 Firejail Authors
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#include "jailcheck.h"
21#include <sys/wait.h>
22#include <sys/stat.h>
23#include <fcntl.h>
24
25static unsigned char *execfile = NULL;
26static int execfile_len = 0;
27
28void noexec_setup(void) {
29 // grab a copy of myself
30 char *self = realpath("/proc/self/exe", NULL);
31 if (self) {
32 struct stat s;
33 if (access(self, X_OK) == 0 && stat(self, &s) == 0) {
34 assert(s.st_size);
35 execfile = malloc(s.st_size);
36
37 int fd = open(self, O_RDONLY);
38 if (fd == -1)
39 errExit("open");
40 int len = 0;
41 do {
42 int rv = read(fd, execfile + len, s.st_size - len);
43 if (rv == -1)
44 errExit("read");
45 if (rv == 0) {
46 // something went wrong!
47 free(execfile);
48 execfile = NULL;
49 printf("Warning: I cannot grab a copy of myself, skipping noexec test...\n");
50 break;
51 }
52 len += rv;
53 }
54 while (len < s.st_size);
55 execfile_len = s.st_size;
56 close(fd);
57 }
58 }
59}
60
61
62void noexec_test(const char *path) {
63 assert(user_uid);
64
65 // I am root in sandbox mount namespace
66 if (!execfile)
67 return;
68
69 char *fname;
70 if (asprintf(&fname, "%s/jailcheck-noexec-%d", path, getpid()) == -1)
71 errExit("asprintf");
72
73 pid_t child = fork();
74 if (child == -1)
75 errExit("fork");
76
77 if (child == 0) { // child
78 // drop privileges
79 if (setgid(user_gid) != 0)
80 errExit("setgid");
81 if (setuid(user_uid) != 0)
82 errExit("setuid");
83 int fd = open(fname, O_CREAT | O_TRUNC | O_WRONLY, 0700);
84 if (fd == -1) {
85 printf(" I cannot create files in %s, skipping noexec...\n", path);
86 exit(1);
87 }
88
89 int len = 0;
90 while (len < execfile_len) {
91 int rv = write(fd, execfile + len, execfile_len - len);
92 if (rv == -1 || rv == 0) {
93 printf(" I cannot create files in %s, skipping noexec....\n", path);
94 exit(1);
95 }
96 len += rv;
97 }
98 fchmod(fd, 0700);
99 close(fd);
100
101 char *arg;
102 if (asprintf(&arg, "--hello=%s", path) == -1)
103 errExit("asprintf");
104 int rv = execl(fname, fname, arg, NULL);
105 (void) rv; // if we get here execl failed
106 exit(0);
107 }
108
109 int status;
110 wait(&status);
111 int rv = unlink(fname);
112 (void) rv;
113} \ No newline at end of file