Skip to content

Commit

Permalink
Merge branch 'reference-3.4' into stage/sunxi-3.4
Browse files Browse the repository at this point in the history
  • Loading branch information
amery committed Oct 22, 2014
2 parents 9a1cd03 + 7cf03b1 commit a8f8ba9
Show file tree
Hide file tree
Showing 122 changed files with 2,648 additions and 346 deletions.
163 changes: 163 additions & 0 deletions Documentation/prctl/seccomp_filter.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
SECure COMPuting with filters
=============================

Introduction
------------

A large number of system calls are exposed to every userland process
with many of them going unused for the entire lifetime of the process.
As system calls change and mature, bugs are found and eradicated. A
certain subset of userland applications benefit by having a reduced set
of available system calls. The resulting set reduces the total kernel
surface exposed to the application. System call filtering is meant for
use with those applications.

Seccomp filtering provides a means for a process to specify a filter for
incoming system calls. The filter is expressed as a Berkeley Packet
Filter (BPF) program, as with socket filters, except that the data
operated on is related to the system call being made: system call
number and the system call arguments. This allows for expressive
filtering of system calls using a filter program language with a long
history of being exposed to userland and a straightforward data set.

Additionally, BPF makes it impossible for users of seccomp to fall prey
to time-of-check-time-of-use (TOCTOU) attacks that are common in system
call interposition frameworks. BPF programs may not dereference
pointers which constrains all filters to solely evaluating the system
call arguments directly.

What it isn't
-------------

System call filtering isn't a sandbox. It provides a clearly defined
mechanism for minimizing the exposed kernel surface. It is meant to be
a tool for sandbox developers to use. Beyond that, policy for logical
behavior and information flow should be managed with a combination of
other system hardening techniques and, potentially, an LSM of your
choosing. Expressive, dynamic filters provide further options down this
path (avoiding pathological sizes or selecting which of the multiplexed
system calls in socketcall() is allowed, for instance) which could be
construed, incorrectly, as a more complete sandboxing solution.

Usage
-----

An additional seccomp mode is added and is enabled using the same
prctl(2) call as the strict seccomp. If the architecture has
CONFIG_HAVE_ARCH_SECCOMP_FILTER, then filters may be added as below:

PR_SET_SECCOMP:
Now takes an additional argument which specifies a new filter
using a BPF program.
The BPF program will be executed over struct seccomp_data
reflecting the system call number, arguments, and other
metadata. The BPF program must then return one of the
acceptable values to inform the kernel which action should be
taken.

Usage:
prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, prog);

The 'prog' argument is a pointer to a struct sock_fprog which
will contain the filter program. If the program is invalid, the
call will return -1 and set errno to EINVAL.

If fork/clone and execve are allowed by @prog, any child
processes will be constrained to the same filters and system
call ABI as the parent.

Prior to use, the task must call prctl(PR_SET_NO_NEW_PRIVS, 1) or
run with CAP_SYS_ADMIN privileges in its namespace. If these are not
true, -EACCES will be returned. This requirement ensures that filter
programs cannot be applied to child processes with greater privileges
than the task that installed them.

Additionally, if prctl(2) is allowed by the attached filter,
additional filters may be layered on which will increase evaluation
time, but allow for further decreasing the attack surface during
execution of a process.

The above call returns 0 on success and non-zero on error.

Return values
-------------
A seccomp filter may return any of the following values. If multiple
filters exist, the return value for the evaluation of a given system
call will always use the highest precedent value. (For example,
SECCOMP_RET_KILL will always take precedence.)

In precedence order, they are:

SECCOMP_RET_KILL:
Results in the task exiting immediately without executing the
system call. The exit status of the task (status & 0x7f) will
be SIGSYS, not SIGKILL.

SECCOMP_RET_TRAP:
Results in the kernel sending a SIGSYS signal to the triggering
task without executing the system call. The kernel will
rollback the register state to just before the system call
entry such that a signal handler in the task will be able to
inspect the ucontext_t->uc_mcontext registers and emulate
system call success or failure upon return from the signal
handler.

The SECCOMP_RET_DATA portion of the return value will be passed
as si_errno.

SIGSYS triggered by seccomp will have a si_code of SYS_SECCOMP.

SECCOMP_RET_ERRNO:
Results in the lower 16-bits of the return value being passed
to userland as the errno without executing the system call.

SECCOMP_RET_TRACE:
When returned, this value will cause the kernel to attempt to
notify a ptrace()-based tracer prior to executing the system
call. If there is no tracer present, -ENOSYS is returned to
userland and the system call is not executed.

