diff options
author | Konstantin Belousov <kib@FreeBSD.org> | 2020-02-09 12:29:51 +0000 |
---|---|---|
committer | Konstantin Belousov <kib@FreeBSD.org> | 2020-02-09 12:29:51 +0000 |
commit | 48fcb463114eda4e5d6db9d709d5dbf53465852b (patch) | |
tree | 14c7c3e7266008ed6359c947ccbbb13f731aec2c /sys/kern/kern_proc.c | |
parent | fc908e500165fec250bea86310e7ae0eedc23af8 (diff) | |
download | src-48fcb463114eda4e5d6db9d709d5dbf53465852b.tar.gz src-48fcb463114eda4e5d6db9d709d5dbf53465852b.zip |
Notes
Diffstat (limited to 'sys/kern/kern_proc.c')
-rw-r--r-- | sys/kern/kern_proc.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index d74295269870..0ff776cf662d 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -2962,6 +2962,77 @@ sysctl_kern_proc_sigtramp(SYSCTL_HANDLER_ARGS) return (error); } +static int +sysctl_kern_proc_sigfastblk(SYSCTL_HANDLER_ARGS) +{ + int *name = (int *)arg1; + u_int namelen = arg2; + pid_t pid; + struct proc *p; + struct thread *td1; + uintptr_t addr; +#ifdef COMPAT_FREEBSD32 + uint32_t addr32; +#endif + int error; + + if (namelen != 1 || req->newptr != NULL) + return (EINVAL); + + pid = (pid_t)name[0]; + error = pget(pid, PGET_HOLD | PGET_NOTWEXIT | PGET_CANDEBUG, &p); + if (error != 0) + return (error); + + PROC_LOCK(p); +#ifdef COMPAT_FREEBSD32 + if (SV_CURPROC_FLAG(SV_ILP32)) { + if (!SV_PROC_FLAG(p, SV_ILP32)) { + error = EINVAL; + goto errlocked; + } + } +#endif + if (pid <= PID_MAX) { + td1 = FIRST_THREAD_IN_PROC(p); + } else { + FOREACH_THREAD_IN_PROC(p, td1) { + if (td1->td_tid == pid) + break; + } + } + if (td1 == NULL) { + error = ESRCH; + goto errlocked; + } + /* + * The access to the private thread flags. It is fine as far + * as no out-of-thin-air values are read from td_pflags, and + * usermode read of the td_sigblock_ptr is racy inherently, + * since target process might have already changed it + * meantime. + */ + if ((td1->td_pflags & TDP_SIGFASTBLOCK) != 0) + addr = (uintptr_t)td1->td_sigblock_ptr; + else + error = ENOTTY; + +errlocked: + _PRELE(p); + PROC_UNLOCK(p); + if (error != 0) + return (error); + +#ifdef COMPAT_FREEBSD32 + if (SV_CURPROC_FLAG(SV_ILP32)) { + addr32 = addr; + error = SYSCTL_OUT(req, &addr32, sizeof(addr32)); + } else +#endif + error = SYSCTL_OUT(req, &addr, sizeof(addr)); + return (error); +} + SYSCTL_NODE(_kern, KERN_PROC, proc, CTLFLAG_RD, 0, "Process table"); SYSCTL_PROC(_kern_proc, KERN_PROC_ALL, all, CTLFLAG_RD|CTLTYPE_STRUCT| @@ -3075,6 +3146,10 @@ static SYSCTL_NODE(_kern_proc, KERN_PROC_SIGTRAMP, sigtramp, CTLFLAG_RD | CTLFLAG_MPSAFE, sysctl_kern_proc_sigtramp, "Process signal trampoline location"); +static SYSCTL_NODE(_kern_proc, KERN_PROC_SIGFASTBLK, sigfastblk, CTLFLAG_RD | + CTLFLAG_ANYBODY | CTLFLAG_MPSAFE, sysctl_kern_proc_sigfastblk, + "Thread sigfastblock address"); + int allproc_gen; /* |