Linux MIPS Architecture development
 help / color / mirror / Atom feed
* 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 64-bit kernel patch 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

* 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(&current->mm->mmap_sem);
+	error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff);
+	up_write(&current->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 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: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 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-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 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

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-09-09 12:16 64-bit kernel patch Carsten Langgaard
2002-09-09 13:03 ` Carsten Langgaard
  -- 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-10-10 11:26 Carsten Langgaard
2002-10-10 11:41 ` Ralf Baechle

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox