From: Ralf Baechle <ralf@oss.sgi.com>
To: Carsten Langgaard <carstenl@mips.com>
Cc: "Maciej W. Rozycki" <macro@ds2.pg.gda.pl>, linux-mips@oss.sgi.com
Subject: Re: IPC syscall fixup (o32 conversion layer)
Date: Tue, 13 Aug 2002 05:23:24 +0200 [thread overview]
Message-ID: <20020813052324.A22438@linux-mips.org> (raw)
In-Reply-To: <3D5131C7.17F9E00@mips.com>; from carstenl@mips.com on Wed, Aug 07, 2002 at 04:42:15PM +0200
Carsten,
On Wed, Aug 07, 2002 at 04:42:15PM +0200, Carsten Langgaard wrote:
> Here is a patch that fixes the ipc syscalls in the o32
> wrapper/conversion routines.
> Needed when running a 64-bit kernel on an o32 userland.
before I finally apply this one, can you do me a favour and check your
code is still working correctly even after I applied yesterdays fix
which changes struct msqid64_id to eleminate the mismatch of the kernel
and libc definitions?
Thanks,
Ralf
> 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/08/07 14:28:03
> @@ -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,9 +1571,25 @@
> unsigned short shm_nattch;
> };
>
> +struct ipc_kludge32 {
> + u32 msgp;
> + s32 msgtyp;
> +};
> +
> #define IPCOP_MASK(__x) (1UL << (__x))
>
> static int
> +ipc_parse_version32(int *cmd)
> +{
> + if (*cmd & IPC_64) {
> + *cmd ^= IPC_64;
> + return IPC_64;
> + } else {
> + return IPC_OLD;
> + }
> +}
> +
> +static int
> do_sys32_semctl(int first, int second, int third, void *uptr)
> {
> union semun fourth;
> @@ -1603,12 +1657,15 @@
> 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);
> @@ -1636,18 +1693,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)
> @@ -1673,9 +1733,10 @@
> {
> int err = -EINVAL, err2;
> struct msqid_ds m;
> - struct msqid64_ds m64;
> - struct msqid_ds32 *up = (struct msqid_ds32 *)uptr;
> + struct msqid_ds32 *up32 = (struct msqid_ds32 *)uptr;
> + struct msqid64_ds32 *up64 = (struct msqid64_ds32 *)uptr;
> mm_segment_t old_fs;
> + int version = ipc_parse_version32(&second);
>
> switch (second) {
>
> @@ -1686,10 +1747,25 @@
> 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 (version == 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 ();
> @@ -1702,27 +1778,54 @@
> case MSG_STAT:
> old_fs = get_fs ();
> set_fs (KERNEL_DS);
> - err = sys_msgctl (first, second, (void *) &m64);
> + err = sys_msgctl (first, second, &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 (version == 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 +1948,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,36 +1956,36 @@
> 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));
> + err = sys_shmdt ((char *)AA(ptr));
> break;
> case SHMGET:
> 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;
next prev parent reply other threads:[~2002-08-13 3:43 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-08-07 14:42 IPC syscall fixup (o32 conversion layer) Carsten Langgaard
2002-08-07 14:58 ` Maciej W. Rozycki
2002-08-07 15:13 ` Ralf Baechle
2002-08-07 15:24 ` Maciej W. Rozycki
2002-08-08 6:57 ` Carsten Langgaard
2002-08-13 3:23 ` Ralf Baechle [this message]
2002-08-19 13:49 ` Carsten Langgaard
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20020813052324.A22438@linux-mips.org \
--to=ralf@oss.sgi.com \
--cc=carstenl@mips.com \
--cc=linux-mips@oss.sgi.com \
--cc=macro@ds2.pg.gda.pl \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox