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.c130
1 files changed, 54 insertions, 76 deletions
diff --git a/src/jailtest/utils.c b/src/jailtest/utils.c
index b24783355..41c21b753 100644
--- a/src/jailtest/utils.c
+++ b/src/jailtest/utils.c
@@ -1,4 +1,24 @@
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*/
1#include "jailtest.h" 20#include "jailtest.h"
21#include "../include/pid.h"
2#include <errno.h> 22#include <errno.h>
3#include <pwd.h> 23#include <pwd.h>
4#include <dirent.h> 24#include <dirent.h>
@@ -38,87 +58,45 @@ errexit:
38 exit(1); 58 exit(1);
39} 59}
40 60
41int find_child(pid_t parent, pid_t *child) { 61// find the second child process for the specified pid
42 *child = 0; // use it to flag a found child 62// return -1 if not found
63//
64// Example:
65//14776:netblue:/usr/bin/firejail /usr/bin/transmission-qt
66// 14777:netblue:/usr/bin/firejail /usr/bin/transmission-qt
67// 14792:netblue:/usr/bin/transmission-qt
68// We need 14792, the first real sandboxed process
69// duplicate from src/firemon/main.c
70int find_child(int id) {
71 int i;
72 int first_child = -1;
43 73
44 DIR *dir; 74 // find the first child
45 if (!(dir = opendir("/proc"))) { 75 for (i = 0; i < max_pids; i++) {
46 // sleep 2 seconds and try again 76 if (pids[i].level == 2 && pids[i].parent == id) {
47 sleep(2); 77 // skip /usr/bin/xdg-dbus-proxy (started by firejail for dbus filtering)
48 if (!(dir = opendir("/proc"))) { 78 char *cmdline = pid_proc_cmdline(i);
49 fprintf(stderr, "Error: cannot open /proc directory\n"); 79 if (strncmp(cmdline, XDG_DBUS_PROXY_PATH, strlen(XDG_DBUS_PROXY_PATH)) == 0) {
50 exit(1); 80 free(cmdline);
51 } 81 continue;
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 } 82 }
83 free(cmdline);
84 first_child = i;
85 break;
96 } 86 }
97 fclose(fp);
98 free(file);
99 } 87 }
100 closedir(dir);
101 return (*child)? 0:1; // 0 = found, 1 = not found
102}
103 88
104pid_t switch_to_child(pid_t pid) { 89 if (first_child == -1)
105 pid_t rv = pid; 90 return -1;
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 91
116 if (strcmp(comm, "firejail") == 0) { 92 // find the second-level child
117 if (find_child(pid, &rv) == 1) { 93 for (i = 0; i < max_pids; i++) {
118 fprintf(stderr, "Error: no valid sandbox\n"); 94 if (pids[i].level == 3 && pids[i].parent == first_child)
119 exit(1); 95 return i;
120 }
121 } 96 }
122 free(comm); 97
123 return rv; 98 // if a second child is not found, return the first child pid
99 // this happens for processes sandboxed with --join
100 return first_child;
124} 101}
102