From owner-freebsd-emulation@FreeBSD.ORG  Mon Sep  8 07:30:23 2008
Return-Path: <owner-freebsd-emulation@FreeBSD.ORG>
Delivered-To: freebsd-emulation@freebsd.org
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id B85981065674;
	Mon,  8 Sep 2008 07:30:23 +0000 (UTC)
	(envelope-from root@dchagin.dialup.corbina.ru)
Received: from contrabass.post.ru (contrabass.post.ru [85.21.78.5])
	by mx1.freebsd.org (Postfix) with ESMTP id 03F928FC35;
	Mon,  8 Sep 2008 07:30:22 +0000 (UTC)
	(envelope-from root@dchagin.dialup.corbina.ru)
Received: from corbina.ru (mail.post.ru [195.14.50.16])
	by contrabass.post.ru (Postfix) with ESMTP id 83D5C1A2E2B;
	Mon,  8 Sep 2008 11:30:20 +0400 (MSD)
X-Virus-Scanned: by cgpav Uf39PSi9pFi9oFi9
Received: from [10.208.17.3] (HELO dchagin.dialup.corbina.ru)
	by corbina.ru (CommuniGate Pro SMTP 5.1.14)
	with ESMTPS id 1083233770; Mon, 08 Sep 2008 11:30:20 +0400
Received: from dchagin.dialup.corbina.ru (localhost.chd.net [127.0.0.1])
	by dchagin.dialup.corbina.ru (8.14.2/8.14.2) with ESMTP id
	m887UJ0Z001497; Mon, 8 Sep 2008 11:30:19 +0400 (MSD)
	(envelope-from root@dchagin.dialup.corbina.ru)
Received: (from root@localhost)
	by dchagin.dialup.corbina.ru (8.14.2/8.14.2/Submit) id m887UE7v001496; 
	Mon, 8 Sep 2008 11:30:14 +0400 (MSD) (envelope-from root)
Date: Mon, 8 Sep 2008 11:30:14 +0400
From: Chagin Dmitry <dchagin@freebsd.org>
To: Roman Divacky <rdivacky@freebsd.org>
Message-ID: <20080908073014.GA1429@dchagin.dialup.corbina.ru>
Mail-Followup-To: Roman Divacky <rdivacky@freebsd.org>,
	MITA Yoshio <mita@ee.t.u-tokyo.ac.jp>,
	freebsd-emulation@freebsd.org
References: <200809072030.m87KU44I064646@freefall.freebsd.org>
	<20080907211228.GA51816@dchagin.dialup.corbina.ru>
	<20080908070505.GA20963@freebsd.org>
Mime-Version: 1.0
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
In-Reply-To: <20080908070505.GA20963@freebsd.org>
User-Agent: Mutt/1.4.2.3i
Cc: freebsd-emulation@freebsd.org, MITA Yoshio <mita@ee.t.u-tokyo.ac.jp>
Subject: Re: kern/117010: [linux] linux_getdents() get something like buffer
	overflow or else
X-BeenThere: freebsd-emulation@freebsd.org
X-Mailman-Version: 2.1.5
Precedence: list
List-Id: Development of Emulators of other operating systems
	<freebsd-emulation.freebsd.org>
List-Unsubscribe: <http://lists.freebsd.org/mailman/listinfo/freebsd-emulation>, 
	<mailto:freebsd-emulation-request@freebsd.org?subject=unsubscribe>
List-Archive: <http://lists.freebsd.org/pipermail/freebsd-emulation>
List-Post: <mailto:freebsd-emulation@freebsd.org>
List-Help: <mailto:freebsd-emulation-request@freebsd.org?subject=help>
List-Subscribe: <http://lists.freebsd.org/mailman/listinfo/freebsd-emulation>, 
	<mailto:freebsd-emulation-request@freebsd.org?subject=subscribe>
X-List-Received-Date: Mon, 08 Sep 2008 07:30:23 -0000

