>Number: 148646 >Category: kern >Synopsis: Implementation of the "environ" file for the linprocfs >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Thu Jul 15 16:50:04 UTC 2010 >Closed-Date: >Last-Modified: >Originator: Fernando >Release: 8.0-RELEASE-p2 >Organization: Open Sistemas >Environment: FreeBSD beastie 8.0-RELEASE-p2 FreeBSD 8.0-RELEASE-p2 #4: Thu Mar 4 19:31:02 CET 2010 r...@beastie:/usr/obj/usr/src/sys/APEKERNEL amd64
>Description: The current version of linprocfs returns the string "doprocenviron". The patch attached below tries to implement the "environ" file that can be found under /proc/<PID>/ in a Linux procfs. The patch tries to be consistent with lib/libkvm/kvm_proc.c It was tested on a 8.0-RELEASE-p2 amd64 and on a 8.0-RELEASE i386 running on qemu. >How-To-Repeat: Just cat /compat/linux/proc/<PID>/environ >Fix: The attached patch could be an initial solution. Patch attached with submission follows: --- /sys/compat/linprocfs/linprocfs.c 2010-07-14 17:56:23.000000000 +0200 +++ linprocfs.c 2010-07-14 17:42:04.000000000 +0200 @@ -933,15 +933,130 @@ return (0); } +extern int proc_rwmem(struct proc *p, struct uio *uio); + +#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 *)) +{ + int ret, i, n_elements; + char *buff; + char* env_vector[MAX_ARGV_STR]; + char env_string[UIO_CHUNK_SZ]; + u_long addr; + struct iovec iov; + struct uio tmp_uio; + struct ps_strings *pss; + + buff = malloc(sizeof(struct ps_strings), M_TEMP, M_WAITOK); + + +#define UIO_HELPER(uio, iov, base, len, iovcnt, \ + offset, resid, segflg, rw, td) do { \ + iov.iov_base = (caddr_t) base; \ + iov.iov_len = len; \ + uio.uio_iov = &iov; \ + uio.uio_iovcnt = iovcnt; \ + uio.uio_offset = (off_t) offset;\ + uio.uio_resid = resid; \ + uio.uio_segflg = segflg; \ + uio.uio_rw = rw; \ + uio.uio_td = td; \ +} while (0) + + PROC_LOCK(p); + + UIO_HELPER(tmp_uio, iov, buff, sizeof(struct ps_strings), + 1, (off_t)(p->p_sysent->sv_psstrings), + sizeof(struct ps_strings), UIO_SYSSPACE, UIO_READ, td); + ret = proc_rwmem(p, &tmp_uio); + if (ret != 0) + return ret; + + pss = (struct ps_strings *)(buff); + + resolver(pss, &addr, &n_elements); + + /* Consistent with lib/libkvm/kvm_proc.c */ + if (n_elements > MAX_ARGV_STR || + (u_long)addr < VM_MIN_ADDRESS || + (u_long)addr >= VM_MAXUSER_ADDRESS) { + PROC_UNLOCK(p); + /* What error code should we return? */ + return 0; + } + + UIO_HELPER(tmp_uio, iov, env_vector, MAX_ARGV_STR, 1, + (vm_offset_t)(addr), iov.iov_len, UIO_SYSSPACE, UIO_READ, td); + ret = proc_rwmem(p, &tmp_uio); + if (ret != 0) + return ret; + + /* Now we can iterate through the list of strings */ + int found_end = 0; + char *pbegin; + for (i = 0; i < n_elements; i++) { + found_end = 0; + pbegin = env_vector[i]; + while(!found_end) { + UIO_HELPER(tmp_uio, iov, env_string, sizeof(env_string), + 1, (vm_offset_t) pbegin, iov.iov_len, UIO_SYSSPACE, UIO_READ, td); + ret = proc_rwmem(p, &tmp_uio); + if (ret != 0) + return ret; + + 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 + */ + sbuf_bcat(sb, env_string, UIO_CHUNK_SZ); + pbegin = &(*pbegin) + UIO_CHUNK_SZ; + } else { + found_end = 1; + } + } + sbuf_printf(sb, "%s", env_string); + } + + PROC_UNLOCK(p); +#undef UIO_HELPER + + + free(buff, M_TEMP); + + return (0); +} + +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/environ */ static int linprocfs_doprocenviron(PFS_FILL_ARGS) { + int ret; - sbuf_printf(sb, "doprocenviron\n%c", '\0'); - return (0); + PROC_LOCK(p); + if ((ret = p_cansee(td, p)) != 0) { + PROC_UNLOCK(p); + return ret; + } + + + PROC_UNLOCK(p); + return (linprocfs_doargv(td, p, sb, ps_string_env)); } /* >Release-Note: >Audit-Trail: >Unformatted: _______________________________________________ freebsd-bugs@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/freebsd-bugs To unsubscribe, send any mail to "freebsd-bugs-unsubscr...@freebsd.org"