Skip to content

Commit 13e3c77

Browse files
committed
Daniel Borkmann says: ==================== pull-request: bpf 2022-12-16 We've added 7 non-merge commits during the last 2 day(s) which contain a total of 9 files changed, 119 insertions(+), 36 deletions(-). 1) Fix for recent syzkaller XDP dispatcher update splat, from Jiri Olsa. 2) Fix BPF program refcount leak in LSM attachment failure path, from Milan Landaverde. 3) Fix BPF program type in map compatibility check for fext, from Toke Høiland-Jørgensen. 4) Fix a BPF selftest compilation error under !CONFIG_SMP config, from Yonghong Song. 5) Fix CI to enable CONFIG_FUNCTION_ERROR_INJECTION after it got changed to a prompt, from Song Liu. 6) Various BPF documentation fixes for socket local storage, from Donald Hunter. * tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf: selftests/bpf: Add a test for using a cpumap from an freplace-to-XDP program bpf: Resolve fext program type when checking map compatibility bpf: Synchronize dispatcher update with bpf_dispatcher_xdp_func bpf: prevent leak of lsm program after failed attach selftests/bpf: Select CONFIG_FUNCTION_ERROR_INJECTION selftests/bpf: Fix a selftest compilation error with CONFIG_SMP=n docs/bpf: Reword docs for BPF_MAP_TYPE_SK_STORAGE ==================== Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
2 parents 68bb101 + f506439 commit 13e3c77

File tree

9 files changed

+119
-36
lines changed

9 files changed

+119
-36
lines changed

Documentation/bpf/map_sk_storage.rst

Lines changed: 30 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,12 @@ bpf_sk_storage_get()
3434
3535
void *bpf_sk_storage_get(struct bpf_map *map, void *sk, void *value, u64 flags)
3636
37-
Socket-local storage can be retrieved using the ``bpf_sk_storage_get()``
38-
helper. The helper gets the storage from ``sk`` that is associated with ``map``.
39-
If the ``BPF_LOCAL_STORAGE_GET_F_CREATE`` flag is used then
40-
``bpf_sk_storage_get()`` will create the storage for ``sk`` if it does not
41-
already exist. ``value`` can be used together with
42-
``BPF_LOCAL_STORAGE_GET_F_CREATE`` to initialize the storage value, otherwise it
43-
will be zero initialized. Returns a pointer to the storage on success, or
37+
Socket-local storage for ``map`` can be retrieved from socket ``sk`` using the
38+
``bpf_sk_storage_get()`` helper. If the ``BPF_LOCAL_STORAGE_GET_F_CREATE``
39+
flag is used then ``bpf_sk_storage_get()`` will create the storage for ``sk``
40+
if it does not already exist. ``value`` can be used together with
41+
``BPF_LOCAL_STORAGE_GET_F_CREATE`` to initialize the storage value, otherwise
42+
it will be zero initialized. Returns a pointer to the storage on success, or
4443
``NULL`` in case of failure.
4544

4645
.. note::
@@ -54,9 +53,9 @@ bpf_sk_storage_delete()
5453
5554
long bpf_sk_storage_delete(struct bpf_map *map, void *sk)
5655
57-
Socket-local storage can be deleted using the ``bpf_sk_storage_delete()``
58-
helper. The helper deletes the storage from ``sk`` that is identified by
59-
``map``. Returns ``0`` on success, or negative error in case of failure.
56+
Socket-local storage for ``map`` can be deleted from socket ``sk`` using the
57+
``bpf_sk_storage_delete()`` helper. Returns ``0`` on success, or negative
58+
error in case of failure.
6059

6160
User space
6261
----------
@@ -68,16 +67,20 @@ bpf_map_update_elem()
6867
6968
int bpf_map_update_elem(int map_fd, const void *key, const void *value, __u64 flags)
7069
71-
Socket-local storage for the socket identified by ``key`` belonging to
72-
``map_fd`` can be added or updated using the ``bpf_map_update_elem()`` libbpf
73-
function. ``key`` must be a pointer to a valid ``fd`` in the user space
74-
program. The ``flags`` parameter can be used to control the update behaviour:
70+
Socket-local storage for map ``map_fd`` can be added or updated locally to a
71+
socket using the ``bpf_map_update_elem()`` libbpf function. The socket is
72+
identified by a `socket` ``fd`` stored in the pointer ``key``. The pointer
73+
``value`` has the data to be added or updated to the socket ``fd``. The type
74+
and size of ``value`` should be the same as the value type of the map
75+
definition.
7576

76-
- ``BPF_ANY`` will create storage for ``fd`` or update existing storage.
77-
- ``BPF_NOEXIST`` will create storage for ``fd`` only if it did not already
78-
exist, otherwise the call will fail with ``-EEXIST``.
79-
- ``BPF_EXIST`` will update existing storage for ``fd`` if it already exists,
80-
otherwise the call will fail with ``-ENOENT``.
77+
The ``flags`` parameter can be used to control the update behaviour:
78+
79+
- ``BPF_ANY`` will create storage for `socket` ``fd`` or update existing storage.
80+
- ``BPF_NOEXIST`` will create storage for `socket` ``fd`` only if it did not
81+
already exist, otherwise the call will fail with ``-EEXIST``.
82+
- ``BPF_EXIST`` will update existing storage for `socket` ``fd`` if it already
83+
exists, otherwise the call will fail with ``-ENOENT``.
8184

