diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 887c2089997..07de442a26d 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -958,14 +958,15 @@ void oom_set(const char *oom_string); // landlock.c #ifdef HAVE_LANDLOCK -int landlock_create_ruleset(struct landlock_ruleset_attr *rsattr,size_t size,__u32 flags); -int landlock_add_rule(int fd,enum landlock_rule_type t,void *attr,__u32 flags); -int landlock_restrict_self(int fd,__u32 flags); -int create_full_ruleset(); -int add_read_access_rule_by_path(int rset_fd,char *allowed_path); -int add_write_access_rule_by_path(int rset_fd,char *allowed_path); -int add_create_special_rule_by_path(int rset_fd,char *allowed_path); -int add_execute_rule_by_path(int rset_fd,char *allowed_path); +int ll_create_ruleset(struct landlock_ruleset_attr *rsattr,size_t size,__u32 flags); +int ll_add_rule(int fd,enum landlock_rule_type t,void *attr,__u32 flags); +int ll_restrict_self(int fd,__u32 flags); +int ll_create_full_ruleset(); +int ll_add_read_access_rule_by_path(int rset_fd,char *allowed_path); +int ll_add_write_access_rule_by_path(int rset_fd,char *allowed_path); +int ll_add_create_special_rule_by_path(int rset_fd,char *allowed_path); +int ll_add_execute_rule_by_path(int rset_fd,char *allowed_path); +void ll_basic_system(void); #endif #endif diff --git a/src/firejail/landlock.c b/src/firejail/landlock.c index e6128e2a28c..09343fbd0da 100644 --- a/src/firejail/landlock.c +++ b/src/firejail/landlock.c @@ -19,11 +19,7 @@ */ #ifdef HAVE_LANDLOCK -#define _GNU_SOURCE -#include -#include -#include -#include +#include "firejail.h" #include #include #include @@ -31,15 +27,15 @@ #include #include -int landlock_create_ruleset(struct landlock_ruleset_attr *rsattr,size_t size,__u32 flags) { +int ll_create_ruleset(struct landlock_ruleset_attr *rsattr,size_t size,__u32 flags) { return syscall(__NR_landlock_create_ruleset,rsattr,size,flags); } -int landlock_add_rule(int fd,enum landlock_rule_type t,void *attr,__u32 flags) { +int ll_add_rule(int fd,enum landlock_rule_type t,void *attr,__u32 flags) { return syscall(__NR_landlock_add_rule,fd,t,attr,flags); } -int landlock_restrict_self(int fd,__u32 flags) { +int ll_restrict_self(int fd,__u32 flags) { prctl(PR_SET_NO_NEW_PRIVS,1,0,0,0); int result = syscall(__NR_landlock_restrict_self,fd,flags); if (result!=0) return result; @@ -49,27 +45,27 @@ int landlock_restrict_self(int fd,__u32 flags) { } } -int create_full_ruleset() { +int ll_create_full_ruleset() { struct landlock_ruleset_attr attr; attr.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_READ_DIR | LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_REMOVE_FILE | LANDLOCK_ACCESS_FS_REMOVE_DIR | LANDLOCK_ACCESS_FS_MAKE_CHAR | LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_MAKE_SOCK | LANDLOCK_ACCESS_FS_MAKE_FIFO | LANDLOCK_ACCESS_FS_MAKE_BLOCK | LANDLOCK_ACCESS_FS_MAKE_SYM | LANDLOCK_ACCESS_FS_EXECUTE; - return landlock_create_ruleset(&attr,sizeof(attr),0); + return ll_create_ruleset(&attr,sizeof(attr),0); } -int add_read_access_rule_by_path(int rset_fd,char *allowed_path) { +int ll_add_read_access_rule_by_path(int rset_fd,char *allowed_path) { int result; int allowed_fd = open(allowed_path,O_PATH | O_CLOEXEC); struct landlock_path_beneath_attr target; target.parent_fd = allowed_fd; target.allowed_access = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_READ_DIR; - result = landlock_add_rule(rset_fd,LANDLOCK_RULE_PATH_BENEATH,&target,0); + result = ll_add_rule(rset_fd,LANDLOCK_RULE_PATH_BENEATH,&target,0); close(allowed_fd); return result; } -int add_write_access_rule_by_path(int rset_fd,char *allowed_path) { +int ll_add_write_access_rule_by_path(int rset_fd,char *allowed_path) { int result; int allowed_fd = open(allowed_path,O_PATH | O_CLOEXEC); struct landlock_path_beneath_attr target; @@ -77,30 +73,65 @@ int add_write_access_rule_by_path(int rset_fd,char *allowed_path) { target.allowed_access = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_REMOVE_FILE | LANDLOCK_ACCESS_FS_REMOVE_DIR | LANDLOCK_ACCESS_FS_MAKE_CHAR | LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_MAKE_SYM; - result = landlock_add_rule(rset_fd,LANDLOCK_RULE_PATH_BENEATH,&target,0); + result = ll_add_rule(rset_fd,LANDLOCK_RULE_PATH_BENEATH,&target,0); close(allowed_fd); return result; } -int add_create_special_rule_by_path(int rset_fd,char *allowed_path) { +int ll_add_create_special_rule_by_path(int rset_fd,char *allowed_path) { int result; int allowed_fd = open(allowed_path,O_PATH | O_CLOEXEC); struct landlock_path_beneath_attr target; target.parent_fd = allowed_fd; target.allowed_access = LANDLOCK_ACCESS_FS_MAKE_SOCK | LANDLOCK_ACCESS_FS_MAKE_FIFO | LANDLOCK_ACCESS_FS_MAKE_BLOCK; - result = landlock_add_rule(rset_fd,LANDLOCK_RULE_PATH_BENEATH,&target,0); + result = ll_add_rule(rset_fd,LANDLOCK_RULE_PATH_BENEATH,&target,0); close(allowed_fd); return result; } -int add_execute_rule_by_path(int rset_fd,char *allowed_path) { +int ll_add_execute_rule_by_path(int rset_fd,char *allowed_path) { int result; int allowed_fd = open(allowed_path,O_PATH | O_CLOEXEC); struct landlock_path_beneath_attr target; target.parent_fd = allowed_fd; target.allowed_access = LANDLOCK_ACCESS_FS_EXECUTE; - result = landlock_add_rule(rset_fd,LANDLOCK_RULE_PATH_BENEATH,&target,0); + result = ll_add_rule(rset_fd,LANDLOCK_RULE_PATH_BENEATH,&target,0); close(allowed_fd); return result; } + +void ll_basic_system(void) { + if (arg_landlock == -1) + arg_landlock = ll_create_full_ruleset(); + + const char *home_dir = env_get("HOME"); + int home_fd = open(home_dir,O_PATH | O_CLOEXEC); + struct landlock_path_beneath_attr target; + target.parent_fd = home_fd; + target.allowed_access = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_READ_DIR | + LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_REMOVE_FILE | + LANDLOCK_ACCESS_FS_REMOVE_DIR | LANDLOCK_ACCESS_FS_MAKE_CHAR | + LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_MAKE_REG | + LANDLOCK_ACCESS_FS_MAKE_SYM; + if (ll_add_rule(arg_landlock,LANDLOCK_RULE_PATH_BENEATH,&target,0)) { + fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); + } + close(home_fd); + + if (ll_add_read_access_rule_by_path(arg_landlock, "/bin/") || + ll_add_execute_rule_by_path(arg_landlock, "/bin/") || + ll_add_read_access_rule_by_path(arg_landlock, "/dev/") || + ll_add_write_access_rule_by_path(arg_landlock, "/dev/") || +// ll_add_execute_rule_by_path(arg_landlock, "/dev/") || + ll_add_read_access_rule_by_path(arg_landlock, "/etc/") || + ll_add_read_access_rule_by_path(arg_landlock, "/lib/") || + ll_add_execute_rule_by_path(arg_landlock, "/lib/") || + ll_add_read_access_rule_by_path(arg_landlock, "/opt/") || + ll_add_execute_rule_by_path(arg_landlock, "/opt/") || + ll_add_read_access_rule_by_path(arg_landlock, "/usr/") || + ll_add_execute_rule_by_path(arg_landlock, "/usr/") || + ll_add_read_access_rule_by_path(arg_landlock, "/var/")) + fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); +} + #endif diff --git a/src/firejail/main.c b/src/firejail/main.c index 20d193a356c..9d96dbbc321 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -167,7 +167,7 @@ int just_run_the_shell = 0; int arg_netlock = 0; int arg_restrict_namespaces = 0; int arg_landlock = -1; -int arg_landlock_proc = 0; +int arg_landlock_proc = 2; // 0 - no access; 1 -read-only; 2 - read-write int parent_to_child_fds[2]; int child_to_parent_fds[2]; @@ -1503,83 +1503,34 @@ int main(int argc, char **argv, char **envp) { exit_err_feature("seccomp"); } #ifdef HAVE_LANDLOCK - else if (strcmp(argv[i], "--landlock") == 0) { - if (arg_landlock == -1) arg_landlock = create_full_ruleset(); - - const char *home_dir = env_get("HOME"); - int home_fd = open(home_dir,O_PATH | O_CLOEXEC); - struct landlock_path_beneath_attr target; - target.parent_fd = home_fd; - target.allowed_access = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_READ_DIR | - LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_REMOVE_FILE | - LANDLOCK_ACCESS_FS_REMOVE_DIR | LANDLOCK_ACCESS_FS_MAKE_CHAR | - LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_MAKE_REG | - LANDLOCK_ACCESS_FS_MAKE_SYM; - if (landlock_add_rule(arg_landlock,LANDLOCK_RULE_PATH_BENEATH,&target,0)) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - close(home_fd); - - if (add_read_access_rule_by_path(arg_landlock, "/bin/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_execute_rule_by_path(arg_landlock, "/bin/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_read_access_rule_by_path(arg_landlock, "/dev/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_read_access_rule_by_path(arg_landlock, "/etc/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_read_access_rule_by_path(arg_landlock, "/lib/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_execute_rule_by_path(arg_landlock, "/lib/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_read_access_rule_by_path(arg_landlock, "/opt/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_execute_rule_by_path(arg_landlock, "/opt/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_read_access_rule_by_path(arg_landlock, "/usr/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_execute_rule_by_path(arg_landlock, "/usr/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_read_access_rule_by_path(arg_landlock, "/var/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - } + else if (strcmp(argv[i], "--landlock") == 0) + ll_basic_system(); 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 if (strncmp(argv[i], "--landlock.read=", 16) == 0) { - if (arg_landlock == -1) arg_landlock = create_full_ruleset(); - if (add_read_access_rule_by_path(arg_landlock, argv[i]+16)) { + if (arg_landlock == -1) arg_landlock = ll_create_full_ruleset(); + if (ll_add_read_access_rule_by_path(arg_landlock, argv[i]+16)) { fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); } } else if (strncmp(argv[i], "--landlock.write=", 17) == 0) { - if (arg_landlock == -1) arg_landlock = create_full_ruleset(); - if (add_write_access_rule_by_path(arg_landlock, argv[i]+17)) { + if (arg_landlock == -1) arg_landlock = ll_create_full_ruleset(); + if (ll_add_write_access_rule_by_path(arg_landlock, argv[i]+17)) { fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); } } else if (strncmp(argv[i], "--landlock.special=", 17) == 0) { - if (arg_landlock == -1) arg_landlock = create_full_ruleset(); - if (add_create_special_rule_by_path(arg_landlock, argv[i]+17)) { + if (arg_landlock == -1) arg_landlock = ll_create_full_ruleset(); + if (ll_add_create_special_rule_by_path(arg_landlock, argv[i]+17)) { fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); } } else if (strncmp(argv[i], "--landlock.execute=", 19) == 0) { - if (arg_landlock == -1) arg_landlock = create_full_ruleset(); - if (add_execute_rule_by_path(arg_landlock, argv[i]+19)) { + if (arg_landlock == -1) arg_landlock = ll_create_full_ruleset(); + if (ll_add_execute_rule_by_path(arg_landlock, argv[i]+19)) { fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); } } diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 59d7da9d301..17548ad5893 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -1080,49 +1080,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { #ifdef HAVE_LANDLOCK // Landlock ruleset paths if (strcmp(ptr, "landlock") == 0) { - if (arg_landlock == -1) arg_landlock = create_full_ruleset(); - const char *home_dir = env_get("HOME"); - int home_fd = open(home_dir,O_PATH | O_CLOEXEC); - struct landlock_path_beneath_attr target; - target.parent_fd = home_fd; - target.allowed_access = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_READ_DIR | LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_REMOVE_FILE | LANDLOCK_ACCESS_FS_REMOVE_DIR | LANDLOCK_ACCESS_FS_MAKE_CHAR | LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_MAKE_SYM; - if (landlock_add_rule(arg_landlock,LANDLOCK_RULE_PATH_BENEATH,&target,0)) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - close(home_fd); - if (add_read_access_rule_by_path(arg_landlock, "/bin/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_execute_rule_by_path(arg_landlock, "/bin/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_read_access_rule_by_path(arg_landlock, "/dev/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_read_access_rule_by_path(arg_landlock, "/etc/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_read_access_rule_by_path(arg_landlock, "/lib/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_execute_rule_by_path(arg_landlock, "/lib/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_read_access_rule_by_path(arg_landlock, "/opt/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_execute_rule_by_path(arg_landlock, "/opt/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_read_access_rule_by_path(arg_landlock, "/usr/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_execute_rule_by_path(arg_landlock, "/usr/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } - if (add_read_access_rule_by_path(arg_landlock, "/var/")) { - fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); - } + ll_basic_system(); return 0; } if (strncmp(ptr, "landlock.proc ", 14) == 0) { @@ -1130,31 +1088,31 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { else if (strncmp(ptr+14, "ro", 2) == 0) arg_landlock_proc = 1; else if (strncmp(ptr+14, "rw", 2) == 0) arg_landlock_proc = 2; return 0; - } + } if (strncmp(ptr, "landlock.read ", 14) == 0) { - if (arg_landlock == -1) arg_landlock = create_full_ruleset(); - if (add_read_access_rule_by_path(arg_landlock, ptr+14)) { + if (arg_landlock == -1) arg_landlock = ll_create_full_ruleset(); + if (ll_add_read_access_rule_by_path(arg_landlock, ptr+14)) { fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); } return 0; } if (strncmp(ptr, "landlock.write ", 15) == 0) { - if (arg_landlock == -1) arg_landlock = create_full_ruleset(); - if (add_write_access_rule_by_path(arg_landlock, ptr+15)) { + if (arg_landlock == -1) arg_landlock = ll_create_full_ruleset(); + if (ll_add_write_access_rule_by_path(arg_landlock, ptr+15)) { fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); } return 0; } if (strncmp(ptr, "landlock.special ", 26) == 0) { - if (arg_landlock == -1) arg_landlock = create_full_ruleset(); - if (add_create_special_rule_by_path(arg_landlock, ptr+26)) { + if (arg_landlock == -1) arg_landlock = ll_create_full_ruleset(); + if (ll_add_create_special_rule_by_path(arg_landlock, ptr+26)) { fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); } return 0; } if (strncmp(ptr, "landlock.execute ", 17) == 0) { - if (arg_landlock == -1) arg_landlock = create_full_ruleset(); - if (add_execute_rule_by_path(arg_landlock, ptr+17)) { + if (arg_landlock == -1) arg_landlock = ll_create_full_ruleset(); + if (ll_add_execute_rule_by_path(arg_landlock, ptr+17)) { fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); } return 0; diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 97023ff5500..6917d9745eb 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c @@ -519,7 +519,7 @@ void start_application(int no_sandbox, int fd, char *set_sandbox_status) { #ifdef HAVE_LANDLOCK // set Landlock if (arg_landlock >= 0) { - if (landlock_restrict_self(arg_landlock,0)) { + if (ll_restrict_self(arg_landlock,0)) { fprintf(stderr,"An error has occured while enabling Landlock self-restriction. Exiting...\n"); exit(1); // it isn't safe to continue if Landlock self-restriction was enabled and the "landlock_restrict_self" syscall has failed } @@ -1017,9 +1017,9 @@ int sandbox(void* sandbox_arg) { #ifdef HAVE_LANDLOCK if (arg_landlock > -1) { if (arg_landlock_proc >= 1) - add_read_access_rule_by_path(arg_landlock, "/proc/"); + ll_add_read_access_rule_by_path(arg_landlock, "/proc/"); if (arg_landlock_proc == 2) - add_write_access_rule_by_path(arg_landlock, "/proc/"); + ll_add_write_access_rule_by_path(arg_landlock, "/proc/"); } #endif //****************************