kern/54604: Made 'ps -e' procfs-independent [PATCH].
Pawel Jakub Dawidek
nick at garage.freebsd.pl
Fri Jul 18 00:40:29 PDT 2003
>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:
More information about the freebsd-bugs
mailing list