* Re: [PATCH][COMPAT] compat_sys_fcntl{,64} 1/9 Generic part
@ 2003-02-28 9:50 sfr
2003-02-28 10:36 ` Andi Kleen
0 siblings, 1 reply; 15+ messages in thread
From: sfr @ 2003-02-28 9:50 UTC (permalink / raw)
To: ak, sfr
Cc: anton, davem, davidm, linux-kernel, matthew, ralf, schwidefsky,
torvalds
Hi Andi,
Thanks for the comments.
From: Andi Kleen <ak@muc.de>
>
> On Fri, Feb 28, 2003 at 05:33:49AM +0100, Stephen Rothwell wrote:
> > +static int get_compat_flock(struct flock *kfl, struct compat_flock *ufl)
> > +{
> > + if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
> > + __get_user(kfl->l_type, &ufl->l_type) ||
> > + __get_user(kfl->l_whence, &ufl->l_whence) ||
> > + __get_user(kfl->l_start, &ufl->l_start) ||
> > + __get_user(kfl->l_len, &ufl->l_len) ||
> > + __get_user(kfl->l_pid, &ufl->l_pid))
>
> Perhaps there should be really a big fat comment on top of compat.c
> that it depends on a hole on __PAGE_OFFSET if the arch allows passing
> 64bit pointers to the compat functions.
One of my tasks is to document all the assumptions in hte comapt code
(and there a a few - and I find more as I go :-)). However, could you
elaborate a bit here - do you mean passing 64 bit pointers from user mode?
> > +asmlinkage long compat_sys_fcntl(unsigned int fd, unsigned int cmd,
> > + unsigned long arg)
> > +{
> > + if ((cmd == F_GETLK64) || (cmd == F_SETLK64) || (cmd == F_SETLKW64))
> > + return -EINVAL;
>
> That won't work for IA32 emulation. There are programs that call
> old style fcntl() with F_*LK64. Just drop the if here.
I was going to elaborate on this when I sent the x86_64 part of the patch.
If you read the "normal" kernel fcntl function, it does NOT accept
F_GETLK64, F_SETLK64 or F_SETLKW64 through the fcntl sys call only
through the fcntl64 syscall. So any program that does call the old
style fcntl() with one of those will fail on ia32 - which is what you are
trying to emulate.
Cheers,
Stephen
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH][COMPAT] compat_sys_fcntl{,64} 1/9 Generic part
2003-02-28 9:50 [PATCH][COMPAT] compat_sys_fcntl{,64} 1/9 Generic part sfr
@ 2003-02-28 10:36 ` Andi Kleen
2003-03-01 9:12 ` Anton Blanchard
0 siblings, 1 reply; 15+ messages in thread
From: Andi Kleen @ 2003-02-28 10:36 UTC (permalink / raw)
To: sfr
Cc: ak, anton, davem, davidm, linux-kernel, matthew, ralf,
schwidefsky, torvalds
On Fri, Feb 28, 2003 at 10:50:35AM +0100, sfr@canb.auug.org.au wrote:
> >
> > On Fri, Feb 28, 2003 at 05:33:49AM +0100, Stephen Rothwell wrote:
> > > +static int get_compat_flock(struct flock *kfl, struct compat_flock *ufl)
> > > +{
> > > + if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
> > > + __get_user(kfl->l_type, &ufl->l_type) ||
> > > + __get_user(kfl->l_whence, &ufl->l_whence) ||
> > > + __get_user(kfl->l_start, &ufl->l_start) ||
> > > + __get_user(kfl->l_len, &ufl->l_len) ||
> > > + __get_user(kfl->l_pid, &ufl->l_pid))
> >
> > Perhaps there should be really a big fat comment on top of compat.c
> > that it depends on a hole on __PAGE_OFFSET if the arch allows passing
> > 64bit pointers to the compat functions.
>
> One of my tasks is to document all the assumptions in hte comapt code
> (and there a a few - and I find more as I go :-)). However, could you
> elaborate a bit here - do you mean passing 64 bit pointers from user mode?
On some architectures it may be possible to smuggle 64bit pointers into
function arguments of the 32bit emulation. It should be able to handle
that without security holes.
e.g. on x86-64 it was for some time using ptrace - you could do
a syscall trace and restart a system call and modify the input arguments
again to contain 64bit pointers. I closed this, but there may be similar
holes on other ports. IMHO the 32bit emulation layer should be 64bit
input argument clean to avoid such subtle problems.
Now there used to be some code that did:
if (get_user(a, &userstruct->firstmember) ||
__get_user(b, &userstruct->secondmember))
return -EFAULT;
Assuming that the access_ok in get_user for sizeof(firstmember) covers
secondmember too which doesn't do access_ok in __get_user. This only
works assuming it should handle 64bit pointers when there is a memory
hole at the end of the user process space, otherwise it could
access kernel pages directly after TASK_SIZE. x86-64 has a big enough
hole there, i assume sparc64 and ia64 have too, but i don't know
about the other 64bit ports.
Actually your fcntl code is ok in this regard because it
uses access_ok with the correct argument, but other code sometimes doesn't.
> > > +asmlinkage long compat_sys_fcntl(unsigned int fd, unsigned int cmd,
> > > + unsigned long arg)
> > > +{
> > > + if ((cmd == F_GETLK64) || (cmd == F_SETLK64) || (cmd == F_SETLKW64))
> > > + return -EINVAL;
> >
> > That won't work for IA32 emulation. There are programs that call
> > old style fcntl() with F_*LK64. Just drop the if here.
>
> I was going to elaborate on this when I sent the x86_64 part of the patch.
> If you read the "normal" kernel fcntl function, it does NOT accept
> F_GETLK64, F_SETLK64 or F_SETLKW64 through the fcntl sys call only
> through the fcntl64 syscall. So any program that does call the old
> style fcntl() with one of those will fail on ia32 - which is what you are
> trying to emulate.
Are you sure? I thought it did. But perhaps I'm confusing it with
fcntl64 here. fcntl64 definitely needs to accept the old style calls
(I remember debugging a problem in some application that relied on that)
-Andi
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH][COMPAT] compat_sys_fcntl{,64} 1/9 Generic part
2003-02-28 10:36 ` Andi Kleen
@ 2003-03-01 9:12 ` Anton Blanchard
0 siblings, 0 replies; 15+ messages in thread
From: Anton Blanchard @ 2003-03-01 9:12 UTC (permalink / raw)
To: Andi Kleen
Cc: sfr, davem, davidm, linux-kernel, matthew, ralf, schwidefsky,
torvalds
> Now there used to be some code that did:
>
> if (get_user(a, &userstruct->firstmember) ||
> __get_user(b, &userstruct->secondmember))
> return -EFAULT;
>
> Assuming that the access_ok in get_user for sizeof(firstmember) covers
> secondmember too which doesn't do access_ok in __get_user. This only
> works assuming it should handle 64bit pointers when there is a memory
> hole at the end of the user process space, otherwise it could
> access kernel pages directly after TASK_SIZE. x86-64 has a big enough
> hole there, i assume sparc64 and ia64 have too, but i don't know
> about the other 64bit ports.
Yeah there are a bunch of those in the ioctl and syscall translation
code that annoys me. ppc64 is safe too, but its not something we should
rely on.
Anton
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [PATCH][COMPAT] compat_sys_fcntl{,64} 1/9 Generic part
@ 2003-03-11 12:20 Martin Schwidefsky
2003-03-12 4:44 ` Stephen Rothwell
0 siblings, 1 reply; 15+ messages in thread
From: Martin Schwidefsky @ 2003-03-11 12:20 UTC (permalink / raw)
To: Arnd Bergmann; +Cc: Stephen Rothwell, linux-kernel
> Did you notice the use of the address conversion macro? Maybe I missed
> something myself, but I suppose this will fail on s390 if the msb of arg
> is not cleared.
True. A(arg) removes the high order bit from arg. This can't be done
in the system call wrapper because in general arg is a 32 bit parameter.
blue skies,
Martin
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH][COMPAT] compat_sys_fcntl{,64} 1/9 Generic part
2003-03-11 12:20 Martin Schwidefsky
@ 2003-03-12 4:44 ` Stephen Rothwell
2003-03-12 5:02 ` Linus Torvalds
0 siblings, 1 reply; 15+ messages in thread
From: Stephen Rothwell @ 2003-03-12 4:44 UTC (permalink / raw)
To: Martin Schwidefsky; +Cc: arnd, linux-kernel, Linus
Hi Martin, Arnd,
On Tue, 11 Mar 2003 13:20:39 +0100 "Martin Schwidefsky" <schwidefsky@de.ibm.com> wrote:
>
>
> > Did you notice the use of the address conversion macro? Maybe I missed
> > something myself, but I suppose this will fail on s390 if the msb of arg
> > is not cleared.
>
> True. A(arg) removes the high order bit from arg. This can't be done
> in the system call wrapper because in general arg is a 32 bit parameter.
I did notice :-) Does the following look OK to you?
This patch also (goes some way) to fixing the net/compat.c as pointers
are used there as well.
Linus, if Martin says this is OK, please apply. This patch is relative
to my previous patch, but applies to recent BK with some fuzz in the
architectures that haven't merged my previous patch yet.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
diff -ruN 2.5.64-2003031211-32bit.1/fs/compat.c 2.5.64-2003031211-32bit.2/fs/compat.c
--- 2.5.64-2003031211-32bit.1/fs/compat.c 2003-03-12 11:55:17.000000000 +1100
+++ 2.5.64-2003031211-32bit.2/fs/compat.c 2003-03-12 15:11:27.000000000 +1100
@@ -191,7 +191,7 @@
case F_GETLK:
case F_SETLK:
case F_SETLKW:
- ret = get_compat_flock(&f, (struct compat_flock *)arg);
+ ret = get_compat_flock(&f, COMPAT_UPTR_TO_PTR(arg));
if (ret != 0)
break;
old_fs = get_fs();
@@ -204,14 +204,14 @@
ret = -EOVERFLOW;
if (ret == 0)
ret = put_compat_flock(&f,
- (struct compat_flock *)arg);
+ COMPAT_UPTR_TO_PTR(arg));
}
break;
case F_GETLK64:
case F_SETLK64:
case F_SETLKW64:
- ret = get_compat_flock64(&f, (struct compat_flock64 *)arg);
+ ret = get_compat_flock64(&f, COMPAT_UPTR_TO_PTR(arg));
if (ret != 0)
break;
old_fs = get_fs();
@@ -227,7 +227,7 @@
ret = -EOVERFLOW;
if (ret == 0)
ret = put_compat_flock64(&f,
- (struct compat_flock64 *)arg);
+ COMPAT_UPTR_TO_PTR(arg));
}
break;
diff -ruN 2.5.64-2003031211-32bit.1/include/asm-ia64/compat.h 2.5.64-2003031211-32bit.2/include/asm-ia64/compat.h
--- 2.5.64-2003031211-32bit.1/include/asm-ia64/compat.h 2003-03-09 20:34:45.000000000 +1100
+++ 2.5.64-2003031211-32bit.2/include/asm-ia64/compat.h 2003-03-12 15:36:14.000000000 +1100
@@ -107,4 +107,13 @@
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef u32 compat_uptr_t;
+#define COMPAT_UPTR_TO_PTR(ptr) ((void *)(unsigned long)(x))
+
#endif /* _ASM_IA64_COMPAT_H */
diff -ruN 2.5.64-2003031211-32bit.1/include/asm-mips64/compat.h 2.5.64-2003031211-32bit.2/include/asm-mips64/compat.h
--- 2.5.64-2003031211-32bit.1/include/asm-mips64/compat.h 2003-03-09 20:34:45.000000000 +1100
+++ 2.5.64-2003031211-32bit.2/include/asm-mips64/compat.h 2003-03-12 15:36:28.000000000 +1100
@@ -103,4 +103,13 @@
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef u32 compat_uptr_t;
+#define COMPAT_UPTR_TO_PTR(ptr) ((void *)(unsigned long)(x))
+
#endif /* _ASM_MIPS64_COMPAT_H */
diff -ruN 2.5.64-2003031211-32bit.1/include/asm-parisc/compat.h 2.5.64-2003031211-32bit.2/include/asm-parisc/compat.h
--- 2.5.64-2003031211-32bit.1/include/asm-parisc/compat.h 2003-03-12 11:55:19.000000000 +1100
+++ 2.5.64-2003031211-32bit.2/include/asm-parisc/compat.h 2003-03-12 15:36:42.000000000 +1100
@@ -103,4 +103,13 @@
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef u32 compat_uptr_t;
+#define COMPAT_UPTR_TO_PTR(ptr) ((void *)(unsigned long)(x))
+
#endif /* _ASM_PARISC_COMPAT_H */
diff -ruN 2.5.64-2003031211-32bit.1/include/asm-ppc64/compat.h 2.5.64-2003031211-32bit.2/include/asm-ppc64/compat.h
--- 2.5.64-2003031211-32bit.1/include/asm-ppc64/compat.h 2003-03-09 20:34:45.000000000 +1100
+++ 2.5.64-2003031211-32bit.2/include/asm-ppc64/compat.h 2003-03-12 15:36:52.000000000 +1100
@@ -98,4 +98,13 @@
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef u32 compat_uptr_t;
+#define COMPAT_UPTR_TO_PTR(ptr) ((void *)(unsigned long)(x))
+
#endif /* _ASM_PPC64_COMPAT_H */
diff -ruN 2.5.64-2003031211-32bit.1/include/asm-s390x/compat.h 2.5.64-2003031211-32bit.2/include/asm-s390x/compat.h
--- 2.5.64-2003031211-32bit.1/include/asm-s390x/compat.h 2003-03-12 11:55:20.000000000 +1100
+++ 2.5.64-2003031211-32bit.2/include/asm-s390x/compat.h 2003-03-12 15:37:03.000000000 +1100
@@ -101,4 +101,13 @@
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef u32 compat_uptr_t;
+#define COMPAT_UPTR_TO_PTR(ptr) ((void *)(unsigned long)((x) & 0x7fffffffUL))
+
#endif /* _ASM_S390X_COMPAT_H */
diff -ruN 2.5.64-2003031211-32bit.1/include/asm-sparc64/compat.h 2.5.64-2003031211-32bit.2/include/asm-sparc64/compat.h
--- 2.5.64-2003031211-32bit.1/include/asm-sparc64/compat.h 2003-03-09 20:34:45.000000000 +1100
+++ 2.5.64-2003031211-32bit.2/include/asm-sparc64/compat.h 2003-03-12 15:37:12.000000000 +1100
@@ -100,4 +100,13 @@
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef u32 compat_uptr_t;
+#define COMPAT_UPTR_TO_PTR(ptr) ((void *)(unsigned long)(x))
+
#endif /* _ASM_SPARC64_COMPAT_H */
diff -ruN 2.5.64-2003031211-32bit.1/include/asm-x86_64/compat.h 2.5.64-2003031211-32bit.2/include/asm-x86_64/compat.h
--- 2.5.64-2003031211-32bit.1/include/asm-x86_64/compat.h 2003-03-12 11:55:21.000000000 +1100
+++ 2.5.64-2003031211-32bit.2/include/asm-x86_64/compat.h 2003-03-12 15:37:19.000000000 +1100
@@ -107,4 +107,13 @@
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffff
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef u32 compat_uptr_t;
+#define COMPAT_UPTR_TO_PTR(ptr) ((void *)(unsigned long)(x))
+
#endif /* _ASM_X86_64_COMPAT_H */
diff -ruN 2.5.64-2003031211-32bit.1/net/compat.c 2.5.64-2003031211-32bit.2/net/compat.c
--- 2.5.64-2003031211-32bit.1/net/compat.c 2003-03-12 11:55:24.000000000 +1100
+++ 2.5.64-2003031211-32bit.2/net/compat.c 2003-03-12 15:29:48.000000000 +1100
@@ -27,7 +27,6 @@
#include <asm/uaccess.h>
#include <net/compat_socket.h>
-#define A(__x) ((unsigned long)(__x))
#define AA(__x) ((unsigned long)(__x))
extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
@@ -49,7 +48,7 @@
break;
}
tot_len += len;
- kiov->iov_base = (void *)A(buf);
+ kiov->iov_base = COMPAT_UPTR_TO_PTR(buf);
kiov->iov_len = (__kernel_size_t) len;
uiov32++;
kiov++;
@@ -69,9 +68,9 @@
if (err)
return -EFAULT;
- kmsg->msg_name = (void *)A(tmp1);
- kmsg->msg_iov = (struct iovec *)A(tmp2);
- kmsg->msg_control = (void *)A(tmp3);
+ kmsg->msg_name = COMPAT_UPTR_TO_PTR(tmp1);
+ kmsg->msg_iov = COMPAT_UPTR_TO_PTR(tmp2);
+ kmsg->msg_control = COMPAT_UPTR_TO_PTR(tmp3);
err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
@@ -458,7 +457,7 @@
__get_user(uptr, &fprog32->filter))
return -EFAULT;
- kfprog.filter = (struct sock_filter *)A(uptr);
+ kfprog.filter = COMPAT_UPTR_TO_PTR(uptr);
fsize = kfprog.len * sizeof(struct sock_filter);
kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
@@ -639,36 +638,37 @@
ret = sys_socket(a0, a1, a[2]);
break;
case SYS_BIND:
- ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]);
+ ret = sys_bind(a0, COMPAT_UPTR_TO_PTR(a1), a[2]);
break;
case SYS_CONNECT:
- ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]);
+ ret = sys_connect(a0, COMPAT_UPTR_TO_PTR(a1), a[2]);
break;
case SYS_LISTEN:
ret = sys_listen(a0, a1);
break;
case SYS_ACCEPT:
- ret = sys_accept(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
+ ret = sys_accept(a0, COMPAT_UPTR_TO_PTR(a1),
+ COMPAT_UPTR_TO_PTR(a[2]));
break;
case SYS_GETSOCKNAME:
- ret = sys_getsockname(a0, (struct sockaddr *)A(a1),
- (int *)A(a[2]));
+ ret = sys_getsockname(a0, COMPAT_UPTR_TO_PTR(a1),
+ COMPAT_UPTR_TO_PTR(a[2]));
break;
case SYS_GETPEERNAME:
- ret = sys_getpeername(a0, (struct sockaddr *)A(a1),
- (int *)A(a[2]));
+ ret = sys_getpeername(a0, COMPAT_UPTR_TO_PTR(a1),
+ COMPAT_UPTR_TO_PTR(a[2]));
break;
case SYS_SOCKETPAIR:
- ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3]));
+ ret = sys_socketpair(a0, a1, a[2], COMPAT_UPTR_TO_PTR(a[3]));
break;
case SYS_SEND:
- ret = sys_send(a0, (void *)A(a1), a[2], a[3]);
+ ret = sys_send(a0, COMPAT_UPTR_TO_PTR(a1), a[2], a[3]);
break;
case SYS_SENDTO:
ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]);
break;
case SYS_RECV:
- ret = sys_recv(a0, (void *)A(a1), a[2], a[3]);
+ ret = sys_recv(a0, COMPAT_UPTR_TO_PTR(a1), a[2], a[3]);
break;
case SYS_RECVFROM:
ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]);
@@ -677,19 +677,20 @@
ret = sys_shutdown(a0,a1);
break;
case SYS_SETSOCKOPT:
- ret = compat_sys_setsockopt(a0, a1, a[2], (char *)A(a[3]),
- a[4]);
+ ret = compat_sys_setsockopt(a0, a1, a[2],
+ COMPAT_UPTR_TO_PTR(a[3]), a[4]);
break;
case SYS_GETSOCKOPT:
- ret = compat_sys_getsockopt(a0, a1, a[2], (char *)(u64)a[3],
- (int *)(u64)a[4]);
+ ret = compat_sys_getsockopt(a0, a1, a[2],
+ COMPAT_UPTR_TO_PTR(a[3]),
+ COMPAT_UPTR_TO_PTR(a[4]));
break;
case SYS_SENDMSG:
- ret = compat_sys_sendmsg(a0, (struct compat_msghdr *)A(a1),
+ ret = compat_sys_sendmsg(a0, COMPAT_UPTR_TO_PTR(a1),
a[2]);
break;
case SYS_RECVMSG:
- ret = compat_sys_recvmsg(a0, (struct compat_msghdr *)A(a1),
+ ret = compat_sys_recvmsg(a0, COMPAT_UPTR_TO_PTR(a1),
a[2]);
break;
default:
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH][COMPAT] compat_sys_fcntl{,64} 1/9 Generic part
2003-03-12 4:44 ` Stephen Rothwell
@ 2003-03-12 5:02 ` Linus Torvalds
2003-03-12 5:22 ` Stephen Rothwell
0 siblings, 1 reply; 15+ messages in thread
From: Linus Torvalds @ 2003-03-12 5:02 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: Martin Schwidefsky, arnd, linux-kernel
On Wed, 12 Mar 2003, Stephen Rothwell wrote:
>
> Linus, if Martin says this is OK, please apply. This patch is relative
> to my previous patch, but applies to recent BK with some fuzz in the
> architectures that haven't merged my previous patch yet.
This is just too much CRAP, in my opinion. It's just unacceptably ugly,
and I don't think the compat layer is worth it if it just keeps on growing
barnacles that are as horrible as this.
Why do you have to shout in the code with macro names from hell?
Make the code _look_ good. Not look like SOMEBODY WHO CANNOT TYPE WITHOUT
THE SHIFT KEY. Make the thing take properly typed arguments, instead of
casting stuff two ways and backwards inside macros.
Linus
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH][COMPAT] compat_sys_fcntl{,64} 1/9 Generic part
2003-03-12 5:02 ` Linus Torvalds
@ 2003-03-12 5:22 ` Stephen Rothwell
2003-03-12 5:26 ` Linus Torvalds
0 siblings, 1 reply; 15+ messages in thread
From: Stephen Rothwell @ 2003-03-12 5:22 UTC (permalink / raw)
To: Linus Torvalds; +Cc: schwidefsky, arnd, linux-kernel
On Tue, 11 Mar 2003 21:02:09 -0800 (PST) Linus Torvalds <torvalds@transmeta.com> wrote:
>
> Why do you have to shout in the code with macro names from hell?
At least it is descriptive as opposed to an uncommented macro
called A ...
> Make the code _look_ good. Not look like SOMEBODY WHO CANNOT TYPE WITHOUT
> THE SHIFT KEY. Make the thing take properly typed arguments, instead of
> casting stuff two ways and backwards inside macros.
you mean like this?
static inline void *compat_ptr(compat_uptr_t uptr)
{
return (void *)uptr;
}
and (for s390x)
static inline void *compat_ptr(compat_uptr_t uptr)
{
return (void *)(uptr & 0x7fffffffUL);
}
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH][COMPAT] compat_sys_fcntl{,64} 1/9 Generic part
2003-03-12 5:22 ` Stephen Rothwell
@ 2003-03-12 5:26 ` Linus Torvalds
2003-03-12 5:57 ` Stephen Rothwell
2003-03-12 11:46 ` David S. Miller
0 siblings, 2 replies; 15+ messages in thread
From: Linus Torvalds @ 2003-03-12 5:26 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: schwidefsky, arnd, linux-kernel
On Wed, 12 Mar 2003, Stephen Rothwell wrote:
>
> > Make the code _look_ good. Not look like SOMEBODY WHO CANNOT TYPE WITHOUT
> > THE SHIFT KEY. Make the thing take properly typed arguments, instead of
> > casting stuff two ways and backwards inside macros.
>
> you mean like this?
Yes, this looks much more sane. If you _really_ want to be anal about
typechecking (and also checking that nobody can possibly use a user
pointer incorrectly), you make
typedef struct {
unsigned int val;
} compat_uptr_t;
and then use
static inline void *compat_ptr(compat_uptr_t uptr)
{
return (void *)uptr.val;
}
which should still result in readable code.
Linus
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH][COMPAT] compat_sys_fcntl{,64} 1/9 Generic part
2003-03-12 5:26 ` Linus Torvalds
@ 2003-03-12 5:57 ` Stephen Rothwell
2003-03-12 11:46 ` David S. Miller
1 sibling, 0 replies; 15+ messages in thread
From: Stephen Rothwell @ 2003-03-12 5:57 UTC (permalink / raw)
To: Linus Torvalds; +Cc: schwidefsky, arnd, linux-kernel
Hi Linus,
OK, next attempt. I have left our the anal type checking for now.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
diff -ruN 2.5.64-2003031211-32bit.1/fs/compat.c 2.5.64-2003031211-32bit.2/fs/compat.c
--- 2.5.64-2003031211-32bit.1/fs/compat.c 2003-03-12 11:55:17.000000000 +1100
+++ 2.5.64-2003031211-32bit.2/fs/compat.c 2003-03-12 16:49:01.000000000 +1100
@@ -191,7 +191,7 @@
case F_GETLK:
case F_SETLK:
case F_SETLKW:
- ret = get_compat_flock(&f, (struct compat_flock *)arg);
+ ret = get_compat_flock(&f, compat_ptr(arg));
if (ret != 0)
break;
old_fs = get_fs();
@@ -203,15 +203,14 @@
((f.l_start + f.l_len) >= COMPAT_OFF_T_MAX))
ret = -EOVERFLOW;
if (ret == 0)
- ret = put_compat_flock(&f,
- (struct compat_flock *)arg);
+ ret = put_compat_flock(&f, compat_ptr(arg));
}
break;
case F_GETLK64:
case F_SETLK64:
case F_SETLKW64:
- ret = get_compat_flock64(&f, (struct compat_flock64 *)arg);
+ ret = get_compat_flock64(&f, compat_ptr(arg));
if (ret != 0)
break;
old_fs = get_fs();
@@ -226,8 +225,7 @@
((f.l_start + f.l_len) >= COMPAT_LOFF_T_MAX))
ret = -EOVERFLOW;
if (ret == 0)
- ret = put_compat_flock64(&f,
- (struct compat_flock64 *)arg);
+ ret = put_compat_flock64(&f, compat_ptr(arg));
}
break;
diff -ruN 2.5.64-2003031211-32bit.1/include/asm-ia64/compat.h 2.5.64-2003031211-32bit.2/include/asm-ia64/compat.h
--- 2.5.64-2003031211-32bit.1/include/asm-ia64/compat.h 2003-03-09 20:34:45.000000000 +1100
+++ 2.5.64-2003031211-32bit.2/include/asm-ia64/compat.h 2003-03-12 16:41:42.000000000 +1100
@@ -107,4 +107,17 @@
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef u32 compat_uptr_t;
+
+static inline void *compat_ptr(compat_ptr_t uptr)
+{
+ return (void *)uptr;
+}
+
#endif /* _ASM_IA64_COMPAT_H */
diff -ruN 2.5.64-2003031211-32bit.1/include/asm-mips64/compat.h 2.5.64-2003031211-32bit.2/include/asm-mips64/compat.h
--- 2.5.64-2003031211-32bit.1/include/asm-mips64/compat.h 2003-03-09 20:34:45.000000000 +1100
+++ 2.5.64-2003031211-32bit.2/include/asm-mips64/compat.h 2003-03-12 16:41:56.000000000 +1100
@@ -103,4 +103,17 @@
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef u32 compat_uptr_t;
+
+static inline void *compat_ptr(compat_ptr_t uptr)
+{
+ return (void *)uptr;
+}
+
#endif /* _ASM_MIPS64_COMPAT_H */
diff -ruN 2.5.64-2003031211-32bit.1/include/asm-parisc/compat.h 2.5.64-2003031211-32bit.2/include/asm-parisc/compat.h
--- 2.5.64-2003031211-32bit.1/include/asm-parisc/compat.h 2003-03-12 11:55:19.000000000 +1100
+++ 2.5.64-2003031211-32bit.2/include/asm-parisc/compat.h 2003-03-12 16:42:07.000000000 +1100
@@ -103,4 +103,17 @@
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef u32 compat_uptr_t;
+
+static inline void *compat_ptr(compat_ptr_t uptr)
+{
+ return (void *)uptr;
+}
+
#endif /* _ASM_PARISC_COMPAT_H */
diff -ruN 2.5.64-2003031211-32bit.1/include/asm-ppc64/compat.h 2.5.64-2003031211-32bit.2/include/asm-ppc64/compat.h
--- 2.5.64-2003031211-32bit.1/include/asm-ppc64/compat.h 2003-03-09 20:34:45.000000000 +1100
+++ 2.5.64-2003031211-32bit.2/include/asm-ppc64/compat.h 2003-03-12 16:43:27.000000000 +1100
@@ -98,4 +98,17 @@
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef u32 compat_uptr_t;
+
+static inline void *compat_ptr(compat_ptr_t uptr)
+{
+ return (void *)uptr;
+}
+
#endif /* _ASM_PPC64_COMPAT_H */
diff -ruN 2.5.64-2003031211-32bit.1/include/asm-s390x/compat.h 2.5.64-2003031211-32bit.2/include/asm-s390x/compat.h
--- 2.5.64-2003031211-32bit.1/include/asm-s390x/compat.h 2003-03-12 11:55:20.000000000 +1100
+++ 2.5.64-2003031211-32bit.2/include/asm-s390x/compat.h 2003-03-12 16:42:53.000000000 +1100
@@ -101,4 +101,17 @@
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef u32 compat_uptr_t;
+
+static inline void *compat_ptr(compat_ptr_t uptr)
+{
+ return (void *)(uptr & 0x7fffffffUL);
+}
+
#endif /* _ASM_S390X_COMPAT_H */
diff -ruN 2.5.64-2003031211-32bit.1/include/asm-sparc64/compat.h 2.5.64-2003031211-32bit.2/include/asm-sparc64/compat.h
--- 2.5.64-2003031211-32bit.1/include/asm-sparc64/compat.h 2003-03-09 20:34:45.000000000 +1100
+++ 2.5.64-2003031211-32bit.2/include/asm-sparc64/compat.h 2003-03-12 16:43:12.000000000 +1100
@@ -100,4 +100,17 @@
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffffL
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef u32 compat_uptr_t;
+
+static inline void *compat_ptr(compat_ptr_t uptr)
+{
+ return (void *)uptr;
+}
+
#endif /* _ASM_SPARC64_COMPAT_H */
diff -ruN 2.5.64-2003031211-32bit.1/include/asm-x86_64/compat.h 2.5.64-2003031211-32bit.2/include/asm-x86_64/compat.h
--- 2.5.64-2003031211-32bit.1/include/asm-x86_64/compat.h 2003-03-12 11:55:21.000000000 +1100
+++ 2.5.64-2003031211-32bit.2/include/asm-x86_64/compat.h 2003-03-12 16:43:56.000000000 +1100
@@ -107,4 +107,17 @@
#define COMPAT_OFF_T_MAX 0x7fffffff
#define COMPAT_LOFF_T_MAX 0x7fffffffffffffff
+/*
+ * A pointer passed in from user mode. This should not
+ * be used for syscall parameters, just declare them
+ * as pointers because the syscall entry code will have
+ * appropriately comverted them already.
+ */
+typedef u32 compat_uptr_t;
+
+static inline void *compat_ptr(compat_ptr_t uptr)
+{
+ return (void *)uptr;
+}
+
#endif /* _ASM_X86_64_COMPAT_H */
diff -ruN 2.5.64-2003031211-32bit.1/net/compat.c 2.5.64-2003031211-32bit.2/net/compat.c
--- 2.5.64-2003031211-32bit.1/net/compat.c 2003-03-12 11:55:24.000000000 +1100
+++ 2.5.64-2003031211-32bit.2/net/compat.c 2003-03-12 16:48:01.000000000 +1100
@@ -27,7 +27,6 @@
#include <asm/uaccess.h>
#include <net/compat_socket.h>
-#define A(__x) ((unsigned long)(__x))
#define AA(__x) ((unsigned long)(__x))
extern asmlinkage long sys_getsockopt(int fd, int level, int optname,
@@ -49,7 +48,7 @@
break;
}
tot_len += len;
- kiov->iov_base = (void *)A(buf);
+ kiov->iov_base = compat_ptr(buf);
kiov->iov_len = (__kernel_size_t) len;
uiov32++;
kiov++;
@@ -60,7 +59,7 @@
int msghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct compat_msghdr *umsg)
{
- u32 tmp1, tmp2, tmp3;
+ compat_uptr_t tmp1, tmp2, tmp3;
int err;
err = get_user(tmp1, &umsg->msg_name);
@@ -69,9 +68,9 @@
if (err)
return -EFAULT;
- kmsg->msg_name = (void *)A(tmp1);
- kmsg->msg_iov = (struct iovec *)A(tmp2);
- kmsg->msg_control = (void *)A(tmp3);
+ kmsg->msg_name = compat_ptr(tmp1);
+ kmsg->msg_iov = compat_ptr(tmp2);
+ kmsg->msg_control = compat_ptr(tmp3);
err = get_user(kmsg->msg_namelen, &umsg->msg_namelen);
err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen);
@@ -451,14 +450,14 @@
struct sock_filter *kfilter;
unsigned int fsize;
mm_segment_t old_fs;
- __u32 uptr;
+ compat_uptr_t uptr;
int ret;
if (get_user(kfprog.len, &fprog32->len) ||
__get_user(uptr, &fprog32->filter))
return -EFAULT;
- kfprog.filter = (struct sock_filter *)A(uptr);
+ kfprog.filter = compat_ptr(uptr);
fsize = kfprog.len * sizeof(struct sock_filter);
kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);
@@ -639,36 +638,34 @@
ret = sys_socket(a0, a1, a[2]);
break;
case SYS_BIND:
- ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]);
+ ret = sys_bind(a0, compat_ptr(a1), a[2]);
break;
case SYS_CONNECT:
- ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]);
+ ret = sys_connect(a0, compat_ptr(a1), a[2]);
break;
case SYS_LISTEN:
ret = sys_listen(a0, a1);
break;
case SYS_ACCEPT:
- ret = sys_accept(a0, (struct sockaddr *)A(a1), (int *)A(a[2]));
+ ret = sys_accept(a0, compat_ptr(a1), compat_ptr(a[2]));
break;
case SYS_GETSOCKNAME:
- ret = sys_getsockname(a0, (struct sockaddr *)A(a1),
- (int *)A(a[2]));
+ ret = sys_getsockname(a0, compat_ptr(a1), compat_ptr(a[2]));
break;
case SYS_GETPEERNAME:
- ret = sys_getpeername(a0, (struct sockaddr *)A(a1),
- (int *)A(a[2]));
+ ret = sys_getpeername(a0, compat_ptr(a1), compat_ptr(a[2]));
break;
case SYS_SOCKETPAIR:
- ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3]));
+ ret = sys_socketpair(a0, a1, a[2], compat_ptr(a[3]));
break;
case SYS_SEND:
- ret = sys_send(a0, (void *)A(a1), a[2], a[3]);
+ ret = sys_send(a0, compat_ptr(a1), a[2], a[3]);
break;
case SYS_SENDTO:
ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]);
break;
case SYS_RECV:
- ret = sys_recv(a0, (void *)A(a1), a[2], a[3]);
+ ret = sys_recv(a0, compat_ptr(a1), a[2], a[3]);
break;
case SYS_RECVFROM:
ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]);
@@ -677,20 +674,18 @@
ret = sys_shutdown(a0,a1);
break;
case SYS_SETSOCKOPT:
- ret = compat_sys_setsockopt(a0, a1, a[2], (char *)A(a[3]),
- a[4]);
+ ret = compat_sys_setsockopt(a0, a1, a[2],
+ compat_ptr(a[3]), a[4]);
break;
case SYS_GETSOCKOPT:
- ret = compat_sys_getsockopt(a0, a1, a[2], (char *)(u64)a[3],
- (int *)(u64)a[4]);
+ ret = compat_sys_getsockopt(a0, a1, a[2],
+ compat_ptr(a[3]), compat_ptr(a[4]));
break;
case SYS_SENDMSG:
- ret = compat_sys_sendmsg(a0, (struct compat_msghdr *)A(a1),
- a[2]);
+ ret = compat_sys_sendmsg(a0, compat_ptr(a1), a[2]);
break;
case SYS_RECVMSG:
- ret = compat_sys_recvmsg(a0, (struct compat_msghdr *)A(a1),
- a[2]);
+ ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]);
break;
default:
ret = -EINVAL;
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH][COMPAT] compat_sys_fcntl{,64} 1/9 Generic part
2003-03-12 5:26 ` Linus Torvalds
2003-03-12 5:57 ` Stephen Rothwell
@ 2003-03-12 11:46 ` David S. Miller
1 sibling, 0 replies; 15+ messages in thread
From: David S. Miller @ 2003-03-12 11:46 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Stephen Rothwell, schwidefsky, arnd, linux-kernel
On Tue, 2003-03-11 at 21:26, Linus Torvalds wrote:
> Yes, this looks much more sane. If you _really_ want to be anal about
> typechecking (and also checking that nobody can possibly use a user
> pointer incorrectly), you make
>
> typedef struct {
> unsigned int val;
> } compat_uptr_t;
Be careful, these kind of "int in a struct" things end up being
passed to functions on the stack instead of registers :-(
This is why we don't do any of the fancy type-checking
page table types on Sparc unless you edit the header files.
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH][COMPAT] compat_sys_fcntl{,64} 1/9 Generic part
@ 2003-03-11 0:41 Stephen Rothwell
0 siblings, 0 replies; 15+ messages in thread
From: Stephen Rothwell @ 2003-03-11 0:41 UTC (permalink / raw)
To: Linus; +Cc: LKML, anton, David S. Miller, ak, davidm, schwidefsky, ralf,
matthew
Hi Linus,
This patch creates compat_sys_fcntl{,64}. The diffstat for the whole
patch set is below, but this is just the generic part, the architecture
specific parts will follow.
This patch also removes struct flock64 from all the 64 bit architectures
(except parisc).
I think I have answered all the questions from the last time I posted
this, so please apply.
arch/ia64/ia32/ia32_entry.S | 4 -
arch/ia64/ia32/sys_ia32.c | 92 -----------------------
arch/mips64/kernel/linux32.c | 44 -----------
arch/mips64/kernel/scall_o32.S | 4 -
arch/parisc/kernel/sys_parisc32.c | 51 -------------
arch/parisc/kernel/syscall.S | 5 -
arch/ppc64/kernel/misc.S | 4 -
arch/ppc64/kernel/sys_ppc32.c | 33 --------
arch/s390x/kernel/entry.S | 4 -
arch/s390x/kernel/linux32.c | 51 -------------
arch/s390x/kernel/linux32.h | 4 -
arch/s390x/kernel/wrapper32.S | 12 +--
arch/sparc64/kernel/sys_sparc32.c | 35 ---------
arch/sparc64/kernel/systbls.S | 6 -
arch/x86_64/ia32/ia32entry.S | 4 -
arch/x86_64/ia32/sys_ia32.c | 96 ------------------------
fs/compat.c | 147 ++++++++++++++++++++++++++++++--------
include/asm-alpha/fcntl.h | 3
include/asm-ia64/compat.h | 19 ++++
include/asm-ia64/fcntl.h | 5 -
include/asm-ia64/ia32.h | 4 -
include/asm-mips64/compat.h | 18 ++++
include/asm-mips64/fcntl.h | 10 --
include/asm-parisc/compat.h | 11 ++
include/asm-ppc64/compat.h | 16 +++-
include/asm-ppc64/fcntl.h | 13 ---
include/asm-s390x/compat.h | 16 +++-
include/asm-s390x/fcntl.h | 2
include/asm-sparc64/compat.h | 16 ++++
include/asm-sparc64/fcntl.h | 11 --
include/asm-x86_64/compat.h | 19 ++++
include/asm-x86_64/fcntl.h | 4 -
include/asm-x86_64/ia32.h | 12 ---
include/linux/compat.h | 3
include/linux/fs.h | 2
35 files changed, 255 insertions(+), 525 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
diff -ruN 2.5.64-2003030918-32bit.1/fs/compat.c 2.5.64-2003030918-32bit.2/fs/compat.c
--- 2.5.64-2003030918-32bit.1/fs/compat.c 2003-01-14 09:57:57.000000000 +1100
+++ 2.5.64-2003030918-32bit.2/fs/compat.c 2003-03-09 20:34:45.000000000 +1100
@@ -75,36 +75,6 @@
return error;
}
-int get_compat_flock(struct flock *kfl, struct compat_flock *ufl)
-{
- int err;
-
- if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)))
- return -EFAULT;
-
- err = __get_user(kfl->l_type, &ufl->l_type);
- err |= __get_user(kfl->l_whence, &ufl->l_whence);
- err |= __get_user(kfl->l_start, &ufl->l_start);
- err |= __get_user(kfl->l_len, &ufl->l_len);
- err |= __get_user(kfl->l_pid, &ufl->l_pid);
- return err;
-}
-
-int put_compat_flock(struct flock *kfl, struct compat_flock *ufl)
-{
- int err;
-
- if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)))
- return -EFAULT;
-
- err = __put_user(kfl->l_type, &ufl->l_type);
- err |= __put_user(kfl->l_whence, &ufl->l_whence);
- err |= __put_user(kfl->l_start, &ufl->l_start);
- err |= __put_user(kfl->l_len, &ufl->l_len);
- err |= __put_user(kfl->l_pid, &ufl->l_pid);
- return err;
-}
-
static int put_compat_statfs(struct compat_statfs *ubuf, struct statfs *kbuf)
{
if (verify_area(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
@@ -159,3 +129,120 @@
out:
return error;
}
+
+static int get_compat_flock(struct flock *kfl, struct compat_flock *ufl)
+{
+ if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
+ __get_user(kfl->l_type, &ufl->l_type) ||
+ __get_user(kfl->l_whence, &ufl->l_whence) ||
+ __get_user(kfl->l_start, &ufl->l_start) ||
+ __get_user(kfl->l_len, &ufl->l_len) ||
+ __get_user(kfl->l_pid, &ufl->l_pid))
+ return -EFAULT;
+ return 0;
+}
+
+static int put_compat_flock(struct flock *kfl, struct compat_flock *ufl)
+{
+ if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) ||
+ __put_user(kfl->l_type, &ufl->l_type) ||
+ __put_user(kfl->l_whence, &ufl->l_whence) ||
+ __put_user(kfl->l_start, &ufl->l_start) ||
+ __put_user(kfl->l_len, &ufl->l_len) ||
+ __put_user(kfl->l_pid, &ufl->l_pid))
+ return -EFAULT;
+ return 0;
+}
+
+static int get_compat_flock64(struct flock *kfl, struct compat_flock64 *ufl)
+{
+ if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
+ __get_user(kfl->l_type, &ufl->l_type) ||
+ __get_user(kfl->l_whence, &ufl->l_whence) ||
+ __get_user(kfl->l_start, &ufl->l_start) ||
+ __get_user(kfl->l_len, &ufl->l_len) ||
+ __get_user(kfl->l_pid, &ufl->l_pid))
+ return -EFAULT;
+ return 0;
+}
+
+static int put_compat_flock64(struct flock *kfl, struct compat_flock64 *ufl)
+{
+ if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) ||
+ __put_user(kfl->l_type, &ufl->l_type) ||
+ __put_user(kfl->l_whence, &ufl->l_whence) ||
+ __put_user(kfl->l_start, &ufl->l_start) ||
+ __put_user(kfl->l_len, &ufl->l_len) ||
+ __put_user(kfl->l_pid, &ufl->l_pid))
+ return -EFAULT;
+ return 0;
+}
+
+extern asmlinkage long sys_fcntl(unsigned int, unsigned int, unsigned long);
+
+asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
+ unsigned long arg)
+{
+ mm_segment_t old_fs;
+ struct flock f;
+ long ret;
+
+ switch (cmd) {
+ case F_GETLK:
+ case F_SETLK:
+ case F_SETLKW:
+ ret = get_compat_flock(&f, (struct compat_flock *)arg);
+ if (ret != 0)
+ break;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_fcntl(fd, cmd, (unsigned long)&f);
+ set_fs(old_fs);
+ if ((cmd == F_GETLK) && (ret == 0)) {
+ if ((f.l_start >= COMPAT_OFF_T_MAX) ||
+ ((f.l_start + f.l_len) >= COMPAT_OFF_T_MAX))
+ ret = -EOVERFLOW;
+ if (ret == 0)
+ ret = put_compat_flock(&f,
+ (struct compat_flock *)arg);
+ }
+ break;
+
+ case F_GETLK64:
+ case F_SETLK64:
+ case F_SETLKW64:
+ ret = get_compat_flock64(&f, (struct compat_flock64 *)arg);
+ if (ret != 0)
+ break;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_fcntl(fd, F_GETLK, (unsigned long)&f);
+ ret = sys_fcntl(fd, (cmd == F_GETLK64) ? F_GETLK :
+ ((cmd == F_SETLK64) ? F_SETLK : F_SETLKW),
+ (unsigned long)&f);
+ set_fs(old_fs);
+ if ((cmd == F_GETLK64) && (ret == 0)) {
+ if ((f.l_start >= COMPAT_LOFF_T_MAX) ||
+ ((f.l_start + f.l_len) >= COMPAT_LOFF_T_MAX))
+ ret = -EOVERFLOW;
+ if (ret == 0)
+ ret = put_compat_flock64(&f,
+ (struct compat_flock64 *)arg);
+ }
+ break;
+
+ default:
+ ret = sys_fcntl(fd, cmd, arg);
+ break;
+ }
+ return ret;
+}
+
+asmlinkage long compat_sys_fcntl(unsigned int fd, unsigned int cmd,
+ unsigned long arg)
+{
+ if ((cmd == F_GETLK64) || (cmd == F_SETLK64) || (cmd == F_SETLKW64))
+ return -EINVAL;
+ return compat_sys_fcntl64(fd, cmd, arg);
+}
+
diff -ruN 2.5.64-2003030918-32bit.1/include/linux/compat.h 2.5.64-2003030918-32bit.2/include/linux/compat.h
--- 2.5.64-2003030918-32bit.1/include/linux/compat.h 2003-01-17 14:01:07.000000000 +1100
+++ 2.5.64-2003030918-32bit.2/include/linux/compat.h 2003-03-09 20:34:45.000000000 +1100
@@ -10,7 +10,6 @@
#include <linux/stat.h>
#include <linux/param.h> /* for HZ */
-#include <linux/fcntl.h> /* for struct flock */
#include <asm/compat.h>
#define compat_jiffies_to_clock_t(x) \
@@ -40,8 +39,6 @@
} compat_sigset_t;
extern int cp_compat_stat(struct kstat *, struct compat_stat *);
-extern int get_compat_flock(struct flock *, struct compat_flock *);
-extern int put_compat_flock(struct flock *, struct compat_flock *);
extern int get_compat_timespec(struct timespec *, struct compat_timespec *);
extern int put_compat_timespec(struct timespec *, struct compat_timespec *);
diff -ruN 2.5.64-2003030918-32bit.1/include/linux/fs.h 2.5.64-2003030918-32bit.2/include/linux/fs.h
--- 2.5.64-2003030918-32bit.1/include/linux/fs.h 2003-03-09 20:09:18.000000000 +1100
+++ 2.5.64-2003030918-32bit.2/include/linux/fs.h 2003-03-09 20:34:45.000000000 +1100
@@ -526,8 +526,10 @@
extern int fcntl_getlk(struct file *, struct flock *);
extern int fcntl_setlk(struct file *, unsigned int, struct flock *);
+#if BITS_PER_LONG == 32
extern int fcntl_getlk64(struct file *, struct flock64 *);
extern int fcntl_setlk64(struct file *, unsigned int, struct flock64 *);
+#endif
/* fs/locks.c */
extern void locks_init_lock(struct file_lock *);
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH][COMPAT] compat_sys_fcntl{,64} 1/9 Generic part
@ 2003-03-10 12:43 Arnd Bergmann
0 siblings, 0 replies; 15+ messages in thread
From: Arnd Bergmann @ 2003-03-10 12:43 UTC (permalink / raw)
To: Stephen Rothwell; +Cc: linux-kernel, Martin Schwidefsky
Stephen Rothwell wrote:
+asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
+ unsigned long arg)
+{
+ mm_segment_t old_fs;
+ struct flock f;
+ long ret;
+
+ switch (cmd) {
+ case F_GETLK:
+ case F_SETLK:
+ case F_SETLKW:
+ ret = get_compat_flock(&f, (struct compat_flock *)arg);
and
-asmlinkage long sys32_fcntl(unsigned int fd, unsigned int cmd, unsigned long arg)
-{
- switch (cmd) {
- case F_GETLK:
- {
- struct flock f;
- mm_segment_t old_fs;
- long ret;
-
- if(get_compat_flock(&f, (struct compat_flock *)A(arg)))
^^^^^^^^
Did you notice the use of the address conversion macro? Maybe I missed
something myself, but I suppose this will fail on s390 if the msb of arg
is not cleared.
Arnd <><
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH][COMPAT] compat_sys_fcntl{,64} 1/9 Generic part
@ 2003-03-04 5:58 Stephen Rothwell
0 siblings, 0 replies; 15+ messages in thread
From: Stephen Rothwell @ 2003-03-04 5:58 UTC (permalink / raw)
To: Linus; +Cc: LKML, anton, David S. Miller, ak, davidm, schwidefsky, ralf,
matthew
Hi Linus,
This patch creates compat_sys_fcntl{,64}. The diffstat for the whole
patch set is below, but this is just the generic part, the architecture
specific parts will follow.
This patch also removes struct flock64 from all the 64 bit architectures
(except parisc).
I think I have answered all the questions from the last time I posted
this, so please apply.
arch/ia64/ia32/ia32_entry.S | 4 -
arch/ia64/ia32/sys_ia32.c | 92 -----------------------
arch/mips64/kernel/linux32.c | 44 -----------
arch/mips64/kernel/scall_o32.S | 4 -
arch/parisc/kernel/sys_parisc32.c | 51 -------------
arch/parisc/kernel/syscall.S | 5 -
arch/ppc64/kernel/misc.S | 4 -
arch/ppc64/kernel/sys_ppc32.c | 33 --------
arch/s390x/kernel/entry.S | 4 -
arch/s390x/kernel/linux32.c | 51 -------------
arch/s390x/kernel/linux32.h | 4 -
arch/s390x/kernel/wrapper32.S | 12 +--
arch/sparc64/kernel/sys_sparc32.c | 35 ---------
arch/sparc64/kernel/systbls.S | 6 -
arch/x86_64/ia32/ia32entry.S | 4 -
arch/x86_64/ia32/sys_ia32.c | 96 ------------------------
fs/compat.c | 147 ++++++++++++++++++++++++++++++--------
include/asm-alpha/fcntl.h | 3
include/asm-ia64/compat.h | 19 ++++
include/asm-ia64/fcntl.h | 5 -
include/asm-ia64/ia32.h | 4 -
include/asm-mips64/compat.h | 18 ++++
include/asm-mips64/fcntl.h | 10 --
include/asm-parisc/compat.h | 11 ++
include/asm-ppc64/compat.h | 16 +++-
include/asm-ppc64/fcntl.h | 13 ---
include/asm-s390x/compat.h | 16 +++-
include/asm-s390x/fcntl.h | 2
include/asm-sparc64/compat.h | 16 ++++
include/asm-sparc64/fcntl.h | 11 --
include/asm-x86_64/compat.h | 18 ++++
include/asm-x86_64/fcntl.h | 4 -
include/asm-x86_64/ia32.h | 12 ---
include/linux/compat.h | 3
include/linux/fs.h | 2
35 files changed, 254 insertions(+), 525 deletions(-)
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
diff -ruN 2.5.63-32bit.1/fs/compat.c 2.5.63-32bit.2/fs/compat.c
--- 2.5.63-32bit.1/fs/compat.c 2003-01-14 09:57:57.000000000 +1100
+++ 2.5.63-32bit.2/fs/compat.c 2003-02-25 14:35:59.000000000 +1100
@@ -75,36 +75,6 @@
return error;
}
-int get_compat_flock(struct flock *kfl, struct compat_flock *ufl)
-{
- int err;
-
- if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)))
- return -EFAULT;
-
- err = __get_user(kfl->l_type, &ufl->l_type);
- err |= __get_user(kfl->l_whence, &ufl->l_whence);
- err |= __get_user(kfl->l_start, &ufl->l_start);
- err |= __get_user(kfl->l_len, &ufl->l_len);
- err |= __get_user(kfl->l_pid, &ufl->l_pid);
- return err;
-}
-
-int put_compat_flock(struct flock *kfl, struct compat_flock *ufl)
-{
- int err;
-
- if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)))
- return -EFAULT;
-
- err = __put_user(kfl->l_type, &ufl->l_type);
- err |= __put_user(kfl->l_whence, &ufl->l_whence);
- err |= __put_user(kfl->l_start, &ufl->l_start);
- err |= __put_user(kfl->l_len, &ufl->l_len);
- err |= __put_user(kfl->l_pid, &ufl->l_pid);
- return err;
-}
-
static int put_compat_statfs(struct compat_statfs *ubuf, struct statfs *kbuf)
{
if (verify_area(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
@@ -159,3 +129,120 @@
out:
return error;
}
+
+static int get_compat_flock(struct flock *kfl, struct compat_flock *ufl)
+{
+ if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
+ __get_user(kfl->l_type, &ufl->l_type) ||
+ __get_user(kfl->l_whence, &ufl->l_whence) ||
+ __get_user(kfl->l_start, &ufl->l_start) ||
+ __get_user(kfl->l_len, &ufl->l_len) ||
+ __get_user(kfl->l_pid, &ufl->l_pid))
+ return -EFAULT;
+ return 0;
+}
+
+static int put_compat_flock(struct flock *kfl, struct compat_flock *ufl)
+{
+ if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) ||
+ __put_user(kfl->l_type, &ufl->l_type) ||
+ __put_user(kfl->l_whence, &ufl->l_whence) ||
+ __put_user(kfl->l_start, &ufl->l_start) ||
+ __put_user(kfl->l_len, &ufl->l_len) ||
+ __put_user(kfl->l_pid, &ufl->l_pid))
+ return -EFAULT;
+ return 0;
+}
+
+static int get_compat_flock64(struct flock *kfl, struct compat_flock64 *ufl)
+{
+ if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
+ __get_user(kfl->l_type, &ufl->l_type) ||
+ __get_user(kfl->l_whence, &ufl->l_whence) ||
+ __get_user(kfl->l_start, &ufl->l_start) ||
+ __get_user(kfl->l_len, &ufl->l_len) ||
+ __get_user(kfl->l_pid, &ufl->l_pid))
+ return -EFAULT;
+ return 0;
+}
+
+static int put_compat_flock64(struct flock *kfl, struct compat_flock64 *ufl)
+{
+ if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) ||
+ __put_user(kfl->l_type, &ufl->l_type) ||
+ __put_user(kfl->l_whence, &ufl->l_whence) ||
+ __put_user(kfl->l_start, &ufl->l_start) ||
+ __put_user(kfl->l_len, &ufl->l_len) ||
+ __put_user(kfl->l_pid, &ufl->l_pid))
+ return -EFAULT;
+ return 0;
+}
+
+extern asmlinkage long sys_fcntl(unsigned int, unsigned int, unsigned long);
+
+asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
+ unsigned long arg)
+{
+ mm_segment_t old_fs;
+ struct flock f;
+ long ret;
+
+ switch (cmd) {
+ case F_GETLK:
+ case F_SETLK:
+ case F_SETLKW:
+ ret = get_compat_flock(&f, (struct compat_flock *)arg);
+ if (ret != 0)
+ break;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_fcntl(fd, cmd, (unsigned long)&f);
+ set_fs(old_fs);
+ if ((cmd == F_GETLK) && (ret == 0)) {
+ if ((f.l_start >= COMPAT_OFF_T_MAX) ||
+ ((f.l_start + f.l_len) >= COMPAT_OFF_T_MAX))
+ ret = -EOVERFLOW;
+ if (ret == 0)
+ ret = put_compat_flock(&f,
+ (struct compat_flock *)arg);
+ }
+ break;
+
+ case F_GETLK64:
+ case F_SETLK64:
+ case F_SETLKW64:
+ ret = get_compat_flock64(&f, (struct compat_flock64 *)arg);
+ if (ret != 0)
+ break;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_fcntl(fd, F_GETLK, (unsigned long)&f);
+ ret = sys_fcntl(fd, (cmd == F_GETLK64) ? F_GETLK :
+ ((cmd == F_SETLK64) ? F_SETLK : F_SETLKW),
+ (unsigned long)&f);
+ set_fs(old_fs);
+ if ((cmd == F_GETLK64) && (ret == 0)) {
+ if ((f.l_start >= COMPAT_LOFF_T_MAX) ||
+ ((f.l_start + f.l_len) >= COMPAT_LOFF_T_MAX))
+ ret = -EOVERFLOW;
+ if (ret == 0)
+ ret = put_compat_flock64(&f,
+ (struct compat_flock64 *)arg);
+ }
+ break;
+
+ default:
+ ret = sys_fcntl(fd, cmd, arg);
+ break;
+ }
+ return ret;
+}
+
+asmlinkage long compat_sys_fcntl(unsigned int fd, unsigned int cmd,
+ unsigned long arg)
+{
+ if ((cmd == F_GETLK64) || (cmd == F_SETLK64) || (cmd == F_SETLKW64))
+ return -EINVAL;
+ return compat_sys_fcntl64(fd, cmd, arg);
+}
+
diff -ruN 2.5.63-32bit.1/include/linux/compat.h 2.5.63-32bit.2/include/linux/compat.h
--- 2.5.63-32bit.1/include/linux/compat.h 2003-01-17 14:01:07.000000000 +1100
+++ 2.5.63-32bit.2/include/linux/compat.h 2003-02-25 14:36:00.000000000 +1100
@@ -10,7 +10,6 @@
#include <linux/stat.h>
#include <linux/param.h> /* for HZ */
-#include <linux/fcntl.h> /* for struct flock */
#include <asm/compat.h>
#define compat_jiffies_to_clock_t(x) \
@@ -40,8 +39,6 @@
} compat_sigset_t;
extern int cp_compat_stat(struct kstat *, struct compat_stat *);
-extern int get_compat_flock(struct flock *, struct compat_flock *);
-extern int put_compat_flock(struct flock *, struct compat_flock *);
extern int get_compat_timespec(struct timespec *, struct compat_timespec *);
extern int put_compat_timespec(struct timespec *, struct compat_timespec *);
diff -ruN 2.5.63-32bit.1/include/linux/fs.h 2.5.63-32bit.2/include/linux/fs.h
--- 2.5.63-32bit.1/include/linux/fs.h 2003-02-25 12:59:59.000000000 +1100
+++ 2.5.63-32bit.2/include/linux/fs.h 2003-02-25 14:36:00.000000000 +1100
@@ -525,8 +525,10 @@
extern int fcntl_getlk(struct file *, struct flock *);
extern int fcntl_setlk(struct file *, unsigned int, struct flock *);
+#if BITS_PER_LONG == 32
extern int fcntl_getlk64(struct file *, struct flock64 *);
extern int fcntl_setlk64(struct file *, unsigned int, struct flock64 *);
+#endif
/* fs/locks.c */
extern void locks_init_lock(struct file_lock *);
^ permalink raw reply [flat|nested] 15+ messages in thread* [PATCH][COMPAT] compat_sys_fcntl{,64} 1/9 Generic part
@ 2003-02-28 4:33 Stephen Rothwell
2003-02-28 8:08 ` Andi Kleen
0 siblings, 1 reply; 15+ messages in thread
From: Stephen Rothwell @ 2003-02-28 4:33 UTC (permalink / raw)
To: LKML; +Cc: Linus, anton, David S. Miller, ak, davidm, schwidefsky, ralf,
matthew
Hi all,
This is my first pass at compat_sys_fcntl and compat_sys_fcntl64.
I am hoping it is OK with everyone.
This is just the generic part of the patch, arch's to follow.
As a side effect, this allows the removal of struct flock64 from all
the 64 bit architectures.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
diff -ruN 2.5.63-32bit.1/fs/compat.c 2.5.63-32bit.2/fs/compat.c
--- 2.5.63-32bit.1/fs/compat.c 2003-01-14 09:57:57.000000000 +1100
+++ 2.5.63-32bit.2/fs/compat.c 2003-02-25 14:35:59.000000000 +1100
@@ -75,36 +75,6 @@
return error;
}
-int get_compat_flock(struct flock *kfl, struct compat_flock *ufl)
-{
- int err;
-
- if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)))
- return -EFAULT;
-
- err = __get_user(kfl->l_type, &ufl->l_type);
- err |= __get_user(kfl->l_whence, &ufl->l_whence);
- err |= __get_user(kfl->l_start, &ufl->l_start);
- err |= __get_user(kfl->l_len, &ufl->l_len);
- err |= __get_user(kfl->l_pid, &ufl->l_pid);
- return err;
-}
-
-int put_compat_flock(struct flock *kfl, struct compat_flock *ufl)
-{
- int err;
-
- if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)))
- return -EFAULT;
-
- err = __put_user(kfl->l_type, &ufl->l_type);
- err |= __put_user(kfl->l_whence, &ufl->l_whence);
- err |= __put_user(kfl->l_start, &ufl->l_start);
- err |= __put_user(kfl->l_len, &ufl->l_len);
- err |= __put_user(kfl->l_pid, &ufl->l_pid);
- return err;
-}
-
static int put_compat_statfs(struct compat_statfs *ubuf, struct statfs *kbuf)
{
if (verify_area(VERIFY_WRITE, ubuf, sizeof(*ubuf)) ||
@@ -159,3 +129,120 @@
out:
return error;
}
+
+static int get_compat_flock(struct flock *kfl, struct compat_flock *ufl)
+{
+ if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
+ __get_user(kfl->l_type, &ufl->l_type) ||
+ __get_user(kfl->l_whence, &ufl->l_whence) ||
+ __get_user(kfl->l_start, &ufl->l_start) ||
+ __get_user(kfl->l_len, &ufl->l_len) ||
+ __get_user(kfl->l_pid, &ufl->l_pid))
+ return -EFAULT;
+ return 0;
+}
+
+static int put_compat_flock(struct flock *kfl, struct compat_flock *ufl)
+{
+ if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) ||
+ __put_user(kfl->l_type, &ufl->l_type) ||
+ __put_user(kfl->l_whence, &ufl->l_whence) ||
+ __put_user(kfl->l_start, &ufl->l_start) ||
+ __put_user(kfl->l_len, &ufl->l_len) ||
+ __put_user(kfl->l_pid, &ufl->l_pid))
+ return -EFAULT;
+ return 0;
+}
+
+static int get_compat_flock64(struct flock *kfl, struct compat_flock64 *ufl)
+{
+ if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
+ __get_user(kfl->l_type, &ufl->l_type) ||
+ __get_user(kfl->l_whence, &ufl->l_whence) ||
+ __get_user(kfl->l_start, &ufl->l_start) ||
+ __get_user(kfl->l_len, &ufl->l_len) ||
+ __get_user(kfl->l_pid, &ufl->l_pid))
+ return -EFAULT;
+ return 0;
+}
+
+static int put_compat_flock64(struct flock *kfl, struct compat_flock64 *ufl)
+{
+ if (!access_ok(VERIFY_WRITE, ufl, sizeof(*ufl)) ||
+ __put_user(kfl->l_type, &ufl->l_type) ||
+ __put_user(kfl->l_whence, &ufl->l_whence) ||
+ __put_user(kfl->l_start, &ufl->l_start) ||
+ __put_user(kfl->l_len, &ufl->l_len) ||
+ __put_user(kfl->l_pid, &ufl->l_pid))
+ return -EFAULT;
+ return 0;
+}
+
+extern asmlinkage long sys_fcntl(unsigned int, unsigned int, unsigned long);
+
+asmlinkage long compat_sys_fcntl64(unsigned int fd, unsigned int cmd,
+ unsigned long arg)
+{
+ mm_segment_t old_fs;
+ struct flock f;
+ long ret;
+
+ switch (cmd) {
+ case F_GETLK:
+ case F_SETLK:
+ case F_SETLKW:
+ ret = get_compat_flock(&f, (struct compat_flock *)arg);
+ if (ret != 0)
+ break;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_fcntl(fd, cmd, (unsigned long)&f);
+ set_fs(old_fs);
+ if ((cmd == F_GETLK) && (ret == 0)) {
+ if ((f.l_start >= COMPAT_OFF_T_MAX) ||
+ ((f.l_start + f.l_len) >= COMPAT_OFF_T_MAX))
+ ret = -EOVERFLOW;
+ if (ret == 0)
+ ret = put_compat_flock(&f,
+ (struct compat_flock *)arg);
+ }
+ break;
+
+ case F_GETLK64:
+ case F_SETLK64:
+ case F_SETLKW64:
+ ret = get_compat_flock64(&f, (struct compat_flock64 *)arg);
+ if (ret != 0)
+ break;
+ old_fs = get_fs();
+ set_fs(KERNEL_DS);
+ ret = sys_fcntl(fd, F_GETLK, (unsigned long)&f);
+ ret = sys_fcntl(fd, (cmd == F_GETLK64) ? F_GETLK :
+ ((cmd == F_SETLK64) ? F_SETLK : F_SETLKW),
+ (unsigned long)&f);
+ set_fs(old_fs);
+ if ((cmd == F_GETLK64) && (ret == 0)) {
+ if ((f.l_start >= COMPAT_LOFF_T_MAX) ||
+ ((f.l_start + f.l_len) >= COMPAT_LOFF_T_MAX))
+ ret = -EOVERFLOW;
+ if (ret == 0)
+ ret = put_compat_flock64(&f,
+ (struct compat_flock64 *)arg);
+ }
+ break;
+
+ default:
+ ret = sys_fcntl(fd, cmd, arg);
+ break;
+ }
+ return ret;
+}
+
+asmlinkage long compat_sys_fcntl(unsigned int fd, unsigned int cmd,
+ unsigned long arg)
+{
+ if ((cmd == F_GETLK64) || (cmd == F_SETLK64) || (cmd == F_SETLKW64))
+ return -EINVAL;
+ return compat_sys_fcntl64(fd, cmd, arg);
+}
+
diff -ruN 2.5.63-32bit.1/include/linux/compat.h 2.5.63-32bit.2/include/linux/compat.h
--- 2.5.63-32bit.1/include/linux/compat.h 2003-01-17 14:01:07.000000000 +1100
+++ 2.5.63-32bit.2/include/linux/compat.h 2003-02-25 14:36:00.000000000 +1100
@@ -10,7 +10,6 @@
#include <linux/stat.h>
#include <linux/param.h> /* for HZ */
-#include <linux/fcntl.h> /* for struct flock */
#include <asm/compat.h>
#define compat_jiffies_to_clock_t(x) \
@@ -40,8 +39,6 @@
} compat_sigset_t;
extern int cp_compat_stat(struct kstat *, struct compat_stat *);
-extern int get_compat_flock(struct flock *, struct compat_flock *);
-extern int put_compat_flock(struct flock *, struct compat_flock *);
extern int get_compat_timespec(struct timespec *, struct compat_timespec *);
extern int put_compat_timespec(struct timespec *, struct compat_timespec *);
diff -ruN 2.5.63-32bit.1/include/linux/fs.h 2.5.63-32bit.2/include/linux/fs.h
--- 2.5.63-32bit.1/include/linux/fs.h 2003-02-25 12:59:59.000000000 +1100
+++ 2.5.63-32bit.2/include/linux/fs.h 2003-02-25 14:36:00.000000000 +1100
@@ -525,8 +525,10 @@
extern int fcntl_getlk(struct file *, struct flock *);
extern int fcntl_setlk(struct file *, unsigned int, struct flock *);
+#if BITS_PER_LONG == 32
extern int fcntl_getlk64(struct file *, struct flock64 *);
extern int fcntl_setlk64(struct file *, unsigned int, struct flock64 *);
+#endif
/* fs/locks.c */
extern void locks_init_lock(struct file_lock *);
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH][COMPAT] compat_sys_fcntl{,64} 1/9 Generic part
2003-02-28 4:33 Stephen Rothwell
@ 2003-02-28 8:08 ` Andi Kleen
0 siblings, 0 replies; 15+ messages in thread
From: Andi Kleen @ 2003-02-28 8:08 UTC (permalink / raw)
To: Stephen Rothwell
Cc: LKML, Linus, anton, David S. Miller, ak, davidm, schwidefsky,
ralf, matthew
On Fri, Feb 28, 2003 at 05:33:49AM +0100, Stephen Rothwell wrote:
> +static int get_compat_flock(struct flock *kfl, struct compat_flock *ufl)
> +{
> + if (!access_ok(VERIFY_READ, ufl, sizeof(*ufl)) ||
> + __get_user(kfl->l_type, &ufl->l_type) ||
> + __get_user(kfl->l_whence, &ufl->l_whence) ||
> + __get_user(kfl->l_start, &ufl->l_start) ||
> + __get_user(kfl->l_len, &ufl->l_len) ||
> + __get_user(kfl->l_pid, &ufl->l_pid))
Perhaps there should be really a big fat comment on top of compat.c
that it depends on a hole on __PAGE_OFFSET if the arch allows passing
64bit pointers to the compat functions.
> +
> +asmlinkage long compat_sys_fcntl(unsigned int fd, unsigned int cmd,
> + unsigned long arg)
> +{
> + if ((cmd == F_GETLK64) || (cmd == F_SETLK64) || (cmd == F_SETLKW64))
> + return -EINVAL;
That won't work for IA32 emulation. There are programs that call
old style fcntl() with F_*LK64. Just drop the if here.
> + return compat_sys_fcntl64(fd, cmd, arg);
-Andi
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2003-03-12 11:36 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-02-28 9:50 [PATCH][COMPAT] compat_sys_fcntl{,64} 1/9 Generic part sfr
2003-02-28 10:36 ` Andi Kleen
2003-03-01 9:12 ` Anton Blanchard
-- strict thread matches above, loose matches on Subject: below --
2003-03-11 12:20 Martin Schwidefsky
2003-03-12 4:44 ` Stephen Rothwell
2003-03-12 5:02 ` Linus Torvalds
2003-03-12 5:22 ` Stephen Rothwell
2003-03-12 5:26 ` Linus Torvalds
2003-03-12 5:57 ` Stephen Rothwell
2003-03-12 11:46 ` David S. Miller
2003-03-11 0:41 Stephen Rothwell
2003-03-10 12:43 Arnd Bergmann
2003-03-04 5:58 Stephen Rothwell
2003-02-28 4:33 Stephen Rothwell
2003-02-28 8:08 ` Andi Kleen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox