All of lore.kernel.org
 help / color / mirror / Atom feed
* siginfo structure in 64-bit kernel
@ 2002-08-07  9:54 Carsten Langgaard
  2002-08-07 11:49 ` Maciej W. Rozycki
  0 siblings, 1 reply; 5+ messages in thread
From: Carsten Langgaard @ 2002-08-07  9:54 UTC (permalink / raw)
  To: Ralf Baechle, Maciej W. Rozycki, linux-mips

[-- Attachment #1: Type: text/plain, Size: 566 bytes --]

The siginfo structure is containing longs, which isn't consistent
between o32 and n64.
So we need a routine to convert siginfo from 64-bit to 32-bit, when we
are running a 64-bit kernel on o32 userland.
Please take a look at the patch below.

/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: siginfo.patch --]
[-- Type: text/plain, Size: 5683 bytes --]

Index: arch/mips64/kernel/signal32.c
===================================================================
RCS file: /cvs/linux/arch/mips64/kernel/signal32.c,v
retrieving revision 1.20.2.7
diff -u -r1.20.2.7 signal32.c
--- arch/mips64/kernel/signal32.c	2002/08/05 23:53:36	1.20.2.7
+++ arch/mips64/kernel/signal32.c	2002/08/07 08:52:00
@@ -360,13 +360,55 @@
 	sigset_t sf_mask;
 };
 
-struct rt_sigframe {
+struct rt_sigframe32 {
 	u32 rs_ass[4];			/* argument save space for o32 */
 	u32 rs_code[2];			/* signal trampoline */
-	struct siginfo rs_info;
+	struct siginfo32 rs_info;
 	struct ucontext rs_uc;
 };
 
+static int copy_siginfo_to_user32(siginfo_t32 *to, siginfo_t *from)
+{
+	int err;
+
+	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32)))
+		return -EFAULT;
+
+	/* If you change siginfo_t structure, please be sure
+	   this code is fixed accordingly.
+	   It should never copy any pad contained in the structure
+	   to avoid security leaks, but must copy the generic
+	   3 ints plus the relevant union member.
+	   This routine must convert siginfo from 64bit to 32bit as well
+	   at the same time.  */
+	err = __put_user(from->si_signo, &to->si_signo);
+	err |= __put_user(from->si_errno, &to->si_errno);
+	err |= __put_user((short)from->si_code, &to->si_code);
+	if (from->si_code < 0)
+		err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
+	else {
+		switch (from->si_code >> 16) {
+		case __SI_CHLD >> 16:
+			err |= __put_user(from->si_utime, &to->si_utime);
+			err |= __put_user(from->si_stime, &to->si_stime);
+			err |= __put_user(from->si_status, &to->si_status);
+		default:
+			err |= __put_user(from->si_pid, &to->si_pid);
+			err |= __put_user(from->si_uid, &to->si_uid);
+			break;
+		case __SI_FAULT >> 16:
+			err |= __put_user((long)from->si_addr, &to->si_addr);
+			break;
+		case __SI_POLL >> 16:
+			err |= __put_user(from->si_band, &to->si_band);
+			err |= __put_user(from->si_fd, &to->si_fd);
+			break;
+		/* case __SI_RT: This is not generated by the kernel as of now.  */
+		}
+	}
+	return err;
+}
+
 asmlinkage void sys32_sigreturn(abi64_no_regargs, struct pt_regs regs)
 {
 	struct sigframe *frame;
@@ -405,11 +447,11 @@
 
 asmlinkage void sys32_rt_sigreturn(abi64_no_regargs, struct pt_regs regs)
 {
-	struct rt_sigframe *frame;
+	struct rt_sigframe32 *frame;
 	sigset_t set;
 	stack_t st;
 
-	frame = (struct rt_sigframe *) regs.regs[29];
+	frame = (struct rt_sigframe32 *) regs.regs[29];
 	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 		goto badframe;
 	if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
@@ -588,7 +630,7 @@
 				  struct pt_regs *regs, int signr,
 				  sigset_t *set, siginfo_t *info)
 {
-	struct rt_sigframe *frame;
+	struct rt_sigframe32 *frame;
 	int err = 0;
 
 	frame = get_sigframe(ka, regs, sizeof(*frame));
@@ -613,8 +655,8 @@
 		flush_cache_sigtramp((unsigned long) frame->rs_code);
 	}
 
-	/* Create siginfo.  */
-	err |= __copy_to_user(&frame->rs_info, info, sizeof(*info));
+	/* Convert (siginfo_t -> siginfo_t32) and copy to user. */
+	err |= copy_siginfo_to_user32(&frame->rs_info,info);
 
 	/* Create the ucontext.  */
 	err |= __put_user(0, &frame->rs_uc.uc_flags);
@@ -639,7 +681,7 @@
 	 *   a2 = pointer to ucontext
 	 *
 	 * $25 and c0_epc point to the signal handler, $29 points to
-	 * the struct rt_sigframe.
+	 * the struct rt_sigframe32.
 	 */
 	regs->regs[ 4] = signr;
 	regs->regs[ 5] = (unsigned long) &frame->rs_info;
Index: include/asm-mips64/siginfo.h
===================================================================
RCS file: /cvs/linux/include/asm-mips64/siginfo.h,v
retrieving revision 1.6.2.2
diff -u -r1.6.2.2 siginfo.h
--- include/asm-mips64/siginfo.h	2002/08/05 23:53:39	1.6.2.2
+++ include/asm-mips64/siginfo.h	2002/08/07 08:52:16
@@ -18,11 +18,21 @@
 	void *sival_ptr;
 } sigval_t;
 
+#ifdef __KERNEL__
+
+typedef union sigval32 {
+	int sival_int;
+	u32 sival_ptr;
+} sigval_t32;
+
+#endif /* __KERNEL__ */
+
 /* This structure matches IRIX 32/n32 ABIs for binary compatibility but
    has Linux extensions.  */
 
 #define SI_MAX_SIZE	128
-#define SI_PAD_SIZE	((SI_MAX_SIZE/sizeof(int)) - 3)
+#define SI_PAD_SIZE	((SI_MAX_SIZE/sizeof(int)) - 4)
+#define SI_PAD_SIZE32	((SI_MAX_SIZE/sizeof(int)) - 3)
 
 typedef struct siginfo {
 	int si_signo;
@@ -81,6 +91,67 @@
 
 	} _sifields;
 } siginfo_t;
+
+#ifdef __KERNEL__
+
+typedef struct siginfo32 {
+	int si_signo;
+	int si_errno;
+	int si_code;
+	union {
+		int _pad[SI_PAD_SIZE32];
+
+		/* kill() */
+		struct {
+			__kernel_pid_t32 _pid;	/* sender's pid */
+			__kernel_uid_t32 _uid;	/* sender's uid */
+		} _kill;
+
+		/* SIGCHLD */
+		struct {
+			__kernel_pid_t32 _pid;	/* which child */
+			__kernel_uid_t32 _uid;	/* sender's uid */
+			__kernel_clock_t32 _utime;
+			int _status;		/* exit code */
+			__kernel_clock_t32 _stime;
+		} _sigchld;
+
+		/* IRIX SIGCHLD */
+		struct {
+			__kernel_pid_t32 _pid;	/* which child */
+			__kernel_clock_t32 _utime;
+			int _status;		/* exit code */
+			__kernel_clock_t32 _stime;
+		} _irix_sigchld;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+		struct {
+			u32 _addr; /* faulting insn/memory ref. */
+		} _sigfault;
+
+		/* SIGPOLL, SIGXFSZ (To do ...)  */
+		struct {
+			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+			int _fd;
+		} _sigpoll;
+
+		/* POSIX.1b timers */
+		struct {
+			unsigned int _timer1;
+			unsigned int _timer2;
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			__kernel_pid_t32 _pid;	/* sender's pid */
+			__kernel_uid_t32 _uid;	/* sender's uid */
+			sigval_t32 _sigval;
+		} _rt;
+
+	} _sifields;
+} siginfo_t32;
+
+#endif /* __KERNEL__ */
 
 /*
  * How these fields are to be accessed.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2002-08-09  8:37 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2002-08-07  9:54 siginfo structure in 64-bit kernel Carsten Langgaard
2002-08-07 11:49 ` Maciej W. Rozycki
2002-08-08 14:26   ` Maciej W. Rozycki
2002-08-08 20:02     ` Carsten Langgaard
2002-08-09  8:39       ` Maciej W. Rozycki

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.