Skip to contentSkip to conversation

more fixes for Opteron ia32 siginfo interface

PATCH In review Joe Korty 2 participants 2 messages Jan 6, 2004 – Jan 7, 2004

lore
Share & tools
lore

Joe Korty

author
#0 lore raw

PATCH 1/1 more fixes for Opteron ia32 siginfo interface

Andi and Andrew,

This patch should fix all the remaining Opteron ia32 siginfo_t issues in 2.6.0. It has been only lightly tested: posix timer tests, a small sigqueue(2) test that I wrote, and part of ltp, all compiled in ia32 mode.

Patch is against 2.6.0 as 2.6.1-rc1 does not compile under Opteron.

ChangeLog:
o Base is 2.6.0 with Andi Kleen's x86_64-2.6.0-1.bz2 patch.
o import Andrew Morton's 2.6.1-rc1 ia32_copy_siginfo_to_user changes.
o add final missing bits to ia32_copy_siginfo_to_user.
o insert missing timer union into siginfo_t32.
o remove siginfo64to32, use ia32_copy_siginfo_to_user instead.
o rewrite siginfo32to64 as ia32_copy_siginfo_from_user, simplify.
o fix possible data leak in sys32_rt_sigtimedwait.

Pick and choose whatever you like from this.
Regards,
Joe

 arch/x86_64/ia32/ia32_signal.c |   49 ++++++++++++++-------
 arch/x86_64/ia32/sys_ia32.c    |   95 +++--------------------------------------
 include/asm-x86_64/ia32.h      |   10 +++-
 3 files changed, 51 insertions(+), 103 deletions(-)
arch/x86_64/ia32/ia32_signal.c +34 -15
diff -ura base/arch/x86_64/ia32/ia32_signal.c new/arch/x86_64/ia32/ia32_signal.c
@@ -44,10 +44,10 @@
 asmlinkage int do_signal(struct pt_regs *regs, sigset_t *oldset);
 void signal_fault(struct pt_regs *regs, void *frame, char *where);
 
-static int ia32_copy_siginfo_to_user(siginfo_t32 *to, siginfo_t *from)
+int ia32_copy_siginfo_to_user(siginfo_t32 __user *to, siginfo_t *from)
 {
 	int err;
-	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
+	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t32)))
 		return -EFAULT;
 
 	/* If you change siginfo_t structure, please make sure that
@@ -55,20 +55,18 @@
 		   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.  */
-	
+
+	err = __put_user(from->si_signo, &to->si_signo);
+	err |= __put_user(from->si_errno, &to->si_errno);
+	err |= __put_user(from->si_code, &to->si_code);
+
 	if (from->si_code < 0) {
-		err = __put_user(from->si_signo, &to->si_signo);
-		err |= __put_user(from->si_errno, &to->si_errno); 
-		err |= __put_user(from->si_code, &to->si_code); 
-		err |= __put_user(from->_sifields._rt._pid, &to->_sifields._rt._pid); 
-		err |= __put_user(from->_sifields._rt._uid, &to->_sifields._rt._uid); 
-		err |= __put_user((u32)(u64)from->_sifields._rt._sigval.sival_ptr, 
-				  &to->_sifields._rt._sigval.sival_ptr); 
+		err |= __put_user(from->si_pid, &to->si_pid);
+		err |= __put_user(from->si_uid, &to->si_uid);
+		err |= __put_user((u32)(u64)from->si_ptr, &to->si_ptr);
 	} else {
-		err = __put_user(from->si_signo, &to->si_signo);
-		err |= __put_user(from->si_errno, &to->si_errno);
-		err |= __put_user(from->si_code, &to->si_code);
-		/* First 32bits of unions are always present.  */
+		/* First 32bits of unions are always present:
+		 * si_pid === si_band === si_tid === si_addr(LS half) */
 		err |= __put_user(from->si_pid, &to->si_pid);
 		switch (from->si_code >> 16) {
 		case __SI_FAULT >> 16:
@@ -78,18 +76,39 @@
 			err |= __put_user(from->si_stime, &to->si_stime);
 			err |= __put_user(from->si_status, &to->si_status);
 		default:
+		case __SI_KILL >> 16:
 			err |= __put_user(from->si_uid, &to->si_uid);
 			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_TIMER >> 16:
+			err |= __put_user(from->si_overrun, &to->si_overrun); 
+			err |= __put_user((u32)(u64)from->si_ptr, &to->si_ptr);
+			break;
 		/* case __SI_RT: This is not generated by the kernel as of now.  */
 		}
 	}
 	return err;
 }
 
+int ia32_copy_siginfo_from_user(siginfo_t *to, siginfo_t32 __user *from)
+{
+	int err;
+	if (!access_ok (VERIFY_READ, from, sizeof(siginfo_t32)))
+		return -EFAULT;
+
+	err = __get_user(to->si_signo, &from->si_signo);
+	err |= __get_user(to->si_errno, &from->si_errno);
+	err |= __get_user(to->si_code, &from->si_code);
+
+	err |= __get_user(to->si_pid, &from->si_pid);
+	err |= __get_user(to->si_uid, &from->si_uid);
+	err |= __get_user((u32)(u64)to->si_ptr, &from->si_ptr);
+
+	return err;
+}
+
 asmlinkage long
 sys32_sigsuspend(int history0, int history1, old_sigset_t mask, struct pt_regs regs)
 {
arch/x86_64/ia32/sys_ia32.c +9 -86

127 lines not on this page · raw message

include/asm-x86_64/ia32.h +8 -2
diff -ura base/include/asm-x86_64/ia32.h new/include/asm-x86_64/ia32.h
@@ -100,8 +100,11 @@
 
 		/* POSIX.1b timers */
 		struct {
-			unsigned int _timer1;
-			unsigned int _timer2;
+			int _tid;		/* timer id */
+			int _overrun;		/* overrun count */
+			sigval_t32 _sigval;	/* same as below */
+			int _sys_private;	/* not to be passed to user */
+			int _overrun_incr;	/* amount to add to overrun */
 		} _timer;
 
 		/* POSIX.1b signals */
@@ -164,9 +167,12 @@
 
 #ifdef __KERNEL__
 struct user_desc;
+struct siginfo_t;
 int do_get_thread_area(struct thread_struct *t, struct user_desc *u_info);
 int do_set_thread_area(struct thread_struct *t, struct user_desc *u_info);
 int ia32_child_tls(struct task_struct *p, struct pt_regs *childregs);
+int ia32_copy_siginfo_from_user(siginfo_t *to, siginfo_t32 __user *from);
+int ia32_copy_siginfo_to_user(siginfo_t32 __user *to, siginfo_t *from);
 #endif
 
 #endif /* !CONFIG_IA32_SUPPORT */
#1 lore raw
Quoted 6 lines · On Tue, 6 Jan 2004 11:28:18 -0500 Joe Korty <[email protected]> wrote:

Andi and Andrew,

This patch should fix all the remaining Opteron ia32 siginfo_t issues in 2.6.0. It has been only lightly tested: posix timer tests, a small sigqueue(2) test that I wrote, and part of ltp, all compiled in ia32 mode.

I applied the patch. Some hunks in ia32_signal.c rejected, but I merged them by hand (and fixed the indentation in the comments)

Thanks,

-Andi