Hi DHCP developers, Andrew Pollock [2008-01-14 20:48 -0800]: > This bug was received some time ago, and I forwarded it on to > dhcp-hackers, because I wasn't aware of dhcp-bugs at the time.
Just confirming that I still think that the server derooting patch makes sense; it is unintrusive and robust. The client patch is more delicate, though, since it needs a suid root wrapper to call the dhclient script. I think it might be better to drop that and replace it with an SELinux or AppArmor policy. FYI I attach the upstream parts of the patch (the one on patches.ubuntu.com is for Debian and also contains the packaging changes, and the upstream patches as diff-of-diffs). It still needs some autoconfiscation, though. Thanks, Martin -- Martin Pitt http://www.piware.de Ubuntu Developer http://www.ubuntu.com Debian Developer http://www.debian.org
diff -Nur dhcp3-3.0.1.old/server/dhcpd.c dhcp3-3.0.1/server/dhcpd.c
--- dhcp3-3.0.1.old/server/dhcpd.c 2005-04-11 18:39:29.845552696 +0200
+++ dhcp3-3.0.1/server/dhcpd.c 2005-04-11 19:19:24.436519536 +0200
@@ -45,6 +45,7 @@
#include "dhcpd.h"
#include "version.h"
+#include "droppriv.h"
#include <omapip/omapip_p.h>
static void usage PROTO ((void));
@@ -226,6 +227,10 @@
char *traceoutfile = (char *)0;
#endif
+ /* drop privileges */
+ cap_value_t capsneeded[] = { CAP_NET_RAW, CAP_NET_BIND_SERVICE };
+ drop_privileges( "dhcpd", "dhcpd", 2, capsneeded, -1 );
+
/* Make sure we have stdin, stdout and stderr. */
status = open ("/dev/null", O_RDWR);
if (status == 0)
@@ -599,6 +604,9 @@
omapi_set_int_value ((omapi_object_t *)dhcp_control_object,
(omapi_object_t *)0, "state", server_running);
+ /* drop all remaining capabilities */
+ drop_privileges( "dhcpd", "dhcpd", 0, NULL, -1 );
+
/* Receive packets and dispatch them... */
dispatch ();
diff -Nur dhcp3-3.0.1.old/server/Makefile.dist dhcp3-3.0.1/server/Makefile.dist
--- dhcp3-3.0.1.old/server/Makefile.dist 2005-04-11 18:39:29.845552696 +0200
+++ dhcp3-3.0.1/server/Makefile.dist 2005-04-11 18:50:07.370634152 +0200
@@ -34,6 +34,7 @@
INCLUDES = -I$(TOP) $(BINDINC) -I$(TOP)/includes
DHCPLIB = ../common/libdhcp.a $(BINDLIB) ../omapip/libomapi.a ../dst/libdst.a
CFLAGS = $(DEBUG) $(PREDEFINES) $(INCLUDES) $(COPTS)
+LIBS = -lcap
all: $(PROG) $(CATMANPAGES)
diff -Nurp dhcp3-3.0.1.old/common/droppriv.c dhcp3-3.0.1/common/droppriv.c
--- dhcp3-3.0.1.old/common/droppriv.c 1970-01-01 01:00:00.000000000 +0100
+++ dhcp3-3.0.1/common/droppriv.c 2005-05-12 15:38:52.000000000 +0200
@@ -0,0 +1,96 @@
+/**
+ * droppriv.c - drop privileges of a program running as root
+ *
+ * (C) 2004 Martin Pitt <[EMAIL PROTECTED]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ */
+
+#include "droppriv.h"
+#include <sys/prctl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <grp.h>
+
+void
+drop_privileges( const char* user, const char* group, int numcaps,
+ cap_value_t* caps, int errorexit )
+{
+ cap_t cap;
+ struct passwd *pw = NULL;
+ struct group *gr = NULL;
+
+ /* determine user and group id */
+ if( user != NULL ) {
+ pw = getpwnam( user );
+ if( !pw ) {
+ fprintf( stderr, "drop_privileges: user %s does not exist\n", user );
+ exit( errorexit );
+ }
+ }
+
+ if( group != NULL ) {
+ gr = getgrnam( group );
+ if( !gr ) {
+ fprintf( stderr, "drop_privileges: group %s does not exist\n", group );
+ exit( errorexit );
+ }
+ }
+
+ /* keep capabilities */
+ if( numcaps > 0 ) {
+ int result;
+
+ if( prctl( PR_SET_KEEPCAPS, 1, 0, 0, 0 ) ) {
+ perror( "drop_privileges: could not keep capabilities" );
+ exit( errorexit );
+ }
+
+ /* test whether cap_set_proc works */
+ cap = cap_get_proc();
+ if( cap ) {
+ result = cap_set_proc( cap );
+ cap_free( cap );
+ if( result )
+ return;
+ } else
+ return;
+ }
+
+
+ /* change uid/gid */
+ if( gr != NULL && setgid( gr->gr_gid ) ) {
+ perror( "drop_privileges: could not set group id" );
+ exit( errorexit );
+ }
+
+ if( pw != NULL && setuid( pw->pw_uid ) ) {
+ perror( "drop_privileges: could not set user id" );
+ exit( errorexit );
+ }
+
+ /* set necessary capabilities */
+ if( numcaps > 0 ) {
+ cap = cap_init();
+ if( cap_set_flag( cap, CAP_PERMITTED, numcaps, caps, CAP_SET ) ||
+ cap_set_flag( cap, CAP_EFFECTIVE, numcaps, caps, CAP_SET ) ) {
+ perror( "drop_privileges: cap_set_flag" );
+ exit( errorexit );
+ }
+
+ if( cap_set_proc( cap ) ) {
+ perror( "drop_privileges: could not install capabilities" );
+ exit( errorexit );
+ }
+
+ if( cap_free( cap ) ) {
+ perror( "drop_privileges: cap_free" );
+ exit( errorexit );
+ }
+ }
+}
+
diff -Nurp dhcp3-3.0.1.old/common/Makefile.dist dhcp3-3.0.1/common/Makefile.dist
--- dhcp3-3.0.1.old/common/Makefile.dist 2004-06-14 23:08:42.000000000 +0200
+++ dhcp3-3.0.1/common/Makefile.dist 2005-05-12 15:31:47.000000000 +0200
@@ -25,11 +25,11 @@ SEDMANPAGES = dhcp-options.man5 dhcp-eva
SRC = raw.c parse.c nit.c icmp.c dispatch.c conflex.c upf.c bpf.c socket.c \
lpf.c dlpi.c packet.c tr.c ethernet.c iscprint.c memory.c print.c \
options.c inet.c tree.c tables.c alloc.c fddi.c ctrace.c dns.c \
- resolv.c execute.c discover.c comapi.c
+ resolv.c execute.c discover.c comapi.c droppriv.c
OBJ = raw.o parse.o nit.o icmp.o dispatch.o conflex.o upf.o bpf.o socket.o \
lpf.o dlpi.o packet.o tr.o ethernet.o iscprint.o memory.o print.o \
options.o inet.o tree.o tables.o alloc.o fddi.o ctrace.o dns.o \
- resolv.o execute.o discover.o comapi.o
+ resolv.o execute.o discover.o comapi.o droppriv.o
MAN = dhcp-options.5 dhcp-eval.5
INCLUDES = -I$(TOP) $(BINDINC) -I$(TOP)/includes
diff -Nurp dhcp3-3.0.1.old/includes/droppriv.h dhcp3-3.0.1/includes/droppriv.h
--- dhcp3-3.0.1.old/includes/droppriv.h 1970-01-01 01:00:00.000000000 +0100
+++ dhcp3-3.0.1/includes/droppriv.h 2005-05-12 15:31:47.000000000 +0200
@@ -0,0 +1,31 @@
+/**
+ * droppriv.h - drop privileges of a program running as root
+ *
+ * (C) 2004 Martin Pitt <[EMAIL PROTECTED]>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ */
+
+#ifndef _DROPPRIV_H
+#define _DROPPRIV_H
+
+#include <sys/capability.h>
+
+/**
+ * Drop all but necessary privileges from a program that is started as
+ * root. Set the running user id and group id to the corresponding
+ * values of 'user' and 'group' (NULL values cause the current
+ * user/group not to change). Drops all capabilities but the
+ * ones specified in caps. numcaps is the number of entries in
+ * caps. On error, a message is printed to stderr and the program
+ * terminates with exit code 'errorexit'.
+ */
+void
+drop_privileges( const char* user, const char* group, int numcaps,
+ cap_value_t* caps, int errorexit );
+
+#endif
+
signature.asc
Description: Digital signature

