From owner-freebsd-bugs@FreeBSD.ORG Thu Jul 15 16:50:04 2010 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id DF7BD1065691 for ; Thu, 15 Jul 2010 16:50:04 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id A460D8FC30 for ; Thu, 15 Jul 2010 16:50:04 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.4/8.14.4) with ESMTP id o6FGo4OY077121 for ; Thu, 15 Jul 2010 16:50:04 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.4/8.14.4/Submit) id o6FGo4iT077120; Thu, 15 Jul 2010 16:50:04 GMT (envelope-from gnats) Resent-Date: Thu, 15 Jul 2010 16:50:04 GMT Resent-Message-Id: <201007151650.o6FGo4iT077120@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Fernando Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 26036106566C for ; Thu, 15 Jul 2010 16:45:44 +0000 (UTC) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21]) by mx1.freebsd.org (Postfix) with ESMTP id 15ED78FC08 for ; Thu, 15 Jul 2010 16:45:44 +0000 (UTC) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.14.3/8.14.3) with ESMTP id o6FGjhmg020768 for ; Thu, 15 Jul 2010 16:45:43 GMT (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.14.3/8.14.3/Submit) id o6FGjhLf020766; Thu, 15 Jul 2010 16:45:43 GMT (envelope-from nobody) Message-Id: <201007151645.o6FGjhLf020766@www.freebsd.org> Date: Thu, 15 Jul 2010 16:45:43 GMT From: Fernando To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: kern/148646: Implementation of the "environ" file for the linprocfs X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 15 Jul 2010 16:50:05 -0000 >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 root@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// 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//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: