Skip to content

Commit c638291

Browse files
Cong WangAlexei Starovoitov
Cong Wang
authored and
Alexei Starovoitov
committed
af_unix: Implement ->psock_update_sk_prot()
Now we can implement unix_bpf_update_proto() to update sk_prot, especially prot->close(). Signed-off-by: Cong Wang <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent c7272e1 commit c638291

File tree

6 files changed

+65
-1
lines changed

6 files changed

+65
-1
lines changed

MAINTAINERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10277,6 +10277,7 @@ F: net/core/skmsg.c
1027710277
F: net/core/sock_map.c
1027810278
F: net/ipv4/tcp_bpf.c
1027910279
F: net/ipv4/udp_bpf.c
10280+
F: net/unix/unix_bpf.c
1028010281

1028110282
LANDLOCK SECURITY MODULE
1028210283
M: Mickaël Salaün <[email protected]>

include/net/af_unix.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,14 @@ void unix_sysctl_unregister(struct net *net);
8989
static inline int unix_sysctl_register(struct net *net) { return 0; }
9090
static inline void unix_sysctl_unregister(struct net *net) {}
9191
#endif
92+
93+
#ifdef CONFIG_BPF_SYSCALL
94+
extern struct proto unix_proto;
95+
96+
int unix_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore);
97+
void __init unix_bpf_build_proto(void);
98+
#else
99+
static inline void __init unix_bpf_build_proto(void)
100+
{}
101+
#endif
92102
#endif

net/core/sock_map.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1517,6 +1517,7 @@ void sock_map_close(struct sock *sk, long timeout)
15171517
release_sock(sk);
15181518
saved_close(sk, timeout);
15191519
}
1520+
EXPORT_SYMBOL_GPL(sock_map_close);
15201521

15211522
static int sock_map_iter_attach_target(struct bpf_prog *prog,
15221523
union bpf_iter_link_info *linfo,

net/unix/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ obj-$(CONFIG_UNIX) += unix.o
77

88
unix-y := af_unix.o garbage.o
99
unix-$(CONFIG_SYSCTL) += sysctl_net_unix.o
10+
unix-$(CONFIG_BPF_SYSCALL) += unix_bpf.o
1011

1112
obj-$(CONFIG_UNIX_DIAG) += unix_diag.o
1213
unix_diag-y := diag.o

net/unix/af_unix.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -788,11 +788,14 @@ static void unix_close(struct sock *sk, long timeout)
788788
*/
789789
}
790790

791-
static struct proto unix_proto = {
791+
struct proto unix_proto = {
792792
.name = "UNIX",
793793
.owner = THIS_MODULE,
794794
.obj_size = sizeof(struct unix_sock),
795795
.close = unix_close,
796+
#ifdef CONFIG_BPF_SYSCALL
797+
.psock_update_sk_prot = unix_bpf_update_proto,
798+
#endif
796799
};
797800

798801
static struct sock *unix_create1(struct net *net, struct socket *sock, int kern)
@@ -2973,6 +2976,7 @@ static int __init af_unix_init(void)
29732976

29742977
sock_register(&unix_family_ops);
29752978
register_pernet_subsys(&unix_net_ops);
2979+
unix_bpf_build_proto();
29762980
out:
29772981
return rc;
29782982
}

net/unix/unix_bpf.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2021 Cong Wang <[email protected]> */
3+
4+
#include <linux/skmsg.h>
5+
#include <linux/bpf.h>
6+
#include <net/sock.h>
7+
#include <net/af_unix.h>
8+
9+
static struct proto *unix_prot_saved __read_mostly;
10+
static DEFINE_SPINLOCK(unix_prot_lock);
11+
static struct proto unix_bpf_prot;
12+
13+
static void unix_bpf_rebuild_protos(struct proto *prot, const struct proto *base)
14+
{
15+
*prot = *base;
16+
prot->close = sock_map_close;
17+
}
18+
19+
static void unix_bpf_check_needs_rebuild(struct proto *ops)
20+
{
21+
if (unlikely(ops != smp_load_acquire(&unix_prot_saved))) {
22+
spin_lock_bh(&unix_prot_lock);
23+
if (likely(ops != unix_prot_saved)) {
24+
unix_bpf_rebuild_protos(&unix_bpf_prot, ops);
25+
smp_store_release(&unix_prot_saved, ops);
26+
}
27+
spin_unlock_bh(&unix_prot_lock);
28+
}
29+
}
30+
31+
int unix_bpf_update_proto(struct sock *sk, struct sk_psock *psock, bool restore)
32+
{
33+
if (restore) {
34+
sk->sk_write_space = psock->saved_write_space;
35+
WRITE_ONCE(sk->sk_prot, psock->sk_proto);
36+
return 0;
37+
}
38+
39+
unix_bpf_check_needs_rebuild(psock->sk_proto);
40+
WRITE_ONCE(sk->sk_prot, &unix_bpf_prot);
41+
return 0;
42+
}
43+
44+
void __init unix_bpf_build_proto(void)
45+
{
46+
unix_bpf_rebuild_protos(&unix_bpf_prot, &unix_proto);
47+
}

0 commit comments

Comments
 (0)