Skip to content

Commit

Permalink
apply landlock rules in the sandbox thread before the application is …
Browse files Browse the repository at this point in the history
…started
  • Loading branch information
netblue30 committed Oct 26, 2023
1 parent d2d135f commit 203005d
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 66 deletions.
7 changes: 7 additions & 0 deletions src/firejail/firejail.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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];
Expand Down Expand Up @@ -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
118 changes: 77 additions & 41 deletions src/firejail/landlock.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,57 +34,43 @@ 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) {
if (rset_fd == -1)
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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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;
}
Expand All @@ -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/") ||
Expand All @@ -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
24 changes: 8 additions & 16 deletions src/firejail/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down
14 changes: 5 additions & 9 deletions src/firejail/profile.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 203005d

Please sign in to comment.