Skip to content

Commit dc3a2d2

Browse files
tohojoAlexei Starovoitov
authored andcommitted
libbpf: Print hint about ulimit when getting permission denied error
Probably the single most common error newcomers to XDP are stumped by is the 'permission denied' error they get when trying to load their program and 'ulimit -l' is set too low. For examples, see [0], [1]. Since the error code is UAPI, we can't change that. Instead, this patch adds a few heuristics in libbpf and outputs an additional hint if they are met: If an EPERM is returned on map create or program load, and geteuid() shows we are root, and the current RLIMIT_MEMLOCK is not infinity, we output a hint about raising 'ulimit -l' as an additional log line. [0] https://marc.info/?l=xdp-newbies&m=157043612505624&w=2 [1] xdp-project/xdp-tutorial#86 Signed-off-by: Toke Høiland-Jørgensen <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Acked-by: Jesper Dangaard Brouer <[email protected]> Acked-by: Yonghong Song <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent d50ecc4 commit dc3a2d2

File tree

1 file changed

+29
-0
lines changed

1 file changed

+29
-0
lines changed

tools/lib/bpf/libbpf.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include <sys/types.h>
4242
#include <sys/vfs.h>
4343
#include <sys/utsname.h>
44+
#include <sys/resource.h>
4445
#include <tools/libc_compat.h>
4546
#include <libelf.h>
4647
#include <gelf.h>
@@ -100,6 +101,32 @@ void libbpf_print(enum libbpf_print_level level, const char *format, ...)
100101
va_end(args);
101102
}
102103

104+
static void pr_perm_msg(int err)
105+
{
106+
struct rlimit limit;
107+
char buf[100];
108+
109+
if (err != -EPERM || geteuid() != 0)
110+
return;
111+
112+
err = getrlimit(RLIMIT_MEMLOCK, &limit);
113+
if (err)
114+
return;
115+
116+
if (limit.rlim_cur == RLIM_INFINITY)
117+
return;
118+
119+
if (limit.rlim_cur < 1024)
120+
snprintf(buf, sizeof(buf), "%lu bytes", limit.rlim_cur);
121+
else if (limit.rlim_cur < 1024*1024)
122+
snprintf(buf, sizeof(buf), "%.1f KiB", (double)limit.rlim_cur / 1024);
123+
else
124+
snprintf(buf, sizeof(buf), "%.1f MiB", (double)limit.rlim_cur / (1024*1024));
125+
126+
pr_warn("permission error while running as root; try raising 'ulimit -l'? current value: %s\n",
127+
buf);
128+
}
129+
103130
#define STRERR_BUFSIZE 128
104131

105132
/* Copied from tools/perf/util/util.h */
@@ -2983,6 +3010,7 @@ bpf_object__create_maps(struct bpf_object *obj)
29833010
cp = libbpf_strerror_r(err, errmsg, sizeof(errmsg));
29843011
pr_warn("failed to create map (name: '%s'): %s(%d)\n",
29853012
map->name, cp, err);
3013+
pr_perm_msg(err);
29863014
for (j = 0; j < i; j++)
29873015
zclose(obj->maps[j].fd);
29883016
return err;
@@ -4381,6 +4409,7 @@ load_program(struct bpf_program *prog, struct bpf_insn *insns, int insns_cnt,
43814409
ret = -errno;
43824410
cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg));
43834411
pr_warn("load bpf program failed: %s\n", cp);
4412+
pr_perm_msg(ret);
43844413

43854414
if (log_buf && log_buf[0] != '\0') {
43864415
ret = -LIBBPF_ERRNO__VERIFY;

0 commit comments

Comments
 (0)