diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 7a03d470418..83098c11391 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -153,6 +153,11 @@ typedef struct profile_entry_t { } ProfileEntry; +typedef struct landlock_entry_t { + struct landlock_entry_t *next; + char *data; +} LandlockEntry; + typedef struct config_t { // user data char *username; @@ -162,6 +167,7 @@ typedef struct config_t { // filesystem ProfileEntry *profile; ProfileEntry *profile_rebuild_etc; // blacklist files in /etc directory used by fs_rebuild_etc() + LandlockEntry *lprofile; #define MAX_PROFILE_IGNORE 32 char *profile_ignore[MAX_PROFILE_IGNORE]; @@ -968,6 +974,7 @@ int ll_add_write_access_rule_by_path(char *allowed_path); int ll_add_create_special_rule_by_path(char *allowed_path); int ll_add_execute_rule_by_path(char *allowed_path); void ll_basic_system(void); +void ll_add_profile(const char *data); #endif #endif diff --git a/src/firejail/landlock.c b/src/firejail/landlock.c index e5b86644039..c45254fc371 100644 --- a/src/firejail/landlock.c +++ b/src/firejail/landlock.c @@ -34,45 +34,31 @@ int ll_get_fd(void) { } #ifndef landlock_create_ruleset -int ll_create_ruleset(struct landlock_ruleset_attr *rsattr,size_t size,__u32 flags) { - return syscall(__NR_landlock_create_ruleset,rsattr,size,flags); +int ll_create_ruleset(struct landlock_ruleset_attr *rsattr, size_t size, __u32 flags) { + return syscall(__NR_landlock_create_ruleset, rsattr, size, flags); } #endif #ifndef landlock_add_rule -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 ll_add_rule(int fd, enum landlock_rule_type t, void *attr, __u32 flags) { + return syscall(__NR_landlock_add_rule, fd, t, attr, flags); } #endif #ifndef landlock_restrict_self static inline int landlock_restrict_self(const int ruleset_fd, - const __u32 flags) -{ + const __u32 flags) { return syscall(__NR_landlock_restrict_self, ruleset_fd, flags); } #endif -int ll_restrict(__u32 flags) { - if (rset_fd == -1) - return 0; - - prctl(PR_SET_NO_NEW_PRIVS,1,0,0,0); - int result = landlock_restrict_self(rset_fd, flags); - if (result!=0) return result; - else { - close(rset_fd); - return 0; - } -} - 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 ll_create_ruleset(&attr,sizeof(attr),0); + 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 ll_create_ruleset(&attr, sizeof(attr), 0); } int ll_add_read_access_rule_by_path(char *allowed_path) { @@ -80,11 +66,11 @@ int ll_add_read_access_rule_by_path(char *allowed_path) { rset_fd = ll_create_full_ruleset(); int result; - int allowed_fd = open(allowed_path,O_PATH | O_CLOEXEC); + 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 = ll_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; } @@ -94,13 +80,13 @@ int ll_add_write_access_rule_by_path(char *allowed_path) { rset_fd = ll_create_full_ruleset(); int result; - int allowed_fd = open(allowed_path,O_PATH | O_CLOEXEC); + 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_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 = ll_add_rule(rset_fd,LANDLOCK_RULE_PATH_BENEATH,&target,0); + LANDLOCK_ACCESS_FS_MAKE_CHAR | LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_MAKE_REG | + LANDLOCK_ACCESS_FS_MAKE_SYM; + result = ll_add_rule(rset_fd, LANDLOCK_RULE_PATH_BENEATH, &target, 0); close(allowed_fd); return result; } @@ -110,11 +96,11 @@ int ll_add_create_special_rule_by_path(char *allowed_path) { rset_fd = ll_create_full_ruleset(); int result; - int allowed_fd = open(allowed_path,O_PATH | O_CLOEXEC); + 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 = ll_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; } @@ -124,11 +110,11 @@ int ll_add_execute_rule_by_path(char *allowed_path) { rset_fd = ll_create_full_ruleset(); int result; - int allowed_fd = open(allowed_path,O_PATH | O_CLOEXEC); + 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 = ll_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; } @@ -138,16 +124,16 @@ void ll_basic_system(void) { rset_fd = ll_create_full_ruleset(); assert(cfg.homedir); - int home_fd = open(cfg.homedir,O_PATH | O_CLOEXEC); + int home_fd = open(cfg.homedir, 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(rset_fd, LANDLOCK_RULE_PATH_BENEATH,&target,0)) - fprintf(stderr,"Error: cannot set the basic Landlock filesystem\n"); + 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(rset_fd, LANDLOCK_RULE_PATH_BENEATH, &target, 0)) + fprintf(stderr, "Error: cannot set the basic Landlock filesystem\n"); close(home_fd); if (ll_add_read_access_rule_by_path("/bin/") || @@ -162,7 +148,57 @@ void ll_basic_system(void) { ll_add_read_access_rule_by_path("/usr/") || ll_add_execute_rule_by_path("/usr/") || ll_add_read_access_rule_by_path("/var/")) - fprintf(stderr,"Error: cannot set the basic Landlock filesystem\n"); + fprintf(stderr, "Error: cannot set the basic Landlock filesystem\n"); } +int ll_restrict(__u32 flags) { + LandlockEntry *ptr = cfg.lprofile; + while (ptr) { + if (strncmp(ptr->data, "landlock.read", 13) == 0) { + if (ll_add_read_access_rule_by_path(ptr->data + 14)) + fprintf(stderr,"Error: cannot add Landlock rule\n"); + } + else if (strncmp(ptr->data, "landlock.write", 14) == 0) { + if (ll_add_write_access_rule_by_path(ptr->data + 15)) + fprintf(stderr,"Error: cannot add Landlock rule\n"); + } + else if (strncmp(ptr->data, "landlock.special", 16) == 0) { + if (ll_add_create_special_rule_by_path(ptr->data + 17)) + fprintf(stderr,"Error: cannot add Landlock rule\n"); + } + else if (strncmp(ptr->data, "landlock.execute", 16) == 0) { + if (ll_add_execute_rule_by_path(ptr->data + 17)) + fprintf(stderr,"Error: cannot add Landlock rule\n"); + } + ptr = ptr->next; + } + + + if (rset_fd == -1) + return 0; + + prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); + int result = landlock_restrict_self(rset_fd, flags); + if (result != 0) return result; + else { + close(rset_fd); + return 0; + } +} + +void ll_add_profile(const char *data) { + LandlockEntry *ptr = malloc(sizeof(LandlockEntry)); + if (!ptr) + errExit("malloc"); + memset(ptr, 0, sizeof(LandlockEntry)); + ptr->data = strdup(data); + if (!ptr->data) + errExit("strdup"); + ptr->next = cfg.lprofile; + cfg.lprofile=ptr; +} + + +#if 0 +#endif #endif diff --git a/src/firejail/main.c b/src/firejail/main.c index 3f72725c3f3..f5eb06f56cb 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -1511,22 +1511,14 @@ int main(int argc, char **argv, char **envp) { 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 (ll_add_read_access_rule_by_path(argv[i]+16)) - fprintf(stderr,"Error: cannot add Landlock rule\n"); - } - else if (strncmp(argv[i], "--landlock.write=", 17) == 0) { - if (ll_add_write_access_rule_by_path(argv[i]+17)) - fprintf(stderr,"Error: cannot add Landlock rule\n"); - } - else if (strncmp(argv[i], "--landlock.special=", 17) == 0) { - if (ll_add_create_special_rule_by_path(argv[i]+17)) - fprintf(stderr,"Error: cannot add Landlock rule\n"); - } - else if (strncmp(argv[i], "--landlock.execute=", 19) == 0) { - if (ll_add_execute_rule_by_path(argv[i]+19)) - fprintf(stderr,"Error: cannot add Landlock rule\n"); - } + else if (strncmp(argv[i], "--landlock.read=", 16) == 0) + ll_add_profile(argv[i] + 2); + else if (strncmp(argv[i], "--landlock.write=", 17) == 0) + ll_add_profile(argv[i] + 2); + else if (strncmp(argv[i], "--landlock.special=", 17) == 0) + ll_add_profile(argv[i] + 2); + else if (strncmp(argv[i], "--landlock.execute=", 19) == 0) + ll_add_profile(argv[i] + 2); #endif else if (strcmp(argv[i], "--memory-deny-write-execute") == 0) { if (checkcfg(CFG_SECCOMP)) diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 170ae3e6209..f16ec2175d1 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -1090,23 +1090,19 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { return 0; } if (strncmp(ptr, "landlock.read ", 14) == 0) { - if (ll_add_read_access_rule_by_path(ptr+14)) - fprintf(stderr,"Error: cannot add Landlock rule, file %s, line %d\n", fname, lineno); + ll_add_profile(ptr); return 0; } if (strncmp(ptr, "landlock.write ", 15) == 0) { - if (ll_add_write_access_rule_by_path(ptr+15)) - fprintf(stderr,"Error: cannot add Landlock rule, file %s, line %d\n", fname, lineno); + ll_add_profile(ptr); return 0; } - if (strncmp(ptr, "landlock.special ", 26) == 0) { - if (ll_add_create_special_rule_by_path(ptr+26)) - fprintf(stderr,"Error: cannot add Landlock rule, file %s, line %d\n", fname, lineno); + if (strncmp(ptr, "landlock.special ", 17) == 0) { + ll_add_profile(ptr); return 0; } if (strncmp(ptr, "landlock.execute ", 17) == 0) { - if (ll_add_execute_rule_by_path(ptr+17)) - fprintf(stderr,"Error: cannot add Landlock rule, file %s, line %d\n", fname, lineno); + ll_add_profile(ptr); return 0; } #endif