mirror of
https://github.com/netblue30/firejail.git
synced 2026-05-15 22:01:33 -06:00
Removing blacklisted files from top level /etc directory if the filse were blacklisted
This commit is contained in:
parent
110a74f094
commit
ba9c9699e7
5 changed files with 143 additions and 105 deletions
|
|
@ -156,6 +156,8 @@ typedef struct config_t {
|
|||
|
||||
// filesystem
|
||||
ProfileEntry *profile;
|
||||
ProfileEntry *profile_rebuild_etc; // blacklist files in /etc directory used by fs_rebuild_etc()
|
||||
|
||||
#define MAX_PROFILE_IGNORE 32
|
||||
char *profile_ignore[MAX_PROFILE_IGNORE];
|
||||
char *chrootdir; // chroot directory
|
||||
|
|
@ -625,7 +627,6 @@ void fs_trace(void);
|
|||
|
||||
// fs_hostname.c
|
||||
void fs_hostname(const char *hostname);
|
||||
void fs_resolvconf(void);
|
||||
char *fs_check_hosts_file(const char *fname);
|
||||
void fs_store_hosts_file(void);
|
||||
void fs_mount_hosts_file(void);
|
||||
|
|
@ -668,6 +669,7 @@ void fs_machineid(void);
|
|||
void fs_private_dir_copy(const char *private_dir, const char *private_run_dir, const char *private_list);
|
||||
void fs_private_dir_mount(const char *private_dir, const char *private_run_dir);
|
||||
void fs_private_dir_list(const char *private_dir, const char *private_run_dir, const char *private_list);
|
||||
void fs_rebuild_etc(void);
|
||||
|
||||
// no_sandbox.c
|
||||
int check_namespace_virt(void);
|
||||
|
|
|
|||
|
|
@ -162,6 +162,19 @@ static void disable_file(OPERATION op, const char *filename) {
|
|||
fs_logger2("blacklist", fname);
|
||||
else
|
||||
fs_logger2("blacklist-nolog", fname);
|
||||
|
||||
// files in /etc will be reprocessed during /etc rebuild
|
||||
if (strncmp(fname, "/etc/", 5) == 0) {
|
||||
ProfileEntry *prf = malloc(sizeof(ProfileEntry));
|
||||
if (!prf)
|
||||
errExit("malloc");
|
||||
memset(prf, 0, sizeof(ProfileEntry));
|
||||
prf->data = strdup(fname);
|
||||
if (!prf->data)
|
||||
errExit("strdup");
|
||||
prf->next = cfg.profile_rebuild_etc;
|
||||
cfg.profile_rebuild_etc = prf;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (op == MOUNT_READONLY || op == MOUNT_RDWR || op == MOUNT_NOEXEC) {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
|
||||
// spoof /etc/machine_id
|
||||
void fs_machineid(void) {
|
||||
|
|
@ -250,3 +251,128 @@ void fs_private_dir_list(const char *private_dir, const char *private_run_dir, c
|
|||
fs_private_dir_mount(private_dir, private_run_dir);
|
||||
fmessage("Private %s installed in %0.2f ms\n", private_dir, timetrace_end());
|
||||
}
|
||||
|
||||
void fs_rebuild_etc(void) {
|
||||
int have_dhcp = 1;
|
||||
if (cfg.dns1 == NULL && !any_dhcp())
|
||||
have_dhcp = 0;
|
||||
|
||||
if (arg_debug)
|
||||
printf("rebuilding /etc directory\n");
|
||||
if (mkdir(RUN_DNS_ETC, 0755))
|
||||
errExit("mkdir");
|
||||
selinux_relabel_path(RUN_DNS_ETC, "/etc");
|
||||
fs_logger("tmpfs /etc");
|
||||
|
||||
DIR *dir = opendir("/etc");
|
||||
if (!dir)
|
||||
errExit("opendir");
|
||||
|
||||
struct stat s;
|
||||
struct dirent *entry;
|
||||
while ((entry = readdir(dir))) {
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||
continue;
|
||||
|
||||
// skip files in cfg.profile_rebuild_etc list
|
||||
// these files are already blacklisted
|
||||
{
|
||||
ProfileEntry *prf = cfg.profile_rebuild_etc;
|
||||
int found = 0;
|
||||
while (prf) {
|
||||
if (strcmp(entry->d_name, prf->data + 5) == 0) { // 5 is strlen("/etc/")
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
prf = prf->next;
|
||||
}
|
||||
if (found)
|
||||
continue;
|
||||
}
|
||||
|
||||
// for resolv.conf we might have to create a brand new file later
|
||||
if (have_dhcp &&
|
||||
(strcmp(entry->d_name, "resolv.conf") == 0 ||
|
||||
strcmp(entry->d_name, "resolv.conf.dhclient-new") == 0))
|
||||
continue;
|
||||
// printf("linking %s\n", entry->d_name);
|
||||
|
||||
char *src;
|
||||
if (asprintf(&src, "/etc/%s", entry->d_name) == -1)
|
||||
errExit("asprintf");
|
||||
if (stat(src, &s) != 0) {
|
||||
free(src);
|
||||
continue;
|
||||
}
|
||||
|
||||
char *dest;
|
||||
if (asprintf(&dest, "%s/%s", RUN_DNS_ETC, entry->d_name) == -1)
|
||||
errExit("asprintf");
|
||||
|
||||
int symlink_done = 0;
|
||||
if (is_link(src)) {
|
||||
char *rp =realpath(src, NULL);
|
||||
if (rp == NULL) {
|
||||
free(src);
|
||||
free(dest);
|
||||
continue;
|
||||
}
|
||||
if (symlink(rp, dest))
|
||||
errExit("symlink");
|
||||
else
|
||||
symlink_done = 1;
|
||||
}
|
||||
else if (S_ISDIR(s.st_mode))
|
||||
create_empty_dir_as_root(dest, s.st_mode);
|
||||
else
|
||||
create_empty_file_as_root(dest, s.st_mode);
|
||||
|
||||
// bind-mount src on top of dest
|
||||
if (!symlink_done) {
|
||||
if (mount(src, dest, NULL, MS_BIND|MS_REC, NULL) < 0)
|
||||
errExit("mount bind mirroring /etc");
|
||||
}
|
||||
fs_logger2("clone", src);
|
||||
|
||||
free(src);
|
||||
free(dest);
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
// mount bind our private etc directory on top of /etc
|
||||
if (arg_debug)
|
||||
printf("Mount-bind %s on top of /etc\n", RUN_DNS_ETC);
|
||||
if (mount(RUN_DNS_ETC, "/etc", NULL, MS_BIND|MS_REC, NULL) < 0)
|
||||
errExit("mount bind mirroring /etc");
|
||||
fs_logger("mount /etc");
|
||||
|
||||
if (have_dhcp == 0)
|
||||
return;
|
||||
|
||||
if (arg_debug)
|
||||
printf("Creating a new /etc/resolv.conf file\n");
|
||||
FILE *fp = fopen("/etc/resolv.conf", "wxe");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Error: cannot create /etc/resolv.conf file\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (cfg.dns1) {
|
||||
if (any_dhcp())
|
||||
fwarning("network setup uses DHCP, nameservers will likely be overwritten\n");
|
||||
fprintf(fp, "nameserver %s\n", cfg.dns1);
|
||||
}
|
||||
if (cfg.dns2)
|
||||
fprintf(fp, "nameserver %s\n", cfg.dns2);
|
||||
if (cfg.dns3)
|
||||
fprintf(fp, "nameserver %s\n", cfg.dns3);
|
||||
if (cfg.dns4)
|
||||
fprintf(fp, "nameserver %s\n", cfg.dns4);
|
||||
|
||||
// mode and owner
|
||||
SET_PERMS_STREAM(fp, 0, 0, 0644);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
fs_logger("create /etc/resolv.conf");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,109 +88,6 @@ errexit:
|
|||
exit(1);
|
||||
}
|
||||
|
||||
void fs_resolvconf(void) {
|
||||
if (cfg.dns1 == NULL && !any_dhcp())
|
||||
return;
|
||||
|
||||
if (arg_debug)
|
||||
printf("mirroring /etc directory\n");
|
||||
if (mkdir(RUN_DNS_ETC, 0755))
|
||||
errExit("mkdir");
|
||||
selinux_relabel_path(RUN_DNS_ETC, "/etc");
|
||||
fs_logger("tmpfs /etc");
|
||||
|
||||
DIR *dir = opendir("/etc");
|
||||
if (!dir)
|
||||
errExit("opendir");
|
||||
|
||||
struct stat s;
|
||||
struct dirent *entry;
|
||||
while ((entry = readdir(dir))) {
|
||||
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
|
||||
continue;
|
||||
// for resolv.conf we create a brand new file
|
||||
if (strcmp(entry->d_name, "resolv.conf") == 0 ||
|
||||
strcmp(entry->d_name, "resolv.conf.dhclient-new") == 0)
|
||||
continue;
|
||||
// printf("linking %s\n", entry->d_name);
|
||||
|
||||
char *src;
|
||||
if (asprintf(&src, "/etc/%s", entry->d_name) == -1)
|
||||
errExit("asprintf");
|
||||
if (stat(src, &s) != 0) {
|
||||
free(src);
|
||||
continue;
|
||||
}
|
||||
|
||||
char *dest;
|
||||
if (asprintf(&dest, "%s/%s", RUN_DNS_ETC, entry->d_name) == -1)
|
||||
errExit("asprintf");
|
||||
|
||||
int symlink_done = 0;
|
||||
if (is_link(src)) {
|
||||
char *rp =realpath(src, NULL);
|
||||
if (rp == NULL) {
|
||||
free(src);
|
||||
free(dest);
|
||||
continue;
|
||||
}
|
||||
if (symlink(rp, dest))
|
||||
errExit("symlink");
|
||||
else
|
||||
symlink_done = 1;
|
||||
}
|
||||
else if (S_ISDIR(s.st_mode))
|
||||
create_empty_dir_as_root(dest, s.st_mode);
|
||||
else
|
||||
create_empty_file_as_root(dest, s.st_mode);
|
||||
|
||||
// bind-mount src on top of dest
|
||||
if (!symlink_done) {
|
||||
if (mount(src, dest, NULL, MS_BIND|MS_REC, NULL) < 0)
|
||||
errExit("mount bind mirroring /etc");
|
||||
}
|
||||
fs_logger2("clone", src);
|
||||
|
||||
free(src);
|
||||
free(dest);
|
||||
}
|
||||
closedir(dir);
|
||||
|
||||
// mount bind our private etc directory on top of /etc
|
||||
if (arg_debug)
|
||||
printf("Mount-bind %s on top of /etc\n", RUN_DNS_ETC);
|
||||
if (mount(RUN_DNS_ETC, "/etc", NULL, MS_BIND|MS_REC, NULL) < 0)
|
||||
errExit("mount bind mirroring /etc");
|
||||
fs_logger("mount /etc");
|
||||
|
||||
if (arg_debug)
|
||||
printf("Creating a new /etc/resolv.conf file\n");
|
||||
FILE *fp = fopen("/etc/resolv.conf", "wxe");
|
||||
if (!fp) {
|
||||
fprintf(stderr, "Error: cannot create /etc/resolv.conf file\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (cfg.dns1) {
|
||||
if (any_dhcp())
|
||||
fwarning("network setup uses DHCP, nameservers will likely be overwritten\n");
|
||||
fprintf(fp, "nameserver %s\n", cfg.dns1);
|
||||
}
|
||||
if (cfg.dns2)
|
||||
fprintf(fp, "nameserver %s\n", cfg.dns2);
|
||||
if (cfg.dns3)
|
||||
fprintf(fp, "nameserver %s\n", cfg.dns3);
|
||||
if (cfg.dns4)
|
||||
fprintf(fp, "nameserver %s\n", cfg.dns4);
|
||||
|
||||
// mode and owner
|
||||
SET_PERMS_STREAM(fp, 0, 0, 0644);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
fs_logger("create /etc/resolv.conf");
|
||||
}
|
||||
|
||||
char *fs_check_hosts_file(const char *fname) {
|
||||
assert(fname);
|
||||
invalid_filename(fname, 0); // no globbing
|
||||
|
|
|
|||
|
|
@ -1043,7 +1043,7 @@ int sandbox(void* sandbox_arg) {
|
|||
//****************************
|
||||
// set dns
|
||||
//****************************
|
||||
fs_resolvconf();
|
||||
fs_rebuild_etc();
|
||||
|
||||
//****************************
|
||||
// start dhcp client
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue