diff options
author | jhb <jhb@FreeBSD.org> | 2003-03-12 16:14:55 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2003-03-12 16:14:55 +0000 |
commit | 7510e91aa212259c9dc6299de44a3aa9ab9e0c8b (patch) | |
tree | 9fe79ec022ed441b321e534a644391a421526f0c /sys/kern/kern_proc.c | |
parent | 00b21712dfd88a8b0f5bb317c0ed75a6f7199ede (diff) | |
download | FreeBSD-src-7510e91aa212259c9dc6299de44a3aa9ab9e0c8b.zip FreeBSD-src-7510e91aa212259c9dc6299de44a3aa9ab9e0c8b.tar.gz |
- Avoid dropping the proc lock around a simple permissions check and just
hold hold it across the check to avoid extra lock operations in the
common case.
- Copy in the new args to a temporary pargs structure before we drop the
reference to the old one. Thus, if the copyin() fails, the process
arguments are unchanged rather than being deleted. Also, p_args is no
longer NULL during the sysctl operation.
Diffstat (limited to 'sys/kern/kern_proc.c')
-rw-r--r-- | sys/kern/kern_proc.c | 34 |
1 files changed, 16 insertions, 18 deletions
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index c444cb0..bbd080e 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -1025,7 +1025,7 @@ sysctl_kern_proc_args(SYSCTL_HANDLER_ARGS) int *name = (int*) arg1; u_int namelen = arg2; struct proc *p; - struct pargs *pa; + struct pargs *pa, *newpa; int error = 0; if (namelen != 1) @@ -1039,12 +1039,12 @@ sysctl_kern_proc_args(SYSCTL_HANDLER_ARGS) PROC_UNLOCK(p); return (0); } - PROC_UNLOCK(p); - if (req->newptr && curproc != p) + if (req->newptr && curproc != p) { + PROC_UNLOCK(p); return (EPERM); + } - PROC_LOCK(p); pa = p->p_args; pargs_hold(pa); PROC_UNLOCK(p); @@ -1055,24 +1055,22 @@ sysctl_kern_proc_args(SYSCTL_HANDLER_ARGS) if (req->newptr == NULL) return (error); + if (req->newlen + sizeof(struct pargs) > ps_arg_cache_limit) + return (error); + + newpa = pargs_alloc(req->newlen); + error = SYSCTL_IN(req, newpa->ar_args, req->newlen); + if (error) { + pargs_free(newpa); + return (error); + } + PROC_LOCK(p); pa = p->p_args; - p->p_args = NULL; + p->p_args = newpa; PROC_UNLOCK(p); pargs_drop(pa); - - if (req->newlen + sizeof(struct pargs) > ps_arg_cache_limit) - return (error); - - pa = pargs_alloc(req->newlen); - error = SYSCTL_IN(req, pa->ar_args, req->newlen); - if (!error) { - PROC_LOCK(p); - p->p_args = pa; - PROC_UNLOCK(p); - } else - pargs_free(pa); - return (error); + return (0); } SYSCTL_NODE(_kern, KERN_PROC, proc, CTLFLAG_RD, 0, "Process table"); |