From owner-svn-src-all@FreeBSD.ORG Fri Sep 24 13:06:53 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 91C2C106566B; Fri, 24 Sep 2010 13:06:53 +0000 (UTC) (envelope-from kostikbel@gmail.com) Received: from mail.zoral.com.ua (mx0.zoral.com.ua [91.193.166.200]) by mx1.freebsd.org (Postfix) with ESMTP id B455E8FC22; Fri, 24 Sep 2010 13:06:52 +0000 (UTC) Received: from deviant.kiev.zoral.com.ua (root@deviant.kiev.zoral.com.ua [10.1.1.148]) by mail.zoral.com.ua (8.14.2/8.14.2) with ESMTP id o8OD6ibW098366 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Fri, 24 Sep 2010 16:06:44 +0300 (EEST) (envelope-from kostikbel@gmail.com) Received: from deviant.kiev.zoral.com.ua (kostik@localhost [127.0.0.1]) by deviant.kiev.zoral.com.ua (8.14.4/8.14.4) with ESMTP id o8OD6iJQ040830; Fri, 24 Sep 2010 16:06:44 +0300 (EEST) (envelope-from kostikbel@gmail.com) Received: (from kostik@localhost) by deviant.kiev.zoral.com.ua (8.14.4/8.14.4/Submit) id o8OD6ig8040829; Fri, 24 Sep 2010 16:06:44 +0300 (EEST) (envelope-from kostikbel@gmail.com) X-Authentication-Warning: deviant.kiev.zoral.com.ua: kostik set sender to kostikbel@gmail.com using -f Date: Fri, 24 Sep 2010 16:06:44 +0300 From: Kostik Belousov To: pluknet Message-ID: <20100924130644.GI34228@deviant.kiev.zoral.com.ua> References: <201009160756.o8G7uZrg065332@svn.freebsd.org> <20100924115311.GH34228@deviant.kiev.zoral.com.ua> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="+Z7/5fzWRHDJ0o7Q" Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.4.2.3i X-Virus-Scanned: clamav-milter 0.95.2 at skuns.kiev.zoral.com.ua X-Virus-Status: Clean X-Spam-Status: No, score=-3.4 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_00, DNS_FROM_OPENWHOIS autolearn=no version=3.2.5 X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on skuns.kiev.zoral.com.ua Cc: svn-src-head@freebsd.org, svn-src-all@freebsd.org, src-committers@freebsd.org, Dag-Erling Smorgrav Subject: Re: svn commit: r212723 - head/sys/compat/linprocfs X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 24 Sep 2010 13:06:53 -0000 --+Z7/5fzWRHDJ0o7Q Content-Type: text/plain; charset=koi8-r Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Fri, Sep 24, 2010 at 04:24:18PM +0400, pluknet wrote: > 2010/9/24 Kostik Belousov : > > On Fri, Sep 24, 2010 at 02:17:29PM +0400, pluknet wrote: > >> On 16 September 2010 11:56, Dag-Erling Smorgrav wrot= e: > >> > Author: des > >> > Date: Thu Sep 16 07:56:34 2010 > >> > New Revision: 212723 > >> > URL: http://svn.freebsd.org/changeset/base/212723 > >> > > >> > Log: > >> > =9AImplement proc/$$/environment. > >> > > >> [...] > >> > >> > =9A/* > >> > =9A* Filler function for proc/pid/environ > >> > =9A*/ > >> > =9Astatic int > >> > =9Alinprocfs_doprocenviron(PFS_FILL_ARGS) > >> > =9A{ > >> > + =9A =9A =9A int ret; > >> > > >> > - =9A =9A =9A sbuf_printf(sb, "doprocenviron\n%c", '\0'); > >> > - =9A =9A =9A return (0); > >> > + =9A =9A =9A PROC_LOCK(p); > >> > >> With this change I observe the following sleepable after non-sleepable: > >> > [LOR there] > >> > >> > >> > + > >> > + =9A =9A =9A if ((ret =3D p_cansee(td, p)) !=3D 0) { > >> > + =9A =9A =9A =9A =9A =9A =9A PROC_UNLOCK(p); > >> > + =9A =9A =9A =9A =9A =9A =9A return ret; > >> > + =9A =9A =9A } > >> > + > >> > + =9A =9A =9A ret =3D linprocfs_doargv(td, p, sb, ps_string_env); > >> > + =9A =9A =9A PROC_UNLOCK(p); > >> > + =9A =9A =9A return (ret); > >> > =9A} > > > > This is easy to fix, isn't it ? But there seems to be much more nits. > > > > First, allocating 512 * sizeof(char *)-byte object on the stack is not > > good. > > > > Second, the initialization of iov_len for reading the array > > of string pointers misses '* sizeof(char *)'. > > > > And third (probably fatal) is the lack of checks that the end of > > array and each string fits into the user portion of the map. I do not > > see why addr that already has u_long type is casted to u_long. Also, > > VM_MIN_ADDRESS, VM_MAXUSER_ADDRESS constants are for the native host > > FreeBSD ABI, they may differ from the target process limits. > > >=20 > Thanks for quick reaction. >=20 > As for the latter, something doesn't quite work here. > I see EFAULT against i386 process running on amd64. Right, the COMPAT_FREEBSD32 case should properly convert both struct ps_strings and array of pointers to the host structures. So this is fourth issue. diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linpro= cfs.c index c7fe158..db837e2 100644 --- a/sys/compat/linprocfs/linprocfs.c +++ b/sys/compat/linprocfs/linprocfs.c @@ -96,6 +96,10 @@ __FBSDID("$FreeBSD$"); #include #endif /* __i386__ || __amd64__ */ =20 +#ifdef COMPAT_FREEBSD32 +#include +#endif + #ifdef COMPAT_LINUX32 /* XXX */ #include #else @@ -951,13 +955,14 @@ linprocfs_doargv(struct thread *td, struct proc *p, s= truct sbuf *sb, struct iovec iov; struct uio tmp_uio; struct ps_strings pss; - int ret, i, n_elements, found_end; - u_long addr; - char* env_vector[MAX_ARGV_STR]; + int ret, i, n_elements, elm_len, found_end; + u_long addr, pbegin; + char **env_vector; char env_string[UIO_CHUNK_SZ]; - char *pbegin; - - +#ifdef COMPAT_FREEBSD32 + struct freebsd32_ps_strings pss32; + uint32_t ptr; +#endif =20 #define UIO_HELPER(uio, iov, base, len, cnt, offset, sz, flg, rw, td) \ do { \ @@ -971,63 +976,112 @@ do { \ uio.uio_rw =3D (rw); \ uio.uio_td =3D (td); \ } while (0) - - UIO_HELPER(tmp_uio, iov, &pss, sizeof(struct ps_strings), 1, - (off_t)(p->p_sysent->sv_psstrings), sizeof(struct ps_strings), - UIO_SYSSPACE, UIO_READ, td); - - ret =3D proc_rwmem(p, &tmp_uio); - if (ret !=3D 0) - return ret; +#define VALID_USER_ADDR(addr) \ + ((addr) >=3D p->p_sysent->sv_minuser && (addr) < p->p_sysent->sv_maxuser) + + env_vector =3D malloc(sizeof(char *) * MAX_ARGV_STR, M_TEMP, M_WAITOK); + +#ifdef COMPAT_FREEBSD32 + if ((p->p_sysent->sv_flags & SV_ILP32) !=3D 0) { + UIO_HELPER(tmp_uio, iov, &pss32, sizeof(pss32), 1, + (off_t)(p->p_sysent->sv_psstrings), + sizeof(pss32), UIO_SYSSPACE, UIO_READ, td); + ret =3D proc_rwmem(p, &tmp_uio); + if (ret !=3D 0) + goto done; + pss.ps_argvstr =3D PTRIN(pss32.ps_argvstr); + pss.ps_nargvstr =3D pss32.ps_nargvstr; + pss.ps_envstr =3D PTRIN(pss32.ps_envstr); + pss.ps_nenvstr =3D pss32.ps_nenvstr; + + elm_len =3D MAX_ARGV_STR * sizeof(int32_t); + } else { +#endif + UIO_HELPER(tmp_uio, iov, &pss, sizeof(pss), 1, + (off_t)(p->p_sysent->sv_psstrings), + sizeof(pss), UIO_SYSSPACE, UIO_READ, td); + ret =3D proc_rwmem(p, &tmp_uio); + if (ret !=3D 0) + goto done; + + elm_len =3D MAX_ARGV_STR * sizeof(char *); +#ifdef COMPAT_FREEBSD32 + } +#endif =20 /* Get the array address and the number of elements */ resolver(pss, &addr, &n_elements); =20 /* Consistent with lib/libkvm/kvm_proc.c */ - if (n_elements > MAX_ARGV_STR || (u_long)addr < VM_MIN_ADDRESS || - (u_long)addr >=3D VM_MAXUSER_ADDRESS) { - /* What error code should we return? */ - return 0; + if (n_elements > MAX_ARGV_STR || !VALID_USER_ADDR(addr) || + !VALID_USER_ADDR(addr + elm_len)) { + ret =3D EFAULT; + goto done; } =20 - UIO_HELPER(tmp_uio, iov, env_vector, MAX_ARGV_STR, 1, - (vm_offset_t)(addr), iov.iov_len, UIO_SYSSPACE, UIO_READ, td); +#ifdef COMPAT_FREEBSD32 + if ((p->p_sysent->sv_flags & SV_ILP32) !=3D 0) { + for (i =3D 0; i < MAX_ARGV_STR; i++) { + UIO_HELPER(tmp_uio, iov, &ptr, sizeof(ptr), 1, + (vm_offset_t)(addr + i * sizeof(uint32_t)), + iov.iov_len, UIO_SYSSPACE, UIO_READ, td); + ret =3D proc_rwmem(p, &tmp_uio); + if (ret !=3D 0) + goto done; + env_vector[i] =3D PTRIN(ptr); + } + } else { +#endif + UIO_HELPER(tmp_uio, iov, env_vector, elm_len, 1, + (vm_offset_t)(addr), iov.iov_len, UIO_SYSSPACE, UIO_READ, + td); + ret =3D proc_rwmem(p, &tmp_uio); + if (ret !=3D 0) + goto done; +#ifdef COMPAT_FREEBSD32 + } +#endif =20 - ret =3D proc_rwmem(p, &tmp_uio); - if (ret !=3D 0) - return ret; =20 /* Now we can iterate through the list of strings */ for (i =3D 0; i < n_elements; i++) { found_end =3D 0; - pbegin =3D env_vector[i]; - while(!found_end) { + pbegin =3D (vm_offset_t)env_vector[i]; + while (!found_end) { + if (!VALID_USER_ADDR(pbegin) || + !VALID_USER_ADDR(pbegin + sizeof(env_string))) { + ret =3D EFAULT; + goto done; + } UIO_HELPER(tmp_uio, iov, env_string, sizeof(env_string), 1, - (vm_offset_t) pbegin, iov.iov_len, UIO_SYSSPACE, - UIO_READ, td); + pbegin, iov.iov_len, UIO_SYSSPACE, UIO_READ, td); =20 - ret =3D proc_rwmem(p, &tmp_uio); - if (ret !=3D 0) - return ret; + ret =3D proc_rwmem(p, &tmp_uio); + if (ret !=3D 0) { + ret =3D 0; + goto done; + } =20 - if (!strvalid(env_string, UIO_CHUNK_SZ)) { + if (!strvalid(env_string, UIO_CHUNK_SZ)) { /* - * We didn't find the end of the string + * We didn't find the end of the string. * Add the string to the buffer and move - * the pointer + * the pointer. */ sbuf_bcat(sb, env_string, UIO_CHUNK_SZ); - pbegin =3D &(*pbegin) + UIO_CHUNK_SZ; - } else { + pbegin +=3D UIO_CHUNK_SZ; + } else found_end =3D 1; - } } sbuf_printf(sb, "%s", env_string); } =20 +#undef VALID_USER_ADDR #undef UIO_HELPER =20 - return (0); +done: + free(env_vector, M_TEMP); + return (ret); } =20 static void @@ -1052,9 +1106,11 @@ linprocfs_doprocenviron(PFS_FILL_ARGS) PROC_UNLOCK(p); return ret; } + _PHOLD(p); + PROC_UNLOCK(p); =20 ret =3D linprocfs_doargv(td, p, sb, ps_string_env); - PROC_UNLOCK(p); + PRELE(p); return (ret); } =20 --+Z7/5fzWRHDJ0o7Q Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.10 (FreeBSD) iEYEARECAAYFAkycomQACgkQC3+MBN1Mb4gm+wCg5iz9Y7aJiRsIeucwFPQ3D/HC bewAoLN9HnfvWULhs4Vm6a36njMwqkcV =V696 -----END PGP SIGNATURE----- --+Z7/5fzWRHDJ0o7Q--