From 77a891838f0456944777830152171c23fb52a71a Mon Sep 17 00:00:00 2001 From: netblue30 Date: Wed, 15 Nov 2017 07:09:41 -0500 Subject: netfilter split, --netfilter.print, --netfilter6.print --- src/firejail/firejail.h | 4 +-- src/firejail/main.c | 12 +++++++ src/firejail/netfilter.c | 91 +++++++++++++++++++++++++++++++++++++++++------- src/firejail/usage.c | 6 ++-- src/firejail/util.c | 43 ----------------------- src/man/firejail.txt | 52 +++++++++++++++++++-------- 6 files changed, 133 insertions(+), 75 deletions(-) (limited to 'src') diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index ab3c13598..f7bebe1b6 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -516,7 +516,6 @@ void create_empty_dir_as_root(const char *dir, mode_t mode); void create_empty_file_as_root(const char *dir, mode_t mode); int set_perms(const char *fname, uid_t uid, gid_t gid, mode_t mode); void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid); -char *read_text_file_or_exit(const char *fname); unsigned extract_timeout(const char *str); // fs_var.c @@ -607,6 +606,7 @@ void check_output(int argc, char **argv); void check_netfilter_file(const char *fname); void netfilter(const char *fname); void netfilter6(const char *fname); +void netfilter_print(pid_t pid, int ipv6); // netns.c void check_netns(const char *nsname); @@ -766,7 +766,7 @@ void build_appimage_cmdline(char **command_line, char **window_title, int argc, // sbox.c // programs #define PATH_FNET (LIBDIR "/firejail/fnet") -#define PATH_FNETFILTER (LIBDIR "/firejail/fnetfilter#define PATH_FNET (LIBDIR "/firejail/fnet") +#define PATH_FNETFILTER (LIBDIR "/firejail/fnetfilter") #define PATH_FIREMON (PREFIX "/bin/firemon") #define PATH_FIREJAIL (PREFIX "/bin/firejail") #define PATH_FSECCOMP (LIBDIR "/firejail/fseccomp") diff --git a/src/firejail/main.c b/src/firejail/main.c index c8b347b5f..d6b0a230e 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -429,6 +429,18 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { exit_err_feature("networking"); exit(0); } + else if (strncmp(argv[i], "--netfilter.print=", 18) == 0) { + // extract pid or sandbox name + pid_t pid = read_pid(argv[i] + 18); + netfilter_print(pid, 0); + exit(0); + } + else if (strncmp(argv[i], "--netfilter6.print=", 19) == 0) { + // extract pid or sandbox name + pid_t pid = read_pid(argv[i] + 19); + netfilter_print(pid, 1); + exit(0); + } #endif //************************************* // independent commands - the program will exit! diff --git a/src/firejail/netfilter.c b/src/firejail/netfilter.c index 517d0462f..e1d0edd01 100644 --- a/src/firejail/netfilter.c +++ b/src/firejail/netfilter.c @@ -63,6 +63,9 @@ void netfilter(const char *fname) { return; } + if (arg_debug) + printf("Installing firewall\n"); + // create an empty user-owned SBOX_STDIN_FILE create_empty_file_as_root(SBOX_STDIN_FILE, 0644); if (set_perms(SBOX_STDIN_FILE, getuid(), getgid(), 0644)) @@ -106,19 +109,15 @@ void netfilter6(const char *fname) { return; } - // create the filter file - char *filter = read_text_file_or_exit(fname); - FILE *fp = fopen(SBOX_STDIN_FILE, "w"); - if (!fp) { - fprintf(stderr, "Error: cannot open %s\n", SBOX_STDIN_FILE); - exit(1); - } - fprintf(fp, "%s\n", filter); - fclose(fp); - - // push filter if (arg_debug) - printf("Installing network filter:\n%s\n", filter); + printf("Installing IPv6 firewall\n"); + + // create an empty user-owned SBOX_STDIN_FILE + create_empty_file_as_root(SBOX_STDIN_FILE, 0644); + if (set_perms(SBOX_STDIN_FILE, getuid(), getgid(), 0644)) + errExit("set_perms"); + + sbox_run(SBOX_USER| SBOX_CAPS_NONE | SBOX_SECCOMP, 3, PATH_FNETFILTER, fname, SBOX_STDIN_FILE); // first run of iptables on this platform installs a number of kernel modules such as ip_tables, x_tables, iptable_filter // we run this command with caps and seccomp disabled in order to allow the loading of these modules @@ -129,6 +128,72 @@ void netfilter6(const char *fname) { if (arg_debug) sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, ip6tables, "-vL"); - free(filter); return; } + +void netfilter_print(pid_t pid, int ipv6) { + EUID_ASSERT(); + + // verify sandbox + EUID_ROOT(); + char *comm = pid_proc_comm(pid); + EUID_USER(); + if (!comm) { + fprintf(stderr, "Error: cannot find sandbox\n"); + exit(1); + } + + // check for firejail sandbox + if (strcmp(comm, "firejail") != 0) { + fprintf(stderr, "Error: cannot find sandbox\n"); + exit(1); + } + free(comm); + + // check network namespace + char *name; + if (asprintf(&name, "/run/firejail/network/%d-netmap", pid) == -1) + errExit("asprintf"); + struct stat s; + if (stat(name, &s) == -1) { + fprintf(stderr, "Error: the sandbox doesn't use a new network namespace\n"); + exit(1); + } + + // join the network namespace + pid_t child; + if (find_child(pid, &child) == -1) { + fprintf(stderr, "Error: cannot join the network namespace\n"); + exit(1); + } + + EUID_ROOT(); + if (join_namespace(child, "net")) { + fprintf(stderr, "Error: cannot join the network namespace\n"); + exit(1); + } + + // find iptables executable + char *iptables = NULL; + char *iptables_restore = NULL; + if (ipv6) { + if (stat("/sbin/ip6tables", &s) == 0) + iptables = "/sbin/ip6tables"; + else if (stat("/usr/sbin/ip6tables", &s) == 0) + iptables = "/usr/sbin/ip6tables"; + } + else { + if (stat("/sbin/iptables", &s) == 0) + iptables = "/sbin/iptables"; + else if (stat("/usr/sbin/iptables", &s) == 0) + iptables = "/usr/sbin/iptables"; + } + + if (iptables == NULL) { + fprintf(stderr, "Error: iptables command not found\n"); + exit(1); + } + + sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, iptables, "-vL"); +} + diff --git a/src/firejail/usage.c b/src/firejail/usage.c index 38de99471..f1581e847 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c @@ -122,8 +122,10 @@ void usage(void) { printf(" --net=ethernet_interface - enable network namespaces and connect to this\n"); printf("\tEthernet interface.\n"); printf(" --net=none - enable a new, unconnected network namespace.\n"); - printf(" --netfilter[=filename] - enable the default client network filter.\n"); - printf(" --netfilter6=filename - enable the IPv6 network filter.\n"); + printf(" --netfilter[=filename] - enable firewall.\n"); + printf(" --netfilter.print=name|pid - print the firewall.\n"); + printf(" --netfilter6=filename - enable IPv6 firewall.\n"); + printf(" --netfilter6.print=name|pid - print the IPv6 firewall.\n"); printf(" --netns=name - Run the program in a named, persistent network namespace.\n"); printf(" --netstats - monitor network statistics.\n"); #endif diff --git a/src/firejail/util.c b/src/firejail/util.c index cea2b76e3..fde180e49 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c @@ -908,49 +908,6 @@ void mkdir_attr(const char *fname, mode_t mode, uid_t uid, gid_t gid) { ASSERT_PERMS(fname, uid, gid, mode); } -char *read_text_file_or_exit(const char *fname) { - assert(fname); - - // open file - int fd = open(fname, O_RDONLY); - if (fd == -1) { - fprintf(stderr, "Error: cannot read %s\n", fname); - exit(1); - } - - int size = lseek(fd, 0, SEEK_END); - if (size == -1) - goto errexit; - if (lseek(fd, 0 , SEEK_SET) == -1) - goto errexit; - - // allocate memory - char *data = malloc(size + 1); // + '\0' - if (data == NULL) - goto errexit; - memset(data, 0, size + 1); - - // read file - int rd = 0; - while (rd < size) { - int rv = read(fd, (unsigned char *) data + rd, size - rd); - if (rv == -1) { - goto errexit; - } - rd += rv; - } - - // close file - close(fd); - return data; - -errexit: - close(fd); - fprintf(stderr, "Error: cannot read %s\n", fname); - exit(1); -} - - unsigned extract_timeout(const char *str) { unsigned s; unsigned m; diff --git a/src/man/firejail.txt b/src/man/firejail.txt index e0eb723bc..bf27c07ad 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt @@ -858,10 +858,13 @@ be created and configured using "ip netns". .TP \fB\-\-netfilter -Enable a default client network filter in the new network namespace. -New network namespaces are created using \-\-net option. If a new network namespaces is not created, -\-\-netfilter option does nothing. -The default filter is as follows: +Enable a default firewall if a new network namespace is created inside the sandbox. +This option has no effect for sandboxes using the system network namespace. +.br + +.br +The default firewall is optimized for regular desktop applications. No incoming +connections are accepted: .br .br @@ -904,19 +907,18 @@ Example: $ firejail \-\-net=eth0 \-\-netfilter firefox .TP \fB\-\-netfilter=filename -Enable the network filter specified by filename in the new network namespace. The filter file format -is the format of iptables-save and iptable-restore commands. -New network namespaces are created using \-\-net option. If a new network namespaces is not created, -\-\-netfilter option does nothing. +Enable the firewall specified by filename if a new network namespace is created inside the sandbox. +This option has no effect for sandboxes using the system network namespace. .br .br -The following filters are available in /etc/firejail directory: +Please use the regular iptables-save/iptables-restore format for the filter file. The following +examples are available in /etc/firejail directory: .br .br .B webserver.net -is a webserver filter that allows access only to TCP ports 80 and 443. +is a webserver firewall that allows access only to TCP ports 80 and 443. Example: .br @@ -928,19 +930,39 @@ $ firejail --netfilter=/etc/firejail/webserver.net --net=eth0 \\ .br .B nolocal.net -is a client filter that disable access to local network. Example: +is a desktop client firewall that disable access to local network. Example: .br .br $ firejail --netfilter=/etc/firejail/nolocal.net \\ .br --net=eth0 firefox +.TP +\fB\-\-netfilter.print=name|pid +Print the firewall installed in the sandbox specified by name or PID. Example: +.br + +.br +$ firejail --net=browser --net=eth0 --netfilter firefox & +.br +$ firejail --netfilter.print=browser + .TP \fB\-\-netfilter6=filename -Enable the IPv6 network filter specified by filename in the new network namespace. The filter file format -is the format of ip6tables-save and ip6table-restore commands. -New network namespaces are created using \-\-net option. If a new network namespaces is not created, -\-\-netfilter6 option does nothing. +Enable the IPv6 firewall specified by filename if a new network namespace is created inside the sandbox. +This option has no effect for sandboxes using the system network namespace. +Please use the regular iptables-save/iptables-restore format for the filter file. + +.TP +\fB\-\-netfilter6.print=name|pid +Print the IPv6 firewall installed in the sandbox specified by name or PID. Example: +.br + +.br +$ firejail --net=browser --net=eth0 --netfilter firefox & +.br +$ firejail --netfilter6.print=browser + .TP \fB\-\-netstats Monitor network namespace statistics, see \fBMONITORING\fR section for more details. -- cgit v1.2.3-54-g00ecf