Skip to content

Commit 9825d86

Browse files
Cong WangAlexei Starovoitov
Cong Wang
authored and
Alexei Starovoitov
committed
af_unix: Implement unix_dgram_bpf_recvmsg()
We have to implement unix_dgram_bpf_recvmsg() to replace the original ->recvmsg() to retrieve skmsg from ingress_msg. AF_UNIX is again special here because the lack of sk_prot->recvmsg(). I simply add a special case inside unix_dgram_recvmsg() to call sk->sk_prot->recvmsg() directly. Signed-off-by: Cong Wang <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Link: https://lore.kernel.org/bpf/[email protected]
1 parent c638291 commit 9825d86

File tree

3 files changed

+93
-3
lines changed

3 files changed

+93
-3
lines changed

include/net/af_unix.h

+2
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ static inline struct unix_sock *unix_sk(const struct sock *sk)
8282
long unix_inq_len(struct sock *sk);
8383
long unix_outq_len(struct sock *sk);
8484

85+
int __unix_dgram_recvmsg(struct sock *sk, struct msghdr *msg, size_t size,
86+
int flags);
8587
#ifdef CONFIG_SYSCTL
8688
int unix_sysctl_register(struct net *net);
8789
void unix_sysctl_unregister(struct net *net);

net/unix/af_unix.c

+16-3
Original file line numberDiff line numberDiff line change
@@ -2098,11 +2098,11 @@ static void unix_copy_addr(struct msghdr *msg, struct sock *sk)
20982098
}
20992099
}
21002100

2101-
static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
2102-
size_t size, int flags)
2101+
int __unix_dgram_recvmsg(struct sock *sk, struct msghdr *msg, size_t size,
2102+
int flags)
21032103
{
21042104
struct scm_cookie scm;
2105-
struct sock *sk = sock->sk;
2105+
struct socket *sock = sk->sk_socket;
21062106
struct unix_sock *u = unix_sk(sk);
21072107
struct sk_buff *skb, *last;
21082108
long timeo;
@@ -2205,6 +2205,19 @@ static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg,
22052205
return err;
22062206
}
22072207

2208+
static int unix_dgram_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
2209+
int flags)
2210+
{
2211+
struct sock *sk = sock->sk;
2212+
2213+
#ifdef CONFIG_BPF_SYSCALL
2214+
if (sk->sk_prot != &unix_proto)
2215+
return sk->sk_prot->recvmsg(sk, msg, size, flags & MSG_DONTWAIT,
2216+
flags & ~MSG_DONTWAIT, NULL);
2217+
#endif
2218+
return __unix_dgram_recvmsg(sk, msg, size, flags);
2219+
}
2220+
22082221
static int unix_read_sock(struct sock *sk, read_descriptor_t *desc,
22092222
sk_read_actor_t recv_actor)
22102223
{

net/unix/unix_bpf.c

+75
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,80 @@
66
#include <net/sock.h>
77
#include <net/af_unix.h>
88

9+
#define unix_sk_has_data(__sk, __psock) \
10+
({ !skb_queue_empty(&__sk->sk_receive_queue) || \
11+
!skb_queue_empty(&__psock->ingress_skb) || \
12+
!list_empty(&__psock->ingress_msg); \
13+
})
14+
15+
static int unix_msg_wait_data(struct sock *sk, struct sk_psock *psock,
16+
long timeo)
17+
{
18+
DEFINE_WAIT_FUNC(wait, woken_wake_function);
19+
struct unix_sock *u = unix_sk(sk);
20+
int ret = 0;
21+
22+
if (sk->sk_shutdown & RCV_SHUTDOWN)
23+
return 1;
24+
25+
if (!timeo)
26+
return ret;
27+
28+
add_wait_queue(sk_sleep(sk), &wait);
29+
sk_set_bit(SOCKWQ_ASYNC_WAITDATA, sk);
30+
if (!unix_sk_has_data(sk, psock)) {
31+
mutex_unlock(&u->iolock);
32+
wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
33+
mutex_lock(&u->iolock);
34+
ret = unix_sk_has_data(sk, psock);
35+
}
36+
sk_clear_bit(SOCKWQ_ASYNC_WAITDATA, sk);
37+
remove_wait_queue(sk_sleep(sk), &wait);
38+
return ret;
39+
}
40+
41+
static int unix_dgram_bpf_recvmsg(struct sock *sk, struct msghdr *msg,
42+
size_t len, int nonblock, int flags,
43+
int *addr_len)
44+
{
45+
struct unix_sock *u = unix_sk(sk);
46+
struct sk_psock *psock;
47+
int copied, ret;
48+
49+
psock = sk_psock_get(sk);
50+
if (unlikely(!psock))
51+
return __unix_dgram_recvmsg(sk, msg, len, flags);
52+
53+
mutex_lock(&u->iolock);
54+
if (!skb_queue_empty(&sk->sk_receive_queue) &&
55+
sk_psock_queue_empty(psock)) {
56+
ret = __unix_dgram_recvmsg(sk, msg, len, flags);
57+
goto out;
58+
}
59+
60+
msg_bytes_ready:
61+
copied = sk_msg_recvmsg(sk, psock, msg, len, flags);
62+
if (!copied) {
63+
long timeo;
64+
int data;
65+
66+
timeo = sock_rcvtimeo(sk, nonblock);
67+
data = unix_msg_wait_data(sk, psock, timeo);
68+
if (data) {
69+
if (!sk_psock_queue_empty(psock))
70+
goto msg_bytes_ready;
71+
ret = __unix_dgram_recvmsg(sk, msg, len, flags);
72+
goto out;
73+
}
74+
copied = -EAGAIN;
75+
}
76+
ret = copied;
77+
out:
78+
mutex_unlock(&u->iolock);
79+
sk_psock_put(sk, psock);
80+
return ret;
81+
}
82+
983
static struct proto *unix_prot_saved __read_mostly;
1084
static DEFINE_SPINLOCK(unix_prot_lock);
1185
static struct proto unix_bpf_prot;
@@ -14,6 +88,7 @@ static void unix_bpf_rebuild_protos(struct proto *prot, const struct proto *base
1488
{
1589
*prot = *base;
1690
prot->close = sock_map_close;
91+
prot->recvmsg = unix_dgram_bpf_recvmsg;
1792
}
1893

1994
static void unix_bpf_check_needs_rebuild(struct proto *ops)

0 commit comments

Comments
 (0)