summaryrefslogtreecommitdiff
path: root/tools/bpf/bpftool/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/bpf/bpftool/common.c')
-rw-r--r--tools/bpf/bpftool/common.c71
1 files changed, 63 insertions, 8 deletions
diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
index b2533f1cae3e..f0288269dae8 100644
--- a/tools/bpf/bpftool/common.c
+++ b/tools/bpf/bpftool/common.c
@@ -42,6 +42,7 @@
#include <unistd.h>
#include <linux/limits.h>
#include <linux/magic.h>
+#include <sys/mount.h>
#include <sys/types.h>
#include <sys/vfs.h>
@@ -59,6 +60,37 @@ static bool is_bpffs(char *path)
return (unsigned long)st_fs.f_type == BPF_FS_MAGIC;
}
+static int mnt_bpffs(const char *target, char *buff, size_t bufflen)
+{
+ bool bind_done = false;
+
+ while (mount("", target, "none", MS_PRIVATE | MS_REC, NULL)) {
+ if (errno != EINVAL || bind_done) {
+ snprintf(buff, bufflen,
+ "mount --make-private %s failed: %s",
+ target, strerror(errno));
+ return -1;
+ }
+
+ if (mount(target, target, "none", MS_BIND, NULL)) {
+ snprintf(buff, bufflen,
+ "mount --bind %s %s failed: %s",
+ target, target, strerror(errno));
+ return -1;
+ }
+
+ bind_done = true;
+ }
+
+ if (mount("bpf", target, "bpf", 0, "mode=0700")) {
+ snprintf(buff, bufflen, "mount -t bpf bpf %s failed: %s",
+ target, strerror(errno));
+ return -1;
+ }
+
+ return 0;
+}
+
int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type)
{
enum bpf_obj_type type;
@@ -89,8 +121,11 @@ int open_obj_pinned_any(char *path, enum bpf_obj_type exp_type)
int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
{
+ char err_str[ERR_MAX_LEN];
unsigned int id;
char *endptr;
+ char *file;
+ char *dir;
int err;
int fd;
@@ -117,16 +152,36 @@ int do_pin_any(int argc, char **argv, int (*get_fd_by_id)(__u32))
}
err = bpf_obj_pin(fd, *argv);
- close(fd);
- if (err) {
- p_err("can't pin the object (%s): %s", *argv,
- errno == EACCES && !is_bpffs(dirname(*argv)) ?
- "directory not in bpf file system (bpffs)" :
- strerror(errno));
- return -1;
+ if (!err)
+ goto out_close;
+
+ file = malloc(strlen(*argv) + 1);
+ strcpy(file, *argv);
+ dir = dirname(file);
+
+ if (errno != EPERM || is_bpffs(dir)) {
+ p_err("can't pin the object (%s): %s", *argv, strerror(errno));
+ goto out_free;
}
- return 0;
+ /* Attempt to mount bpffs, then retry pinning. */
+ err = mnt_bpffs(dir, err_str, ERR_MAX_LEN);
+ if (!err) {
+ err = bpf_obj_pin(fd, *argv);
+ if (err)
+ p_err("can't pin the object (%s): %s", *argv,
+ strerror(errno));
+ } else {
+ err_str[ERR_MAX_LEN - 1] = '\0';
+ p_err("can't mount BPF file system to pin the object (%s): %s",
+ *argv, err_str);
+ }
+
+out_free:
+ free(file);
+out_close:
+ close(fd);
+ return err;
}
const char *get_fd_type_name(enum bpf_obj_type type)