diff options
author | iedowse <iedowse@FreeBSD.org> | 2002-12-08 18:30:44 +0000 |
---|---|---|
committer | iedowse <iedowse@FreeBSD.org> | 2002-12-08 18:30:44 +0000 |
commit | fe6446a0553d019fe05cc881be005c791278013e (patch) | |
tree | 39602db7442b2f756b0e327ac9e22f7ca356c3ff /sys/compat/linux/linux_file.c | |
parent | 18cbf216ce64cfcf05f303aac7fb12eaf768df36 (diff) | |
download | FreeBSD-src-fe6446a0553d019fe05cc881be005c791278013e.zip FreeBSD-src-fe6446a0553d019fe05cc881be005c791278013e.tar.gz |
Fix emulation of the fcntl64() syscall. In Linux, this is exactly
the same as fcntl() except that it supports the new 64-bit file
locking commands (LINUX_F_GETLK64 etc) that use the `flock64'
structure. We had been interpreting all flock structures passed to
fcntl64() as `struct flock64' instead of only the ones from F_*64
commands.
The glibc in linux_base-7 uses fcntl64() by default, but the bug
was often non-fatal since the misinterpretation typically only
causes junk to appear in the `l_len' field and most junk values are
accepted as valid range lengths. The result is occasional EINVAL
errors from F_SETLK and a few bytes after the supplied `struct
flock' getting clobbered during F_GETLK.
PR: kern/37656
Reviewed by: marcel
Approved by: re
MFC after: 1 week
Diffstat (limited to 'sys/compat/linux/linux_file.c')
-rw-r--r-- | sys/compat/linux/linux_file.c | 72 |
1 files changed, 33 insertions, 39 deletions
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c index 76dba79..3cf3bc5 100644 --- a/sys/compat/linux/linux_file.c +++ b/sys/compat/linux/linux_file.c @@ -931,6 +931,8 @@ bsd_to_linux_flock64(struct flock *bsd_flock, struct l_flock64 *linux_flock) static int fcntl_common(struct thread *td, struct linux_fcntl64_args *args) { + struct l_flock linux_flock; + struct flock bsd_flock; struct file *fp; long arg; int error, result; @@ -977,6 +979,37 @@ fcntl_common(struct thread *td, struct linux_fcntl64_args *args) arg |= O_ASYNC; return (kern_fcntl(td, args->fd, F_SETFL, arg)); + case LINUX_F_GETLK: + error = copyin((caddr_t)args->arg, &linux_flock, + sizeof(linux_flock)); + if (error) + return (error); + linux_to_bsd_flock(&linux_flock, &bsd_flock); + error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock); + if (error) + return (error); + bsd_to_linux_flock(&bsd_flock, &linux_flock); + return (copyout(&linux_flock, (caddr_t)args->arg, + sizeof(linux_flock))); + + case LINUX_F_SETLK: + error = copyin((caddr_t)args->arg, &linux_flock, + sizeof(linux_flock)); + if (error) + return (error); + linux_to_bsd_flock(&linux_flock, &bsd_flock); + return (kern_fcntl(td, args->fd, F_SETLK, + (intptr_t)&bsd_flock)); + + case LINUX_F_SETLKW: + error = copyin((caddr_t)args->arg, &linux_flock, + sizeof(linux_flock)); + if (error) + return (error); + linux_to_bsd_flock(&linux_flock, &bsd_flock); + return (kern_fcntl(td, args->fd, F_SETLKW, + (intptr_t)&bsd_flock)); + case LINUX_F_GETOWN: return (kern_fcntl(td, args->fd, F_GETOWN, 0)); @@ -1005,48 +1038,12 @@ int linux_fcntl(struct thread *td, struct linux_fcntl_args *args) { struct linux_fcntl64_args args64; - struct l_flock linux_flock; - struct flock bsd_flock; - int error; #ifdef DEBUG if (ldebug(fcntl)) printf(ARGS(fcntl, "%d, %08x, *"), args->fd, args->cmd); #endif - switch (args->cmd) { - case LINUX_F_GETLK: - error = copyin((caddr_t)args->arg, &linux_flock, - sizeof(linux_flock)); - if (error) - return (error); - linux_to_bsd_flock(&linux_flock, &bsd_flock); - error = kern_fcntl(td, args->fd, F_GETLK, (intptr_t)&bsd_flock); - if (error) - return (error); - bsd_to_linux_flock(&bsd_flock, &linux_flock); - return (copyout(&linux_flock, (caddr_t)args->arg, - sizeof(linux_flock))); - - case LINUX_F_SETLK: - error = copyin((caddr_t)args->arg, &linux_flock, - sizeof(linux_flock)); - if (error) - return (error); - linux_to_bsd_flock(&linux_flock, &bsd_flock); - return (kern_fcntl(td, args->fd, F_SETLK, - (intptr_t)&bsd_flock)); - - case LINUX_F_SETLKW: - error = copyin((caddr_t)args->arg, &linux_flock, - sizeof(linux_flock)); - if (error) - return (error); - linux_to_bsd_flock(&linux_flock, &bsd_flock); - return (kern_fcntl(td, args->fd, F_SETLKW, - (intptr_t)&bsd_flock)); - } - args64.fd = args->fd; args64.cmd = args->cmd; args64.arg = args->arg; @@ -1067,7 +1064,6 @@ linux_fcntl64(struct thread *td, struct linux_fcntl64_args *args) #endif switch (args->cmd) { - case LINUX_F_GETLK: case LINUX_F_GETLK64: error = copyin((caddr_t)args->arg, &linux_flock, sizeof(linux_flock)); @@ -1081,7 +1077,6 @@ linux_fcntl64(struct thread *td, struct linux_fcntl64_args *args) return (copyout(&linux_flock, (caddr_t)args->arg, sizeof(linux_flock))); - case LINUX_F_SETLK: case LINUX_F_SETLK64: error = copyin((caddr_t)args->arg, &linux_flock, sizeof(linux_flock)); @@ -1091,7 +1086,6 @@ linux_fcntl64(struct thread *td, struct linux_fcntl64_args *args) return (kern_fcntl(td, args->fd, F_SETLK, (intptr_t)&bsd_flock)); - case LINUX_F_SETLKW: case LINUX_F_SETLKW64: error = copyin((caddr_t)args->arg, &linux_flock, sizeof(linux_flock)); |