From patchwork Tue Apr 9 17:27:37 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stanislav Fomichev X-Patchwork-Id: 1082563 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@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; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.b="iz0uC5jd"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44dvPY0LvNz9sSQ for ; Wed, 10 Apr 2019 03:27:45 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726685AbfDIR1n (ORCPT ); Tue, 9 Apr 2019 13:27:43 -0400 Received: from mail-vk1-f201.google.com ([209.85.221.201]:44132 "EHLO mail-vk1-f201.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726512AbfDIR1m (ORCPT ); Tue, 9 Apr 2019 13:27:42 -0400 Received: by mail-vk1-f201.google.com with SMTP id f3so8677814vkb.11 for ; Tue, 09 Apr 2019 10:27:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:message-id:mime-version:subject:from:to:cc; bh=NYCMzd5qLaZVzWSIQyNmFsGM2SPPQWJoWBxuQisbDXY=; b=iz0uC5jdNa0F1pUfWiBFPPqWNuvc7MOZfoeol/NM39XfvjNWv4DqKgzyVOfjWGGS+4 fYZYAWm6/XVJAoLVx3jLnqhYn6pbDGQx451gmNI1ODg6IbxHux5IzjfipjEknSoln6FS ctiRJU+GuCv/XFTnLlVyFbXMVGdHnRdHxe4YQt0njGX5tEU+wF1UrCwcdGwS1ktzinSs VkecAo438MdHfP63ODMAWk3d9pmlt77vV3oMo0L1S2SGvbrItYGiCOJ7DeScZtp0unRv 45bjk/Hb+doFqGXZ5eHa8JO5PnK9tKdmO0EJEfpnVNUNxNxpvd/j8okTQIHPCoBpWzMB bVeg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:message-id:mime-version:subject:from:to:cc; bh=NYCMzd5qLaZVzWSIQyNmFsGM2SPPQWJoWBxuQisbDXY=; b=dBF6z3v8uXZUeVJYNchAi1ZeR1L03vVJHKWIGqShCnWX2w5PyaK1/Lx+JSsHLHJGuv MDvd4h4OElSrQzCIjaLI/w8ESsxmuOenphMZKpFF7kz9fQxfCgB0HcNSsyg+6jiG/x0U AzSF6pz4baUYY55Jn6bHmW9o2qbh5ViY8JkjZdC/Fk2FkApGVVl3bb6Si5p2s1HbUy+2 95Obzl/xtoRDy/bog7Ud0M8/Lf9aN9yUzLmEPFzpFxUuhWrJCUwDr/G/HiuqCvTpKemV GX5pN/6GaN21cYhVL67MOu1UKwRRQkPnVoQ6SxgIzR57a53tNOpJvTYTm9ta+oDRnxGJ OpWg== X-Gm-Message-State: APjAAAU8vzXC9ufMznknGxjL6lpg03db5q9PS3zW4CTIo0wMKANKn+9i /1iYYxwdX4Lfry4TRukyR175n5LDVKQRkLALmCNIcTnjQ2De45S9y1dfEW9dvEILOkuhGkVNDb7 d27lkRFF1/vbDVjAfMjiFw35F7jGQSxvATaacOZdtF0eoDRdcsCr0rA== X-Google-Smtp-Source: APXvYqwateBMlSafIrncmXfFWrKyz2SoFJ1SwIRoTzMeHUokkxN5p8nkg8LC+qx+FPzJYeixEjZ/Z+k= X-Received: by 2002:a67:df08:: with SMTP id s8mr4177362vsk.40.1554830861467; Tue, 09 Apr 2019 10:27:41 -0700 (PDT) Date: Tue, 9 Apr 2019 10:27:37 -0700 Message-Id: <20190409172739.242389-1-sdf@google.com> Mime-Version: 1.0 X-Mailer: git-send-email 2.21.0.392.gf8f6787159e-goog Subject: [PATCH bpf-next v3 1/3] bpf: support input __sk_buff context in BPF_PROG_TEST_RUN From: Stanislav Fomichev To: netdev@vger.kernel.org, bpf@vger.kernel.org Cc: davem@davemloft.net, ast@kernel.org, daniel@iogearbox.net, Stanislav Fomichev , Martin Lau Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org Add new set of arguments to bpf_attr for BPF_PROG_TEST_RUN: * ctx_in/ctx_size_in - input context * ctx_out/ctx_size_out - output context The intended use case is to pass some meta data to the test runs that operate on skb (this has being brought up on recent LPC). For programs that use bpf_prog_test_run_skb, support __sk_buff input and output. Initially, from input __sk_buff, copy _only_ cb and priority into skb, all other non-zero fields are prohibited (with EINVAL). If the user has set ctx_out/ctx_size_out, copy the potentially modified __sk_buff back to the userspace. We require all fields of input __sk_buff except the ones we explicitly support to be set to zero. The expectation is that in the future we might add support for more fields and we want to fail explicitly if the user runs the program on the kernel where we don't yet support them. The API is intentionally vague (i.e. we don't explicitly add __sk_buff to bpf_attr, but ctx_in) to potentially let other test_run types use this interface in the future (this can be xdp_md for xdp types for example). v3: * handle case where ctx_in is NULL, but ctx_out is not [Martin] * convert size==0 checks to ptr==NULL checks and add some extra ptr checks [Martin] v2: * Addressed comments from Martin Lau Cc: Martin Lau Signed-off-by: Stanislav Fomichev Acked-by: Martin KaFai Lau --- include/uapi/linux/bpf.h | 7 ++ kernel/bpf/syscall.c | 10 ++- net/bpf/test_run.c | 142 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 150 insertions(+), 9 deletions(-) diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h index 837024512baf..8e96f99cebf8 100644 --- a/include/uapi/linux/bpf.h +++ b/include/uapi/linux/bpf.h @@ -396,6 +396,13 @@ union bpf_attr { __aligned_u64 data_out; __u32 repeat; __u32 duration; + __u32 ctx_size_in; /* input: len of ctx_in */ + __u32 ctx_size_out; /* input/output: len of ctx_out + * returns ENOSPC if ctx_out + * is too small. + */ + __aligned_u64 ctx_in; + __aligned_u64 ctx_out; } test; struct { /* anonymous struct used by BPF_*_GET_*_ID */ diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 1d65e56594db..5bb963e8f9b0 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -1949,7 +1949,7 @@ static int bpf_prog_query(const union bpf_attr *attr, return cgroup_bpf_prog_query(attr, uattr); } -#define BPF_PROG_TEST_RUN_LAST_FIELD test.duration +#define BPF_PROG_TEST_RUN_LAST_FIELD test.ctx_out static int bpf_prog_test_run(const union bpf_attr *attr, union bpf_attr __user *uattr) @@ -1962,6 +1962,14 @@ static int bpf_prog_test_run(const union bpf_attr *attr, if (CHECK_ATTR(BPF_PROG_TEST_RUN)) return -EINVAL; + if ((attr->test.ctx_size_in && !attr->test.ctx_in) || + (!attr->test.ctx_size_in && attr->test.ctx_in)) + return -EINVAL; + + if ((attr->test.ctx_size_out && !attr->test.ctx_out) || + (!attr->test.ctx_size_out && attr->test.ctx_out)) + return -EINVAL; + prog = bpf_prog_get(attr->test.prog_fd); if (IS_ERR(prog)) return PTR_ERR(prog); diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c index fab142b796ef..2023d8841c6d 100644 --- a/net/bpf/test_run.c +++ b/net/bpf/test_run.c @@ -123,12 +123,125 @@ static void *bpf_test_init(const union bpf_attr *kattr, u32 size, return data; } +static void *bpf_ctx_init(const union bpf_attr *kattr, u32 max_size) +{ + void __user *data_in = u64_to_user_ptr(kattr->test.ctx_in); + void __user *data_out = u64_to_user_ptr(kattr->test.ctx_out); + u32 size = kattr->test.ctx_size_in; + void *data; + int err; + + if (!data_in && !data_out) + return NULL; + + data = kzalloc(max_size, GFP_USER); + if (!data) + return ERR_PTR(-ENOMEM); + + if (data_in) { + err = bpf_check_uarg_tail_zero(data_in, max_size, size); + if (err) { + kfree(data); + return ERR_PTR(err); + } + + if (copy_from_user(data, data_in, size)) { + kfree(data); + return ERR_PTR(-EFAULT); + } + } + return data; +} + +static int bpf_ctx_finish(const union bpf_attr *kattr, + union bpf_attr __user *uattr, const void *data, + u32 size) +{ + void __user *data_out = u64_to_user_ptr(kattr->test.ctx_out); + int err = -EFAULT; + u32 copy_size = size; + + if (!data || !data_out) + return 0; + + if (copy_size > kattr->test.ctx_size_out) { + copy_size = kattr->test.ctx_size_out; + err = -ENOSPC; + } + + if (copy_to_user(data_out, data, copy_size)) + goto out; + if (copy_to_user(&uattr->test.ctx_size_out, &size, sizeof(size))) + goto out; + if (err != -ENOSPC) + err = 0; +out: + return err; +} + +/** + * range_is_zero - test whether buffer is initialized + * @buf: buffer to check + * @from: check from this position + * @to: check up until (excluding) this position + * + * This function returns true if the there is a non-zero byte + * in the buf in the range [from,to). + */ +static inline bool range_is_zero(void *buf, size_t from, size_t to) +{ + return !memchr_inv((u8 *)buf + from, 0, to - from); +} + +static int convert___skb_to_skb(struct sk_buff *skb, struct __sk_buff *__skb) +{ + struct qdisc_skb_cb *cb = (struct qdisc_skb_cb *)skb->cb; + + if (!__skb) + return 0; + + /* make sure the fields we don't use are zeroed */ + if (!range_is_zero(__skb, 0, offsetof(struct __sk_buff, priority))) + return -EINVAL; + + /* priority is allowed */ + + if (!range_is_zero(__skb, offsetof(struct __sk_buff, priority) + + FIELD_SIZEOF(struct __sk_buff, priority), + offsetof(struct __sk_buff, cb))) + return -EINVAL; + + /* cb is allowed */ + + if (!range_is_zero(__skb, offsetof(struct __sk_buff, cb) + + FIELD_SIZEOF(struct __sk_buff, cb), + sizeof(struct __sk_buff))) + return -EINVAL; + + skb->priority = __skb->priority; + memcpy(&cb->data, __skb->cb, QDISC_CB_PRIV_LEN); + + return 0; +} + +static void convert_skb_to___skb(struct sk_buff *skb, struct __sk_buff *__skb) +{ + struct qdisc_skb_cb *cb = (struct qdisc_skb_cb *)skb->cb; + + if (!__skb) + return; + + __skb->priority = skb->priority; + memcpy(__skb->cb, &cb->data, QDISC_CB_PRIV_LEN); +} + int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr, union bpf_attr __user *uattr) { bool is_l2 = false, is_direct_pkt_access = false; u32 size = kattr->test.data_size_in; u32 repeat = kattr->test.repeat; + struct __sk_buff *ctx = NULL; u32 retval, duration; int hh_len = ETH_HLEN; struct sk_buff *skb; @@ -141,6 +254,12 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr, if (IS_ERR(data)) return PTR_ERR(data); + ctx = bpf_ctx_init(kattr, sizeof(struct __sk_buff)); + if (IS_ERR(ctx)) { + kfree(data); + return PTR_ERR(ctx); + } + switch (prog->type) { case BPF_PROG_TYPE_SCHED_CLS: case BPF_PROG_TYPE_SCHED_ACT: @@ -158,6 +277,7 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr, sk = kzalloc(sizeof(struct sock), GFP_USER); if (!sk) { kfree(data); + kfree(ctx); return -ENOMEM; } sock_net_set(sk, current->nsproxy->net_ns); @@ -166,6 +286,7 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr, skb = build_skb(data, 0); if (!skb) { kfree(data); + kfree(ctx); kfree(sk); return -ENOMEM; } @@ -180,32 +301,37 @@ int bpf_prog_test_run_skb(struct bpf_prog *prog, const union bpf_attr *kattr, __skb_push(skb, hh_len); if (is_direct_pkt_access) bpf_compute_data_pointers(skb); + ret = convert___skb_to_skb(skb, ctx); + if (ret) + goto out; ret = bpf_test_run(prog, skb, repeat, &retval, &duration); - if (ret) { - kfree_skb(skb); - kfree(sk); - return ret; - } + if (ret) + goto out; if (!is_l2) { if (skb_headroom(skb) < hh_len) { int nhead = HH_DATA_ALIGN(hh_len - skb_headroom(skb)); if (pskb_expand_head(skb, nhead, 0, GFP_USER)) { - kfree_skb(skb); - kfree(sk); - return -ENOMEM; + ret = -ENOMEM; + goto out; } } memset(__skb_push(skb, hh_len), 0, hh_len); } + convert_skb_to___skb(skb, ctx); size = skb->len; /* bpf program can never convert linear skb to non-linear */ if (WARN_ON_ONCE(skb_is_nonlinear(skb))) size = skb_headlen(skb); ret = bpf_test_finish(kattr, uattr, skb->data, size, retval, duration); + if (!ret) + ret = bpf_ctx_finish(kattr, uattr, ctx, + sizeof(struct __sk_buff)); +out: kfree_skb(skb); kfree(sk); + kfree(ctx); return ret; } From patchwork Tue Apr 9 17:27:38 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stanislav Fomichev X-Patchwork-Id: 1082565 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.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=bpf-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.b="IGg1GUgM"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44dvPZ4y68z9sSm for ; Wed, 10 Apr 2019 03:27:46 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726750AbfDIR1q (ORCPT ); Tue, 9 Apr 2019 13:27:46 -0400 Received: from mail-pg1-f201.google.com ([209.85.215.201]:41191 "EHLO mail-pg1-f201.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726690AbfDIR1o (ORCPT ); Tue, 9 Apr 2019 13:27:44 -0400 Received: by mail-pg1-f201.google.com with SMTP id v9so13070574pgg.8 for ; Tue, 09 Apr 2019 10:27:44 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=TPX6cTYh61RNjrelF8pt2tCkW6NVS4y5gHCKwdw0Nmw=; b=IGg1GUgMMSodCHRwQqKLG2MneJ5zjtfIC/bgrXbXc1qKkcftCYsNpKVS2eVbs0ozJz QsoHChVuRyA1mIU9D0pedAs3JftXdx9mbNwbvBENL0iL2ZljaRKa4sQwxnmTfpKcpfKl v2wZ9HI4ICOkONjcoD3EZ60pGIi+n9D5Z3mrwRLVhDxBK32FbbPMkhB0T924NsAXDdGL GyO1pQ1ouwi8u1AH+pnxZtOsJmqMwXTXjGh9I/wmCQ6vVuwIADuYmS0EPcpdblw6iOJh esrYCgycU8bWxQdcGJbp3hJez9N8IDyccg2Jzst2MIcDmyUsClzSB45w/BKq5/Xns4WU Q3Aw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=TPX6cTYh61RNjrelF8pt2tCkW6NVS4y5gHCKwdw0Nmw=; b=toNsFYmizK/UkhYvLvLcJHh1tvfR5s2Bs/yUwB+TVPYuKIzptFsw4IWhlH1CcMZBhA sZj4bgpIppHBiqC1Lk25xjjEflrLVC3Y93uLgT6/fwyOtfORLqlCcumtupJuiM+VA3UL 2dvkViVLS1HsRzgr5eRqnk7ACR6tnWbQgLqcX85fgKQ2C7x7gTN6trn23ldtAVECXMFs FQiACAbCtlFqKhlJ9VUoRjMCgSSudOCrRdeWU8t8EqZo018Q/nBOVXY8KnNsBv0F71TC En6YQTDLeG+lKwBTyyuJF84GbMqrvtrTAeD/aMb5wFrYWUmGh3FQL6wQVJ2wPkLI+9pW Vhvg== X-Gm-Message-State: APjAAAWNQkJrHMjkgtm2ICJr1uQIr0g4VrTvUAxnc4micZ83xtzdGDRT mqWMgSK0CTcLIFU4WAjuxK7kjKQ= X-Google-Smtp-Source: APXvYqwThwQ3T5W4utchgxzLL7cXC/7GRSkSRrHuGOGYEuhN3grWGshTmvep22riZyJUwaEJY4H1KyQ= X-Received: by 2002:a63:42c5:: with SMTP id p188mr805360pga.47.1554830863696; Tue, 09 Apr 2019 10:27:43 -0700 (PDT) Date: Tue, 9 Apr 2019 10:27:38 -0700 In-Reply-To: <20190409172739.242389-1-sdf@google.com> Message-Id: <20190409172739.242389-2-sdf@google.com> Mime-Version: 1.0 References: <20190409172739.242389-1-sdf@google.com> X-Mailer: git-send-email 2.21.0.392.gf8f6787159e-goog Subject: [PATCH bpf-next v3 2/3] libbpf: add support for ctx_{size, }_{in, out} in BPF_PROG_TEST_RUN From: Stanislav Fomichev To: netdev@vger.kernel.org, bpf@vger.kernel.org Cc: davem@davemloft.net, ast@kernel.org, daniel@iogearbox.net, Stanislav Fomichev , Martin Lau Sender: bpf-owner@vger.kernel.org Precedence: bulk List-Id: netdev.vger.kernel.org Support recently introduced input/output context for test runs. We extend only bpf_prog_test_run_xattr. bpf_prog_test_run is unextendable and left as is. Cc: Martin Lau Signed-off-by: Stanislav Fomichev Acked-by: Martin KaFai Lau --- tools/include/uapi/linux/bpf.h | 7 +++++++ tools/lib/bpf/bpf.c | 5 +++++ tools/lib/bpf/bpf.h | 5 +++++ 3 files changed, 17 insertions(+) diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h index 837024512baf..8e96f99cebf8 100644 --- a/tools/include/uapi/linux/bpf.h +++ b/tools/include/uapi/linux/bpf.h @@ -396,6 +396,13 @@ union bpf_attr { __aligned_u64 data_out; __u32 repeat; __u32 duration; + __u32 ctx_size_in; /* input: len of ctx_in */ + __u32 ctx_size_out; /* input/output: len of ctx_out + * returns ENOSPC if ctx_out + * is too small. + */ + __aligned_u64 ctx_in; + __aligned_u64 ctx_out; } test; struct { /* anonymous struct used by BPF_*_GET_*_ID */ diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index a1db869a6fda..d740da7ae1d3 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -545,10 +545,15 @@ int bpf_prog_test_run_xattr(struct bpf_prog_test_run_attr *test_attr) attr.test.data_out = ptr_to_u64(test_attr->data_out); attr.test.data_size_in = test_attr->data_size_in; attr.test.data_size_out = test_attr->data_size_out; + attr.test.ctx_in = ptr_to_u64(test_attr->ctx_in); + attr.test.ctx_out = ptr_to_u64(test_attr->ctx_out); + attr.test.ctx_size_in = test_attr->ctx_size_in; + attr.test.ctx_size_out = test_attr->ctx_size_out; attr.test.repeat = test_attr->repeat; ret = sys_bpf(BPF_PROG_TEST_RUN, &attr, sizeof(attr)); test_attr->data_size_out = attr.test.data_size_out; + test_attr->ctx_size_out = attr.test.ctx_size_out; test_attr->retval = attr.test.retval; test_attr->duration = attr.test.duration; return ret; diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h index e2c0df7b831f..385418a6d54b 100644 --- a/tools/lib/bpf/bpf.h +++ b/tools/lib/bpf/bpf.h @@ -135,6 +135,11 @@ struct bpf_prog_test_run_attr { * out: length of data_out */ __u32 retval; /* out: return code of the BPF program */ __u32 duration; /* out: average per repetition in ns */ + const void *ctx_in; /* optional */ + __u32 ctx_size_in; + void *ctx_out; /* optional */ + __u32 ctx_size_out; /* in: max length of ctx_out + * out: length of cxt_out */ }; LIBBPF_API int bpf_prog_test_run_xattr(struct bpf_prog_test_run_attr *test_attr); From patchwork Tue Apr 9 17:27:39 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stanislav Fomichev X-Patchwork-Id: 1082567 X-Patchwork-Delegate: bpf@iogearbox.net Return-Path: X-Original-To: incoming-bpf@patchwork.ozlabs.org Delivered-To: patchwork-incoming-bpf@bilbo.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=bpf-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=google.com header.i=@google.com header.b="k25hOwzp"; dkim-atps=neutral Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44dvPc44KJz9sSQ for ; Wed, 10 Apr 2019 03:27:48 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726708AbfDIR1s (ORCPT ); Tue, 9 Apr 2019 13:27:48 -0400 Received: from mail-qk1-f202.google.com ([209.85.222.202]:49769 "EHLO mail-qk1-f202.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726785AbfDIR1r (ORCPT ); Tue, 9 Apr 2019 13:27:47 -0400 Received: by mail-qk1-f202.google.com with SMTP id 23so15061877qkl.16 for ; Tue, 09 Apr 2019 10:27:46 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:in-reply-to:message-id:mime-version:references:subject:from:to :cc; bh=UGkvoUGvalrE4O9PVqzTvRKhxc7cE1P5JFCWJIKCuWs=; b=k25hOwzpBUAYswSu5bY3u2BQFNi2BlNtfkeHNl4OxNvbuNrgVmA7o6B5qNMNvvIClN yE4XfRHcHtLLM+4tTN28TeiOfEQFT0+mfoqwOfOR/2Pc+Jm8NA3Q5Pba8AivbUiCx6hF yirXoWUSn1HYadMB2HxWUiB+RLrU/sDcOyDa8N+n2wFl8XRTFNzbbVhCUqa9mVb+9WXt cffXtcc5jYaW8GdL1/kPQsbTYA/RciW0d5X8zeNKUxyhKwAXGlHqMG5Ys4GB4Pao8Q6R StGYJwNiPB0FIi3gg1qrvV8KreUTcEVT+xgxPPNn3iUKHy8vMtjUeuo8tYBedF4IG47c Kfxg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:in-reply-to:message-id:mime-version :references:subject:from:to:cc; bh=UGkvoUGvalrE4O9PVqzTvRKhxc7cE1P5JFCWJIKCuWs=; b=He7yRfqvqKyxa5FoA0rhDoFsrkhc14VjbLpS2VZ9qWBLsnjIn4P3CKYZ1G8xRpoGrK 7HwgSTgkCQKfcRyHxdFLgdr/bjlnnpnrGQB6fCqhVboexVz0jAI0W9Nk6DILkrmqk72c MOeLm+R59tH5AjFNwhy+JHrirEH9FP/WCogt6wVmzZfDedWe3UtUIYgSEDR8p9yh0BXj QwOrrjHN4wa0sQhAX6yL2dARvRZIbLZYyTN2rtzT5kMbUPQX3CKzEbeRcZPhihkWE4SI EEr7qPIrjnY0ddMIRgvdS+rHxq8qJs8z3fNqNtesDpAFjDZoiSd9oc2ARFSMIe/F5v0k ZPjA== X-Gm-Message-State: APjAAAXsZEnSfSHp8aROwVbZv2rzCqnWqG/hympr6ZQ5ujYgRaDs4d+/ gJKouKWnPHTJlYAxbdB0cJWhgiA= X-Google-Smtp-Source: APXvYqz7Sfl0RT+hHe8aiREQ9UEp6KD6b9m/kyk0SWszMhmI0ugQSxdhY3Z0acm4F/J+7CvRWhcMM5I= X-Received: by 2002:ac8:277d:: with SMTP id h58mr5011892qth.31.1554830866241; Tue, 09 Apr 2019 10:27:46 -0700 (PDT) Date: Tue, 9 Apr 2019 10:27:39 -0700 In-Reply-To: <20190409172739.242389-1-sdf@google.com> Message-Id: <20190409172739.242389-3-sdf@google.com> Mime-Version: 1.0 References: <20190409172739.242389-1-sdf@google.com> X-Mailer: git-send-email 2.21.0.392.gf8f6787159e-goog Subject: [PATCH bpf-next v3 3/3] selftests: bpf: add selftest for __sk_buff context in BPF_PROG_TEST_RUN From: Stanislav Fomichev To: netdev@vger.kernel.org, bpf@vger.kernel.org Cc: davem@davemloft.net, ast@kernel.org, daniel@iogearbox.net, Stanislav Fomichev , Martin Lau Sender: bpf-owner@vger.kernel.org Precedence: bulk List-Id: netdev.vger.kernel.org Simple test that sets cb to {1,2,3,4,5} and priority to 6, runs bpf program that fails if cb is not what we expect and increments cb[i] and priority. When the test finishes, we check that cb is now {2,3,4,5,6} and priority is 7. We also test the sanity checks: * ctx_in is provided, but ctx_size_in is zero (same for ctx_out/ctx_size_out) * unexpected non-zero fields in __sk_buff return EINVAL Cc: Martin Lau Signed-off-by: Stanislav Fomichev Acked-by: Martin KaFai Lau --- .../selftests/bpf/prog_tests/skb_ctx.c | 89 +++++++++++++++++++ .../selftests/bpf/progs/test_skb_ctx.c | 21 +++++ 2 files changed, 110 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/skb_ctx.c create mode 100644 tools/testing/selftests/bpf/progs/test_skb_ctx.c diff --git a/tools/testing/selftests/bpf/prog_tests/skb_ctx.c b/tools/testing/selftests/bpf/prog_tests/skb_ctx.c new file mode 100644 index 000000000000..e95baa32e277 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/skb_ctx.c @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: GPL-2.0 +#include + +void test_skb_ctx(void) +{ + struct __sk_buff skb = { + .cb[0] = 1, + .cb[1] = 2, + .cb[2] = 3, + .cb[3] = 4, + .cb[4] = 5, + .priority = 6, + }; + struct bpf_prog_test_run_attr tattr = { + .data_in = &pkt_v4, + .data_size_in = sizeof(pkt_v4), + .ctx_in = &skb, + .ctx_size_in = sizeof(skb), + .ctx_out = &skb, + .ctx_size_out = sizeof(skb), + }; + struct bpf_object *obj; + int err; + int i; + + err = bpf_prog_load("./test_skb_ctx.o", BPF_PROG_TYPE_SCHED_CLS, &obj, + &tattr.prog_fd); + if (CHECK_ATTR(err, "load", "err %d errno %d\n", err, errno)) + return; + + /* ctx_in != NULL, ctx_size_in == 0 */ + + tattr.ctx_size_in = 0; + err = bpf_prog_test_run_xattr(&tattr); + CHECK_ATTR(err == 0, "ctx_size_in", "err %d errno %d\n", err, errno); + tattr.ctx_size_in = sizeof(skb); + + /* ctx_out != NULL, ctx_size_out == 0 */ + + tattr.ctx_size_out = 0; + err = bpf_prog_test_run_xattr(&tattr); + CHECK_ATTR(err == 0, "ctx_size_out", "err %d errno %d\n", err, errno); + tattr.ctx_size_out = sizeof(skb); + + /* non-zero [len, tc_index] fields should be rejected*/ + + skb.len = 1; + err = bpf_prog_test_run_xattr(&tattr); + CHECK_ATTR(err == 0, "len", "err %d errno %d\n", err, errno); + skb.len = 0; + + skb.tc_index = 1; + err = bpf_prog_test_run_xattr(&tattr); + CHECK_ATTR(err == 0, "tc_index", "err %d errno %d\n", err, errno); + skb.tc_index = 0; + + /* non-zero [hash, sk] fields should be rejected */ + + skb.hash = 1; + err = bpf_prog_test_run_xattr(&tattr); + CHECK_ATTR(err == 0, "hash", "err %d errno %d\n", err, errno); + skb.hash = 0; + + skb.sk = (struct bpf_sock *)1; + err = bpf_prog_test_run_xattr(&tattr); + CHECK_ATTR(err == 0, "sk", "err %d errno %d\n", err, errno); + skb.sk = 0; + + err = bpf_prog_test_run_xattr(&tattr); + CHECK_ATTR(err != 0 || tattr.retval, + "run", + "err %d errno %d retval %d\n", + err, errno, tattr.retval); + + CHECK_ATTR(tattr.ctx_size_out != sizeof(skb), + "ctx_size_out", + "incorrect output size, want %lu have %u\n", + sizeof(skb), tattr.ctx_size_out); + + for (i = 0; i < 5; i++) + CHECK_ATTR(skb.cb[i] != i + 2, + "ctx_out_cb", + "skb->cb[i] == %d, expected %d\n", + skb.cb[i], i + 2); + CHECK_ATTR(skb.priority != 7, + "ctx_out_priority", + "skb->priority == %d, expected %d\n", + skb.priority, 7); +} diff --git a/tools/testing/selftests/bpf/progs/test_skb_ctx.c b/tools/testing/selftests/bpf/progs/test_skb_ctx.c new file mode 100644 index 000000000000..7a80960d7df1 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/test_skb_ctx.c @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include "bpf_helpers.h" + +int _version SEC("version") = 1; +char _license[] SEC("license") = "GPL"; + +SEC("skb_ctx") +int process(struct __sk_buff *skb) +{ + #pragma clang loop unroll(full) + for (int i = 0; i < 5; i++) { + if (skb->cb[i] != i + 1) + return 1; + skb->cb[i]++; + } + skb->priority++; + + return 0; +}