Commit 0b3b9ca3 authored by Quentin Monnet's avatar Quentin Monnet Committed by Daniel Borkmann

tools: bpftool: Make libcap dependency optional

The new libcap dependency is not used for an essential feature of
bpftool, and we could imagine building the tool without checks on
CAP_SYS_ADMIN by disabling probing features as an unprivileged users.

Make it so, in order to avoid a hard dependency on libcap, and to ease
packaging/embedding of bpftool.
Signed-off-by: default avatarQuentin Monnet <quentin@isovalent.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Acked-by: default avatarJohn Fastabend <john.fastabend@gmail.com>
Link: https://lore.kernel.org/bpf/20200429144506.8999-4-quentin@isovalent.com
parent cf9bf714
...@@ -55,7 +55,9 @@ DESCRIPTION ...@@ -55,7 +55,9 @@ DESCRIPTION
that case usually represent a small subset of the parameters that case usually represent a small subset of the parameters
supported by the system. Unprivileged users MUST use the supported by the system. Unprivileged users MUST use the
**unprivileged** keyword: This is to avoid misdetection if **unprivileged** keyword: This is to avoid misdetection if
bpftool is inadvertently run as non-root, for example. bpftool is inadvertently run as non-root, for example. This
keyword is unavailable if bpftool was compiled without
libcap.
**bpftool feature probe dev** *NAME* [**full**] [**macros** [**prefix** *PREFIX*]] **bpftool feature probe dev** *NAME* [**full**] [**macros** [**prefix** *PREFIX*]]
Probe network device for supported eBPF features and dump Probe network device for supported eBPF features and dump
......
...@@ -55,16 +55,15 @@ ifneq ($(EXTRA_LDFLAGS),) ...@@ -55,16 +55,15 @@ ifneq ($(EXTRA_LDFLAGS),)
LDFLAGS += $(EXTRA_LDFLAGS) LDFLAGS += $(EXTRA_LDFLAGS)
endif endif
LIBS = $(LIBBPF) -lelf -lz -lcap
INSTALL ?= install INSTALL ?= install
RM ?= rm -f RM ?= rm -f
CLANG ?= clang CLANG ?= clang
FEATURE_USER = .bpftool FEATURE_USER = .bpftool
FEATURE_TESTS = libbfd disassembler-four-args reallocarray zlib \ FEATURE_TESTS = libbfd disassembler-four-args reallocarray zlib libcap \
clang-bpf-global-var
FEATURE_DISPLAY = libbfd disassembler-four-args zlib libcap \
clang-bpf-global-var clang-bpf-global-var
FEATURE_DISPLAY = libbfd disassembler-four-args zlib clang-bpf-global-var
check_feat := 1 check_feat := 1
NON_CHECK_FEAT_TARGETS := clean uninstall doc doc-clean doc-install doc-uninstall NON_CHECK_FEAT_TARGETS := clean uninstall doc doc-clean doc-install doc-uninstall
...@@ -90,6 +89,12 @@ ifeq ($(feature-reallocarray), 0) ...@@ -90,6 +89,12 @@ ifeq ($(feature-reallocarray), 0)
CFLAGS += -DCOMPAT_NEED_REALLOCARRAY CFLAGS += -DCOMPAT_NEED_REALLOCARRAY
endif endif
LIBS = $(LIBBPF) -lelf -lz
ifeq ($(feature-libcap), 1)
CFLAGS += -DUSE_LIBCAP
LIBS += -lcap
endif
include $(wildcard $(OUTPUT)*.d) include $(wildcard $(OUTPUT)*.d)
all: $(OUTPUT)bpftool all: $(OUTPUT)bpftool
......
...@@ -6,7 +6,9 @@ ...@@ -6,7 +6,9 @@
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <net/if.h> #include <net/if.h>
#ifdef USE_LIBCAP
#include <sys/capability.h> #include <sys/capability.h>
#endif
#include <sys/utsname.h> #include <sys/utsname.h>
#include <sys/vfs.h> #include <sys/vfs.h>
...@@ -37,7 +39,9 @@ static const char * const helper_name[] = { ...@@ -37,7 +39,9 @@ static const char * const helper_name[] = {
#undef BPF_HELPER_MAKE_ENTRY #undef BPF_HELPER_MAKE_ENTRY
static bool full_mode; static bool full_mode;
#ifdef USE_LIBCAP
static bool run_as_unprivileged; static bool run_as_unprivileged;
#endif
/* Miscellaneous utility functions */ /* Miscellaneous utility functions */
...@@ -475,11 +479,13 @@ probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types, ...@@ -475,11 +479,13 @@ probe_prog_type(enum bpf_prog_type prog_type, bool *supported_types,
} }
res = bpf_probe_prog_type(prog_type, ifindex); res = bpf_probe_prog_type(prog_type, ifindex);
#ifdef USE_LIBCAP
/* Probe may succeed even if program load fails, for unprivileged users /* Probe may succeed even if program load fails, for unprivileged users
* check that we did not fail because of insufficient permissions * check that we did not fail because of insufficient permissions
*/ */
if (run_as_unprivileged && errno == EPERM) if (run_as_unprivileged && errno == EPERM)
res = false; res = false;
#endif
supported_types[prog_type] |= res; supported_types[prog_type] |= res;
...@@ -535,12 +541,14 @@ probe_helper_for_progtype(enum bpf_prog_type prog_type, bool supported_type, ...@@ -535,12 +541,14 @@ probe_helper_for_progtype(enum bpf_prog_type prog_type, bool supported_type,
if (supported_type) { if (supported_type) {
res = bpf_probe_helper(id, prog_type, ifindex); res = bpf_probe_helper(id, prog_type, ifindex);
#ifdef USE_LIBCAP
/* Probe may succeed even if program load fails, for /* Probe may succeed even if program load fails, for
* unprivileged users check that we did not fail because of * unprivileged users check that we did not fail because of
* insufficient permissions * insufficient permissions
*/ */
if (run_as_unprivileged && errno == EPERM) if (run_as_unprivileged && errno == EPERM)
res = false; res = false;
#endif
} }
if (json_output) { if (json_output) {
...@@ -738,6 +746,7 @@ static void section_misc(const char *define_prefix, __u32 ifindex) ...@@ -738,6 +746,7 @@ static void section_misc(const char *define_prefix, __u32 ifindex)
static int handle_perms(void) static int handle_perms(void)
{ {
#ifdef USE_LIBCAP
cap_value_t cap_list[1] = { CAP_SYS_ADMIN }; cap_value_t cap_list[1] = { CAP_SYS_ADMIN };
bool has_sys_admin_cap = false; bool has_sys_admin_cap = false;
cap_flag_value_t val; cap_flag_value_t val;
...@@ -793,6 +802,18 @@ static int handle_perms(void) ...@@ -793,6 +802,18 @@ static int handle_perms(void)
} }
return res; return res;
#else
/* Detection assumes user has sufficient privileges (CAP_SYS_ADMIN).
* We do not use libpcap so let's approximate, and restrict usage to
* root user only.
*/
if (geteuid()) {
p_err("full feature probing requires root privileges");
return -1;
}
return 0;
#endif /* USE_LIBCAP */
} }
static int do_probe(int argc, char **argv) static int do_probe(int argc, char **argv)
...@@ -852,8 +873,13 @@ static int do_probe(int argc, char **argv) ...@@ -852,8 +873,13 @@ static int do_probe(int argc, char **argv)
return -1; return -1;
define_prefix = GET_ARG(); define_prefix = GET_ARG();
} else if (is_prefix(*argv, "unprivileged")) { } else if (is_prefix(*argv, "unprivileged")) {
#ifdef USE_LIBCAP
run_as_unprivileged = true; run_as_unprivileged = true;
NEXT_ARG(); NEXT_ARG();
#else
p_err("unprivileged run not supported, recompile bpftool with libcap");
return -1;
#endif
} else { } else {
p_err("expected no more arguments, 'kernel', 'dev', 'macros' or 'prefix', got: '%s'?", p_err("expected no more arguments, 'kernel', 'dev', 'macros' or 'prefix', got: '%s'?",
*argv); *argv);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment