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

Commit a0727e8c authored by Will Drewry's avatar Will Drewry Committed by James Morris
Browse files

signal, x86: add SIGSYS info and make it synchronous.



This change enables SIGSYS, defines _sigfields._sigsys, and adds
x86 (compat) arch support.  _sigsys defines fields which allow
a signal handler to receive the triggering system call number,
the relevant AUDIT_ARCH_* value for that number, and the address
of the callsite.

SIGSYS is added to the SYNCHRONOUS_MASK because it is desirable for it
to have setup_frame() called for it. The goal is to ensure that
ucontext_t reflects the machine state from the time-of-syscall and not
from another signal handler.

The first consumer of SIGSYS would be seccomp filter.  In particular,
a filter program could specify a new return value, SECCOMP_RET_TRAP,
which would result in the system call being denied and the calling
thread signaled.  This also means that implementing arch-specific
support can be dependent upon HAVE_ARCH_SECCOMP_FILTER.

Suggested-by: default avatarH. Peter Anvin <hpa@zytor.com>
Signed-off-by: default avatarWill Drewry <wad@chromium.org>
Acked-by: default avatarSerge Hallyn <serge.hallyn@canonical.com>
Reviewed-by: default avatarH. Peter Anvin <hpa@zytor.com>
Acked-by: default avatarEric Paris <eparis@redhat.com>

v18: - added acked by, rebase
v17: - rebase and reviewed-by addition
v14: - rebase/nochanges
v13: - rebase on to 88ebdda6
v12: - reworded changelog (oleg@redhat.com)
v11: - fix dropped words in the change description
     - added fallback copy_siginfo support.
     - added __ARCH_SIGSYS define to allow stepped arch support.
v10: - first version based on suggestion
Signed-off-by: default avatarJames Morris <james.l.morris@oracle.com>
parent acf3b2c7
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -67,6 +67,10 @@ int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
			switch (from->si_code >> 16) {
			case __SI_FAULT >> 16:
				break;
			case __SI_SYS >> 16:
				put_user_ex(from->si_syscall, &to->si_syscall);
				put_user_ex(from->si_arch, &to->si_arch);
				break;
			case __SI_CHLD >> 16:
				if (ia32) {
					put_user_ex(from->si_utime, &to->si_utime);
+6 −0
Original line number Diff line number Diff line
@@ -144,6 +144,12 @@ typedef struct compat_siginfo {
			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
			int _fd;
		} _sigpoll;

		struct {
			unsigned int _call_addr; /* calling insn */
			int _syscall;	/* triggering system call number */
			unsigned int _arch;	/* AUDIT_ARCH_* of syscall */
		} _sigsys;
	} _sifields;
} compat_siginfo_t;

+22 −0
Original line number Diff line number Diff line
@@ -90,9 +90,18 @@ typedef struct siginfo {
			__ARCH_SI_BAND_T _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
			int _fd;
		} _sigpoll;

		/* SIGSYS */
		struct {
			void __user *_call_addr; /* calling insn */
			int _syscall;	/* triggering system call number */
			unsigned int _arch;	/* AUDIT_ARCH_* of syscall */
		} _sigsys;
	} _sifields;
} siginfo_t;

/* If the arch shares siginfo, then it has SIGSYS. */
#define __ARCH_SIGSYS
#endif

/*
@@ -116,6 +125,11 @@ typedef struct siginfo {
#define si_addr_lsb	_sifields._sigfault._addr_lsb
#define si_band		_sifields._sigpoll._band
#define si_fd		_sifields._sigpoll._fd
#ifdef __ARCH_SIGSYS
#define si_call_addr	_sifields._sigsys._call_addr
#define si_syscall	_sifields._sigsys._syscall
#define si_arch		_sifields._sigsys._arch
#endif

#ifdef __KERNEL__
#define __SI_MASK	0xffff0000u
@@ -126,6 +140,7 @@ typedef struct siginfo {
#define __SI_CHLD	(4 << 16)
#define __SI_RT		(5 << 16)
#define __SI_MESGQ	(6 << 16)
#define __SI_SYS	(7 << 16)
#define __SI_CODE(T,N)	((T) | ((N) & 0xffff))
#else
#define __SI_KILL	0
@@ -135,6 +150,7 @@ typedef struct siginfo {
#define __SI_CHLD	0
#define __SI_RT		0
#define __SI_MESGQ	0
#define __SI_SYS	0
#define __SI_CODE(T,N)	(N)
#endif

@@ -231,6 +247,12 @@ typedef struct siginfo {
#define POLL_HUP	(__SI_POLL|6)	/* device disconnected */
#define NSIGPOLL	6

/*
 * SIGSYS si_codes
 */
#define SYS_SECCOMP		(__SI_SYS|1)	/* seccomp triggered */
#define NSIGSYS	1

/*
 * sigevent definitions
 * 
+8 −1
Original line number Diff line number Diff line
@@ -160,7 +160,7 @@ void recalc_sigpending(void)

#define SYNCHRONOUS_MASK \
	(sigmask(SIGSEGV) | sigmask(SIGBUS) | sigmask(SIGILL) | \
	 sigmask(SIGTRAP) | sigmask(SIGFPE))
	 sigmask(SIGTRAP) | sigmask(SIGFPE) | sigmask(SIGSYS))

int next_signal(struct sigpending *pending, sigset_t *mask)
{
@@ -2706,6 +2706,13 @@ int copy_siginfo_to_user(siginfo_t __user *to, siginfo_t *from)
		err |= __put_user(from->si_uid, &to->si_uid);
		err |= __put_user(from->si_ptr, &to->si_ptr);
		break;
#ifdef __ARCH_SIGSYS
	case __SI_SYS:
		err |= __put_user(from->si_call_addr, &to->si_call_addr);
		err |= __put_user(from->si_syscall, &to->si_syscall);
		err |= __put_user(from->si_arch, &to->si_arch);
		break;
#endif
	default: /* this is just in case for now ... */
		err |= __put_user(from->si_pid, &to->si_pid);
		err |= __put_user(from->si_uid, &to->si_uid);