summaryrefslogtreecommitdiffstats
path: root/sys/compat/linux
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2012-07-02 21:01:03 +0000
committerkib <kib@FreeBSD.org>2012-07-02 21:01:03 +0000
commit53224f018aac13056c11af9d1233317b1754149c (patch)
tree26c1ae1ac3dde3bf8b9b01fad04caad427a4ef48 /sys/compat/linux
parent293bf50336e246390039b341f229e30d00d97d27 (diff)
downloadFreeBSD-src-53224f018aac13056c11af9d1233317b1754149c.zip
FreeBSD-src-53224f018aac13056c11af9d1233317b1754149c.tar.gz
Extend the KPI to lock and unlock f_offset member of struct file. It
now fully encapsulates all accesses to f_offset, and extends f_offset locking to other consumers that need it, in particular, to lseek() and variants of getdirentries(). Ensure that on 32bit architectures f_offset, which is 64bit quantity, always read and written under the mtxpool protection. This fixes apparently easy to trigger race when parallel lseek()s or lseek() and read/write could destroy file offset. The already broken ABI emulations, including iBCS and SysV, are not converted (yet). Tested by: pho No objections from: jhb MFC after: 3 weeks
Diffstat (limited to 'sys/compat/linux')
-rw-r--r--sys/compat/linux/linux_file.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
index 67b1b38..b0c2e4a 100644
--- a/sys/compat/linux/linux_file.c
+++ b/sys/compat/linux/linux_file.c
@@ -357,15 +357,16 @@ getdents_common(struct thread *td, struct linux_getdents64_args *args,
return (EBADF);
}
+ off = foffset_lock(fp, 0);
vp = fp->f_vnode;
vfslocked = VFS_LOCK_GIANT(vp->v_mount);
if (vp->v_type != VDIR) {
VFS_UNLOCK_GIANT(vfslocked);
+ foffset_unlock(fp, off, 0);
fdrop(fp, td);
return (EINVAL);
}
- off = fp->f_offset;
buflen = max(LINUX_DIRBLKSIZ, nbytes);
buflen = min(buflen, MAXBSIZE);
@@ -514,7 +515,6 @@ getdents_common(struct thread *td, struct linux_getdents64_args *args,
goto eof;
}
- fp->f_offset = off;
if (justone)
nbytes = resid + linuxreclen;
@@ -527,6 +527,7 @@ out:
VOP_UNLOCK(vp, 0);
VFS_UNLOCK_GIANT(vfslocked);
+ foffset_unlock(fp, off, 0);
fdrop(fp, td);
free(buf, M_TEMP);
free(lbuf, M_TEMP);
OpenPOWER on IntegriCloud