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

Commit 8112c4f1 authored by Kees Cook's avatar Kees Cook
Browse files

seccomp: remove 2-phase API



Since nothing is using the 2-phase API, and it adds more complexity than
benefit, remove it.

Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Cc: Andy Lutomirski <luto@kernel.org>
parent c87a8517
Loading
Loading
Loading
Loading
+0 −6
Original line number Diff line number Diff line
@@ -35,12 +35,6 @@ static inline int secure_computing(const struct seccomp_data *sd)
		return  __secure_computing(sd);
	return 0;
}

#define SECCOMP_PHASE1_OK	0
#define SECCOMP_PHASE1_SKIP	1

extern u32 seccomp_phase1(struct seccomp_data *sd);
int seccomp_phase2(u32 phase1_result);
#else
extern void secure_computing_strict(int this_syscall);
#endif
+41 −88
Original line number Diff line number Diff line
@@ -173,7 +173,7 @@ static int seccomp_check_filter(struct sock_filter *filter, unsigned int flen)
 *
 * Returns valid seccomp BPF response codes.
 */
static u32 seccomp_run_filters(struct seccomp_data *sd)
static u32 seccomp_run_filters(const struct seccomp_data *sd)
{
	struct seccomp_data sd_local;
	u32 ret = SECCOMP_RET_ALLOW;
@@ -554,20 +554,9 @@ void secure_computing_strict(int this_syscall)
		BUG();
}
#else
int __secure_computing(const struct seccomp_data *sd)
{
	u32 phase1_result = seccomp_phase1(sd);

	if (likely(phase1_result == SECCOMP_PHASE1_OK))
		return 0;
	else if (likely(phase1_result == SECCOMP_PHASE1_SKIP))
		return -1;
	else
		return seccomp_phase2(phase1_result);
}

#ifdef CONFIG_SECCOMP_FILTER
static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd)
static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd)
{
	u32 filter_ret, action;
	int data;
@@ -599,10 +588,33 @@ static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd)
		goto skip;

	case SECCOMP_RET_TRACE:
		return filter_ret;  /* Save the rest for phase 2. */
		/* ENOSYS these calls if there is no tracer attached. */
		if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) {
			syscall_set_return_value(current,
						 task_pt_regs(current),
						 -ENOSYS, 0);
			goto skip;
		}

		/* Allow the BPF to provide the event message */
		ptrace_event(PTRACE_EVENT_SECCOMP, data);
		/*
		 * The delivery of a fatal signal during event
		 * notification may silently skip tracer notification.
		 * Terminating the task now avoids executing a system
		 * call that may not be intended.
		 */
		if (fatal_signal_pending(current))
			do_exit(SIGSYS);
		/* Check if the tracer forced the syscall to be skipped. */
		this_syscall = syscall_get_nr(current, task_pt_regs(current));
		if (this_syscall < 0)
			goto skip;

		return 0;

	case SECCOMP_RET_ALLOW:
		return SECCOMP_PHASE1_OK;
		return 0;

	case SECCOMP_RET_KILL:
	default:
@@ -614,96 +626,37 @@ static u32 __seccomp_phase1_filter(int this_syscall, struct seccomp_data *sd)

skip:
	audit_seccomp(this_syscall, 0, action);
	return SECCOMP_PHASE1_SKIP;
	return -1;
}
#else
static int __seccomp_filter(int this_syscall, const struct seccomp_data *sd)
{
	BUG();
}
#endif

/**
 * seccomp_phase1() - run fast path seccomp checks on the current syscall
 * @arg sd: The seccomp_data or NULL
 *
 * This only reads pt_regs via the syscall_xyz helpers.  The only change
 * it will make to pt_regs is via syscall_set_return_value, and it will
 * only do that if it returns SECCOMP_PHASE1_SKIP.
 *
 * If sd is provided, it will not read pt_regs at all.
 *
 * It may also call do_exit or force a signal; these actions must be
 * safe.
 *
 * If it returns SECCOMP_PHASE1_OK, the syscall passes checks and should
 * be processed normally.
 *
 * If it returns SECCOMP_PHASE1_SKIP, then the syscall should not be
 * invoked.  In this case, seccomp_phase1 will have set the return value
 * using syscall_set_return_value.
 *
 * If it returns anything else, then the return value should be passed
 * to seccomp_phase2 from a context in which ptrace hooks are safe.
 */
u32 seccomp_phase1(struct seccomp_data *sd)
int __secure_computing(const struct seccomp_data *sd)
{
	int mode = current->seccomp.mode;
	int this_syscall = sd ? sd->nr :
		syscall_get_nr(current, task_pt_regs(current));
	int this_syscall;

	if (config_enabled(CONFIG_CHECKPOINT_RESTORE) &&
	    unlikely(current->ptrace & PT_SUSPEND_SECCOMP))
		return SECCOMP_PHASE1_OK;
		return 0;

	this_syscall = sd ? sd->nr :
		syscall_get_nr(current, task_pt_regs(current));

	switch (mode) {
	case SECCOMP_MODE_STRICT:
		__secure_computing_strict(this_syscall);  /* may call do_exit */
		return SECCOMP_PHASE1_OK;
#ifdef CONFIG_SECCOMP_FILTER
		return 0;
	case SECCOMP_MODE_FILTER:
		return __seccomp_phase1_filter(this_syscall, sd);
#endif
		return __seccomp_filter(this_syscall, sd);
	default:
		BUG();
	}
}

/**
 * seccomp_phase2() - finish slow path seccomp work for the current syscall
 * @phase1_result: The return value from seccomp_phase1()
 *
 * This must be called from a context in which ptrace hooks can be used.
 *
 * Returns 0 if the syscall should be processed or -1 to skip the syscall.
 */
int seccomp_phase2(u32 phase1_result)
{
	struct pt_regs *regs = task_pt_regs(current);
	u32 action = phase1_result & SECCOMP_RET_ACTION;
	int data = phase1_result & SECCOMP_RET_DATA;

	BUG_ON(action != SECCOMP_RET_TRACE);

	audit_seccomp(syscall_get_nr(current, regs), 0, action);

	/* Skip these calls if there is no tracer. */
	if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP)) {
		syscall_set_return_value(current, regs,
					 -ENOSYS, 0);
		return -1;
	}

	/* Allow the BPF to provide the event message */
	ptrace_event(PTRACE_EVENT_SECCOMP, data);
	/*
	 * The delivery of a fatal signal during event
	 * notification may silently skip tracer notification.
	 * Terminating the task now avoids executing a system
	 * call that may not be intended.
	 */
	if (fatal_signal_pending(current))
		do_exit(SIGSYS);
	if (syscall_get_nr(current, regs) < 0)
		return -1;  /* Explicit request to skip. */

	return 0;
}
#endif /* CONFIG_HAVE_ARCH_SECCOMP_FILTER */

long prctl_get_seccomp(void)