Commit e459f49b authored by Mariusz Dudek's avatar Mariusz Dudek Committed by Alexei Starovoitov

libbpf: Separate XDP program load with xsk socket creation

Add support for separation of eBPF program load and xsk socket
creation.

This is needed for use-case when you want to privide as little
privileges as possible to the data plane application that will
handle xsk socket creation and incoming traffic.

With this patch the data entity container can be run with only
CAP_NET_RAW capability to fulfill its purpose of creating xsk
socket and handling packages. In case your umem is larger or
equal process limit for MEMLOCK you need either increase the
limit or CAP_IPC_LOCK capability.

To resolve privileges issue two APIs are introduced:

- xsk_setup_xdp_prog - loads the built in XDP program. It can
also return xsks_map_fd which is needed by unprivileged process
to update xsks_map with AF_XDP socket "fd"

- xsk_socket__update_xskmap - inserts an AF_XDP socket into an xskmap
for a particular xsk_socket
Signed-off-by: default avatarMariusz Dudek <mariuszx.dudek@intel.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Acked-by: default avatarMagnus Karlsson <magnus.karlsson@intel.com>
Link: https://lore.kernel.org/bpf/20201203090546.11976-2-mariuszx.dudek@intel.com
parent 22e8ebe3
...@@ -346,4 +346,6 @@ LIBBPF_0.3.0 { ...@@ -346,4 +346,6 @@ LIBBPF_0.3.0 {
btf__parse_split; btf__parse_split;
btf__new_empty_split; btf__new_empty_split;
btf__new_split; btf__new_split;
xsk_setup_xdp_prog;
xsk_socket__update_xskmap;
} LIBBPF_0.2.0; } LIBBPF_0.2.0;
...@@ -566,8 +566,35 @@ static int xsk_set_bpf_maps(struct xsk_socket *xsk) ...@@ -566,8 +566,35 @@ static int xsk_set_bpf_maps(struct xsk_socket *xsk)
&xsk->fd, 0); &xsk->fd, 0);
} }
static int xsk_setup_xdp_prog(struct xsk_socket *xsk) static int xsk_create_xsk_struct(int ifindex, struct xsk_socket *xsk)
{ {
char ifname[IFNAMSIZ];
struct xsk_ctx *ctx;
char *interface;
ctx = calloc(1, sizeof(*ctx));
if (!ctx)
return -ENOMEM;
interface = if_indextoname(ifindex, &ifname[0]);
if (!interface) {
free(ctx);
return -errno;
}
ctx->ifindex = ifindex;
strncpy(ctx->ifname, ifname, IFNAMSIZ - 1);
ctx->ifname[IFNAMSIZ - 1] = 0;
xsk->ctx = ctx;
return 0;
}
static int __xsk_setup_xdp_prog(struct xsk_socket *_xdp,
int *xsks_map_fd)
{
struct xsk_socket *xsk = _xdp;
struct xsk_ctx *ctx = xsk->ctx; struct xsk_ctx *ctx = xsk->ctx;
__u32 prog_id = 0; __u32 prog_id = 0;
int err; int err;
...@@ -584,8 +611,7 @@ static int xsk_setup_xdp_prog(struct xsk_socket *xsk) ...@@ -584,8 +611,7 @@ static int xsk_setup_xdp_prog(struct xsk_socket *xsk)
err = xsk_load_xdp_prog(xsk); err = xsk_load_xdp_prog(xsk);
if (err) { if (err) {
xsk_delete_bpf_maps(xsk); goto err_load_xdp_prog;
return err;
} }
} else { } else {
ctx->prog_fd = bpf_prog_get_fd_by_id(prog_id); ctx->prog_fd = bpf_prog_get_fd_by_id(prog_id);
...@@ -598,15 +624,29 @@ static int xsk_setup_xdp_prog(struct xsk_socket *xsk) ...@@ -598,15 +624,29 @@ static int xsk_setup_xdp_prog(struct xsk_socket *xsk)
} }
} }
if (xsk->rx) if (xsk->rx) {
err = xsk_set_bpf_maps(xsk); err = xsk_set_bpf_maps(xsk);
if (err) { if (err) {
xsk_delete_bpf_maps(xsk); if (!prog_id) {
goto err_set_bpf_maps;
} else {
close(ctx->prog_fd); close(ctx->prog_fd);
return err; return err;
} }
}
}
if (xsks_map_fd)
*xsks_map_fd = ctx->xsks_map_fd;
return 0; return 0;
err_set_bpf_maps:
close(ctx->prog_fd);
bpf_set_link_xdp_fd(ctx->ifindex, -1, 0);
err_load_xdp_prog:
xsk_delete_bpf_maps(xsk);
return err;
} }
static struct xsk_ctx *xsk_get_ctx(struct xsk_umem *umem, int ifindex, static struct xsk_ctx *xsk_get_ctx(struct xsk_umem *umem, int ifindex,
...@@ -689,6 +729,40 @@ static struct xsk_ctx *xsk_create_ctx(struct xsk_socket *xsk, ...@@ -689,6 +729,40 @@ static struct xsk_ctx *xsk_create_ctx(struct xsk_socket *xsk,
return ctx; return ctx;
} }
static void xsk_destroy_xsk_struct(struct xsk_socket *xsk)
{
free(xsk->ctx);
free(xsk);
}
int xsk_socket__update_xskmap(struct xsk_socket *xsk, int fd)
{
xsk->ctx->xsks_map_fd = fd;
return xsk_set_bpf_maps(xsk);
}
int xsk_setup_xdp_prog(int ifindex, int *xsks_map_fd)
{
struct xsk_socket *xsk;
int res;
xsk = calloc(1, sizeof(*xsk));
if (!xsk)
return -ENOMEM;
res = xsk_create_xsk_struct(ifindex, xsk);
if (res) {
free(xsk);
return -EINVAL;
}
res = __xsk_setup_xdp_prog(xsk, xsks_map_fd);
xsk_destroy_xsk_struct(xsk);
return res;
}
int xsk_socket__create_shared(struct xsk_socket **xsk_ptr, int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
const char *ifname, const char *ifname,
__u32 queue_id, struct xsk_umem *umem, __u32 queue_id, struct xsk_umem *umem,
...@@ -838,7 +912,7 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr, ...@@ -838,7 +912,7 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr,
ctx->prog_fd = -1; ctx->prog_fd = -1;
if (!(xsk->config.libbpf_flags & XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD)) { if (!(xsk->config.libbpf_flags & XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD)) {
err = xsk_setup_xdp_prog(xsk); err = __xsk_setup_xdp_prog(xsk, NULL);
if (err) if (err)
goto out_mmap_tx; goto out_mmap_tx;
} }
......
...@@ -204,6 +204,11 @@ struct xsk_umem_config { ...@@ -204,6 +204,11 @@ struct xsk_umem_config {
__u32 flags; __u32 flags;
}; };
LIBBPF_API int xsk_setup_xdp_prog(int ifindex,
int *xsks_map_fd);
LIBBPF_API int xsk_socket__update_xskmap(struct xsk_socket *xsk,
int xsks_map_fd);
/* Flags for the libbpf_flags field. */ /* Flags for the libbpf_flags field. */
#define XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD (1 << 0) #define XSK_LIBBPF_FLAGS__INHIBIT_PROG_LOAD (1 << 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment