Skip to contentSkip to conversation

iputils: Add capability dropping

PATCH Applied Ángel González 2 participants 2 messages Feb 10, 2012 – Feb 21, 2012

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 iputils: Add capability dropping

This patch adds support for dropping capabilities to the iputils programs which need root privileges (ping, ping6, clockdiff, traceroute6), so that users installing them suid can instead install them setcap cap_net_raw+ep

The feature adds libcap as a requisite. In order to disable the feature
sed -i "s/-DCAPABILITIES//;s/ -lcap//" Makefile

---

Makefile +6 -5
diff -ur iputils/Makefile iputils-capabilities/Makefile
@@ -14,7 +14,7 @@
 # What a pity, all new gccs are buggy and -Werror does not work. Sigh.
 #CCOPT=-D_GNU_SOURCE -O2 -Wstrict-prototypes -Wall -g -Werror
 CCOPT=-D_GNU_SOURCE -O2 -Wstrict-prototypes -Wall -g
-CFLAGS=$(CCOPT) $(GLIBCFIX) $(DEFINES) 
+CFLAGS=$(CCOPT) $(GLIBCFIX) $(DEFINES) -DCAPABILITIES
 
 IPV4_TARGETS=tracepath ping clockdiff rdisc arping tftpd rarpd
 IPV6_TARGETS=tracepath6 traceroute6 ping6
@@ -25,11 +25,12 @@
 
 all: $(TARGETS)
 
-
+clockdiff: -lcap
+traceroute6: -lcap
 tftpd: tftpd.o tftpsubs.o
-arping: arping.o -lsysfs
-ping: ping.o ping_common.o
-ping6: ping6.o ping_common.o -lresolv -lcrypto
+arping: arping.o -lsysfs -lcap
+ping: ping.o ping_common.o -lcap
+ping6: ping6.o ping_common.o -lresolv -lcrypto -lcap
 ping.o ping6.o ping_common.o: ping_common.h
 tftpd.o tftpsubs.o: tftp.h
 
arping.c +14 -0
diff -ur iputils/arping.c iputils-capabilities/arping.c
@@ -22,6 +22,9 @@
 #include <linux/if_ether.h>
 #include <net/if_arp.h>
 #include <sys/uio.h>
+#ifdef CAPABILITIES
+#include <sys/capability.h>
+#endif
 
 #include <netdb.h>
 #include <unistd.h>
@@ -356,6 +359,17 @@
 		exit(-1);
 	}
 