On Mon, Sep 08, 2008 at 09:05:05AM +0200, Roman Divacky wrote:
> On Mon, Sep 08, 2008 at 01:12:28AM +0400, Chagin Dmitry wrote:
> > On Sun, Sep 07, 2008 at 08:30:04PM +0000, MITA Yoshio wrote:
> > > The following reply was made to PR kern/117010; it has been noted by GNATS.
> > > 
> > > From: MITA Yoshio <mita@ee.t.u-tokyo.ac.jp>
> > > To: bug-followup@FreeBSD.org,samflanker@gmail.com,
> > >     Chagin Dmitry <chagin.dmitry@gmail.com>,
> > >     beech@FreeBSD.org
> > > Cc:  
> > > Subject: Re: kern/117010: [linux] linux_getdents() get something like buffer overflow or else
> > > Date: Sun, 07 Sep 2008 21:42:15 +0200
> > > 
> > >  Hello, 
> > >  
> > >  I've tested a patch from Mr. Dmitry concerning Mr. Ermakov's PR:
> > >  
> > >  http://www.freebsd.org/cgi/query-pr.cgi?pr=117010
> > >  
> > >  Patch:
> > >  >From:	Chagin Dmitry <chagin.dmitry@gmail.com>
> > >  >Date:	Fri, 25 Jul 2008 10:22:46 +0400 (MSD)
> > >  
> > >  This worked!!! to make skype2 work.  
> > >  Otherwise skype2 dumped core as Mr.  reported. 
> > >  
> > >  Regards,
> > >  -----
> > >  Tested Environment: 
> > >  FreeBSD 7.0-RELEASE
> > >  linux_base-fc6-6_5
> > >  linux-glib2-2.6.6
> > >  skype-2.0.0.68,1 
> > >  
> > >  /etc/sysctl.conf:
> > >  compat.linux.osrelease=2.6.16
> > >  
> > >  /etc/make.conf:
> > >  OVERRIDE_LINUX_BASE_PORT=fc6 
> > 
> > Please, try a patch bellow:
> > 
> > diff --git a/src/sys/compat/linux/linux_file.c b/src/sys/compat/linux/linux_file.c
> > index 303bc3f..413e597 100644
> > --- a/src/sys/compat/linux/linux_file.c
> > +++ b/src/sys/compat/linux/linux_file.c
> > @@ -303,9 +303,20 @@ struct l_dirent64 {
> >  	char		d_name[LINUX_NAME_MAX + 1];
> >  };
> >  
> > -#define LINUX_RECLEN(de,namlen) \
> > -    ALIGN((((char *)&(de)->d_name - (char *)de) + (namlen) + 1))
> > +/*
> > + * Linux uses the last byte in the dirent buffer to store d_type,
> > + * at least glibc-2.7 requires it. For what l_dirent padded on 2 bytes.
> > + */
> > +#define LINUX_RECLEN(namlen)						\
> > +    roundup((offsetof(struct l_dirent, d_name) + (namlen) + 2),		\
> > +    sizeof(l_ulong))
> > +
> > +#define LINUX_RECLEN64(namlen)						\
> > +    roundup((offsetof(struct l_dirent64, d_name) + (namlen) + 1),	\
> > +    sizeof(uint64_t))
> >  
> > +#define LINUX_MAXRECLEN		max(LINUX_RECLEN(LINUX_NAME_MAX),	\
> > +				    LINUX_RECLEN64(LINUX_NAME_MAX))
> >  #define	LINUX_DIRBLKSIZ		512
> >  
> >  static int
> > @@ -318,12 +329,13 @@ getdents_common(struct thread *td, struct linux_getdents64_args *args,
> >  	int len, reclen;		/* BSD-format */
> >  	caddr_t outp;			/* Linux-format */
> >  	int resid, linuxreclen=0;	/* Linux-format */
> > +	caddr_t lbuf;			/* Linux-format */
> >  	struct file *fp;
> >  	struct uio auio;
> >  	struct iovec aiov;
> >  	off_t off;
> > -	struct l_dirent linux_dirent;
> > -	struct l_dirent64 linux_dirent64;
> > +	struct l_dirent *linux_dirent;
> > +	struct l_dirent64 *linux_dirent64;
> >  	int buflen, error, eofflag, nbytes, justone;
> >  	u_long *cookies = NULL, *cookiep;
> >  	int ncookies, vfslocked;
> > @@ -359,6 +371,7 @@ getdents_common(struct thread *td, struct linux_getdents64_args *args,
> >  	buflen = max(LINUX_DIRBLKSIZ, nbytes);
> >  	buflen = min(buflen, MAXBSIZE);
> >  	buf = malloc(buflen, M_TEMP, M_WAITOK);
> > +	lbuf = malloc(LINUX_MAXRECLEN, M_TEMP, M_WAITOK | M_ZERO);
> >  	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
> >  
> >  again:
> > @@ -436,8 +449,8 @@ again:
> >  		}
> >  
> >  		linuxreclen = (is64bit)
> > -		    ? LINUX_RECLEN(&linux_dirent64, bdp->d_namlen)
> > -		    : LINUX_RECLEN(&linux_dirent, bdp->d_namlen);
> > +		    ? LINUX_RECLEN64(bdp->d_namlen)
> > +		    : LINUX_RECLEN(bdp->d_namlen);
> >  
> >  		if (reclen > len || resid < linuxreclen) {
> >  			outp++;
> > @@ -446,34 +459,41 @@ again:
> >  
> >  		if (justone) {
> >  			/* readdir(2) case. */
> > -			linux_dirent.d_ino = bdp->d_fileno;
> > -			linux_dirent.d_off = (l_off_t)linuxreclen;
> > -			linux_dirent.d_reclen = (l_ushort)bdp->d_namlen;
> > -			strcpy(linux_dirent.d_name, bdp->d_name);
> > -			error = copyout(&linux_dirent, outp, linuxreclen);
> > -		} else {
> > -			if (is64bit) {
> > -				linux_dirent64.d_ino = bdp->d_fileno;
> > -				linux_dirent64.d_off = (cookiep)
> > -				    ? (l_off_t)*cookiep
> > -				    : (l_off_t)(off + reclen);
> > -				linux_dirent64.d_reclen =
> > -				    (l_ushort)linuxreclen;
> > -				linux_dirent64.d_type = bdp->d_type;
> > -				strcpy(linux_dirent64.d_name, bdp->d_name);
> > -				error = copyout(&linux_dirent64, outp,
> > -				    linuxreclen);
> > -			} else {
> > -				linux_dirent.d_ino = bdp->d_fileno;
> > -				linux_dirent.d_off = (cookiep)
> > -				    ? (l_off_t)*cookiep
> > -				    : (l_off_t)(off + reclen);
> > -				linux_dirent.d_reclen = (l_ushort)linuxreclen;
> > -				strcpy(linux_dirent.d_name, bdp->d_name);
> > -				error = copyout(&linux_dirent, outp,
> > -				    linuxreclen);
> > -			}
> > +			linux_dirent = (struct l_dirent*)lbuf;
> > +			linux_dirent->d_ino = bdp->d_fileno;
> > +			linux_dirent->d_off = (l_off_t)linuxreclen;
> > +			linux_dirent->d_reclen = (l_ushort)bdp->d_namlen;
> > +			strlcpy(linux_dirent->d_name, bdp->d_name,
> > +			    linuxreclen - offsetof(struct l_dirent, d_name));
> > +			error = copyout(linux_dirent, outp, linuxreclen);
> >  		}
> > +		if (is64bit) {
> > +			linux_dirent64 = (struct l_dirent64*)lbuf;
> > +			linux_dirent64->d_ino = bdp->d_fileno;
> > +			linux_dirent64->d_off = (cookiep)
> > +			    ? (l_off_t)*cookiep
> > +			    : (l_off_t)(off + reclen);
> > +			linux_dirent64->d_reclen = (l_ushort)linuxreclen;
> > +			linux_dirent64->d_type = bdp->d_type;
> > +			strlcpy(linux_dirent64->d_name, bdp->d_name,
> > +			    linuxreclen - offsetof(struct l_dirent64, d_name));
> > +			error = copyout(linux_dirent64, outp, linuxreclen);
> > +		} else if (!justone) {
> > +			linux_dirent = (struct l_dirent*)lbuf;
> > +			linux_dirent->d_ino = bdp->d_fileno;
> > +			linux_dirent->d_off = (cookiep)
> > +			    ? (l_off_t)*cookiep
> > +			    : (l_off_t)(off + reclen);
> > +			linux_dirent->d_reclen = (l_ushort)linuxreclen;
> > +			/*
> > +			 * Copy d_type to last byte of l_dirent buffer
> > +			 */
> > +			lbuf[linuxreclen-1] = bdp->d_type;
> > +			strlcpy(linux_dirent->d_name, bdp->d_name,
> > +			    linuxreclen - offsetof(struct l_dirent, d_name)-1);
> > +			error = copyout(linux_dirent, outp, linuxreclen);
> > +		}
> > +
> >  		if (error)
> >  			goto out;
> >  
> > @@ -509,6 +529,7 @@ out:
> >  	VFS_UNLOCK_GIANT(vfslocked);
> >  	fdrop(fp, td);
> >  	free(buf, M_TEMP);
> > +	free(lbuf, M_TEMP);
> >  	return (error);
> >  }
> >  
> > 
> > Roman, I think that this patch can be commited (if testing passes :))
> > thnx!
> 
> yes.... this is the version of the patch I posted to you + the comment changed, right?

yes

-- 
Have fun!
chd