History

Merge tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf

Daniel Borkmann says: ==================== bpf 2022-11-04 We've added 8 non-merge commits during the last 3 day(s) which contain a total of 10 files changed, 113 insertions(+), 16 deletions(-). The main changes are: 1) Fix memory leak upon allocation failure in BPF verifier's stack state tracking, from Kees Cook. 2) Fix address leakage when BPF progs release reference to an object, from Youlin Li. 3) Fix BPF CI breakage from buggy in.h uapi header dependency, from Andrii Nakryiko. 4) Fix bpftool pin sub-command's argument parsing, from Pu Lehui. 5) Fix BPF sockmap lockdep warning by cancelling psock work outside of socket lock, from Cong Wang. 6) Follow-up for BPF sockmap to fix sk_forward_alloc accounting, from Wang Yufen. bpf-for-netdev * tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf: selftests/bpf: Add verifier test for release_reference() bpf: Fix wrong reg type conversion in release_reference() bpf, sock_map: Move cancel_work_sync() out of sock lock tools/headers: Pull in stddef.h to uapi to fix BPF selftests build in CI net/ipv4: Fix linux/in.h header dependencies bpftool: Fix NULL pointer dereference when pin {PROG, MAP, LINK} without FILE bpf, sockmap: Fix the sk->sk_forward_alloc warning of sk_stream_kill_queues bpf, verifier: Fix memory leak in array reallocation for stack state ====================

Jakub Kicinski committed 4 years ago

Commit f2c24be2 parents 9521c9d 475244f10 files · +113 −16Browse files

Unified · Split

10 files
  1. include/linux/skmsg.h +1 −1
  2. include/uapi/linux/in.h +1 −0
  3. kernel/bpf/verifier.c +13 −4
  4. net/core/skmsg.c +2 −5
  5. net/core/sock_map.c +4 −3
  6. net/ipv4/tcp_bpf.c +5 −3
  7. tools/bpf/bpftool/common.c +3 −0
  8. tools/include/uapi/linux/in.h +1 −0
  9. tools/include/uapi/linux/stddef.h +47 −0
  10. tools/testing/selftests/bpf/verifier/ref_tracking.c +36 −0