+#ifdef CAPABILITIES
+	{
+		cap_t caps = cap_init();
+		if (cap_set_proc(caps)) {
+			perror("arping: cap_set_proc");
+			exit(-1);
+		}
+		cap_free(caps);
+	}
+#endif
+
 	while ((ch = getopt(argc, argv, "h?bfDUAqc:w:s:I:V")) != EOF) {
 		switch(ch) {
 		case 'b':
clockdiff.c +19 -9
diff -ur iputils/clockdiff.c iputils-capabilities/clockdiff.c
@@ -20,6 +20,9 @@
 #include <arpa/inet.h>
 #include <errno.h>
 #include <linux/types.h>
+#ifdef CAPABILITIES
+#include <sys/capability.h>
+#endif
 
 void usage(void) __attribute__((noreturn));
 
@@ -530,6 +533,20 @@
   exit(1);
 }
 
+void drop_rights(void) {
+#ifdef CAPABILITIES
+	cap_t caps = cap_init();
+	if (cap_set_proc(caps)) {
+		perror("clockdiff: cap_set_proc");
+		exit(-1);
+	}
+	cap_free(caps);
+#endif
+	if (setuid(getuid())) {
+		perror("clockdiff: setuid");
+		exit(-1);
+	}
+}
 
 int
 main(int argc, char *argv[])
@@ -541,10 +558,7 @@
 	int n_errno = 0;
 
 	if (argc < 2) {
-		if (setuid(getuid())) {
-			perror("clockdiff: setuid");
-			exit(-1);
-		}
+		drop_rights();
 		usage();
 	}
 
@@ -554,11 +568,7 @@
 	errno = 0;
 	if (nice(-16) == -1)
 		n_errno = errno;
-
-	if (setuid(getuid())) {
-		perror("clockdiff: setuid");
-		exit(-1);
-	}
+	drop_rights();
 
 	if (argc == 3) {
 		if (strcmp(argv[1], "-o") == 0) {
ping.c +13 -0
diff -ur iputils/ping.c iputils-capabilities/ping.c
@@ -62,6 +62,9 @@
 
 #include <netinet/ip.h>
 #include <netinet/ip_icmp.h>
+#ifdef CAPABILITIES
+#include <sys/capability.h>
+#endif
 
 #ifndef ICMP_FILTER
 #define ICMP_FILTER	1
@@ -131,6 +134,16 @@
 		perror("ping: setuid");
 		exit(-1);
 	}
+#ifdef CAPABILITIES
+	{
+		cap_t caps = cap_init();
+		if (cap_set_proc(caps)) {
+			perror("ping: cap_set_proc");
+			exit(-1);
+		}
+		cap_free(caps);
+	}
+#endif
 
 	source.sin_family = AF_INET;
 
ping6.c +14 -1
diff -ur iputils/ping6.c iputils-capabilities/ping6.c
@@ -72,6 +72,9 @@
 #include <netinet/ip6.h>
 #include <netinet/icmp6.h>
 #include <resolv.h>
+#ifdef CAPABILITIES
+#include <sys/capability.h>
+#endif
 
 #include "ping6_niquery.h"
 
@@ -551,9 +554,19 @@
 
 	uid = getuid();
 	if (setuid(uid)) {
-		perror("ping: setuid");
+		perror("ping6: setuid");
 		exit(-1);
 	}
+#ifdef CAPABILITIES
+	{
+		cap_t caps = cap_init();
+		if (cap_set_proc(caps)) {
+			perror("ping6: cap_set_proc");
+			exit(-1);
+		}
+		cap_free(caps);
+	}
+#endif
 
 	source.sin6_family = AF_INET6;
 	memset(&firsthop, 0, sizeof(firsthop));
traceroute6.c +13 -0
diff -ur iputils/traceroute6.c iputils-capabilities/traceroute6.c
@@ -249,6 +249,9 @@
 #include <netinet/ip6.h>
 #include <netinet/icmp6.h>
 #include <linux/types.h>
+#ifdef CAPABILITIES
+#include <sys/capability.h>
+#endif
 
 #include <arpa/inet.h>
 
@@ -342,6 +345,16 @@
 		perror("traceroute6: setuid");
 		exit(-1);
 	}
+#ifdef CAPABILITIES
+	{
+		cap_t caps = cap_init();
+		if (cap_set_proc(caps)) {
+			perror("traceroute6: cap_set_proc");
+			exit(-1);
+		}
+		cap_free(caps);
+	}
+#endif
 
 	on = 1;
 	seq = tos = 0;
#1 lore raw

Applied. Thank you.

Quoted 226 lines · Ángel González

This patch adds support for dropping capabilities to the iputils programs which need root privileges (ping, ping6, clockdiff, traceroute6), so that users installing them suid can instead install them setcap cap_net_raw+ep

The feature adds libcap as a requisite. In order to disable the feature
sed -i "s/-DCAPABILITIES//;s/ -lcap//" Makefile

---

diff -ur iputils/Makefile iputils-capabilities/Makefile

Makefile +6 -5
@@ -14,7 +14,7 @@
  # What a pity, all new gccs are buggy and -Werror does not work. Sigh.
  #CCOPT=-D_GNU_SOURCE -O2 -Wstrict-prototypes -Wall -g -Werror
  CCOPT=-D_GNU_SOURCE -O2 -Wstrict-prototypes -Wall -g
-CFLAGS=$(CCOPT) $(GLIBCFIX) $(DEFINES)
+CFLAGS=$(CCOPT) $(GLIBCFIX) $(DEFINES) -DCAPABILITIES
 
  IPV4_TARGETS=tracepath ping clockdiff rdisc arping tftpd rarpd
  IPV6_TARGETS=tracepath6 traceroute6 ping6
@@ -25,11 +25,12 @@
 
  all: $(TARGETS)
 
-
+clockdiff: -lcap
+traceroute6: -lcap
  tftpd: tftpd.o tftpsubs.o
-arping: arping.o -lsysfs
-ping: ping.o ping_common.o
-ping6: ping6.o ping_common.o -lresolv -lcrypto
+arping: arping.o -lsysfs -lcap
+ping: ping.o ping_common.o -lcap
+ping6: ping6.o ping_common.o -lresolv -lcrypto -lcap
  ping.o ping6.o ping_common.o: ping_common.h
  tftpd.o tftpsubs.o: tftp.h
 

diff -ur iputils/arping.c iputils-capabilities/arping.c

arping.c +14 -0
@@ -22,6 +22,9 @@
  #include<linux/if_ether.h>
  #include<net/if_arp.h>
  #include<sys/uio.h>
+#ifdef CAPABILITIES
+#include<sys/capability.h>
+#endif
 
  #include<netdb.h>
  #include<unistd.h>
@@ -356,6 +359,17 @@
  		exit(-1);
  	}
 
