diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2020-12-31 22:29:40 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2021-01-10 02:41:20 +0000 |
commit | 4daea938130b4a219e01d678e9499f0bdb715f82 (patch) | |
tree | f404049a57daf52ea4e78800470ac19f691b3c58 | |
parent | a008bdeda3b8278fe600cf83ecf44acd1ccb30b6 (diff) | |
download | src-4daea938130b4a219e01d678e9499f0bdb715f82.tar.gz src-4daea938130b4a219e01d678e9499f0bdb715f82.zip |
Lock proctree in around fill_kinfo_proc().
Proctree lock is needed for correct calculation and collection of the
job-control related data in kinfo_proc. There was even an XXX comment
about it.
Satisfy locking and lock ordering requirements by taking proctree lock
around pass over each bucket in proc_iterate(), and in sysctl_kern_proc()
and note_procstat_proc() for individual process reporting.
Reviewed by: jilles
Tested by: pho
MFC after: 2 weeks
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D27871
-rw-r--r-- | sys/kern/imgact_elf.c | 2 | ||||
-rw-r--r-- | sys/kern/kern_proc.c | 5 |
2 files changed, 7 insertions, 0 deletions
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index f6482bfcfb21..4f5d5a9a0736 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -2386,8 +2386,10 @@ __elfN(note_procstat_proc)(void *arg, struct sbuf *sb, size_t *sizep) KASSERT(*sizep == size, ("invalid size")); structsize = sizeof(elf_kinfo_proc_t); sbuf_bcat(sb, &structsize, sizeof(structsize)); + sx_slock(&proctree_lock); PROC_LOCK(p); kern_proc_out(p, sb, ELF_KERN_PROC_MASK); + sx_sunlock(&proctree_lock); } *sizep = size; } diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index fab1df795799..c63d136a3046 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -1653,6 +1653,7 @@ proc_iterate(int (*cb)(struct proc *, void *), void *cbarg) int error, i, j; for (i = 0; i < pidhashlock + 1; i++) { + sx_slock(&proctree_lock); sx_slock(&pidhashtbl_lock[i]); for (j = i; j <= pidhash; j += pidhashlock + 1) { LIST_FOREACH(p, &pidhashtbl[j], p_hash) { @@ -1662,11 +1663,13 @@ proc_iterate(int (*cb)(struct proc *, void *), void *cbarg) PROC_LOCK_ASSERT(p, MA_NOTOWNED); if (error != 0) { sx_sunlock(&pidhashtbl_lock[i]); + sx_sunlock(&proctree_lock); return (error); } } } sx_sunlock(&pidhashtbl_lock[i]); + sx_sunlock(&proctree_lock); } return (0); } @@ -1792,9 +1795,11 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS) error = sysctl_wire_old_buffer(req, 0); if (error) return (error); + sx_slock(&proctree_lock); error = pget((pid_t)name[0], PGET_CANSEE, &p); if (error == 0) error = sysctl_out_proc(p, req, flags); + sx_sunlock(&proctree_lock); return (error); } |