From owner-freebsd-amd64@FreeBSD.ORG Sun Aug 30 14:44:58 2009 Return-Path: Delivered-To: freebsd-amd64@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id A4764106566C; Sun, 30 Aug 2009 14:44:58 +0000 (UTC) (envelope-from kostikbel@gmail.com) Received: from mail.zoral.com.ua (skuns.zoral.com.ua [91.193.166.194]) by mx1.freebsd.org (Postfix) with ESMTP id E38D98FC17; Sun, 30 Aug 2009 14:44:57 +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 n7UEiqf9009063 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Sun, 30 Aug 2009 17:44:52 +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.3/8.14.3) with ESMTP id n7UEiqfx087454; Sun, 30 Aug 2009 17:44:52 +0300 (EEST) (envelope-from kostikbel@gmail.com) Received: (from kostik@localhost) by deviant.kiev.zoral.com.ua (8.14.3/8.14.3/Submit) id n7UEiqSU087453; Sun, 30 Aug 2009 17:44:52 +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: Sun, 30 Aug 2009 17:44:52 +0300 From: Kostik Belousov To: freebsd-amd64@freebsd.org Message-ID: <20090830144452.GK1881@deviant.kiev.zoral.com.ua> References: <20090824193344.GA34949@server.vk2pj.dyndns.org> <20090829233454.GA13036@server.vk2pj.dyndns.org> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha1; protocol="application/pgp-signature"; boundary="ef8eQmdvO1j1gFMO" Content-Disposition: inline In-Reply-To: <20090829233454.GA13036@server.vk2pj.dyndns.org> 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=-4.4 required=5.0 tests=ALL_TRUSTED,AWL,BAYES_00 autolearn=ham version=3.2.5 X-Spam-Checker-Version: SpamAssassin 3.2.5 (2008-06-10) on skuns.kiev.zoral.com.ua Cc: freebsd-current@freebsd.org Subject: Re: sshd failing in jail X-BeenThere: freebsd-amd64@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Porting FreeBSD to the AMD64 platform List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 30 Aug 2009 14:44:58 -0000 --ef8eQmdvO1j1gFMO Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Sun, Aug 30, 2009 at 09:34:54AM +1000, Peter Jeremy wrote: > [Redirected to amd64 because this is an amd64 kernel bug] >=20 > On 2009-Aug-25 05:33:44 +1000, Peter Jeremy wrote: > >I am attempting to build an i386 jail on an amd64 box to build > >packages for my netbook. The host is running -current from just over > >two weeks ago and the jail is -current from early June. The jail was > >built by doing a dump|restore of my netbook and then tweaking various > >config files to give it a new identity. The jail's devfs is using > >"devfsrules_jail" from /etc/default/devfs.rules. > > > >The jail starts OK but when I attempt to ssh into it, I just get > >"Connection closed by ". >=20 > Turns out this is a bug in the 32-bit select(2) wrapper on 64-bit > kernels. The userland fd_set arguments are not wrapped but passed > directly to kern_select(). Unfortunately, fd_set is (effectively) an > array of longs which means kern_select() assumes fd_set is a multiple > of 8-bytes whilst userland assumes it is a multiple of 4 bytes. As a > result, the kernel can over-write an extra 4 bytes of user memory. In > the case of sshd, this causes part of the RSA host key to be trashed > when privilege separation mode is enabled. >=20 > This bug also affects linux emulation on amd64 and potentially affects > any other 64-bit kernels with 32-bit emulation modes. I have raised > amd64/138318 to cover it. I do not think that we can go the proposed route, since changing the type of __fd_mask changes the type of fd_set. The later would not affect the kernel ABI, but definitely changes the ABI of any code that passes fd_sets. Also, looking closely at the issue you found, I think that copyin is the same problematic as copyout, since we can end up reading one more word then userspace supplied. This is not a problem only because most user code keeps fd_sets on stack. Could you test that the patch below fixes real sshd issue. At least, it passes your select test from the PR. diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/f= reebsd32_misc.c index 466aab4..71b22aa 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -589,7 +589,8 @@ freebsd32_select(struct thread *td, struct freebsd32_se= lect_args *uap) * XXX big-endian needs to convert the fd_sets too. * XXX Do pointers need PTRIN()? */ - return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp)); + return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp, + sizeof(int32_t) * 8)); } =20 /* diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c index 267da07..1d5eaf8 100644 --- a/sys/compat/linux/linux_misc.c +++ b/sys/compat/linux/linux_misc.c @@ -522,7 +522,7 @@ linux_select(struct thread *td, struct linux_select_arg= s *args) tvp =3D NULL; =20 error =3D kern_select(td, args->nfds, args->readfds, args->writefds, - args->exceptfds, tvp); + args->exceptfds, tvp, sizeof(l_int) * 8); =20 #ifdef DEBUG if (ldebug(select)) diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index bd0f279..6831fe8 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -774,12 +774,13 @@ select(td, uap) } else tvp =3D NULL; =20 - return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp)); + return (kern_select(td, uap->nd, uap->in, uap->ou, uap->ex, tvp, + NFDBITS)); } =20 int kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou, - fd_set *fd_ex, struct timeval *tvp) + fd_set *fd_ex, struct timeval *tvp, int abi_nfdbits) { struct filedesc *fdp; /* @@ -792,7 +793,7 @@ kern_select(struct thread *td, int nd, fd_set *fd_in, f= d_set *fd_ou, fd_mask *ibits[3], *obits[3], *selbits, *sbp; struct timeval atv, rtv, ttv; int error, timo; - u_int nbufbytes, ncpbytes, nfdbits; + u_int nbufbytes, ncpbytes, ncpubytes, nfdbits; =20 if (nd < 0) return (EINVAL); @@ -806,6 +807,7 @@ kern_select(struct thread *td, int nd, fd_set *fd_in, f= d_set *fd_ou, */ nfdbits =3D roundup(nd, NFDBITS); ncpbytes =3D nfdbits / NBBY; + ncpubytes =3D roundup(nd, abi_nfdbits) / NBBY; nbufbytes =3D 0; if (fd_in !=3D NULL) nbufbytes +=3D 2 * ncpbytes; @@ -832,9 +834,11 @@ kern_select(struct thread *td, int nd, fd_set *fd_in, = fd_set *fd_ou, ibits[x] =3D sbp + nbufbytes / 2 / sizeof *sbp; \ obits[x] =3D sbp; \ sbp +=3D ncpbytes / sizeof *sbp; \ - error =3D copyin(name, ibits[x], ncpbytes); \ + error =3D copyin(name, ibits[x], ncpubytes); \ if (error !=3D 0) \ goto done; \ + bzero((char *)ibits[x] + ncpubytes, \ + ncpbytes - ncpubytes); \ } \ } while (0) getbits(fd_in, 0); @@ -888,7 +892,7 @@ done: if (error =3D=3D EWOULDBLOCK) error =3D 0; #define putbits(name, x) \ - if (name && (error2 =3D copyout(obits[x], name, ncpbytes))) \ + if (name && (error2 =3D copyout(obits[x], name, ncpubytes))) \ error =3D error2; if (error =3D=3D 0) { int error2; diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h index d0f209c..e1c83cc 100644 --- a/sys/sys/syscallsubr.h +++ b/sys/sys/syscallsubr.h @@ -170,7 +170,7 @@ int kern_sched_rr_get_interval(struct thread *td, pid_t= pid, int kern_semctl(struct thread *td, int semid, int semnum, int cmd, union semun *arg, register_t *rval); int kern_select(struct thread *td, int nd, fd_set *fd_in, fd_set *fd_ou, - fd_set *fd_ex, struct timeval *tvp); + fd_set *fd_ex, struct timeval *tvp, int abi_nfdbits); int kern_sendfile(struct thread *td, struct sendfile_args *uap, struct uio *hdr_uio, struct uio *trl_uio, int compat); int kern_sendit(struct thread *td, int s, struct msghdr *mp, int flags, --ef8eQmdvO1j1gFMO Content-Type: application/pgp-signature Content-Disposition: inline -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (FreeBSD) iEYEARECAAYFAkqakGMACgkQC3+MBN1Mb4hPJgCgzkRRw85CqSG0dRODxYD4h6HE bkcAn1M/oT7H9vmpIJHOTd7++i7VhKt+ =NGrs -----END PGP SIGNATURE----- --ef8eQmdvO1j1gFMO--