include/linux/skmsg.h+1−1
@@ -376,7 +376,7 @@ static inline void sk_psock_report_error(struct sk_psock *psock, int err) · 375 unmodified lines
376376 }
377377
378378 struct sk_psock *sk_psock_init(struct sock *sk, int node);
379−void sk_psock_stop(struct sk_psock *psock, bool wait);
379+void sk_psock_stop(struct sk_psock *psock);
380380
381381 #if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)
382382 int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock);
include/uapi/linux/in.h+1−0
@@ -20,6 +20,7 @@ · 19 unmodified lines
2020 #define _UAPI_LINUX_IN_H
2121
2222 #include <linux/types.h>
23+#include <linux/stddef.h>
2324 #include <linux/libc-compat.h>
2425 #include <linux/socket.h>
2526
kernel/bpf/verifier.c+13−4
@@ -1027,12 +1027,17 @@ out: · 1026 unmodified lines
10271027 */
10281028 static void *realloc_array(void *arr, size_t old_n, size_t new_n, size_t size)
10291029 {
1030+ void *new_arr;
1031+
10301032 if (!new_n || old_n == new_n)
10311033 goto out;
10321034
1033− arr = krealloc_array(arr, new_n, size, GFP_KERNEL);
1034− if (!arr)
1035+ new_arr = krealloc_array(arr, new_n, size, GFP_KERNEL);
1036+ if (!new_arr) {
1037+ kfree(arr);
10351038 return NULL;
1039+ }
1040+ arr = new_arr;
10361041
10371042 if (new_n > old_n)
10381043 memset(arr + old_n * size, 0, (new_n - old_n) * size);
@@ -6618,8 +6623,12 @@ static int release_reference(struct bpf_verifier_env *env, · 5579 unmodified lines
66186623 return err;
66196624
66206625 bpf_for_each_reg_in_vstate(env->cur_state, state, reg, ({
6621− if (reg->ref_obj_id == ref_obj_id)
6622− __mark_reg_unknown(env, reg);
6626+ if (reg->ref_obj_id == ref_obj_id) {
6627+ if (!env->allow_ptr_leaks)
6628+ __mark_reg_not_init(env, reg);
6629+ else
6630+ __mark_reg_unknown(env, reg);
6631+ }
66236632 }));
66246633
66256634 return 0;
net/core/skmsg.c+2−5
@@ -803,16 +803,13 @@ static void sk_psock_link_destroy(struct sk_psock *psock) · 802 unmodified lines
803803 }
804804 }
805805
806−void sk_psock_stop(struct sk_psock *psock, bool wait)
806+void sk_psock_stop(struct sk_psock *psock)
807807 {
808808 spin_lock_bh(&psock->ingress_lock);
809809 sk_psock_clear_state(psock, SK_PSOCK_TX_ENABLED);
810810 sk_psock_cork_free(psock);
811811 __sk_psock_zap_ingress(psock);
812812 spin_unlock_bh(&psock->ingress_lock);
813−
814− if (wait)
815− cancel_work_sync(&psock->work);
816813 }
817814
818815 static void sk_psock_done_strp(struct sk_psock *psock);
@@ -850,7 +847,7 @@ void sk_psock_drop(struct sock *sk, struct sk_psock *psock) · 31 unmodified lines
850847 sk_psock_stop_verdict(sk, psock);
851848 write_unlock_bh(&sk->sk_callback_lock);
852849
853− sk_psock_stop(psock, false);
850+ sk_psock_stop(psock);
854851
855852 INIT_RCU_WORK(&psock->rwork, sk_psock_destroy);
856853 queue_rcu_work(system_wq, &psock->rwork);
net/core/sock_map.c+4−3
@@ -1596,7 +1596,7 @@ void sock_map_destroy(struct sock *sk) · 1595 unmodified lines
15961596 saved_destroy = psock->saved_destroy;
15971597 sock_map_remove_links(sk, psock);
15981598 rcu_read_unlock();
1599− sk_psock_stop(psock, false);
1599+ sk_psock_stop(psock);
16001600 sk_psock_put(sk, psock);
16011601 saved_destroy(sk);
16021602 }
@@ -1619,9 +1619,10 @@ void sock_map_close(struct sock *sk, long timeout) · 16 unmodified lines
16191619 saved_close = psock->saved_close;
16201620 sock_map_remove_links(sk, psock);
16211621 rcu_read_unlock();
1622− sk_psock_stop(psock, true);
1623− sk_psock_put(sk, psock);
1622+ sk_psock_stop(psock);
16241623 release_sock(sk);
1624+ cancel_work_sync(&psock->work);
1625+ sk_psock_put(sk, psock);
16251626 saved_close(sk, timeout);
16261627 }
16271628 EXPORT_SYMBOL_GPL(sock_map_close);
net/ipv4/tcp_bpf.c+5−3
@@ -278,7 +278,7 @@ static int tcp_bpf_send_verdict(struct sock *sk, struct sk_psock *psock, · 277 unmodified lines
278278 {
279279 bool cork = false, enospc = sk_msg_full(msg);
280280 struct sock *sk_redir;
281− u32 tosend, delta = 0;
281+ u32 tosend, origsize, sent, delta = 0;
282282 u32 eval = __SK_NONE;
283283 int ret;
284284
@@ -333,10 +333,12 @@ more_data: · 48 unmodified lines
333333 cork = true;
334334 psock->cork = NULL;
335335 }
336− sk_msg_return(sk, msg, msg->sg.size);
336+ sk_msg_return(sk, msg, tosend);
337337 release_sock(sk);
338338
339+ origsize = msg->sg.size;
339340 ret = tcp_bpf_sendmsg_redir(sk_redir, msg, tosend, flags);
341+ sent = origsize - msg->sg.size;
340342
341343 if (eval == __SK_REDIRECT)
342344 sock_put(sk_redir);
@@ -375,7 +377,7 @@ more_data: · 32 unmodified lines
375377 msg->sg.data[msg->sg.start].page_link &&
376378 msg->sg.data[msg->sg.start].length) {
377379 if (eval == __SK_REDIRECT)
378− sk_mem_charge(sk, msg->sg.size);
380+ sk_mem_charge(sk, tosend - sent);
379381 goto more_data;
380382 }
381383 }
tools/bpf/bpftool/common.c+3−0
@@ -300,6 +300,9 @@ int do_pin_any(int argc, char **argv, int (*get_fd)(int *, char ***)) · 299 unmodified lines
300300 int err;
301301 int fd;
302302
303+ if (!REQ_ARGS(3))
304+ return -EINVAL;
305+
303306 fd = get_fd(&argc, &argv);
304307 if (fd < 0)
305308 return fd;
tools/include/uapi/linux/in.h+1−0
@@ -20,6 +20,7 @@ · 19 unmodified lines
2020 #define _UAPI_LINUX_IN_H
2121
2222 #include <linux/types.h>
23+#include <linux/stddef.h>
2324 #include <linux/libc-compat.h>
2425 #include <linux/socket.h>
2526
tools/include/uapi/linux/stddef.h+47−0
@@ -0,0 +1,47 @@
1+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
2+#ifndef _LINUX_STDDEF_H
3+#define _LINUX_STDDEF_H
4+
5+
6+
7+#ifndef __always_inline
8+#define __always_inline __inline__
9+#endif
10+
11+/**
12+ * __struct_group() - Create a mirrored named and anonyomous struct
13+ *
14+ * @TAG: The tag name for the named sub-struct (usually empty)
15+ * @NAME: The identifier name of the mirrored sub-struct
16+ * @ATTRS: Any struct attributes (usually empty)
17+ * @MEMBERS: The member declarations for the mirrored structs
18+ *
19+ * Used to create an anonymous union of two structs with identical layout
20+ * and size: one anonymous and one named. The former's members can be used
21+ * normally without sub-struct naming, and the latter can be used to
22+ * reason about the start, end, and size of the group of struct members.
23+ * The named struct can also be explicitly tagged for layer reuse, as well
24+ * as both having struct attributes appended.
25+ */
26+#define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \
27+ union { \
28+ struct { MEMBERS } ATTRS; \
29+ struct TAG { MEMBERS } ATTRS NAME; \
30+ }
31+
32+/**
33+ * __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union
34+ *
35+ * @TYPE: The type of each flexible array element
36+ * @NAME: The name of the flexible array member
37+ *
38+ * In order to have a flexible array member in a union or alone in a
39+ * struct, it needs to be wrapped in an anonymous struct with at least 1
40+ * named member, but that member can be empty.
41+ */
42+#define __DECLARE_FLEX_ARRAY(TYPE, NAME) \
43+ struct { \
44+ struct { } __empty_ ## NAME; \
45+ TYPE NAME[]; \
46+ }
47+#endif
tools/testing/selftests/bpf/verifier/ref_tracking.c+36−0
@@ -1044,3 +1044,39 @@ · 1043 unmodified lines
10441044 .result_unpriv = REJECT,
10451045 .errstr_unpriv = "unknown func",
10461046 },
1047+{
1048+ "reference tracking: try to leak released ptr reg",
1049+ .insns = {
1050+ BPF_MOV64_IMM(BPF_REG_0, 0),
1051+ BPF_STX_MEM(BPF_W, BPF_REG_10, BPF_REG_0, -4),
1052+ BPF_MOV64_REG(BPF_REG_2, BPF_REG_10),
1053+ BPF_ALU64_IMM(BPF_ADD, BPF_REG_2, -4),
1054+ BPF_LD_MAP_FD(BPF_REG_1, 0),
1055+ BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
1056+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
1057+ BPF_EXIT_INSN(),
1058+ BPF_MOV64_REG(BPF_REG_9, BPF_REG_0),
1059+
1060+ BPF_MOV64_IMM(BPF_REG_0, 0),
1061+ BPF_LD_MAP_FD(BPF_REG_1, 0),
1062+ BPF_MOV64_IMM(BPF_REG_2, 8),
1063+ BPF_MOV64_IMM(BPF_REG_3, 0),
1064+ BPF_EMIT_CALL(BPF_FUNC_ringbuf_reserve),
1065+ BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
1066+ BPF_EXIT_INSN(),
1067+ BPF_MOV64_REG(BPF_REG_8, BPF_REG_0),
1068+
1069+ BPF_MOV64_REG(BPF_REG_1, BPF_REG_8),
1070+ BPF_MOV64_IMM(BPF_REG_2, 0),
1071+ BPF_EMIT_CALL(BPF_FUNC_ringbuf_discard),
1072+ BPF_MOV64_IMM(BPF_REG_0, 0),
1073+
1074+ BPF_STX_MEM(BPF_DW, BPF_REG_9, BPF_REG_8, 0),
1075+ BPF_EXIT_INSN()
1076+ },
1077+ .fixup_map_array_48b = { 4 },
1078+ .fixup_map_ringbuf = { 11 },
1079+ .result = ACCEPT,
1080+ .result_unpriv = REJECT,
1081+ .errstr_unpriv = "R8 !read_ok"
1082+},