diff -urN iputils-s20101006.orig/arping.c iputils-s20101006/arping.c --- iputils-s20101006.orig/arping.c 2011-01-23 01:40:55.000000000 +0200 +++ iputils-s20101006/arping.c 2011-05-03 20:21:19.000000000 +0300 @@ -35,6 +35,8 @@ #include #include "SNAPSHOT.h" +#include "fixfds.h" +#include "droppriv.h" static void usage(void) __attribute__((noreturn)); @@ -346,16 +348,10 @@ { int socket_errno; int ch; - uid_t uid = getuid(); s = socket(PF_PACKET, SOCK_DGRAM, 0); socket_errno = errno; - if (setuid(uid)) { - perror("arping: setuid"); - exit(-1); - } - while ((ch = getopt(argc, argv, "h?bfDUAqc:w:s:I:V")) != EOF) { switch(ch) { case 'b': @@ -504,6 +500,10 @@ close(probe_fd); }; +#if 0 + drop_priv(); +#endif + ((struct sockaddr_ll *)&me)->sll_family = AF_PACKET; ((struct sockaddr_ll *)&me)->sll_ifindex = ifindex; ((struct sockaddr_ll *)&me)->sll_protocol = htons(ETH_P_ARP); @@ -530,6 +530,7 @@ #if 1 set_device_broadcast(device, ((struct sockaddr_ll *)&he)->sll_addr, ((struct sockaddr_ll *)&he)->sll_halen); + drop_priv(); #else memset(((struct sockaddr_ll *)&he)->sll_addr, -1, ((struct sockaddr_ll *)&he)->sll_halen); #endif diff -urN iputils-s20101006.orig/clockdiff.c iputils-s20101006/clockdiff.c --- iputils-s20101006.orig/clockdiff.c 2011-01-23 01:40:55.000000000 +0200 +++ iputils-s20101006/clockdiff.c 2011-05-03 20:20:16.000000000 +0300 @@ -20,6 +20,9 @@ #include #include #include +#include "fixfds.h" +#include "dropcap.h" + void usage(void) __attribute__((noreturn)); @@ -539,6 +542,8 @@ char hostname[MAX_HOSTNAMELEN]; int s_errno = 0; + fix_fds(); + if (argc < 2) { if (setuid(getuid())) { perror("clockdiff: setuid"); @@ -550,10 +555,7 @@ sock_raw = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); s_errno = errno; - if (setuid(getuid())) { - perror("clockdiff: setuid"); - exit(-1); - } + drop_cap(); if (argc == 3) { if (strcmp(argv[1], "-o") == 0) { diff -urN iputils-s20101006.orig/dropcap.c iputils-s20101006/dropcap.c --- iputils-s20101006.orig/dropcap.c 1970-01-01 03:00:00.000000000 +0300 +++ iputils-s20101006/dropcap.c 2011-05-03 20:20:16.000000000 +0300 @@ -0,0 +1,79 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dropcap.h" + +extern void drop_cap (void); + +void +drop_cap (void) +{ + const char *dir = "/var/resolv"; + cap_t caps; + uid_t uid = getuid (); + gid_t gid = getgid (); + + if (uid && geteuid()) + return; + + if (setgroups (0, NULL) < 0) + error (EXIT_FAILURE, errno, "setgroups"); + + if (prctl (PR_SET_KEEPCAPS, 1)) + error (EXIT_FAILURE, errno, "prctl (PR_SET_KEEPCAPS, 1) failed"); + + if (!uid) + { + const char *user = "iputils"; + struct passwd *pw = getpwnam (user); + + if (!pw) + error (EXIT_FAILURE, 0, + "lookup of user \"%s\" failed", user); + + gid = pw->pw_gid; + uid = pw->pw_uid; + endpwent (); + + if (!uid) + error (EXIT_FAILURE, 0, + "user \"%s\" shouldn't be root", user); + } + + if (chroot (dir) < 0) + error (EXIT_FAILURE, errno, "chroot to \"%s\" failed", dir); + + if (chdir ("/") < 0) + error (EXIT_FAILURE, errno, "chdir to \"/\" failed"); + + if (setgid (gid) < 0) + error (EXIT_FAILURE, errno, "setgid"); + + caps = cap_from_text ("cap_setuid,cap_net_raw=ep"); + if (!caps) + error (EXIT_FAILURE, errno, "cap_from_text failed"); + + if (cap_set_proc (caps) < 0) + error (EXIT_FAILURE, errno, "cap_set_proc failed"); + + cap_free (caps); + + if (setreuid (uid, uid) < 0) + error (EXIT_FAILURE, errno, "setreuid"); + + caps = cap_from_text ("cap_net_raw=ep"); + if (!caps) + error (EXIT_FAILURE, errno, "cap_from_text failed"); + + if (cap_set_proc (caps) < 0) + error (EXIT_FAILURE, errno, "cap_set_proc failed"); + + cap_free (caps); +} diff -urN iputils-s20101006.orig/dropcap.h iputils-s20101006/dropcap.h --- iputils-s20101006.orig/dropcap.h 1970-01-01 03:00:00.000000000 +0300 +++ iputils-s20101006/dropcap.h 2011-05-03 20:20:16.000000000 +0300 @@ -0,0 +1,6 @@ +#ifndef __DROPCAP_H__ +#define __DROPCAP_H__ + +extern void drop_cap (void); + +#endif /* __DROPCAP_H__ */ diff -urN iputils-s20101006.orig/droppriv.c iputils-s20101006/droppriv.c --- iputils-s20101006.orig/droppriv.c 1970-01-01 03:00:00.000000000 +0300 +++ iputils-s20101006/droppriv.c 2011-05-03 20:20:16.000000000 +0300 @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include +#include + +#include "droppriv.h" + +uid_t uid = -1; + +void +drop_priv (void) +{ + const char *dir = "/var/resolv"; + uid = getuid (); + + if (uid && geteuid()) + return; + + if (setgroups (0, NULL) < 0) + error (EXIT_FAILURE, errno, "setgroups"); + + if (uid) + { + if (chroot (dir) < 0) + error (EXIT_FAILURE, errno, "chroot to \"%s\" failed", + dir); + + if (chdir ("/") < 0) + error (EXIT_FAILURE, errno, "chdir to \"/\" failed"); + + if (setgid (getgid ()) < 0) + error (EXIT_FAILURE, errno, "setgid"); + + if (setuid (uid) < 0) + error (EXIT_FAILURE, errno, "setuid"); + } else + { + const char *user = "iputils"; + struct passwd *pw = getpwnam (user); + + if (!pw) + error (EXIT_FAILURE, 0, + "lookup of user \"%s\" failed", user); + endpwent (); + + if (!pw->pw_uid) + error (EXIT_FAILURE, 0, + "user \"%s\" shouldn't be root", user); + + if (chroot (dir) < 0) + error (EXIT_FAILURE, errno, "chroot to \"%s\" failed", + dir); + + if (chdir ("/") < 0) + error (EXIT_FAILURE, errno, "chdir to \"/\" failed"); + + if (setgid (pw->pw_gid) < 0) + error (EXIT_FAILURE, errno, "setgid"); + + if (setuid (pw->pw_uid) < 0) + error (EXIT_FAILURE, errno, "setuid"); + } +} diff -urN iputils-s20101006.orig/droppriv.h iputils-s20101006/droppriv.h --- iputils-s20101006.orig/droppriv.h 1970-01-01 03:00:00.000000000 +0300 +++ iputils-s20101006/droppriv.h 2011-05-03 20:20:16.000000000 +0300 @@ -0,0 +1,10 @@ +#ifndef __DROPPRIV_H__ +#define __DROPPRIV_H__ + +#include + +extern void drop_priv (void); + +extern uid_t uid; + +#endif /* __DROPPRIV_H__ */ diff -urN iputils-s20101006.orig/fixfds.c iputils-s20101006/fixfds.c --- iputils-s20101006.orig/fixfds.c 1970-01-01 03:00:00.000000000 +0300 +++ iputils-s20101006/fixfds.c 2011-05-03 20:20:16.000000000 +0300 @@ -0,0 +1,27 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "fixfds.h" + +void +fix_fds (void) +{ + struct stat stb; + + if ((fstat (STDIN_FILENO, &stb) < 0) + && (open (_PATH_DEVNULL, O_RDONLY) != STDIN_FILENO)) + error (EXIT_FAILURE, errno, "open: %s", _PATH_DEVNULL); + + if ((fstat (STDOUT_FILENO, &stb) < 0) + && (open (_PATH_DEVNULL, O_WRONLY) != STDOUT_FILENO)) + error (EXIT_FAILURE, errno, "open: %s", _PATH_DEVNULL); + + if ((fstat (STDERR_FILENO, &stb) < 0) + && (open (_PATH_DEVNULL, O_WRONLY) != STDERR_FILENO)) + error (EXIT_FAILURE, errno, "open: %s", _PATH_DEVNULL); +} diff -urN iputils-s20101006.orig/fixfds.h iputils-s20101006/fixfds.h --- iputils-s20101006.orig/fixfds.h 1970-01-01 03:00:00.000000000 +0300 +++ iputils-s20101006/fixfds.h 2011-05-03 20:20:16.000000000 +0300 @@ -0,0 +1,6 @@ +#ifndef __FIXFDS_H__ +#define __FIXFDS_H__ + +extern void fix_fds (void); + +#endif /* __FIXFDS_H__ */ diff -urN iputils-s20101006.orig/Makefile iputils-s20101006/Makefile --- iputils-s20101006.orig/Makefile 2011-01-23 01:40:55.000000000 +0200 +++ iputils-s20101006/Makefile 2011-05-03 20:20:16.000000000 +0300 @@ -26,10 +26,15 @@ all: $(TARGETS) +arping: arping.o -lsysfs fixfds.o droppriv.o +clockdiff: clockdiff.o fixfds.o dropcap.o + $(LINK.o) $^ $(LOADLIBES) $(LDLIBS) -lcap -o $@ tftpd: tftpd.o tftpsubs.o -arping: arping.o -lsysfs -ping: ping.o ping_common.o -ping6: ping6.o ping_common.o -lresolv -lcrypto +tracepath: tracepath.o fixfds.o droppriv.o +tracepath6: tracepath6.o fixfds.o droppriv.o +traceroute6: traceroute6.o fixfds.o droppriv.o +ping: ping.o ping_common.o fixfds.o droppriv.o +ping6: ping6.o ping_common.o fixfds.o droppriv.o -lresolv -lcrypto ping.o ping6.o ping_common.o: ping_common.h tftpd.o tftpsubs.o: tftp.h diff -urN iputils-s20101006.orig/ping6.c iputils-s20101006/ping6.c --- iputils-s20101006.orig/ping6.c 2011-01-23 01:40:55.000000000 +0200 +++ iputils-s20101006/ping6.c 2011-05-03 20:20:16.000000000 +0300 @@ -67,6 +67,8 @@ * This program has to run SUID to ROOT to access the ICMP socket. */ #include "ping_common.h" +#include "fixfds.h" +#include "droppriv.h" #include #include @@ -529,14 +531,12 @@ #endif static uint32_t scope_id = 0; + fix_fds(); + icmp_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); socket_errno = errno; - uid = getuid(); - if (setuid(uid)) { - perror("ping: setuid"); - exit(-1); - } + drop_priv(); source.sin6_family = AF_INET6; memset(&firsthop, 0, sizeof(firsthop)); diff -urN iputils-s20101006.orig/ping.c iputils-s20101006/ping.c --- iputils-s20101006.orig/ping.c 2011-01-23 01:40:55.000000000 +0200 +++ iputils-s20101006/ping.c 2011-05-03 20:20:16.000000000 +0300 @@ -59,6 +59,8 @@ */ #include "ping_common.h" +#include "fixfds.h" +#include "droppriv.h" #include #include @@ -123,14 +125,12 @@ char *target, hnamebuf[MAX_HOSTNAMELEN]; char rspace[3 + 4 * NROUTES + 1]; /* record route space */ + fix_fds(); + icmp_sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); socket_errno = errno; - uid = getuid(); - if (setuid(uid)) { - perror("ping: setuid"); - exit(-1); - } + drop_priv(); source.sin_family = AF_INET; diff -urN iputils-s20101006.orig/ping_common.c iputils-s20101006/ping_common.c --- iputils-s20101006.orig/ping_common.c 2011-01-23 01:40:55.000000000 +0200 +++ iputils-s20101006/ping_common.c 2011-05-03 20:20:16.000000000 +0300 @@ -1,6 +1,7 @@ #include "ping_common.h" #include #include +#include "droppriv.h" int options; @@ -55,7 +56,6 @@ int datalen = DEFDATALEN; char *hostname; -int uid; int ident; /* process id to identify our packets */ static int screen_width = INT_MAX; diff -urN iputils-s20101006.orig/ping_common.h iputils-s20101006/ping_common.h --- iputils-s20101006.orig/ping_common.h 2011-01-23 01:40:55.000000000 +0200 +++ iputils-s20101006/ping_common.h 2011-05-03 20:20:16.000000000 +0300 @@ -77,7 +77,6 @@ extern int datalen; extern char *hostname; -extern int uid; extern int ident; /* process id to identify our packets */ extern int sndbuf; diff -urN iputils-s20101006.orig/tracepath6.c iputils-s20101006/tracepath6.c --- iputils-s20101006.orig/tracepath6.c 2011-01-23 01:40:55.000000000 +0200 +++ iputils-s20101006/tracepath6.c 2011-05-03 20:20:16.000000000 +0300 @@ -25,6 +25,8 @@ #include #include #include +#include "fixfds.h" +#include "droppriv.h" #ifndef SOL_IPV6 #define SOL_IPV6 IPPROTO_IPV6 @@ -375,6 +377,9 @@ int gai; char pbuf[NI_MAXSERV]; + fix_fds(); + drop_priv(); + while ((ch = getopt(argc, argv, "nbh?l:")) != EOF) { switch(ch) { case 'n': diff -urN iputils-s20101006.orig/tracepath.c iputils-s20101006/tracepath.c --- iputils-s20101006.orig/tracepath.c 2011-01-23 01:40:55.000000000 +0200 +++ iputils-s20101006/tracepath.c 2011-05-03 20:20:16.000000000 +0300 @@ -23,6 +23,8 @@ #include #include #include +#include "fixfds.h" +#include "droppriv.h" #ifndef IP_PMTUDISC_PROBE #define IP_PMTUDISC_PROBE 3 @@ -299,6 +301,9 @@ char *p; int ch; + fix_fds(); + drop_priv(); + while ((ch = getopt(argc, argv, "nbh?l:")) != EOF) { switch(ch) { case 'n': diff -urN iputils-s20101006.orig/traceroute6.c iputils-s20101006/traceroute6.c --- iputils-s20101006.orig/traceroute6.c 2011-01-23 01:40:55.000000000 +0200 +++ iputils-s20101006/traceroute6.c 2011-05-03 20:20:16.000000000 +0300 @@ -260,6 +260,8 @@ #include #include "SNAPSHOT.h" +#include "fixfds.h" +#include "droppriv.h" #ifndef SOL_IPV6 #define SOL_IPV6 IPPROTO_IPV6 @@ -335,13 +337,12 @@ int ch, i, on, probe, seq, tos, ttl; int socket_errno; + fix_fds(); + icmp_sock = socket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6); socket_errno = errno; - if (setuid(getuid())) { - perror("traceroute6: setuid"); - exit(-1); - } + drop_priv(); on = 1; seq = tos = 0;