All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Borkmann <daniel@iogearbox.net>
To: "Toke Høiland-Jørgensen" <toke@redhat.com>
Cc: Alexei Starovoitov <ast@kernel.org>,
	Martin KaFai Lau <kafai@fb.com>, Song Liu <songliubraving@fb.com>,
	Yonghong Song <yhs@fb.com>,
	Marek Majkowski <marek@cloudflare.com>,
	Lorenz Bauer <lmb@cloudflare.com>,
	Alan Maguire <alan.maguire@oracle.com>,
	Jesper Dangaard Brouer <brouer@redhat.com>,
	David Miller <davem@davemloft.net>,
	netdev@vger.kernel.org, bpf@vger.kernel.org
Subject: Re: [PATCH bpf-next v3 2/5] bpf: Add support for setting chain call sequence for programs
Date: Mon, 7 Oct 2019 22:38:55 +0200	[thread overview]
Message-ID: <20191007203855.GE27307@pc-66.home> (raw)
In-Reply-To: <157046883723.2092443.3902769602513209987.stgit@alrua-x1>

On Mon, Oct 07, 2019 at 07:20:37PM +0200, Toke Høiland-Jørgensen wrote:
> From: Toke Høiland-Jørgensen <toke@redhat.com>
> 
> This adds support for setting and deleting bpf chain call programs through
> a couple of new commands in the bpf() syscall. The CHAIN_ADD and CHAIN_DEL
> commands take two eBPF program fds and a return code, and install the
> 'next' program to be chain called after the 'prev' program if that program
> returns 'retcode'. A retcode of -1 means "wildcard", so that the program
> will be executed regardless of the previous program's return code.
> 
> 
> The syscall command names are based on Alexei's prog_chain example[0],
> which Alan helpfully rebased on current bpf-next. However, the logic and
> program storage is obviously adapted to the execution logic in the previous
> commit.
> 
> [0] https://git.kernel.org/pub/scm/linux/kernel/git/ast/bpf.git/commit/?h=prog_chain&id=f54f45d00f91e083f6aec2abe35b6f0be52ae85b&context=15
> 
> Signed-off-by: Alan Maguire <alan.maguire@oracle.com>
> Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
> ---
>  include/uapi/linux/bpf.h |   10 ++++++
>  kernel/bpf/syscall.c     |   78 ++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 88 insertions(+)
> 
> diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
> index 1ce80a227be3..b03c23963af8 100644
> --- a/include/uapi/linux/bpf.h
> +++ b/include/uapi/linux/bpf.h
> @@ -107,6 +107,9 @@ enum bpf_cmd {
>  	BPF_MAP_LOOKUP_AND_DELETE_ELEM,
>  	BPF_MAP_FREEZE,
>  	BPF_BTF_GET_NEXT_ID,
> +	BPF_PROG_CHAIN_ADD,
> +	BPF_PROG_CHAIN_DEL,
> +	BPF_PROG_CHAIN_GET,
>  };
>  
>  enum bpf_map_type {
> @@ -516,6 +519,13 @@ union bpf_attr {
>  		__u64		probe_offset;	/* output: probe_offset */
>  		__u64		probe_addr;	/* output: probe_addr */
>  	} task_fd_query;
> +
> +	struct { /* anonymous struct used by BPF_PROG_CHAIN_* commands */
> +		__u32		prev_prog_fd;
> +		__u32		next_prog_fd;
> +		__u32		retcode;
> +		__u32		next_prog_id;   /* output: prog_id */
> +	};
>  } __attribute__((aligned(8)));
>  
>  /* The description below is an attempt at providing documentation to eBPF
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index b8a203a05881..be8112e08a88 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
> @@ -2113,6 +2113,79 @@ static int bpf_prog_test_run(const union bpf_attr *attr,
>  	return ret;
>  }
>  
> +#define BPF_PROG_CHAIN_LAST_FIELD next_prog_id
> +
> +static int bpf_prog_chain(int cmd, const union bpf_attr *attr,
> +			  union bpf_attr __user *uattr)
> +{
> +	struct bpf_prog *prog, *next_prog, *old_prog;
> +	struct bpf_prog **array;
> +	int ret = -EOPNOTSUPP;
> +	u32 index, prog_id;
> +
> +	if (CHECK_ATTR(BPF_PROG_CHAIN))
> +		return -EINVAL;
> +
> +	/* Index 0 is wildcard, encoded as ~0 by userspace */
> +	if (attr->retcode == ((u32) ~0))
> +		index = 0;
> +	else
> +		index = attr->retcode + 1;
> +
> +	if (index >= BPF_NUM_CHAIN_SLOTS)
> +		return -E2BIG;
> +
> +	prog = bpf_prog_get(attr->prev_prog_fd);
> +	if (IS_ERR(prog))
> +		return PTR_ERR(prog);
> +
> +	/* If the chain_calls bit is not set, that's because the chain call flag
> +	 * was not set on program load, and so we can't support chain calls.
> +	 */
> +	if (!prog->chain_calls)
> +		goto out;
> +
> +	array = prog->aux->chain_progs;
> +
> +	switch (cmd) {
> +	case BPF_PROG_CHAIN_ADD:
> +		next_prog = bpf_prog_get(attr->next_prog_fd);
> +		if (IS_ERR(next_prog)) {
> +			ret = PTR_ERR(next_prog);
> +			break;
> +		}
> +		old_prog = xchg(array + index, next_prog);
> +		if (old_prog)
> +			bpf_prog_put(old_prog);
> +		ret = 0;
> +		break;

How are circular dependencies resolved here? Seems the situation is
not prevented, so progs unloaded via XDP won't get the __bpf_prog_free()
call where they then drop the references of all the other progs in the
chain.

> +	case BPF_PROG_CHAIN_DEL:
> +		old_prog = xchg(array + index, NULL);
> +		if (old_prog) {
> +			bpf_prog_put(old_prog);
> +			ret = 0;
> +		} else {
> +			ret = -ENOENT;
> +		}
> +		break;
> +	case BPF_PROG_CHAIN_GET:
> +		old_prog = READ_ONCE(array[index]);
> +		if (old_prog) {
> +			prog_id = old_prog->aux->id;
> +			if (put_user(prog_id, &uattr->next_prog_id))
> +				ret = -EFAULT;
> +			else
> +				ret = 0;
> +		} else
> +			ret = -ENOENT;
> +		break;
> +	}
> +
> +out:
> +	bpf_prog_put(prog);
> +	return ret;
> +}
> +
>  #define BPF_OBJ_GET_NEXT_ID_LAST_FIELD next_id
>  
>  static int bpf_obj_get_next_id(const union bpf_attr *attr,
> @@ -2885,6 +2958,11 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz
>  	case BPF_PROG_TEST_RUN:
>  		err = bpf_prog_test_run(&attr, uattr);
>  		break;
> +	case BPF_PROG_CHAIN_ADD:
> +	case BPF_PROG_CHAIN_DEL:
> +	case BPF_PROG_CHAIN_GET:
> +		err = bpf_prog_chain(cmd, &attr, uattr);
> +		break;
>  	case BPF_PROG_GET_NEXT_ID:
>  		err = bpf_obj_get_next_id(&attr, uattr,
>  					  &prog_idr, &prog_idr_lock);
> 

  reply	other threads:[~2019-10-07 20:39 UTC|newest]

Thread overview: 61+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-10-07 17:20 [PATCH bpf-next v3 0/5] xdp: Support multiple programs on a single interface through chain calls Toke Høiland-Jørgensen
2019-10-07 17:20 ` [PATCH bpf-next v3 1/5] bpf: Support chain calling multiple BPF programs after each other Toke Høiland-Jørgensen
2019-10-07 20:42   ` Alexei Starovoitov
2019-10-08  8:07     ` Toke Høiland-Jørgensen
2019-10-09  1:51       ` Alexei Starovoitov
2019-10-09  8:03         ` Toke Høiland-Jørgensen
2019-10-10  4:41           ` Alexei Starovoitov
2019-10-14 12:35             ` Toke Høiland-Jørgensen
2019-10-14 17:08               ` John Fastabend
2019-10-14 18:48                 ` Toke Høiland-Jørgensen
2019-10-15 16:30                   ` Edward Cree
2019-10-15 16:42                     ` Toke Høiland-Jørgensen
2019-10-15 18:33                       ` Edward Cree
2019-10-17 12:11                         ` Toke Høiland-Jørgensen
2019-10-22 17:27                           ` Edward Cree
2019-10-22 18:07                             ` Toke Høiland-Jørgensen
2019-11-12  2:51                               ` static and dynamic linking. Was: [PATCH bpf-next v3 1/5] bpf: Support chain calling multiple BPF Alexei Starovoitov
2019-11-12 16:20                                 ` Toke Høiland-Jørgensen
2019-11-12 19:52                                   ` Alexei Starovoitov
2019-11-12 21:25                                     ` Edward Cree
2019-11-12 23:18                                       ` Alexei Starovoitov
2019-11-13 18:30                                         ` Edward Cree
2019-11-13 18:51                                           ` Andrii Nakryiko
2019-11-15  2:13                                           ` Alexei Starovoitov
2019-11-15 16:56                                             ` John Fastabend
2019-11-12 23:25                                     ` John Fastabend
2019-11-13  0:21                                       ` Alexei Starovoitov
2019-11-13  5:33                                         ` John Fastabend
2019-11-15  1:50                                           ` Alexei Starovoitov
2019-11-15 16:39                                             ` John Fastabend
2019-11-14 15:41                                     ` Toke Høiland-Jørgensen
2019-11-12 16:32                                 ` Edward Cree
2019-11-15 11:48                                 ` Lorenz Bauer
2019-11-15 23:02                                   ` Alexei Starovoitov
2019-11-18 13:29                                     ` Lorenz Bauer
2019-10-21 23:51                         ` [PATCH bpf-next v3 1/5] bpf: Support chain calling multiple BPF programs after each other Edward Cree
2019-10-16  2:28               ` Alexei Starovoitov
2019-10-16  8:27                 ` Jesper Dangaard Brouer
2019-10-16 10:35                   ` Daniel Borkmann
2019-10-16 11:16                     ` Toke Høiland-Jørgensen
2019-10-16 13:51                 ` Toke Høiland-Jørgensen
2019-10-19 20:09                   ` bpf indirect calls Alexei Starovoitov
2019-10-20 10:58                     ` Toke Høiland-Jørgensen
2019-10-25 16:30                       ` Alexei Starovoitov
2019-10-27 12:15                         ` Toke Høiland-Jørgensen
2023-09-27 13:27                     ` Matt Bobrowski
2023-09-29 21:06                       ` Alexei Starovoitov
2023-10-02 18:50                         ` Barret Rhoden
2023-10-06  9:36                         ` Matt Bobrowski
2023-10-06 18:49                           ` Alexei Starovoitov
2023-10-19 12:28                             ` Matt Bobrowski
2019-10-09 10:19         ` [PATCH bpf-next v3 1/5] bpf: Support chain calling multiple BPF programs after each other Jesper Dangaard Brouer
2019-10-09 17:57           ` Alexei Starovoitov
2019-10-07 17:20 ` [PATCH bpf-next v3 2/5] bpf: Add support for setting chain call sequence for programs Toke Høiland-Jørgensen
2019-10-07 20:38   ` Daniel Borkmann [this message]
2019-10-08  8:09     ` Toke Høiland-Jørgensen
2019-10-07 17:20 ` [PATCH bpf-next v3 3/5] tools: Update bpf.h header for program chain calls Toke Høiland-Jørgensen
2019-10-07 17:20 ` [PATCH bpf-next v3 4/5] libbpf: Add syscall wrappers for BPF_PROG_CHAIN_* commands Toke Høiland-Jørgensen
2019-10-07 17:20 ` [PATCH bpf-next v3 5/5] selftests: Add tests for XDP chain calls Toke Høiland-Jørgensen
2019-10-07 18:58 ` [PATCH bpf-next v3 0/5] xdp: Support multiple programs on a single interface through " John Fastabend
2019-10-08  8:42   ` Toke Høiland-Jørgensen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191007203855.GE27307@pc-66.home \
    --to=daniel@iogearbox.net \
    --cc=alan.maguire@oracle.com \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=brouer@redhat.com \
    --cc=davem@davemloft.net \
    --cc=kafai@fb.com \
    --cc=lmb@cloudflare.com \
    --cc=marek@cloudflare.com \
    --cc=netdev@vger.kernel.org \
    --cc=songliubraving@fb.com \
    --cc=toke@redhat.com \
    --cc=yhs@fb.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.