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
376}376}
377 377
378struct sk_psock *sk_psock_init(struct sock *sk, int node);378struct sk_psock *sk_psock_init(struct sock *sk, int node);
379void sk_psock_stop(struct sk_psock *psock, bool wait);379void sk_psock_stop(struct sk_psock *psock);
380 380
381#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)381#if IS_ENABLED(CONFIG_BPF_STREAM_PARSER)
382int sk_psock_init_strp(struct sock *sk, struct sk_psock *psock);382int 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
20#define _UAPI_LINUX_IN_H20#define _UAPI_LINUX_IN_H
21 21
22#include <linux/types.h>22#include <linux/types.h>
23#include <linux/stddef.h>
23#include <linux/libc-compat.h>24#include <linux/libc-compat.h>
24#include <linux/socket.h>25#include <linux/socket.h>
25 26
kernel/bpf/verifier.c+13−4
@@ -1027,12 +1027,17 @@ out: · 1026 unmodified lines
1027 */1027 */
1028static void *realloc_array(void *arr, size_t old_n, size_t new_n, size_t size)1028static void *realloc_array(void *arr, size_t old_n, size_t new_n, size_t size)
1029{1029{
1030 void *new_arr;
1031
1030 if (!new_n || old_n == new_n)1032 if (!new_n || old_n == new_n)
1031 goto out;1033 goto out;
1032 1034
1033 arr = krealloc_array(arr, new_n, size, GFP_KERNEL);1035 new_arr = krealloc_array(arr, new_n, size, GFP_KERNEL);
1034 if (!arr)1036 if (!new_arr) {
1037 kfree(arr);
1035 return NULL;1038 return NULL;
1039 }
1040 arr = new_arr;
1036 1041
1037 if (new_n > old_n)1042 if (new_n > old_n)
1038 memset(arr + old_n * size, 0, (new_n - old_n) * size);1043 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
6618 return err;6623 return err;
6619 6624
6620 bpf_for_each_reg_in_vstate(env->cur_state, state, reg, ({6625 bpf_for_each_reg_in_vstate(env->cur_state, state, reg, ({
6621 if (reg->ref_obj_id == ref_obj_id)6626 if (reg->ref_obj_id == ref_obj_id) {
6622 __mark_reg_unknown(env, reg);6627 if (!env->allow_ptr_leaks)
6628 __mark_reg_not_init(env, reg);
6629 else
6630 __mark_reg_unknown(env, reg);
6631 }
6623 }));6632 }));
6624 6633
6625 return 0;6634 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
803 }803 }
804}804}
805 805
806void sk_psock_stop(struct sk_psock *psock, bool wait)806void sk_psock_stop(struct sk_psock *psock)
807{807{
808 spin_lock_bh(&psock->ingress_lock);808 spin_lock_bh(&psock->ingress_lock);
809 sk_psock_clear_state(psock, SK_PSOCK_TX_ENABLED);809 sk_psock_clear_state(psock, SK_PSOCK_TX_ENABLED);
810 sk_psock_cork_free(psock);810 sk_psock_cork_free(psock);
811 __sk_psock_zap_ingress(psock);811 __sk_psock_zap_ingress(psock);
812 spin_unlock_bh(&psock->ingress_lock);812 spin_unlock_bh(&psock->ingress_lock);
813
814 if (wait)
815 cancel_work_sync(&psock->work);
816}813}
817 814
818static void sk_psock_done_strp(struct sk_psock *psock);815static 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
850 sk_psock_stop_verdict(sk, psock);847 sk_psock_stop_verdict(sk, psock);
851 write_unlock_bh(&sk->sk_callback_lock);848 write_unlock_bh(&sk->sk_callback_lock);
852 849
853 sk_psock_stop(psock, false);850 sk_psock_stop(psock);
854 851
855 INIT_RCU_WORK(&psock->rwork, sk_psock_destroy);852 INIT_RCU_WORK(&psock->rwork, sk_psock_destroy);
856 queue_rcu_work(system_wq, &psock->rwork);853 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
1596 saved_destroy = psock->saved_destroy;1596 saved_destroy = psock->saved_destroy;
1597 sock_map_remove_links(sk, psock);1597 sock_map_remove_links(sk, psock);
1598 rcu_read_unlock();1598 rcu_read_unlock();
1599 sk_psock_stop(psock, false);1599 sk_psock_stop(psock);
1600 sk_psock_put(sk, psock);1600 sk_psock_put(sk, psock);
1601 saved_destroy(sk);1601 saved_destroy(sk);
1602}1602}
@@ -1619,9 +1619,10 @@ void sock_map_close(struct sock *sk, long timeout) · 16 unmodified lines
1619 saved_close = psock->saved_close;1619 saved_close = psock->saved_close;
1620 sock_map_remove_links(sk, psock);1620 sock_map_remove_links(sk, psock);
1621 rcu_read_unlock();1621 rcu_read_unlock();
1622 sk_psock_stop(psock, true);1622 sk_psock_stop(psock);
1623 sk_psock_put(sk, psock);
1624 release_sock(sk);1623 release_sock(sk);
1624 cancel_work_sync(&psock->work);
1625 sk_psock_put(sk, psock);
1625 saved_close(sk, timeout);1626 saved_close(sk, timeout);
1626}1627}
1627EXPORT_SYMBOL_GPL(sock_map_close);1628EXPORT_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
278{278{
279 bool cork = false, enospc = sk_msg_full(msg);279 bool cork = false, enospc = sk_msg_full(msg);
280 struct sock *sk_redir;280 struct sock *sk_redir;
281 u32 tosend, delta = 0;281 u32 tosend, origsize, sent, delta = 0;
282 u32 eval = __SK_NONE;282 u32 eval = __SK_NONE;
283 int ret;283 int ret;
284 284
@@ -333,10 +333,12 @@ more_data: · 48 unmodified lines
333 cork = true;333 cork = true;
334 psock->cork = NULL;334 psock->cork = NULL;
335 }335 }
336 sk_msg_return(sk, msg, msg->sg.size);336 sk_msg_return(sk, msg, tosend);
337 release_sock(sk);337 release_sock(sk);
338 338
339 origsize = msg->sg.size;
339 ret = tcp_bpf_sendmsg_redir(sk_redir, msg, tosend, flags);340 ret = tcp_bpf_sendmsg_redir(sk_redir, msg, tosend, flags);
341 sent = origsize - msg->sg.size;
340 342
341 if (eval == __SK_REDIRECT)343 if (eval == __SK_REDIRECT)
342 sock_put(sk_redir);344 sock_put(sk_redir);
@@ -375,7 +377,7 @@ more_data: · 32 unmodified lines
375 msg->sg.data[msg->sg.start].page_link &&377 msg->sg.data[msg->sg.start].page_link &&
376 msg->sg.data[msg->sg.start].length) {378 msg->sg.data[msg->sg.start].length) {
377 if (eval == __SK_REDIRECT)379 if (eval == __SK_REDIRECT)
378 sk_mem_charge(sk, msg->sg.size);380 sk_mem_charge(sk, tosend - sent);
379 goto more_data;381 goto more_data;
380 }382 }
381 }383 }
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
300 int err;300 int err;
301 int fd;301 int fd;
302 302
303 if (!REQ_ARGS(3))
304 return -EINVAL;
305
303 fd = get_fd(&argc, &argv);306 fd = get_fd(&argc, &argv);
304 if (fd < 0)307 if (fd < 0)
305 return fd;308 return fd;
tools/include/uapi/linux/in.h+1−0
@@ -20,6 +20,7 @@ · 19 unmodified lines
20#define _UAPI_LINUX_IN_H20#define _UAPI_LINUX_IN_H
21 21
22#include <linux/types.h>22#include <linux/types.h>
23#include <linux/stddef.h>
23#include <linux/libc-compat.h>24#include <linux/libc-compat.h>
24#include <linux/socket.h>25#include <linux/socket.h>
25 26
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
1044 .result_unpriv = REJECT,1044 .result_unpriv = REJECT,
1045 .errstr_unpriv = "unknown func",1045 .errstr_unpriv = "unknown func",
1046},1046},
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},