]> git.proxmox.com Git - mirror_iproute2.git/commitdiff
Drop capabilities if not running ip exec vrf with libcap
authorLuca Boccassi <bluca@debian.org>
Tue, 27 Mar 2018 17:48:55 +0000 (18:48 +0100)
committerStephen Hemminger <stephen@networkplumber.org>
Tue, 27 Mar 2018 18:48:23 +0000 (11:48 -0700)
ip vrf exec requires root or CAP_NET_ADMIN, CAP_SYS_ADMIN and
CAP_DAC_OVERRIDE. It is not possible to run unprivileged commands like
ping as non-root or non-cap-enabled due to this requirement.
To allow users and administrators to safely add the required
capabilities to the binary, drop all capabilities on start if not
invoked with "vrf exec".
Update the manpage with the requirements.

Signed-off-by: Luca Boccassi <bluca@debian.org>
Signed-off-by: Stephen Hemminger <stephen@networkplumber.org>
configure
include/utils.h
ip/ip.c
ip/ipvrf.c
lib/utils.c
man/man8/ip-vrf.8

index f7c2d7a7d57c698570783ec14cae98a71332bfb8..5ef5cd4cf9cde980c5951153594a9c93de3bf41c 100755 (executable)
--- a/configure
+++ b/configure
@@ -336,6 +336,20 @@ EOF
     rm -f $TMPDIR/strtest.c $TMPDIR/strtest
 }
 
+check_cap()
+{
+       if ${PKG_CONFIG} libcap --exists
+       then
+               echo "HAVE_CAP:=y" >>$CONFIG
+               echo "yes"
+
+               echo 'CFLAGS += -DHAVE_LIBCAP' `${PKG_CONFIG} libcap --cflags` >>$CONFIG
+               echo 'LDLIBS +=' `${PKG_CONFIG} libcap --libs` >> $CONFIG
+       else
+               echo "no"
+       fi
+}
+
 quiet_config()
 {
        cat <<EOF
@@ -410,6 +424,9 @@ check_berkeley_db
 echo -n "need for strlcpy: "
 check_strlcpy
 
+echo -n "libcap support: "
+check_cap
+
 echo >> $CONFIG
 echo "%.o: %.c" >> $CONFIG
 echo ' $(QUIET_CC)$(CC) $(CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<' >> $CONFIG
index 0394268e1276f7c7d47c3495844b391156440236..e7bffe8acbda405234e06a55078ee8af978636fa 100644 (file)
@@ -299,4 +299,6 @@ size_t strlcpy(char *dst, const char *src, size_t size);
 size_t strlcat(char *dst, const char *src, size_t size);
 #endif
 
+void drop_cap(void);
+
 #endif /* __UTILS_H__ */
diff --git a/ip/ip.c b/ip/ip.c
index e0cd96cb1c15975f3f14745dd57c9cffe486719f..e716fed8e8fe6f526c2665f7a5a6492a542bf317 100644 (file)
--- a/ip/ip.c
+++ b/ip/ip.c
@@ -174,6 +174,18 @@ int main(int argc, char **argv)
        char *batch_file = NULL;
        int color = 0;
 
+       /* to run vrf exec without root, capabilities might be set, drop them
+        * if not needed as the first thing.
+        * execv will drop them for the child command.
+        * vrf exec requires:
+        * - cap_dac_override to create the cgroup subdir in /sys
+        * - cap_sys_admin to load the BPF program
+        * - cap_net_admin to set the socket into the cgroup
+        */
+       if (argc < 3 || strcmp(argv[1], "vrf") != 0 ||
+                       strcmp(argv[2], "exec") != 0)
+               drop_cap();
+
        basename = strrchr(argv[0], '/');
        if (basename == NULL)
                basename = argv[0];
index f9277e1e66bdf84eb9b0fb1946df53f72f8443a5..8a6b7f977b1423da8c1ee0df8379d90ba4716cc0 100644 (file)
@@ -436,6 +436,8 @@ out2:
 out:
        free(mnt);
 
+       drop_cap();
+
        return rc;
 }
 
index 4fe4ac1e679ffcfea436478b845f5f1d0135f21c..dadefb55096c3a3e72110993a761e1e46f4f6127 100644 (file)
@@ -30,6 +30,9 @@
 #include <time.h>
 #include <sys/time.h>
 #include <errno.h>
+#ifdef HAVE_LIBCAP
+#include <sys/capability.h>
+#endif
 
 #include "rt_names.h"
 #include "utils.h"
@@ -1495,3 +1498,22 @@ size_t strlcat(char *dst, const char *src, size_t size)
        return dlen + strlcpy(dst + dlen, src, size - dlen);
 }
 #endif
+
+void drop_cap(void)
+{
+#ifdef HAVE_LIBCAP
+       /* don't harmstring root/sudo */
+       if (getuid() != 0 && geteuid() != 0) {
+               cap_t capabilities;
+
+               capabilities = cap_get_proc();
+               if (!capabilities)
+                       exit(EXIT_FAILURE);
+               if (cap_clear(capabilities) != 0)
+                       exit(EXIT_FAILURE);
+               if (cap_set_proc(capabilities) != 0)
+                       exit(EXIT_FAILURE);
+               cap_free(capabilities);
+       }
+#endif
+}
index 187893393be22530fd233da4ca0df1fb7cba675e..1a42cebe1aef44f6de820254677e1b03a4709be9 100644 (file)
@@ -63,6 +63,14 @@ a VRF other than the default VRF (main table). A command can be run against
 the default VRF by passing the "default" as the VRF name. This is useful if
 the current shell is associated with another VRF (e.g, Management VRF).
 
+This command requires the system to be booted with cgroup v2 (e.g. with systemd,
+add systemd.unified_cgroup_hierarchy=1 to the kernel command line).
+
+This command also requires to be ran as root or with the CAP_SYS_ADMIN,
+CAP_NET_ADMIN and CAP_DAC_OVERRIDE capabilities. If built with libcap and if
+capabilities are added to the ip binary program via setcap, the program will
+drop them as the first thing when invoked, unless the command is vrf exec.
+
 .TP
 .B ip vrf identify [PID] - Report VRF association for process
 .sp