Skip to content

Commit 515186b

Browse files
committed
Merge tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Pull bpf fixes from Alexei Starovoitov: - Fix sk_local_storage diag dump via netlink (Amery Hung) - Fix off-by-one in arena direct-value access (Junyoung Jang) - Reject TCP_NODELAY in bpf-tcp congestion control (KaFai Wan) - Fix type confusion in bpf_*_sock() (Kuniyuki Iwashima) - Reject TX-only AF_XDP sockets (Linpu Yu) - Don't run arg-tracking analysis twice on main subprog (Paul Chaignon) - Fix NULL pointer dereference in bpf_sk_storage_clone and fib lookup (Weiming Shi) * tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf: bpf: Fix off-by-one boundary validation in arena direct-value access xskmap: reject TX-only AF_XDP sockets bpf: Don't run arg-tracking analysis twice on main subprog bpf: Free reuseport cBPF prog after RCU grace period. bpf: tcp: Fix type confusion in sol_tcp_sockopt(). bpf: tcp: Fix type confusion in bpf_skc_to_tcp6_sock(). bpf: tcp: Fix type confusion in bpf_skc_to_tcp_sock(). mptcp: bpf: Fix type confusion in bpf_mptcp_sock_from_subflow() selftest: bpf: Add test for bpf_tcp_sock() and RAW socket. bpf: tcp: Fix type confusion in bpf_tcp_sock(). tools/headers: Regenerate stddef.h to fix BPF selftests bpf: Fix sk_local_storage diag dumping uninitialized special fields bpf: Fix NULL pointer dereference in bpf_skb_fib_lookup() sockmap: Fix sk_psock_drop() race vs sock_map_{unhash,close,destroy}(). bpf: Fix NULL pointer dereference in bpf_sk_storage_clone and diag paths selftests/bpf: Verify bpf-tcp-cc rejects TCP_NODELAY selftests/bpf: Test TCP_NODELAY in TCP hdr opt callbacks bpf: Reject TCP_NODELAY in bpf-tcp-cc bpf: Reject TCP_NODELAY in TCP header option callbacks
2 parents 1bfaee9 + 3ac1a46 commit 515186b

16 files changed

Lines changed: 189 additions & 51 deletions

File tree

include/linux/bpf.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3725,6 +3725,7 @@ extern const struct bpf_func_proto bpf_for_each_map_elem_proto;
37253725
extern const struct bpf_func_proto bpf_btf_find_by_name_kind_proto;
37263726
extern const struct bpf_func_proto bpf_sk_setsockopt_proto;
37273727
extern const struct bpf_func_proto bpf_sk_getsockopt_proto;
3728+
extern const struct bpf_func_proto bpf_sk_setsockopt_nodelay_proto;
37283729
extern const struct bpf_func_proto bpf_unlocked_sk_setsockopt_proto;
37293730
extern const struct bpf_func_proto bpf_unlocked_sk_getsockopt_proto;
37303731
extern const struct bpf_func_proto bpf_find_vma_proto;

