aboutsummaryrefslogtreecommitdiffstats
path: root/src/jailtest/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/jailtest/utils.c')
-rw-r--r--src/jailtest/utils.c124
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
8char *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
21char *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
36errexit:
37 fprintf(stderr, "Error: cannot find home directory for user %s\n", user);
38 exit(1);
39}
40
41int 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
104pid_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}