Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

landlock: move commands into profile and add landlock.enforce #6125

Merged
merged 4 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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