From owner-freebsd-emulation@FreeBSD.ORG Wed Sep 10 08:07:41 2008 Return-Path: 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 2A8031065670 for ; Wed, 10 Sep 2008 08:07:41 +0000 (UTC) (envelope-from samflanker@gmail.com) Received: from yw-out-2324.google.com (yw-out-2324.google.com [74.125.46.30]) by mx1.freebsd.org (Postfix) with ESMTP id D34628FC08 for ; Wed, 10 Sep 2008 08:07:40 +0000 (UTC) (envelope-from samflanker@gmail.com) Received: by yw-out-2324.google.com with SMTP id 9so395631ywe.13 for ; Wed, 10 Sep 2008 01:07:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:message-id:date:from :user-agent:mime-version:to:cc:subject:content-type :content-transfer-encoding; bh=n/7rWGF4XHFZc9PGvbjgMEIpTxxfIaMwoxKj0O95Bmc=; b=lV/qDnig+yhDUmIy3XzW7fBhOOwf9VtzTI5m1NZamWAwNjS44etvz4SKruXoEstHv4 Wbo23PSRP3kARlKkCDSHDoUv/mPFKK6APDNljIkA1ZIVxiDkXx+wYUxCUCl6LfVpo+zq ugvd82dRG2TLClzsFtiolzaeQ/33HVP/+xRUk= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=message-id:date:from:user-agent:mime-version:to:cc:subject :content-type:content-transfer-encoding; b=FI7Emh2UBcU1E80f8uj2FogyXUaKNknLpLd/1h9X3exOKXt/COpu7WG8HN4eudsRb8 mytSYAJ7lk0lEo0oF4fwkbIuSsrHDy2lvmIb38ISFxorv6bd9G8baIFzp/ncJmWCOyDB fQhowKQJmyb5bqJgN7Pfz31nk9PSLZyzOYlsI= Received: by 10.86.80.17 with SMTP id d17mr673737fgb.24.1221032681655; Wed, 10 Sep 2008 00:44:41 -0700 (PDT) Received: from ?192.168.1.107? ( [213.152.137.42]) by mx.google.com with ESMTPS id d4sm8071630fga.5.2008.09.10.00.44.39 (version=SSLv3 cipher=RC4-MD5); Wed, 10 Sep 2008 00:44:40 -0700 (PDT) Message-ID: <48C77AE9.90700@gmail.com> Date: Wed, 10 Sep 2008 11:44:41 +0400 From: sam User-Agent: Thunderbird 2.0.0.4 (Windows/20070604) MIME-Version: 1.0 To: chagin.dmitry@gmail.com Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Cc: beech@FreeBSD.org, mita@ee.t.u-tokyo.ac.jp, freebsd-emulation@freebsd.org 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 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 10 Sep 2008 08:07:41 -0000 On Mon, Sep 08, 2008 at 01:12:28AM +0400, Chagin Dmitry wrote: >/ 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! Hello Iam tested this patch on my old testing pack (with source) http://cs.udmvt.ru/files/temp/linux_getdents.tar.bz2 (bin.file linux_getdents_static compiled on system Linux 2.6.9 with old glibc version) # uname -a FreeBSD damascus 7.0-STABLE FreeBSD 7.0-STABLE #0: Mon Aug 25 12:41:55 MSD 2008 root@static:/usr/obj/usr/src/sys/DAMASCUS i386 # sysctl compat.linux.osrelease compat.linux.osrelease: 2.6.16 # pkg_info|grep linux linux_base-fc-4_13 Base set of packages needed in Linux mode (for i386/amd64) /before patch ------------------------------------------------------------------- # ./linux_getdents_static ./temp/ Reading... . .. ak47-1.wav ak47-2.wav *** sliderelease1.wav Closing... *** glibc detected *** ./linux_getdents_static: double free or corruption (!prev): 0x080c7688 *** ======= Backtrace: ========= [0x80515fe] [0x8054cdb] [0x80564b8] [0x804828b] [0x80484ab] [0x8048151] ======= Memory map: ======== 08048000-080c3000 r-xp 0008d000 00:00 4168734 /usr/home/venom/temp/temp/devel/linux/linux_getdents_static 080c3000-080c6000 rw-p 00025000 00:00 0 080c6000-080e8000 rwxp 00025000 00:00 0 480c3000-480c4000 rwxp 0013d000 00:00 0 48100000-48121000 rwxp 0013d000 00:00 0 48121000-48200000 ---p 0013d000 00:00 0 bfbe0000-bfc00000 rwxp 00020000 00:00 0 Abort trap: 6 (core dumped) ------------------------------------------------------------------- after patch ------------------------------------------------------------------- # ./linux_getdents_static ./temp/ Reading... . .. ak47-1.wav ak47-2.wav *** sliderelease1.wav Closing...Done! ------------------------------------------------------------------- thanks /Vladimir Ermakov