diff options
Diffstat (limited to 'src/jailtest/utils.c')
-rw-r--r-- | src/jailtest/utils.c | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/src/jailtest/utils.c b/src/jailtest/utils.c new file mode 100644 index 000000000..b24783355 --- /dev/null +++ b/src/jailtest/utils.c | |||
@@ -0,0 +1,124 @@ | |||
1 | #include "jailtest.h" | ||
2 | #include <errno.h> | ||
3 | #include <pwd.h> | ||
4 | #include <dirent.h> | ||
5 | |||
6 | #define BUFLEN 4096 | ||
7 | |||
8 | char *get_sudo_user(void) { | ||
9 | char *user = getenv("SUDO_USER"); | ||
10 | if (!user) { | ||
11 | user = getpwuid(getuid())->pw_name; | ||
12 | if (!user) { | ||
13 | fprintf(stderr, "Error: cannot detect login user\n"); | ||
14 | exit(1); | ||
15 | } | ||
16 | } | ||
17 | |||
18 | return user; | ||
19 | } | ||
20 | |||
21 | char *get_homedir(const char *user, uid_t *uid, gid_t *gid) { | ||
22 | // find home directory | ||
23 | struct passwd *pw = getpwnam(user); | ||
24 | if (!pw) | ||
25 | goto errexit; | ||
26 | |||
27 | char *home = pw->pw_dir; | ||
28 | if (!home) | ||
29 | goto errexit; | ||
30 | |||
31 | *uid = pw->pw_uid; | ||
32 | *gid = pw->pw_gid; | ||
33 | |||
34 | return home; | ||
35 | |||
36 | errexit: | ||
37 | fprintf(stderr, "Error: cannot find home directory for user %s\n", user); | ||
38 | exit(1); | ||
39 | } | ||
40 | |||
41 | int find_child(pid_t parent, pid_t *child) { | ||
42 | *child = 0; // use it to flag a found child | ||
43 | |||
44 | DIR *dir; | ||
45 | if (!(dir = opendir("/proc"))) { | ||
46 | // sleep 2 seconds and try again | ||
47 | sleep(2); | ||
48 | if (!(dir = opendir("/proc"))) { | ||
49 | fprintf(stderr, "Error: cannot open /proc directory\n"); | ||
50 | exit(1); | ||
51 | } | ||
52 | } | ||
53 | |||
54 | struct dirent *entry; | ||
55 | char *end; | ||
56 | while (*child == 0 && (entry = readdir(dir))) { | ||
57 | pid_t pid = strtol(entry->d_name, &end, 10); | ||
58 | if (end == entry->d_name || *end) | ||
59 | continue; | ||
60 | if (pid == parent) | ||
61 | continue; | ||
62 | |||
63 | // open stat file | ||
64 | char *file; | ||
65 | if (asprintf(&file, "/proc/%u/status", pid) == -1) { | ||
66 | perror("asprintf"); | ||
67 | exit(1); | ||
68 | } | ||
69 | FILE *fp = fopen(file, "r"); | ||
70 | if (!fp) { | ||
71 | free(file); | ||
72 | continue; | ||
73 | } | ||
74 | |||
75 | // look for firejail executable name | ||
76 | char buf[BUFLEN]; | ||
77 | while (fgets(buf, BUFLEN - 1, fp)) { | ||
78 | if (strncmp(buf, "PPid:", 5) == 0) { | ||
79 | char *ptr = buf + 5; | ||
80 | while (*ptr != '\0' && (*ptr == ' ' || *ptr == '\t')) { | ||
81 | ptr++; | ||
82 | } | ||
83 | if (*ptr == '\0') { | ||
84 | fprintf(stderr, "Error: cannot read /proc file\n"); | ||
85 | exit(1); | ||
86 | } | ||
87 | if (parent == atoi(ptr)) { | ||
88 | // we don't want /usr/bin/xdg-dbus-proxy! | ||
89 | char *cmdline = pid_proc_cmdline(pid); | ||
90 | if (strncmp(cmdline, XDG_DBUS_PROXY_PATH, strlen(XDG_DBUS_PROXY_PATH)) != 0) | ||
91 | *child = pid; | ||
92 | free(cmdline); | ||
93 | } | ||
94 | break; // stop reading the file | ||
95 | } | ||
96 | } | ||
97 | fclose(fp); | ||
98 | free(file); | ||
99 | } | ||
100 | closedir(dir); | ||
101 | return (*child)? 0:1; // 0 = found, 1 = not found | ||
102 | } | ||
103 | |||
104 | pid_t switch_to_child(pid_t pid) { | ||
105 | pid_t rv = pid; | ||
106 | errno = 0; | ||
107 | char *comm = pid_proc_comm(pid); | ||
108 | if (!comm) { | ||
109 | if (errno == ENOENT) | ||
110 | fprintf(stderr, "Error: cannot find process with pid %d\n", pid); | ||
111 | else | ||
112 | fprintf(stderr, "Error: cannot read /proc file\n"); | ||
113 | exit(1); | ||
114 | } | ||
115 | |||
116 | if (strcmp(comm, "firejail") == 0) { | ||
117 | if (find_child(pid, &rv) == 1) { | ||
118 | fprintf(stderr, "Error: no valid sandbox\n"); | ||
119 | exit(1); | ||
120 | } | ||
121 | } | ||
122 | free(comm); | ||
123 | return rv; | ||
124 | } | ||