On Thu, Apr 27, 2023 at 01:55:33PM +0300, Vitaliy Makkoveev wrote: > Now only direct netlock used for inet sockets protection. The unlocked > access to all other sockets is safe, but we could lost consistency for a > little. Since the solock() used for sockets protection, make locking > path common and use it. Make it shared because this is read-only access > to sockets data. For same reason use shared netlock while performing > inpcb tables foreach walkthrough.
This is still wrong. fill_file() is not allowed to sleep. So you can not use a rwlock in here. fill_file is called inside a allprocess LIST_FOREACH loop and sleeping there will blow up. Maybe it is enough to grab a shared NETLOCK around the LIST_FOREACH() to ensure that we don't sleep inside. Please fix this properly. Right now running fstat is like playing russian roulette. > Index: sys/kern/kern_sysctl.c > =================================================================== > RCS file: /cvs/src/sys/kern/kern_sysctl.c,v > retrieving revision 1.411 > diff -u -p -r1.411 kern_sysctl.c > --- sys/kern/kern_sysctl.c 22 Jan 2023 12:05:44 -0000 1.411 > +++ sys/kern/kern_sysctl.c 27 Apr 2023 10:18:01 -0000 > @@ -1173,14 +1173,11 @@ fill_file(struct kinfo_file *kf, struct > > if (so == NULL) { > so = (struct socket *)fp->f_data; > + solock_shared(so); > + locked = 1; > + } else { > /* 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; > - } > + soassertlocked(so); > } > > kf->so_type = so->so_type; > @@ -1203,14 +1200,13 @@ fill_file(struct kinfo_file *kf, struct > kf->so_splicelen = -1; > if (so->so_pcb == NULL) { > if (locked) > - NET_UNLOCK(); > + sounlock_shared(so); > break; > } > switch (kf->so_family) { > 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; > @@ -1232,7 +1228,6 @@ fill_file(struct kinfo_file *kf, struct > 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; > @@ -1279,7 +1274,7 @@ fill_file(struct kinfo_file *kf, struct > } > } > if (locked) > - NET_UNLOCK(); > + sounlock_shared(so); > break; > } > > @@ -1375,7 +1370,7 @@ sysctl_file(int *name, u_int namelen, ch > if (arg == DTYPE_SOCKET) { > struct inpcb *inp; > > - NET_LOCK(); > + NET_LOCK_SHARED(); > mtx_enter(&tcbtable.inpt_mtx); > TAILQ_FOREACH(inp, &tcbtable.inpt_queue, inp_queue) > FILLSO(inp->inp_socket); > @@ -1395,7 +1390,7 @@ sysctl_file(int *name, u_int namelen, ch > FILLSO(inp->inp_socket); > mtx_leave(&rawin6pcbtable.inpt_mtx); > #endif > - NET_UNLOCK(); > + NET_UNLOCK_SHARED(); > } > fp = NULL; > while ((fp = fd_iterfile(fp, p)) != NULL) { > -- :wq Claudio