Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 212a36a1 authored by Eric W. Biederman's avatar Eric W. Biederman
Browse files

signal: Unify and correct copy_siginfo_from_user32



The function copy_siginfo_from_user32 is used for two things, in ptrace
since the dawn of siginfo for arbirarily modifying a signal that
user space sees, and in sigqueueinfo to send a signal with arbirary
siginfo data.

Create a single copy of copy_siginfo_from_user32 that all architectures
share, and teach it to handle all of the cases in the siginfo union.

In the generic version of copy_siginfo_from_user32 ensure that all
of the fields in siginfo are initialized so that the siginfo structure
can be safely copied to userspace if necessary.

When copying the embedded sigval union copy the si_int member.  That
ensures the 32bit values passes through the kernel unchanged.

Signed-off-by: default avatar"Eric W. Biederman" <ebiederm@xmission.com>
parent 56b81456
Loading
Loading
Loading
Loading
+0 −10
Original line number Diff line number Diff line
@@ -195,16 +195,6 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
	return err;
}

int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
{
	if (copy_from_user(to, from, __ARCH_SI_PREAMBLE_SIZE) ||
	    copy_from_user(to->_sifields._pad,
			   from->_sifields._pad, SI_PAD_SIZE))
		return -EFAULT;

	return 0;
}

/*
 * VFP save/restore code.
 *
+0 −10
Original line number Diff line number Diff line
@@ -133,13 +133,3 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, const siginfo_t *from)
	}
	return err;
}

int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
{
	if (copy_from_user(to, from, 3*sizeof(int)) ||
	    copy_from_user(to->_sifields._pad,
			   from->_sifields._pad, SI_PAD_SIZE32))
		return -EFAULT;

	return 0;
}
+0 −44
Original line number Diff line number Diff line
@@ -261,50 +261,6 @@ setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __
	return err;
}

int
copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
{
	compat_uptr_t addr;
	int err;

	if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
		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);

	if (to->si_code < 0)
		err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
	else {
		switch (siginfo_layout(to->si_signo, to->si_code)) {
		      case SIL_CHLD:
			err |= __get_user(to->si_utime, &from->si_utime);
			err |= __get_user(to->si_stime, &from->si_stime);
			err |= __get_user(to->si_status, &from->si_status);
		      default:
		      case SIL_KILL:
			err |= __get_user(to->si_pid, &from->si_pid);
			err |= __get_user(to->si_uid, &from->si_uid);
			break;
		      case SIL_FAULT:
			err |= __get_user(addr, &from->si_addr);
			to->si_addr = compat_ptr(addr);
			break;
		      case SIL_POLL:
			err |= __get_user(to->si_band, &from->si_band);
			err |= __get_user(to->si_fd, &from->si_fd);
			break;
		      case SIL_RT:
			err |= __get_user(to->si_pid, &from->si_pid);
			err |= __get_user(to->si_uid, &from->si_uid);
			err |= __get_user(to->si_int, &from->si_int);
			break;
		}
	}
	return err;
}

int
copy_siginfo_to_user32 (compat_siginfo_t __user *to, const siginfo_t *from)
{
+0 −1
Original line number Diff line number Diff line
@@ -35,7 +35,6 @@ struct compat_ucontext {
/* ELF32 signal handling */

int copy_siginfo_to_user32 (compat_siginfo_t __user *to, const siginfo_t *from);
int copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from);

/* In a deft move of uber-hackery, we decide to carry the top half of all
 * 64-bit registers in a non-portable, non-ABI, hidden structure.
+0 −9
Original line number Diff line number Diff line
@@ -933,15 +933,6 @@ int copy_siginfo_to_user32(struct compat_siginfo __user *d, const siginfo_t *s)

#define copy_siginfo_to_user	copy_siginfo_to_user32

int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
{
	if (copy_from_user(to, from, 3*sizeof(int)) ||
	    copy_from_user(to->_sifields._pad,
			   from->_sifields._pad, SI_PAD_SIZE32))
		return -EFAULT;

	return 0;
}
#endif /* CONFIG_PPC64 */

/*
Loading