Skip to content

Commit

Permalink
Merge pull request netblue30#6125 from kmk3/landlock-enforce
Browse files Browse the repository at this point in the history
landlock: move commands into profile and add landlock.enforce
  • Loading branch information
netblue30 committed Dec 21, 2023
2 parents 46d70ca + 760f50f commit c245fec
Show file tree
Hide file tree
Showing 15 changed files with 91 additions and 153 deletions.
2 changes: 1 addition & 1 deletion contrib/syntax/lists/profile_commands_arg0.list
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ keep-config-pulse
keep-dev-shm
keep-shell-rc
keep-var-tmp
landlock
landlock.enforce
machine-id
memory-deny-write-execute
netfilter
Expand Down
1 change: 0 additions & 1 deletion contrib/syntax/lists/profile_commands_arg1.list
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ iprange
join-or-start
keep-fd
landlock.execute
landlock.proc
landlock.read
landlock.special
landlock.write
Expand Down
39 changes: 39 additions & 0 deletions etc/inc/landlock-common.inc
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# This file is overwritten during software install.
# Persistent customizations should go in a .local file.
include landlock-common.local

landlock.read / # whole system read
landlock.read /proc
landlock.special / # sockets etc.

# write access
landlock.write ${HOME}
landlock.write ${RUNUSER}
landlock.write /dev
landlock.write /proc
landlock.write /run/shm
landlock.write /tmp

# exec access
## misc
landlock.execute /opt
landlock.execute /run/firejail # appimage and various firejail features
## bin
landlock.execute /bin
landlock.execute /sbin
landlock.execute /usr/bin
landlock.execute /usr/sbin
landlock.execute /usr/games
landlock.execute /usr/local/bin
landlock.execute /usr/local/sbin
landlock.execute /usr/local/games
## lib
landlock.execute /lib
landlock.execute /lib32
landlock.execute /libx32
landlock.execute /lib64
landlock.execute /usr/lib
landlock.execute /usr/lib32
landlock.execute /usr/libx32
landlock.execute /usr/lib64
landlock.execute /usr/local/lib
2 changes: 2 additions & 0 deletions etc/profile-a-l/default.profile
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ include disable-programs.inc
#include whitelist-usr-share-common.inc
#include whitelist-var-common.inc

include landlock-common.inc

#apparmor
caps.drop all
#ipc-namespace
Expand Down
7 changes: 7 additions & 0 deletions etc/templates/profile.template
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,13 @@ include globals.local
#include whitelist-usr-share-common.inc
#include whitelist-var-common.inc

# Landlock commands
##landlock.read PATH
##landlock.write PATH
##landlock.special PATH
##landlock.execute PATH
#include landlock-common.inc

##allusers
#apparmor
#caps.drop all
Expand Down
2 changes: 1 addition & 1 deletion src/bash_completion/firejail.bash_completion.in
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ _firejail()
_filedir -d
return 0
;;
--landlock)
--landlock.enforce)
return 0
;;
--landlock.read)
Expand Down
4 changes: 1 addition & 3 deletions src/firejail/firejail.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,8 +293,7 @@ extern int arg_overlay; // overlay option
extern int arg_overlay_keep; // place overlay diff in a known directory
extern int arg_overlay_reuse; // allow the reuse of overlays

extern int arg_landlock; // add basic Landlock rules
extern int arg_landlock_proc; // 0 - no access; 1 -read-only; 2 - read-write
extern int arg_landlock_enforce; // enforce the Landlock ruleset

extern int arg_seccomp; // enable default seccomp filter
extern int arg_seccomp32; // enable default seccomp filter for 32 bit arch
Expand Down Expand Up @@ -973,7 +972,6 @@ int ll_read(const char *allowed_path);
int ll_write(const char *allowed_path);
int ll_special(const char *allowed_path);
int ll_exec(const char *allowed_path);
int ll_basic_system(void);
int ll_restrict(uint32_t flags);
void ll_add_profile(int type, const char *data);
#endif /* HAVE_LANDLOCK */
Expand Down
69 changes: 12 additions & 57 deletions src/firejail/landlock.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@ static int ll_create_full_ruleset(void) {
return ruleset_fd;
}

