From 16fe3b976a5c0d42817c4d8ed886efbc0759922f Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 28 Sep 2012 16:53:51 +0000 Subject: -do not close stdin/stdout for standard system progs --- src/dns/gnunet-helper-dns.c | 48 ++++++++++++++++++++++++++++++++++++++++++++- src/pt/test_gns_vpn.c | 48 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 88 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/dns/gnunet-helper-dns.c b/src/dns/gnunet-helper-dns.c index 1fb1dcfbb..c230ec544 100644 --- a/src/dns/gnunet-helper-dns.c +++ b/src/dns/gnunet-helper-dns.c @@ -154,6 +154,33 @@ signal_handler (int signal) } +/** + * Open '/dev/null' and make the result the given + * file descriptor. + * + * @param target_fd desired FD to point to /dev/null + * @param flags open flags (O_RDONLY, O_WRONLY) + */ +static void +open_dev_null (int target_fd, + int flags) +{ + int fd; + + fd = open ("/dev/null", flags); + if (-1 == fd) + abort (); + if (fd == target_fd) + return; + if (-1 == dup2 (fd, target_fd)) + { + (void) close (fd); + abort (); + } + (void) close (fd); +} + + /** * Run the given command and wait for it to complete. * @@ -183,7 +210,9 @@ fork_and_exec (const char *file, /* close stdin/stdout to not cause interference with the helper's main protocol! */ (void) close (0); + open_dev_null (0, O_RDONLY); (void) close (1); + open_dev_null (1, O_WRONLY); (void) execv (file, cmd); /* can only get here on error */ fprintf (stderr, @@ -683,6 +712,7 @@ PROCESS_BUFFER: * 25-39 failed to drop privs and then failed to undo some changes to routing table * 40 failed to regain privs * 41-55 failed to regain prisv and then failed to undo some changes to routing table + * 254 insufficient priviledges * 255 failed to handle kill signal properly */ int @@ -692,6 +722,7 @@ main (int argc, char *const*argv) char dev[IFNAMSIZ]; char mygid[32]; int fd_tun; + uid_t uid; if (6 != argc) { @@ -699,6 +730,22 @@ main (int argc, char *const*argv) return 1; } + /* assert privs so we can modify the firewall rules! */ + uid = getuid (); +#ifdef HAVE_SETRESUID + if (0 != setresuid (uid, 0, 0)) + { + fprintf (stderr, "Failed to setresuid to root: %s\n", strerror (errno)); + return 254; + } +#else + if (0 != seteuid (0)) + { + fprintf (stderr, "Failed to seteuid back to root: %s\n", strerror (errno)); + return 254; + } +#endif + /* verify that the binaries were care about are executable */ if (0 == access ("/sbin/iptables", X_OK)) sbin_iptables = "/sbin/iptables"; @@ -899,7 +946,6 @@ main (int argc, char *const*argv) /* drop privs *except* for the saved UID; this is not perfect, but better than doing nothing */ - uid_t uid = getuid (); #ifdef HAVE_SETRESUID if (0 != setresuid (uid, uid, 0)) { diff --git a/src/pt/test_gns_vpn.c b/src/pt/test_gns_vpn.c index 9789ce7d9..faff03cf3 100644 --- a/src/pt/test_gns_vpn.c +++ b/src/pt/test_gns_vpn.c @@ -239,6 +239,7 @@ curl_main () NULL); } + static void start_curl (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { @@ -261,12 +262,14 @@ start_curl (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) curl_main (); } + static void disco_ns (void* cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { GNUNET_NAMESTORE_disconnect (namestore); } + /** * Callback invoked from the namestore service once record is * created. @@ -354,6 +357,7 @@ mhd_main () NULL); } + static void run (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg, @@ -437,6 +441,33 @@ test_af (int af) } +/** + * Open '/dev/null' and make the result the given + * file descriptor. + * + * @param target_fd desired FD to point to /dev/null + * @param flags open flags (O_RDONLY, O_WRONLY) + */ +static void +open_dev_null (int target_fd, + int flags) +{ + int fd; + + fd = open ("/dev/null", flags); + if (-1 == fd) + abort (); + if (fd == target_fd) + return; + if (-1 == dup2 (fd, target_fd)) + { + (void) close (fd); + abort (); + } + (void) close (fd); +} + + /** * Run the given command and wait for it to complete. * @@ -466,7 +497,9 @@ fork_and_exec (const char *file, /* close stdin/stdout to not cause interference with the helper's main protocol! */ (void) close (0); + open_dev_null (0, O_RDONLY); (void) close (1); + open_dev_null (1, O_WRONLY); (void) execv (file, cmd); /* can only get here on error */ fprintf (stderr, @@ -515,7 +548,7 @@ main (int argc, char *const *argv) if (0 != fork_and_exec (sbin_iptables, iptables_args)) { fprintf (stderr, - "IPtables not available, Skipping.\n"); + "Failed to run `iptables -t mangle -L -v'. Skipping test.\n"); return 0; } @@ -529,12 +562,13 @@ main (int argc, char *const *argv) return 0; } - if ( (GNUNET_YES != - GNUNET_OS_check_helper_binary ("gnunet-helper-vpn")) || - (GNUNET_YES != - GNUNET_OS_check_helper_binary ("gnunet-helper-exit")) || - (GNUNET_YES != - GNUNET_OS_check_helper_binary ("gnunet-helper-dns"))) + if ( (0 != geteuid ()) && + ( (GNUNET_YES != + GNUNET_OS_check_helper_binary ("gnunet-helper-vpn")) || + (GNUNET_YES != + GNUNET_OS_check_helper_binary ("gnunet-helper-exit")) || + (GNUNET_YES != + GNUNET_OS_check_helper_binary ("gnunet-helper-dns"))) ) { fprintf (stderr, "WARNING: gnunet-helper-{exit,vpn,dns} binaries in $PATH are not SUID, refusing to run test (as it would have to fail).\n"); -- cgit v1.2.3