kernel/bpf/arena.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ static int arena_map_direct_value_addr(const struct bpf_map *map, u64 *imm, u32
511511
{
512512
struct bpf_arena *arena = container_of(map, struct bpf_arena, map);
513513

514-
if ((u64)off > arena->user_vm_end - arena->user_vm_start)
514+
if ((u64)off >= arena->user_vm_end - arena->user_vm_start)
515515
return -ERANGE;
516516
*imm = (unsigned long)arena->user_vm_start;
517517
return 0;

kernel/bpf/liveness.c

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1914,26 +1914,15 @@ int bpf_compute_subprog_arg_access(struct bpf_verifier_env *env)
19141914
return -ENOMEM;
19151915
}
19161916

1917-
instance = call_instance(env, NULL, 0, 0);
1918-
if (IS_ERR(instance)) {
1919-
err = PTR_ERR(instance);
1920-
goto out;
1921-
}
1922-
err = analyze_subprog(env, NULL, info, instance, callsites);
1923-
if (err)
1924-
goto out;
1925-
19261917
/*
1927-
* Subprogs and callbacks that don't receive FP-derived arguments
1928-
* cannot access ancestor stack frames, so they were skipped during
1929-
* the recursive walk above. Async callbacks (timer, workqueue) are
1930-
* also not reachable from the main program's call graph. Analyze
1931-
* all unvisited subprogs as independent roots at depth 0.
1918+
* Analyze every subprog in reverse topological order (callers
1919+
* before callees) so that each subprog is analyzed before its
1920+
* callees, allowing the recursive walk inside analyze_subprog()
1921+
* to naturally reach callees that receive FP-derived args.
19321922
*
1933-
* Use reverse topological order (callers before callees) so that
1934-
* each subprog is analyzed before its callees, allowing the
1935-
* recursive walk inside analyze_subprog() to naturally
1936-
* reach nested callees that also lack FP-derived args.
1923+
* Subprogs and callbacks that don't receive FP-derived arguments
1924+
* cannot access ancestor stack frames are analyzed independently.
1925+
* Async callbacks (timer, workqueue) are handled the same way.
19371926
*/
19381927
for (k = env->subprog_cnt - 1; k >= 0; k--) {
19391928
int sub = env->subprog_topo_order[k];

net/core/bpf_sk_storage.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ int bpf_sk_storage_clone(const struct sock *sk, struct sock *newsk)
172172
struct bpf_map *map;
173173

174174
smap = rcu_dereference(SDATA(selem)->smap);
175-
if (!(smap->map.map_flags & BPF_F_CLONE))
175+
if (!smap || !(smap->map.map_flags & BPF_F_CLONE))
176176
continue;
177177

178178
/* Note that for lockless listeners adding new element
@@ -531,10 +531,10 @@ bpf_sk_storage_diag_alloc(const struct nlattr *nla_stgs)
531531
}
532532
EXPORT_SYMBOL_GPL(bpf_sk_storage_diag_alloc);
533533

534-
static int diag_get(struct bpf_local_storage_data *sdata, struct sk_buff *skb)
534+
static int diag_get(struct bpf_local_storage_map *smap,
535+
struct bpf_local_storage_data *sdata, struct sk_buff *skb)
535536
{
536537
struct nlattr *nla_stg, *nla_value;
537-
struct bpf_local_storage_map *smap;
538538

539539
/* It cannot exceed max nlattr's payload */
540540
BUILD_BUG_ON(U16_MAX - NLA_HDRLEN < BPF_LOCAL_STORAGE_MAX_VALUE_SIZE);
@@ -543,7 +543,6 @@ static int diag_get(struct bpf_local_storage_data *sdata, struct sk_buff *skb)
543543
if (!nla_stg)
544544
return -EMSGSIZE;
545545

546-
smap = rcu_dereference(sdata->smap);
547546
if (nla_put_u32(skb, SK_DIAG_BPF_STORAGE_MAP_ID, smap->map.id))
548547
goto errout;
549548

@@ -558,6 +557,7 @@ static int diag_get(struct bpf_local_storage_data *sdata, struct sk_buff *skb)
558557
sdata->data, true);
559558
else
560559
copy_map_value(&smap->map, nla_data(nla_value), sdata->data);
560+
check_and_init_map_value(&smap->map, nla_data(nla_value));
561561

562562
nla_nest_end(skb, nla_stg);
563563
return 0;
@@ -596,9 +596,11 @@ static int bpf_sk_storage_diag_put_all(struct sock *sk, struct sk_buff *skb,
596596
saved_len = skb->len;
597597
hlist_for_each_entry_rcu(selem, &sk_storage->list, snode) {
598598
smap = rcu_dereference(SDATA(selem)->smap);
599+
if (!smap)
600+
continue;
599601
diag_size += nla_value_size(smap->map.value_size);
600602

601-
if (nla_stgs && diag_get(SDATA(selem), skb))
603+
if (nla_stgs && diag_get(smap, SDATA(selem), skb))
602604
/* Continue to learn diag_size */
603605
err = -EMSGSIZE;
604606
}
@@ -665,7 +667,7 @@ int bpf_sk_storage_diag_put(struct bpf_sk_storage_diag *diag,
665667

666668
diag_size += nla_value_size(diag->maps[i]->value_size);
667669

668-
if (nla_stgs && diag_get(sdata, skb))
670+
if (nla_stgs && diag_get((struct bpf_local_storage_map *)diag->maps[i], sdata, skb))
669671
/* Continue to learn diag_size */
670672
err = -EMSGSIZE;
671673
}

net/core/filter.c

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,15 +1654,24 @@ int sk_reuseport_attach_bpf(u32 ufd, struct sock *sk)
16541654
return err;
16551655
}
16561656

1657+
static void sk_reuseport_prog_free_rcu(struct rcu_head *rcu)
1658+
{
1659+
struct bpf_prog_aux *aux = container_of(rcu, struct bpf_prog_aux, rcu);
1660+
struct bpf_prog *prog = aux->prog;
1661+
1662+
bpf_release_orig_filter(prog);
1663+
bpf_prog_free(prog);
1664+
}
1665+
16571666
void sk_reuseport_prog_free(struct bpf_prog *prog)
16581667
{
16591668
if (!prog)
16601669
return;
16611670

1662-
if (prog->type == BPF_PROG_TYPE_SK_REUSEPORT)
1663-
bpf_prog_put(prog);
1671+
if (bpf_prog_was_classic(prog))
1672+
call_rcu(&prog->aux->rcu, sk_reuseport_prog_free_rcu);
16641673
else
1665-
bpf_prog_destroy(prog);
1674+
bpf_prog_put(prog);
16661675
}
16671676

16681677
static inline int __bpf_try_make_writable(struct sk_buff *skb,
@@ -5481,7 +5490,7 @@ static int sol_tcp_sockopt(struct sock *sk, int optname,
54815490
char *optval, int *optlen,
54825491
bool getopt)
54835492
{
5484-
if (sk->sk_protocol != IPPROTO_TCP)
5493+
if (!sk_is_tcp(sk))
54855494
return -EINVAL;
54865495

54875496
switch (optname) {
@@ -5688,6 +5697,30 @@ const struct bpf_func_proto bpf_sk_getsockopt_proto = {
56885697
.arg5_type = ARG_CONST_SIZE,
56895698
};
56905699

5700+
BPF_CALL_5(bpf_sk_setsockopt_nodelay, struct sock *, sk, int, level,
5701+
int, optname, char *, optval, int, optlen)
5702+
{
5703+
/*
5704+
* TCP_NODELAY triggers tcp_push_pending_frames() and re-enters
5705+
* CA_EVENT_TX_START in bpf_tcp_cc.
5706+
*/
5707+
if (level == SOL_TCP && optname == TCP_NODELAY)
5708+
return -EOPNOTSUPP;
5709+
5710+
return _bpf_setsockopt(sk, level, optname, optval, optlen);
5711+
}
5712+
5713+
const struct bpf_func_proto bpf_sk_setsockopt_nodelay_proto = {
5714+
.func = bpf_sk_setsockopt_nodelay,
5715+
.gpl_only = false,
5716+
.ret_type = RET_INTEGER,
5717+
.arg1_type = ARG_PTR_TO_BTF_ID_SOCK_COMMON,
5718+
.arg2_type = ARG_ANYTHING,
5719+
.arg3_type = ARG_ANYTHING,
5720+
.arg4_type = ARG_PTR_TO_MEM | MEM_RDONLY,
5721+
.arg5_type = ARG_CONST_SIZE,
5722+
};
5723+
56915724
BPF_CALL_5(bpf_unlocked_sk_setsockopt, struct sock *, sk, int, level,
56925725
int, optname, char *, optval, int, optlen)
56935726
{
@@ -5833,6 +5866,12 @@ BPF_CALL_5(bpf_sock_ops_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
58335866
if (!is_locked_tcp_sock_ops(bpf_sock))
58345867
return -EOPNOTSUPP;
58355868

5869+
/* TCP_NODELAY triggers tcp_push_pending_frames() and re-enters these callbacks. */
5870+
if ((bpf_sock->op == BPF_SOCK_OPS_HDR_OPT_LEN_CB ||
5871+
bpf_sock->op == BPF_SOCK_OPS_WRITE_HDR_OPT_CB) &&
5872+
level == SOL_TCP && optname == TCP_NODELAY)
5873+
return -EOPNOTSUPP;
5874+
58365875
return _bpf_setsockopt(bpf_sock->sk, level, optname, optval, optlen);
58375876
}
58385877

@@ -6443,6 +6482,8 @@ BPF_CALL_4(bpf_skb_fib_lookup, struct sk_buff *, skb,
64436482
* against MTU of FIB lookup resulting net_device
64446483
*/
64456484
dev = dev_get_by_index_rcu(net, params->ifindex);
6485+
if (unlikely(!dev))
6486+
return -ENODEV;
64466487
if (!is_skb_forwardable(dev, skb))
64476488
rc = BPF_FIB_LKUP_RET_FRAG_NEEDED;
64486489

@@ -7443,7 +7484,7 @@ u32 bpf_tcp_sock_convert_ctx_access(enum bpf_access_type type,
74437484

74447485
BPF_CALL_1(bpf_tcp_sock, struct sock *, sk)
74457486
{
7446-
if (sk_fullsock(sk) && sk->sk_protocol == IPPROTO_TCP)
7487+
if (sk_fullsock(sk) && sk_is_tcp(sk))
74477488
return (unsigned long)sk;
74487489

74497490
return (unsigned long)NULL;
@@ -11915,7 +11956,7 @@ BPF_CALL_1(bpf_skc_to_tcp6_sock, struct sock *, sk)
1191511956
*/
1191611957
BTF_TYPE_EMIT(struct tcp6_sock);
1191711958
if (sk && sk_fullsock(sk) && sk->sk_protocol == IPPROTO_TCP &&
11918-
sk->sk_family == AF_INET6)
11959+
sk->sk_type == SOCK_STREAM && sk->sk_family == AF_INET6)
1191911960
return (unsigned long)sk;
1192011961

1192111962
return (unsigned long)NULL;
@@ -11931,7 +11972,7 @@ const struct bpf_func_proto bpf_skc_to_tcp6_sock_proto = {
1193111972

1193211973
BPF_CALL_1(bpf_skc_to_tcp_sock, struct sock *, sk)
1193311974
{
11934-
if (sk && sk_fullsock(sk) && sk->sk_protocol == IPPROTO_TCP)
11975+
if (sk && sk_fullsock(sk) && sk_is_tcp(sk))
1193511976
return (unsigned long)sk;
1193611977

1193711978
return (unsigned long)NULL;

net/core/sock_map.c

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1630,18 +1630,23 @@ void sock_map_unhash(struct sock *sk)
16301630
void (*saved_unhash)(struct sock *sk);
16311631
struct sk_psock *psock;
16321632

1633+
retry:
16331634
rcu_read_lock();
16341635
psock = sk_psock(sk);
16351636
if (unlikely(!psock)) {
16361637
rcu_read_unlock();
16371638
saved_unhash = READ_ONCE(sk->sk_prot)->unhash;
1639+
if (unlikely(saved_unhash == sock_map_unhash))
1640+
goto retry;
16381641
} else {
16391642
saved_unhash = psock->saved_unhash;
16401643
sock_map_remove_links(sk, psock);
16411644
rcu_read_unlock();
1645+
1646+
if (WARN_ON_ONCE(saved_unhash == sock_map_unhash))
1647+
return;
16421648
}
1643-
if (WARN_ON_ONCE(saved_unhash == sock_map_unhash))
1644-
return;
1649+
16451650
if (saved_unhash)
16461651
saved_unhash(sk);
16471652
}
@@ -1652,20 +1657,25 @@ void sock_map_destroy(struct sock *sk)
16521657
void (*saved_destroy)(struct sock *sk);
16531658
struct sk_psock *psock;
16541659

1660+
retry:
16551661
rcu_read_lock();
16561662
psock = sk_psock_get(sk);
16571663
if (unlikely(!psock)) {
16581664
rcu_read_unlock();
16591665
saved_destroy = READ_ONCE(sk->sk_prot)->destroy;
1666+
if (unlikely(saved_destroy == sock_map_destroy))
1667+
goto retry;
16601668
} else {
16611669
saved_destroy = psock->saved_destroy;
16621670
sock_map_remove_links(sk, psock);
16631671
rcu_read_unlock();
16641672
sk_psock_stop(psock);
16651673
sk_psock_put(sk, psock);
1674+
1675+
if (WARN_ON_ONCE(saved_destroy == sock_map_destroy))
1676+
return;
16661677
}
1667-
if (WARN_ON_ONCE(saved_destroy == sock_map_destroy))
1668-
return;
1678+
16691679
if (saved_destroy)
16701680
saved_destroy(sk);
16711681
}
@@ -1676,32 +1686,33 @@ void sock_map_close(struct sock *sk, long timeout)
16761686
void (*saved_close)(struct sock *sk, long timeout);
16771687
struct sk_psock *psock;
16781688

1689+
retry:
16791690
lock_sock(sk);
16801691
rcu_read_lock();
1681-
psock = sk_psock(sk);
1692+
psock = sk_psock_get(sk);
16821693
if (likely(psock)) {
16831694
saved_close = psock->saved_close;
16841695
sock_map_remove_links(sk, psock);
1685-
psock = sk_psock_get(sk);
1686-
if (unlikely(!psock))
1687-
goto no_psock;
16881696
rcu_read_unlock();
16891697
sk_psock_stop(psock);
16901698
release_sock(sk);
16911699
cancel_delayed_work_sync(&psock->work);
16921700
sk_psock_put(sk, psock);
1701+
1702+
/* Make sure we do not recurse. This is a bug.
1703+
* Leak the socket instead of crashing on a stack overflow.
1704+
*/
1705+
if (WARN_ON_ONCE(saved_close == sock_map_close))
1706+
return;
16931707
} else {
16941708
saved_close = READ_ONCE(sk->sk_prot)->close;
1695-
no_psock:
16961709
rcu_read_unlock();
16971710
release_sock(sk);
1711+
1712+
if (unlikely(saved_close == sock_map_close))
1713+
goto retry;
16981714
}
16991715

1700-
/* Make sure we do not recurse. This is a bug.
1701-
* Leak the socket instead of crashing on a stack overflow.
1702-
*/
1703-
if (WARN_ON_ONCE(saved_close == sock_map_close))
1704-
return;
17051716
saved_close(sk, timeout);
17061717
}
17071718
EXPORT_SYMBOL_GPL(sock_map_close);

net/ipv4/bpf_tcp_ca.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ bpf_tcp_ca_get_func_proto(enum bpf_func_id func_id,
168168
*/
169169
if (prog_ops_moff(prog) !=
170170
offsetof(struct tcp_congestion_ops, release))
171-
return &bpf_sk_setsockopt_proto;
171+
return &bpf_sk_setsockopt_nodelay_proto;
172172
return NULL;
173173
case BPF_FUNC_getsockopt:
174174
/* Since get/setsockopt is usually expected to

net/mptcp/bpf.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
struct mptcp_sock *bpf_mptcp_sock_from_subflow(struct sock *sk)
1616
{
17-
if (sk && sk_fullsock(sk) && sk->sk_protocol == IPPROTO_TCP && sk_is_mptcp(sk))
17+
if (sk && sk_fullsock(sk) && sk_is_tcp(sk) && sk_is_mptcp(sk))
1818
return mptcp_sk(mptcp_subflow_ctx(sk)->conn);
1919

2020
return NULL;

net/xdp/xskmap.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,10 @@ static long xsk_map_update_elem(struct bpf_map *map, void *key, void *value,
184184
}
185185

186186
xs = (struct xdp_sock *)sock->sk;
187+
if (!READ_ONCE(xs->rx)) {
188+
sockfd_put(sock);
189+
return -ENOBUFS;
190+
}
187191

188192
map_entry = &m->xsk_map[i];
189193
node = xsk_map_node_alloc(m, map_entry);

tools/include/uapi/linux/stddef.h

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#define _LINUX_STDDEF_H
44

55

6-
76
#ifndef __always_inline
87
#define __always_inline __inline__
98
#endif
@@ -36,6 +35,11 @@
3635
struct __struct_group_tag(TAG) { MEMBERS } ATTRS NAME; \
3736
} ATTRS
3837

38+
#ifdef __cplusplus
39+
/* sizeof(struct{}) is 1 in C++, not 0, can't use C version of the macro. */
40+
#define __DECLARE_FLEX_ARRAY(T, member) \
41+
T member[0]
42+
#else
3943
/**
4044
* __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union
4145
*
@@ -52,3 +56,23 @@
5256
TYPE NAME[]; \
5357
}
5458
#endif
59+
60+
#ifndef __counted_by
61+
#define __counted_by(m)
62+
#endif
63+
64+
#ifndef __counted_by_le
65+
#define __counted_by_le(m)
66+
#endif
67+
68+
#ifndef __counted_by_be
69+
#define __counted_by_be(m)
70+
#endif
71+
72+
#ifndef __counted_by_ptr
73+
#define __counted_by_ptr(m)
74+
#endif
75+
76+
#define __kernel_nonstring
77+
78+
#endif /* _LINUX_STDDEF_H */

0 commit comments

Comments
 (0)