summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2002-12-08 18:30:44 +0000
committeriedowse <iedowse@FreeBSD.org>2002-12-08 18:30:44 +0000
commitfe6446a0553d019fe05cc881be005c791278013e (patch)
tree39602db7442b2f756b0e327ac9e22f7ca356c3ff /sys
parent18cbf216ce64cfcf05f303aac7fb12eaf768df36 (diff)
downloadFreeBSD-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')
-rw-r--r--sys/compat/linux/linux_file.c72
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));
OpenPOWER on IntegriCloud