[ovs-dev] [PATCH RFC] ovs-vswitchd: Drop all capabilities that OVS doesn't need.
Ben Pfaff
blp at nicira.com
Wed Jul 23 00:07:20 UTC 2014
Signed-off-by: Ben Pfaff <blp at nicira.com>
---
ovs-vswitchd typically runs as root, but it doesn't need most of the powers
of root. This commit makes it drop all the capabilities that it doesn't
typically need.
I don't know how capabilities are really used in practice. Something
equivalent could be achieved through the file system. I don't know the
preferred way to do it.
diff --git a/configure.ac b/configure.ac
index 971c7b3..9665516 100644
--- a/configure.ac
+++ b/configure.ac
@@ -55,6 +55,7 @@ OVS_CHECK_COVERAGE
OVS_CHECK_NDEBUG
OVS_CHECK_NETLINK
OVS_CHECK_OPENSSL
+OVS_CHECK_LIBCAP
OVS_CHECK_LOGDIR
OVS_CHECK_PYTHON
OVS_CHECK_PYTHON_COMPAT
diff --git a/m4/openvswitch.m4 b/m4/openvswitch.m4
index 26b8058..6017c74 100644
--- a/m4/openvswitch.m4
+++ b/m4/openvswitch.m4
@@ -192,6 +192,15 @@ AC_DEFUN([OVS_CHECK_BACKTRACE],
[AC_DEFINE([HAVE_BACKTRACE], [1],
[Define to 1 if you have backtrace(3).])])])
+dnl Defines HAVE_LIBCAP if libcap and <sys/capability.h> are available.
+AC_DEFUN([OVS_CHECK_LIBCAP],
+ [AC_CHECK_HEADER([sys/capability.h],
+ [AC_SEARCH_LIBS([cap_get_proc], [cap])
+ if test $ac_cv_search_cap_get_proc != no; then
+ AC_DEFINE([HAVE_LIBCAP], [1],
+ [Define to 1 if you have libcap and <sys/capability.h>.])
+ fi])])
+
dnl Checks for valgrind/valgrind.h.
AC_DEFUN([OVS_CHECK_VALGRIND],
[AC_CHECK_HEADERS([valgrind/valgrind.h])])
diff --git a/vswitchd/ovs-vswitchd.c b/vswitchd/ovs-vswitchd.c
index 3c843e1..6625cd7 100644
--- a/vswitchd/ovs-vswitchd.c
+++ b/vswitchd/ovs-vswitchd.c
@@ -49,6 +49,9 @@
#include "vlog.h"
#include "lib/vswitch-idl.h"
#include "lib/netdev-dpdk.h"
+#ifdef HAVE_LIBCAP
+#include <sys/capability.h>
+#endif
VLOG_DEFINE_THIS_MODULE(vswitchd);
@@ -60,6 +63,7 @@ static unixctl_cb_func ovs_vswitchd_exit;
static char *parse_options(int argc, char *argv[], char **unixctl_path);
static void usage(void) NO_RETURN;
+static void drop_capabilities(void);
int
main(int argc, char *argv[])
@@ -75,6 +79,8 @@ main(int argc, char *argv[])
argc -= retval;
argv += retval;
+ drop_capabilities();
+
proctitle_init(argc, argv);
service_start(&argc, &argv);
remote = parse_options(argc, argv, &unixctl_path);
@@ -265,3 +271,77 @@ ovs_vswitchd_exit(struct unixctl_conn *conn, int argc OVS_UNUSED,
*exiting = true;
unixctl_command_reply(conn, NULL);
}
+
+static void
+drop_capabilities(void)
+{
+#ifdef HAVE_LIBCAP
+ /* Capabilities we'd like to retain, if we have them. */
+ static const cap_value_t keep[] = {
+ CAP_IPC_LOCK, CAP_NET_ADMIN, CAP_NET_BIND_SERVICE, CAP_NET_RAW
+ };
+
+ cap_t cur, next;
+ char *s;
+ int i;
+
+ /* Get current capabilities. */
+ cur = cap_get_proc();
+ if (!cur) {
+ VLOG_FATAL("failed to retrieve process capabilities (%s)",
+ ovs_strerror(errno));
+ }
+
+ /* Get empty capability. */
+ next = cap_init();
+ if (!next) {
+ VLOG_FATAL("failed to create capability set (%s)",
+ ovs_strerror(errno));
+ }
+
+ /* Copy the capabilities that we want to keep from 'cur' to 'next'.
+ * Leave other capabilities unset.
+ * Thus, 'keep' is effectively a whitelist; we drop all other
+ * capabilities. */
+ for (i = 0; i < ARRAY_SIZE(keep); i++) {
+ static const int flags[] = {
+ CAP_EFFECTIVE, CAP_INHERITABLE, CAP_PERMITTED
+ };
+ cap_value_t value = keep[i];
+ int j;
+
+ for (j = 0; j < ARRAY_SIZE(flags); j++) {
+ cap_flag_t flag = flags[j];
+ cap_flag_value_t flag_value;
+
+ if (cap_get_flag(cur, value, flags[j], &flag_value)) {
+ VLOG_FATAL("failed to get capability flag (%s)",
+ ovs_strerror(errno));
+ }
+ if (cap_set_flag(next, flag, 1, &value, flag_value)) {
+ VLOG_FATAL("failed to set capability flag (%s)",
+ ovs_strerror(errno));
+ }
+ }
+ }
+
+ /* Set our capability set to 'next'. */
+ if (cap_set_proc(next)) {
+ VLOG_FATAL("failed to set process capabilities (%s)",
+ ovs_strerror(errno));
+ }
+
+ /* Log that we dropped capabilities. */
+ s = cap_to_text(next, NULL);
+ if (!s) {
+ VLOG_FATAL("failed to convert capabilities to text (%s)",
+ ovs_strerror(errno));
+ }
+ VLOG_INFO("reduced capability set to: %s", s);
+
+ /* Clean up. */
+ cap_free(s);
+ cap_free(cur);
+ cap_free(next);
+#endif /* HAVE_LIBCAP */
+}
--
1.7.10.4
More information about the dev
mailing list