aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/common.c')
-rw-r--r--src/lib/common.c192
1 files changed, 192 insertions, 0 deletions
diff --git a/src/lib/common.c b/src/lib/common.c
new file mode 100644
index 000000000..6d928abbb
--- /dev/null
+++ b/src/lib/common.c
@@ -0,0 +1,192 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
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#define _GNU_SOURCE
21#include <stdio.h>
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <sys/wait.h>
25#include <fcntl.h>
26#include <sys/syscall.h>
27#include <errno.h>
28#include <unistd.h>
29#include <sys/prctl.h>
30#include <signal.h>
31#include <dirent.h>
32#include <string.h>
33#include "../include/common.h"
34
35int join_namespace(pid_t pid, char *type) {
36 char *path;
37 if (asprintf(&path, "/proc/%u/ns/%s", pid, type) == -1)
38 errExit("asprintf");
39
40 int fd = open(path, O_RDONLY);
41 if (fd < 0) {
42 free(path);
43 fprintf(stderr, "Error: cannot open /proc/%u/ns/%s.\n", pid, type);
44 return -1;
45 }
46
47 if (syscall(__NR_setns, fd, 0) < 0) {
48 free(path);
49 fprintf(stderr, "Error: cannot join namespace %s.\n", type);
50 close(fd);
51 return -1;
52 }
53
54 close(fd);
55 free(path);
56 return 0;
57}
58
59// return 1 if error
60int name2pid(const char *name, pid_t *pid) {
61 pid_t parent = getpid();
62
63 DIR *dir;
64 if (!(dir = opendir("/proc"))) {
65 // sleep 2 seconds and try again
66 sleep(2);
67 if (!(dir = opendir("/proc"))) {
68 fprintf(stderr, "Error: cannot open /proc directory\n");
69 exit(1);
70 }
71 }
72
73 struct dirent *entry;
74 char *end;
75 while ((entry = readdir(dir))) {
76 pid_t newpid = strtol(entry->d_name, &end, 10);
77 if (end == entry->d_name || *end)
78 continue;
79 if (newpid == parent)
80 continue;
81
82 // check if this is a firejail executable
83 char *comm = pid_proc_comm(newpid);
84 if (comm) {
85 // remove \n
86 char *ptr = strchr(comm, '\n');
87 if (ptr)
88 *ptr = '\0';
89 if (strcmp(comm, "firejail")) {
90 free(comm);
91 continue;
92 }
93 free(comm);
94 }
95
96 char *cmd = pid_proc_cmdline(newpid);
97 if (cmd) {
98 // mark the end of the name
99 char *ptr = strstr(cmd, "--name=");
100 char *start = ptr;
101 if (!ptr) {
102 free(cmd);
103 continue;
104 }
105 while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0')
106 ptr++;
107 *ptr = '\0';
108 int rv = strcmp(start + 7, name);
109 if (rv == 0) {
110 free(cmd);
111 *pid = newpid;
112 closedir(dir);
113 return 0;
114 }
115 free(cmd);
116 }
117 }
118 closedir(dir);
119 return 1;
120}
121
122#define BUFLEN 4096
123char *pid_proc_comm(const pid_t pid) {
124 // open /proc/pid/cmdline file
125 char *fname;
126 int fd;
127 if (asprintf(&fname, "/proc/%d//comm", pid) == -1)
128 return NULL;
129 if ((fd = open(fname, O_RDONLY)) < 0) {
130 free(fname);
131 return NULL;
132 }
133 free(fname);
134
135 // read file
136 unsigned char buffer[BUFLEN];
137 ssize_t len;
138 if ((len = read(fd, buffer, sizeof(buffer) - 1)) <= 0) {
139 close(fd);
140 return NULL;
141 }
142 buffer[len] = '\0';
143 close(fd);
144
145 // return a malloc copy of the command line
146 char *rv = strdup((char *) buffer);
147 if (strlen(rv) == 0) {
148 free(rv);
149 return NULL;
150 }
151 return rv;
152}
153
154char *pid_proc_cmdline(const pid_t pid) {
155 // open /proc/pid/cmdline file
156 char *fname;
157 int fd;
158 if (asprintf(&fname, "/proc/%d/cmdline", pid) == -1)
159 return NULL;
160 if ((fd = open(fname, O_RDONLY)) < 0) {
161 free(fname);
162 return NULL;
163 }
164 free(fname);
165
166 // read file
167 unsigned char buffer[BUFLEN];
168 ssize_t len;
169 if ((len = read(fd, buffer, sizeof(buffer) - 1)) <= 0) {
170 close(fd);
171 return NULL;
172 }
173 buffer[len] = '\0';
174 close(fd);
175
176 // clean data
177 int i;
178 for (i = 0; i < len; i++) {
179 if (buffer[i] == '\0')
180 buffer[i] = ' ';
181 if (buffer[i] >= 0x80) // execv in progress!!!
182 return NULL;
183 }
184
185 // return a malloc copy of the command line
186 char *rv = strdup((char *) buffer);
187 if (strlen(rv) == 0) {
188 free(rv);
189 return NULL;
190 }
191 return rv;
192}