aboutsummaryrefslogtreecommitdiffstats
path: root/src/firejail/fs_dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/firejail/fs_dev.c')
-rw-r--r--src/firejail/fs_dev.c163
1 files changed, 163 insertions, 0 deletions
diff --git a/src/firejail/fs_dev.c b/src/firejail/fs_dev.c
new file mode 100644
index 000000000..80bd11582
--- /dev/null
+++ b/src/firejail/fs_dev.c
@@ -0,0 +1,163 @@
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#include "firejail.h"
21#include <sys/mount.h>
22#include <sys/stat.h>
23#include <linux/limits.h>
24#include <glob.h>
25#include <dirent.h>
26#include <fcntl.h>
27#include <pwd.h>
28#ifndef _BSD_SOURCE
29#define _BSD_SOURCE
30#endif
31#include <sys/types.h>
32
33static void create_char_dev(const char *path, mode_t mode, int major, int minor) {
34 dev_t dev = makedev(major, minor);
35 int rv = mknod(path, S_IFCHR | mode, dev);
36 if (rv == -1)
37 goto errexit;
38
39
40 if (chmod(path, mode) < 0)
41 goto errexit;
42 if (chown(path, 0, 0) < 0)
43 goto errexit;
44
45 return;
46
47errexit:
48 fprintf(stderr, "Error: cannot create %s device\n", path);
49 exit(1);
50}
51
52static void create_link(const char *oldpath, const char *newpath) {
53 if (symlink(oldpath, newpath) == -1)
54 goto errexit;
55 if (chown(newpath, 0, 0) < 0)
56 goto errexit;
57 return;
58
59errexit:
60 fprintf(stderr, "Error: cannot create %s device\n", newpath);
61 exit(1);
62}
63
64void fs_private_dev(void){
65 // install a new /dev directory
66 if (arg_debug)
67 printf("Mounting tmpfs on /dev\n");
68 if (mount("tmpfs", "/dev", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
69 errExit("mounting /dev");
70
71 // create /dev/shm
72 if (arg_debug)
73 printf("Create /dev/shm directory\n");
74 int rv = mkdir("/dev/shm", S_IRWXU | S_IRWXG | S_IRWXO);
75 if (rv == -1)
76 errExit("mkdir");
77 if (chown("/dev/shm", 0, 0) < 0)
78 errExit("chown");
79 if (chmod("/dev/shm", S_IRWXU | S_IRWXG | S_IRWXO) < 0)
80 errExit("chmod");
81
82 // create devices
83 create_char_dev("/dev/zero", 0666, 1, 5); // mknod -m 666 /dev/zero c 1 5
84 create_char_dev("/dev/null", 0666, 1, 3); // mknod -m 666 /dev/null c 1 3
85 create_char_dev("/dev/full", 0666, 1, 7); // mknod -m 666 /dev/full c 1 7
86 create_char_dev("/dev/random", 0666, 1, 8); // Mknod -m 666 /dev/random c 1 8
87 create_char_dev("/dev/urandom", 0666, 1, 9); // mknod -m 666 /dev/urandom c 1 9
88 create_char_dev("/dev/tty", 0666, 5, 0); // mknod -m 666 /dev/tty c 5 0
89#if 0
90 create_dev("/dev/tty0", "mknod -m 666 /dev/tty0 c 4 0");
91 create_dev("/dev/console", "mknod -m 622 /dev/console c 5 1");
92#endif
93
94 // pseudo-terminal
95 rv = mkdir("/dev/pts", 0755);
96 if (rv == -1)
97 errExit("mkdir");
98 if (chown("/dev/pts", 0, 0) < 0)
99 errExit("chown");
100 if (chmod("/dev/pts", 0755) < 0)
101 errExit("chmod");
102 create_char_dev("/dev/pts/ptmx", 0666, 5, 2); //"mknod -m 666 /dev/pts/ptmx c 5 2");
103 create_link("/dev/pts/ptmx", "/dev/ptmx");
104 // mount -vt devpts -o newinstance -o ptmxmode=0666 devpts //dev/pts
105 if (mount("devpts", "/dev/pts", "devpts", MS_MGC_VAL, "newinstance,ptmxmode=0666") < 0)
106 errExit("mounting /dev/pts");
107
108#if 0
109 // stdin, stdout, stderr
110 create_link("/proc/self/fd", "/dev/fd");
111 create_link("/proc/self/fd/0", "/dev/stdin");
112 create_link("/proc/self/fd/1", "/dev/stdout");
113 create_link("/proc/self/fd/2", "/dev/stderr");
114#endif
115}
116
117
118void fs_dev_shm(void) {
119 uid_t uid = getuid(); // set a new shm only if we started as root
120 if (uid)
121 return;
122
123 if (is_dir("/dev/shm")) {
124 if (arg_debug)
125 printf("Mounting tmpfs on /dev/shm\n");
126 if (mount("tmpfs", "/dev/shm", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
127 errExit("mounting /dev/shm");
128 }
129 else {
130 char *lnk = get_link("/dev/shm");
131 if (lnk) {
132 // convert a link such as "../shm" into "/shm"
133 char *lnk2 = lnk;
134 int cnt = 0;
135 while (strncmp(lnk2, "../", 3) == 0) {
136 cnt++;
137 lnk2 = lnk2 + 3;
138 }
139 if (cnt != 0)
140 lnk2 = lnk + (cnt - 1) * 3 + 2;
141
142 if (!is_dir(lnk2)) {
143 // create directory
144 if (mkdir(lnk2, S_IRWXU|S_IRWXG|S_IRWXO))
145 errExit("mkdir");
146 if (chown(lnk2, 0, 0))
147 errExit("chown");
148 if (chmod(lnk2, S_IRWXU|S_IRWXG|S_IRWXO))
149 errExit("chmod");
150 }
151 if (arg_debug)
152 printf("Mounting tmpfs on %s on behalf of /dev/shm\n", lnk2);
153 if (mount("tmpfs", lnk2, "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=777,gid=0") < 0)
154 errExit("mounting /var/tmp");
155 free(lnk);
156 }
157 else {
158 fprintf(stderr, "Warning: /dev/shm not mounted\n");
159 dbg_test_dir("/dev/shm");
160 }
161
162 }
163}