diff options
author | 2019-06-13 20:52:36 +0000 | |
---|---|---|
committer | 2019-06-13 20:52:36 +0000 | |
commit | 0fe0bd9326e05a05c0f55e030d7af496a0f8fe52 (patch) | |
tree | cfd758841e7eb185acedd46a1c8de3d2b2d00b65 | |
parent | Do memory size calculations as unsigned long. Otherwise (diff) | |
download | wireguard-openbsd-0fe0bd9326e05a05c0f55e030d7af496a0f8fe52.tar.xz wireguard-openbsd-0fe0bd9326e05a05c0f55e030d7af496a0f8fe52.zip |
When tcp_close() is running in parallel with fill_file(), the kernel
could crash due to missing inp_ppcb. This happend when fstat(1)
was called often and TCP was aborted with reset. Protect the sysctl
path with the net lock.
OK mpi@
-rw-r--r-- | sys/kern/kern_sysctl.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 7096e861223..c1a82f7dcc5 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sysctl.c,v 1.358 2019/06/01 14:11:17 mpi Exp $ */ +/* $OpenBSD: kern_sysctl.c,v 1.359 2019/06/13 20:52:36 bluhm Exp $ */ /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */ /*- @@ -1152,8 +1152,19 @@ fill_file(struct kinfo_file *kf, struct file *fp, struct filedesc *fdp, break; case DTYPE_SOCKET: { - if (so == NULL) + int locked = 0; + + if (so == NULL) { so = (struct socket *)fp->f_data; + /* if so is passed as parameter it is already locked */ + switch (so->so_proto->pr_domain->dom_family) { + case AF_INET: + case AF_INET6: + NET_LOCK(); + locked = 1; + break; + } + } kf->so_type = so->so_type; kf->so_state = so->so_state; @@ -1178,6 +1189,7 @@ fill_file(struct kinfo_file *kf, struct file *fp, struct filedesc *fdp, case AF_INET: { struct inpcb *inpcb = so->so_pcb; + NET_ASSERT_LOCKED(); if (show_pointers) kf->inp_ppcb = PTRTOINT64(inpcb->inp_ppcb); kf->inp_lport = inpcb->inp_lport; @@ -1199,6 +1211,7 @@ fill_file(struct kinfo_file *kf, struct file *fp, struct filedesc *fdp, case AF_INET6: { struct inpcb *inpcb = so->so_pcb; + NET_ASSERT_LOCKED(); if (show_pointers) kf->inp_ppcb = PTRTOINT64(inpcb->inp_ppcb); kf->inp_lport = inpcb->inp_lport; @@ -1244,6 +1257,8 @@ fill_file(struct kinfo_file *kf, struct file *fp, struct filedesc *fdp, break; } } + if (locked) + NET_UNLOCK(); break; } |