Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris: "Highlights: - TPM core and driver updates/fixes - IPv6 security labeling (CALIPSO) - Lots of Apparmor fixes - Seccomp: remove 2-phase API, close hole where ptrace can change syscall #" * 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (156 commits) apparmor: fix SECURITY_APPARMOR_HASH_DEFAULT parameter handling tpm: Add TPM 2.0 support to the Nuvoton i2c driver (NPCT6xx family) tpm: Factor out common startup code tpm: use devm_add_action_or_reset tpm2_i2c_nuvoton: add irq validity check tpm: read burstcount from TPM_STS in one 32-bit transaction tpm: fix byte-order for the value read by tpm2_get_tpm_pt tpm_tis_core: convert max timeouts from msec to jiffies apparmor: fix arg_size computation for when setprocattr is null terminated apparmor: fix oops, validate buffer size in apparmor_setprocattr() apparmor: do not expose kernel stack apparmor: fix module parameters can be changed after policy is locked apparmor: fix oops in profile_unpack() when policy_db is not present apparmor: don't check for vmalloc_addr if kvzalloc() failed apparmor: add missing id bounds check on dfa verification apparmor: allow SYS_CAP_RESOURCE to be sufficient to prlimit another task apparmor: use list_next_entry instead of list_entry_next apparmor: fix refcount race when finding a child profile apparmor: fix ref count leak when profile sha1 hash is read apparmor: check that xindex is in trans_table bounds ...
This commit is contained in:
@@ -64,22 +64,16 @@ static void do_audit_syscall_entry(struct pt_regs *regs, u32 arch)
|
||||
}
|
||||
|
||||
/*
|
||||
* We can return 0 to resume the syscall or anything else to go to phase
|
||||
* 2. If we resume the syscall, we need to put something appropriate in
|
||||
* regs->orig_ax.
|
||||
*
|
||||
* NB: We don't have full pt_regs here, but regs->orig_ax and regs->ax
|
||||
* are fully functional.
|
||||
*
|
||||
* For phase 2's benefit, our return value is:
|
||||
* 0: resume the syscall
|
||||
* 1: go to phase 2; no seccomp phase 2 needed
|
||||
* anything else: go to phase 2; pass return value to seccomp
|
||||
* Returns the syscall nr to run (which should match regs->orig_ax) or -1
|
||||
* to skip the syscall.
|
||||
*/
|
||||
unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch)
|
||||
static long syscall_trace_enter(struct pt_regs *regs)
|
||||
{
|
||||
u32 arch = in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
|
||||
|
||||
struct thread_info *ti = pt_regs_to_thread_info(regs);
|
||||
unsigned long ret = 0;
|
||||
bool emulated = false;
|
||||
u32 work;
|
||||
|
||||
if (IS_ENABLED(CONFIG_DEBUG_ENTRY))
|
||||
@@ -87,11 +81,19 @@ unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch)
|
||||
|
||||
work = ACCESS_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY;
|
||||
|
||||
if (unlikely(work & _TIF_SYSCALL_EMU))
|
||||
emulated = true;
|
||||
|
||||
if ((emulated || (work & _TIF_SYSCALL_TRACE)) &&
|
||||
tracehook_report_syscall_entry(regs))
|
||||
return -1L;
|
||||
|
||||
if (emulated)
|
||||
return -1L;
|
||||
|
||||
#ifdef CONFIG_SECCOMP
|
||||
/*
|
||||
* Do seccomp first -- it should minimize exposure of other
|
||||
* code, and keeping seccomp fast is probably more valuable
|
||||
* than the rest of this.
|
||||
* Do seccomp after ptrace, to catch any tracer changes.
|
||||
*/
|
||||
if (work & _TIF_SECCOMP) {
|
||||
struct seccomp_data sd;
|
||||
@@ -118,69 +120,12 @@ unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch)
|
||||
sd.args[5] = regs->bp;
|
||||
}
|
||||
|
||||
BUILD_BUG_ON(SECCOMP_PHASE1_OK != 0);
|
||||
BUILD_BUG_ON(SECCOMP_PHASE1_SKIP != 1);
|
||||
|
||||
ret = seccomp_phase1(&sd);
|
||||
if (ret == SECCOMP_PHASE1_SKIP) {
|
||||
regs->orig_ax = -1;
|
||||
ret = 0;
|
||||
} else if (ret != SECCOMP_PHASE1_OK) {
|
||||
return ret; /* Go directly to phase 2 */
|
||||
}
|
||||
|
||||
work &= ~_TIF_SECCOMP;
|
||||
ret = __secure_computing(&sd);
|
||||
if (ret == -1)
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Do our best to finish without phase 2. */
|
||||
if (work == 0)
|
||||
return ret; /* seccomp and/or nohz only (ret == 0 here) */
|
||||
|
||||
#ifdef CONFIG_AUDITSYSCALL
|
||||
if (work == _TIF_SYSCALL_AUDIT) {
|
||||
/*
|
||||
* If there is no more work to be done except auditing,
|
||||
* then audit in phase 1. Phase 2 always audits, so, if
|
||||
* we audit here, then we can't go on to phase 2.
|
||||
*/
|
||||
do_audit_syscall_entry(regs, arch);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 1; /* Something is enabled that we can't handle in phase 1 */
|
||||
}
|
||||
|
||||
/* Returns the syscall nr to run (which should match regs->orig_ax). */
|
||||
long syscall_trace_enter_phase2(struct pt_regs *regs, u32 arch,
|
||||
unsigned long phase1_result)
|
||||
{
|
||||
struct thread_info *ti = pt_regs_to_thread_info(regs);
|
||||
long ret = 0;
|
||||
u32 work = ACCESS_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY;
|
||||
|
||||
if (IS_ENABLED(CONFIG_DEBUG_ENTRY))
|
||||
BUG_ON(regs != task_pt_regs(current));
|
||||
|
||||
#ifdef CONFIG_SECCOMP
|
||||
/*
|
||||
* Call seccomp_phase2 before running the other hooks so that
|
||||
* they can see any changes made by a seccomp tracer.
|
||||
*/
|
||||
if (phase1_result > 1 && seccomp_phase2(phase1_result)) {
|
||||
/* seccomp failures shouldn't expose any additional code. */
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (unlikely(work & _TIF_SYSCALL_EMU))
|
||||
ret = -1L;
|
||||
|
||||
if ((ret || test_thread_flag(TIF_SYSCALL_TRACE)) &&
|
||||
tracehook_report_syscall_entry(regs))
|
||||
ret = -1L;
|
||||
|
||||
if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
|
||||
trace_sys_enter(regs, regs->orig_ax);
|
||||
|
||||
@@ -189,17 +134,6 @@ long syscall_trace_enter_phase2(struct pt_regs *regs, u32 arch,
|
||||
return ret ?: regs->orig_ax;
|
||||
}
|
||||
|
||||
long syscall_trace_enter(struct pt_regs *regs)
|
||||
{
|
||||
u32 arch = in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
|
||||
unsigned long phase1_result = syscall_trace_enter_phase1(regs, arch);
|
||||
|
||||
if (phase1_result == 0)
|
||||
return regs->orig_ax;
|
||||
else
|
||||
return syscall_trace_enter_phase2(regs, arch, phase1_result);
|
||||
}
|
||||
|
||||
#define EXIT_TO_USERMODE_LOOP_FLAGS \
|
||||
(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_UPROBE | \
|
||||
_TIF_NEED_RESCHED | _TIF_USER_RETURN_NOTIFY)
|
||||
|
Reference in New Issue
Block a user