Skip to content

Commit 0d47fa5

Browse files
committed
Daniel Borkmann says: ==================== pull-request: bpf 2023-11-30 We've added 5 non-merge commits during the last 7 day(s) which contain a total of 10 files changed, 66 insertions(+), 15 deletions(-). The main changes are: 1) Fix AF_UNIX splat from use after free in BPF sockmap, from John Fastabend. 2) Fix a syzkaller splat in netdevsim by properly handling offloaded programs (and not device-bound ones), from Stanislav Fomichev. 3) Fix bpf_mem_cache_alloc_flags() to initialize the allocation hint, from Hou Tao. 4) Fix netkit by rejecting IFLA_NETKIT_PEER_INFO in changelink, from Daniel Borkmann. * tag 'for-netdev' of https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf: bpf, sockmap: Add af_unix test with both sockets in map bpf, sockmap: af_unix stream sockets need to hold ref for pair sock netkit: Reject IFLA_NETKIT_PEER_INFO in netkit_change_link bpf: Add missed allocation hint for bpf_mem_cache_alloc_flags() netdevsim: Don't accept device bound programs ==================== Link: https://lore.kernel.org/r/20231129234916.16128-1-daniel@iogearbox.net Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 83f2df9 + 51354f7 commit 0d47fa5

10 files changed

Lines changed: 66 additions & 15 deletions

File tree

drivers/net/netdevsim/bpf.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ static void nsim_prog_set_loaded(struct bpf_prog *prog, bool loaded)
9393
{
9494
struct nsim_bpf_bound_prog *state;
9595

96-
if (!prog || !prog->aux->offload)
96+
if (!prog || !bpf_prog_is_offloaded(prog->aux))
9797
return;
9898

9999
state = prog->aux->offload->dev_priv;
@@ -311,7 +311,7 @@ nsim_setup_prog_hw_checks(struct netdevsim *ns, struct netdev_bpf *bpf)
311311
if (!bpf->prog)
312312
return 0;
313313

314-
if (!bpf->prog->aux->offload) {
314+
if (!bpf_prog_is_offloaded(bpf->prog->aux)) {
315315
NSIM_EA(bpf->extack, "xdpoffload of non-bound program");
316316
return -EINVAL;
317317
}

drivers/net/netkit.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,12 @@ static int netkit_change_link(struct net_device *dev, struct nlattr *tb[],
851851
return -EACCES;
852852
}
853853

854+
if (data[IFLA_NETKIT_PEER_INFO]) {
855+
NL_SET_ERR_MSG_ATTR(extack, data[IFLA_NETKIT_PEER_INFO],
856+
"netkit peer info cannot be changed after device creation");
857+
return -EINVAL;
858+
}
859+
854860
if (data[IFLA_NETKIT_POLICY]) {
855861
attr = data[IFLA_NETKIT_POLICY];
856862
policy = nla_get_u32(attr);

include/linux/skmsg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ struct sk_psock {
106106
struct mutex work_mutex;
107107
struct sk_psock_work_state work_state;
108108
struct delayed_work work;
109+
struct sock *sk_pair;
109110
struct rcu_work rwork;
110111
};
111112

include/net/af_unix.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ struct unix_sock {
7575
};
7676

7777
#define unix_sk(ptr) container_of_const(ptr, struct unix_sock, sk)
78+
#define unix_peer(sk) (unix_sk(sk)->peer)
7879

7980
#define peer_wait peer_wq.wait
8081

kernel/bpf/memalloc.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,8 @@ void notrace *bpf_mem_cache_alloc_flags(struct bpf_mem_alloc *ma, gfp_t flags)
978978
memcg = get_memcg(c);
979979
old_memcg = set_active_memcg(memcg);
980980
ret = __alloc(c, NUMA_NO_NODE, GFP_KERNEL | __GFP_NOWARN | __GFP_ACCOUNT);
981+
if (ret)
982+
*(struct bpf_mem_cache **)ret = c;
981983
set_active_memcg(old_memcg);
982984
mem_cgroup_put(memcg);
983985
}

net/core/skmsg.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -826,6 +826,8 @@ static void sk_psock_destroy(struct work_struct *work)
826826

827827
if (psock->sk_redir)
828828
sock_put(psock->sk_redir);
829+
if (psock->sk_pair)
830+
sock_put(psock->sk_pair);
829831
sock_put(psock->sk);
830832
kfree(psock);
831833
}

net/unix/af_unix.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,8 +213,6 @@ static inline bool unix_secdata_eq(struct scm_cookie *scm, struct sk_buff *skb)
213213
}
214214
#endif /* CONFIG_SECURITY_NETWORK */
215215

