Skip to content

Commit c44d6f4

Browse files
committed
unix/stream: provide uipc_cantrcvmore()
and use it the pr_shutdown method. While unix/dgram can still use generic socket socantrcvmore(), the stream versions need a specific one. This fixes a panic reported by syzkaller. While here inline unp_shutdown() into uipc_shutdown(). Reported-by: [email protected]
1 parent 0b52d6c commit c44d6f4

File tree

1 file changed

+28
-24
lines changed

1 file changed

+28
-24
lines changed

sys/kern/uipc_usrreq.c

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,6 @@ static int unp_connectat(int, struct socket *, struct sockaddr *,
299299
static void unp_connect2(struct socket *, struct socket *, bool);
300300
static void unp_disconnect(struct unpcb *unp, struct unpcb *unp2);
301301
static void unp_dispose(struct socket *so);
302-
static void unp_shutdown(struct unpcb *);
303302
static void unp_drop(struct unpcb *);
304303
static void unp_gc(__unused void *, int);
305304
static void unp_scan(struct mbuf *, void (*)(struct filedescent **, int));
@@ -1341,6 +1340,18 @@ uipc_wakeup(struct socket *so)
13411340
SOCK_RECVBUF_UNLOCK(so);
13421341
}
13431342

1343+
static void
1344+
uipc_cantrcvmore(struct socket *so)
1345+
{
1346+
1347+
SOCK_RECVBUF_LOCK(so);
1348+
so->so_rcv.sb_state |= SBS_CANTRCVMORE;
1349+
if (so->so_rcv.uxst_peer != NULL)
1350+
uipc_wakeup(so);
1351+
else
1352+
SOCK_RECVBUF_UNLOCK(so);
1353+
}
1354+
13441355
static int
13451356
uipc_soreceive_stream_or_seqpacket(struct socket *so, struct sockaddr **psa,
13461357
struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp)
@@ -2646,18 +2657,28 @@ uipc_shutdown(struct socket *so, enum shutdown_how how)
26462657

26472658
switch (how) {
26482659
case SHUT_RD:
2649-
socantrcvmore(so);
2660+
if (so->so_type == SOCK_DGRAM)
2661+
socantrcvmore(so);
2662+
else
2663+
uipc_cantrcvmore(so);
26502664
unp_dispose(so);
26512665
break;
26522666
case SHUT_RDWR:
2653-
socantrcvmore(so);
2667+
if (so->so_type == SOCK_DGRAM)
2668+
socantrcvmore(so);
2669+
else
2670+
uipc_cantrcvmore(so);
26542671
unp_dispose(so);
26552672
/* FALLTHROUGH */
26562673
case SHUT_WR:
2657-
UNP_PCB_LOCK(unp);
2658-
socantsendmore(so);
2659-
unp_shutdown(unp);
2660-
UNP_PCB_UNLOCK(unp);
2674+
if (so->so_type == SOCK_DGRAM) {
2675+
socantsendmore(so);
2676+
} else {
2677+
UNP_PCB_LOCK(unp);
2678+
if (unp->unp_conn != NULL)
2679+
uipc_cantrcvmore(unp->unp_conn->unp_socket);
2680+
UNP_PCB_UNLOCK(unp);
2681+
}
26612682
}
26622683
wakeup(&so->so_timeo);
26632684

@@ -3380,23 +3401,6 @@ SYSCTL_PROC(_net_local_seqpacket, OID_AUTO, pcblist,
33803401
(void *)(intptr_t)SOCK_SEQPACKET, 0, unp_pcblist, "S,xunpcb",
33813402
"List of active local seqpacket sockets");
33823403

3383-
static void
3384-
unp_shutdown(struct unpcb *unp)
3385-
{
3386-
struct unpcb *unp2;
3387-
struct socket *so;
3388-
3389-
UNP_PCB_LOCK_ASSERT(unp);
3390-
3391-
unp2 = unp->unp_conn;
3392-
if ((unp->unp_socket->so_type == SOCK_STREAM ||
3393-
(unp->unp_socket->so_type == SOCK_SEQPACKET)) && unp2 != NULL) {
3394-
so = unp2->unp_socket;
3395-
if (so != NULL)
3396-
socantrcvmore(so);
3397-
}
3398-
}
3399-
34003404
static void
34013405
unp_drop(struct unpcb *unp)
34023406
{

0 commit comments

Comments
 (0)