+#ifdef CAPABILITIES
+	{
+		cap_t caps = cap_init();
+		if (cap_set_proc(caps)) {
+			perror("arping: cap_set_proc");
+			exit(-1);
+		}
+		cap_free(caps);
+	}
+#endif
+
  	while ((ch = getopt(argc, argv, "h?bfDUAqc:w:s:I:V")) != EOF) {
  		switch(ch) {
  		case 'b':

diff -ur iputils/clockdiff.c iputils-capabilities/clockdiff.c

clockdiff.c +19 -9
@@ -20,6 +20,9 @@
  #include<arpa/inet.h>
  #include<errno.h>
  #include<linux/types.h>
+#ifdef CAPABILITIES
+#include<sys/capability.h>
+#endif
 
  void usage(void) __attribute__((noreturn));
 
@@ -530,6 +533,20 @@
    exit(1);
  }
 
+void drop_rights(void) {
+#ifdef CAPABILITIES
+	cap_t caps = cap_init();
+	if (cap_set_proc(caps)) {
+		perror("clockdiff: cap_set_proc");
+		exit(-1);
+	}
+	cap_free(caps);
+#endif
+	if (setuid(getuid())) {
+		perror("clockdiff: setuid");
+		exit(-1);
+	}
+}
 
  int
  main(int argc, char *argv[])
@@ -541,10 +558,7 @@
  	int n_errno = 0;
 
  	if (argc<  2) {
-		if (setuid(getuid())) {
-			perror("clockdiff: setuid");
-			exit(-1);
-		}
+		drop_rights();
  		usage();
  	}
 
@@ -554,11 +568,7 @@
  	errno = 0;
  	if (nice(-16) == -1)
  		n_errno = errno;
-
-	if (setuid(getuid())) {
-		perror("clockdiff: setuid");
-		exit(-1);
-	}
+	drop_rights();
 
  	if (argc == 3) {
  		if (strcmp(argv[1], "-o") == 0) {

diff -ur iputils/ping.c iputils-capabilities/ping.c

ping.c +13 -0
@@ -62,6 +62,9 @@
 
  #include<netinet/ip.h>
  #include<netinet/ip_icmp.h>
+#ifdef CAPABILITIES
+#include<sys/capability.h>
+#endif
 
  #ifndef ICMP_FILTER
  #define ICMP_FILTER	1
@@ -131,6 +134,16 @@
  		perror("ping: setuid");
  		exit(-1);
  	}
+#ifdef CAPABILITIES
+	{
+		cap_t caps = cap_init();
+		if (cap_set_proc(caps)) {
+			perror("ping: cap_set_proc");
+			exit(-1);
+		}
+		cap_free(caps);
+	}
+#endif
 
  	source.sin_family = AF_INET;
 

diff -ur iputils/ping6.c iputils-capabilities/ping6.c

ping6.c +14 -1
@@ -72,6 +72,9 @@
  #include<netinet/ip6.h>
  #include<netinet/icmp6.h>
  #include<resolv.h>
+#ifdef CAPABILITIES
+#include<sys/capability.h>
+#endif
 
  #include "ping6_niquery.h"
 
@@ -551,9 +554,19 @@
 
  	uid = getuid();
  	if (setuid(uid)) {
-		perror("ping: setuid");
+		perror("ping6: setuid");
  		exit(-1);
  	}
+#ifdef CAPABILITIES
+	{
+		cap_t caps = cap_init();
+		if (cap_set_proc(caps)) {
+			perror("ping6: cap_set_proc");
+			exit(-1);
+		}
+		cap_free(caps);
+	}
+#endif
 
  	source.sin6_family = AF_INET6;
  	memset(&firsthop, 0, sizeof(firsthop));

diff -ur iputils/traceroute6.c iputils-capabilities/traceroute6.c

traceroute6.c +13 -0
@@ -249,6 +249,9 @@
  #include<netinet/ip6.h>
  #include<netinet/icmp6.h>
  #include<linux/types.h>
+#ifdef CAPABILITIES
+#include<sys/capability.h>
+#endif
 
  #include<arpa/inet.h>
 
@@ -342,6 +345,16 @@
  		perror("traceroute6: setuid");
  		exit(-1);
  	}
+#ifdef CAPABILITIES
+	{
+		cap_t caps = cap_init();
+		if (cap_set_proc(caps)) {
+			perror("traceroute6: cap_set_proc");
+			exit(-1);
+		}
+		cap_free(caps);
+	}
+#endif
 
  	on = 1;
  	seq = tos = 0;