A tracer will be notified if it requests PTRACE_O_TRACESECCOMP
using ptrace(PTRACE_SETOPTIONS). The tracer will be notified
of a PTRACE_EVENT_SECCOMP and the SECCOMP_RET_DATA portion of
the BPF program return value will be available to the tracer
via PTRACE_GETEVENTMSG.

SECCOMP_RET_ALLOW:
Results in the system call being executed.

If multiple filters exist, the return value for the evaluation of a
given system call will always use the highest precedent value.

Precedence is only determined using the SECCOMP_RET_ACTION mask. When
multiple filters return values of the same precedence, only the
SECCOMP_RET_DATA from the most recently installed filter will be
returned.

Pitfalls
--------

The biggest pitfall to avoid during use is filtering on system call
number without checking the architecture value. Why? On any
architecture that supports multiple system call invocation conventions,
the system call numbers may vary based on the specific invocation. If
the numbers in the different calling conventions overlap, then checks in
the filters may be abused. Always check the arch value!

Example
-------

The samples/seccomp/ directory contains both an x86-specific example
and a more generic example of a higher level macro interface for BPF
program generation.



Adding architecture support
-----------------------

See arch/Kconfig for the authoritative requirements. In general, if an
architecture supports both ptrace_event and seccomp, it will be able to
support seccomp filter with minor fixup: SIGSYS support and seccomp return
value checking. Then it must just add CONFIG_HAVE_ARCH_SECCOMP_FILTER
to its arch-specific Kconfig.
3 changes: 3 additions & 0 deletions Documentation/stable_kernel_rules.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ Rules on what kind of patches are accepted, and which ones are not, into the

Procedure for submitting patches to the -stable tree:

- If the patch covers files in net/ or drivers/net please follow netdev stable
submission guidelines as described in
Documentation/networking/netdev-FAQ.txt
- Send the patch, after verifying that it follows the above rules, to
stable@vger.kernel.org. You must note the upstream commit ID in the
changelog of your submission, as well as the kernel version you wish
Expand Down
10 changes: 10 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -5937,6 +5937,16 @@ S: Maintained
F: drivers/mmc/host/sdhci.*
F: drivers/mmc/host/sdhci-pltfm.[ch]

SECURE COMPUTING
M: Kees Cook <keescook@chromium.org>
T: git git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux.git seccomp
S: Supported
F: kernel/seccomp.c
F: include/uapi/linux/seccomp.h
F: include/linux/seccomp.h
K: \bsecure_computing
K: \bTIF_SECCOMP\b

SECURE DIGITAL HOST CONTROLLER INTERFACE, OPEN FIRMWARE BINDINGS (SDHCI-OF)
M: Anton Vorontsov <avorontsov@ru.mvista.com>
L: linuxppc-dev@lists.ozlabs.org
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
VERSION = 3
PATCHLEVEL = 4
SUBLEVEL = 103
SUBLEVEL = 104
EXTRAVERSION =
NAME = Saber-toothed Squirrel

Expand Down
24 changes: 24 additions & 0 deletions arch/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -219,4 +219,28 @@ config HAVE_CMPXCHG_DOUBLE
config ARCH_WANT_OLD_COMPAT_IPC
bool

config HAVE_ARCH_SECCOMP_FILTER
bool
help
An arch should select this symbol if it provides all of these things:
- syscall_get_arch()
- syscall_get_arguments()
- syscall_rollback()
- syscall_set_return_value()
- SIGSYS siginfo_t support
- secure_computing is called from a ptrace_event()-safe context
- secure_computing return value is checked and a return value of -1
results in the system call being skipped immediately.
- seccomp syscall wired up

config SECCOMP_FILTER
def_bool y
depends on HAVE_ARCH_SECCOMP_FILTER && SECCOMP && NET
help
Enable tasks to build secure computing environments defined
in terms of Berkeley Packet Filter programs which implement
task-defined system call filtering polices.

See Documentation/prctl/seccomp_filter.txt for details.

source "kernel/gcov/Kconfig"
5 changes: 5 additions & 0 deletions arch/alpha/include/asm/io.h
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,11 @@ extern inline void writeq(u64 b, volatile void __iomem *addr)
}
#endif

#define ioread16be(p) be16_to_cpu(ioread16(p))
#define ioread32be(p) be32_to_cpu(ioread32(p))
#define iowrite16be(v,p) iowrite16(cpu_to_be16(v), (p))
#define iowrite32be(v,p) iowrite32(cpu_to_be32(v), (p))

#define inb_p inb
#define inw_p inw
#define inl_p inl
Expand Down
1 change: 1 addition & 0 deletions arch/alpha/oprofile/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <linux/smp.h>
#include <linux/errno.h>
#include <asm/ptrace.h>
#include <asm/special_insns.h>

