aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@protonmail.com>2023-10-24 12:43:46 -0400
committerLibravatar Kelvin M. Klann <kmk3.code@protonmail.com>2023-11-07 17:55:13 -0300
commit13b2c566df883269b55f77757bb50a5d2890ec20 (patch)
tree5c7ccc9d00886b93c4429a91671161fa6464f1f9 /src
parentcleanup (diff)
downloadfirejail-13b2c566df883269b55f77757bb50a5d2890ec20.tar.gz
firejail-13b2c566df883269b55f77757bb50a5d2890ec20.tar.zst
firejail-13b2c566df883269b55f77757bb50a5d2890ec20.zip
feature: add Landlock support
Based on 5315 by ChrysoliteAzalea. It is based on the same underlying structure, but with a lot of refactoring/simplification and with bugfixes and improvements. Co-authored-by: Kelvin M. Klann <kmk3.code@protonmail.com> Co-authored-by: Азалия Смарагдова <charming.flurry@yandex.ru>
Diffstat (limited to 'src')
-rw-r--r--src/bash_completion/firejail.bash_completion.in19
-rw-r--r--src/firejail/checkcfg.c7
-rw-r--r--src/firejail/firejail.h22
-rw-r--r--src/firejail/landlock.c263
-rw-r--r--src/firejail/main.c28
-rw-r--r--src/firejail/profile.c38
-rw-r--r--src/firejail/sandbox.c22
-rw-r--r--src/firejail/usage.c8
-rw-r--r--src/firejail/util.c7
-rw-r--r--src/man/firejail-profile.5.in31
-rw-r--r--src/man/firejail.1.in87
-rw-r--r--src/zsh_completion/_firejail.in5
12 files changed, 537 insertions, 0 deletions
diff --git a/src/bash_completion/firejail.bash_completion.in b/src/bash_completion/firejail.bash_completion.in
index 98e3a035e..eab0f7df6 100644
--- a/src/bash_completion/firejail.bash_completion.in
+++ b/src/bash_completion/firejail.bash_completion.in
@@ -42,6 +42,25 @@ _firejail()
42 _filedir -d 42 _filedir -d
43 return 0 43 return 0
44 ;; 44 ;;
45 --landlock)
46 return 0
47 ;;
48 --landlock.read)
49 _filedir
50 return 0
51 ;;
52 --landlock.write)
53 _filedir
54 return 0
55 ;;
56 --landlock.special)
57 _filedir
58 return 0
59 ;;
60 --landlock.execute)
61 _filedir
62 return 0
63 ;;
45 --tmpfs) 64 --tmpfs)
46 _filedir 65 _filedir
47 return 0 66 return 0
diff --git a/src/firejail/checkcfg.c b/src/firejail/checkcfg.c
index d2289bb40..7792c6541 100644
--- a/src/firejail/checkcfg.c
+++ b/src/firejail/checkcfg.c
@@ -363,6 +363,13 @@ static const char *const compiletime_support =
363 "disabled" 363 "disabled"
364#endif 364#endif
365 365
366 "\n\t- Landlock support is "
367#ifdef HAVE_LANDLOCK
368 "enabled"
369#else
370 "disabled"
371#endif
372
366 "\n\t- networking support is " 373 "\n\t- networking support is "
367#ifdef HAVE_NETWORK 374#ifdef HAVE_NETWORK
368 "enabled" 375 "enabled"
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index c791913ea..efeda7228 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -281,6 +281,9 @@ extern int arg_overlay; // overlay option
281extern int arg_overlay_keep; // place overlay diff in a known directory 281extern int arg_overlay_keep; // place overlay diff in a known directory
282extern int arg_overlay_reuse; // allow the reuse of overlays 282extern int arg_overlay_reuse; // allow the reuse of overlays
283 283
284extern int arg_landlock; // add basic Landlock rules
285extern int arg_landlock_proc; // 0 - no access; 1 -read-only; 2 - read-write
286
284extern int arg_seccomp; // enable default seccomp filter 287extern int arg_seccomp; // enable default seccomp filter
285extern int arg_seccomp32; // enable default seccomp filter for 32 bit arch 288extern int arg_seccomp32; // enable default seccomp filter for 32 bit arch
286extern int arg_seccomp_postexec; // need postexec ld.preload library? 289extern int arg_seccomp_postexec; // need postexec ld.preload library?
@@ -950,4 +953,23 @@ void run_ids(int argc, char **argv);
950// oom.c 953// oom.c
951void oom_set(const char *oom_string); 954void oom_set(const char *oom_string);
952 955
956// landlock.c
957#ifdef HAVE_LANDLOCK
958int ll_get_fd(void);
959int ll_read(const char *allowed_path);
960int ll_write(const char *allowed_path);
961int ll_special(const char *allowed_path);
962int ll_exec(const char *allowed_path);
963int ll_basic_system(void);
964int ll_restrict(__u32 flags);
965#else
966static inline int ll_get_fd(void) { return -1; }
967static inline int ll_read(...) { return 0; }
968static inline int ll_write(...) { return 0; }
969static inline int ll_special(...) { return 0; }
970static inline int ll_exec(...) { return 0; }
971static inline int ll_basic_system(void) { return 0; }
972static inline int ll_restrict(...) { return 0; }
973#endif /* HAVE_LANDLOCK */
974
953#endif 975#endif
diff --git a/src/firejail/landlock.c b/src/firejail/landlock.c
new file mode 100644
index 000000000..b5f4140c5
--- /dev/null
+++ b/src/firejail/landlock.c
@@ -0,0 +1,263 @@
1/*
2 * Copyright (C) 2014-2023 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*/
20
21#ifdef HAVE_LANDLOCK
22#include "firejail.h"
23#include <linux/landlock.h>
24#include <sys/prctl.h>
25#include <sys/syscall.h>
26#include <sys/types.h>
27#include <errno.h>
28#include <fcntl.h>
29
30static int ll_ruleset_fd = -1;
31
32int ll_get_fd(void) {
33 return ll_ruleset_fd;
34}
35
36#ifndef landlock_create_ruleset
37static inline int
38landlock_create_ruleset(const struct landlock_ruleset_attr *const attr,
39 const size_t size, const __u32 flags) {
40 return syscall(__NR_landlock_create_ruleset, attr, size, flags);
41}
42#endif
43
44#ifndef landlock_add_rule
45static inline int
46landlock_add_rule(const int ruleset_fd,
47 const enum landlock_rule_type rule_type,
48 const void *const rule_attr,
49 const __u32 flags) {
50 return syscall(__NR_landlock_add_rule, ruleset_fd, rule_type,
51 rule_attr, flags);
52}
53#endif
54
55#ifndef landlock_restrict_self
56static inline int
57landlock_restrict_self(const int ruleset_fd, const __u32 flags) {
58 return syscall(__NR_landlock_restrict_self, ruleset_fd, flags);
59}
60#endif
61
62static int ll_create_full_ruleset() {
63 struct landlock_ruleset_attr attr;
64 attr.handled_access_fs =
65 LANDLOCK_ACCESS_FS_EXECUTE |
66 LANDLOCK_ACCESS_FS_MAKE_BLOCK |
67 LANDLOCK_ACCESS_FS_MAKE_CHAR |
68 LANDLOCK_ACCESS_FS_MAKE_DIR |
69 LANDLOCK_ACCESS_FS_MAKE_FIFO |
70 LANDLOCK_ACCESS_FS_MAKE_REG |
71 LANDLOCK_ACCESS_FS_MAKE_SOCK |
72 LANDLOCK_ACCESS_FS_MAKE_SYM |
73 LANDLOCK_ACCESS_FS_READ_DIR |
74 LANDLOCK_ACCESS_FS_READ_FILE |
75 LANDLOCK_ACCESS_FS_REMOVE_DIR |
76 LANDLOCK_ACCESS_FS_REMOVE_FILE |
77 LANDLOCK_ACCESS_FS_WRITE_FILE;
78
79 ll_ruleset_fd = landlock_create_ruleset(&attr, sizeof(attr), 0);
80 if (ll_ruleset_fd < 0) {
81 fprintf(stderr, "Error: failed to create a Landlock ruleset: %s\n",
82 strerror(errno));
83 }
84 return ll_ruleset_fd;
85}
86
87int ll_read(const char *allowed_path) {
88 if (ll_ruleset_fd == -1)
89 ll_ruleset_fd = ll_create_full_ruleset();
90
91 int error;
92 int allowed_fd = open(allowed_path, O_PATH | O_CLOEXEC);
93 if (allowed_fd < 0) {
94 if (arg_debug) {
95 fprintf(stderr, "%s: failed to open %s: %s\n",
96 __func__, allowed_path, strerror(errno));
97 }
98 return 0;
99 }
100 struct landlock_path_beneath_attr target;
101 target.parent_fd = allowed_fd;
102 target.allowed_access =
103 LANDLOCK_ACCESS_FS_READ_DIR |
104 LANDLOCK_ACCESS_FS_READ_FILE;
105
106 error = landlock_add_rule(ll_ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
107 &target, 0);
108 if (error) {
109 fprintf(stderr, "Error: %s: failed to add Landlock rule for %s: %s\n",
110 __func__, allowed_path, strerror(errno));
111 }
112 close(allowed_fd);
113 return error;
114}
115
116int ll_write(const char *allowed_path) {
117 if (ll_ruleset_fd == -1)
118 ll_ruleset_fd = ll_create_full_ruleset();
119
120 int error;
121 int allowed_fd = open(allowed_path, O_PATH | O_CLOEXEC);
122 if (allowed_fd < 0) {
123 if (arg_debug) {
124 fprintf(stderr, "%s: failed to open %s: %s\n",
125 __func__, allowed_path, strerror(errno));
126 }
127 return 0;
128 }
129 struct landlock_path_beneath_attr target;
130 target.parent_fd = allowed_fd;
131 target.allowed_access =
132 LANDLOCK_ACCESS_FS_MAKE_DIR |
133 LANDLOCK_ACCESS_FS_MAKE_REG |
134 LANDLOCK_ACCESS_FS_MAKE_SYM |
135 LANDLOCK_ACCESS_FS_REMOVE_DIR |
136 LANDLOCK_ACCESS_FS_REMOVE_FILE |
137 LANDLOCK_ACCESS_FS_WRITE_FILE;
138
139 error = landlock_add_rule(ll_ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
140 &target, 0);
141 if (error) {
142 fprintf(stderr, "Error: %s: failed to add Landlock rule for %s: %s\n",
143 __func__, allowed_path, strerror(errno));
144 }
145 close(allowed_fd);
146 return error;
147}
148
149int ll_special(const char *allowed_path) {
150 if (ll_ruleset_fd == -1)
151 ll_ruleset_fd = ll_create_full_ruleset();
152
153 int error;
154 int allowed_fd = open(allowed_path, O_PATH | O_CLOEXEC);
155 if (allowed_fd < 0) {
156 if (arg_debug) {
157 fprintf(stderr, "%s: failed to open %s: %s\n",
158 __func__, allowed_path, strerror(errno));
159 }
160 return 0;
161 }
162 struct landlock_path_beneath_attr target;
163 target.parent_fd = allowed_fd;
164 target.allowed_access =
165 LANDLOCK_ACCESS_FS_MAKE_BLOCK |
166 LANDLOCK_ACCESS_FS_MAKE_CHAR |
167 LANDLOCK_ACCESS_FS_MAKE_FIFO |
168 LANDLOCK_ACCESS_FS_MAKE_SOCK;
169
170 error = landlock_add_rule(ll_ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
171 &target, 0);
172 if (error) {
173 fprintf(stderr, "Error: %s: failed to add Landlock rule for %s: %s\n",
174 __func__, allowed_path, strerror(errno));
175 }
176 close(allowed_fd);
177 return error;
178}
179
180int ll_exec(const char *allowed_path) {
181 if (ll_ruleset_fd == -1)
182 ll_ruleset_fd = ll_create_full_ruleset();
183
184 int error;
185 int allowed_fd = open(allowed_path, O_PATH | O_CLOEXEC);
186 if (allowed_fd < 0) {
187 if (arg_debug) {
188 fprintf(stderr, "%s: failed to open %s: %s\n",
189 __func__, allowed_path, strerror(errno));
190 }
191 return 0;
192 }
193 struct landlock_path_beneath_attr target;
194 target.parent_fd = allowed_fd;
195 target.allowed_access =
196 LANDLOCK_ACCESS_FS_EXECUTE;
197
198 error = landlock_add_rule(ll_ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
199 &target, 0);
200 if (error) {
201 fprintf(stderr, "Error: %s: failed to add Landlock rule for %s: %s\n",
202 __func__, allowed_path, strerror(errno));
203 }
204 close(allowed_fd);
205 return error;
206}
207
208int ll_basic_system(void) {
209 assert(cfg.homedir);
210
211 if (ll_ruleset_fd == -1)
212 ll_ruleset_fd = ll_create_full_ruleset();
213
214 int error =
215 ll_read("/bin/") ||
216 ll_read("/dev/") ||
217 ll_read("/etc/") ||
218 ll_read("/lib/") ||
219 ll_read("/opt/") ||
220 ll_read("/usr/") ||
221 ll_read("/var/") ||
222 ll_read(cfg.homedir) ||
223
224 ll_write("/dev/") ||
225 ll_write(cfg.homedir) ||
226
227 ll_exec("/bin/") ||
228 ll_exec("/lib/") ||
229 ll_exec("/opt/") ||
230 ll_exec("/usr/");
231
232 if (error) {
233 fprintf(stderr, "Error: %s: failed to set --landlock rules\n",
234 __func__);
235 }
236 return error;
237}
238
239int ll_restrict(__u32 flags) {
240 if (ll_ruleset_fd == -1)
241 return 0;
242
243 int error;
244 error = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
245 if (error) {
246 fprintf(stderr, "Error: %s: failed to restrict privileges: %s\n",
247 __func__, strerror(errno));
248 goto out;
249 }
250 error = landlock_restrict_self(ll_ruleset_fd, flags);
251 if (error) {
252 fprintf(stderr, "Error: %s: failed to enforce Landlock: %s\n",
253 __func__, strerror(errno));
254 goto out;
255 }
256 if (arg_debug)
257 printf("%s: Enforcing Landlock\n", __func__);
258out:
259 close(ll_ruleset_fd);
260 return error;
261}
262
263#endif /* HAVE_LANDLOCK */
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 0c9c80137..df31fe2ce 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -75,6 +75,9 @@ int arg_overlay = 0; // overlay option
75int arg_overlay_keep = 0; // place overlay diff in a known directory 75int arg_overlay_keep = 0; // place overlay diff in a known directory
76int arg_overlay_reuse = 0; // allow the reuse of overlays 76int arg_overlay_reuse = 0; // allow the reuse of overlays
77 77
78int arg_landlock = 0; // add basic Landlock rules
79int arg_landlock_proc = 2; // 0 - no access; 1 -read-only; 2 - read-write
80
78int arg_seccomp = 0; // enable default seccomp filter 81int arg_seccomp = 0; // enable default seccomp filter
79int arg_seccomp32 = 0; // enable default seccomp filter for 32 bit arch 82int arg_seccomp32 = 0; // enable default seccomp filter for 32 bit arch
80int arg_seccomp_postexec = 0; // need postexec ld.preload library? 83int arg_seccomp_postexec = 0; // need postexec ld.preload library?
@@ -1500,6 +1503,31 @@ int main(int argc, char **argv, char **envp) {
1500 else 1503 else
1501 exit_err_feature("seccomp"); 1504 exit_err_feature("seccomp");
1502 } 1505 }
1506#ifdef HAVE_LANDLOCK
1507 else if (strcmp(argv[i], "--landlock") == 0)
1508 arg_landlock = 1;
1509 else if (strncmp(argv[i], "--landlock.proc=", 16) == 0) {
1510 if (strncmp(argv[i] + 16, "no", 2) == 0)
1511 arg_landlock_proc = 0;
1512 else if (strncmp(argv[i] + 16, "ro", 2) == 0)
1513 arg_landlock_proc = 1;
1514 else if (strncmp(argv[i] + 16, "rw", 2) == 0)
1515 arg_landlock_proc = 2;
1516 else {
1517 fprintf(stderr, "Error: invalid landlock.proc value: %s\n",
1518 argv[i] + 16);
1519 exit(1);
1520 }
1521 }
1522 else if (strncmp(argv[i], "--landlock.read=", 16) == 0)
1523 ll_read(argv[i] + 16);
1524 else if (strncmp(argv[i], "--landlock.write=", 17) == 0)
1525 ll_write(argv[i] + 17);
1526 else if (strncmp(argv[i], "--landlock.special=", 19) == 0)
1527 ll_special(argv[i] + 19);
1528 else if (strncmp(argv[i], "--landlock.execute=", 19) == 0)
1529 ll_exec(argv[i] + 19);
1530#endif
1503 else if (strcmp(argv[i], "--memory-deny-write-execute") == 0) { 1531 else if (strcmp(argv[i], "--memory-deny-write-execute") == 0) {
1504 if (checkcfg(CFG_SECCOMP)) 1532 if (checkcfg(CFG_SECCOMP))
1505 arg_memory_deny_write_execute = 1; 1533 arg_memory_deny_write_execute = 1;
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index a250e5611..08804c5f3 100644
--- a/src/firejail/profile.c
+++ b/src/firejail/profile.c
@@ -1077,6 +1077,44 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
1077 return 0; 1077 return 0;
1078 } 1078 }
1079 1079
1080#ifdef HAVE_LANDLOCK
1081 // Landlock ruleset paths
1082 if (strcmp(ptr, "landlock") == 0) {
1083 arg_landlock = 1;
1084 return 0;
1085 }
1086 if (strncmp(ptr, "landlock.proc ", 14) == 0) {
1087 if (strncmp(ptr + 14, "no", 2) == 0)
1088 arg_landlock_proc = 0;
1089 else if (strncmp(ptr + 14, "ro", 2) == 0)
1090 arg_landlock_proc = 1;
1091 else if (strncmp(ptr + 14, "rw", 2) == 0)
1092 arg_landlock_proc = 2;
1093 else {
1094 fprintf(stderr, "Error: invalid landlock.proc value: %s\n",
1095 ptr + 14);
1096 exit(1);
1097 }
1098 return 0;
1099 }
1100 if (strncmp(ptr, "landlock.read ", 14) == 0) {
1101 ll_read(ptr + 14);
1102 return 0;
1103 }
1104 if (strncmp(ptr, "landlock.write ", 15) == 0) {
1105 ll_write(ptr + 15);
1106 return 0;
1107 }
1108 if (strncmp(ptr, "landlock.special ", 17) == 0) {
1109 ll_special(ptr + 17);
1110 return 0;
1111 }
1112 if (strncmp(ptr, "landlock.execute ", 17) == 0) {
1113 ll_exec(ptr + 17);
1114 return 0;
1115 }
1116#endif
1117
1080 // memory deny write&execute 1118 // memory deny write&execute
1081 if (strcmp(ptr, "memory-deny-write-execute") == 0) { 1119 if (strcmp(ptr, "memory-deny-write-execute") == 0) {
1082 if (checkcfg(CFG_SECCOMP)) 1120 if (checkcfg(CFG_SECCOMP))
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index 827be5d85..dbc115137 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -516,6 +516,28 @@ void start_application(int no_sandbox, int fd, char *set_sandbox_status) {
516 printf("LD_PRELOAD=%s\n", getenv("LD_PRELOAD")); 516 printf("LD_PRELOAD=%s\n", getenv("LD_PRELOAD"));
517 } 517 }
518 518
519#ifdef HAVE_LANDLOCK
520 //****************************
521 // Configure Landlock
522 //****************************
523 if (arg_landlock)
524 ll_basic_system();
525
526 if (ll_get_fd() != -1) {
527 if (arg_landlock_proc >= 1)
528 ll_read("/proc/");
529 if (arg_landlock_proc == 2)
530 ll_write("/proc/");
531 }
532
533 if (ll_restrict(0)) {
534 // It isn't safe to continue if Landlock self-restriction was
535 // enabled and the "landlock_restrict_self" syscall has failed.
536 fprintf(stderr, "Error: ll_restrict() failed, exiting...\n");
537 exit(1);
538 }
539#endif
540
519 if (just_run_the_shell) { 541 if (just_run_the_shell) {
520 char *arg[2]; 542 char *arg[2];
521 arg[0] = cfg.usershell; 543 arg[0] = cfg.usershell;
diff --git a/src/firejail/usage.c b/src/firejail/usage.c
index e8758c807..5f9185da9 100644
--- a/src/firejail/usage.c
+++ b/src/firejail/usage.c
@@ -133,6 +133,14 @@ static const char *const usage_str =
133 " --keep-fd - inherit open file descriptors to sandbox.\n" 133 " --keep-fd - inherit open file descriptors to sandbox.\n"
134 " --keep-shell-rc - do not copy shell rc files from /etc/skel\n" 134 " --keep-shell-rc - do not copy shell rc files from /etc/skel\n"
135 " --keep-var-tmp - /var/tmp directory is untouched.\n" 135 " --keep-var-tmp - /var/tmp directory is untouched.\n"
136#ifdef HAVE_LANDLOCK
137 " --landlock - add basic rules to the Landlock ruleset.\n"
138 " --landlock.proc=no|ro|rw - add an access rule for /proc to the Landlock ruleset.\n"
139 " --landlock.read=path - add a read access rule for the path to the Landlock ruleset.\n"
140 " --landlock.write=path - add a write access rule for the path to the Landlock ruleset.\n"
141 " --landlock.special=path - add an access rule for the path to the Landlock ruleset for creating block/char devices, named pipes and sockets.\n"
142 " --landlock.execute=path - add an execute access rule for the path to the Landlock ruleset.\n"
143#endif
136 " --list - list all sandboxes.\n" 144 " --list - list all sandboxes.\n"
137#ifdef HAVE_FILE_TRANSFER 145#ifdef HAVE_FILE_TRANSFER
138 " --ls=name|pid dir_or_filename - list files in sandbox container.\n" 146 " --ls=name|pid dir_or_filename - list files in sandbox container.\n"
diff --git a/src/firejail/util.c b/src/firejail/util.c
index bd32181b5..c0f30931c 100644
--- a/src/firejail/util.c
+++ b/src/firejail/util.c
@@ -1338,6 +1338,13 @@ void close_all(int *keep_list, size_t sz) {
1338 if (keep) 1338 if (keep)
1339 continue; 1339 continue;
1340 1340
1341#ifdef HAVE_LANDLOCK
1342 // Don't close the file descriptor of the Landlock ruleset; it
1343 // will be automatically closed by the "ll_restrict" wrapper
1344 // function.
1345 if (fd == ll_get_fd())
1346 continue;
1347#endif
1341 close(fd); 1348 close(fd);
1342 } 1349 }
1343 closedir(dir); 1350 closedir(dir);
diff --git a/src/man/firejail-profile.5.in b/src/man/firejail-profile.5.in
index 3a678b14f..76f5e4d20 100644
--- a/src/man/firejail-profile.5.in
+++ b/src/man/firejail-profile.5.in
@@ -507,6 +507,37 @@ Blacklist all Linux capabilities.
507.TP 507.TP
508\fBcaps.keep capability,capability,capability 508\fBcaps.keep capability,capability,capability
509Whitelist given Linux capabilities. 509Whitelist given Linux capabilities.
510#ifdef HAVE_LANDLOCK
511.TP
512\fBlandlock
513Create a Landlock ruleset (if it doesn't already exist) and add basic access
514rules to it.
515.TP
516\fBlandlock.proc no|ro|rw
517Add an access rule for /proc directory (read-only if set to \fBro\fR and
518read-write if set to \fBrw\fR).
519The access rule for /proc is added after this directory is set up in the
520sandbox.
521Access rules for /proc set up with other Landlock-related profile options have
522no effect.
523.TP
524\fBlandlock.read path
525Create a Landlock ruleset (if it doesn't already exist) and add a read access
526rule for path.
527.TP
528\fBlandlock.write path
529Create a Landlock ruleset (if it doesn't already exist) and add a write access
530rule for path.
531.TP
532\fBlandlock.special path
533Create a Landlock ruleset (if it doesn't already exist) and add a rule that
534allows the creation of block devices, character devices, named pipes (FIFOs)
535and Unix domain sockets beneath given path.
536.TP
537\fBlandlock.execute path
538Create a Landlock ruleset (if it doesn't already exist) and add an execution
539permission rule for path.
540#endif
510.TP 541.TP
511\fBmemory-deny-write-execute 542\fBmemory-deny-write-execute
512Install a seccomp filter to block attempts to create memory mappings 543Install a seccomp filter to block attempts to create memory mappings
diff --git a/src/man/firejail.1.in b/src/man/firejail.1.in
index 06969e851..d5a00c41b 100644
--- a/src/man/firejail.1.in
+++ b/src/man/firejail.1.in
@@ -1243,6 +1243,52 @@ Example:
1243.br 1243.br
1244$ firejail --keep-var-tmp 1244$ firejail --keep-var-tmp
1245 1245
1246#ifdef HAVE_LANDLOCK
1247.TP
1248\fB\-\-landlock
1249Create a Landlock ruleset (if it doesn't already exist) and add basic access
1250rules to it.
1251The basic set of rules applies the following access permissions:
1252.PP
1253.RS
1254- read: /bin, /dev, /etc, /lib, /opt, /proc, /usr, /var
1255.br
1256- write: /dev, /proc
1257.br
1258- exec: /bin, /lib, /opt, /usr
1259.RE
1260.PP
1261See the \fBLANDLOCK\fR section for more information.
1262.TP
1263\fB\-\-landlock.proc=no|ro|rw
1264Add an access rule for /proc directory (read-only if set to \fBro\fR and
1265read-write if set to \fBrw\fR).
1266The access rule for /proc is added after this directory is set up in the
1267sandbox.
1268Access rules for /proc set up with other Landlock-related command-line options
1269have no effect.
1270.TP
1271\fB\-\-landlock.read=path
1272Create a Landlock ruleset (if it doesn't already exist) and add a read access
1273rule for path.
1274.TP
1275\fB\-\-landlock.write=path
1276Create a Landlock ruleset (if it doesn't already exist) and add a write access
1277rule for path.
1278.TP
1279\fB\-\-landlock.special=path
1280Create a Landlock ruleset (if it doesn't already exist) and add a rule that
1281allows the creation of block devices, character devices, named pipes (FIFOs)
1282and Unix domain sockets beneath given path.
1283.TP
1284\fB\-\-landlock.execute=path
1285Create a Landlock ruleset (if it doesn't already exist) and add an execution
1286permission rule for path.
1287.PP
1288Example:
1289.PP
1290$ firejail \-\-landlock.read=/ \-\-landlock.write=/home \-\-landlock.execute=/usr
1291#endif
1246.TP 1292.TP
1247\fB\-\-list 1293\fB\-\-list
1248List all sandboxes, see \fBMONITORING\fR section for more details. 1294List all sandboxes, see \fBMONITORING\fR section for more details.
@@ -3365,6 +3411,47 @@ To enable AppArmor confinement on top of your current Firejail security features
3365$ firejail --apparmor firefox 3411$ firejail --apparmor firefox
3366#endif 3412#endif
3367 3413
3414#ifdef HAVE_LANDLOCK
3415.SH LANDLOCK
3416Landlock is a Linux security module first introduced in version 5.13 of the
3417Linux kernel.
3418It allows unprivileged processes to restrict their access to the filesystem.
3419Once imposed, these restrictions can never be removed, and all child processes
3420created by a Landlock-restricted processes inherit these restrictions.
3421Firejail supports Landlock as an additional sandboxing feature.
3422It can be used to ensure that a sandboxed application can only access files and
3423directories that it was explicitly allowed to access.
3424Firejail supports populating the ruleset with both a basic set of rules (see
3425\fB\-\-landlock\fR) and with a custom set of rules.
3426.TP
3427Important notes:
3428.PP
3429.RS
3430- A process can install a Landlock ruleset only if it has either
3431\fBCAP_SYS_ADMIN\fR in its effective capability set, or the "No New
3432Privileges" restriction enabled.
3433Because of this, enabling the Landlock feature will also cause Firejail to
3434enable the "No New Privileges" restriction, regardless of the profile or the
3435\fB\-\-no\-new\-privs\fR command line option.
3436.PP
3437- Access to the /proc directory is managed through the \fB\-\-landlock.proc\fR
3438command line option.
3439.PP
3440- Access to the /etc directory is automatically allowed.
3441To override this, use the \fB\-\-writable\-etc\fR command line option.
3442You can also use the \fB\-\-private\-etc\fR option to restrict access to the
3443/etc directory.
3444.RE
3445.PP
3446To enable Landlock self-restriction on top of your current Firejail security
3447features, pass \fB\-\-landlock\fR flag to Firejail command line.
3448You can also use \fB\-\-landlock.read\fR, \fB\-\-landlock.write\fR,
3449\fB\-\-landlock.special\fR and \fB\-\-landlock.execute\fR options together with
3450\fB\-\-landlock\fR or instead of it.
3451Example:
3452.PP
3453$ firejail \-\-landlock \-\-landlock.read=/media \-\-landlock.proc=ro mc
3454#endif
3368.SH DESKTOP INTEGRATION 3455.SH DESKTOP INTEGRATION
3369A symbolic link to /usr/bin/firejail under the name of a program, will start the program in Firejail sandbox. 3456A symbolic link to /usr/bin/firejail under the name of a program, will start the program in Firejail sandbox.
3370The symbolic link should be placed in the first $PATH position. On most systems, a good place 3457The symbolic link should be placed in the first $PATH position. On most systems, a good place
diff --git a/src/zsh_completion/_firejail.in b/src/zsh_completion/_firejail.in
index 7e87bb991..89cb1b84c 100644
--- a/src/zsh_completion/_firejail.in
+++ b/src/zsh_completion/_firejail.in
@@ -106,6 +106,11 @@ _firejail_args=(
106 '--keep-fd[inherit open file descriptors to sandbox]: :' 106 '--keep-fd[inherit open file descriptors to sandbox]: :'
107 '--keep-shell-rc[do not copy shell rc files from /etc/skel]' 107 '--keep-shell-rc[do not copy shell rc files from /etc/skel]'
108 '--keep-var-tmp[/var/tmp directory is untouched]' 108 '--keep-var-tmp[/var/tmp directory is untouched]'
109 '--landlock.proc=-[add an access rule for /proc to the Landlock ruleset]: :(no ro rw)'
110 '--landlock.read=-[add a read access rule for the path to the Landlock ruleset]: :_files'
111 '--landlock.write=-[add a write access rule for the path to the Landlock ruleset]: :_files'
112 '--landlock.special=-[add an access rule for the path to the Landlock ruleset for creating block/char devices, named pipes and sockets]: :_files'
113 '--landlock.execute=-[add an execute access rule for the path to the Landlock ruleset]: :_files'
109 '--machine-id[spoof /etc/machine-id with a random id]' 114 '--machine-id[spoof /etc/machine-id with a random id]'
110 '--memory-deny-write-execute[seccomp filter to block attempts to create memory mappings that are both writable and executable]' 115 '--memory-deny-write-execute[seccomp filter to block attempts to create memory mappings that are both writable and executable]'
111 '*--mkdir=-[create a directory]:' 116 '*--mkdir=-[create a directory]:'