patch-2.4.2 linux/arch/s390/kernel/signal.c

Next file: linux/arch/s390/kernel/smp.c
Previous file: linux/arch/s390/kernel/setup.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.1/linux/arch/s390/kernel/signal.c linux/arch/s390/kernel/signal.c
@@ -2,7 +2,7 @@
  *  arch/s390/kernel/signal.c
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) 1999,2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  *
  *    Based on Intel version
@@ -37,7 +37,7 @@
 #define SIGFRAME_COMMON \
 __u8     callee_used_stack[__SIGNAL_FRAMESIZE]; \
 struct sigcontext sc; \
-sigregs sregs; \
+_sigregs sregs; \
 __u8 retcode[S390_SYSCALL_SIZE];
 
 typedef struct 
@@ -54,6 +54,41 @@
 
 asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
 
+int copy_siginfo_to_user(siginfo_t *to, siginfo_t *from)
+{
+	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
+		return -EFAULT;
+	if (from->si_code < 0)
+		return __copy_to_user(to, from, sizeof(siginfo_t));
+	else {
+		int err;
+
+		/* 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.  */
+		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);
+		/* First 32bits of unions are always present.  */
+		err |= __put_user(from->si_pid, &to->si_pid);
+		switch (from->si_code >> 16) {
+		case __SI_FAULT >> 16:
+			break;
+		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_uid, &to->si_uid);
+			break;
+		/* case __SI_RT: This is not generated by the kernel as of now.  */
+		}
+		return err;
+	}
+}
+
 /*
  * Atomically swap in the new signal mask, and wait for a signal.
  */
@@ -71,7 +106,7 @@
 	regs->gprs[2] = -EINTR;
 
 	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule();
 		if (do_signal(regs, &saveset))
 			return -EINTR;
@@ -99,7 +134,7 @@
 	regs->gprs[2] = -EINTR;
 
 	while (1) {
-		current->state = TASK_INTERRUPTIBLE;
+		set_current_state(TASK_INTERRUPTIBLE);
 		schedule();
 		if (do_signal(regs, &saveset))
 			return -EINTR;
@@ -139,16 +174,15 @@
 }
 
 asmlinkage int
-sys_sigaltstack(const stack_t *uss, stack_t *uoss)
+sys_sigaltstack(const stack_t *uss, stack_t *uoss, struct pt_regs *regs)
 {
-	struct pt_regs *regs = (struct pt_regs *) &uss;
 	return do_sigaltstack(uss, uoss, regs->gprs[15]);
 }
 
 
 
 
-static int save_sigregs(struct pt_regs *regs,sigregs *sregs)
+static int save_sigregs(struct pt_regs *regs,_sigregs *sregs)
 {
 	int err;
 	s390_fp_regs fpregs;
@@ -163,7 +197,7 @@
 	
 }
 
-static int restore_sigregs(struct pt_regs *regs,sigregs *sregs)
+static int restore_sigregs(struct pt_regs *regs,_sigregs *sregs)
 {
 	int err;
 	s390_fp_regs fpregs;
@@ -185,13 +219,13 @@
 
 static int
 restore_sigcontext(struct sigcontext *sc, pt_regs *regs,
-		 sigregs *sregs,sigset_t *set)
+		 _sigregs *sregs,sigset_t *set)
 {
 	unsigned int err;
 
 	err=restore_sigregs(regs,sregs);
 	if(!err)
-		err=__copy_from_user(&set->sig,&sc->oldmask,SIGMASK_COPY_SIZE);
+		err=__copy_from_user(&set->sig,&sc->oldmask,_SIGMASK_COPY_SIZE);
 		return(err);
 }
 
