From owner-freebsd-bugs@FreeBSD.ORG Sun Jun 21 19:10:05 2009 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 D0ECC106564A for ; Sun, 21 Jun 2009 19:10:03 +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 BDB708FC15 for ; Sun, 21 Jun 2009 19:10:03 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.14.3/8.14.3) with ESMTP id n5LJA3qj037893 for ; Sun, 21 Jun 2009 19:10:03 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.3/8.14.3/Submit) id n5LJA3Wb037892; Sun, 21 Jun 2009 19:10:03 GMT (envelope-from gnats) Date: Sun, 21 Jun 2009 19:10:03 GMT Message-Id: <200906211910.n5LJA3Wb037892@freefall.freebsd.org> To: freebsd-bugs@FreeBSD.org From: dfilter@FreeBSD.ORG (dfilter service) Cc: Subject: Re: kern/113939: commit references a PR X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list Reply-To: dfilter service List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 21 Jun 2009 19:10:06 -0000 The following reply was made to PR kern/113939; it has been noted by GNATS. From: dfilter@FreeBSD.ORG (dfilter service) To: bug-followup@FreeBSD.org Cc: Subject: Re: kern/113939: commit references a PR Date: Sun, 21 Jun 2009 19:02:43 +0000 (UTC) Author: dchagin Date: Sun Jun 21 19:02:32 2009 New Revision: 194599 URL: http://svn.freebsd.org/changeset/base/194599 Log: MFC r164890 (by jkim): Fixes for 'blocking in fifoor state' problem of LTP tests. linux_*stat*() functions were opening files with O_RDONLY to get major/minor pair for char/block special files. Unfortunately, when these functions are used against fifo, it is blocked forever because there is no writer. Instead, we only open char/block special files for major/minor conversion. We have to get rid of kern_open() entirely from translate_path_major_minor() but today is not the day. While I am here, add checks for errors before calling translate_path_major_minor(). MFC r179651: d_ino member of linux_dirent structure should be unsigned long. MFC r182892: Getdents requires padding with 2 bytes instead of 1 byte as with getdents64. The last byte is used for storing the d_type, add this to plain getdents case where it was missing before. Also change the code to use strlcpy instead of plain strcpy. MFC r188572: Fix an edge-case of the linux readdir: We need the size of a linux dirent structure, not the size of a pointer to it. PR: kern/113939 Approved by: kib (mentor) Modified: stable/6/sys/ (props changed) stable/6/sys/compat/linux/linux_file.c stable/6/sys/compat/linux/linux_stats.c stable/6/sys/contrib/pf/ (props changed) stable/6/sys/dev/cxgb/ (props changed) Modified: stable/6/sys/compat/linux/linux_file.c ============================================================================== --- stable/6/sys/compat/linux/linux_file.c Sun Jun 21 17:35:04 2009 (r194598) +++ stable/6/sys/compat/linux/linux_file.c Sun Jun 21 19:02:32 2009 (r194599) @@ -232,7 +232,7 @@ linux_readdir(struct thread *td, struct */ struct l_dirent { - l_long d_ino; + l_ulong d_ino; l_off_t d_off; l_ushort d_reclen; char d_name[LINUX_NAME_MAX + 1]; @@ -246,9 +246,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. That is why l_dirent is padded with 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 @@ -261,12 +272,13 @@ getdents_common(struct thread *td, struc 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; @@ -276,7 +288,7 @@ getdents_common(struct thread *td, struc /* readdir(2) case. Always struct dirent. */ if (is64bit) return (EINVAL); - nbytes = sizeof(linux_dirent); + nbytes = sizeof(*linux_dirent); justone = 1; } else justone = 0; @@ -302,6 +314,7 @@ getdents_common(struct thread *td, struc 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, td); again: @@ -379,8 +392,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++; @@ -389,34 +402,41 @@ again: if (justone) { /* readdir(2) case. */ - linux_dirent.d_ino = (l_long)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; @@ -452,6 +472,7 @@ out: VFS_UNLOCK_GIANT(vfslocked); fdrop(fp, td); free(buf, M_TEMP); + free(lbuf, M_TEMP); return (error); } Modified: stable/6/sys/compat/linux/linux_stats.c ============================================================================== --- stable/6/sys/compat/linux/linux_stats.c Sun Jun 21 17:35:04 2009 (r194598) +++ stable/6/sys/compat/linux/linux_stats.c Sun Jun 21 19:02:32 2009 (r194599) @@ -99,23 +99,16 @@ static void translate_fd_major_minor(struct thread *td, int fd, struct stat *buf) { struct file *fp; - int error; int major, minor; - if ((error = fget(td, fd, &fp)) != 0) + if ((!S_ISCHR(buf->st_mode) && !S_ISBLK(buf->st_mode)) || + fget(td, fd, &fp) != 0) return; - if (fp->f_vnode) { - if (fp->f_vnode->v_type == VCHR - || fp->f_vnode->v_type == VBLK) { - if (fp->f_vnode->v_un.vu_cdev) { - if (linux_driver_get_major_minor( - fp->f_vnode->v_un.vu_cdev->si_name, - &major, &minor) == 0) { - buf->st_rdev = (major << 8 | minor); - } - } - } - } + if (fp->f_vnode != NULL && + fp->f_vnode->v_un.vu_cdev != NULL && + linux_driver_get_major_minor(fp->f_vnode->v_un.vu_cdev->si_name, + &major, &minor) == 0) + buf->st_rdev = (major << 8 | minor); fdrop(fp, td); } @@ -128,6 +121,8 @@ translate_path_major_minor(struct thread int fd; int temp; + if (!S_ISCHR(buf->st_mode) && !S_ISBLK(buf->st_mode)) + return; temp = td->td_retval[0]; if (kern_open(td, path, UIO_SYSSPACE, O_RDONLY, 0) != 0) return; @@ -178,18 +173,19 @@ linux_newstat(struct thread *td, struct #endif error = kern_stat(td, path, UIO_SYSSPACE, &buf); - if (!error && strlen(path) > strlen("/dev/pts/") && - !strncmp(path, "/dev/pts/", strlen("/dev/pts/")) - && path[9] >= '0' && path[9] <= '9') { - /* - * Linux checks major and minors of the slave device to make - * sure it's a pty device, so let's make him believe it is. - */ - buf.st_rdev = (136 << 8); - } - - translate_path_major_minor(td, path, &buf); - + if (!error) { + if (strlen(path) > strlen("/dev/pts/") && + !strncmp(path, "/dev/pts/", strlen("/dev/pts/")) && + path[9] >= '0' && path[9] <= '9') { + /* + * Linux checks major and minors of the slave device + * to make sure it's a pty device, so let's make him + * believe it is. + */ + buf.st_rdev = (136 << 8); + } else + translate_path_major_minor(td, path, &buf); + } LFREEPATH(path); if (error) return (error); _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"