static int ll_fs(const char *allowed_path, const __u64 allowed_access,
const char *caller) {
static int _ll_fs(const char *allowed_path, const __u64 allowed_access,
const char *caller) {
if (!ll_is_supported())
return 0;

Expand Down Expand Up @@ -155,6 +155,16 @@ static int ll_fs(const char *allowed_path, const __u64 allowed_access,
return error;
}

// TODO: Add support for the ${PATH} macro.
static int ll_fs(const char *allowed_path, const __u64 allowed_access,
const char *caller) {
char *expanded_path = expand_macros(allowed_path);
int error = _ll_fs(expanded_path, allowed_access, caller);

free(expanded_path);
return error;
}

int ll_read(const char *allowed_path) {
__u64 allowed_access =
LANDLOCK_ACCESS_FS_READ_DIR |
Expand Down Expand Up @@ -192,58 +202,6 @@ int ll_exec(const char *allowed_path) {
return ll_fs(allowed_path, allowed_access, __func__);
}

int ll_basic_system(void) {
assert(cfg.homedir);

if (!ll_is_supported())
return 0;

if (ll_ruleset_fd == -1)
ll_ruleset_fd = ll_create_full_ruleset();

int error;
char *rundir;
if (asprintf(&rundir, "/run/user/%d", getuid()) == -1)
errExit("asprintf");

error =
ll_read("/") || // whole system read
ll_special("/") || // sockets etc.

ll_write("/tmp") || // write access
ll_write("/dev") ||
ll_write("/run/shm") ||
ll_write(cfg.homedir) ||
ll_write(rundir) ||

ll_exec("/opt") || // exec access
ll_exec("/bin") ||
ll_exec("/sbin") ||
ll_exec("/lib") ||
ll_exec("/lib32") ||
ll_exec("/libx32") ||
ll_exec("/lib64") ||
ll_exec("/usr/bin") ||
ll_exec("/usr/sbin") ||
ll_exec("/usr/games") ||
ll_exec("/usr/lib") ||
ll_exec("/usr/lib32") ||
ll_exec("/usr/libx32") ||
ll_exec("/usr/lib64") ||
ll_exec("/usr/local/bin") ||
ll_exec("/usr/local/sbin") ||
ll_exec("/usr/local/games") ||
ll_exec("/usr/local/lib") ||
ll_exec("/run/firejail"); // appimage and various firejail features

if (error) {
fprintf(stderr, "Error: %s: failed to set --landlock rules\n",
__func__);
}
free(rundir);
return error;
}

int ll_restrict(uint32_t flags) {
if (!ll_is_supported())
return 0;
Expand Down Expand Up @@ -293,9 +251,6 @@ void ll_add_profile(int type, const char *data) {
assert(type < LL_MAX);
assert(data);

if (!ll_is_supported())
return;

while (*data == ' ' || *data == '\t')
data++;

Expand Down
20 changes: 3 additions & 17 deletions src/firejail/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@ int arg_overlay = 0; // overlay option
int arg_overlay_keep = 0; // place overlay diff in a known directory
int arg_overlay_reuse = 0; // allow the reuse of overlays

int arg_landlock = 0; // add basic Landlock rules
int arg_landlock_proc = 2; // 0 - no access; 1 -read-only; 2 - read-write
int arg_landlock_enforce = 0; // enforce the Landlock ruleset

int arg_seccomp = 0; // enable default seccomp filter
int arg_seccomp32 = 0; // enable default seccomp filter for 32 bit arch
Expand Down Expand Up @@ -1504,21 +1503,8 @@ int main(int argc, char **argv, char **envp) {
exit_err_feature("seccomp");
}
#ifdef HAVE_LANDLOCK
else if (strcmp(argv[i], "--landlock") == 0)
arg_landlock = 1;
else if (strncmp(argv[i], "--landlock.proc=", 16) == 0) {
if (strncmp(argv[i] + 16, "no", 2) == 0)
arg_landlock_proc = 0;
else if (strncmp(argv[i] + 16, "ro", 2) == 0)
arg_landlock_proc = 1;
else if (strncmp(argv[i] + 16, "rw", 2) == 0)
arg_landlock_proc = 2;
else {
fprintf(stderr, "Error: invalid landlock.proc value: %s\n",
argv[i] + 16);
exit(1);
}
}
else if (strncmp(argv[i], "--landlock.enforce", 18) == 0)
arg_landlock_enforce = 1;
else if (strncmp(argv[i], "--landlock.read=", 16) == 0)
ll_add_profile(LL_READ, argv[i] + 16);
else if (strncmp(argv[i], "--landlock.write=", 17) == 0)
Expand Down
21 changes: 3 additions & 18 deletions src/firejail/profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -1074,24 +1074,9 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
}

#ifdef HAVE_LANDLOCK
// Landlock ruleset paths
if (strcmp(ptr, "landlock") == 0) {
arg_landlock = 1;
return 0;
}
if (strncmp(ptr, "landlock.proc ", 14) == 0) {
if (strncmp(ptr + 14, "no", 2) == 0)
arg_landlock_proc = 0;
else if (strncmp(ptr + 14, "ro", 2) == 0)
arg_landlock_proc = 1;
else if (strncmp(ptr + 14, "rw", 2) == 0)
arg_landlock_proc = 2;
else {
fprintf(stderr, "Error: invalid landlock.proc value: %s\n",
ptr + 14);
exit(1);
}
return 0;
if (strncmp(ptr, "landlock.enforce", 16) == 0) {
arg_landlock_enforce = 1;
return 0;
}
if (strncmp(ptr, "landlock.read ", 14) == 0) {
ll_add_profile(LL_READ, ptr + 14);
Expand Down
15 changes: 4 additions & 11 deletions src/firejail/sandbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -520,21 +520,14 @@ void start_application(int no_sandbox, int fd, char *set_sandbox_status) {
//****************************
// Configure Landlock
//****************************
if (arg_landlock)
ll_basic_system();

if (ll_get_fd() != -1) {
if (arg_landlock_proc >= 1)
ll_read("/proc/");
if (arg_landlock_proc == 2)
ll_write("/proc/");
}

if (ll_restrict(0)) {
if (arg_landlock_enforce && ll_restrict(0)) {
// It isn't safe to continue if Landlock self-restriction was
// enabled and the "landlock_restrict_self" syscall has failed.
fprintf(stderr, "Error: ll_restrict() failed, exiting...\n");
exit(1);
} else {
if (arg_debug)
fprintf(stderr, "Not enforcing Landlock\n");
}
#endif

Expand Down
3 changes: 1 addition & 2 deletions src/firejail/usage.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,7 @@ static const char *const usage_str =
" --keep-shell-rc - do not copy shell rc files from /etc/skel\n"
" --keep-var-tmp - /var/tmp directory is untouched.\n"
#ifdef HAVE_LANDLOCK
" --landlock - add basic rules to the Landlock ruleset.\n"
" --landlock.proc=no|ro|rw - add an access rule for /proc to the Landlock ruleset.\n"
" --landlock.enforce - enforce the Landlock ruleset.\n"
" --landlock.read=path - add a read access rule for the path to the Landlock ruleset.\n"
" --landlock.write=path - add a write access rule for the path to the Landlock ruleset.\n"
" --landlock.special=path - add an access rule for the path to the Landlock ruleset for creating block/char devices, named pipes and sockets.\n"
Expand Down
15 changes: 4 additions & 11 deletions src/man/firejail-profile.5.in
Original file line number Diff line number Diff line change
Expand Up @@ -509,17 +509,10 @@ Blacklist all Linux capabilities.
Whitelist given Linux capabilities.
#ifdef HAVE_LANDLOCK
.TP
\fBlandlock
Create a Landlock ruleset (if it doesn't already exist) and add basic access
rules to it.
.TP
\fBlandlock.proc no|ro|rw
Add an access rule for /proc directory (read-only if set to \fBro\fR and
read-write if set to \fBrw\fR).
The access rule for /proc is added after this directory is set up in the
sandbox.
Access rules for /proc set up with other Landlock-related profile options have
no effect.
\fBlandlock.enforce
Enforce the Landlock ruleset.
.PP
Without it, the other Landlock commands have no effect.
.TP
\fBlandlock.read path
Create a Landlock ruleset (if it doesn't already exist) and add a read access
Expand Down
Loading

0 comments on commit c245fec

Please sign in to comment.