Date: Fri, 18 Jul 2003 09:38:11 +0200 (CEST) From: Pawel Jakub Dawidek <nick@garage.freebsd.pl> To: FreeBSD-gnats-submit@FreeBSD.org Subject: kern/54604: Made 'ps -e' procfs-independent [PATCH]. Message-ID: <20030718073811.BCABE3ABB4D@milla.ask33.net> Resent-Message-ID: <200307180740.h6I7eI8t054810@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>Number: 54604 >Category: kern >Synopsis: Made 'ps -e' procfs-independent [PATCH]. >Confidential: no >Severity: non-critical >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Fri Jul 18 00:40:07 PDT 2003 >Closed-Date: >Last-Modified: >Originator: Pawel Jakub Dawidek >Release: FreeBSD 5.1-CURRENT i386 >Organization: >Environment: System: FreeBSD czort.hell.none FreeBSD 5.1-CURRENT i386 osreldate: 501102 >Description: For now, 'ps -e' depends on procfs. With this patch environment variables are stored as arguments and could be fetched via sysctls kern.proc.env.<PID>. By default kern.ps_envsopen sysctl is set to 0, but it should be save to set it to 1. I'm using pargs_ref_lock to protect environments reference count also, I think there is no need to create new mutex and duplicate existing functions (pargs_*). While I'm here, removed 'extern int ps_showallprocs' - there is no such variable in FreeBSD 5.x. >How-To-Repeat: Try to run 'ps -e' without procfs mounted. >Fix: Patch against FreeBSD 5.1-CURRENT, kern.osreldate: 501102. diff -upr /usr/src/bin/ps/ps.c src/bin/ps/ps.c --- /usr/src/bin/ps/ps.c Tue Jul 1 11:23:22 2003 +++ src/bin/ps/ps.c Fri Jul 18 09:11:09 2003 @@ -568,7 +568,7 @@ saveuser(KINFO *ki) } else { ki->ki_args = NULL; } - if (needenv && UREADOK(ki)) { + if (needenv && (UREADOK(ki) || (ki->ki_p->ki_envs != NULL))) { ki->ki_env = strdup(fmt(kvm_getenvv, ki, (char *)NULL, 0)); } else if (needenv) { ki->ki_env = malloc(3); diff -upr /usr/src/lib/libkvm/kvm_proc.c src/lib/libkvm/kvm_proc.c --- /usr/src/lib/libkvm/kvm_proc.c Tue Jul 1 11:27:05 2003 +++ src/lib/libkvm/kvm_proc.c Fri Jul 18 09:10:07 2003 @@ -188,6 +188,7 @@ kvm_proclist(kd, what, arg, p, bp, maxcn kp->ki_addr = proc.p_uarea; /* kp->ki_kstack = proc.p_thread.td_kstack; XXXKSE */ kp->ki_args = proc.p_args; + kp->ki_envs = proc.p_envs; kp->ki_tracep = proc.p_tracevp; kp->ki_textvp = proc.p_textvp; kp->ki_fd = proc.p_fd; @@ -834,13 +835,14 @@ kvm_doargv(kd, kp, nchr, info) } /* - * Get the command args. This code is now machine independent. + * Get the command args or envs. This code is now machine independent. */ -char ** -kvm_getargv(kd, kp, nchr) +static char ** +kvm_getargvenvv(kd, kp, nchr, args) kvm_t *kd; const struct kinfo_proc *kp; int nchr; + int args; /* 1 for args, 0 for envs */ { int oid[4]; int i; @@ -858,8 +860,13 @@ kvm_getargv(kd, kp, nchr) if (!buflen) { bufsz = sizeof(buflen); - i = sysctlbyname("kern.ps_arg_cache_limit", - &buflen, &bufsz, NULL, 0); + if (args) { + i = sysctlbyname("kern.ps_arg_cache_limit", &buflen, + &bufsz, NULL, 0); + } else { + i = sysctlbyname("kern.ps_env_cache_limit", &buflen, + &bufsz, NULL, 0); + } if (i == -1) { buflen = 0; } else { @@ -873,7 +880,7 @@ kvm_getargv(kd, kp, nchr) if (buf != NULL) { oid[0] = CTL_KERN; oid[1] = KERN_PROC; - oid[2] = KERN_PROC_ARGS; + oid[2] = args ? KERN_PROC_ARGS : KERN_PROC_ENVS; oid[3] = kp->ki_pid; bufsz = buflen; i = sysctl(oid, 4, buf, &bufsz, 0, 0); @@ -895,7 +902,17 @@ kvm_getargv(kd, kp, nchr) } if (kp->ki_flag & P_SYSTEM) return (NULL); - return (kvm_doargv(kd, kp, nchr, ps_str_a)); + return (kvm_doargv(kd, kp, nchr, args ? ps_str_a : ps_str_e)); +} + +char ** +kvm_getargv(kd, kp, nchr) + kvm_t *kd; + const struct kinfo_proc *kp; + int nchr; +{ + + return (kvm_getargvenvv(kd, kp, nchr, 1)); } char ** @@ -904,7 +921,8 @@ kvm_getenvv(kd, kp, nchr) const struct kinfo_proc *kp; int nchr; { - return (kvm_doargv(kd, kp, nchr, ps_str_e)); + + return (kvm_getargvenvv(kd, kp, nchr, 0)); } /* diff -upr /usr/src/sys/compat/linprocfs/linprocfs.c src/sys/compat/linprocfs/linprocfs.c --- /usr/src/sys/compat/linprocfs/linprocfs.c Tue Jul 1 11:28:26 2003 +++ src/sys/compat/linprocfs/linprocfs.c Fri Jul 18 00:09:38 2003 @@ -721,7 +721,15 @@ linprocfs_doproccmdline(PFS_FILL_ARGS) static int linprocfs_doprocenviron(PFS_FILL_ARGS) { - sbuf_printf(sb, "doprocenviron\n%c", '\0'); + + PROC_LOCK(p); + if (p->p_envs != NULL && (ps_envsopen || !p_cansee(td, p))) { + sbuf_bcpy(sb, p->p_envs->ar_envs, p->p_envs->ar_length); + PROC_UNLOCK(p); + } else { + PROC_UNLOCK(p); + sbuf_printf(sb, "doprocenviron\n%c", '\0'); + } return (0); } diff -upr /usr/src/sys/compat/svr4/svr4_misc.c src/sys/compat/svr4/svr4_misc.c --- /usr/src/sys/compat/svr4/svr4_misc.c Tue Jul 1 11:28:26 2003 +++ src/sys/compat/svr4/svr4_misc.c Thu Jul 17 22:08:13 2003 @@ -1343,9 +1343,10 @@ loop: q->p_ucred = NULL; /* - * Remove unused arguments + * Remove unused arguments and environment variables */ pargs_drop(q->p_args); + pargs_drop(q->p_envs); PROC_UNLOCK(q); /* diff -upr /usr/src/sys/kern/kern_exec.c src/sys/kern/kern_exec.c --- /usr/src/sys/kern/kern_exec.c Thu Jul 17 21:56:44 2003 +++ src/sys/kern/kern_exec.c Fri Jul 18 09:14:05 2003 @@ -95,8 +95,17 @@ u_long ps_arg_cache_limit = PAGE_SIZE / SYSCTL_ULONG(_kern, OID_AUTO, ps_arg_cache_limit, CTLFLAG_RW, &ps_arg_cache_limit, 0, ""); +u_long ps_env_cache_limit = PAGE_SIZE / 4; +SYSCTL_ULONG(_kern, OID_AUTO, ps_env_cache_limit, CTLFLAG_RW, + &ps_env_cache_limit, 0, ""); + int ps_argsopen = 1; -SYSCTL_INT(_kern, OID_AUTO, ps_argsopen, CTLFLAG_RW, &ps_argsopen, 0, ""); +SYSCTL_INT(_kern, OID_AUTO, ps_argsopen, CTLFLAG_RW, &ps_argsopen, 0, + "get/set arguments/proctitle"); + +int ps_envsopen = 0; +SYSCTL_INT(_kern, OID_AUTO, ps_envsopen, CTLFLAG_RW, &ps_envsopen, 0, + "get/set environment variables"); #ifdef __ia64__ /* XXX HACK */ @@ -159,11 +168,12 @@ kern_execve(td, fname, argv, envv, mac_p struct ucred *newcred = NULL, *oldcred; struct uidinfo *euip; register_t *stack_base; - int error, len, i; + int error, len, i, argslen, envslen; struct image_params image_params, *imgp; struct vattr attr; int (*img_first)(struct image_params *); struct pargs *oldargs = NULL, *newargs = NULL; + struct pargs *oldenvs = NULL, *newenvs = NULL; struct sigacts *oldsigacts, *newsigacts; #ifdef KTRACE struct vnode *tracevp = NULL; @@ -393,9 +403,12 @@ interpret: */ newcred = crget(); euip = uifind(attr.va_uid); - i = imgp->endargs - imgp->stringbase; - if (ps_arg_cache_limit >= i + sizeof(struct pargs)) - newargs = pargs_alloc(i); + argslen = imgp->endargs - imgp->startargs; + if (ps_arg_cache_limit >= argslen + sizeof(struct pargs)) + newargs = pargs_alloc(argslen); + envslen = imgp->endenvs - imgp->startenvs; + if (ps_env_cache_limit >= envslen + sizeof(struct pargs)) + newenvs = pargs_alloc(envslen); /* close files on exec */ fdcloseexec(td); @@ -577,11 +590,22 @@ interpret: p->p_args = NULL; /* Cache arguments if they fit inside our allowance */ - if (ps_arg_cache_limit >= i + sizeof(struct pargs)) { - bcopy(imgp->stringbase, newargs->ar_args, i); + if (ps_arg_cache_limit >= argslen + sizeof(struct pargs)) { + bcopy(imgp->startargs, newargs->ar_args, argslen); p->p_args = newargs; newargs = NULL; } + + /* Free any previous environment cache */ + oldenvs = p->p_envs; + p->p_envs = NULL; + + /* Cache environment variables if they fit inside our allowance */ + if (ps_env_cache_limit >= envslen + sizeof(struct pargs)) { + bcopy(imgp->startenvs, newenvs->ar_envs, envslen); + p->p_envs = newenvs; + newenvs = NULL; + } PROC_UNLOCK(p); /* Set values passed into the program in registers. */ @@ -618,6 +642,10 @@ done1: pargs_drop(oldargs); if (newargs != NULL) pargs_drop(newargs); + if (oldenvs != NULL) + pargs_drop(oldenvs); + if (newenvs != NULL) + pargs_drop(newenvs); if (oldsigacts != NULL) sigacts_free(oldsigacts); @@ -959,6 +987,8 @@ exec_extract_strings(imgp) imgp->envc++; } } + + imgp->endenvs = imgp->stringp; return (0); } diff -upr /usr/src/sys/kern/kern_fork.c src/sys/kern/kern_fork.c --- /usr/src/sys/kern/kern_fork.c Tue Jul 1 11:29:30 2003 +++ src/sys/kern/kern_fork.c Thu Jul 17 22:56:39 2003 @@ -511,6 +511,7 @@ again: td2->td_ucred = crhold(p2->p_ucred); /* XXXKSE */ pargs_hold(p2->p_args); + pargs_hold(p2->p_envs); if (flags & RFSIGSHARE) { p2->p_sigacts = sigacts_hold(p1->p_sigacts); diff -upr /usr/src/sys/kern/kern_proc.c src/sys/kern/kern_proc.c --- /usr/src/sys/kern/kern_proc.c Tue Jul 1 11:29:30 2003 +++ src/sys/kern/kern_proc.c Fri Jul 18 09:13:38 2003 @@ -643,6 +643,7 @@ fill_kinfo_thread(struct thread *td, str PROC_LOCK_ASSERT(p, MA_OWNED); kp->ki_addr =/* p->p_addr; */0; /* XXXKSE */ kp->ki_args = p->p_args; + kp->ki_envs = p->p_envs; kp->ki_textvp = p->p_textvp; #ifdef KTRACE kp->ki_tracep = p->p_tracevp; @@ -1092,9 +1093,12 @@ sysctl_kern_proc_args(SYSCTL_HANDLER_ARG if (!p) return (0); - if ((!ps_argsopen) && p_cansee(curthread, p)) { - PROC_UNLOCK(p); - return (0); + if (p_cansee(curthread, p)) { + if ((oidp->oid_number == KERN_PROC_ARGS && !ps_argsopen) || + (oidp->oid_number == KERN_PROC_ENVS && !ps_envsopen)) { + PROC_UNLOCK(p); + return (0); + } } if (req->newptr && curproc != p) { @@ -1102,7 +1106,10 @@ sysctl_kern_proc_args(SYSCTL_HANDLER_ARG return (EPERM); } - pa = p->p_args; + if (oidp->oid_number == KERN_PROC_ARGS) + pa = p->p_args; + else /* if (oidp->oid_number == KERN_PROC_ENVS) */ + pa = p->p_envs; pargs_hold(pa); PROC_UNLOCK(p); if (req->oldptr != NULL && pa != NULL) @@ -1111,8 +1118,13 @@ sysctl_kern_proc_args(SYSCTL_HANDLER_ARG if (error != 0 || req->newptr == NULL) return (error); - if (req->newlen + sizeof(struct pargs) > ps_arg_cache_limit) - return (ENOMEM); + if (oidp->oid_number == KERN_PROC_ARGS) { + if (req->newlen + sizeof(struct pargs) > ps_arg_cache_limit) + return (ENOMEM); + } else /* if (oidp->oid_number == KERN_PROC_ENVS) */ { + if (req->newlen + sizeof(struct pargs) > ps_env_cache_limit) + return (ENOMEM); + } newpa = pargs_alloc(req->newlen); error = SYSCTL_IN(req, newpa->ar_args, req->newlen); if (error != 0) { @@ -1120,8 +1132,13 @@ sysctl_kern_proc_args(SYSCTL_HANDLER_ARG return (error); } PROC_LOCK(p); - pa = p->p_args; - p->p_args = newpa; + if (oidp->oid_number == KERN_PROC_ARGS) { + pa = p->p_args; + p->p_args = newpa; + } else /* if (oidp->oid_number == KERN_PROC_ENVS) */ { + pa = p->p_envs; + p->p_envs = newpa; + } PROC_UNLOCK(p); pargs_drop(pa); return (0); @@ -1152,3 +1169,6 @@ SYSCTL_NODE(_kern_proc, KERN_PROC_PROC, SYSCTL_NODE(_kern_proc, KERN_PROC_ARGS, args, CTLFLAG_RW | CTLFLAG_ANYBODY, sysctl_kern_proc_args, "Process argument list"); + +SYSCTL_NODE(_kern_proc, KERN_PROC_ENVS, envs, CTLFLAG_RW | CTLFLAG_ANYBODY, + sysctl_kern_proc_args, "Process environment variable list"); diff -upr /usr/src/sys/sys/imgact.h src/sys/sys/imgact.h --- /usr/src/sys/sys/imgact.h Tue Nov 5 18:51:55 2002 +++ src/sys/sys/imgact.h Thu Jul 17 21:35:42 2003 @@ -53,8 +53,11 @@ struct image_params { struct vattr *attr; /* attributes of file */ const char *image_header; /* head of file to exec */ char *stringbase; /* base address of tmp string storage */ +#define startargs stringbase char *stringp; /* current 'end' pointer of tmp strings */ char *endargs; /* end of argv vector */ +#define startenvs endargs + char *endenvs; /* end of envv vector */ int stringspace; /* space left in tmp string storage area */ int argc, envc; /* count of argument and environment strings */ char *argv0; /* Replacement for argv[0] when interpreting */ diff -upr /usr/src/sys/sys/proc.h src/sys/sys/proc.h --- /usr/src/sys/sys/proc.h Sat Jun 28 10:29:04 2003 +++ src/sys/sys/proc.h Fri Jul 18 00:27:07 2003 @@ -109,6 +109,7 @@ struct pargs { u_int ar_ref; /* Reference count. */ u_int ar_length; /* Length. */ u_char ar_args[1]; /* Arguments. */ +#define ar_envs ar_args }; /*- @@ -590,6 +591,7 @@ struct proc { struct pgrp *p_pgrp; /* (c + e) Pointer to process group. */ struct sysentvec *p_sysent; /* (b) Syscall dispatch info. */ struct pargs *p_args; /* (c) Process arguments. */ + struct pargs *p_envs; /* (c) Process environment variables. */ rlim_t p_cpulimit; /* (j) Current CPU limit in seconds. */ /* End area that is copied on creation. */ #define p_endcopy p_xstat @@ -808,8 +810,9 @@ extern int hogticks; /* Limit on kerne extern int nprocs, maxproc; /* Current and max number of procs. */ extern int maxprocperuid; /* Max procs per uid. */ extern u_long ps_arg_cache_limit; +extern u_long ps_env_cache_limit; extern int ps_argsopen; -extern int ps_showallprocs; +extern int ps_envsopen; extern int sched_quantum; /* Scheduling quantum in ticks. */ LIST_HEAD(proclist, proc); diff -upr /usr/src/sys/sys/sysctl.h src/sys/sys/sysctl.h --- /usr/src/sys/sys/sysctl.h Thu Jul 17 21:55:26 2003 +++ src/sys/sys/sysctl.h Thu Jul 17 21:59:09 2003 @@ -412,7 +412,8 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_e #define KERN_PROC_UID 5 /* by effective uid */ #define KERN_PROC_RUID 6 /* by real uid */ #define KERN_PROC_ARGS 7 /* get/set arguments/proctitle */ -#define KERN_PROC_PROC 8 /* only return procs */ +#define KERN_PROC_ENVS 8 /* get/set environment variables */ +#define KERN_PROC_PROC 9 /* only return procs */ /* * KERN_IPC identifiers diff -upr /usr/src/sys/sys/user.h src/sys/sys/user.h --- /usr/src/sys/sys/user.h Tue May 13 22:36:02 2003 +++ src/sys/sys/user.h Fri Jul 18 00:42:04 2003 @@ -160,7 +160,8 @@ struct kinfo_proc { long ki_tdflags; /* XXXKSE kthread flag */ struct pcb *ki_pcb; /* kernel virtual addr of pcb */ void *ki_kstack; /* kernel virtual addr of stack */ - long ki_spare[22]; /* spare constants */ + struct pargs *ki_envs; /* address of environment variables */ + long ki_spare[21]; /* spare constants */ }; void fill_kinfo_proc(struct proc *, struct kinfo_proc *); >Release-Note: >Audit-Trail: >Unformatted:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20030718073811.BCABE3ABB4D>