From patchwork Wed Oct 25 03:11:28 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Kicinski X-Patchwork-Id: 830083 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=netronome-com.20150623.gappssmtp.com header.i=@netronome-com.20150623.gappssmtp.com header.b="bQ8jNBXA"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3yMFYF2q4yz9sPk for ; Wed, 25 Oct 2017 14:12:01 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751871AbdJYDL6 (ORCPT ); Tue, 24 Oct 2017 23:11:58 -0400 Received: from mail-pf0-f196.google.com ([209.85.192.196]:55093 "EHLO mail-pf0-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751806AbdJYDL4 (ORCPT ); Tue, 24 Oct 2017 23:11:56 -0400 Received: by mail-pf0-f196.google.com with SMTP id n89so21166794pfk.11 for ; Tue, 24 Oct 2017 20:11:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=netronome-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id; bh=MZ8YZkYHmNWiONhVlDDfk02nD60uXynzjWwg/o6bGAM=; b=bQ8jNBXA85r0fi4LNJEUVmHoSP9Uw2gdYYOgc9SKehVoptuqGM00l3xtP4x9bBQiF5 k1EV+yVFtV0efDqeWbMKx8KdcAJt4hTAxmD2RJ6CNGiPZJyM/ZnOWJaW9IEJbDsbEmNs FSdT7aoXrj+OSnOkCxgEuiqIY2U/aNy5cFPY4xmWRNloSRs02KkI7GHEvfqXEuPL/e3i bYRnpkwo+zdEqSnOCkX4mrIiGxIkP379+zOffAFtBFY9xTJpxLIgiX5gHIJS/CEL0h6X i7L48mdhViQaF8rTwUy5BkOws6PhwOmb0vKQNTrloIDbeRMmRtZVcRcwOfS71e47Zk+H 8X4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=MZ8YZkYHmNWiONhVlDDfk02nD60uXynzjWwg/o6bGAM=; b=LL9v/Jh/1MEsdb3VeJ3TjeMAvQrTt9GrhIAEYkRPQh3EhYI6m7p6X23HfUDkYdD5O/ 3+xOql+GqKje+QWrSJshZKPbgXKWejM9pofNcVTYQNiXo4tIA+T+QMg3iMpqR2KetnxR AIntI80dw0fO/WJynkXXcBICi1vgaSZ9qWOsme13Ihwcw4hrTiHfiTZOHpCCP+q9bgUJ iMTqor+uDZbRYtSww5jGdTELHTl/B38ZJFMt6cs10rHucybPc/LfL+0gar+Zt3ebGcpD 6/1pnSSn916Fz5uKbhrNhePL6EPhqRRk589U9A0fwUocKVqG39v8mSM5/pO+SsSSD+8q JvNQ== X-Gm-Message-State: AMCzsaWYOAfu8PNQ28We+SHM3EuIBTWEudOyo1wRIeIPHabKcjvMJthN ZIGOAuATSltYCYpKLbWFYKUf4Qee X-Google-Smtp-Source: ABhQp+SKJgosP4ZH9s6FzSfU4fRar1FQhFMuWvTxyKPLEGmousESJpeF0tqHKe11R08gl4d6lIFsqQ== X-Received: by 10.98.211.220 with SMTP id z89mr753764pfk.99.1508901115596; Tue, 24 Oct 2017 20:11:55 -0700 (PDT) Received: from jkicinski-Precision-T1700.netronome.com ([75.53.12.129]) by smtp.gmail.com with ESMTPSA id r64sm2654245pfg.25.2017.10.24.20.11.53 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 24 Oct 2017 20:11:54 -0700 (PDT) From: Jakub Kicinski To: netdev@vger.kernel.org Cc: oss-drivers@netronome.com, alexei.starovoitov@gmail.com, daniel@iogearbox.net, Quentin Monnet , Jakub Kicinski Subject: [PATCH net-next] tools: bpftool: try to mount bpffs if required for pinning objects Date: Tue, 24 Oct 2017 20:11:28 -0700 Message-Id: <20171025031128.13990-1-jakub.kicinski@netronome.com> X-Mailer: git-send-email 2.14.1 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Quentin Monnet One possible cause of failure for `bpftool {prog|map} pin * file FILE` is the FILE not being in an eBPF virtual file system (bpffs). In this case, make bpftool attempt to mount bpffs on the parent directory of the FILE. Then, if this operation is successful, try again to pin the object. The code for mnt_bpffs() is a copy of function bpf_mnt_fs() from iproute2 package (under lib/bpf.c, taken at commit 4b73d52f8a81), with modifications regarding handling of error messages. Signed-off-by: Quentin Monnet Signed-off-by: Jakub Kicinski Acked-by: Alexei Starovoitov --- tools/bpf/bpftool/common.c | 71 ++++++++++++++++++++++++++++++++++++++++------ tools/bpf/bpftool/main.h | 2 ++ 2 files changed, 65 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 #include #include +#include #include #include @@ -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) diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h index 2f94bed03a8d..d315d01be645 100644 --- a/tools/bpf/bpftool/main.h +++ b/tools/bpf/bpftool/main.h @@ -51,6 +51,8 @@ #define NEXT_ARGP() ({ (*argc)--; (*argv)++; if (*argc < 0) usage(); }) #define BAD_ARG() ({ p_err("what is '%s'?\n", *argv); -1; }) +#define ERR_MAX_LEN 1024 + #define BPF_TAG_FMT "%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx" #define HELP_SPEC_PROGRAM \