8285
Returns ``0`` on success, or negative error in case of failure.
8386

@@ -88,10 +91,10 @@ bpf_map_lookup_elem()
8891
8992
int bpf_map_lookup_elem(int map_fd, const void *key, void *value)
9093
91-
Socket-local storage for the socket identified by ``key`` belonging to
92-
``map_fd`` can be retrieved using the ``bpf_map_lookup_elem()`` libbpf
93-
function. ``key`` must be a pointer to a valid ``fd`` in the user space
94-
program. Returns ``0`` on success, or negative error in case of failure.
94+
Socket-local storage for map ``map_fd`` can be retrieved from a socket using
95+
the ``bpf_map_lookup_elem()`` libbpf function. The storage is retrieved from
96+
the socket identified by a `socket` ``fd`` stored in the pointer
97+
``key``. Returns ``0`` on success, or negative error in case of failure.
9598

9699
bpf_map_delete_elem()
97100
~~~~~~~~~~~~~~~~~~~~~
@@ -100,9 +103,10 @@ bpf_map_delete_elem()
100103
101104
int bpf_map_delete_elem(int map_fd, const void *key)
102105
103-
Socket-local storage for the socket identified by ``key`` belonging to
104-
``map_fd`` can be deleted using the ``bpf_map_delete_elem()`` libbpf
105-
function. Returns ``0`` on success, or negative error in case of failure.
106+
Socket-local storage for map ``map_fd`` can be deleted from a socket using the
107+
``bpf_map_delete_elem()`` libbpf function. The storage is deleted from the
108+
socket identified by a `socket` ``fd`` stored in the pointer ``key``. Returns
109+
``0`` on success, or negative error in case of failure.
106110

107111
Examples
108112
========

kernel/bpf/core.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2092,6 +2092,7 @@ static unsigned int __bpf_prog_ret0_warn(const void *ctx,
20922092
bool bpf_prog_map_compatible(struct bpf_map *map,
20932093
const struct bpf_prog *fp)
20942094
{
2095+
enum bpf_prog_type prog_type = resolve_prog_type(fp);
20952096
bool ret;
20962097

20972098
if (fp->kprobe_override)
@@ -2102,12 +2103,12 @@ bool bpf_prog_map_compatible(struct bpf_map *map,
21022103
/* There's no owner yet where we could check for
21032104
* compatibility.
21042105
*/
2105-
map->owner.type = fp->type;
2106+
map->owner.type = prog_type;
21062107
map->owner.jited = fp->jited;
21072108
map->owner.xdp_has_frags = fp->aux->xdp_has_frags;
21082109
ret = true;
21092110
} else {
2110-
ret = map->owner.type == fp->type &&
2111+
ret = map->owner.type == prog_type &&
21112112
map->owner.jited == fp->jited &&
21122113
map->owner.xdp_has_frags == fp->aux->xdp_has_frags;
21132114
}

kernel/bpf/dispatcher.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,11 @@ static void bpf_dispatcher_update(struct bpf_dispatcher *d, int prev_num_progs)
125125

126126
__BPF_DISPATCHER_UPDATE(d, new ?: (void *)&bpf_dispatcher_nop_func);
127127

128+
/* Make sure all the callers executing the previous/old half of the
129+
* image leave it, so following update call can modify it safely.
130+
*/
131+
synchronize_rcu();
132+
128133
if (new)
129134
d->image_off = noff;
130135
}

kernel/bpf/syscall.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3518,9 +3518,9 @@ static int bpf_prog_attach(const union bpf_attr *attr)
35183518
case BPF_PROG_TYPE_LSM:
35193519
if (ptype == BPF_PROG_TYPE_LSM &&
35203520
prog->expected_attach_type != BPF_LSM_CGROUP)
3521-
return -EINVAL;
3522-
3523-
ret = cgroup_bpf_prog_attach(attr, ptype, prog);
3521+
ret = -EINVAL;
3522+
else
3523+
ret = cgroup_bpf_prog_attach(attr, ptype, prog);
35243524
break;
35253525
default:
35263526
ret = -EINVAL;

tools/testing/selftests/bpf/config

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ CONFIG_CRYPTO_USER_API_HASH=y
1616
CONFIG_DYNAMIC_FTRACE=y
1717
CONFIG_FPROBE=y
1818
CONFIG_FTRACE_SYSCALLS=y
19+
CONFIG_FUNCTION_ERROR_INJECTION=y
1920
CONFIG_FUNCTION_TRACER=y
2021
CONFIG_GENEVE=y
2122
CONFIG_IKCONFIG=y

tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
#include <network_helpers.h>
55
#include <bpf/btf.h>
66
#include "bind4_prog.skel.h"
7+
#include "freplace_progmap.skel.h"
8+
#include "xdp_dummy.skel.h"
79

810
typedef int (*test_cb)(struct bpf_object *obj);
911

@@ -500,6 +502,50 @@ static void test_fentry_to_cgroup_bpf(void)
500502
bind4_prog__destroy(skel);
501503
}
502504

