Removing blacklisted files from top level /etc directory if the filse were blacklisted

This commit is contained in:
netblue30 2021-07-14 11:28:58 -04:00
parent 110a74f094
commit ba9c9699e7
5 changed files with 143 additions and 105 deletions

View file

@ -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);

View file

@ -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) {

View file

@ -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");
}

View file

@ -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

View file

@ -1043,7 +1043,7 @@ int sandbox(void* sandbox_arg) {
//****************************
// set dns
//****************************
fs_resolvconf();
fs_rebuild_etc();
//****************************
// start dhcp client