@@ -227,15 +261,12 @@
 asmlinkage int sys_rt_sigreturn(struct pt_regs *regs)
 {
 	rt_sigframe *frame = (rt_sigframe *)regs->gprs[15];
-	stack_t st;
 
 	if (sigreturn_common(regs,sizeof(rt_sigframe)))
 		goto badframe;
-	if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
-		goto badframe;
 	/* It is more difficult to avoid calling this function than to
 	   call it and ignore errors.  */
-	do_sigaltstack(&st, NULL, regs->gprs[15]);
+	do_sigaltstack(&frame->uc.uc_stack, NULL, regs->gprs[15]);
 	return regs->gprs[2];
 
 badframe:
@@ -290,7 +321,7 @@
 		err=__put_user(&frame->sregs,&frame->sc.sregs);
 	if(!err)
 
-		err=__copy_to_user(&frame->sc.oldmask,&set->sig,SIGMASK_COPY_SIZE);
+		err=__copy_to_user(&frame->sc.oldmask,&set->sig,_SIGMASK_COPY_SIZE);
 	if(!err)
 	{
 		regs->gprs[2]=(current->exec_domain
@@ -316,14 +347,17 @@
 static void setup_frame(int sig, struct k_sigaction *ka,
 			sigset_t *set, struct pt_regs * regs)
 {
+	sigframe *frame;
 
-	if(!setup_frame_common(sig,ka,set,regs,sizeof(sigframe),
-		    (S390_SYSCALL_OPCODE|__NR_sigreturn)))
+	if((frame=setup_frame_common(sig,ka,set,regs,sizeof(sigframe),
+		    (S390_SYSCALL_OPCODE|__NR_sigreturn)))==0)
 		goto give_sigsegv;
 #if DEBUG_SIG
 	printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
 		current->comm, current->pid, frame, regs->eip, frame->pretcode);
 #endif
+	/* Martin wants this for pthreads */
+	regs->gprs[3] = (addr_t)&frame->sc;
 	return;
 
 give_sigsegv:
@@ -343,7 +377,7 @@
 		    (S390_SYSCALL_OPCODE|__NR_rt_sigreturn)))==0)
 		goto give_sigsegv;
 	
-	err = __copy_to_user(&frame->info, info, sizeof(*info));
+	err = copy_siginfo_to_user(&frame->info, info);
 
 	/* Create the ucontext.  */
 	err |= __put_user(0, &frame->uc.uc_flags);
@@ -352,8 +386,9 @@
 	err |= __put_user(sas_ss_flags(orig_sp),
 			  &frame->uc.uc_stack.ss_flags);
 	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
-	regs->gprs[3] = (u32)&frame->info;
-	regs->gprs[4] = (u32)&frame->uc;
+	err |= __put_user(&frame->sc,&frame->uc.sc);
+	regs->gprs[3] = (addr_t)&frame->info;
+	regs->gprs[4] = (addr_t)&frame->uc;
 
 	if (err)
 		goto give_sigsegv;
@@ -452,10 +487,10 @@
 		if (!signr)
 			break;
 
-		if ((current->flags & PF_PTRACED) && signr != SIGKILL) {
+		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
 			/* Let the debugger run.  */
 			current->exit_code = signr;
-			current->state = TASK_STOPPED;
+			set_current_state(TASK_STOPPED);
 			notify_parent(current, SIGCHLD);
 			schedule();
 
@@ -511,7 +546,7 @@
 				/* FALLTHRU */
 
 			case SIGSTOP:
-				current->state = TASK_STOPPED;
+				set_current_state(TASK_STOPPED);
 				current->exit_code = signr;
 				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
 					notify_parent(current, SIGCHLD);
@@ -540,7 +575,7 @@
 	}
 
 	/* Did we come from a system call? */
-	if ( regs->trap == 0x20 /* System Call! */ ) {
+	if ( regs->trap == __LC_SVC_OLD_PSW /* System Call! */ ) {
 		/* Restart the system call - no handlers present */
 		if (regs->gprs[2] == -ERESTARTNOHAND ||
 		    regs->gprs[2] == -ERESTARTSYS ||

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)