#include "op_impl.h"

Expand Down
2 changes: 2 additions & 0 deletions arch/arm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ config ARM
select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7))
select HAVE_C_RECORDMCOUNT
select HAVE_GENERIC_HARDIRQS
select HAVE_SPARSE_IRQ
select HAVE_ARCH_SECCOMP_FILTER
select GENERIC_IRQ_SHOW
select CPU_PM if (SUSPEND || CPU_IDLE)
select GENERIC_PCI_IOMAP
Expand Down
80 changes: 80 additions & 0 deletions arch/arm/include/asm/syscall.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Access to user system call parameters and results
*
* Copyright (C) 2012 The Chromium OS Authors <chromium-os-dev@chromium.org>
*
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU General Public License v.2.
*
* See asm-generic/syscall.h for descriptions of what we must do here.
*/
#ifndef _ASM_ARM_SYSCALL_H
#define _ASM_ARM_SYSCALL_H

#include <linux/audit.h> /* for AUDIT_ARCH_* */
#include <linux/elf.h> /* for ELF_EM */
#include <linux/sched.h>
#include <linux/thread_info.h> /* for task_thread_info */
#include <linux/err.h>

static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
{
return task_thread_info(task)->syscall;
}

static inline void syscall_rollback(struct task_struct *task,
struct pt_regs *regs)
{
regs->ARM_r0 = regs->ARM_ORIG_r0;
}

static inline long syscall_get_error(struct task_struct *task,
struct pt_regs *regs)
{
unsigned long error = regs->ARM_r0;
return IS_ERR_VALUE(error) ? error : 0;
}

static inline long syscall_get_return_value(struct task_struct *task,
struct pt_regs *regs)
{
return regs->ARM_r0;
}

static inline void syscall_set_return_value(struct task_struct *task,
struct pt_regs *regs,
int error, long val)
{
regs->ARM_r0 = (long) error ?: val;
}

static inline void syscall_get_arguments(struct task_struct *task,
struct pt_regs *regs,
unsigned int i, unsigned int n,
unsigned long *args)
{
BUG_ON(i + n > 6);
memcpy(args, &regs->ARM_r0 + i, n * sizeof(args[0]));
}

static inline void syscall_set_arguments(struct task_struct *task,
struct pt_regs *regs,
unsigned int i, unsigned int n,
const unsigned long *args)
{
BUG_ON(i + n > 6);
memcpy(&regs->ARM_r0 + i, args, n * sizeof(args[0]));
}

static inline int syscall_get_arch(struct task_struct *task,
struct pt_regs *regs)
{
/* ARM tasks don't change audit architectures on the fly. */
#ifdef __ARMEB__
return AUDIT_ARCH_ARMEB;
#else
return AUDIT_ARCH_ARM;
#endif
}
#endif /* _ASM_ARM_SYSCALL_H */
1 change: 1 addition & 0 deletions arch/arm/include/asm/unistd.h
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,7 @@
#define __NR_setns (__NR_SYSCALL_BASE+375)
#define __NR_process_vm_readv (__NR_SYSCALL_BASE+376)
#define __NR_process_vm_writev (__NR_SYSCALL_BASE+377)
#define __NR_seccomp (__NR_SYSCALL_BASE+383)

/*
* The following SWIs are ARM private.
Expand Down
6 changes: 6 additions & 0 deletions arch/arm/kernel/calls.S
Original file line number Diff line number Diff line change
Expand Up @@ -387,6 +387,12 @@
/* 375 */ CALL(sys_setns)
CALL(sys_process_vm_readv)
CALL(sys_process_vm_writev)
CALL(sys_ni_syscall)
CALL(sys_ni_syscall)
/* 380 */ CALL(sys_ni_syscall)
CALL(sys_ni_syscall)
CALL(sys_ni_syscall)
CALL(sys_seccomp)
#ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
#define syscalls_counted
Expand Down
7 changes: 1 addition & 6 deletions arch/arm/kernel/entry-common.S
Original file line number Diff line number Diff line change
Expand Up @@ -444,12 +444,7 @@ ENTRY(vector_swi)

#ifdef CONFIG_SECCOMP
tst r10, #_TIF_SECCOMP
beq 1f
mov r0, scno
bl __secure_computing
add r0, sp, #S_R0 + S_OFF @ pointer to regs
ldmia r0, {r0 - r3} @ have to reload r0 - r3
1:
bne __sys_trace
#endif

tst r10, #_TIF_SYSCALL_WORK @ are we tracing syscalls?
Expand Down
Loading

0 comments on commit a8f8ba9

Please sign in to comment.