216-
#define unix_peer(sk) (unix_sk(sk)->peer)
217-
218216
static inline int unix_our_peer(struct sock *sk, struct sock *osk)
219217
{
220218
return unix_peer(osk) == sk;

net/unix/unix_bpf.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,12 +159,17 @@ int unix_dgram_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool re
159159

160160
int unix_stream_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore)
161161
{
162+
struct sock *sk_pair;
163+
162164
if (restore) {
163165
sk->sk_write_space = psock->saved_write_space;
164166
sock_replace_proto(sk, psock->sk_proto);
165167
return 0;
166168
}
167169

170+
sk_pair = unix_peer(sk);
171+
sock_hold(sk_pair);
172+
psock->sk_pair = sk_pair;
168173
unix_stream_bpf_check_needs_rebuild(psock->sk_proto);
169174
sock_replace_proto(sk, &unix_stream_bpf_prot);
170175
return 0;

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

Lines changed: 40 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,7 +1337,8 @@ static void test_redir(struct test_sockmap_listen *skel, struct bpf_map *map,
13371337
}
13381338

13391339
static void pairs_redir_to_connected(int cli0, int peer0, int cli1, int peer1,
1340-
int sock_mapfd, int verd_mapfd, enum redir_mode mode)
1340+
int sock_mapfd, int nop_mapfd,
1341+
int verd_mapfd, enum redir_mode mode)
13411342
{
13421343
const char *log_prefix = redir_mode_str(mode);
13431344
unsigned int pass;
@@ -1351,6 +1352,12 @@ static void pairs_redir_to_connected(int cli0, int peer0, int cli1, int peer1,
13511352
if (err)
13521353
return;
13531354

1355+
if (nop_mapfd >= 0) {
1356+
err = add_to_sockmap(nop_mapfd, cli0, cli1);
1357+
if (err)
1358+
return;
1359+
}
1360+
13541361
n = write(cli1, "a", 1);
13551362
if (n < 0)
13561363
FAIL_ERRNO("%s: write", log_prefix);
@@ -1387,7 +1394,7 @@ static void unix_redir_to_connected(int sotype, int sock_mapfd,
13871394
goto close0;
13881395
c1 = sfd[0], p1 = sfd[1];
13891396

1390-
pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, verd_mapfd, mode);
1397+
pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, -1, verd_mapfd, mode);
13911398

13921399
xclose(c1);
13931400
xclose(p1);
@@ -1677,7 +1684,7 @@ static void udp_redir_to_connected(int family, int sock_mapfd, int verd_mapfd,
16771684
if (err)
16781685
goto close_cli0;
16791686

1680-
pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, verd_mapfd, mode);
1687+
pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, -1, verd_mapfd, mode);
16811688

16821689
xclose(c1);
16831690
xclose(p1);
@@ -1735,7 +1742,7 @@ static void inet_unix_redir_to_connected(int family, int type, int sock_mapfd,
17351742
if (err)
17361743
goto close;
17371744

1738-
pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, verd_mapfd, mode);
1745+
pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, -1, verd_mapfd, mode);
17391746

17401747
xclose(c1);
17411748
xclose(p1);
@@ -1770,8 +1777,10 @@ static void inet_unix_skb_redir_to_connected(struct test_sockmap_listen *skel,
17701777
xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_VERDICT);
17711778
}
17721779

