* 64-bit kernel patch
@ 2002-10-10 11:26 Carsten Langgaard
2002-10-10 11:41 ` Ralf Baechle
0 siblings, 1 reply; 17+ messages in thread
From: Carsten Langgaard @ 2002-10-10 11:26 UTC (permalink / raw)
To: Ralf Baechle, Maciej W. Rozycki, linux-mips
[-- Attachment #1: Type: text/plain, Size: 381 bytes --]
Here is yet another patch for the 64-bit syscall wrapper.
/Carsten
--
_ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com
|\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527
| \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555
TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556
Denmark http://www.mips.com
[-- Attachment #2: syscall_wrapper.part5.patch --]
[-- Type: text/plain, Size: 5554 bytes --]
Index: arch/mips64/kernel/linux32.c
===================================================================
RCS file: /home/cvs/linux/arch/mips64/kernel/linux32.c,v
retrieving revision 1.42.2.16
diff -u -r1.42.2.16 linux32.c
--- arch/mips64/kernel/linux32.c 3 Oct 2002 09:38:26 -0000 1.42.2.16
+++ arch/mips64/kernel/linux32.c 10 Oct 2002 11:22:40 -0000
@@ -751,12 +751,17 @@
int ret;
struct statfs s;
mm_segment_t old_fs = get_fs();
-
- set_fs (KERNEL_DS);
- ret = sys_statfs((const char *)path, &s);
- set_fs (old_fs);
- if (put_statfs(buf, &s))
- return -EFAULT;
+ char *pth;
+
+ pth = getname (path);
+ ret = PTR_ERR(pth);
+ if (!IS_ERR(pth)) {
+ set_fs (KERNEL_DS);
+ ret = sys_statfs((const char *)path, &s);
+ set_fs (old_fs);
+ if (!ret && put_statfs(buf, &s))
+ return -EFAULT;
+ }
return ret;
}
@@ -1652,6 +1657,19 @@
unsigned short shm_nattch;
};
+struct shmid64_ds32 {
+ struct ipc64_perm32 shm_perm;
+ __kernel_size_t32 shm_segsz;
+ __kernel_time_t32 shm_atime;
+ __kernel_time_t32 shm_dtime;
+ __kernel_time_t32 shm_ctime;
+ __kernel_pid_t32 shm_cpid;
+ __kernel_pid_t32 shm_lpid;
+ unsigned int shm_nattch;
+ unsigned int __unused1;
+ unsigned int __unused2;
+};
+
struct ipc_kludge32 {
u32 msgp;
s32 msgtyp;
@@ -1945,7 +1963,8 @@
int err = -EFAULT, err2;
struct shmid_ds s;
struct shmid64_ds s64;
- struct shmid_ds32 *up = (struct shmid_ds32 *)uptr;
+ struct shmid_ds32 *up32 = (struct shmid_ds32 *)uptr;
+ struct shmid64_ds32 *up64 = (struct shmid64_ds32 *)uptr;
mm_segment_t old_fs;
struct shm_info32 {
int used_ids;
@@ -1954,18 +1973,24 @@
} *uip = (struct shm_info32 *)uptr;
struct shm_info si;
- switch (second) {
-
+ switch (second & ~IPC_64) {
case IPC_INFO:
+ second = IPC_INFO; /* So that we don't have to translate it */
case IPC_RMID:
case SHM_LOCK:
case SHM_UNLOCK:
err = sys_shmctl (first, second, (struct shmid_ds *)uptr);
break;
case IPC_SET:
- err = get_user (s.shm_perm.uid, &up->shm_perm.uid);
- err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);
- err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);
+ if (second & IPC_64) {
+ err = get_user(s.shm_perm.uid, &up64->shm_perm.uid);
+ err |= get_user(s.shm_perm.gid, &up64->shm_perm.gid);
+ err |= get_user(s.shm_perm.mode, &up64->shm_perm.mode);
+ } else {
+ err = get_user(s.shm_perm.uid, &up32->shm_perm.uid);
+ err |= get_user(s.shm_perm.gid, &up32->shm_perm.gid);
+ err |= get_user(s.shm_perm.mode, &up32->shm_perm.mode);
+ }
if (err)
break;
old_fs = get_fs ();
@@ -1982,23 +2007,45 @@
set_fs (old_fs);
if (err < 0)
break;
- err2 = put_user (s64.shm_perm.key, &up->shm_perm.key);
- err2 |= __put_user (s64.shm_perm.uid, &up->shm_perm.uid);
- err2 |= __put_user (s64.shm_perm.gid, &up->shm_perm.gid);
- err2 |= __put_user (s64.shm_perm.cuid,
- &up->shm_perm.cuid);
- err2 |= __put_user (s64.shm_perm.cgid,
- &up->shm_perm.cgid);
- err2 |= __put_user (s64.shm_perm.mode,
- &up->shm_perm.mode);
- err2 |= __put_user (s64.shm_perm.seq, &up->shm_perm.seq);
- err2 |= __put_user (s64.shm_atime, &up->shm_atime);
- err2 |= __put_user (s64.shm_dtime, &up->shm_dtime);
- err2 |= __put_user (s64.shm_ctime, &up->shm_ctime);
- err2 |= __put_user (s64.shm_segsz, &up->shm_segsz);
- err2 |= __put_user (s64.shm_nattch, &up->shm_nattch);
- err2 |= __put_user (s64.shm_cpid, &up->shm_cpid);
- err2 |= __put_user (s64.shm_lpid, &up->shm_lpid);
+ if (second & IPC_64) {
+ if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) {
+ err = -EFAULT;
+ break;
+ }
+ err2 = __put_user(s64.shm_perm.key, &up64->shm_perm.key);
+ err2 |= __put_user(s64.shm_perm.uid, &up64->shm_perm.uid);
+ err2 |= __put_user(s64.shm_perm.gid, &up64->shm_perm.gid);
+ err2 |= __put_user(s64.shm_perm.cuid, &up64->shm_perm.cuid);
+ err2 |= __put_user(s64.shm_perm.cgid, &up64->shm_perm.cgid);
+ err2 |= __put_user(s64.shm_perm.mode, &up64->shm_perm.mode);
+ err2 |= __put_user(s64.shm_perm.seq, &up64->shm_perm.seq);
+ err2 |= __put_user(s64.shm_atime, &up64->shm_atime);
+ err2 |= __put_user(s64.shm_dtime, &up64->shm_dtime);
+ err2 |= __put_user(s64.shm_ctime, &up64->shm_ctime);
+ err2 |= __put_user(s64.shm_segsz, &up64->shm_segsz);
+ err2 |= __put_user(s64.shm_nattch, &up64->shm_nattch);
+ err2 |= __put_user(s64.shm_cpid, &up64->shm_cpid);
+ err2 |= __put_user(s64.shm_lpid, &up64->shm_lpid);
+ } else {
+ if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) {
+ err = -EFAULT;
+ break;
+ }
+ err2 = __put_user(s64.shm_perm.key, &up32->shm_perm.key);
+ err2 |= __put_user(s64.shm_perm.uid, &up32->shm_perm.uid);
+ err2 |= __put_user(s64.shm_perm.gid, &up32->shm_perm.gid);
+ err2 |= __put_user(s64.shm_perm.cuid, &up32->shm_perm.cuid);
+ err2 |= __put_user(s64.shm_perm.cgid, &up32->shm_perm.cgid);
+ err2 |= __put_user(s64.shm_perm.mode, &up32->shm_perm.mode);
+ err2 |= __put_user(s64.shm_perm.seq, &up32->shm_perm.seq);
+ err2 |= __put_user(s64.shm_atime, &up32->shm_atime);
+ err2 |= __put_user(s64.shm_dtime, &up32->shm_dtime);
+ err2 |= __put_user(s64.shm_ctime, &up32->shm_ctime);
+ err2 |= __put_user(s64.shm_segsz, &up32->shm_segsz);
+ err2 |= __put_user(s64.shm_nattch, &up32->shm_nattch);
+ err2 |= __put_user(s64.shm_cpid, &up32->shm_cpid);
+ err2 |= __put_user(s64.shm_lpid, &up32->shm_lpid);
+ }
if (err2)
err = -EFAULT;
break;
@@ -2022,7 +2069,11 @@
err = -EFAULT;
break;
+ default:
+ err = - EINVAL;
+ break;
}
+
return err;
}
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: 64-bit kernel patch 2002-10-10 11:26 64-bit kernel patch Carsten Langgaard @ 2002-10-10 11:41 ` Ralf Baechle 0 siblings, 0 replies; 17+ messages in thread From: Ralf Baechle @ 2002-10-10 11:41 UTC (permalink / raw) To: Carsten Langgaard; +Cc: Maciej W. Rozycki, linux-mips On Thu, Oct 10, 2002 at 01:26:55PM +0200, Carsten Langgaard wrote: > Here is yet another patch for the 64-bit syscall wrapper. Thanks for this obvious fix ... Ralf ^ permalink raw reply [flat|nested] 17+ messages in thread
* 64-bit kernel patch.
@ 2002-10-02 13:22 Carsten Langgaard
2002-10-02 13:40 ` Maciej W. Rozycki
0 siblings, 1 reply; 17+ messages in thread
From: Carsten Langgaard @ 2002-10-02 13:22 UTC (permalink / raw)
To: Ralf Baechle, linux-mips
[-- Attachment #1: Type: text/plain, Size: 550 bytes --]
I have a number of patches for the o32 syscall wrapper/conversion
routines, which is needed when running a 64-bit kernel on an o32
userland.
Here is the first one. Ralf, could you please apply it, so I can send
the next one.
/Carsten
--
_ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com
|\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527
| \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555
TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556
Denmark http://www.mips.com
[-- Attachment #2: syscall_wrapper.part1.patch --]
[-- Type: text/plain, Size: 1670 bytes --]
Index: arch/mips64/kernel/linux32.c
===================================================================
RCS file: /home/cvs/linux/arch/mips64/kernel/linux32.c,v
retrieving revision 1.42.2.12
diff -u -r1.42.2.12 linux32.c
--- arch/mips64/kernel/linux32.c 27 Sep 2002 23:29:17 -0000 1.42.2.12
+++ arch/mips64/kernel/linux32.c 2 Oct 2002 13:13:42 -0000
@@ -179,7 +179,32 @@
return err;
}
-asmlinkage int sys_mmap2(void) {return 0;}
+asmlinkage unsigned long
+sys32_mmap2(unsigned long addr, size_t len, unsigned long prot,
+ unsigned long flags, unsigned long fd, unsigned long pgoff)
+{
+ struct file * file = NULL;
+ unsigned long error;
+
+ error = -EINVAL;
+ if (!(flags & MAP_ANONYMOUS)) {
+ error = -EBADF;
+ file = fget(fd);
+ if (!file)
+ goto out;
+ }
+ flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
+
+ down_write(¤t->mm->mmap_sem);
+ error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+ up_write(¤t->mm->mmap_sem);
+ if (file)
+ fput(file);
+
+out:
+ return error;
+}
+
asmlinkage long sys_truncate(const char * path, unsigned long length);
Index: arch/mips64/kernel/scall_o32.S
===================================================================
RCS file: /home/cvs/linux/arch/mips64/kernel/scall_o32.S,v
retrieving revision 1.48.2.15
diff -u -r1.48.2.15 scall_o32.S
--- arch/mips64/kernel/scall_o32.S 11 Sep 2002 13:56:36 -0000 1.48.2.15
+++ arch/mips64/kernel/scall_o32.S 2 Oct 2002 13:13:42 -0000
@@ -522,7 +522,7 @@
sys sys_sendfile 4
sys sys_ni_syscall 0
sys sys_ni_syscall 0
- sys sys_mmap2 6 /* 4210 */
+ sys sys32_mmap2 6 /* 4210 */
sys sys_truncate64 2
sys sys_ftruncate64 2
sys sys_newstat 2
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: 64-bit kernel patch. 2002-10-02 13:22 Carsten Langgaard @ 2002-10-02 13:40 ` Maciej W. Rozycki 2002-10-02 13:44 ` Carsten Langgaard ` (2 more replies) 0 siblings, 3 replies; 17+ messages in thread From: Maciej W. Rozycki @ 2002-10-02 13:40 UTC (permalink / raw) To: Carsten Langgaard; +Cc: Ralf Baechle, linux-mips On Wed, 2 Oct 2002, Carsten Langgaard wrote: > I have a number of patches for the o32 syscall wrapper/conversion > routines, which is needed when running a 64-bit kernel on an o32 > userland. > Here is the first one. Ralf, could you please apply it, so I can send > the next one. Do you have a fix for sys32_sendmsg/sys32_recvmsg as well? I just started working on it and I'd prefer not to do a duplicate work. As a side note -- arch/mips64/kernel/linux32.c is a huge collection of often unrelated functions. It might be beneficial to split the file functionally, e.g. into fs32.c, net32.c, etc. or even with a finer grain, preferably in a subdirectory, e.g. arch/mips64/linux32/. What do you think? -- + Maciej W. Rozycki, Technical University of Gdansk, Poland + +--------------------------------------------------------------+ + e-mail: macro@ds2.pg.gda.pl, PGP key available + ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: 64-bit kernel patch. 2002-10-02 13:40 ` Maciej W. Rozycki @ 2002-10-02 13:44 ` Carsten Langgaard 2002-10-02 13:46 ` Ralf Baechle 2002-10-02 14:05 ` Carsten Langgaard 2 siblings, 0 replies; 17+ messages in thread From: Carsten Langgaard @ 2002-10-02 13:44 UTC (permalink / raw) To: Maciej W. Rozycki; +Cc: Ralf Baechle, linux-mips "Maciej W. Rozycki" wrote: > On Wed, 2 Oct 2002, Carsten Langgaard wrote: > > > I have a number of patches for the o32 syscall wrapper/conversion > > routines, which is needed when running a 64-bit kernel on an o32 > > userland. > > Here is the first one. Ralf, could you please apply it, so I can send > > the next one. > > Do you have a fix for sys32_sendmsg/sys32_recvmsg as well? I just > started working on it and I'd prefer not to do a duplicate work. Yes, that's exactly the next one, I will be sending. So stay tuned. > > As a side note -- arch/mips64/kernel/linux32.c is a huge collection of > often unrelated functions. It might be beneficial to split the file > functionally, e.g. into fs32.c, net32.c, etc. or even with a finer grain, > preferably in a subdirectory, e.g. arch/mips64/linux32/. What do you > think? That's probably a good idea, but I would like to get my patches out first, before splitting things up. > > > -- > + Maciej W. Rozycki, Technical University of Gdansk, Poland + > +--------------------------------------------------------------+ > + e-mail: macro@ds2.pg.gda.pl, PGP key available + -- _ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com |\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527 | \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555 TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556 Denmark http://www.mips.com ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: 64-bit kernel patch. 2002-10-02 13:40 ` Maciej W. Rozycki 2002-10-02 13:44 ` Carsten Langgaard @ 2002-10-02 13:46 ` Ralf Baechle 2002-10-02 14:02 ` Carsten Langgaard 2002-10-02 14:05 ` Carsten Langgaard 2 siblings, 1 reply; 17+ messages in thread From: Ralf Baechle @ 2002-10-02 13:46 UTC (permalink / raw) To: Maciej W. Rozycki; +Cc: Carsten Langgaard, linux-mips On Wed, Oct 02, 2002 at 03:40:27PM +0200, Maciej W. Rozycki wrote: > As a side note -- arch/mips64/kernel/linux32.c is a huge collection of > often unrelated functions. It might be beneficial to split the file > functionally, e.g. into fs32.c, net32.c, etc. or even with a finer grain, > preferably in a subdirectory, e.g. arch/mips64/linux32/. What do you > think? Much of the code is so generic it almost deserves to live in a directory even higher in the hierarchy. If you look at the 32-bit compat code for the various 64-bit architectures of Linux (in particular sparc64 and ia64), it's a single huge cut'n'paste session. Not much of that code is actually architecture dependant. Ralf ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: 64-bit kernel patch. 2002-10-02 13:46 ` Ralf Baechle @ 2002-10-02 14:02 ` Carsten Langgaard 2002-10-02 14:06 ` Ralf Baechle 0 siblings, 1 reply; 17+ messages in thread From: Carsten Langgaard @ 2002-10-02 14:02 UTC (permalink / raw) To: Ralf Baechle; +Cc: Maciej W. Rozycki, linux-mips Ralf Baechle wrote: > On Wed, Oct 02, 2002 at 03:40:27PM +0200, Maciej W. Rozycki wrote: > > > As a side note -- arch/mips64/kernel/linux32.c is a huge collection of > > often unrelated functions. It might be beneficial to split the file > > functionally, e.g. into fs32.c, net32.c, etc. or even with a finer grain, > > preferably in a subdirectory, e.g. arch/mips64/linux32/. What do you > > think? > > Much of the code is so generic it almost deserves to live in a directory > even higher in the hierarchy. If you look at the 32-bit compat code for > the various 64-bit architectures of Linux (in particular sparc64 and ia64), > it's a single huge cut'n'paste session. Not much of that code is actually > architecture dependant. That would be even better, but unfortunately a lot of the structures used in the compat code is not exactly the same across architectures :-( But it should be possible to merges a lot this stuff into a generic (architecture independent) set of functions. > > Ralf -- _ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com |\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527 | \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555 TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556 Denmark http://www.mips.com ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: 64-bit kernel patch. 2002-10-02 14:02 ` Carsten Langgaard @ 2002-10-02 14:06 ` Ralf Baechle 0 siblings, 0 replies; 17+ messages in thread From: Ralf Baechle @ 2002-10-02 14:06 UTC (permalink / raw) To: Carsten Langgaard; +Cc: Maciej W. Rozycki, linux-mips On Wed, Oct 02, 2002 at 04:02:55PM +0200, Carsten Langgaard wrote: > > Much of the code is so generic it almost deserves to live in a directory > > even higher in the hierarchy. If you look at the 32-bit compat code for > > the various 64-bit architectures of Linux (in particular sparc64 and ia64), > > it's a single huge cut'n'paste session. Not much of that code is actually > > architecture dependant. > > That would be even better, but unfortunately a lot of the structures used in > the compat code is not exactly the same across architectures :-( > But it should be possible to merges a lot this stuff into a generic > (architecture independent) set of functions. True. The basic plan would be to provide the structure definitions and some architecture dependencies from headers and keep the generic compat code in a linux-32 directory. The syscalls are still fairly harmless - the true pain are all the ioctls that keep growing and changing like weed ... Ralf ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: 64-bit kernel patch. 2002-10-02 13:40 ` Maciej W. Rozycki 2002-10-02 13:44 ` Carsten Langgaard 2002-10-02 13:46 ` Ralf Baechle @ 2002-10-02 14:05 ` Carsten Langgaard 2002-10-02 14:09 ` Ralf Baechle 2 siblings, 1 reply; 17+ messages in thread From: Carsten Langgaard @ 2002-10-02 14:05 UTC (permalink / raw) To: Maciej W. Rozycki; +Cc: Ralf Baechle, linux-mips [-- Attachment #1: Type: text/plain, Size: 1371 bytes --] Ok, here is the next patch. It fixes the sys32_sendmsg and sys32_recvmsg. /Carsten "Maciej W. Rozycki" wrote: > On Wed, 2 Oct 2002, Carsten Langgaard wrote: > > > I have a number of patches for the o32 syscall wrapper/conversion > > routines, which is needed when running a 64-bit kernel on an o32 > > userland. > > Here is the first one. Ralf, could you please apply it, so I can send > > the next one. > > Do you have a fix for sys32_sendmsg/sys32_recvmsg as well? I just > started working on it and I'd prefer not to do a duplicate work. > > As a side note -- arch/mips64/kernel/linux32.c is a huge collection of > often unrelated functions. It might be beneficial to split the file > functionally, e.g. into fs32.c, net32.c, etc. or even with a finer grain, > preferably in a subdirectory, e.g. arch/mips64/linux32/. What do you > think? > > -- > + Maciej W. Rozycki, Technical University of Gdansk, Poland + > +--------------------------------------------------------------+ > + e-mail: macro@ds2.pg.gda.pl, PGP key available + -- _ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com |\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527 | \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555 TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556 Denmark http://www.mips.com [-- Attachment #2: syscall_wrapper.part2.patch --] [-- Type: text/plain, Size: 21784 bytes --] Index: arch/mips64/kernel/linux32.c =================================================================== RCS file: /home/cvs/linux/arch/mips64/kernel/linux32.c,v retrieving revision 1.42.2.13 diff -u -r1.42.2.13 linux32.c --- arch/mips64/kernel/linux32.c 2 Oct 2002 13:32:45 -0000 1.42.2.13 +++ arch/mips64/kernel/linux32.c 2 Oct 2002 13:55:08 -0000 @@ -32,6 +32,7 @@ #include <linux/dnotify.h> #include <linux/module.h> #include <net/sock.h> +#include <net/scm.h> #include <asm/uaccess.h> #include <asm/mman.h> @@ -1712,6 +1713,7 @@ return err; } +static int do_sys32_msgsnd (int first, int second, int third, void *uptr) { struct msgbuf32 *up = (struct msgbuf32 *)uptr; @@ -2244,7 +2246,7 @@ /* * Declare the 32-bit version of the msghdr */ - + struct msghdr32 { unsigned int msg_name; /* Socket name */ int msg_namelen; /* Length of name */ @@ -2255,74 +2257,132 @@ unsigned msg_flags; }; -static inline int -shape_msg(struct msghdr *mp, struct msghdr32 *mp32) +struct cmsghdr32 { + __kernel_size_t32 cmsg_len; + int cmsg_level; + int cmsg_type; +}; + +/* Bleech... */ +#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen)) +#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen) cmsg32_nxthdr((mhdr), (cmsg), (cmsglen)) + +#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) ) + +#define CMSG32_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32)))) +#define CMSG32_SPACE(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len)) +#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len)) + +#define __CMSG32_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr32) ? \ + (struct cmsghdr32 *)(ctl) : \ + (struct cmsghdr32 *)NULL) +#define CMSG32_FIRSTHDR(msg) __CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen) + +__inline__ struct cmsghdr32 *__cmsg32_nxthdr(void *__ctl, __kernel_size_t __size, + struct cmsghdr32 *__cmsg, int __cmsg_len) { - int ret; - unsigned int i; + struct cmsghdr32 * __ptr; - if (!access_ok(VERIFY_READ, mp32, sizeof(*mp32))) - return(-EFAULT); - ret = __get_user(i, &mp32->msg_name); - mp->msg_name = (void *)A(i); - ret |= __get_user(mp->msg_namelen, &mp32->msg_namelen); - ret |= __get_user(i, &mp32->msg_iov); - mp->msg_iov = (struct iovec *)A(i); - ret |= __get_user(mp->msg_iovlen, &mp32->msg_iovlen); - ret |= __get_user(i, &mp32->msg_control); - mp->msg_control = (void *)A(i); - ret |= __get_user(mp->msg_controllen, &mp32->msg_controllen); - ret |= __get_user(mp->msg_flags, &mp32->msg_flags); - return(ret ? -EFAULT : 0); + __ptr = (struct cmsghdr32 *)(((unsigned char *) __cmsg) + + CMSG32_ALIGN(__cmsg_len)); + if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size) + return NULL; + + return __ptr; } -/* - * Verify & re-shape IA32 iovec. The caller must ensure that the - * iovec is big enough to hold the re-shaped message iovec. - * - * Save time not doing verify_area. copy_*_user will make this work - * in any case. - * - * Don't need to check the total size for overflow (cf net/core/iovec.c), - * 32-bit sizes can't overflow a 64-bit count. - */ +__inline__ struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *__msg, + struct cmsghdr32 *__cmsg, + int __cmsg_len) +{ + return __cmsg32_nxthdr(__msg->msg_control, __msg->msg_controllen, + __cmsg, __cmsg_len); +} -static inline int -verify_iovec32(struct msghdr *m, struct iovec *iov, char *address, int mode) +static inline int iov_from_user32_to_kern(struct iovec *kiov, + struct iovec32 *uiov32, + int niov) { - int size, err, ct; - struct iovec32 *iov32; + int tot_len = 0; - if(m->msg_namelen) - { - if(mode==VERIFY_READ) - { - err=move_addr_to_kernel(m->msg_name, m->msg_namelen, address); - if(err<0) - goto out; + while(niov > 0) { + u32 len, buf; + + if(get_user(len, &uiov32->iov_len) || + get_user(buf, &uiov32->iov_base)) { + tot_len = -EFAULT; + break; } + tot_len += len; + kiov->iov_base = (void *)AA(buf); + kiov->iov_len = (__kernel_size_t) len; + uiov32++; + kiov++; + niov--; + } + return tot_len; +} - m->msg_name = address; - } else - m->msg_name = NULL; +static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, + struct msghdr32 *umsg) +{ + u32 tmp1, tmp2, tmp3; + int err; - err = -EFAULT; - size = m->msg_iovlen * sizeof(struct iovec32); - if (copy_from_user(iov, m->msg_iov, size)) - goto out; - m->msg_iov=iov; + err = get_user(tmp1, &umsg->msg_name); + err |= __get_user(tmp2, &umsg->msg_iov); + err |= __get_user(tmp3, &umsg->msg_control); + if (err) + return -EFAULT; - err = 0; - iov32 = (struct iovec32 *)iov; - for (ct = m->msg_iovlen; ct-- > 0; ) { - iov[ct].iov_len = (__kernel_size_t)iov32[ct].iov_len; - iov[ct].iov_base = (void *) A(iov32[ct].iov_base); - err += iov[ct].iov_len; - } -out: + kmsg->msg_name = (void *)AA(tmp1); + kmsg->msg_iov = (struct iovec *)AA(tmp2); + kmsg->msg_control = (void *)AA(tmp3); + + err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); + err |= get_user(kmsg->msg_iovlen, &umsg->msg_iovlen); + err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); + err |= get_user(kmsg->msg_flags, &umsg->msg_flags); + return err; } +/* I've named the args so it is easy to tell whose space the pointers are in. */ +static int verify_iovec32(struct msghdr *kern_msg, struct iovec *kern_iov, + char *kern_address, int mode) +{ + int tot_len; + + if(kern_msg->msg_namelen) { + if(mode==VERIFY_READ) { + int err = move_addr_to_kernel(kern_msg->msg_name, + kern_msg->msg_namelen, + kern_address); + if(err < 0) + return err; + } + kern_msg->msg_name = kern_address; + } else + kern_msg->msg_name = NULL; + + if(kern_msg->msg_iovlen > UIO_FASTIOV) { + kern_iov = kmalloc(kern_msg->msg_iovlen * sizeof(struct iovec), + GFP_KERNEL); + if(!kern_iov) + return -ENOMEM; + } + + tot_len = iov_from_user32_to_kern(kern_iov, + (struct iovec32 *)kern_msg->msg_iov, + kern_msg->msg_iovlen); + if(tot_len >= 0) + kern_msg->msg_iov = kern_iov; + else if(kern_msg->msg_iovlen > UIO_FASTIOV) + kfree(kern_iov); + + return tot_len; +} + extern __inline__ void sockfd_put(struct socket *sock) { @@ -2330,177 +2390,385 @@ } /* XXX This really belongs in some header file... -DaveM */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - +#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - 16 for IP, 16 for IPX, 24 for IPv6, about 80 for AX.25 */ extern struct socket *sockfd_lookup(int fd, int *err); -/* - * BSD sendmsg interface +/* There is a lot of hair here because the alignment rules (and + * thus placement) of cmsg headers and length are different for + * 32-bit apps. -DaveM */ - -int sys32_sendmsg(int fd, struct msghdr32 *msg, unsigned flags) +static int cmsghdr_from_user32_to_kern(struct msghdr *kmsg, + unsigned char *stackbuf, int stackbuf_size) { - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; /* 20 is size of ipv6_pktinfo */ - unsigned char *ctl_buf = ctl; - struct msghdr msg_sys; - int err, ctl_len, iov_size, total_len; + struct cmsghdr32 *ucmsg; + struct cmsghdr *kcmsg, *kcmsg_base; + __kernel_size_t32 ucmlen; + __kernel_size_t kcmlen, tmp; + + kcmlen = 0; + kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf; + ucmsg = CMSG32_FIRSTHDR(kmsg); + while(ucmsg != NULL) { + if(get_user(ucmlen, &ucmsg->cmsg_len)) + return -EFAULT; - err = -EFAULT; - if (shape_msg(&msg_sys, msg)) - goto out; + /* Catch bogons. */ + if(CMSG32_ALIGN(ucmlen) < + CMSG32_ALIGN(sizeof(struct cmsghdr32))) + return -ENOBUFS; + if((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) + + ucmlen) > kmsg->msg_controllen) + return -EINVAL; + + tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + + CMSG_ALIGN(sizeof(struct cmsghdr))); + kcmlen += tmp; + ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); + } + if(kcmlen == 0) + return -EINVAL; - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; + /* The kcmlen holds the 64-bit version of the control length. + * It may not be modified as we do not stick it into the kmsg + * until we have successfully copied over all of the data + * from the user. + */ + if(kcmlen > stackbuf_size) + kcmsg_base = kcmsg = kmalloc(kcmlen, GFP_KERNEL); + if(kcmsg == NULL) + return -ENOBUFS; + + /* Now copy them over neatly. */ + memset(kcmsg, 0, kcmlen); + ucmsg = CMSG32_FIRSTHDR(kmsg); + while(ucmsg != NULL) { + __get_user(ucmlen, &ucmsg->cmsg_len); + tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) + + CMSG_ALIGN(sizeof(struct cmsghdr))); + kcmsg->cmsg_len = tmp; + __get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level); + __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type); + + /* Copy over the data. */ + if(copy_from_user(CMSG_DATA(kcmsg), + CMSG32_DATA(ucmsg), + (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))))) + goto out_free_efault; + + /* Advance. */ + kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp)); + ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen); + } + + /* Ok, looks like we made it. Hook it up and return success. */ + kmsg->msg_control = kcmsg_base; + kmsg->msg_controllen = kcmlen; + return 0; - /* do not move before msg_sys is valid */ - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; +out_free_efault: + if(kcmsg_base != (struct cmsghdr *)stackbuf) + kfree(kcmsg_base); + return -EFAULT; +} - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; +static void put_cmsg32(struct msghdr *kmsg, int level, int type, + int len, void *data) +{ + struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; + struct cmsghdr32 cmhdr; + int cmlen = CMSG32_LEN(len); + + if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) { + kmsg->msg_flags |= MSG_CTRUNC; + return; } - /* This will also move the address data into kernel space */ - err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ); - if (err < 0) - goto out_freeiov; - total_len = err; + if(kmsg->msg_controllen < cmlen) { + kmsg->msg_flags |= MSG_CTRUNC; + cmlen = kmsg->msg_controllen; + } + cmhdr.cmsg_level = level; + cmhdr.cmsg_type = type; + cmhdr.cmsg_len = cmlen; - err = -ENOBUFS; + if(copy_to_user(cm, &cmhdr, sizeof cmhdr)) + return; + if(copy_to_user(CMSG32_DATA(cm), data, cmlen - sizeof(struct cmsghdr32))) + return; + cmlen = CMSG32_SPACE(len); + kmsg->msg_control += cmlen; + kmsg->msg_controllen -= cmlen; +} + +static void scm_detach_fds32(struct msghdr *kmsg, struct scm_cookie *scm) +{ + struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control; + int fdmax = (kmsg->msg_controllen - sizeof(struct cmsghdr32)) / sizeof(int); + int fdnum = scm->fp->count; + struct file **fp = scm->fp->fp; + int *cmfptr; + int err = 0, i; + + if (fdnum < fdmax) + fdmax = fdnum; + + for (i = 0, cmfptr = (int *) CMSG32_DATA(cm); i < fdmax; i++, cmfptr++) { + int new_fd; + err = get_unused_fd(); + if (err < 0) + break; + new_fd = err; + err = put_user(new_fd, cmfptr); + if (err) { + put_unused_fd(new_fd); + break; + } + /* Bump the usage count and install the file. */ + get_file(fp[i]); + fd_install(new_fd, fp[i]); + } - if (msg_sys.msg_controllen > INT_MAX) - goto out_freeiov; - ctl_len = msg_sys.msg_controllen; - if (ctl_len) - { - if (ctl_len > sizeof(ctl)) - { - err = -ENOBUFS; - ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); - if (ctl_buf == NULL) - goto out_freeiov; + if (i > 0) { + int cmlen = CMSG32_LEN(i * sizeof(int)); + if (!err) + err = put_user(SOL_SOCKET, &cm->cmsg_level); + if (!err) + err = put_user(SCM_RIGHTS, &cm->cmsg_type); + if (!err) + err = put_user(cmlen, &cm->cmsg_len); + if (!err) { + cmlen = CMSG32_SPACE(i * sizeof(int)); + kmsg->msg_control += cmlen; + kmsg->msg_controllen -= cmlen; } - err = -EFAULT; - if (copy_from_user(ctl_buf, msg_sys.msg_control, ctl_len)) - goto out_freectl; - msg_sys.msg_control = ctl_buf; - } - msg_sys.msg_flags = flags; - - if (sock->file->f_flags & O_NONBLOCK) - msg_sys.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &msg_sys, total_len); - -out_freectl: - if (ctl_buf != ctl) - sock_kfree_s(sock->sk, ctl_buf, ctl_len); -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; + } + if (i < fdnum) + kmsg->msg_flags |= MSG_CTRUNC; + + /* + * All of the files that fit in the message have had their + * usage counts incremented, so we just free the list. + */ + __scm_destroy(scm); } -/* - * BSD recvmsg interface +/* In these cases we (currently) can just copy to data over verbatim + * because all CMSGs created by the kernel have well defined types which + * have the same layout in both the 32-bit and 64-bit API. One must add + * some special cased conversions here if we start sending control messages + * with incompatible types. + * + * SCM_RIGHTS and SCM_CREDENTIALS are done by hand in recvmsg32 right after + * we do our work. The remaining cases are: + * + * SOL_IP IP_PKTINFO struct in_pktinfo 32-bit clean + * IP_TTL int 32-bit clean + * IP_TOS __u8 32-bit clean + * IP_RECVOPTS variable length 32-bit clean + * IP_RETOPTS variable length 32-bit clean + * (these last two are clean because the types are defined + * by the IPv4 protocol) + * IP_RECVERR struct sock_extended_err + + * struct sockaddr_in 32-bit clean + * SOL_IPV6 IPV6_RECVERR struct sock_extended_err + + * struct sockaddr_in6 32-bit clean + * IPV6_PKTINFO struct in6_pktinfo 32-bit clean + * IPV6_HOPLIMIT int 32-bit clean + * IPV6_FLOWINFO u32 32-bit clean + * IPV6_HOPOPTS ipv6 hop exthdr 32-bit clean + * IPV6_DSTOPTS ipv6 dst exthdr(s) 32-bit clean + * IPV6_RTHDR ipv6 routing exthdr 32-bit clean + * IPV6_AUTHHDR ipv6 auth exthdr 32-bit clean */ - -int -sys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags) +static void cmsg32_recvmsg_fixup(struct msghdr *kmsg, unsigned long orig_cmsg_uptr) { - struct socket *sock; - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov=iovstack; - struct msghdr msg_sys; - unsigned long cmsg_ptr; - int err, iov_size, total_len, len; + unsigned char *workbuf, *wp; + unsigned long bufsz, space_avail; + struct cmsghdr *ucmsg; + + bufsz = ((unsigned long)kmsg->msg_control) - orig_cmsg_uptr; + space_avail = kmsg->msg_controllen + bufsz; + wp = workbuf = kmalloc(bufsz, GFP_KERNEL); + if(workbuf == NULL) + goto fail; + + /* To make this more sane we assume the kernel sends back properly + * formatted control messages. Because of how the kernel will truncate + * the cmsg_len for MSG_TRUNC cases, we need not check that case either. + */ + ucmsg = (struct cmsghdr *) orig_cmsg_uptr; + while(((unsigned long)ucmsg) <= + (((unsigned long)kmsg->msg_control) - sizeof(struct cmsghdr))) { + struct cmsghdr32 *kcmsg32 = (struct cmsghdr32 *) wp; + int clen64, clen32; + + /* UCMSG is the 64-bit format CMSG entry in user-space. + * KCMSG32 is within the kernel space temporary buffer + * we use to convert into a 32-bit style CMSG. + */ + __get_user(kcmsg32->cmsg_len, &ucmsg->cmsg_len); + __get_user(kcmsg32->cmsg_level, &ucmsg->cmsg_level); + __get_user(kcmsg32->cmsg_type, &ucmsg->cmsg_type); + + clen64 = kcmsg32->cmsg_len; + copy_from_user(CMSG32_DATA(kcmsg32), CMSG_DATA(ucmsg), + clen64 - CMSG_ALIGN(sizeof(*ucmsg))); + clen32 = ((clen64 - CMSG_ALIGN(sizeof(*ucmsg))) + + CMSG32_ALIGN(sizeof(struct cmsghdr32))); + kcmsg32->cmsg_len = clen32; + + ucmsg = (struct cmsghdr *) (((char *)ucmsg) + CMSG_ALIGN(clen64)); + wp = (((char *)kcmsg32) + CMSG32_ALIGN(clen32)); + } + + /* Copy back fixed up data, and adjust pointers. */ + bufsz = (wp - workbuf); + copy_to_user((void *)orig_cmsg_uptr, workbuf, bufsz); + + kmsg->msg_control = (struct cmsghdr *) + (((char *)orig_cmsg_uptr) + bufsz); + kmsg->msg_controllen = space_avail - bufsz; - /* kernel mode address */ - char addr[MAX_SOCK_ADDR]; + kfree(workbuf); + return; - /* user mode address pointers */ - struct sockaddr *uaddr; - int *uaddr_len; +fail: + /* If we leave the 64-bit format CMSG chunks in there, + * the application could get confused and crash. So to + * ensure greater recovery, we report no CMSGs. + */ + kmsg->msg_controllen += bufsz; + kmsg->msg_control = (void *) orig_cmsg_uptr; +} - err=-EFAULT; - if (shape_msg(&msg_sys, msg)) - goto out; +asmlinkage int sys32_sendmsg(int fd, struct msghdr32 *user_msg, unsigned user_flags) +{ + struct socket *sock; + char address[MAX_SOCK_ADDR]; + struct iovec iov[UIO_FASTIOV]; + unsigned char ctl[sizeof(struct cmsghdr) + 20]; + unsigned char *ctl_buf = ctl; + struct msghdr kern_msg; + int err, total_len; - sock = sockfd_lookup(fd, &err); - if (!sock) + if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) + return -EFAULT; + if(kern_msg.msg_iovlen > UIO_MAXIOV) + return -EINVAL; + err = verify_iovec32(&kern_msg, iov, address, VERIFY_READ); + if (err < 0) goto out; + total_len = err; - err = -EINVAL; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; + if(kern_msg.msg_controllen) { + err = cmsghdr_from_user32_to_kern(&kern_msg, ctl, sizeof(ctl)); + if(err) + goto out_freeiov; + ctl_buf = kern_msg.msg_control; + } + kern_msg.msg_flags = user_flags; - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; + sock = sockfd_lookup(fd, &err); + if (sock != NULL) { + if (sock->file->f_flags & O_NONBLOCK) + kern_msg.msg_flags |= MSG_DONTWAIT; + err = sock_sendmsg(sock, &kern_msg, total_len); + sockfd_put(sock); } - /* - * Save the user-mode address (verify_iovec will change the - * kernel msghdr to use the kernel address space) - */ + /* N.B. Use kfree here, as kern_msg.msg_controllen might change? */ + if(ctl_buf != ctl) + kfree(ctl_buf); +out_freeiov: + if(kern_msg.msg_iov != iov) + kfree(kern_msg.msg_iov); +out: + return err; +} - uaddr = msg_sys.msg_name; - uaddr_len = &msg->msg_namelen; - err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out_freeiov; - total_len=err; +asmlinkage int sys32_recvmsg(int fd, struct msghdr32 *user_msg, unsigned int user_flags) +{ + struct iovec iovstack[UIO_FASTIOV]; + struct msghdr kern_msg; + char addr[MAX_SOCK_ADDR]; + struct socket *sock; + struct iovec *iov = iovstack; + struct sockaddr *uaddr; + int *uaddr_len; + unsigned long cmsg_ptr; + int err, total_len, len = 0; - cmsg_ptr = (unsigned long)msg_sys.msg_control; - msg_sys.msg_flags = 0; + if(msghdr_from_user32_to_kern(&kern_msg, user_msg)) + return -EFAULT; + if(kern_msg.msg_iovlen > UIO_MAXIOV) + return -EINVAL; - if (sock->file->f_flags & O_NONBLOCK) - flags |= MSG_DONTWAIT; - err = sock_recvmsg(sock, &msg_sys, total_len, flags); + uaddr = kern_msg.msg_name; + uaddr_len = &user_msg->msg_namelen; + err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE); if (err < 0) - goto out_freeiov; - len = err; + goto out; + total_len = err; - if (uaddr != NULL) { - err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len); - if (err < 0) - goto out_freeiov; + cmsg_ptr = (unsigned long) kern_msg.msg_control; + kern_msg.msg_flags = 0; + + sock = sockfd_lookup(fd, &err); + if (sock != NULL) { + struct scm_cookie scm; + + if (sock->file->f_flags & O_NONBLOCK) + user_flags |= MSG_DONTWAIT; + memset(&scm, 0, sizeof(scm)); + err = sock->ops->recvmsg(sock, &kern_msg, total_len, + user_flags, &scm); + if(err >= 0) { + len = err; + if(!kern_msg.msg_control) { + if(sock->passcred || scm.fp) + kern_msg.msg_flags |= MSG_CTRUNC; + if(scm.fp) + __scm_destroy(&scm); + } else { + /* If recvmsg processing itself placed some + * control messages into user space, it's is + * using 64-bit CMSG processing, so we need + * to fix it up before we tack on more stuff. + */ + if((unsigned long) kern_msg.msg_control != cmsg_ptr) + cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr); + + /* Wheee... */ + if(sock->passcred) + put_cmsg32(&kern_msg, + SOL_SOCKET, SCM_CREDENTIALS, + sizeof(scm.creds), &scm.creds); + if(scm.fp != NULL) + scm_detach_fds32(&kern_msg, &scm); + } + } + sockfd_put(sock); } - err = __put_user(msg_sys.msg_flags, &msg->msg_flags); - if (err) - goto out_freeiov; - err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr, - &msg->msg_controllen); - if (err) - goto out_freeiov; - err = len; -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); + if(uaddr != NULL && kern_msg.msg_namelen && err >= 0) + err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len); + if(cmsg_ptr != 0 && err >= 0) { + unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control); + __kernel_size_t32 uclen = (__kernel_size_t32) (ucmsg_ptr - cmsg_ptr); + err |= __put_user(uclen, &user_msg->msg_controllen); + } + if(err >= 0) + err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags); + if(kern_msg.msg_iov != iov) + kfree(kern_msg.msg_iov); out: - return err; + if(err < 0) + return err; + return len; } asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count); ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: 64-bit kernel patch. 2002-10-02 14:05 ` Carsten Langgaard @ 2002-10-02 14:09 ` Ralf Baechle 2002-10-02 14:33 ` Carsten Langgaard ` (2 more replies) 0 siblings, 3 replies; 17+ messages in thread From: Ralf Baechle @ 2002-10-02 14:09 UTC (permalink / raw) To: Carsten Langgaard; +Cc: Maciej W. Rozycki, linux-mips On Wed, Oct 02, 2002 at 04:05:02PM +0200, Carsten Langgaard wrote: > Ok, here is the next patch. > It fixes the sys32_sendmsg and sys32_recvmsg. Ok, in. Maciej, you can start the chainsawing ;-) Ralf ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: 64-bit kernel patch. 2002-10-02 14:09 ` Ralf Baechle @ 2002-10-02 14:33 ` Carsten Langgaard 2002-10-03 6:49 ` Carsten Langgaard 2002-10-03 11:39 ` Maciej W. Rozycki 2 siblings, 0 replies; 17+ messages in thread From: Carsten Langgaard @ 2002-10-02 14:33 UTC (permalink / raw) To: Ralf Baechle; +Cc: Maciej W. Rozycki, linux-mips [-- Attachment #1: Type: text/plain, Size: 598 bytes --] Here is another linux32.c patch. /Carsten Ralf Baechle wrote: > On Wed, Oct 02, 2002 at 04:05:02PM +0200, Carsten Langgaard wrote: > > > Ok, here is the next patch. > > It fixes the sys32_sendmsg and sys32_recvmsg. > > Ok, in. Maciej, you can start the chainsawing ;-) > > Ralf -- _ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com |\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527 | \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555 TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556 Denmark http://www.mips.com [-- Attachment #2: syscall_wrapper.part3.patch --] [-- Type: text/plain, Size: 3532 bytes --] Index: arch/mips64/kernel/linux32.c =================================================================== RCS file: /home/cvs/linux/arch/mips64/kernel/linux32.c,v retrieving revision 1.42.2.14 diff -u -r1.42.2.14 linux32.c --- arch/mips64/kernel/linux32.c 2 Oct 2002 14:09:24 -0000 1.42.2.14 +++ arch/mips64/kernel/linux32.c 2 Oct 2002 14:29:30 -0000 @@ -1598,6 +1598,15 @@ unsigned short sem_nsems; /* no. of semaphores in array */ }; +struct semid64_ds32 { + struct ipc64_perm32 sem_perm; + __kernel_time_t32 sem_otime; + __kernel_time_t32 sem_ctime; + unsigned int sem_nsems; + unsigned int __unused1; + unsigned int __unused2; +}; + struct msqid_ds32 { struct ipc_perm32 msg_perm; @@ -1655,7 +1664,6 @@ u32 pad; int err, err2; struct semid64_ds s; - struct semid_ds32 *usp; mm_segment_t old_fs; if (!uptr) @@ -1668,7 +1676,6 @@ else fourth.__pad = (void *)A(pad); switch (third & ~IPC_64) { - case IPC_INFO: case IPC_RMID: case IPC_SET: @@ -1685,29 +1692,54 @@ case IPC_STAT: case SEM_STAT: - usp = (struct semid_ds32 *)A(pad); fourth.__pad = &s; old_fs = get_fs (); set_fs (KERNEL_DS); err = sys_semctl (first, second, third, fourth); set_fs (old_fs); - err2 = put_user(s.sem_perm.key, &usp->sem_perm.key); - err2 |= __put_user(s.sem_perm.uid, &usp->sem_perm.uid); - err2 |= __put_user(s.sem_perm.gid, &usp->sem_perm.gid); - err2 |= __put_user(s.sem_perm.cuid, - &usp->sem_perm.cuid); - err2 |= __put_user (s.sem_perm.cgid, - &usp->sem_perm.cgid); - err2 |= __put_user (s.sem_perm.mode, - &usp->sem_perm.mode); - err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq); - err2 |= __put_user (s.sem_otime, &usp->sem_otime); - err2 |= __put_user (s.sem_ctime, &usp->sem_ctime); - err2 |= __put_user (s.sem_nsems, &usp->sem_nsems); + + if (third & IPC_64) { + struct semid64_ds32 *usp64 = (struct semid64_ds32 *) A(pad); + + if (!access_ok(VERIFY_WRITE, usp64, sizeof(*usp64))) { + err = -EFAULT; + break; + } + err2 = __put_user(s.sem_perm.key, &usp64->sem_perm.key); + err2 |= __put_user(s.sem_perm.uid, &usp64->sem_perm.uid); + err2 |= __put_user(s.sem_perm.gid, &usp64->sem_perm.gid); + err2 |= __put_user(s.sem_perm.cuid, &usp64->sem_perm.cuid); + err2 |= __put_user(s.sem_perm.cgid, &usp64->sem_perm.cgid); + err2 |= __put_user(s.sem_perm.mode, &usp64->sem_perm.mode); + err2 |= __put_user(s.sem_perm.seq, &usp64->sem_perm.seq); + err2 |= __put_user(s.sem_otime, &usp64->sem_otime); + err2 |= __put_user(s.sem_ctime, &usp64->sem_ctime); + err2 |= __put_user(s.sem_nsems, &usp64->sem_nsems); + } else { + struct semid_ds32 *usp32 = (struct semid_ds32 *) A(pad); + + if (!access_ok(VERIFY_WRITE, usp32, sizeof(*usp32))) { + err = -EFAULT; + break; + } + err2 = __put_user(s.sem_perm.key, &usp32->sem_perm.key); + err2 |= __put_user(s.sem_perm.uid, &usp32->sem_perm.uid); + err2 |= __put_user(s.sem_perm.gid, &usp32->sem_perm.gid); + err2 |= __put_user(s.sem_perm.cuid, &usp32->sem_perm.cuid); + err2 |= __put_user(s.sem_perm.cgid, &usp32->sem_perm.cgid); + err2 |= __put_user(s.sem_perm.mode, &usp32->sem_perm.mode); + err2 |= __put_user(s.sem_perm.seq, &usp32->sem_perm.seq); + err2 |= __put_user(s.sem_otime, &usp32->sem_otime); + err2 |= __put_user(s.sem_ctime, &usp32->sem_ctime); + err2 |= __put_user(s.sem_nsems, &usp32->sem_nsems); + } if (err2) err = -EFAULT; break; + default: + err = - EINVAL; + break; } return err; ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: 64-bit kernel patch. 2002-10-02 14:09 ` Ralf Baechle 2002-10-02 14:33 ` Carsten Langgaard @ 2002-10-03 6:49 ` Carsten Langgaard 2002-10-03 11:39 ` Maciej W. Rozycki 2 siblings, 0 replies; 17+ messages in thread From: Carsten Langgaard @ 2002-10-03 6:49 UTC (permalink / raw) To: Ralf Baechle; +Cc: Maciej W. Rozycki, linux-mips [-- Attachment #1: Type: text/plain, Size: 597 bytes --] Here is the next patch in line. /Carsten Ralf Baechle wrote: > On Wed, Oct 02, 2002 at 04:05:02PM +0200, Carsten Langgaard wrote: > > > Ok, here is the next patch. > > It fixes the sys32_sendmsg and sys32_recvmsg. > > Ok, in. Maciej, you can start the chainsawing ;-) > > Ralf -- _ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com |\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527 | \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555 TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556 Denmark http://www.mips.com [-- Attachment #2: syscall_wrapper.part4.patch --] [-- Type: text/plain, Size: 1611 bytes --] Index: arch/mips64/kernel/linux32.c =================================================================== RCS file: /home/cvs/linux/arch/mips64/kernel/linux32.c,v retrieving revision 1.42.2.15 diff -u -r1.42.2.15 linux32.c --- arch/mips64/kernel/linux32.c 2 Oct 2002 14:40:23 -0000 1.42.2.15 +++ arch/mips64/kernel/linux32.c 3 Oct 2002 06:44:51 -0000 @@ -2803,6 +2803,27 @@ return len; } +extern asmlinkage ssize_t sys_sendfile(int out_fd, int in_fd, off_t *offset, size_t count); + +asmlinkage int sys32_sendfile(int out_fd, int in_fd, __kernel_off_t32 *offset, s32 count) +{ + mm_segment_t old_fs = get_fs(); + int ret; + off_t of; + + if (offset && get_user(of, offset)) + return -EFAULT; + + set_fs(KERNEL_DS); + ret = sys_sendfile(out_fd, in_fd, offset ? &of : NULL, count); + set_fs(old_fs); + + if (offset && put_user(of, offset)) + return -EFAULT; + + return ret; +} + asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count); asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3, Index: arch/mips64/kernel/scall_o32.S =================================================================== RCS file: /home/cvs/linux/arch/mips64/kernel/scall_o32.S,v retrieving revision 1.48.2.16 diff -u -r1.48.2.16 scall_o32.S --- arch/mips64/kernel/scall_o32.S 2 Oct 2002 13:32:45 -0000 1.48.2.16 +++ arch/mips64/kernel/scall_o32.S 3 Oct 2002 06:44:51 -0000 @@ -519,7 +519,7 @@ sys sys_capget 2 sys sys_capset 2 /* 4205 */ sys sys32_sigaltstack 0 - sys sys_sendfile 4 + sys sys32_sendfile 4 sys sys_ni_syscall 0 sys sys_ni_syscall 0 sys sys32_mmap2 6 /* 4210 */ ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: 64-bit kernel patch. 2002-10-02 14:09 ` Ralf Baechle 2002-10-02 14:33 ` Carsten Langgaard 2002-10-03 6:49 ` Carsten Langgaard @ 2002-10-03 11:39 ` Maciej W. Rozycki 2002-10-04 6:39 ` Carsten Langgaard 2 siblings, 1 reply; 17+ messages in thread From: Maciej W. Rozycki @ 2002-10-03 11:39 UTC (permalink / raw) To: Ralf Baechle; +Cc: Carsten Langgaard, linux-mips On Wed, 2 Oct 2002, Ralf Baechle wrote: > > Ok, here is the next patch. > > It fixes the sys32_sendmsg and sys32_recvmsg. > > Ok, in. Maciej, you can start the chainsawing ;-) Hmm, I couldn't test it as init now crashes with a SIGSEGV soon after starting. I had no time to investigate it further. I fear it might be related, though -- /dev/initctl communication? -- + Maciej W. Rozycki, Technical University of Gdansk, Poland + +--------------------------------------------------------------+ + e-mail: macro@ds2.pg.gda.pl, PGP key available + ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: 64-bit kernel patch. 2002-10-03 11:39 ` Maciej W. Rozycki @ 2002-10-04 6:39 ` Carsten Langgaard 2002-10-04 12:43 ` Maciej W. Rozycki 0 siblings, 1 reply; 17+ messages in thread From: Carsten Langgaard @ 2002-10-04 6:39 UTC (permalink / raw) To: Maciej W. Rozycki; +Cc: Ralf Baechle, linux-mips Hmm, are you sure it's related ? It works fine for me, and it fixes the problems I had before I added this fix. /Carsten "Maciej W. Rozycki" wrote: > On Wed, 2 Oct 2002, Ralf Baechle wrote: > > > > Ok, here is the next patch. > > > It fixes the sys32_sendmsg and sys32_recvmsg. > > > > Ok, in. Maciej, you can start the chainsawing ;-) > > Hmm, I couldn't test it as init now crashes with a SIGSEGV soon after > starting. I had no time to investigate it further. I fear it might be > related, though -- /dev/initctl communication? > > -- > + Maciej W. Rozycki, Technical University of Gdansk, Poland + > +--------------------------------------------------------------+ > + e-mail: macro@ds2.pg.gda.pl, PGP key available + -- _ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com |\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527 | \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555 TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556 Denmark http://www.mips.com ^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: 64-bit kernel patch. 2002-10-04 6:39 ` Carsten Langgaard @ 2002-10-04 12:43 ` Maciej W. Rozycki 0 siblings, 0 replies; 17+ messages in thread From: Maciej W. Rozycki @ 2002-10-04 12:43 UTC (permalink / raw) To: Carsten Langgaard; +Cc: Ralf Baechle, linux-mips On Fri, 4 Oct 2002, Carsten Langgaard wrote: > Hmm, are you sure it's related ? No, I wasn't -- as I wrote I had no time to investigate it further and I was asking for comments from people. Now I'm sure it is not. > It works fine for me, and it fixes the problems I had before I added this > fix. Yep, it works here with openssh, which used not to work before. Thanks a lot. The reason of the failure was a recent r4kcache.h breakage -- this is the kind of mistakes that makes me consider a run-time check a necessity even for supposedly trivial and innocent changes (well, a compilation should actually suffice for lone comment updates). -- + Maciej W. Rozycki, Technical University of Gdansk, Poland + +--------------------------------------------------------------+ + e-mail: macro@ds2.pg.gda.pl, PGP key available + ^ permalink raw reply [flat|nested] 17+ messages in thread
* 64-bit kernel patch
@ 2002-09-09 12:16 Carsten Langgaard
2002-09-09 13:03 ` Carsten Langgaard
0 siblings, 1 reply; 17+ messages in thread
From: Carsten Langgaard @ 2002-09-09 12:16 UTC (permalink / raw)
To: Ralf Baechle, linux-mips
I have send this patch before, although it's a little bit different from
the previous one.
The patch fixes the ipc syscalls in the o32 wrapper/conversion routines,
which is needed when running a 64-bit kernel on an o32 userland.
Ralf, could you please apply.
/Carsten
--
_ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com
|\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527
| \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555
TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556
Denmark http://www.mips.com
^ permalink raw reply [flat|nested] 17+ messages in thread* Re: 64-bit kernel patch 2002-09-09 12:16 Carsten Langgaard @ 2002-09-09 13:03 ` Carsten Langgaard 0 siblings, 0 replies; 17+ messages in thread From: Carsten Langgaard @ 2002-09-09 13:03 UTC (permalink / raw) To: Ralf Baechle, linux-mips [-- Attachment #1: Type: text/plain, Size: 1005 bytes --] OK, I try again. This time with the patch attached. /Carsten Carsten Langgaard wrote: > I have send this patch before, although it's a little bit different from > the previous one. > The patch fixes the ipc syscalls in the o32 wrapper/conversion routines, > which is needed when running a 64-bit kernel on an o32 userland. > Ralf, could you please apply. > > /Carsten > > -- > _ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com > |\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527 > | \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555 > TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556 > Denmark http://www.mips.com -- _ _ ____ ___ Carsten Langgaard Mailto:carstenl@mips.com |\ /|||___)(___ MIPS Denmark Direct: +45 4486 5527 | \/ ||| ____) Lautrupvang 4B Switch: +45 4486 5555 TECHNOLOGIES 2750 Ballerup Fax...: +45 4486 5556 Denmark http://www.mips.com [-- Attachment #2: ipc.patch --] [-- Type: text/plain, Size: 9947 bytes --] Index: arch/mips64/kernel/linux32.c =================================================================== RCS file: /cvs/linux/arch/mips64/kernel/linux32.c,v retrieving revision 1.42.2.9 diff -u -r1.42.2.9 linux32.c --- arch/mips64/kernel/linux32.c 2002/07/23 12:26:09 1.42.2.9 +++ arch/mips64/kernel/linux32.c 2002/09/09 12:06:04 @@ -35,8 +35,16 @@ #include <asm/mman.h> #include <asm/ipc.h> - +/* Use this to get at 32-bit user passed pointers. */ +/* A() macro should be used for places where you e.g. + have some internal variable u32 and just want to get + rid of a compiler warning. AA() has to be used in + places where you want to convert a function argument + to 32bit pointer or when you e.g. access pt_regs + structure and want to consider 32bit registers only. + */ #define A(__x) ((unsigned long)(__x)) +#define AA(__x) ((unsigned long)((int)__x)) #ifdef __MIPSEB__ #define merge_64(r1,r2) ((((r1) & 0xffffffffUL) << 32) + ((r2) & 0xffffffffUL)) @@ -1494,6 +1502,19 @@ unsigned short seq; }; +struct ipc64_perm32 { + key_t key; + __kernel_uid_t32 uid; + __kernel_gid_t32 gid; + __kernel_uid_t32 cuid; + __kernel_gid_t32 cgid; + __kernel_mode_t32 mode; + unsigned short seq; + unsigned short __pad1; + unsigned int __unused1; + unsigned int __unused2; +}; + struct semid_ds32 { struct ipc_perm32 sem_perm; /* permissions .. see ipc.h */ __kernel_time_t32 sem_otime; /* last semop time */ @@ -1522,6 +1543,23 @@ __kernel_ipc_pid_t32 msg_lrpid; }; +struct msqid64_ds32 { + struct ipc64_perm32 msg_perm; + __kernel_time_t32 msg_stime; + unsigned int __unused1; + __kernel_time_t32 msg_rtime; + unsigned int __unused2; + __kernel_time_t32 msg_ctime; + unsigned int __unused3; + unsigned int msg_cbytes; + unsigned int msg_qnum; + unsigned int msg_qbytes; + __kernel_pid_t32 msg_lspid; + __kernel_pid_t32 msg_lrpid; + unsigned int __unused4; + unsigned int __unused5; +}; + struct shmid_ds32 { struct ipc_perm32 shm_perm; int shm_segsz; @@ -1533,7 +1571,10 @@ unsigned short shm_nattch; }; -#define IPCOP_MASK(__x) (1UL << (__x)) +struct ipc_kludge32 { + u32 msgp; + s32 msgtyp; +}; static int do_sys32_semctl(int first, int second, int third, void *uptr) @@ -1600,21 +1641,23 @@ return err; } -static int do_sys32_msgsnd (int first, int second, int third, void *uptr) { - struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf) - + 4, GFP_USER); struct msgbuf32 *up = (struct msgbuf32 *)uptr; + struct msgbuf *p; mm_segment_t old_fs; int err; + if (second < 0) + return -EINVAL; + p = kmalloc (second + sizeof (struct msgbuf) + + 4, GFP_USER); if (!p) return -ENOMEM; err = get_user (p->mtype, &up->mtype); if (err) goto out; - err = __copy_from_user (p->mtext, &up->mtext, second); + err |= __copy_from_user (p->mtext, &up->mtext, second); if (err) goto out; old_fs = get_fs (); @@ -1623,6 +1666,7 @@ set_fs (old_fs); out: kfree (p); + return err; } @@ -1636,18 +1680,21 @@ int err; if (!version) { - struct ipc_kludge *uipck = (struct ipc_kludge *)uptr; - struct ipc_kludge ipck; + struct ipc_kludge32 *uipck = (struct ipc_kludge32 *)uptr; + struct ipc_kludge32 ipck; err = -EINVAL; if (!uptr) goto out; err = -EFAULT; - if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge))) + if (copy_from_user (&ipck, uipck, sizeof (struct ipc_kludge32))) goto out; - uptr = (void *)A(ipck.msgp); + uptr = (void *)AA(ipck.msgp); msgtyp = ipck.msgtyp; } + + if (second < 0) + return -EINVAL; err = -ENOMEM; p = kmalloc (second + sizeof (struct msgbuf) + 4, GFP_USER); if (!p) @@ -1672,13 +1719,12 @@ do_sys32_msgctl (int first, int second, void *uptr) { int err = -EINVAL, err2; - struct msqid_ds m; - struct msqid64_ds m64; - struct msqid_ds32 *up = (struct msqid_ds32 *)uptr; + struct msqid64_ds m; + struct msqid_ds32 *up32 = (struct msqid_ds32 *)uptr; + struct msqid64_ds32 *up64 = (struct msqid64_ds32 *)uptr; mm_segment_t old_fs; - switch (second) { - + switch (second & ~IPC_64) { case IPC_INFO: case IPC_RMID: case MSG_INFO: @@ -1686,15 +1732,30 @@ break; case IPC_SET: - err = get_user (m.msg_perm.uid, &up->msg_perm.uid); - err |= __get_user (m.msg_perm.gid, &up->msg_perm.gid); - err |= __get_user (m.msg_perm.mode, &up->msg_perm.mode); - err |= __get_user (m.msg_qbytes, &up->msg_qbytes); + if (second & IPC_64) { + if (!access_ok(VERIFY_READ, up64, sizeof(*up64))) { + err = -EFAULT; + break; + } + err = __get_user(m.msg_perm.uid, &up64->msg_perm.uid); + err |= __get_user(m.msg_perm.gid, &up64->msg_perm.gid); + err |= __get_user(m.msg_perm.mode, &up64->msg_perm.mode); + err |= __get_user(m.msg_qbytes, &up64->msg_qbytes); + } else { + if (!access_ok(VERIFY_READ, up32, sizeof(*up32))) { + err = -EFAULT; + break; + } + err = __get_user(m.msg_perm.uid, &up32->msg_perm.uid); + err |= __get_user(m.msg_perm.gid, &up32->msg_perm.gid); + err |= __get_user(m.msg_perm.mode, &up32->msg_perm.mode); + err |= __get_user(m.msg_qbytes, &up32->msg_qbytes); + } if (err) break; old_fs = get_fs (); set_fs (KERNEL_DS); - err = sys_msgctl (first, second, &m); + err = sys_msgctl (first, second, (struct msqid_ds *)&m); set_fs (old_fs); break; @@ -1702,27 +1763,54 @@ case MSG_STAT: old_fs = get_fs (); set_fs (KERNEL_DS); - err = sys_msgctl (first, second, (void *) &m64); + err = sys_msgctl (first, second, (struct msqid_ds *)&m); set_fs (old_fs); - err2 = put_user (m64.msg_perm.key, &up->msg_perm.key); - err2 |= __put_user(m64.msg_perm.uid, &up->msg_perm.uid); - err2 |= __put_user(m64.msg_perm.gid, &up->msg_perm.gid); - err2 |= __put_user(m64.msg_perm.cuid, &up->msg_perm.cuid); - err2 |= __put_user(m64.msg_perm.cgid, &up->msg_perm.cgid); - err2 |= __put_user(m64.msg_perm.mode, &up->msg_perm.mode); - err2 |= __put_user(m64.msg_perm.seq, &up->msg_perm.seq); - err2 |= __put_user(m64.msg_stime, &up->msg_stime); - err2 |= __put_user(m64.msg_rtime, &up->msg_rtime); - err2 |= __put_user(m64.msg_ctime, &up->msg_ctime); - err2 |= __put_user(m64.msg_cbytes, &up->msg_cbytes); - err2 |= __put_user(m64.msg_qnum, &up->msg_qnum); - err2 |= __put_user(m64.msg_qbytes, &up->msg_qbytes); - err2 |= __put_user(m64.msg_lspid, &up->msg_lspid); - err2 |= __put_user(m64.msg_lrpid, &up->msg_lrpid); - if (err2) - err = -EFAULT; + if (second & IPC_64) { + if (!access_ok(VERIFY_WRITE, up64, sizeof(*up64))) { + err = -EFAULT; + break; + } + err2 = __put_user(m.msg_perm.key, &up64->msg_perm.key); + err2 |= __put_user(m.msg_perm.uid, &up64->msg_perm.uid); + err2 |= __put_user(m.msg_perm.gid, &up64->msg_perm.gid); + err2 |= __put_user(m.msg_perm.cuid, &up64->msg_perm.cuid); + err2 |= __put_user(m.msg_perm.cgid, &up64->msg_perm.cgid); + err2 |= __put_user(m.msg_perm.mode, &up64->msg_perm.mode); + err2 |= __put_user(m.msg_perm.seq, &up64->msg_perm.seq); + err2 |= __put_user(m.msg_stime, &up64->msg_stime); + err2 |= __put_user(m.msg_rtime, &up64->msg_rtime); + err2 |= __put_user(m.msg_ctime, &up64->msg_ctime); + err2 |= __put_user(m.msg_cbytes, &up64->msg_cbytes); + err2 |= __put_user(m.msg_qnum, &up64->msg_qnum); + err2 |= __put_user(m.msg_qbytes, &up64->msg_qbytes); + err2 |= __put_user(m.msg_lspid, &up64->msg_lspid); + err2 |= __put_user(m.msg_lrpid, &up64->msg_lrpid); + if (err2) + err = -EFAULT; + } else { + if (!access_ok(VERIFY_WRITE, up32, sizeof(*up32))) { + err = -EFAULT; + break; + } + err2 = __put_user(m.msg_perm.key, &up32->msg_perm.key); + err2 |= __put_user(m.msg_perm.uid, &up32->msg_perm.uid); + err2 |= __put_user(m.msg_perm.gid, &up32->msg_perm.gid); + err2 |= __put_user(m.msg_perm.cuid, &up32->msg_perm.cuid); + err2 |= __put_user(m.msg_perm.cgid, &up32->msg_perm.cgid); + err2 |= __put_user(m.msg_perm.mode, &up32->msg_perm.mode); + err2 |= __put_user(m.msg_perm.seq, &up32->msg_perm.seq); + err2 |= __put_user(m.msg_stime, &up32->msg_stime); + err2 |= __put_user(m.msg_rtime, &up32->msg_rtime); + err2 |= __put_user(m.msg_ctime, &up32->msg_ctime); + err2 |= __put_user(m.msg_cbytes, &up32->msg_cbytes); + err2 |= __put_user(m.msg_qnum, &up32->msg_qnum); + err2 |= __put_user(m.msg_qbytes, &up32->msg_qbytes); + err2 |= __put_user(m.msg_lspid, &up32->msg_lspid); + err2 |= __put_user(m.msg_lrpid, &up32->msg_lrpid); + if (err2) + err = -EFAULT; + } break; - } return err; @@ -1845,7 +1933,7 @@ case SEMOP: /* struct sembuf is the same on 32 and 64bit :)) */ - err = sys_semop (first, (struct sembuf *)A(ptr), + err = sys_semop (first, (struct sembuf *)AA(ptr), second); break; case SEMGET: @@ -1853,27 +1941,27 @@ break; case SEMCTL: err = do_sys32_semctl (first, second, third, - (void *)A(ptr)); + (void *)AA(ptr)); break; case MSGSND: err = do_sys32_msgsnd (first, second, third, - (void *)A(ptr)); + (void *)AA(ptr)); break; case MSGRCV: err = do_sys32_msgrcv (first, second, fifth, third, - version, (void *)A(ptr)); + version, (void *)AA(ptr)); break; case MSGGET: err = sys_msgget ((key_t) first, second); break; case MSGCTL: - err = do_sys32_msgctl (first, second, (void *)A(ptr)); + err = do_sys32_msgctl (first, second, (void *)AA(ptr)); break; case SHMAT: err = do_sys32_shmat (first, second, third, - version, (void *)A(ptr)); + version, (void *)AA(ptr)); break; case SHMDT: err = sys_shmdt ((char *)A(ptr)); @@ -1882,7 +1970,7 @@ err = sys_shmget (first, second, third); break; case SHMCTL: - err = do_sys32_shmctl (first, second, (void *)A(ptr)); + err = do_sys32_shmctl (first, second, (void *)AA(ptr)); break; default: err = -EINVAL; ^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2002-10-10 11:41 UTC | newest] Thread overview: 17+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2002-10-10 11:26 64-bit kernel patch Carsten Langgaard 2002-10-10 11:41 ` Ralf Baechle -- strict thread matches above, loose matches on Subject: below -- 2002-10-02 13:22 Carsten Langgaard 2002-10-02 13:40 ` Maciej W. Rozycki 2002-10-02 13:44 ` Carsten Langgaard 2002-10-02 13:46 ` Ralf Baechle 2002-10-02 14:02 ` Carsten Langgaard 2002-10-02 14:06 ` Ralf Baechle 2002-10-02 14:05 ` Carsten Langgaard 2002-10-02 14:09 ` Ralf Baechle 2002-10-02 14:33 ` Carsten Langgaard 2002-10-03 6:49 ` Carsten Langgaard 2002-10-03 11:39 ` Maciej W. Rozycki 2002-10-04 6:39 ` Carsten Langgaard 2002-10-04 12:43 ` Maciej W. Rozycki 2002-09-09 12:16 Carsten Langgaard 2002-09-09 13:03 ` Carsten Langgaard
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox