Date: Sat, 29 Oct 2011 13:32:39 +0300 From: Mikolaj Golub <trociny@freebsd.org> To: Kostik Belousov <kostikbel@gmail.com> Cc: freebsd-hackers@freebsd.org, Robert Watson <rwatson@freebsd.org> Subject: Re: "ps -e" without procfs(5) Message-ID: <86aa8k2im0.fsf@kopusha.home.net> References: <86y5wkeuw9.fsf@kopusha.home.net> <20111016171005.GB50300@deviant.kiev.zoral.com.ua> <86aa8qozyx.fsf@kopusha.home.net> <20111025082451.GO50300@deviant.kiev.zoral.com.ua>
index | next in thread | previous in thread | raw e-mail
[-- Attachment #1 --]
KB> On Tue, Oct 25, 2011 at 12:13:10AM +0300, Mikolaj Golub wrote:
>>
>> On Sun, 16 Oct 2011 20:10:05 +0300 Kostik Belousov wrote:
>>
>> KB> In my opinion, the way to implement the feature is to (re)use
>> KB> linprocfs_doargv() and provide another kern.proc sysctl to retrieve the
>> KB> argv and env vectors. Then, ps(1) and procstat(1) can use it, as well as
>> KB> procfs and linprocfs inside the kernel.
>>
>> Thanks! I am testing a patch (without auxv vector so far) and have some
>> questions.
>>
>> Original ps -e returns environment only for user owned processes (the access is
>> restricted by the permissions of /proc/pid/mem file). My kern.proc.env sysctl
>> does not have such a restriction. I suppose I should add it? What function I
>> could use for this?
>>
>> BTW, linprocfs allows to read other user's environment.
KB> linprocfs uses p_cansee() to check the permissions. There are sysctls
KB> security.bsd.see_other_{ug}ids that control the behaviour.
KB> I believe that the new sysctl shall use the same check.
>>
>> KB> While you are at the code, it would be useful to also export the auxv vector,
>> KB> which is immediately before env.
>>
>> It looks I can find the location of auxv but what about the size? Or do you
>> propose to extend struct ps_strings to store location and size of auxv? I
>> could do this way...
KB> No, extending ps_strings is not needed and it is too radical change.
KB> The auxv vector must end by the AT_NULL aux entry. You can also artificially
KB> limit the amount of read aux vectors to, say, 256, which is much more then
KB> it is currently defined.
What do you think about the attached patch? This is a kernel
part. COMPAT_FREEBSD32 has not been tested after the last update (just checked
that it compiles): it looks I will not have access to amd64 box for testing
during the weekend. I will test it after the weekend.
Both kernel and userland parts are available here:
http://people.freebsd.org/~trociny/env.sys.patch
http://people.freebsd.org/~trociny/env.user.patch
Currently there is an issue with procstat -x: if one tried to run it on 64 bit
for a 32 bit process it would not detect this so would output a garbage. Could
somebody recommend a way how to get this info about a process from userlend?
--
Mikolaj Golub
[-- Attachment #2 --]
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index fb97913..4949f98 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -168,6 +168,7 @@ struct p_sched;
struct proc;
struct procdesc;
struct racct;
+struct sbuf;
struct sleepqueue;
struct td_sched;
struct thread;
@@ -843,6 +844,10 @@ int p_canwait(struct thread *td, struct proc *p);
struct pargs *pargs_alloc(int len);
void pargs_drop(struct pargs *pa);
void pargs_hold(struct pargs *pa);
+int proc_getargv(struct thread *td, struct proc *p, struct sbuf *sb,
+ size_t nchr);
+int proc_getenvv(struct thread *td, struct proc *p, struct sbuf *sb,
+ size_t nchr);
void procinit(void);
void proc_linkup0(struct proc *p, struct thread *td);
void proc_linkup(struct proc *p, struct thread *td);
diff --git a/sys/sys/sysctl.h b/sys/sys/sysctl.h
index 1e879f5..99ea342 100644
--- a/sys/sys/sysctl.h
+++ b/sys/sys/sysctl.h
@@ -559,6 +559,8 @@ SYSCTL_ALLOWED_TYPES(UINT64, uint64_t *a; unsigned long long *b; );
#define KERN_PROC_VMMAP 32 /* VM map entries for process */
#define KERN_PROC_FILEDESC 33 /* File descriptors for process */
#define KERN_PROC_GROUPS 34 /* process groups */
+#define KERN_PROC_ENV 35 /* get environment */
+#define KERN_PROC_AUXV 36 /* get ELF auxiliary vector */
/*
* KERN_IPC identifiers
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 998e7ca..ef4055a 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -41,6 +41,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/exec.h>
#include <sys/kernel.h>
#include <sys/limits.h>
#include <sys/lock.h>
@@ -49,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mount.h>
#include <sys/mutex.h>
#include <sys/proc.h>
+#include <sys/ptrace.h>
#include <sys/refcount.h>
#include <sys/sbuf.h>
#include <sys/sysent.h>
@@ -66,6 +68,8 @@ __FBSDID("$FreeBSD$");
#include <sys/vnode.h>
#include <sys/eventhandler.h>
+#include <machine/elf.h>
+
#ifdef DDB
#include <ddb/ddb.h>
#endif
@@ -1356,6 +1360,218 @@ pargs_drop(struct pargs *pa)
pargs_free(pa);
}
+static int
+proc_read_mem(struct thread *td, struct proc *p, vm_offset_t offset, void* buf,
+ size_t len)
+{
+ struct iovec iov;
+ struct uio uio;
+
+ iov.iov_base = (caddr_t)buf;
+ iov.iov_len = len;
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_offset = offset;
+ uio.uio_resid = (ssize_t)len;
+ uio.uio_segflg = UIO_SYSSPACE;
+ uio.uio_rw = UIO_READ;
+ uio.uio_td = td;
+
+ return (proc_rwmem(p, &uio));
+}
+
+#define PROC_AUXV_MAX 256 /* Limit on auxv size. */
+
+enum proc_vector_type {
+ PROC_ARG,
+ PROC_ENV,
+ PROC_AUX,
+};
+
+#ifdef COMPAT_FREEBSD32
+static int
+get_proc_vector32(struct thread *td, struct proc *p, char ***proc_vectorp,
+ size_t *vsizep, enum proc_vector_type type)
+{
+ struct freebsd32_ps_strings pss;
+ Elf32_Auxinfo aux;
+ vm_offset_t vptr, ptr;
+ uint32_t *proc_vector32;
+ char **proc_vector;
+ size_t vsize, size;
+ int i, error;
+
+ error = proc_read_mem(td, p, (vm_offset_t)(p->p_sysent->sv_psstrings),
+ &pss, sizeof(pss));
+ if (error != 0)
+ return (error);
+ switch (type) {
+ case PROC_ARG:
+ vptr = (vm_offset_t)PTRIN(pss.ps_argvstr);
+ vsize = pss.ps_nargvstr;
+ size = vsize * sizeof(int32_t);
+ break;
+ case PROC_ENV:
+ vptr = (vm_offset_t)PTRIN(pss.ps_envstr);
+ vsize = pss.ps_nenvstr;
+ size = vsize * sizeof(int32_t);
+ break;
+ case PROC_AUX:
+ vptr = ptr = (vm_offset_t)PTRIN(pss.ps_envstr) +
+ (pss.ps_nenvstr + 1) * sizeof(int32_t);
+ for (i = 0; i < PROC_AUXV_MAX; i++) {
+ error = proc_read_mem(td, p, ptr, &aux, sizeof(aux));
+ if (error != 0)
+ return (error);
+ if (aux.a_type == AT_NULL)
+ break;
+ ptr += sizeof(aux);
+ }
+ if (aux.a_type != AT_NULL) {
+ *proc_vectorp = NULL;
+ *vsizep = 0;
+ return (0);
+ }
+ vsize = i + 1;
+ size = vsize * sizeof(aux);
+ break;
+ default:
+ KASSERT(0, ("Wrong proc vector type: %d", type));
+ }
+ proc_vector32 = malloc(size, M_TEMP, M_WAITOK);
+ error = proc_read_mem(td, p, vptr, proc_vector32, size);
+ if (error != 0)
+ goto done;
+ if (type == PROC_AUX) {
+ *proc_vectorp = (char **)proc_vector32;
+ *vsizep = vsize;
+ return (0);
+ }
+ proc_vector = malloc(vsize * sizeof(char *), M_TEMP, M_WAITOK);
+ for (i = 0; i < (int)vsize; i++)
+ proc_vector[i] = PTRIN(proc_vector32[i]);
+ *proc_vectorp = proc_vector;
+ *vsizep = vsize;
+done:
+ free(proc_vector32, M_TEMP);
+ return (error);
+}
+#endif
+
+static int
+get_proc_vector(struct thread *td, struct proc *p, char ***proc_vectorp,
+ size_t *vsizep, enum proc_vector_type type)
+{
+ struct ps_strings pss;
+ Elf_Auxinfo aux;
+ vm_offset_t vptr, ptr;
+ char **proc_vector;
+ size_t vsize, size;
+ int error, i;
+
+#ifdef COMPAT_FREEBSD32
+ if (SV_PROC_FLAG(p, SV_ILP32) != 0)
+ return (get_proc_vector32(td, p, proc_vectorp, vsizep, type));
+#endif
+ error = proc_read_mem(td, p, (vm_offset_t)(p->p_sysent->sv_psstrings),
+ &pss, sizeof(pss));
+ if (error != 0)
+ return (error);
+ switch (type) {
+ case PROC_ARG:
+ vptr = (vm_offset_t)pss.ps_argvstr;
+ vsize = pss.ps_nargvstr;
+ size = vsize * sizeof(char *);
+ break;
+ case PROC_ENV:
+ vptr = (vm_offset_t)pss.ps_envstr;
+ vsize = pss.ps_nenvstr;
+ size = vsize * sizeof(char *);
+ break;
+ case PROC_AUX:
+ vptr = ptr = (vm_offset_t)pss.ps_envstr + (pss.ps_nenvstr + 1)
+ * sizeof(char *);
+ for (i = 0; i < PROC_AUXV_MAX; i++) {
+ error = proc_read_mem(td, p, ptr, &aux, sizeof(aux));
+ if (error != 0)
+ return (error);
+ if (aux.a_type == AT_NULL)
+ break;
+ ptr += sizeof(aux);
+ }
+ if (aux.a_type != AT_NULL) {
+ *proc_vectorp = NULL;
+ *vsizep = 0;
+ return (0);
+ }
+ vsize = i + 1;
+ size = vsize * sizeof(aux);
+ break;
+ default:
+ KASSERT(0, ("Wrong proc vector type: %d", type));
+ }
+ proc_vector = malloc(size, M_TEMP, M_WAITOK);
+ error = proc_read_mem(td, p, vptr, proc_vector, size);
+ if (error != 0) {
+ free(proc_vector, M_TEMP);
+ return (error);
+ }
+ *proc_vectorp = proc_vector;
+ *vsizep = vsize;
+
+ return (0);
+}
+
+#define GET_PS_STRINGS_CHUNK_SZ 256 /* Chunk size (bytes) for ps_strings operations. */
+
+static int
+get_ps_strings(struct thread *td, struct proc *p, struct sbuf *sb,
+ enum proc_vector_type type, size_t nchr)
+{
+ vm_offset_t offset;
+ size_t done, len, vsize;
+ int error, i;
+ char **proc_vector;
+ char pss_string[GET_PS_STRINGS_CHUNK_SZ];
+
+ error = get_proc_vector(td, p, &proc_vector, &vsize, type);
+ if (error != 0)
+ return (error);
+ for (done = 0, i = 0; i < (int)vsize && done < nchr; i++) {
+ for (offset = (vm_offset_t)proc_vector[i]; ;
+ offset += GET_PS_STRINGS_CHUNK_SZ) {
+ error = proc_read_mem(td, p, offset, pss_string,
+ sizeof(pss_string));
+ if (error != 0)
+ goto done;
+ len = strnlen(pss_string, GET_PS_STRINGS_CHUNK_SZ);
+ if (done + len >= nchr)
+ len = nchr - done - 1;
+ sbuf_bcat(sb, pss_string, len);
+ if (len != GET_PS_STRINGS_CHUNK_SZ)
+ break;
+ done += GET_PS_STRINGS_CHUNK_SZ;
+ }
+ sbuf_bcat(sb, "", 1);
+ done += len + 1;
+ }
+done:
+ free(proc_vector, M_TEMP);
+ return (error);
+}
+
+int
+proc_getargv(struct thread *td, struct proc *p, struct sbuf *sb, size_t nchr)
+{
+ return (get_ps_strings(curthread, p, sb, PROC_ARG, nchr));
+}
+
+int
+proc_getenvv(struct thread *td, struct proc *p, struct sbuf *sb, size_t nchr)
+{
+ return (get_ps_strings(curthread, p, sb, PROC_ENV, nchr));
+}
+
/*
* This sysctl allows a process to retrieve the argument list or process
* title for another process without groping around in the address space
@@ -1369,7 +1585,8 @@ sysctl_kern_proc_args(SYSCTL_HANDLER_ARGS)
u_int namelen = arg2;
struct pargs *newpa, *pa;
struct proc *p;
- int error = 0;
+ struct sbuf sb;
+ int error = 0, error2;
if (namelen != 1)
return (EINVAL);
@@ -1389,11 +1606,24 @@ sysctl_kern_proc_args(SYSCTL_HANDLER_ARGS)
}
pa = p->p_args;
- pargs_hold(pa);
- PROC_UNLOCK(p);
- if (pa != NULL)
+ if (pa != NULL) {
+ pargs_hold(pa);
+ PROC_UNLOCK(p);
error = SYSCTL_OUT(req, pa->ar_args, pa->ar_length);
- pargs_drop(pa);
+ pargs_drop(pa);
+ } else if ((p->p_flag & (P_WEXIT | P_SYSTEM)) == 0) {
+ _PHOLD(p);
+ PROC_UNLOCK(p);
+ sbuf_new_for_sysctl(&sb, NULL, GET_PS_STRINGS_CHUNK_SZ, req);
+ error = proc_getargv(curthread, p, &sb, req->oldlen);
+ error2 = sbuf_finish(&sb);
+ PRELE(p);
+ sbuf_delete(&sb);
+ if (error == 0 && error2 != 0)
+ error = error2;
+ } else {
+ PROC_UNLOCK(p);
+ }
if (error != 0 || req->newptr == NULL)
return (error);
@@ -1414,6 +1644,95 @@ sysctl_kern_proc_args(SYSCTL_HANDLER_ARGS)
}
/*
+ * This sysctl allows a process to retrieve environment of another process.
+ */
+static int
+sysctl_kern_proc_env(SYSCTL_HANDLER_ARGS)
+{
+ int *name = (int*) arg1;
+ u_int namelen = arg2;
+ struct proc *p;
+ struct sbuf sb;
+ int error, error2;
+
+ if (namelen != 1)
+ return (EINVAL);
+
+ p = pfind((pid_t)name[0]);
+ if (p == NULL)
+ return (ESRCH);
+ if (p->p_flag & P_WEXIT) {
+ PROC_UNLOCK(p);
+ return (ESRCH);
+ }
+ if ((error = p_candebug(curthread, p)) != 0) {
+ PROC_UNLOCK(p);
+ return (error);
+ }
+ if (p->p_flag & P_SYSTEM) {
+ PROC_UNLOCK(p);
+ return (0);
+ }
+ _PHOLD(p);
+ PROC_UNLOCK(p);
+ sbuf_new_for_sysctl(&sb, NULL, GET_PS_STRINGS_CHUNK_SZ, req);
+ error = proc_getenvv(curthread, p, &sb, req->oldlen);
+ error2 = sbuf_finish(&sb);
+ PRELE(p);
+ sbuf_delete(&sb);
+ return (error != 0 ? error : error2);
+}
+
+/*
+ * This sysctl allows a process to retrieve ELF auxiliary vector of
+ * another process.
+ */
+static int
+sysctl_kern_proc_auxv(SYSCTL_HANDLER_ARGS)
+{
+ int *name = (int*) arg1;
+ u_int namelen = arg2;
+ struct proc *p;
+ size_t vsize;
+ char **auxv;
+ int error;
+
+ if (namelen != 1)
+ return (EINVAL);
+
+ p = pfind((pid_t)name[0]);
+ if (p == NULL)
+ return (ESRCH);
+ if (p->p_flag & P_WEXIT) {
+ PROC_UNLOCK(p);
+ return (ESRCH);
+ }
+ if ((error = p_cansee(curthread, p)) != 0) {
+ PROC_UNLOCK(p);
+ return (error);
+ }
+ if (p->p_flag & P_SYSTEM) {
+ PROC_UNLOCK(p);
+ return (0);
+ }
+ _PHOLD(p);
+ PROC_UNLOCK(p);
+ error = get_proc_vector(curthread, p, &auxv, &vsize, PROC_AUX);
+ PRELE(p);
+ if (error == 0) {
+#ifdef COMPAT_FREEBSD32
+ if (SV_PROC_FLAG(p, SV_ILP32) != 0)
+ error = SYSCTL_OUT(req, auxv, vsize *
+ sizeof(Elf32_Auxinfo));
+ else
+#endif
+ error = SYSCTL_OUT(req, auxv, vsize * sizeof(Elf_Auxinfo));
+ free(auxv, M_TEMP);
+ }
+ return (error);
+}
+
+/*
* This sysctl allows a process to retrieve the path of the executable for
* itself or another process.
*/
@@ -2026,6 +2345,14 @@ static SYSCTL_NODE(_kern_proc, KERN_PROC_ARGS, args,
CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE,
sysctl_kern_proc_args, "Process argument list");
+static SYSCTL_NODE(_kern_proc, KERN_PROC_ENV, env,
+ CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE,
+ sysctl_kern_proc_env, "Process environment");
+
+static SYSCTL_NODE(_kern_proc, KERN_PROC_AUXV, auxv,
+ CTLFLAG_RW | CTLFLAG_ANYBODY | CTLFLAG_MPSAFE,
+ sysctl_kern_proc_auxv, "Process ELF auxiliary vector");
+
static SYSCTL_NODE(_kern_proc, KERN_PROC_PATHNAME, pathname, CTLFLAG_RD |
CTLFLAG_MPSAFE, sysctl_kern_proc_pathname, "Process executable path");
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
index 8832d3d..2f8ec1a 100644
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -919,150 +919,6 @@ linprocfs_doprocroot(PFS_FILL_ARGS)
return (0);
}
-#define MAX_ARGV_STR 512 /* Max number of argv-like strings */
-#define UIO_CHUNK_SZ 256 /* Max chunk size (bytes) for uiomove */
-
-static int
-linprocfs_doargv(struct thread *td, struct proc *p, struct sbuf *sb,
- void (*resolver)(const struct ps_strings, u_long *, int *))
-{
- struct iovec iov;
- struct uio tmp_uio;
- struct ps_strings pss;
- int ret, i, n_elements, elm_len;
- u_long addr, pbegin;
- char **env_vector, *envp;
- char env_string[UIO_CHUNK_SZ];
-#ifdef COMPAT_FREEBSD32
- struct freebsd32_ps_strings pss32;
- uint32_t *env_vector32;
-#endif
-
-#define UIO_HELPER(uio, iov, base, len, cnt, offset, sz, flg, rw, td) \
-do { \
- iov.iov_base = (caddr_t)(base); \
- iov.iov_len = (len); \
- uio.uio_iov = &(iov); \
- uio.uio_iovcnt = (cnt); \
- uio.uio_offset = (off_t)(offset); \
- uio.uio_resid = (sz); \
- uio.uio_segflg = (flg); \
- uio.uio_rw = (rw); \
- uio.uio_td = (td); \
-} while (0)
-
- env_vector = malloc(sizeof(char *) * MAX_ARGV_STR, M_TEMP, M_WAITOK);
-
-#ifdef COMPAT_FREEBSD32
- env_vector32 = NULL;
- if (SV_PROC_FLAG(p, SV_ILP32) != 0) {
- env_vector32 = malloc(sizeof(*env_vector32) * MAX_ARGV_STR,
- M_TEMP, M_WAITOK);
- elm_len = sizeof(int32_t);
- envp = (char *)env_vector32;
-
- UIO_HELPER(tmp_uio, iov, &pss32, sizeof(pss32), 1,
- (off_t)(p->p_sysent->sv_psstrings),
- sizeof(pss32), UIO_SYSSPACE, UIO_READ, td);
- ret = proc_rwmem(p, &tmp_uio);
- if (ret != 0)
- goto done;
- pss.ps_argvstr = PTRIN(pss32.ps_argvstr);
- pss.ps_nargvstr = pss32.ps_nargvstr;
- pss.ps_envstr = PTRIN(pss32.ps_envstr);
- pss.ps_nenvstr = pss32.ps_nenvstr;
- } else {
-#endif
- elm_len = sizeof(char *);
- envp = (char *)env_vector;
-
- UIO_HELPER(tmp_uio, iov, &pss, sizeof(pss), 1,
- (off_t)(p->p_sysent->sv_psstrings),
- sizeof(pss), UIO_SYSSPACE, UIO_READ, td);
- ret = proc_rwmem(p, &tmp_uio);
- if (ret != 0)
- goto done;
-#ifdef COMPAT_FREEBSD32
- }
-#endif
-
- /* Get the array address and the number of elements */
- resolver(pss, &addr, &n_elements);
-
- /* Consistent with lib/libkvm/kvm_proc.c */
- if (n_elements > MAX_ARGV_STR) {
- ret = E2BIG;
- goto done;
- }
-
- UIO_HELPER(tmp_uio, iov, envp, n_elements * elm_len, 1,
- (vm_offset_t)(addr), iov.iov_len, UIO_SYSSPACE, UIO_READ, td);
- ret = proc_rwmem(p, &tmp_uio);
- if (ret != 0)
- goto done;
-#ifdef COMPAT_FREEBSD32
- if (env_vector32 != NULL) {
- for (i = 0; i < n_elements; i++)
- env_vector[i] = PTRIN(env_vector32[i]);
- }
-#endif
-
- /* Now we can iterate through the list of strings */
- for (i = 0; i < n_elements; i++) {
- pbegin = (vm_offset_t)env_vector[i];
- for (;;) {
- UIO_HELPER(tmp_uio, iov, env_string, sizeof(env_string),
- 1, pbegin, iov.iov_len, UIO_SYSSPACE, UIO_READ, td);
- ret = proc_rwmem(p, &tmp_uio);
- if (ret != 0)
- goto done;
-
- if (!strvalid(env_string, UIO_CHUNK_SZ)) {
- /*
- * We didn't find the end of the string.
- * Add the string to the buffer and move
- * the pointer. But do not allow strings
- * of unlimited length.
- */
- sbuf_bcat(sb, env_string, UIO_CHUNK_SZ);
- if (sbuf_len(sb) >= ARG_MAX) {
- ret = E2BIG;
- goto done;
- }
- pbegin += UIO_CHUNK_SZ;
- } else {
- sbuf_cat(sb, env_string);
- break;
- }
- }
- sbuf_bcat(sb, "", 1);
- }
-#undef UIO_HELPER
-
-done:
- free(env_vector, M_TEMP);
-#ifdef COMPAT_FREEBSD32
- free(env_vector32, M_TEMP);
-#endif
- return (ret);
-}
-
-static void
-ps_string_argv(const struct ps_strings ps, u_long *addr, int *n)
-{
-
- *addr = (u_long) ps.ps_argvstr;
- *n = ps.ps_nargvstr;
-}
-
-static void
-ps_string_env(const struct ps_strings ps, u_long *addr, int *n)
-{
-
- *addr = (u_long) ps.ps_envstr;
- *n = ps.ps_nenvstr;
-}
-
/*
* Filler function for proc/pid/cmdline
*/
@@ -1090,9 +946,15 @@ linprocfs_doproccmdline(PFS_FILL_ARGS)
PROC_UNLOCK(p);
return (0);
}
+
+ if ((p->p_flag & (P_WEXIT | P_SYSTEM)) != 0) {
+ PROC_UNLOCK(p);
+ return (0);
+ }
+
PROC_UNLOCK(p);
- ret = linprocfs_doargv(td, p, sb, ps_string_argv);
+ ret = proc_getargv(td, p, sb, ARG_MAX);
return (ret);
}
@@ -1118,9 +980,15 @@ linprocfs_doprocenviron(PFS_FILL_ARGS)
PROC_UNLOCK(p);
return (0);
}
+
+ if ((p->p_flag & (P_WEXIT | P_SYSTEM)) != 0) {
+ PROC_UNLOCK(p);
+ return (0);
+ }
+
PROC_UNLOCK(p);
- ret = linprocfs_doargv(td, p, sb, ps_string_env);
+ ret = proc_getenvv(td, p, sb, ARG_MAX);
return (ret);
}
help
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?86aa8k2im0.fsf>