1773-
static void unix_inet_redir_to_connected(int family, int type, int sock_mapfd,
1774-
int verd_mapfd, enum redir_mode mode)
1780+
static void unix_inet_redir_to_connected(int family, int type,
1781+
int sock_mapfd, int nop_mapfd,
1782+
int verd_mapfd,
1783+
enum redir_mode mode)
17751784
{
17761785
int c0, c1, p0, p1;
17771786
int sfd[2];
@@ -1785,7 +1794,8 @@ static void unix_inet_redir_to_connected(int family, int type, int sock_mapfd,
17851794
goto close_cli0;
17861795
c1 = sfd[0], p1 = sfd[1];
17871796

1788-
pairs_redir_to_connected(c0, p0, c1, p1, sock_mapfd, verd_mapfd, mode);
1797+
pairs_redir_to_connected(c0, p0, c1, p1,
1798+
sock_mapfd, nop_mapfd, verd_mapfd, mode);
17891799

17901800
xclose(c1);
17911801
xclose(p1);
@@ -1799,6 +1809,7 @@ static void unix_inet_skb_redir_to_connected(struct test_sockmap_listen *skel,
17991809
struct bpf_map *inner_map, int family)
18001810
{
18011811
int verdict = bpf_program__fd(skel->progs.prog_skb_verdict);
1812+
int nop_map = bpf_map__fd(skel->maps.nop_map);
18021813
int verdict_map = bpf_map__fd(skel->maps.verdict_map);
18031814
int sock_map = bpf_map__fd(inner_map);
18041815
int err;
@@ -1808,14 +1819,32 @@ static void unix_inet_skb_redir_to_connected(struct test_sockmap_listen *skel,
18081819
return;
18091820

18101821
skel->bss->test_ingress = false;
1811-
unix_inet_redir_to_connected(family, SOCK_DGRAM, sock_map, verdict_map,
1822+
unix_inet_redir_to_connected(family, SOCK_DGRAM,
1823+
sock_map, -1, verdict_map,
18121824
REDIR_EGRESS);
1813-
unix_inet_redir_to_connected(family, SOCK_STREAM, sock_map, verdict_map,
1825+
unix_inet_redir_to_connected(family, SOCK_DGRAM,
1826+
sock_map, -1, verdict_map,
1827+
REDIR_EGRESS);
1828+
1829+
unix_inet_redir_to_connected(family, SOCK_DGRAM,
1830+
sock_map, nop_map, verdict_map,
1831+
REDIR_EGRESS);
1832+
unix_inet_redir_to_connected(family, SOCK_STREAM,
1833+
sock_map, nop_map, verdict_map,
18141834
REDIR_EGRESS);
18151835
skel->bss->test_ingress = true;
1816-
unix_inet_redir_to_connected(family, SOCK_DGRAM, sock_map, verdict_map,
1836+
unix_inet_redir_to_connected(family, SOCK_DGRAM,
1837+
sock_map, -1, verdict_map,
1838+
REDIR_INGRESS);
1839+
unix_inet_redir_to_connected(family, SOCK_STREAM,
1840+
sock_map, -1, verdict_map,
1841+
REDIR_INGRESS);
1842+
1843+
unix_inet_redir_to_connected(family, SOCK_DGRAM,
1844+
sock_map, nop_map, verdict_map,
18171845
REDIR_INGRESS);
1818-
unix_inet_redir_to_connected(family, SOCK_STREAM, sock_map, verdict_map,
1846+
unix_inet_redir_to_connected(family, SOCK_STREAM,
1847+
sock_map, nop_map, verdict_map,
18191848
REDIR_INGRESS);
18201849

18211850
xbpf_prog_detach2(verdict, sock_map, BPF_SK_SKB_VERDICT);

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ struct {
1414
__type(value, __u64);
1515
} sock_map SEC(".maps");
1616

17+
struct {
18+
__uint(type, BPF_MAP_TYPE_SOCKMAP);
19+
__uint(max_entries, 2);
20+
__type(key, __u32);
21+
__type(value, __u64);
22+
} nop_map SEC(".maps");
23+
1724
struct {
1825
__uint(type, BPF_MAP_TYPE_SOCKHASH);
1926
__uint(max_entries, 2);

0 commit comments

Comments
 (0)