505+
static void test_func_replace_progmap(void)
506+
{
507+
struct bpf_cpumap_val value = { .qsize = 1 };
508+
struct freplace_progmap *skel = NULL;
509+
struct xdp_dummy *tgt_skel = NULL;
510+
__u32 key = 0;
511+
int err;
512+
513+
skel = freplace_progmap__open();
514+
if (!ASSERT_OK_PTR(skel, "prog_open"))
515+
return;
516+
517+
tgt_skel = xdp_dummy__open_and_load();
518+
if (!ASSERT_OK_PTR(tgt_skel, "tgt_prog_load"))
519+
goto out;
520+
521+
err = bpf_program__set_attach_target(skel->progs.xdp_cpumap_prog,
522+
bpf_program__fd(tgt_skel->progs.xdp_dummy_prog),
523+
"xdp_dummy_prog");
524+
if (!ASSERT_OK(err, "set_attach_target"))
525+
goto out;
526+
527+
err = freplace_progmap__load(skel);
528+
if (!ASSERT_OK(err, "obj_load"))
529+
goto out;
530+
531+
/* Prior to fixing the kernel, loading the PROG_TYPE_EXT 'redirect'
532+
* program above will cause the map owner type of 'cpumap' to be set to
533+
* PROG_TYPE_EXT. This in turn will cause the bpf_map_update_elem()
534+
* below to fail, because the program we are inserting into the map is
535+
* of PROG_TYPE_XDP. After fixing the kernel, the initial ownership will
536+
* be correctly resolved to the *target* of the PROG_TYPE_EXT program
537+
* (i.e., PROG_TYPE_XDP) and the map update will succeed.
538+
*/
539+
value.bpf_prog.fd = bpf_program__fd(skel->progs.xdp_drop_prog);
540+
err = bpf_map_update_elem(bpf_map__fd(skel->maps.cpu_map),
541+
&key, &value, 0);
542+
ASSERT_OK(err, "map_update");
543+
544+
out:
545+
xdp_dummy__destroy(tgt_skel);
546+
freplace_progmap__destroy(skel);
547+
}
548+
503549
/* NOTE: affect other tests, must run in serial mode */
504550
void serial_test_fexit_bpf2bpf(void)
505551
{
@@ -525,4 +571,6 @@ void serial_test_fexit_bpf2bpf(void)
525571
test_func_replace_global_func();
526572
if (test__start_subtest("fentry_to_cgroup_bpf"))
527573
test_fentry_to_cgroup_bpf();
574+
if (test__start_subtest("func_replace_progmap"))
575+
test_func_replace_progmap();
528576
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include <linux/bpf.h>
3+
#include <bpf/bpf_helpers.h>
4+
5+
struct {
6+
__uint(type, BPF_MAP_TYPE_CPUMAP);
7+
__type(key, __u32);
8+
__type(value, struct bpf_cpumap_val);
9+
__uint(max_entries, 1);
10+
} cpu_map SEC(".maps");
11+
12+
SEC("xdp/cpumap")
13+
int xdp_drop_prog(struct xdp_md *ctx)
14+
{
15+
return XDP_DROP;
16+
}
17+
18+
SEC("freplace")
19+
int xdp_cpumap_prog(struct xdp_md *ctx)
20+
{
21+
return bpf_redirect_map(&cpu_map, 0, XDP_PASS);
22+
}
23+
24+
char _license[] SEC("license") = "GPL";

tools/testing/selftests/bpf/progs/rcu_read_lock.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -288,13 +288,13 @@ int nested_rcu_region(void *ctx)
288288
SEC("?fentry.s/" SYS_PREFIX "sys_getpgid")
289289
int task_untrusted_non_rcuptr(void *ctx)
290290
{
291-
struct task_struct *task, *last_wakee;
291+
struct task_struct *task, *group_leader;
292292

293293
task = bpf_get_current_task_btf();
294294
bpf_rcu_read_lock();
295-
/* the pointer last_wakee marked as untrusted */
296-
last_wakee = task->real_parent->last_wakee;
297-
(void)bpf_task_storage_get(&map_a, last_wakee, 0, 0);
295+
/* the pointer group_leader marked as untrusted */
296+
group_leader = task->real_parent->group_leader;
297+
(void)bpf_task_storage_get(&map_a, group_leader, 0, 0);
298298
bpf_rcu_read_unlock();
299299
return 0;
300300
}

tools/testing/selftests/bpf/progs/task_kfunc_failure.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ int BPF_PROG(task_kfunc_acquire_trusted_walked, struct task_struct *task, u64 cl
7373
struct task_struct *acquired;
7474

7575
/* Can't invoke bpf_task_acquire() on a trusted pointer obtained from walking a struct. */
76-
acquired = bpf_task_acquire(task->last_wakee);
76+
acquired = bpf_task_acquire(task->group_leader);
7777
bpf_task_release(acquired);
7878

7979
return 0;

0 commit comments

Comments
 (0)