summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony G. Basile <blueness@gentoo.org>2013-11-04 19:05:54 -0500
committerAnthony G. Basile <blueness@gentoo.org>2013-11-04 19:05:54 -0500
commitee6147f8d257074979248d11bf7736e30662d0ea (patch)
treeb2b086a34476f2b1ce9b283508f4f4f5275823a0
parentGrsec/PaX: 2.9.1-{2.6.32.61,3.2.52,3.11.6}-201310292050 (diff)
downloadhardened-patchset-ee6147f8d257074979248d11bf7736e30662d0ea.tar.gz
hardened-patchset-ee6147f8d257074979248d11bf7736e30662d0ea.tar.bz2
hardened-patchset-ee6147f8d257074979248d11bf7736e30662d0ea.zip
Grsec/PaX: 2.9.1-{3.2.52,3.11.6}-20131102163520131102
-rw-r--r--3.11.6/0000_README2
-rw-r--r--3.11.6/4420_grsecurity-2.9.1-3.11.6-201311021635.patch (renamed from 3.11.6/4420_grsecurity-2.9.1-3.11.6-201310292050.patch)107
-rw-r--r--3.2.52/0000_README2
-rw-r--r--3.2.52/4420_grsecurity-2.9.1-3.2.52-201311021628.patch (renamed from 3.2.52/4420_grsecurity-2.9.1-3.2.52-201310292049.patch)1688
4 files changed, 1690 insertions, 109 deletions
diff --git a/3.11.6/0000_README b/3.11.6/0000_README
index 2489326..358a97d 100644
--- a/3.11.6/0000_README
+++ b/3.11.6/0000_README
@@ -2,7 +2,7 @@ README
-----------------------------------------------------------------------------
Individual Patch Descriptions:
-----------------------------------------------------------------------------
-Patch: 4420_grsecurity-2.9.1-3.11.6-201310292050.patch
+Patch: 4420_grsecurity-2.9.1-3.11.6-201311021635.patch
From: http://www.grsecurity.net
Desc: hardened-sources base patch from upstream grsecurity
diff --git a/3.11.6/4420_grsecurity-2.9.1-3.11.6-201310292050.patch b/3.11.6/4420_grsecurity-2.9.1-3.11.6-201311021635.patch
index 020c231..306363f 100644
--- a/3.11.6/4420_grsecurity-2.9.1-3.11.6-201310292050.patch
+++ b/3.11.6/4420_grsecurity-2.9.1-3.11.6-201311021635.patch
@@ -46087,6 +46087,19 @@ index fcb0329..d77b7f2 100644
ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
if (ret)
+diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
+index 408a42e..f0d432c 100644
+--- a/drivers/scsi/aacraid/linit.c
++++ b/drivers/scsi/aacraid/linit.c
+@@ -771,6 +771,8 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long
+ static int aac_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
+ {
+ struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
++ if (!capable(CAP_SYS_RAWIO))
++ return -EPERM;
+ return aac_compat_do_ioctl(dev, cmd, (unsigned long)arg);
+ }
+
diff --git a/drivers/scsi/bfa/bfa_fcpim.h b/drivers/scsi/bfa/bfa_fcpim.h
index e693af6..2e525b6 100644
--- a/drivers/scsi/bfa/bfa_fcpim.h
@@ -47112,6 +47125,18 @@ index ee3a57f..18368c1 100644
tdev->dev = device_create(timed_output_class, NULL,
MKDEV(0, tdev->index), NULL, "%s", tdev->name);
if (IS_ERR(tdev->dev))
+diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c
+index f67a225..756b634 100644
+--- a/drivers/staging/bcm/Bcmchar.c
++++ b/drivers/staging/bcm/Bcmchar.c
+@@ -1960,6 +1960,7 @@ cntrlEnd:
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n");
+
++ memset(&DevInfo, 0, sizeof(DevInfo));
+ DevInfo.MaxRDMBufferSize = BUFFER_4K;
+ DevInfo.u32DSDStartOffset = EEPROM_CALPARAM_START;
+ DevInfo.u32RxAlignmentCorrection = 0;
diff --git a/drivers/staging/media/solo6x10/solo6x10-core.c b/drivers/staging/media/solo6x10/solo6x10-core.c
index 3675020..e80d92c 100644
--- a/drivers/staging/media/solo6x10/solo6x10-core.c
@@ -47203,6 +47228,20 @@ index c3a90e7..023619a 100644
#endif
}
+diff --git a/drivers/staging/ozwpan/ozcdev.c b/drivers/staging/ozwpan/ozcdev.c
+index 374fdc3..ea5f9f3 100644
+--- a/drivers/staging/ozwpan/ozcdev.c
++++ b/drivers/staging/ozwpan/ozcdev.c
+@@ -152,6 +152,9 @@ static ssize_t oz_cdev_write(struct file *filp, const char __user *buf,
+ struct oz_app_hdr *app_hdr;
+ struct oz_serial_ctx *ctx;
+
++ if (count > sizeof(ei->data) - sizeof(*elt) - sizeof(*app_hdr))
++ return -EINVAL;
++
+ spin_lock_bh(&g_cdev.lock);
+ pd = g_cdev.active_pd;
+ if (pd)
diff --git a/drivers/staging/rtl8712/rtl871x_io.h b/drivers/staging/rtl8712/rtl871x_io.h
index dc23395..cf7e9b1 100644
--- a/drivers/staging/rtl8712/rtl871x_io.h
@@ -47346,6 +47385,47 @@ index c699a30..b90a5fd 100644
pDevice->apdev->netdev_ops = &apdev_netdev_ops;
pDevice->apdev->type = ARPHRD_IEEE80211;
+diff --git a/drivers/staging/wlags49_h2/wl_priv.c b/drivers/staging/wlags49_h2/wl_priv.c
+index c97e0e1..7e10dcd 100644
+--- a/drivers/staging/wlags49_h2/wl_priv.c
++++ b/drivers/staging/wlags49_h2/wl_priv.c
+@@ -570,6 +570,7 @@ int wvlan_uil_put_info(struct uilreq *urq, struct wl_private *lp)
+ ltv_t *pLtv;
+ bool_t ltvAllocated = FALSE;
+ ENCSTRCT sEncryption;
++ size_t len;
+
+ #ifdef USE_WDS
+ hcf_16 hcfPort = HCF_PORT_0;
+@@ -686,7 +687,8 @@ int wvlan_uil_put_info(struct uilreq *urq, struct wl_private *lp)
+ break;
+ case CFG_CNF_OWN_NAME:
+ memset(lp->StationName, 0, sizeof(lp->StationName));
+- memcpy((void *)lp->StationName, (void *)&pLtv->u.u8[2], (size_t)pLtv->u.u16[0]);
++ len = min_t(size_t, pLtv->u.u16[0], sizeof(lp->StationName));
++ strlcpy(lp->StationName, &pLtv->u.u8[2], len);
+ pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
+ break;
+ case CFG_CNF_LOAD_BALANCING:
+@@ -1783,6 +1785,7 @@ int wvlan_set_station_nickname(struct net_device *dev,
+ {
+ struct wl_private *lp = wl_priv(dev);
+ unsigned long flags;
++ size_t len;
+ int ret = 0;
+ /*------------------------------------------------------------------------*/
+
+@@ -1793,8 +1796,8 @@ int wvlan_set_station_nickname(struct net_device *dev,
+ wl_lock(lp, &flags);
+
+ memset(lp->StationName, 0, sizeof(lp->StationName));
+-
+- memcpy(lp->StationName, extra, wrqu->data.length);
++ len = min_t(size_t, wrqu->data.length, sizeof(lp->StationName));
++ strlcpy(lp->StationName, extra, len);
+
+ /* Commit the adapter parameters */
+ wl_apply(lp);
diff --git a/drivers/staging/zcache/tmem.h b/drivers/staging/zcache/tmem.h
index d128ce2..fc1f9a1 100644
--- a/drivers/staging/zcache/tmem.h
@@ -85733,6 +85813,20 @@ index e796429..6e38f9f 100644
static inline void *ptr_to_indirect(void *ptr)
{
+diff --git a/lib/scatterlist.c b/lib/scatterlist.c
+index a685c8a..d16fa29 100644
+--- a/lib/scatterlist.c
++++ b/lib/scatterlist.c
+@@ -577,7 +577,8 @@ void sg_miter_stop(struct sg_mapping_iter *miter)
+ miter->__offset += miter->consumed;
+ miter->__remaining -= miter->consumed;
+
+- if (miter->__flags & SG_MITER_TO_SG)
++ if ((miter->__flags & SG_MITER_TO_SG) &&
++ !PageSlab(miter->page))
+ flush_kernel_dcache_page(miter->page);
+
+ if (miter->__flags & SG_MITER_ATOMIC) {
diff --git a/lib/strncpy_from_user.c b/lib/strncpy_from_user.c
index bb2b201..46abaf9 100644
--- a/lib/strncpy_from_user.c
@@ -91613,6 +91707,19 @@ index dfa602c..3103d88 100644
if (!IS_ERR(flo))
fle->object = flo;
else
+diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c
+index 52d0f83..4a1d064 100644
+--- a/net/core/flow_dissector.c
++++ b/net/core/flow_dissector.c
+@@ -40,7 +40,7 @@ again:
+ struct iphdr _iph;
+ ip:
+ iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph);
+- if (!iph)
++ if (!iph || iph->ihl < 5)
+ return false;
+
+ if (ip_is_fragment(iph))
diff --git a/net/core/iovec.c b/net/core/iovec.c
index de178e4..1dabd8b 100644
--- a/net/core/iovec.c
diff --git a/3.2.52/0000_README b/3.2.52/0000_README
index f3e1e87..7ddab2f 100644
--- a/3.2.52/0000_README
+++ b/3.2.52/0000_README
@@ -126,7 +126,7 @@ Patch: 1051_linux-3.2.52.patch
From: http://www.kernel.org
Desc: Linux 3.2.52
-Patch: 4420_grsecurity-2.9.1-3.2.52-201310292049.patch
+Patch: 4420_grsecurity-2.9.1-3.2.52-201311021628.patch
From: http://www.grsecurity.net
Desc: hardened-sources base patch from upstream grsecurity
diff --git a/3.2.52/4420_grsecurity-2.9.1-3.2.52-201310292049.patch b/3.2.52/4420_grsecurity-2.9.1-3.2.52-201311021628.patch
index e09de55..398b6be 100644
--- a/3.2.52/4420_grsecurity-2.9.1-3.2.52-201310292049.patch
+++ b/3.2.52/4420_grsecurity-2.9.1-3.2.52-201311021628.patch
@@ -485,6 +485,39 @@ index 1dd2c09..6f850c4 100644
$(cmd_crmodverdir)
$(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
$(build)=$(build-dir) $(@:.ko=.o)
+diff --git a/arch/Kconfig b/arch/Kconfig
+index 4b0669c..7389b35 100644
+--- a/arch/Kconfig
++++ b/arch/Kconfig
+@@ -181,4 +181,28 @@ config HAVE_RCU_TABLE_FREE
+ config ARCH_HAVE_NMI_SAFE_CMPXCHG
+ 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
++ - uses __secure_computing_int() or secure_computing()
++ - 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.
++
++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"
diff --git a/arch/alpha/include/asm/atomic.h b/arch/alpha/include/asm/atomic.h
index 6f1aca7..fa956e0 100644
--- a/arch/alpha/include/asm/atomic.h
@@ -8873,10 +8906,18 @@ index ad8f795..2c7eec6 100644
/*
* Memory returned by kmalloc() may be used for DMA, so we must make
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
-index fb2e69d..9cd4eea 100644
+index fb2e69d..27ff8ca 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
-@@ -235,7 +235,7 @@ config X86_HT
+@@ -75,6 +75,7 @@ config X86
+ select HAVE_BPF_JIT if (X86_64 && NET)
+ select CLKEVT_I8253
+ select ARCH_HAVE_NMI_SAFE_CMPXCHG
++ select HAVE_ARCH_SECCOMP_FILTER
+
+ config INSTRUCTION_DECODER
+ def_bool (KPROBES || PERF_EVENTS)
+@@ -235,7 +236,7 @@ config X86_HT
config X86_32_LAZY_GS
def_bool y
@@ -8885,7 +8926,7 @@ index fb2e69d..9cd4eea 100644
config ARCH_HWEIGHT_CFLAGS
string
-@@ -999,6 +999,7 @@ config MICROCODE_OLD_INTERFACE
+@@ -999,6 +1000,7 @@ config MICROCODE_OLD_INTERFACE
config X86_MSR
tristate "/dev/cpu/*/msr - Model-specific register support"
@@ -8893,7 +8934,7 @@ index fb2e69d..9cd4eea 100644
---help---
This device gives privileged processes access to the x86
Model-Specific Registers (MSRs). It is a character device with
-@@ -1022,7 +1023,7 @@ choice
+@@ -1022,7 +1024,7 @@ choice
config NOHIGHMEM
bool "off"
@@ -8902,7 +8943,7 @@ index fb2e69d..9cd4eea 100644
---help---
Linux can use up to 64 Gigabytes of physical memory on x86 systems.
However, the address space of 32-bit x86 processors is only 4
-@@ -1059,7 +1060,7 @@ config NOHIGHMEM
+@@ -1059,7 +1061,7 @@ config NOHIGHMEM
config HIGHMEM4G
bool "4GB"
@@ -8911,7 +8952,7 @@ index fb2e69d..9cd4eea 100644
---help---
Select this if you have a 32-bit processor and between 1 and 4
gigabytes of physical RAM.
-@@ -1113,7 +1114,7 @@ config PAGE_OFFSET
+@@ -1113,7 +1115,7 @@ config PAGE_OFFSET
hex
default 0xB0000000 if VMSPLIT_3G_OPT
default 0x80000000 if VMSPLIT_2G
@@ -8920,7 +8961,7 @@ index fb2e69d..9cd4eea 100644
default 0x40000000 if VMSPLIT_1G
default 0xC0000000
depends on X86_32
-@@ -1496,6 +1497,7 @@ config SECCOMP
+@@ -1496,6 +1498,7 @@ config SECCOMP
config CC_STACKPROTECTOR
bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
@@ -8928,7 +8969,7 @@ index fb2e69d..9cd4eea 100644
---help---
This option turns on the -fstack-protector GCC feature. This
feature puts, at the beginning of functions, a canary value on
-@@ -1616,6 +1618,8 @@ config X86_NEED_RELOCS
+@@ -1616,6 +1619,8 @@ config X86_NEED_RELOCS
config PHYSICAL_ALIGN
hex "Alignment value to which kernel should be aligned" if X86_32
default "0x1000000"
@@ -8937,7 +8978,7 @@ index fb2e69d..9cd4eea 100644
range 0x2000 0x1000000
---help---
This value puts the alignment restrictions on physical address
-@@ -1647,9 +1651,10 @@ config HOTPLUG_CPU
+@@ -1647,9 +1652,10 @@ config HOTPLUG_CPU
Say N if you want to disable CPU hotplug.
config COMPAT_VDSO
@@ -9766,10 +9807,21 @@ index fd84387..887aa7e 100644
(unsigned long)create_aout_tables((char __user *)bprm->p, bprm);
/* start thread */
diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
-index 6557769..ef6ae89 100644
+index 6557769..dfa8ead 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
-@@ -169,7 +169,7 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
+@@ -73,6 +73,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:
+ put_user_ex(from->si_utime, &to->si_utime);
+ put_user_ex(from->si_stime, &to->si_stime);
+@@ -169,7 +173,7 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
}
seg = get_fs();
set_fs(KERNEL_DS);
@@ -9778,7 +9830,7 @@ index 6557769..ef6ae89 100644
set_fs(seg);
if (ret >= 0 && uoss_ptr) {
if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)))
-@@ -370,7 +370,7 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
+@@ -370,7 +374,7 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
*/
static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
size_t frame_size,
@@ -9787,7 +9839,7 @@ index 6557769..ef6ae89 100644
{
unsigned long sp;
-@@ -391,7 +391,7 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+@@ -391,7 +395,7 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
if (used_math()) {
sp = sp - sig_xstate_ia32_size;
@@ -9796,7 +9848,7 @@ index 6557769..ef6ae89 100644
if (save_i387_xstate_ia32(*fpstate) < 0)
return (void __user *) -1L;
}
-@@ -399,7 +399,7 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
+@@ -399,7 +403,7 @@ static void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
sp -= frame_size;
/* Align the stack pointer according to the i386 ABI,
* i.e. so that on function entry ((sp + 4) & 15) == 0. */
@@ -9805,7 +9857,7 @@ index 6557769..ef6ae89 100644
return (void __user *) sp;
}
-@@ -457,7 +457,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
+@@ -457,7 +461,7 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
* These are actually not used anymore, but left because some
* gdb versions depend on them as a marker.
*/
@@ -9814,7 +9866,7 @@ index 6557769..ef6ae89 100644
} put_user_catch(err);
if (err)
-@@ -499,7 +499,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+@@ -499,7 +503,7 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
0xb8,
__NR_ia32_rt_sigreturn,
0x80cd,
@@ -9823,7 +9875,7 @@ index 6557769..ef6ae89 100644
};
frame = get_sigframe(ka, regs, sizeof(*frame), &fpstate);
-@@ -529,16 +529,18 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
+@@ -529,16 +533,18 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
if (ka->sa.sa_flags & SA_RESTORER)
restorer = ka->sa.sa_restorer;
@@ -11945,6 +11997,23 @@ index a203659..9889f1c 100644
extern struct legacy_pic *legacy_pic;
extern struct legacy_pic null_legacy_pic;
+diff --git a/arch/x86/include/asm/ia32.h b/arch/x86/include/asm/ia32.h
+index 1f7e625..541485f 100644
+--- a/arch/x86/include/asm/ia32.h
++++ b/arch/x86/include/asm/ia32.h
+@@ -126,6 +126,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;
+
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
index d8e8eef..1765f78 100644
--- a/arch/x86/include/asm/io.h
@@ -13832,6 +13901,54 @@ index cb23852..2dde194 100644
asmlinkage long sys32_sysfs(int, u32, u32);
asmlinkage long sys32_sched_rr_get_interval(compat_pid_t,
+diff --git a/arch/x86/include/asm/syscall.h b/arch/x86/include/asm/syscall.h
+index c4a348f..e2ad7ea 100644
+--- a/arch/x86/include/asm/syscall.h
++++ b/arch/x86/include/asm/syscall.h
+@@ -13,6 +13,7 @@
+ #ifndef _ASM_X86_SYSCALL_H
+ #define _ASM_X86_SYSCALL_H
+
++#include <linux/audit.h>
+ #include <linux/sched.h>
+ #include <linux/err.h>
+
+@@ -86,6 +87,12 @@ static inline void syscall_set_arguments(struct task_struct *task,
+ memcpy(&regs->bx + i, args, n * sizeof(args[0]));
+ }
+
++static inline int syscall_get_arch(struct task_struct *task,
++ struct pt_regs *regs)
++{
++ return AUDIT_ARCH_I386;
++}
++
+ #else /* CONFIG_X86_64 */
+
+ static inline void syscall_get_arguments(struct task_struct *task,
+@@ -210,6 +217,22 @@ static inline void syscall_set_arguments(struct task_struct *task,
+ }
+ }
+
++static inline int syscall_get_arch(struct task_struct *task,
++ struct pt_regs *regs)
++{
++#ifdef CONFIG_IA32_EMULATION
++ /*
++ * TS_COMPAT is set for 32-bit syscall entries and then
++ * remains set until we return to user mode.
++ *
++ * TIF_IA32 tasks should always have TS_COMPAT set at
++ * system call time.
++ */
++ if (task_thread_info(task)->status & TS_COMPAT)
++ return AUDIT_ARCH_I386;
++#endif
++ return AUDIT_ARCH_X86_64;
++}
+ #endif /* CONFIG_X86_32 */
+
+ #endif /* _ASM_X86_SYSCALL_H */
diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h
index d75adff..c0cc78b 100644
--- a/arch/x86/include/asm/system.h
@@ -20676,7 +20793,7 @@ index 6a364a6..b147d11 100644
ip = *(u64 *)(fp+8);
if (!in_sched_functions(ip))
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
-index 2dc4121..869e219 100644
+index 2dc4121..60e1086 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -181,14 +181,13 @@ unsigned long kernel_stack_pointer(struct pt_regs *regs)
@@ -20792,7 +20909,28 @@ index 2dc4121..869e219 100644
/*
* If we stepped into a sysenter/syscall insn, it trapped in
* kernel mode; do_debug() cleared TF and set TIF_SINGLESTEP.
-@@ -1443,6 +1451,11 @@ void syscall_trace_leave(struct pt_regs *regs)
+@@ -1409,7 +1417,11 @@ long syscall_trace_enter(struct pt_regs *regs)
+ regs->flags |= X86_EFLAGS_TF;
+
+ /* do the secure computing check first */
+- secure_computing(regs->orig_ax);
++ if (secure_computing(regs->orig_ax)) {
++ /* seccomp failures shouldn't expose any additional code. */
++ ret = -1L;
++ goto out;
++ }
+
+ if (unlikely(test_thread_flag(TIF_SYSCALL_EMU)))
+ ret = -1L;
+@@ -1436,6 +1448,7 @@ long syscall_trace_enter(struct pt_regs *regs)
+ #endif
+ }
+
++out:
+ return ret ?: regs->orig_ax;
+ }
+
+@@ -1443,6 +1456,11 @@ void syscall_trace_leave(struct pt_regs *regs)
{
bool step;
@@ -42476,7 +42614,7 @@ index 2836538..30edf9d 100644
ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr);
if (ret) {
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
-index 705e13e..91c873c 100644
+index 705e13e..46f4afb 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -93,7 +93,7 @@ static DECLARE_PCI_DEVICE_TABLE(aac_pci_tbl) = {
@@ -42488,6 +42626,15 @@ index 705e13e..91c873c 100644
#endif
{ 0x1028, 0x0001, 0x1028, 0x0001, 0, 0, 0 }, /* PERC 2/Si (Iguana/PERC2Si) */
{ 0x1028, 0x0002, 0x1028, 0x0002, 0, 0, 1 }, /* PERC 3/Di (Opal/PERC3Di) */
+@@ -771,6 +771,8 @@ static long aac_compat_do_ioctl(struct aac_dev *dev, unsigned cmd, unsigned long
+ static int aac_compat_ioctl(struct scsi_device *sdev, int cmd, void __user *arg)
+ {
+ struct aac_dev *dev = (struct aac_dev *)sdev->host->hostdata;
++ if (!capable(CAP_SYS_RAWIO))
++ return -EPERM;
+ return aac_compat_do_ioctl(dev, cmd, (unsigned long)arg);
+ }
+
diff --git a/drivers/scsi/aic94xx/aic94xx_init.c b/drivers/scsi/aic94xx/aic94xx_init.c
index d5ff142..49c0ebb 100644
--- a/drivers/scsi/aic94xx/aic94xx_init.c
@@ -43447,6 +43594,18 @@ index b2ccdea..84cde75 100644
static u8 *buf;
+diff --git a/drivers/staging/bcm/Bcmchar.c b/drivers/staging/bcm/Bcmchar.c
+index 2fa658e..391b768 100644
+--- a/drivers/staging/bcm/Bcmchar.c
++++ b/drivers/staging/bcm/Bcmchar.c
+@@ -1932,6 +1932,7 @@ cntrlEnd:
+
+ BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Called IOCTL_BCM_GET_DEVICE_DRIVER_INFO\n");
+
++ memset(&DevInfo, 0, sizeof(DevInfo));
+ DevInfo.MaxRDMBufferSize = BUFFER_4K;
+ DevInfo.u32DSDStartOffset = EEPROM_CALPARAM_START;
+ DevInfo.u32RxAlignmentCorrection = 0;
diff --git a/drivers/staging/gma500/power.c b/drivers/staging/gma500/power.c
index 436fe97..4082570 100644
--- a/drivers/staging/gma500/power.c
@@ -43809,6 +43968,59 @@ index df8ea25..47dd9c6 100644
pDevice->apdev->netdev_ops = &apdev_netdev_ops;
pDevice->apdev->type = ARPHRD_IEEE80211;
+diff --git a/drivers/staging/wlags49_h2/wl_priv.c b/drivers/staging/wlags49_h2/wl_priv.c
+index 260d4f0..ed836c2 100644
+--- a/drivers/staging/wlags49_h2/wl_priv.c
++++ b/drivers/staging/wlags49_h2/wl_priv.c
+@@ -570,6 +570,7 @@ int wvlan_uil_put_info( struct uilreq *urq, struct wl_private *lp )
+ ltv_t *pLtv;
+ bool_t ltvAllocated = FALSE;
+ ENCSTRCT sEncryption;
++ size_t len;
+
+ #ifdef USE_WDS
+ hcf_16 hcfPort = HCF_PORT_0;
+@@ -685,9 +686,10 @@ int wvlan_uil_put_info( struct uilreq *urq, struct wl_private *lp )
+ pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] );
+ break;
+ case CFG_CNF_OWN_NAME:
+- memset( lp->StationName, 0, sizeof( lp->StationName ));
+- memcpy( (void *)lp->StationName, (void *)&pLtv->u.u8[2], (size_t)pLtv->u.u16[0]);
+- pLtv->u.u16[0] = CNV_INT_TO_LITTLE( pLtv->u.u16[0] );
++ memset(lp->StationName, 0, sizeof(lp->StationName));
++ len = min_t(size_t, pLtv->u.u16[0], sizeof(lp->StationName));
++ strlcpy(lp->StationName, &pLtv->u.u8[2], len);
++ pLtv->u.u16[0] = CNV_INT_TO_LITTLE(pLtv->u.u16[0]);
+ break;
+ case CFG_CNF_LOAD_BALANCING:
+ lp->loadBalancing = pLtv->u.u16[0];
+@@ -1798,9 +1800,10 @@ int wvlan_set_station_nickname(struct net_device *dev,
+ union iwreq_data *wrqu,
+ char *extra)
+ {
+- struct wl_private *lp = wl_priv(dev);
+- unsigned long flags;
+- int ret = 0;
++ struct wl_private *lp = wl_priv(dev);
++ unsigned long flags;
++ size_t len;
++ int ret = 0;
+ /*------------------------------------------------------------------------*/
+
+
+@@ -1809,9 +1812,9 @@ int wvlan_set_station_nickname(struct net_device *dev,
+
+ wl_lock(lp, &flags);
+
+- memset( lp->StationName, 0, sizeof( lp->StationName ));
+-
+- memcpy( lp->StationName, extra, wrqu->data.length);
++ memset(lp->StationName, 0, sizeof(lp->StationName));
++ len = min_t(size_t, wrqu->data.length, sizeof(lp->StationName));
++ strlcpy(lp->StationName, extra, len);
+
+ /* Commit the adapter parameters */
+ wl_apply( lp );
diff --git a/drivers/staging/zcache/tmem.c b/drivers/staging/zcache/tmem.c
index 1ca66ea..76f1343 100644
--- a/drivers/staging/zcache/tmem.c
@@ -51373,7 +51585,7 @@ index 451b9b8..12e5a03 100644
out_free_fd:
diff --git a/fs/exec.c b/fs/exec.c
-index a2d0e51..d46efb6 100644
+index a2d0e51..0d1143c 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -55,12 +55,35 @@
@@ -51760,7 +51972,21 @@ index a2d0e51..d46efb6 100644
/* Set the new mm task size. We have to do that late because it may
* depend on TIF_32BIT which is only updated in flush_thread() on
-@@ -1268,7 +1347,7 @@ int check_unsafe_exec(struct linux_binprm *bprm)
+@@ -1259,6 +1338,13 @@ int check_unsafe_exec(struct linux_binprm *bprm)
+ bprm->unsafe |= LSM_UNSAFE_PTRACE;
+ }
+
++ /*
++ * This isn't strictly necessary, but it makes it harder for LSMs to
++ * mess up.
++ */
++ if (current->no_new_privs)
++ bprm->unsafe |= LSM_UNSAFE_NO_NEW_PRIVS;
++
+ n_fs = 1;
+ spin_lock(&p->fs->lock);
+ rcu_read_lock();
+@@ -1268,7 +1354,7 @@ int check_unsafe_exec(struct linux_binprm *bprm)
}
rcu_read_unlock();
@@ -51769,7 +51995,17 @@ index a2d0e51..d46efb6 100644
bprm->unsafe |= LSM_UNSAFE_SHARE;
} else {
res = -EAGAIN;
-@@ -1463,6 +1542,31 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
+@@ -1302,7 +1388,8 @@ int prepare_binprm(struct linux_binprm *bprm)
+ bprm->cred->euid = current_euid();
+ bprm->cred->egid = current_egid();
+
+- if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)) {
++ if (!(bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) &&
++ !current->no_new_privs) {
+ /* Set-uid? */
+ if (mode & S_ISUID) {
+ bprm->per_clear |= PER_CLEAR_ON_SETID;
+@@ -1463,6 +1550,31 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
EXPORT_SYMBOL(search_binary_handler);
@@ -51801,7 +52037,7 @@ index a2d0e51..d46efb6 100644
/*
* sys_execve() executes a new program.
*/
-@@ -1471,6 +1575,11 @@ static int do_execve_common(const char *filename,
+@@ -1471,6 +1583,11 @@ static int do_execve_common(const char *filename,
struct user_arg_ptr envp,
struct pt_regs *regs)
{
@@ -51813,7 +52049,7 @@ index a2d0e51..d46efb6 100644
struct linux_binprm *bprm;
struct file *file;
struct files_struct *displaced;
-@@ -1478,6 +1587,8 @@ static int do_execve_common(const char *filename,
+@@ -1478,6 +1595,8 @@ static int do_execve_common(const char *filename,
int retval;
const struct cred *cred = current_cred();
@@ -51822,7 +52058,7 @@ index a2d0e51..d46efb6 100644
/*
* We move the actual failure in case of RLIMIT_NPROC excess from
* set*uid() to execve() because too many poorly written programs
-@@ -1518,12 +1629,22 @@ static int do_execve_common(const char *filename,
+@@ -1518,12 +1637,22 @@ static int do_execve_common(const char *filename,
if (IS_ERR(file))
goto out_unmark;
@@ -51845,7 +52081,7 @@ index a2d0e51..d46efb6 100644
retval = bprm_mm_init(bprm);
if (retval)
goto out_file;
-@@ -1540,24 +1661,70 @@ static int do_execve_common(const char *filename,
+@@ -1540,24 +1669,70 @@ static int do_execve_common(const char *filename,
if (retval < 0)
goto out;
@@ -51920,7 +52156,7 @@ index a2d0e51..d46efb6 100644
current->fs->in_exec = 0;
current->in_execve = 0;
acct_update_integrals(current);
-@@ -1566,6 +1733,14 @@ static int do_execve_common(const char *filename,
+@@ -1566,6 +1741,14 @@ static int do_execve_common(const char *filename,
put_files_struct(displaced);
return retval;
@@ -51935,7 +52171,7 @@ index a2d0e51..d46efb6 100644
out:
if (bprm->mm) {
acct_arg_size(bprm, 0);
-@@ -1639,7 +1814,7 @@ static int expand_corename(struct core_name *cn)
+@@ -1639,7 +1822,7 @@ static int expand_corename(struct core_name *cn)
{
char *old_corename = cn->corename;
@@ -51944,7 +52180,7 @@ index a2d0e51..d46efb6 100644
cn->corename = krealloc(old_corename, cn->size, GFP_KERNEL);
if (!cn->corename) {
-@@ -1736,7 +1911,7 @@ static int format_corename(struct core_name *cn, long signr)
+@@ -1736,7 +1919,7 @@ static int format_corename(struct core_name *cn, long signr)
int pid_in_pattern = 0;
int err = 0;
@@ -51953,7 +52189,7 @@ index a2d0e51..d46efb6 100644
cn->corename = kmalloc(cn->size, GFP_KERNEL);
cn->used = 0;
-@@ -1833,6 +2008,284 @@ out:
+@@ -1833,6 +2016,284 @@ out:
return ispipe;
}
@@ -52238,7 +52474,7 @@ index a2d0e51..d46efb6 100644
static int zap_process(struct task_struct *start, int exit_code)
{
struct task_struct *t;
-@@ -2006,17 +2459,17 @@ static void coredump_finish(struct mm_struct *mm)
+@@ -2006,17 +2467,17 @@ static void coredump_finish(struct mm_struct *mm)
void set_dumpable(struct mm_struct *mm, int value)
{
switch (value) {
@@ -52259,7 +52495,7 @@ index a2d0e51..d46efb6 100644
set_bit(MMF_DUMP_SECURELY, &mm->flags);
smp_wmb();
set_bit(MMF_DUMPABLE, &mm->flags);
-@@ -2029,7 +2482,7 @@ static int __get_dumpable(unsigned long mm_flags)
+@@ -2029,7 +2490,7 @@ static int __get_dumpable(unsigned long mm_flags)
int ret;
ret = mm_flags & MMF_DUMPABLE_MASK;
@@ -52268,7 +52504,7 @@ index a2d0e51..d46efb6 100644
}
int get_dumpable(struct mm_struct *mm)
-@@ -2044,17 +2497,17 @@ static void wait_for_dump_helpers(struct file *file)
+@@ -2044,17 +2505,17 @@ static void wait_for_dump_helpers(struct file *file)
pipe = file->f_path.dentry->d_inode->i_pipe;
pipe_lock(pipe);
@@ -52291,7 +52527,7 @@ index a2d0e51..d46efb6 100644
pipe_unlock(pipe);
}
-@@ -2115,7 +2568,8 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
+@@ -2115,7 +2576,8 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
int retval = 0;
int flag = 0;
int ispipe;
@@ -52301,7 +52537,7 @@ index a2d0e51..d46efb6 100644
struct coredump_params cprm = {
.signr = signr,
.regs = regs,
-@@ -2130,6 +2584,9 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
+@@ -2130,6 +2592,9 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
audit_core_dumps(signr);
@@ -52311,7 +52547,7 @@ index a2d0e51..d46efb6 100644
binfmt = mm->binfmt;
if (!binfmt || !binfmt->core_dump)
goto fail;
-@@ -2140,14 +2597,16 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
+@@ -2140,14 +2605,16 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
if (!cred)
goto fail;
/*
@@ -52332,7 +52568,7 @@ index a2d0e51..d46efb6 100644
}
retval = coredump_wait(exit_code, &core_state);
-@@ -2197,7 +2656,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
+@@ -2197,7 +2664,7 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
}
cprm.limit = RLIM_INFINITY;
@@ -52341,7 +52577,7 @@ index a2d0e51..d46efb6 100644
if (core_pipe_limit && (core_pipe_limit < dump_count)) {
printk(KERN_WARNING "Pid %d(%s) over core_pipe_limit\n",
task_tgid_vnr(current), current->comm);
-@@ -2224,9 +2683,19 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
+@@ -2224,9 +2691,19 @@ void do_coredump(long signr, int exit_code, struct pt_regs *regs)
} else {
struct inode *inode;
@@ -52361,7 +52597,7 @@ index a2d0e51..d46efb6 100644
cprm.file = filp_open(cn.corename,
O_CREAT | 2 | O_NOFOLLOW | O_LARGEFILE | flag,
0600);
-@@ -2267,7 +2736,7 @@ close_fail:
+@@ -2267,7 +2744,7 @@ close_fail:
filp_close(cprm.file, NULL);
fail_dropcount:
if (ispipe)
@@ -52370,7 +52606,7 @@ index a2d0e51..d46efb6 100644
fail_unlock:
kfree(cn.corename);
fail_corename:
-@@ -2286,7 +2755,7 @@ fail:
+@@ -2286,7 +2763,7 @@ fail:
*/
int dump_write(struct file *file, const void *addr, int nr)
{
@@ -70045,6 +70281,93 @@ index bc00876..9aa9b1f 100644
#endif /* CONFIG_MMU */
#endif /* !__ASSEMBLY__ */
+diff --git a/include/asm-generic/siginfo.h b/include/asm-generic/siginfo.h
+index 0dd4e87..af5d035 100644
+--- a/include/asm-generic/siginfo.h
++++ b/include/asm-generic/siginfo.h
+@@ -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 user 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
+
+@@ -232,6 +248,12 @@ typedef struct siginfo {
+ #define NSIGPOLL 6
+
+ /*
++ * SIGSYS si_codes
++ */
++#define SYS_SECCOMP (__SI_SYS|1) /* seccomp triggered */
++#define NSIGSYS 1
++
++/*
+ * sigevent definitions
+ *
+ * It seems likely that SIGEV_THREAD will have to be handled from
+diff --git a/include/asm-generic/syscall.h b/include/asm-generic/syscall.h
+index 5c122ae..a2c13dc 100644
+--- a/include/asm-generic/syscall.h
++++ b/include/asm-generic/syscall.h
+@@ -142,4 +142,18 @@ void syscall_set_arguments(struct task_struct *task, struct pt_regs *regs,
+ unsigned int i, unsigned int n,
+ const unsigned long *args);
+
++/**
++ * syscall_get_arch - return the AUDIT_ARCH for the current system call
++ * @task: task of interest, must be in system call entry tracing
++ * @regs: task_pt_regs() of @task
++ *
++ * Returns the AUDIT_ARCH_* based on the system call convention in use.
++ *
++ * It's only valid to call this when @task is stopped on entry to a system
++ * call, due to %TIF_SYSCALL_TRACE, %TIF_SYSCALL_AUDIT, or %TIF_SECCOMP.
++ *
++ * Note, at present this function is only required with
++ * CONFIG_HAVE_ARCH_SECCOMP_FILTER.
++ */
++int syscall_get_arch(struct task_struct *task, struct pt_regs *regs);
+ #endif /* _ASM_SYSCALL_H */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index b5e2e4c..6a5373e 100644
--- a/include/asm-generic/vmlinux.lds.h
@@ -70207,6 +70530,18 @@ index 26c1f78..6722682 100644
/**
* struct ttm_mem_global - Global memory accounting structure.
+diff --git a/include/linux/Kbuild b/include/linux/Kbuild
+index a3ce901..fd50c75 100644
+--- a/include/linux/Kbuild
++++ b/include/linux/Kbuild
+@@ -329,6 +329,7 @@ header-y += scc.h
+ header-y += sched.h
+ header-y += screen_info.h
+ header-y += sdla.h
++header-y += seccomp.h
+ header-y += securebits.h
+ header-y += selinux_netlink.h
+ header-y += sem.h
diff --git a/include/linux/a.out.h b/include/linux/a.out.h
index e86dfca..40cc55f 100644
--- a/include/linux/a.out.h
@@ -70248,6 +70583,40 @@ index 49a83ca..d0a847e 100644
struct atmphy_ops {
int (*start)(struct atm_dev *dev);
+diff --git a/include/linux/audit.h b/include/linux/audit.h
+index 2f81c6f..225b4e4 100644
+--- a/include/linux/audit.h
++++ b/include/linux/audit.h
+@@ -430,6 +430,7 @@ extern void audit_putname(const char *name);
+ extern void __audit_inode(const char *name, const struct dentry *dentry);
+ extern void __audit_inode_child(const struct dentry *dentry,
+ const struct inode *parent);
++extern void __audit_seccomp(unsigned long syscall, long signr, int code);
+ extern void __audit_ptrace(struct task_struct *t);
+
+ static inline int audit_dummy_context(void)
+@@ -453,6 +454,12 @@ static inline void audit_inode_child(const struct dentry *dentry,
+ }
+ void audit_core_dumps(long signr);
+
++static inline void audit_seccomp(unsigned long syscall, long signr, int code)
++{
++ if (unlikely(!audit_dummy_context()))
++ __audit_seccomp(syscall, signr, code);
++}
++
+ static inline void audit_ptrace(struct task_struct *t)
+ {
+ if (unlikely(!audit_dummy_context()))
+@@ -558,6 +565,8 @@ extern int audit_signals;
+ #define audit_inode(n,d) do { (void)(d); } while (0)
+ #define audit_inode_child(i,p) do { ; } while (0)
+ #define audit_core_dumps(i) do { ; } while (0)
++#define audit_seccomp(i,s,c) do { ; } while (0)
++#define __audit_seccomp(i,s,c) do { ; } while (0)
+ #define auditsc_get_stamp(c,t,s) (0)
+ #define audit_get_loginuid(t) (-1)
+ #define audit_get_sessionid(t) (-1)
diff --git a/include/linux/binfmts.h b/include/linux/binfmts.h
index acd8d4b..f2defe2 100644
--- a/include/linux/binfmts.h
@@ -71053,18 +71422,38 @@ index 82163c4..c4b3b50 100644
extern struct kmem_cache *files_cachep;
diff --git a/include/linux/filter.h b/include/linux/filter.h
-index 8eeb205..d59bfa2 100644
+index 8eeb205..13d571c 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
-@@ -134,6 +134,7 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */
+@@ -10,6 +10,7 @@
+ #ifdef __KERNEL__
+ #include <linux/atomic.h>
++#include <linux/compat.h>
+ #endif
+
+ /*
+@@ -132,8 +133,19 @@ struct sock_fprog { /* Required for SO_ATTACH_FILTER. */
+
+ #ifdef __KERNEL__
+
++#ifdef CONFIG_COMPAT
++/*
++ * A struct sock_filter is architecture independent.
++ */
++struct compat_sock_fprog {
++ u16 len;
++ compat_uptr_t filter; /* struct sock_filter * */
++};
++#endif
++
struct sk_buff;
struct sock;
+struct bpf_jit_work;
struct sk_filter
{
-@@ -141,6 +142,9 @@ struct sk_filter
+@@ -141,6 +153,9 @@ struct sk_filter
unsigned int len; /* Number of filter blocks */
unsigned int (*bpf_func)(const struct sk_buff *skb,
const struct sock_filter *filter);
@@ -71074,6 +71463,14 @@ index 8eeb205..d59bfa2 100644
struct rcu_head rcu;
struct sock_filter insns[0];
};
+@@ -228,6 +243,7 @@ enum {
+ BPF_S_ANC_HATYPE,
+ BPF_S_ANC_RXHASH,
+ BPF_S_ANC_CPU,
++ BPF_S_ANC_SECCOMP_LD_W,
+ };
+
+ #endif /* __KERNEL__ */
diff --git a/include/linux/fs.h b/include/linux/fs.h
index a276817..ba31358 100644
--- a/include/linux/fs.h
@@ -73967,6 +74364,30 @@ index b8d4ddd..bb59d8b 100644
/*
* The return value from decompress routine is the length of the
+diff --git a/include/linux/prctl.h b/include/linux/prctl.h
+index a3baeb2..b527252 100644
+--- a/include/linux/prctl.h
++++ b/include/linux/prctl.h
+@@ -102,4 +102,19 @@
+
+ #define PR_MCE_KILL_GET 34
+
++/*
++ * If no_new_privs is set, then operations that grant new privileges (i.e.
++ * execve) will either fail or not grant them. This affects suid/sgid,
++ * file capabilities, and LSMs.
++ *
++ * Operations that merely manipulate or drop existing privileges (setresuid,
++ * capset, etc.) will still work. Drop those privileges if you want them gone.
++ *
++ * Changing LSM security domain is considered a new privilege. So, for example,
++ * asking selinux for a specific new context (e.g. with runcon) will result
++ * in execve returning -EPERM.
++ */
++#define PR_SET_NO_NEW_PRIVS 38
++#define PR_GET_NO_NEW_PRIVS 39
++
+ #endif /* _LINUX_PRCTL_H */
diff --git a/include/linux/printk.h b/include/linux/printk.h
index f0e22f7..82dd544 100644
--- a/include/linux/printk.h
@@ -74022,10 +74443,40 @@ index 643b96c..9544c71 100644
extern const struct proc_ns_operations utsns_operations;
extern const struct proc_ns_operations ipcns_operations;
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
-index 800f113..12c82ec 100644
+index 800f113..13b3715 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
-@@ -129,10 +129,12 @@ extern void __ptrace_unlink(struct task_struct *child);
+@@ -62,8 +62,9 @@
+ #define PTRACE_O_TRACEEXEC 0x00000010
+ #define PTRACE_O_TRACEVFORKDONE 0x00000020
+ #define PTRACE_O_TRACEEXIT 0x00000040
++#define PTRACE_O_TRACESECCOMP 0x00000080
+
+-#define PTRACE_O_MASK 0x0000007f
++#define PTRACE_O_MASK 0x000000ff
+
+ /* Wait extended result codes for the above trace options. */
+ #define PTRACE_EVENT_FORK 1
+@@ -73,6 +74,7 @@
+ #define PTRACE_EVENT_VFORK_DONE 5
+ #define PTRACE_EVENT_EXIT 6
+ #define PTRACE_EVENT_STOP 7
++#define PTRACE_EVENT_SECCOMP 8
+
+ #include <asm/ptrace.h>
+
+@@ -101,8 +103,9 @@
+ #define PT_TRACE_EXEC PT_EVENT_FLAG(PTRACE_EVENT_EXEC)
+ #define PT_TRACE_VFORK_DONE PT_EVENT_FLAG(PTRACE_EVENT_VFORK_DONE)
+ #define PT_TRACE_EXIT PT_EVENT_FLAG(PTRACE_EVENT_EXIT)
++#define PT_TRACE_SECCOMP PT_EVENT_FLAG(PTRACE_EVENT_SECCOMP)
+
+-#define PT_TRACE_MASK 0x000003f4
++#define PT_TRACE_MASK 0x00000bf4
+
+ /* single stepping state bits (used on ARM and PA-RISC) */
+ #define PT_SINGLESTEP_BIT 31
+@@ -129,10 +132,12 @@ extern void __ptrace_unlink(struct task_struct *child);
extern void exit_ptrace(struct task_struct *tracer);
#define PTRACE_MODE_READ 1
#define PTRACE_MODE_ATTACH 2
@@ -74040,7 +74491,7 @@ index 800f113..12c82ec 100644
static inline int ptrace_reparented(struct task_struct *child)
{
-@@ -197,9 +199,10 @@ static inline void ptrace_event(int event, unsigned long message)
+@@ -197,9 +202,10 @@ static inline void ptrace_event(int event, unsigned long message)
if (unlikely(ptrace_event_enabled(current, event))) {
current->ptrace_message = message;
ptrace_notify((event << 8) | SIGTRAP);
@@ -74267,7 +74718,7 @@ index 2148b12..519b820 100644
static inline void anon_vma_merge(struct vm_area_struct *vma,
diff --git a/include/linux/sched.h b/include/linux/sched.h
-index 8204898..76f518d 100644
+index 8204898..070429f 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -101,6 +101,7 @@ struct bio_list;
@@ -74365,7 +74816,16 @@ index 8204898..76f518d 100644
struct load_weight {
unsigned long weight, inv_weight;
-@@ -1341,8 +1379,8 @@ struct task_struct {
+@@ -1301,6 +1339,8 @@ struct task_struct {
+ * execve */
+ unsigned in_iowait:1;
+
++ /* task may not gain privileges */
++ unsigned no_new_privs:1;
+
+ /* Revert to default priority/policy when forking */
+ unsigned sched_reset_on_fork:1;
+@@ -1341,8 +1381,8 @@ struct task_struct {
struct list_head thread_group;
struct completion *vfork_done; /* for vfork() */
@@ -74376,7 +74836,7 @@ index 8204898..76f518d 100644
cputime_t utime, stime, utimescaled, stimescaled;
cputime_t gtime;
-@@ -1358,13 +1396,6 @@ struct task_struct {
+@@ -1358,13 +1398,6 @@ struct task_struct {
struct task_cputime cputime_expires;
struct list_head cpu_timers[3];
@@ -74390,7 +74850,7 @@ index 8204898..76f518d 100644
char comm[TASK_COMM_LEN]; /* executable name excluding path
- access with [gs]et_task_comm (which lock
it with task_lock())
-@@ -1381,8 +1412,16 @@ struct task_struct {
+@@ -1381,8 +1414,16 @@ struct task_struct {
#endif
/* CPU-specific state of this task */
struct thread_struct thread;
@@ -74407,7 +74867,16 @@ index 8204898..76f518d 100644
/* open file information */
struct files_struct *files;
/* namespaces */
-@@ -1429,6 +1468,11 @@ struct task_struct {
+@@ -1405,7 +1446,7 @@ struct task_struct {
+ uid_t loginuid;
+ unsigned int sessionid;
+ #endif
+- seccomp_t seccomp;
++ struct seccomp seccomp;
+
+ /* Thread group tracking */
+ u32 parent_exec_id;
+@@ -1429,6 +1470,11 @@ struct task_struct {
struct rt_mutex_waiter *pi_blocked_on;
#endif
@@ -74419,7 +74888,7 @@ index 8204898..76f518d 100644
#ifdef CONFIG_DEBUG_MUTEXES
/* mutex deadlock detection */
struct mutex_waiter *blocked_on;
-@@ -1544,6 +1588,28 @@ struct task_struct {
+@@ -1544,6 +1590,28 @@ struct task_struct {
unsigned long default_timer_slack_ns;
struct list_head *scm_work_list;
@@ -74448,7 +74917,7 @@ index 8204898..76f518d 100644
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
/* Index of current stored address in ret_stack */
int curr_ret_stack;
-@@ -1578,6 +1644,52 @@ struct task_struct {
+@@ -1578,6 +1646,52 @@ struct task_struct {
#endif
};
@@ -74501,7 +74970,7 @@ index 8204898..76f518d 100644
/* Future-safe accessor for struct task_struct's cpus_allowed. */
#define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed)
-@@ -2093,7 +2205,9 @@ void yield(void);
+@@ -2093,7 +2207,9 @@ void yield(void);
extern struct exec_domain default_exec_domain;
union thread_union {
@@ -74511,7 +74980,7 @@ index 8204898..76f518d 100644
unsigned long stack[THREAD_SIZE/sizeof(long)];
};
-@@ -2126,6 +2240,7 @@ extern struct pid_namespace init_pid_ns;
+@@ -2126,6 +2242,7 @@ extern struct pid_namespace init_pid_ns;
*/
extern struct task_struct *find_task_by_vpid(pid_t nr);
@@ -74519,7 +74988,7 @@ index 8204898..76f518d 100644
extern struct task_struct *find_task_by_pid_ns(pid_t nr,
struct pid_namespace *ns);
-@@ -2247,6 +2362,12 @@ static inline void mmdrop(struct mm_struct * mm)
+@@ -2247,6 +2364,12 @@ static inline void mmdrop(struct mm_struct * mm)
extern void mmput(struct mm_struct *);
/* Grab a reference to a task's mm, if it is not already going away */
extern struct mm_struct *get_task_mm(struct task_struct *task);
@@ -74532,7 +75001,7 @@ index 8204898..76f518d 100644
/* Remove the current tasks stale references to the old mm_struct */
extern void mm_release(struct task_struct *, struct mm_struct *);
/* Allocate a new mm structure and copy contents from tsk->mm */
-@@ -2263,7 +2384,7 @@ extern void __cleanup_sighand(struct sighand_struct *);
+@@ -2263,7 +2386,7 @@ extern void __cleanup_sighand(struct sighand_struct *);
extern void exit_itimers(struct signal_struct *);
extern void flush_itimer_signals(void);
@@ -74541,7 +75010,7 @@ index 8204898..76f518d 100644
extern void daemonize(const char *, ...);
extern int allow_signal(int);
-@@ -2428,9 +2549,9 @@ static inline unsigned long *end_of_stack(struct task_struct *p)
+@@ -2428,9 +2551,9 @@ static inline unsigned long *end_of_stack(struct task_struct *p)
#endif
@@ -74567,8 +75036,154 @@ index 899fbb4..1cb4138 100644
} __attribute__((packed));
#define VIDEO_TYPE_MDA 0x10 /* Monochrome Text Display */
+diff --git a/include/linux/seccomp.h b/include/linux/seccomp.h
+index cc7a4e9..306733e 100644
+--- a/include/linux/seccomp.h
++++ b/include/linux/seccomp.h
+@@ -1,25 +1,89 @@
+ #ifndef _LINUX_SECCOMP_H
+ #define _LINUX_SECCOMP_H
+
++#include <linux/compiler.h>
++#include <linux/types.h>
+
++
++/* Valid values for seccomp.mode and prctl(PR_SET_SECCOMP, <mode>) */
++#define SECCOMP_MODE_DISABLED 0 /* seccomp is not in use. */
++#define SECCOMP_MODE_STRICT 1 /* uses hard-coded filter. */
++#define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */
++
++/*
++ * All BPF programs must return a 32-bit value.
++ * The bottom 16-bits are for optional return data.
++ * The upper 16-bits are ordered from least permissive values to most.
++ *
++ * The ordering ensures that a min_t() over composed return values always
++ * selects the least permissive choice.
++ */
++#define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */
++#define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */
++#define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */
++#define SECCOMP_RET_TRACE 0x7ff00000U /* pass to a tracer or disallow */
++#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */
++
++/* Masks for the return value sections. */
++#define SECCOMP_RET_ACTION 0xffff0000U
++#define SECCOMP_RET_DATA 0x0000ffffU
++
++/**
++ * struct seccomp_data - the format the BPF program executes over.
++ * @nr: the system call number
++ * @arch: indicates system call convention as an AUDIT_ARCH_* value
++ * as defined in <linux/audit.h>.
++ * @instruction_pointer: at the time of the system call.
++ * @args: up to 6 system call arguments always stored as 64-bit values
++ * regardless of the architecture.
++ */
++struct seccomp_data {
++ int nr;
++ __u32 arch;
++ __u64 instruction_pointer;
++ __u64 args[6];
++};
++
++#ifdef __KERNEL__
+ #ifdef CONFIG_SECCOMP
+
+ #include <linux/thread_info.h>
+ #include <asm/seccomp.h>
+
+-typedef struct { int mode; } seccomp_t;
++struct seccomp_filter;
++/**
++ * struct seccomp - the state of a seccomp'ed process
++ *
++ * @mode: indicates one of the valid values above for controlled
++ * system calls available to a process.
++ * @filter: The metadata and ruleset for determining what system calls
++ * are allowed for a task.
++ *
++ * @filter must only be accessed from the context of current as there
++ * is no locking.
++ */
++struct seccomp {
++ int mode;
++ struct seccomp_filter *filter;
++};
+
+-extern void __secure_computing(int);
+-static inline void secure_computing(int this_syscall)
++/*
++ * Direct callers to __secure_computing should be updated as
++ * CONFIG_HAVE_ARCH_SECCOMP_FILTER propagates.
++ */
++extern void __secure_computing(int) __deprecated;
++extern int __secure_computing_int(int);
++static inline int secure_computing(int this_syscall)
+ {
+ if (unlikely(test_thread_flag(TIF_SECCOMP)))
+- __secure_computing(this_syscall);
++ return __secure_computing_int(this_syscall);
++ return 0;
+ }
+
+ extern long prctl_get_seccomp(void);
+-extern long prctl_set_seccomp(unsigned long);
++extern long prctl_set_seccomp(unsigned long, char __user *);
+
+-static inline int seccomp_mode(seccomp_t *s)
++static inline int seccomp_mode(struct seccomp *s)
+ {
+ return s->mode;
+ }
+@@ -28,25 +92,40 @@ static inline int seccomp_mode(seccomp_t *s)
+
+ #include <linux/errno.h>
+
+-typedef struct { } seccomp_t;
++struct seccomp { };
++struct seccomp_filter { };
+
+-#define secure_computing(x) do { } while (0)
++#define secure_computing(x) 0
+
+ static inline long prctl_get_seccomp(void)
+ {
+ return -EINVAL;
+ }
+
+-static inline long prctl_set_seccomp(unsigned long arg2)
++static inline long prctl_set_seccomp(unsigned long arg2, char __user *arg3)
+ {
+ return -EINVAL;
+ }
+
+-static inline int seccomp_mode(seccomp_t *s)
++static inline int seccomp_mode(struct seccomp *s)
+ {
+ return 0;
+ }
+-
+ #endif /* CONFIG_SECCOMP */
+
++#ifdef CONFIG_SECCOMP_FILTER
++extern void put_seccomp_filter(struct task_struct *tsk);
++extern void get_seccomp_filter(struct task_struct *tsk);
++extern u32 seccomp_bpf_load(int off);
++#else /* CONFIG_SECCOMP_FILTER */
++static inline void put_seccomp_filter(struct task_struct *tsk)
++{
++ return;
++}
++static inline void get_seccomp_filter(struct task_struct *tsk)
++{
++ return;
++}
++#endif /* CONFIG_SECCOMP_FILTER */
++#endif /* __KERNEL__ */
+ #endif /* _LINUX_SECCOMP_H */
diff --git a/include/linux/security.h b/include/linux/security.h
-index e8c619d..ff41b06 100644
+index e8c619d..99d0f1f 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -37,6 +37,7 @@
@@ -74588,7 +75203,15 @@ index e8c619d..ff41b06 100644
#ifdef CONFIG_MMU
extern unsigned long mmap_min_addr;
extern unsigned long dac_mmap_min_addr;
-@@ -1676,6 +1675,8 @@ int security_capset(struct cred *new, const struct cred *old,
+@@ -130,6 +129,7 @@ struct request_sock;
+ #define LSM_UNSAFE_SHARE 1
+ #define LSM_UNSAFE_PTRACE 2
+ #define LSM_UNSAFE_PTRACE_CAP 4
++#define LSM_UNSAFE_NO_NEW_PRIVS 8
+
+ #ifdef CONFIG_MMU
+ /*
+@@ -1676,6 +1676,8 @@ int security_capset(struct cred *new, const struct cred *old,
const kernel_cap_t *permitted);
int security_capable(struct user_namespace *ns, const struct cred *cred,
int cap);
@@ -74597,7 +75220,7 @@ index e8c619d..ff41b06 100644
int security_real_capable(struct task_struct *tsk, struct user_namespace *ns,
int cap);
int security_real_capable_noaudit(struct task_struct *tsk,
-@@ -1880,6 +1881,12 @@ static inline int security_capable(struct user_namespace *ns,
+@@ -1880,6 +1882,12 @@ static inline int security_capable(struct user_namespace *ns,
return cap_capable(current, cred, ns, cap, SECURITY_CAP_AUDIT);
}
@@ -77495,10 +78118,18 @@ index d4bc594..efa193f 100644
return;
}
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
-index 47b7fc1..c003c33 100644
+index 47b7fc1..9af0605 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
-@@ -1166,8 +1166,8 @@ static void audit_log_execve_info(struct audit_context *context,
+@@ -67,6 +67,7 @@
+ #include <linux/syscalls.h>
+ #include <linux/capability.h>
+ #include <linux/fs_struct.h>
++#include <linux/compat.h>
+
+ #include "audit.h"
+
+@@ -1166,8 +1167,8 @@ static void audit_log_execve_info(struct audit_context *context,
struct audit_buffer **ab,
struct audit_aux_data_execve *axi)
{
@@ -77509,7 +78140,7 @@ index 47b7fc1..c003c33 100644
const char __user *p;
char *buf;
-@@ -2118,7 +2118,7 @@ int auditsc_get_stamp(struct audit_context *ctx,
+@@ -2118,7 +2119,7 @@ int auditsc_get_stamp(struct audit_context *ctx,
}
/* global counter which is incremented every time something logs in */
@@ -77518,7 +78149,7 @@ index 47b7fc1..c003c33 100644
/**
* audit_set_loginuid - set a task's audit_context loginuid
-@@ -2131,7 +2131,7 @@ static atomic_t session_id = ATOMIC_INIT(0);
+@@ -2131,7 +2132,7 @@ static atomic_t session_id = ATOMIC_INIT(0);
*/
int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
{
@@ -77527,6 +78158,97 @@ index 47b7fc1..c003c33 100644
struct audit_context *context = task->audit_context;
if (context && context->in_syscall) {
+@@ -2499,46 +2500,59 @@ void __audit_mmap_fd(int fd, int flags)
+ context->type = AUDIT_MMAP;
+ }
+
+-/**
+- * audit_core_dumps - record information about processes that end abnormally
+- * @signr: signal value
+- *
+- * If a process ends with a core dump, something fishy is going on and we
+- * should record the event for investigation.
+- */
+-void audit_core_dumps(long signr)
++static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr)
+ {
+- struct audit_buffer *ab;
+- u32 sid;
+- uid_t auid = audit_get_loginuid(current), uid;
++ uid_t auid, uid;
+ gid_t gid;
+- unsigned int sessionid = audit_get_sessionid(current);
++ unsigned int sessionid;
+
+- if (!audit_enabled)
+- return;
+-
+- if (signr == SIGQUIT) /* don't care for those */
+- return;
+-
+- ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
++ auid = audit_get_loginuid(current);
++ sessionid = audit_get_sessionid(current);
+ current_uid_gid(&uid, &gid);
++
+ audit_log_format(ab, "auid=%u uid=%u gid=%u ses=%u",
+ auid, uid, gid, sessionid);
+- security_task_getsecid(current, &sid);
+- if (sid) {
+- char *ctx = NULL;
+- u32 len;
+-
+- if (security_secid_to_secctx(sid, &ctx, &len))
+- audit_log_format(ab, " ssid=%u", sid);
+- else {
+- audit_log_format(ab, " subj=%s", ctx);
+- security_release_secctx(ctx, len);
+- }
+- }
++ audit_log_task_context(ab);
+ audit_log_format(ab, " pid=%d comm=", current->pid);
+ audit_log_untrustedstring(ab, current->comm);
++ audit_log_format(ab, " reason=");
++ audit_log_string(ab, reason);
+ audit_log_format(ab, " sig=%ld", signr);
++}
++/**
++ * audit_core_dumps - record information about processes that end abnormally
++ * @signr: signal value
++ *
++ * If a process ends with a core dump, something fishy is going on and we
++ * should record the event for investigation.
++ */
++void audit_core_dumps(long signr)
++{
++ struct audit_buffer *ab;
++
++ if (!audit_enabled)
++ return;
++
++ if (signr == SIGQUIT) /* don't care for those */
++ return;
++
++ ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
++ audit_log_abend(ab, "memory violation", signr);
++ audit_log_end(ab);
++}
++
++void __audit_seccomp(unsigned long syscall, long signr, int code)
++{
++ struct audit_buffer *ab;
++
++ ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
++ audit_log_abend(ab, "seccomp", signr);
++ audit_log_format(ab, " syscall=%ld", syscall);
++#ifdef CONFIG_COMPAT
++ audit_log_format(ab, " compat=%d", is_compat_task());
++#endif
++ audit_log_format(ab, " ip=0x%lx", KSTK_EIP(current));
++ audit_log_format(ab, " code=0x%x", code);
+ audit_log_end(ab);
+ }
+
diff --git a/kernel/capability.c b/kernel/capability.c
index b463871..59495fd 100644
--- a/kernel/capability.c
@@ -78224,10 +78946,26 @@ index 234e152..0ae0243 100644
{
struct signal_struct *sig = current->signal;
diff --git a/kernel/fork.c b/kernel/fork.c
-index ce0c182..360568a 100644
+index ce0c182..c6ec99a 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
-@@ -270,19 +270,24 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
+@@ -34,6 +34,7 @@
+ #include <linux/cgroup.h>
+ #include <linux/security.h>
+ #include <linux/hugetlb.h>
++#include <linux/seccomp.h>
+ #include <linux/swap.h>
+ #include <linux/syscalls.h>
+ #include <linux/jiffies.h>
+@@ -168,6 +169,7 @@ void free_task(struct task_struct *tsk)
+ free_thread_info(tsk->stack);
+ rt_mutex_debug_task_free(tsk);
+ ftrace_graph_exit_task(tsk);
++ put_seccomp_filter(tsk);
+ free_task_struct(tsk);
+ }
+ EXPORT_SYMBOL(free_task);
+@@ -270,19 +272,24 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
}
err = arch_dup_task_struct(tsk, orig);
@@ -78256,7 +78994,7 @@ index ce0c182..360568a 100644
#endif
/*
-@@ -306,13 +311,78 @@ out:
+@@ -306,13 +313,78 @@ out:
}
#ifdef CONFIG_MMU
@@ -78339,7 +79077,7 @@ index ce0c182..360568a 100644
down_write(&oldmm->mmap_sem);
flush_cache_dup_mm(oldmm);
-@@ -324,8 +394,8 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
+@@ -324,8 +396,8 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
mm->locked_vm = 0;
mm->mmap = NULL;
mm->mmap_cache = NULL;
@@ -78350,7 +79088,7 @@ index ce0c182..360568a 100644
mm->map_count = 0;
cpumask_clear(mm_cpumask(mm));
mm->mm_rb = RB_ROOT;
-@@ -341,63 +411,16 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
+@@ -341,63 +413,16 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
prev = NULL;
for (mpnt = oldmm->mmap; mpnt; mpnt = mpnt->vm_next) {
@@ -78419,7 +79157,7 @@ index ce0c182..360568a 100644
/*
* Link in the new vma and copy the page table entries.
-@@ -420,6 +443,31 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
+@@ -420,6 +445,31 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
if (retval)
goto out;
}
@@ -78451,7 +79189,7 @@ index ce0c182..360568a 100644
/* a new mm has just been created */
arch_dup_mmap(oldmm, mm);
retval = 0;
-@@ -428,14 +476,6 @@ out:
+@@ -428,14 +478,6 @@ out:
flush_tlb_mm(oldmm);
up_write(&oldmm->mmap_sem);
return retval;
@@ -78466,7 +79204,7 @@ index ce0c182..360568a 100644
}
static inline int mm_alloc_pgd(struct mm_struct *mm)
-@@ -647,6 +687,26 @@ struct mm_struct *get_task_mm(struct task_struct *task)
+@@ -647,6 +689,26 @@ struct mm_struct *get_task_mm(struct task_struct *task)
}
EXPORT_SYMBOL_GPL(get_task_mm);
@@ -78493,7 +79231,7 @@ index ce0c182..360568a 100644
/* Please note the differences between mmput and mm_release.
* mmput is called whenever we stop holding onto a mm_struct,
* error success whatever.
-@@ -832,13 +892,20 @@ static int copy_fs(unsigned long clone_flags, struct task_struct *tsk)
+@@ -832,13 +894,20 @@ static int copy_fs(unsigned long clone_flags, struct task_struct *tsk)
spin_unlock(&fs->lock);
return -EAGAIN;
}
@@ -78515,7 +79253,7 @@ index ce0c182..360568a 100644
return 0;
}
-@@ -1047,7 +1114,7 @@ static void posix_cpu_timers_init(struct task_struct *tsk)
+@@ -1047,7 +1116,7 @@ static void posix_cpu_timers_init(struct task_struct *tsk)
* parts of the process environment (as per the clone
* flags). The actual kick-off is left to the caller.
*/
@@ -78524,7 +79262,15 @@ index ce0c182..360568a 100644
unsigned long stack_start,
struct pt_regs *regs,
unsigned long stack_size,
-@@ -1104,10 +1171,13 @@ static struct task_struct *copy_process(unsigned long clone_flags,
+@@ -1096,6 +1165,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
+ goto fork_out;
+
+ ftrace_graph_init_task(p);
++ get_seccomp_filter(p);
+
+ rt_mutex_init_task(p);
+
+@@ -1104,10 +1174,13 @@ static struct task_struct *copy_process(unsigned long clone_flags,
DEBUG_LOCKS_WARN_ON(!p->softirqs_enabled);
#endif
retval = -EAGAIN;
@@ -78540,7 +79286,7 @@ index ce0c182..360568a 100644
goto bad_fork_free;
}
current->flags &= ~PF_NPROC_EXCEEDED;
-@@ -1341,6 +1411,11 @@ static struct task_struct *copy_process(unsigned long clone_flags,
+@@ -1341,6 +1414,11 @@ static struct task_struct *copy_process(unsigned long clone_flags,
goto bad_fork_free_pid;
}
@@ -78552,7 +79298,7 @@ index ce0c182..360568a 100644
if (clone_flags & CLONE_THREAD) {
current->signal->nr_threads++;
atomic_inc(&current->signal->live);
-@@ -1421,6 +1496,8 @@ bad_fork_cleanup_count:
+@@ -1421,6 +1499,8 @@ bad_fork_cleanup_count:
bad_fork_free:
free_task(p);
fork_out:
@@ -78561,7 +79307,7 @@ index ce0c182..360568a 100644
return ERR_PTR(retval);
}
-@@ -1507,6 +1584,7 @@ long do_fork(unsigned long clone_flags,
+@@ -1507,6 +1587,7 @@ long do_fork(unsigned long clone_flags,
p = copy_process(clone_flags, stack_start, regs, stack_size,
child_tidptr, NULL, trace);
@@ -78569,7 +79315,7 @@ index ce0c182..360568a 100644
/*
* Do this prior waking up the new thread - the thread pointer
* might get invalid after that point, if the thread exits quickly.
-@@ -1521,6 +1599,8 @@ long do_fork(unsigned long clone_flags,
+@@ -1521,6 +1602,8 @@ long do_fork(unsigned long clone_flags,
if (clone_flags & CLONE_PARENT_SETTID)
put_user(nr, parent_tidptr);
@@ -78578,7 +79324,7 @@ index ce0c182..360568a 100644
if (clone_flags & CLONE_VFORK) {
p->vfork_done = &vfork;
init_completion(&vfork);
-@@ -1591,7 +1671,7 @@ void __init proc_caches_init(void)
+@@ -1591,7 +1674,7 @@ void __init proc_caches_init(void)
mm_cachep = kmem_cache_create("mm_struct",
sizeof(struct mm_struct), ARCH_MIN_MMSTRUCT_ALIGN,
SLAB_HWCACHE_ALIGN|SLAB_PANIC|SLAB_NOTRACK, NULL);
@@ -78587,7 +79333,7 @@ index ce0c182..360568a 100644
mmap_init();
nsproxy_cache_init();
}
-@@ -1630,7 +1710,7 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp)
+@@ -1630,7 +1713,7 @@ static int unshare_fs(unsigned long unshare_flags, struct fs_struct **new_fsp)
return 0;
/* don't need lock here; in the worst case we'll do useless copy */
@@ -78596,7 +79342,7 @@ index ce0c182..360568a 100644
return 0;
*new_fsp = copy_fs_struct(fs);
-@@ -1719,7 +1799,8 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
+@@ -1719,7 +1802,8 @@ SYSCALL_DEFINE1(unshare, unsigned long, unshare_flags)
fs = current->fs;
spin_lock(&fs->lock);
current->fs = new_fs;
@@ -80543,7 +81289,7 @@ index 76b8e77..a2930e8 100644
}
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
-index 67fedad..32d32a04 100644
+index 67fedad..82362a6 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -211,7 +211,8 @@ int ptrace_check_attach(struct task_struct *child, bool ignore_state)
@@ -80627,7 +81373,17 @@ index 67fedad..32d32a04 100644
return -EFAULT;
copied += retval;
src += retval;
-@@ -719,7 +737,7 @@ int ptrace_request(struct task_struct *child, long request,
+@@ -582,6 +600,9 @@ static int ptrace_setoptions(struct task_struct *child, unsigned long data)
+ if (data & PTRACE_O_TRACEEXIT)
+ child->ptrace |= PT_TRACE_EXIT;
+
++ if (data & PTRACE_O_TRACESECCOMP)
++ child->ptrace |= PT_TRACE_SECCOMP;
++
+ return (data & ~PTRACE_O_MASK) ? -EINVAL : 0;
+ }
+
+@@ -719,7 +740,7 @@ int ptrace_request(struct task_struct *child, long request,
bool seized = child->ptrace & PT_SEIZED;
int ret = -EIO;
siginfo_t siginfo, *si;
@@ -80636,7 +81392,7 @@ index 67fedad..32d32a04 100644
unsigned long __user *datalp = datavp;
unsigned long flags;
-@@ -921,14 +939,21 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr,
+@@ -921,14 +942,21 @@ SYSCALL_DEFINE4(ptrace, long, request, long, pid, unsigned long, addr,
goto out;
}
@@ -80659,7 +81415,7 @@ index 67fedad..32d32a04 100644
goto out_put_task_struct;
}
-@@ -956,7 +981,7 @@ int generic_ptrace_peekdata(struct task_struct *tsk, unsigned long addr,
+@@ -956,7 +984,7 @@ int generic_ptrace_peekdata(struct task_struct *tsk, unsigned long addr,
copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0);
if (copied != sizeof(tmp))
return -EIO;
@@ -80668,7 +81424,7 @@ index 67fedad..32d32a04 100644
}
int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr,
-@@ -1050,7 +1075,7 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
+@@ -1050,7 +1078,7 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
}
asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
@@ -80677,7 +81433,7 @@ index 67fedad..32d32a04 100644
{
struct task_struct *child;
long ret;
-@@ -1066,14 +1091,21 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
+@@ -1066,14 +1094,21 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid,
goto out;
}
@@ -81428,8 +82184,513 @@ index c261da7..4e5221ad 100644
{
int this_cpu = smp_processor_id();
struct rq *this_rq = cpu_rq(this_cpu);
+diff --git a/kernel/seccomp.c b/kernel/seccomp.c
+index 57d4b13..bc84054 100644
+--- a/kernel/seccomp.c
++++ b/kernel/seccomp.c
+@@ -3,15 +3,353 @@
+ *
+ * Copyright 2004-2005 Andrea Arcangeli <andrea@cpushare.com>
+ *
+- * This defines a simple but solid secure-computing mode.
++ * Copyright (C) 2012 Google, Inc.
++ * Will Drewry <wad@chromium.org>
++ *
++ * This defines a simple but solid secure-computing facility.
++ *
++ * Mode 1 uses a fixed list of allowed system calls.
++ * Mode 2 allows user-defined system call filters in the form
++ * of Berkeley Packet Filters/Linux Socket Filters.
+ */
+
+-#include <linux/seccomp.h>
+-#include <linux/sched.h>
++#include <linux/atomic.h>
++#include <linux/audit.h>
+ #include <linux/compat.h>
++#include <linux/filter.h>
++#include <linux/ptrace.h>
++#include <linux/sched.h>
++#include <linux/seccomp.h>
++#include <linux/security.h>
++#include <linux/slab.h>
++#include <linux/uaccess.h>
++
++#ifdef CONFIG_HAVE_ARCH_SECCOMP_FILTER
++#include <asm/syscall.h>
++#endif
+
+ /* #define SECCOMP_DEBUG 1 */
+-#define NR_SECCOMP_MODES 1
++
++#ifdef CONFIG_SECCOMP_FILTER
++/**
++ * struct seccomp_filter - container for seccomp BPF programs
++ *
++ * @usage: reference count to manage the object liftime.
++ * get/put helpers should be used when accessing an instance
++ * outside of a lifetime-guarded section. In general, this
++ * is only needed for handling filters shared across tasks.
++ * @prev: points to a previously installed, or inherited, filter
++ * @len: the number of instructions in the program
++ * @insns: the BPF program instructions to evaluate
++ *
++ * seccomp_filter objects are organized in a tree linked via the @prev
++ * pointer. For any task, it appears to be a singly-linked list starting
++ * with current->seccomp.filter, the most recently attached or inherited filter.
++ * However, multiple filters may share a @prev node, by way of fork(), which
++ * results in a unidirectional tree existing in memory. This is similar to
++ * how namespaces work.
++ *
++ * seccomp_filter objects should never be modified after being attached
++ * to a task_struct (other than @usage).
++ */
++struct seccomp_filter {
++ atomic_t usage;
++ struct seccomp_filter *prev;
++ unsigned short len; /* Instruction count */
++ struct sock_filter insns[];
++};
++
++/* Limit any path through the tree to 256KB worth of instructions. */
++#define MAX_INSNS_PER_PATH ((1 << 18) / sizeof(struct sock_filter))
++
++/**
++ * get_u32 - returns a u32 offset into data
++ * @data: a unsigned 64 bit value
++ * @index: 0 or 1 to return the first or second 32-bits
++ *
++ * This inline exists to hide the length of unsigned long.
++ * If a 32-bit unsigned long is passed in, it will be extended
++ * and the top 32-bits will be 0. If it is a 64-bit unsigned
++ * long, then whatever data is resident will be properly returned.
++ */
++static inline u32 get_u32(u64 data, int index)
++{
++ return ((u32 *)&data)[index];
++}
++
++/* Helper for bpf_load below. */
++#define BPF_DATA(_name) offsetof(struct seccomp_data, _name)
++/**
++ * bpf_load: checks and returns a pointer to the requested offset
++ * @off: offset into struct seccomp_data to load from
++ *
++ * Returns the requested 32-bits of data.
++ * seccomp_chk_filter() should assure that @off is 32-bit aligned
++ * and not out of bounds. Failure to do so is a BUG.
++ */
++u32 seccomp_bpf_load(int off)
++{
++ struct pt_regs *regs = task_pt_regs(current);
++ if (off == BPF_DATA(nr))
++ return syscall_get_nr(current, regs);
++ if (off == BPF_DATA(arch))
++ return syscall_get_arch(current, regs);
++ if (off >= BPF_DATA(args[0]) && off < BPF_DATA(args[6])) {
++ unsigned long value;
++ int arg = (off - BPF_DATA(args[0])) / sizeof(u64);
++ int index = !!(off % sizeof(u64));
++ syscall_get_arguments(current, regs, arg, 1, &value);
++ return get_u32(value, index);
++ }
++ if (off == BPF_DATA(instruction_pointer))
++ return get_u32(KSTK_EIP(current), 0);
++ if (off == BPF_DATA(instruction_pointer) + sizeof(u32))
++ return get_u32(KSTK_EIP(current), 1);
++ /* seccomp_chk_filter should make this impossible. */
++ BUG();
++}
++
++/**
++ * seccomp_chk_filter - verify seccomp filter code
++ * @filter: filter to verify
++ * @flen: length of filter
++ *
++ * Takes a previously checked filter (by sk_chk_filter) and
++ * redirects all filter code that loads struct sk_buff data
++ * and related data through seccomp_bpf_load. It also
++ * enforces length and alignment checking of those loads.
++ *
++ * Returns 0 if the rule set is legal or -EINVAL if not.
++ */
++static int seccomp_chk_filter(struct sock_filter *filter, unsigned int flen)
++{
++ int pc;
++ for (pc = 0; pc < flen; pc++) {
++ struct sock_filter *ftest = &filter[pc];
++ u16 code = ftest->code;
++ u32 k = ftest->k;
++ switch (code) {
++ case BPF_S_LD_W_ABS:
++ ftest->code = BPF_S_ANC_SECCOMP_LD_W;
++ /* 32-bit aligned and not out of bounds. */
++ if (k >= sizeof(struct seccomp_data) || k & 3)
++ return -EINVAL;
++ continue;
++ case BPF_S_LD_W_LEN:
++ ftest->code = BPF_S_LD_IMM;
++ ftest->k = sizeof(struct seccomp_data);
++ continue;
++ case BPF_S_LDX_W_LEN:
++ ftest->code = BPF_S_LDX_IMM;
++ ftest->k = sizeof(struct seccomp_data);
++ continue;
++ /* Explicitly include allowed calls. */
++ case BPF_S_RET_K:
++ case BPF_S_RET_A:
++ case BPF_S_ALU_ADD_K:
++ case BPF_S_ALU_ADD_X:
++ case BPF_S_ALU_SUB_K:
++ case BPF_S_ALU_SUB_X:
++ case BPF_S_ALU_MUL_K:
++ case BPF_S_ALU_MUL_X:
++ case BPF_S_ALU_DIV_X:
++ case BPF_S_ALU_AND_K:
++ case BPF_S_ALU_AND_X:
++ case BPF_S_ALU_OR_K:
++ case BPF_S_ALU_OR_X:
++ case BPF_S_ALU_LSH_K:
++ case BPF_S_ALU_LSH_X:
++ case BPF_S_ALU_RSH_K:
++ case BPF_S_ALU_RSH_X:
++ case BPF_S_ALU_NEG:
++ case BPF_S_LD_IMM:
++ case BPF_S_LDX_IMM:
++ case BPF_S_MISC_TAX:
++ case BPF_S_MISC_TXA:
++ case BPF_S_ALU_DIV_K:
++ case BPF_S_LD_MEM:
++ case BPF_S_LDX_MEM:
++ case BPF_S_ST:
++ case BPF_S_STX:
++ case BPF_S_JMP_JA:
++ case BPF_S_JMP_JEQ_K:
++ case BPF_S_JMP_JEQ_X:
++ case BPF_S_JMP_JGE_K:
++ case BPF_S_JMP_JGE_X:
++ case BPF_S_JMP_JGT_K:
++ case BPF_S_JMP_JGT_X:
++ case BPF_S_JMP_JSET_K:
++ case BPF_S_JMP_JSET_X:
++ continue;
++ default:
++ return -EINVAL;
++ }
++ }
++ return 0;
++}
++
++/**
++ * seccomp_run_filters - evaluates all seccomp filters against @syscall
++ * @syscall: number of the current system call
++ *
++ * Returns valid seccomp BPF response codes.
++ */
++static u32 seccomp_run_filters(int syscall)
++{
++ struct seccomp_filter *f;
++ u32 ret = SECCOMP_RET_ALLOW;
++
++ /* Ensure unexpected behavior doesn't result in failing open. */
++ if (WARN_ON(current->seccomp.filter == NULL))
++ return SECCOMP_RET_KILL;
++
++ /*
++ * All filters are evaluated in order of youngest to oldest. The lowest
++ * BPF return value (ignoring the DATA) always takes priority.
++ */
++ for (f = current->seccomp.filter; f; f = f->prev) {
++ u32 cur_ret = sk_run_filter(NULL, f->insns);
++ if ((cur_ret & SECCOMP_RET_ACTION) < (ret & SECCOMP_RET_ACTION))
++ ret = cur_ret;
++ }
++ return ret;
++}
++
++/**
++ * seccomp_attach_filter: Attaches a seccomp filter to current.
++ * @fprog: BPF program to install
++ *
++ * Returns 0 on success or an errno on failure.
++ */
++static long seccomp_attach_filter(struct sock_fprog *fprog)
++{
++ struct seccomp_filter *filter;
++ unsigned long fp_size = fprog->len * sizeof(struct sock_filter);
++ unsigned long total_insns = fprog->len;
++ long ret;
++
++ if (fprog->len == 0 || fprog->len > BPF_MAXINSNS)
++ return -EINVAL;
++
++ for (filter = current->seccomp.filter; filter; filter = filter->prev)
++ total_insns += filter->len + 4; /* include a 4 instr penalty */
++ if (total_insns > MAX_INSNS_PER_PATH)
++ return -ENOMEM;
++
++ /*
++ * Installing a seccomp filter requires that the task have
++ * CAP_SYS_ADMIN in its namespace or be running with no_new_privs.
++ * This avoids scenarios where unprivileged tasks can affect the
++ * behavior of privileged children.
++ */
++ if (!current->no_new_privs &&
++ security_real_capable_noaudit(current, current_user_ns(),
++ CAP_SYS_ADMIN) != 0)
++ return -EACCES;
++
++ /* Allocate a new seccomp_filter */
++ filter = kzalloc(sizeof(struct seccomp_filter) + fp_size, GFP_KERNEL);
++ if (!filter)
++ return -ENOMEM;
++ atomic_set(&filter->usage, 1);
++ filter->len = fprog->len;
++
++ /* Copy the instructions from fprog. */
++ ret = -EFAULT;
++ if (copy_from_user(filter->insns, fprog->filter, fp_size))
++ goto fail;
++
++ /* Check and rewrite the fprog via the skb checker */
++ ret = sk_chk_filter(filter->insns, filter->len);
++ if (ret)
++ goto fail;
++
++ /* Check and rewrite the fprog for seccomp use */
++ ret = seccomp_chk_filter(filter->insns, filter->len);
++ if (ret)
++ goto fail;
++
++ /*
++ * If there is an existing filter, make it the prev and don't drop its
++ * task reference.
++ */
++ filter->prev = current->seccomp.filter;
++ current->seccomp.filter = filter;
++ return 0;
++fail:
++ kfree(filter);
++ return ret;
++}
++
++/**
++ * seccomp_attach_user_filter - attaches a user-supplied sock_fprog
++ * @user_filter: pointer to the user data containing a sock_fprog.
++ *
++ * Returns 0 on success and non-zero otherwise.
++ */
++long seccomp_attach_user_filter(char __user *user_filter)
++{
++ struct sock_fprog fprog;
++ long ret = -EFAULT;
++
++#ifdef CONFIG_COMPAT
++ if (is_compat_task()) {
++ struct compat_sock_fprog fprog32;
++ if (copy_from_user(&fprog32, user_filter, sizeof(fprog32)))
++ goto out;
++ fprog.len = fprog32.len;
++ fprog.filter = compat_ptr(fprog32.filter);
++ } else /* falls through to the if below. */
++#endif
++ if (copy_from_user(&fprog, user_filter, sizeof(fprog)))
++ goto out;
++ ret = seccomp_attach_filter(&fprog);
++out:
++ return ret;
++}
++
++/* get_seccomp_filter - increments the reference count of the filter on @tsk */
++void get_seccomp_filter(struct task_struct *tsk)
++{
++ struct seccomp_filter *orig = tsk->seccomp.filter;
++ if (!orig)
++ return;
++ /* Reference count is bounded by the number of total processes. */
++ atomic_inc(&orig->usage);
++}
++
++/* put_seccomp_filter - decrements the ref count of tsk->seccomp.filter */
++void put_seccomp_filter(struct task_struct *tsk)
++{
++ struct seccomp_filter *orig = tsk->seccomp.filter;
++ /* Clean up single-reference branches iteratively. */
++ while (orig && atomic_dec_and_test(&orig->usage)) {
++ struct seccomp_filter *freeme = orig;
++ orig = orig->prev;
++ kfree(freeme);
++ }
++}
++
++/**
++ * seccomp_send_sigsys - signals the task to allow in-process syscall emulation
++ * @syscall: syscall number to send to userland
++ * @reason: filter-supplied reason code to send to userland (via si_errno)
++ *
++ * Forces a SIGSYS with a code of SYS_SECCOMP and related sigsys info.
++ */
++static void seccomp_send_sigsys(int syscall, int reason)
++{
++ struct siginfo info;
++ memset(&info, 0, sizeof(info));
++ info.si_signo = SIGSYS;
++ info.si_code = SYS_SECCOMP;
++ info.si_call_addr = (void __user *)KSTK_EIP(current);
++ info.si_errno = reason;
++ info.si_arch = syscall_get_arch(current, task_pt_regs(current));
++ info.si_syscall = syscall;
++ force_sig_info(SIGSYS, &info, current);
++}
++#endif /* CONFIG_SECCOMP_FILTER */
+
+ /*
+ * Secure computing mode 1 allows only read/write/exit/sigreturn.
+@@ -32,11 +370,21 @@ static int mode1_syscalls_32[] = {
+
+ void __secure_computing(int this_syscall)
+ {
++ /* Filter calls should never use this function. */
++ BUG_ON(current->seccomp.mode == SECCOMP_MODE_FILTER);
++ __secure_computing_int(this_syscall);
++}
++
++int __secure_computing_int(int this_syscall)
++{
+ int mode = current->seccomp.mode;
+- int * syscall;
++ int exit_sig = 0;
++ int *syscall;
++ u32 ret = SECCOMP_RET_KILL;
++ int data;
+
+ switch (mode) {
+- case 1:
++ case SECCOMP_MODE_STRICT:
+ syscall = mode1_syscalls;
+ #ifdef CONFIG_COMPAT
+ if (is_compat_task())
+@@ -44,9 +392,44 @@ void __secure_computing(int this_syscall)
+ #endif
+ do {
+ if (*syscall == this_syscall)
+- return;
++ return 0;
+ } while (*++syscall);
++ exit_sig = SIGKILL;
+ break;
++#ifdef CONFIG_SECCOMP_FILTER
++ case SECCOMP_MODE_FILTER:
++ ret = seccomp_run_filters(this_syscall);
++ data = ret & SECCOMP_RET_DATA;
++ switch (ret & SECCOMP_RET_ACTION) {
++ case SECCOMP_RET_ERRNO:
++ /* Set the low-order 16-bits as a errno. */
++ syscall_set_return_value(current, task_pt_regs(current),
++ -data, 0);
++ goto skip;
++ case SECCOMP_RET_TRAP:
++ /* Show the handler the original registers. */
++ syscall_rollback(current, task_pt_regs(current));
++ /* Let the filter pass back 16 bits of data. */
++ seccomp_send_sigsys(this_syscall, data);
++ goto skip;
++ case SECCOMP_RET_TRACE:
++ /* Skip these calls if there is no tracer. */
++ if (!ptrace_event_enabled(current, PTRACE_EVENT_SECCOMP))
++ goto skip;
++ /* Allow the BPF to provide the event message */
++ ptrace_event(PTRACE_EVENT_SECCOMP, data);
++ if (fatal_signal_pending(current))
++ break;
++ return 0;
++ case SECCOMP_RET_ALLOW:
++ return 0;
++ case SECCOMP_RET_KILL:
++ default:
++ break;
++ }
++ exit_sig = SIGSYS;
++ break;
++#endif
+ default:
+ BUG();
+ }
+@@ -54,7 +437,11 @@ void __secure_computing(int this_syscall)
+ #ifdef SECCOMP_DEBUG
+ dump_stack();
+ #endif
+- do_exit(SIGKILL);
++ __audit_seccomp(this_syscall, exit_sig, ret);
++ do_exit(exit_sig);
++skip:
++ audit_seccomp(this_syscall, exit_sig, ret);
++ return -1;
+ }
+
+ long prctl_get_seccomp(void)
+@@ -62,25 +449,48 @@ long prctl_get_seccomp(void)
+ return current->seccomp.mode;
+ }
+
+-long prctl_set_seccomp(unsigned long seccomp_mode)
++/**
++ * prctl_set_seccomp: configures current->seccomp.mode
++ * @seccomp_mode: requested mode to use
++ * @filter: optional struct sock_fprog for use with SECCOMP_MODE_FILTER
++ *
++ * This function may be called repeatedly with a @seccomp_mode of
++ * SECCOMP_MODE_FILTER to install additional filters. Every filter
++ * successfully installed will be evaluated (in reverse order) for each system
++ * call the task makes.
++ *
++ * Once current->seccomp.mode is non-zero, it may not be changed.
++ *
++ * Returns 0 on success or -EINVAL on failure.
++ */
++long prctl_set_seccomp(unsigned long seccomp_mode, char __user *filter)
+ {
+- long ret;
++ long ret = -EINVAL;
+
+- /* can set it only once to be even more secure */
+- ret = -EPERM;
+- if (unlikely(current->seccomp.mode))
++ if (current->seccomp.mode &&
++ current->seccomp.mode != seccomp_mode)
+ goto out;
+
+- ret = -EINVAL;
+- if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) {
+- current->seccomp.mode = seccomp_mode;
+- set_thread_flag(TIF_SECCOMP);
++ switch (seccomp_mode) {
++ case SECCOMP_MODE_STRICT:
++ ret = 0;
+ #ifdef TIF_NOTSC
+ disable_TSC();
+ #endif
+- ret = 0;
++ break;
++#ifdef CONFIG_SECCOMP_FILTER
++ case SECCOMP_MODE_FILTER:
++ ret = seccomp_attach_user_filter(filter);
++ if (ret)
++ goto out;
++ break;
++#endif
++ default:
++ goto out;
+ }
+
+- out:
++ current->seccomp.mode = seccomp_mode;
++ set_thread_flag(TIF_SECCOMP);
++out:
+ return ret;
+ }
diff --git a/kernel/signal.c b/kernel/signal.c
-index 3ecf574..7b5d245 100644
+index 3ecf574..0541e21 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -45,12 +45,12 @@ static struct kmem_cache *sigqueue_cachep;
@@ -81456,6 +82717,15 @@ index 3ecf574..7b5d245 100644
handler = sig_handler(t, sig);
+@@ -159,7 +159,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)
+ {
@@ -364,6 +364,9 @@ __sigqueue_alloc(int sig, struct task_struct *t, gfp_t flags, int override_rlimi
atomic_inc(&user->sigpending);
rcu_read_unlock();
@@ -81538,7 +82808,21 @@ index 3ecf574..7b5d245 100644
return ret;
}
-@@ -2765,7 +2788,15 @@ do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info)
+@@ -2631,6 +2654,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);
+@@ -2765,7 +2795,15 @@ do_send_specific(pid_t tgid, pid_t pid, int sig, struct siginfo *info)
int error = -ESRCH;
rcu_read_lock();
@@ -81681,7 +82965,7 @@ index 2f194e9..2c05ea9 100644
.priority = 10,
};
diff --git a/kernel/sys.c b/kernel/sys.c
-index 9d557df..691558c 100644
+index 9d557df..b2a5319 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -158,6 +158,12 @@ static int set_one_prio(struct task_struct *p, int niceval, int error)
@@ -81852,6 +83136,32 @@ index 9d557df..691558c 100644
error = -EINVAL;
break;
}
+@@ -1808,7 +1851,7 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
+ error = prctl_get_seccomp();
+ break;
+ case PR_SET_SECCOMP:
+- error = prctl_set_seccomp(arg2);
++ error = prctl_set_seccomp(arg2, (char __user *)arg3);
+ break;
+ case PR_GET_TSC:
+ error = GET_TSC_CTL(arg2);
+@@ -1868,6 +1911,16 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
+ else
+ error = PR_MCE_KILL_DEFAULT;
+ break;
++ case PR_SET_NO_NEW_PRIVS:
++ if (arg2 != 1 || arg3 || arg4 || arg5)
++ return -EINVAL;
++
++ current->no_new_privs = 1;
++ break;
++ case PR_GET_NO_NEW_PRIVS:
++ if (arg2 || arg3 || arg4 || arg5)
++ return -EINVAL;
++ return current->no_new_privs ? 1 : 0;
+ default:
+ error = -EINVAL;
+ break;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index ea7ec7f..798623e 100644
--- a/kernel/sysctl.c
@@ -83724,6 +85034,20 @@ index d9df745..e73c2fe 100644
static inline void *ptr_to_indirect(void *ptr)
{
+diff --git a/lib/scatterlist.c b/lib/scatterlist.c
+index 4ceb05d..2ffcb3c 100644
+--- a/lib/scatterlist.c
++++ b/lib/scatterlist.c
+@@ -419,7 +419,8 @@ void sg_miter_stop(struct sg_mapping_iter *miter)
+ if (miter->addr) {
+ miter->__offset += miter->consumed;
+
+- if (miter->__flags & SG_MITER_TO_SG)
++ if ((miter->__flags & SG_MITER_TO_SG) &&
++ !PageSlab(miter->page))
+ flush_kernel_dcache_page(miter->page);
+
+ if (miter->__flags & SG_MITER_ATOMIC) {
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index d74c317..1170419 100644
--- a/lib/vsprintf.c
@@ -89809,7 +91133,7 @@ index f78f898..d7aa843 100644
if (__rtnl_register(PF_CAN, RTM_GETROUTE, NULL, cgw_dump_jobs, NULL)) {
diff --git a/net/compat.c b/net/compat.c
-index 8c979cc..2b1960c 100644
+index 8c979cc..453a165 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -71,9 +71,11 @@ int get_compat_msghdr(struct msghdr *kmsg, struct compat_msghdr __user *umsg)
@@ -89887,7 +91211,22 @@ index 8c979cc..2b1960c 100644
int fdmax = (kmsg->msg_controllen - sizeof(struct compat_cmsghdr)) / sizeof(int);
int fdnum = scm->fp->count;
struct file **fp = scm->fp->fp;
-@@ -370,7 +372,7 @@ static int do_set_sock_timeout(struct socket *sock, int level,
+@@ -326,14 +328,6 @@ void scm_detach_fds_compat(struct msghdr *kmsg, struct scm_cookie *scm)
+ __scm_destroy(scm);
+ }
+
+-/*
+- * A struct sock_filter is architecture independent.
+- */
+-struct compat_sock_fprog {
+- u16 len;
+- compat_uptr_t filter; /* struct sock_filter * */
+-};
+-
+ static int do_set_attach_filter(struct socket *sock, int level, int optname,
+ char __user *optval, unsigned int optlen)
+ {
+@@ -370,7 +364,7 @@ static int do_set_sock_timeout(struct socket *sock, int level,
return -EFAULT;
old_fs = get_fs();
set_fs(KERNEL_DS);
@@ -89896,7 +91235,7 @@ index 8c979cc..2b1960c 100644
set_fs(old_fs);
return err;
-@@ -431,7 +433,7 @@ static int do_get_sock_timeout(struct socket *sock, int level, int optname,
+@@ -431,7 +425,7 @@ static int do_get_sock_timeout(struct socket *sock, int level, int optname,
len = sizeof(ktime);
old_fs = get_fs();
set_fs(KERNEL_DS);
@@ -89905,7 +91244,7 @@ index 8c979cc..2b1960c 100644
set_fs(old_fs);
if (!err) {
-@@ -566,7 +568,7 @@ int compat_mc_setsockopt(struct sock *sock, int level, int optname,
+@@ -566,7 +560,7 @@ int compat_mc_setsockopt(struct sock *sock, int level, int optname,
case MCAST_JOIN_GROUP:
case MCAST_LEAVE_GROUP:
{
@@ -89914,7 +91253,7 @@ index 8c979cc..2b1960c 100644
struct group_req __user *kgr =
compat_alloc_user_space(sizeof(struct group_req));
u32 interface;
-@@ -587,7 +589,7 @@ int compat_mc_setsockopt(struct sock *sock, int level, int optname,
+@@ -587,7 +581,7 @@ int compat_mc_setsockopt(struct sock *sock, int level, int optname,
case MCAST_BLOCK_SOURCE:
case MCAST_UNBLOCK_SOURCE:
{
@@ -89923,7 +91262,7 @@ index 8c979cc..2b1960c 100644
struct group_source_req __user *kgsr = compat_alloc_user_space(
sizeof(struct group_source_req));
u32 interface;
-@@ -608,7 +610,7 @@ int compat_mc_setsockopt(struct sock *sock, int level, int optname,
+@@ -608,7 +602,7 @@ int compat_mc_setsockopt(struct sock *sock, int level, int optname,
}
case MCAST_MSFILTER:
{
@@ -89932,7 +91271,7 @@ index 8c979cc..2b1960c 100644
struct group_filter __user *kgf;
u32 interface, fmode, numsrc;
-@@ -646,7 +648,7 @@ int compat_mc_getsockopt(struct sock *sock, int level, int optname,
+@@ -646,7 +640,7 @@ int compat_mc_getsockopt(struct sock *sock, int level, int optname,
char __user *optval, int __user *optlen,
int (*getsockopt)(struct sock *, int, int, char __user *, int __user *))
{
@@ -89941,7 +91280,7 @@ index 8c979cc..2b1960c 100644
struct group_filter __user *kgf;
int __user *koptlen;
u32 interface, fmode, numsrc;
-@@ -799,7 +801,7 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
+@@ -799,7 +793,7 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args)
if (call < SYS_SOCKET || call > SYS_SENDMMSG)
return -EINVAL;
@@ -90150,6 +91489,30 @@ index 2367246..4a0a677 100644
if (copy_to_user(useraddr, &dump, sizeof(dump))) {
ret = -EFAULT;
goto out;
+diff --git a/net/core/filter.c b/net/core/filter.c
+index 5dea452..d775edc 100644
+--- a/net/core/filter.c
++++ b/net/core/filter.c
+@@ -39,6 +39,7 @@
+ #include <linux/filter.h>
+ #include <linux/reciprocal_div.h>
+ #include <linux/ratelimit.h>
++#include <linux/seccomp.h>
+
+ /* No hurry in this branch */
+ static void *__load_pointer(const struct sk_buff *skb, int k, unsigned int size)
+@@ -350,6 +351,11 @@ load_b:
+ A = 0;
+ continue;
+ }
++#ifdef CONFIG_SECCOMP_FILTER
++ case BPF_S_ANC_SECCOMP_LD_W:
++ A = seccomp_bpf_load(fentry->k);
++ continue;
++#endif
+ default:
+ WARN_RATELIMIT(1, "Unknown code:%u jt:%u tf:%u k:%u\n",
+ fentry->code, fentry->jt,
diff --git a/net/core/flow.c b/net/core/flow.c
index e318c7e..168b1d0 100644
--- a/net/core/flow.c
@@ -98042,6 +99405,73 @@ index 69ddb47..be0f0f9 100644
error = aafs_create(".load", 0640, &aa_fs_profile_load);
if (error)
goto error;
+diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
+index c1e18ba..7316d77 100644
+--- a/security/apparmor/domain.c
++++ b/security/apparmor/domain.c
+@@ -395,6 +395,11 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
+ new_profile = find_attach(ns, &ns->base.profiles, name);
+ if (!new_profile)
+ goto cleanup;
++ /*
++ * NOTE: Domain transitions from unconfined are allowed
++ * even when no_new_privs is set because this aways results
++ * in a further reduction of permissions.
++ */
+ goto apply;
+ }
+
+@@ -455,6 +460,16 @@ int apparmor_bprm_set_creds(struct linux_binprm *bprm)
+ /* fail exec */
+ error = -EACCES;
+
++ /*
++ * Policy has specified a domain transition, if no_new_privs then
++ * fail the exec.
++ */
++ if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS) {
++ aa_put_profile(new_profile);
++ error = -EPERM;
++ goto cleanup;
++ }
++
+ if (!new_profile)
+ goto audit;
+
+@@ -609,6 +624,14 @@ int aa_change_hat(const char *hats[], int count, u64 token, bool permtest)
+ const char *target = NULL, *info = NULL;
+ int error = 0;
+
++ /*
++ * Fail explicitly requested domain transitions if no_new_privs.
++ * There is no exception for unconfined as change_hat is not
++ * available.
++ */
++ if (current->no_new_privs)
++ return -EPERM;
++
+ /* released below */
+ cred = get_current_cred();
+ cxt = cred->security;
+@@ -750,6 +773,18 @@ int aa_change_profile(const char *ns_name, const char *hname, bool onexec,
+ cxt = cred->security;
+ profile = aa_cred_profile(cred);
+
++ /*
++ * Fail explicitly requested domain transitions if no_new_privs
++ * and not unconfined.
++ * Domain transitions from unconfined are allowed even when
++ * no_new_privs is set because this aways results in a reduction
++ * of permissions.
++ */
++ if (current->no_new_privs && !unconfined(profile)) {
++ put_cred(cred);
++ return -EPERM;
++ }
++
+ if (ns_name) {
+ /* released below */
+ ns = aa_find_namespace(profile->ns, ns_name);
diff --git a/security/apparmor/include/apparmorfs.h b/security/apparmor/include/apparmorfs.h
index cb1e93a..14f955c 100644
--- a/security/apparmor/include/apparmorfs.h
@@ -98574,7 +100004,7 @@ index 741dd13..ee8043e 100644
profile->file.dfa = unpack_dfa(e);
if (IS_ERR(profile->file.dfa)) {
diff --git a/security/commoncap.c b/security/commoncap.c
-index 12440ee..e16cba1 100644
+index 12440ee..2ec6d88 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -29,6 +29,7 @@
@@ -98640,7 +100070,27 @@ index 12440ee..e16cba1 100644
/*
* Attempt to get the on-exec apply capability sets for an executable file from
* its xattrs and, if present, apply them to the proposed credentials being
-@@ -585,6 +625,9 @@ int cap_bprm_secureexec(struct linux_binprm *bprm)
+@@ -521,14 +561,17 @@ skip:
+
+
+ /* Don't let someone trace a set[ug]id/setpcap binary with the revised
+- * credentials unless they have the appropriate permit
++ * credentials unless they have the appropriate permit.
++ *
++ * In addition, if NO_NEW_PRIVS, then ensure we get no new privs.
+ */
+ if ((new->euid != old->uid ||
+ new->egid != old->gid ||
+ !cap_issubset(new->cap_permitted, old->cap_permitted)) &&
+ bprm->unsafe & ~LSM_UNSAFE_PTRACE_CAP) {
+ /* downgrade; they get no more than they had, and maybe less */
+- if (!capable(CAP_SETUID)) {
++ if (!capable(CAP_SETUID) ||
++ (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)) {
+ new->euid = new->uid;
+ new->egid = new->gid;
+ }
+@@ -585,6 +628,9 @@ int cap_bprm_secureexec(struct linux_binprm *bprm)
{
const struct cred *cred = current_cred();
@@ -98981,7 +100431,7 @@ index dca1c22..4fa4591 100644
lock = &avc_cache.slots_lock[hvalue];
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
-index 1126c10..3684fc7 100644
+index 1126c10..e2dad6b 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -94,8 +94,6 @@
@@ -98993,7 +100443,31 @@ index 1126c10..3684fc7 100644
/* SECMARK reference count */
static atomic_t selinux_secmark_refcount = ATOMIC_INIT(0);
-@@ -5449,7 +5447,7 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
+@@ -2000,6 +1998,13 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
+ new_tsec->sid = old_tsec->exec_sid;
+ /* Reset exec SID on execve. */
+ new_tsec->exec_sid = 0;
++
++ /*
++ * Minimize confusion: if no_new_privs and a transition is
++ * explicitly requested, then fail the exec.
++ */
++ if (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS)
++ return -EPERM;
+ } else {
+ /* Check for a default transition on this program. */
+ rc = security_transition_sid(old_tsec->sid, isec->sid,
+@@ -2012,7 +2017,8 @@ static int selinux_bprm_set_creds(struct linux_binprm *bprm)
+ COMMON_AUDIT_DATA_INIT(&ad, PATH);
+ ad.u.path = bprm->file->f_path;
+
+- if (bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID)
++ if ((bprm->file->f_path.mnt->mnt_flags & MNT_NOSUID) ||
++ (bprm->unsafe & LSM_UNSAFE_NO_NEW_PRIVS))
+ new_tsec->sid = old_tsec->sid;
+
+ if (new_tsec->sid == old_tsec->sid) {
+@@ -5449,7 +5455,7 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer)
#endif
@@ -99002,7 +100476,7 @@ index 1126c10..3684fc7 100644
.name = "selinux",
.ptrace_access_check = selinux_ptrace_access_check,
-@@ -5795,6 +5793,9 @@ static void selinux_nf_ip_exit(void)
+@@ -5795,6 +5801,9 @@ static void selinux_nf_ip_exit(void)
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
static int selinux_disabled;
@@ -99012,7 +100486,7 @@ index 1126c10..3684fc7 100644
int selinux_disable(void)
{
if (ss_initialized) {
-@@ -5812,7 +5813,9 @@ int selinux_disable(void)
+@@ -5812,7 +5821,9 @@ int selinux_disable(void)
selinux_disabled = 1;
selinux_enabled = 0;