summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnthony G. Basile <blueness@gentoo.org>2012-01-20 19:32:01 -0500
committerAnthony G. Basile <blueness@gentoo.org>2012-01-20 19:32:01 -0500
commit17cab42d71d4c06dca008dae518a254bb7e704f2 (patch)
tree4a9883876522258633a2da1e6b16658168843ed7
parentGrsec/PaX: 2.2.2-2.6.32.54-201201182131 + 2.2.2-3.1.10-201201182132 (diff)
downloadhardened-patchset-17cab42d71d4c06dca008dae518a254bb7e704f2.tar.gz
hardened-patchset-17cab42d71d4c06dca008dae518a254bb7e704f2.tar.bz2
hardened-patchset-17cab42d71d4c06dca008dae518a254bb7e704f2.zip
Grsec/PaX: 2.2.2-2.6.32.54-201201182131 + 2.2.2-3.1.10-20120118213220120120
-rw-r--r--2.6.32/0000_README2
-rw-r--r--2.6.32/4420_grsecurity-2.2.2-2.6.32.54-201201201821.patch (renamed from 2.6.32/4420_grsecurity-2.2.2-2.6.32.54-201201182131.patch)118
-rw-r--r--3.1.10/0000_README2
-rw-r--r--3.1.10/4420_grsecurity-2.2.2-3.1.10-201201201822.patch (renamed from 3.1.10/4420_grsecurity-2.2.2-3.1.10-201201182132.patch)617
4 files changed, 527 insertions, 212 deletions
diff --git a/2.6.32/0000_README b/2.6.32/0000_README
index 2f2c637..71815cd 100644
--- a/2.6.32/0000_README
+++ b/2.6.32/0000_README
@@ -10,7 +10,7 @@ Patch: 1053_linux-2.6.32.54.patch
From: http://www.kernel.org
Desc: Linux 2.6.32.54
-Patch: 4420_grsecurity-2.2.2-2.6.32.54-201201182131.patch
+Patch: 4420_grsecurity-2.2.2-2.6.32.54-201201201821.patch
From: http://www.grsecurity.net
Desc: hardened-sources base patch from upstream grsecurity
diff --git a/2.6.32/4420_grsecurity-2.2.2-2.6.32.54-201201182131.patch b/2.6.32/4420_grsecurity-2.2.2-2.6.32.54-201201201821.patch
index 8e8325c..c0d9feb 100644
--- a/2.6.32/4420_grsecurity-2.2.2-2.6.32.54-201201182131.patch
+++ b/2.6.32/4420_grsecurity-2.2.2-2.6.32.54-201201201821.patch
@@ -7848,7 +7848,7 @@ index 588a7aa..a3468b0 100644
if (err)
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
-index 4edd8eb..a558697 100644
+index 4edd8eb..29124b4 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -13,7 +13,9 @@
@@ -7907,12 +7907,13 @@ index 4edd8eb..a558697 100644
movl %ebp,%ebp /* zero extension */
pushq $__USER32_DS
CFI_ADJUST_CFA_OFFSET 8
-@@ -135,28 +157,41 @@ ENTRY(ia32_sysenter_target)
+@@ -135,28 +157,42 @@ ENTRY(ia32_sysenter_target)
pushfq
CFI_ADJUST_CFA_OFFSET 8
/*CFI_REL_OFFSET rflags,0*/
- movl 8*3-THREAD_SIZE+TI_sysenter_return(%rsp), %r10d
- CFI_REGISTER rip,r10
++ orl $X86_EFLAGS_IF,(%rsp)
+ GET_THREAD_INFO(%r11)
+ movl TI_sysenter_return(%r11), %r11d
+ CFI_REGISTER rip,r11
@@ -7955,7 +7956,7 @@ index 4edd8eb..a558697 100644
CFI_REMEMBER_STATE
jnz sysenter_tracesys
cmpq $(IA32_NR_syscalls-1),%rax
-@@ -166,13 +201,15 @@ sysenter_do_call:
+@@ -166,13 +202,15 @@ sysenter_do_call:
sysenter_dispatch:
call *ia32_sys_call_table(,%rax,8)
movq %rax,RAX-ARGOFFSET(%rsp)
@@ -7974,7 +7975,7 @@ index 4edd8eb..a558697 100644
/* clear IF, that popfq doesn't enable interrupts early */
andl $~0x200,EFLAGS-R11(%rsp)
movl RIP-R11(%rsp),%edx /* User %eip */
-@@ -200,6 +237,9 @@ sysexit_from_sys_call:
+@@ -200,6 +238,9 @@ sysexit_from_sys_call:
movl %eax,%esi /* 2nd arg: syscall number */
movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */
call audit_syscall_entry
@@ -7984,7 +7985,7 @@ index 4edd8eb..a558697 100644
movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */
cmpq $(IA32_NR_syscalls-1),%rax
ja ia32_badsys
-@@ -211,7 +251,7 @@ sysexit_from_sys_call:
+@@ -211,7 +252,7 @@ sysexit_from_sys_call:
.endm
.macro auditsys_exit exit
@@ -7993,7 +7994,7 @@ index 4edd8eb..a558697 100644
jnz ia32_ret_from_sys_call
TRACE_IRQS_ON
sti
-@@ -221,12 +261,12 @@ sysexit_from_sys_call:
+@@ -221,12 +262,12 @@ sysexit_from_sys_call:
movzbl %al,%edi /* zero-extend that into %edi */
inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
call audit_syscall_exit
@@ -8008,7 +8009,7 @@ index 4edd8eb..a558697 100644
jz \exit
CLEAR_RREGS -ARGOFFSET
jmp int_with_check
-@@ -244,7 +284,7 @@ sysexit_audit:
+@@ -244,7 +285,7 @@ sysexit_audit:
sysenter_tracesys:
#ifdef CONFIG_AUDITSYSCALL
@@ -8017,7 +8018,7 @@ index 4edd8eb..a558697 100644
jz sysenter_auditsys
#endif
SAVE_REST
-@@ -252,6 +292,9 @@ sysenter_tracesys:
+@@ -252,6 +293,9 @@ sysenter_tracesys:
movq $-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */
movq %rsp,%rdi /* &pt_regs -> arg1 */
call syscall_trace_enter
@@ -8027,7 +8028,7 @@ index 4edd8eb..a558697 100644
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
RESTORE_REST
cmpq $(IA32_NR_syscalls-1),%rax
-@@ -283,19 +326,20 @@ ENDPROC(ia32_sysenter_target)
+@@ -283,19 +327,20 @@ ENDPROC(ia32_sysenter_target)
ENTRY(ia32_cstar_target)
CFI_STARTPROC32 simple
CFI_SIGNAL_FRAME
@@ -8050,7 +8051,7 @@ index 4edd8eb..a558697 100644
movl %eax,%eax /* zero extension */
movq %rax,ORIG_RAX-ARGOFFSET(%rsp)
movq %rcx,RIP-ARGOFFSET(%rsp)
-@@ -311,13 +355,19 @@ ENTRY(ia32_cstar_target)
+@@ -311,13 +356,19 @@ ENTRY(ia32_cstar_target)
/* no need to do an access_ok check here because r8 has been
32bit zero extended */
/* hardware stack frame is complete now */
@@ -8073,7 +8074,7 @@ index 4edd8eb..a558697 100644
CFI_REMEMBER_STATE
jnz cstar_tracesys
cmpq $IA32_NR_syscalls-1,%rax
-@@ -327,13 +377,15 @@ cstar_do_call:
+@@ -327,13 +378,15 @@ cstar_do_call:
cstar_dispatch:
call *ia32_sys_call_table(,%rax,8)
movq %rax,RAX-ARGOFFSET(%rsp)
@@ -8092,7 +8093,7 @@ index 4edd8eb..a558697 100644
RESTORE_ARGS 1,-ARG_SKIP,1,1,1
movl RIP-ARGOFFSET(%rsp),%ecx
CFI_REGISTER rip,rcx
-@@ -361,7 +413,7 @@ sysretl_audit:
+@@ -361,7 +414,7 @@ sysretl_audit:
cstar_tracesys:
#ifdef CONFIG_AUDITSYSCALL
@@ -8101,7 +8102,7 @@ index 4edd8eb..a558697 100644
jz cstar_auditsys
#endif
xchgl %r9d,%ebp
-@@ -370,6 +422,9 @@ cstar_tracesys:
+@@ -370,6 +423,9 @@ cstar_tracesys:
movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
movq %rsp,%rdi /* &pt_regs -> arg1 */
call syscall_trace_enter
@@ -8111,7 +8112,7 @@ index 4edd8eb..a558697 100644
LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */
RESTORE_REST
xchgl %ebp,%r9d
-@@ -415,11 +470,6 @@ ENTRY(ia32_syscall)
+@@ -415,11 +471,6 @@ ENTRY(ia32_syscall)
CFI_REL_OFFSET rip,RIP-RIP
PARAVIRT_ADJUST_EXCEPTION_FRAME
SWAPGS
@@ -8123,7 +8124,7 @@ index 4edd8eb..a558697 100644
movl %eax,%eax
pushq %rax
CFI_ADJUST_CFA_OFFSET 8
-@@ -427,9 +477,15 @@ ENTRY(ia32_syscall)
+@@ -427,9 +478,15 @@ ENTRY(ia32_syscall)
/* note the registers are not zero extended to the sf.
this could be a problem. */
SAVE_ARGS 0,0,1
@@ -8142,7 +8143,7 @@ index 4edd8eb..a558697 100644
jnz ia32_tracesys
cmpq $(IA32_NR_syscalls-1),%rax
ja ia32_badsys
-@@ -448,6 +504,9 @@ ia32_tracesys:
+@@ -448,6 +505,9 @@ ia32_tracesys:
movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
movq %rsp,%rdi /* &pt_regs -> arg1 */
call syscall_trace_enter
@@ -8152,7 +8153,7 @@ index 4edd8eb..a558697 100644
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
RESTORE_REST
cmpq $(IA32_NR_syscalls-1),%rax
-@@ -462,6 +521,7 @@ ia32_badsys:
+@@ -462,6 +522,7 @@ ia32_badsys:
quiet_ni_syscall:
movq $-ENOSYS,%rax
@@ -52799,7 +52800,7 @@ index c5ef152..1363194 100644
+}
+#endif
diff --git a/fs/proc/base.c b/fs/proc/base.c
-index 67f7dc0..e95ea4f 100644
+index 67f7dc0..67ab883 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -102,6 +102,22 @@ struct pid_entry {
@@ -52922,7 +52923,29 @@ index 67f7dc0..e95ea4f 100644
put_task_struct(task);
}
return allowed;
-@@ -963,6 +1004,9 @@ static ssize_t environ_read(struct file *file, char __user *buf,
+@@ -809,6 +850,8 @@ static int mem_open(struct inode* inode, struct file* file)
+ return 0;
+ }
+
++static int task_dumpable(struct task_struct *task);
++
+ static ssize_t mem_read(struct file * file, char __user * buf,
+ size_t count, loff_t *ppos)
+ {
+@@ -824,6 +867,12 @@ static ssize_t mem_read(struct file * file, char __user * buf,
+ if (check_mem_permission(task))
+ goto out;
+
++ // XXX: temporary workaround
++ if (!task_dumpable(task) && task == current) {
++ ret = -EACCES;
++ goto out;
++ }
++
+ ret = -ENOMEM;
+ page = (char *)__get_free_page(GFP_TEMPORARY);
+ if (!page)
+@@ -963,6 +1012,9 @@ static ssize_t environ_read(struct file *file, char __user *buf,
if (!task)
goto out_no_task;
@@ -52932,7 +52955,7 @@ index 67f7dc0..e95ea4f 100644
if (!ptrace_may_access(task, PTRACE_MODE_READ))
goto out;
-@@ -1377,7 +1421,7 @@ static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
+@@ -1377,7 +1429,7 @@ static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
path_put(&nd->path);
/* Are we allowed to snoop on the tasks file descriptors? */
@@ -52941,7 +52964,7 @@ index 67f7dc0..e95ea4f 100644
goto out;
error = PROC_I(inode)->op.proc_get_link(inode, &nd->path);
-@@ -1417,8 +1461,18 @@ static int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int b
+@@ -1417,8 +1469,18 @@ static int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int b
struct path path;
/* Are we allowed to snoop on the tasks file descriptors? */
@@ -52962,7 +52985,7 @@ index 67f7dc0..e95ea4f 100644
error = PROC_I(inode)->op.proc_get_link(inode, &path);
if (error)
-@@ -1483,7 +1537,11 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st
+@@ -1483,7 +1545,11 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st
rcu_read_lock();
cred = __task_cred(task);
inode->i_uid = cred->euid;
@@ -52974,7 +52997,7 @@ index 67f7dc0..e95ea4f 100644
rcu_read_unlock();
}
security_task_to_inode(task, inode);
-@@ -1501,6 +1559,9 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
+@@ -1501,6 +1567,9 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
struct inode *inode = dentry->d_inode;
struct task_struct *task;
const struct cred *cred;
@@ -52984,7 +53007,7 @@ index 67f7dc0..e95ea4f 100644
generic_fillattr(inode, stat);
-@@ -1508,13 +1569,41 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
+@@ -1508,13 +1577,41 @@ static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat
stat->uid = 0;
stat->gid = 0;
task = pid_task(proc_pid(inode), PIDTYPE_PID);
@@ -53027,7 +53050,7 @@ index 67f7dc0..e95ea4f 100644
}
rcu_read_unlock();
return 0;
-@@ -1545,11 +1634,20 @@ static int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
+@@ -1545,11 +1642,20 @@ static int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
if (task) {
if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
@@ -53048,7 +53071,7 @@ index 67f7dc0..e95ea4f 100644
rcu_read_unlock();
} else {
inode->i_uid = 0;
-@@ -1670,7 +1768,8 @@ static int proc_fd_info(struct inode *inode, struct path *path, char *info)
+@@ -1670,7 +1776,8 @@ static int proc_fd_info(struct inode *inode, struct path *path, char *info)
int fd = proc_fd(inode);
if (task) {
@@ -53058,7 +53081,7 @@ index 67f7dc0..e95ea4f 100644
put_task_struct(task);
}
if (files) {
-@@ -1922,12 +2021,22 @@ static const struct file_operations proc_fd_operations = {
+@@ -1922,12 +2029,22 @@ static const struct file_operations proc_fd_operations = {
static int proc_fd_permission(struct inode *inode, int mask)
{
int rv;
@@ -53083,7 +53106,7 @@ index 67f7dc0..e95ea4f 100644
return rv;
}
-@@ -2036,6 +2145,9 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
+@@ -2036,6 +2153,9 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
if (!task)
goto out_no_task;
@@ -53093,7 +53116,7 @@ index 67f7dc0..e95ea4f 100644
/*
* Yes, it does not scale. And it should not. Don't add
* new entries into /proc/<tgid>/ without very good reasons.
-@@ -2080,6 +2192,9 @@ static int proc_pident_readdir(struct file *filp,
+@@ -2080,6 +2200,9 @@ static int proc_pident_readdir(struct file *filp,
if (!task)
goto out_no_task;
@@ -53103,7 +53126,7 @@ index 67f7dc0..e95ea4f 100644
ret = 0;
i = filp->f_pos;
switch (i) {
-@@ -2347,7 +2462,7 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
+@@ -2347,7 +2470,7 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd,
void *cookie)
{
@@ -53112,7 +53135,7 @@ index 67f7dc0..e95ea4f 100644
if (!IS_ERR(s))
__putname(s);
}
-@@ -2553,7 +2668,7 @@ static const struct pid_entry tgid_base_stuff[] = {
+@@ -2553,7 +2676,7 @@ static const struct pid_entry tgid_base_stuff[] = {
#ifdef CONFIG_SCHED_DEBUG
REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
#endif
@@ -53121,7 +53144,7 @@ index 67f7dc0..e95ea4f 100644
INF("syscall", S_IRUGO, proc_pid_syscall),
#endif
INF("cmdline", S_IRUGO, proc_pid_cmdline),
-@@ -2578,10 +2693,10 @@ static const struct pid_entry tgid_base_stuff[] = {
+@@ -2578,10 +2701,10 @@ static const struct pid_entry tgid_base_stuff[] = {
#ifdef CONFIG_SECURITY
DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations),
#endif
@@ -53134,7 +53157,7 @@ index 67f7dc0..e95ea4f 100644
ONE("stack", S_IRUGO, proc_pid_stack),
#endif
#ifdef CONFIG_SCHEDSTATS
-@@ -2611,6 +2726,9 @@ static const struct pid_entry tgid_base_stuff[] = {
+@@ -2611,6 +2734,9 @@ static const struct pid_entry tgid_base_stuff[] = {
#ifdef CONFIG_TASK_IO_ACCOUNTING
INF("io", S_IRUSR, proc_tgid_io_accounting),
#endif
@@ -53144,7 +53167,7 @@ index 67f7dc0..e95ea4f 100644
};
static int proc_tgid_base_readdir(struct file * filp,
-@@ -2735,7 +2853,14 @@ static struct dentry *proc_pid_instantiate(struct inode *dir,
+@@ -2735,7 +2861,14 @@ static struct dentry *proc_pid_instantiate(struct inode *dir,
if (!inode)
goto out;
@@ -53159,7 +53182,7 @@ index 67f7dc0..e95ea4f 100644
inode->i_op = &proc_tgid_base_inode_operations;
inode->i_fop = &proc_tgid_base_operations;
inode->i_flags|=S_IMMUTABLE;
-@@ -2777,7 +2902,11 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct
+@@ -2777,7 +2910,11 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct
if (!task)
goto out;
@@ -53171,7 +53194,7 @@ index 67f7dc0..e95ea4f 100644
put_task_struct(task);
out:
return result;
-@@ -2842,6 +2971,11 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
+@@ -2842,6 +2979,11 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
unsigned int nr;
struct task_struct *reaper;
@@ -53183,7 +53206,7 @@ index 67f7dc0..e95ea4f 100644
struct tgid_iter iter;
struct pid_namespace *ns;
-@@ -2865,8 +2999,27 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
+@@ -2865,8 +3007,27 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
for (iter = next_tgid(ns, iter);
iter.task;
iter.tgid += 1, iter = next_tgid(ns, iter)) {
@@ -53212,7 +53235,7 @@ index 67f7dc0..e95ea4f 100644
put_task_struct(iter.task);
goto out;
}
-@@ -2892,7 +3045,7 @@ static const struct pid_entry tid_base_stuff[] = {
+@@ -2892,7 +3053,7 @@ static const struct pid_entry tid_base_stuff[] = {
#ifdef CONFIG_SCHED_DEBUG
REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
#endif
@@ -53221,7 +53244,7 @@ index 67f7dc0..e95ea4f 100644
INF("syscall", S_IRUGO, proc_pid_syscall),
#endif
INF("cmdline", S_IRUGO, proc_pid_cmdline),
-@@ -2916,10 +3069,10 @@ static const struct pid_entry tid_base_stuff[] = {
+@@ -2916,10 +3077,10 @@ static const struct pid_entry tid_base_stuff[] = {
#ifdef CONFIG_SECURITY
DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations),
#endif
@@ -70839,7 +70862,7 @@ index b781007..f738b04 100644
if (nsops < 1 || semid < 0)
diff --git a/ipc/shm.c b/ipc/shm.c
-index d30732c..7379456 100644
+index d30732c..e4992cd 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -70,6 +70,14 @@ static void shm_destroy (struct ipc_namespace *ns, struct shmid_kernel *shp);
@@ -70897,7 +70920,20 @@ index d30732c..7379456 100644
shm_params.key = key;
shm_params.flg = shmflg;
shm_params.u.size = size;
-@@ -880,9 +897,21 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
+@@ -857,6 +874,12 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
+ f_mode = FMODE_READ | FMODE_WRITE;
+ }
+ if (shmflg & SHM_EXEC) {
++
++#ifdef CONFIG_PAX_MPROTECT
++ if (current->mm->pax_flags & MF_PAX_MPROTECT)
++ goto out;
++#endif
++
+ prot |= PROT_EXEC;
+ acc_mode |= S_IXUGO;
+ }
+@@ -880,9 +903,21 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
if (err)
goto out_unlock;
diff --git a/3.1.10/0000_README b/3.1.10/0000_README
index c6d0fe6..73b6f88 100644
--- a/3.1.10/0000_README
+++ b/3.1.10/0000_README
@@ -2,7 +2,7 @@ README
-----------------------------------------------------------------------------
Individual Patch Descriptions:
-----------------------------------------------------------------------------
-Patch: 4420_grsecurity-2.2.2-3.1.10-201201182132.patch
+Patch: 4420_grsecurity-2.2.2-3.1.10-201201201822.patch
From: http://www.grsecurity.net
Desc: hardened-sources base patch from upstream grsecurity
diff --git a/3.1.10/4420_grsecurity-2.2.2-3.1.10-201201182132.patch b/3.1.10/4420_grsecurity-2.2.2-3.1.10-201201201822.patch
index 2f087ff..03b7ff6 100644
--- a/3.1.10/4420_grsecurity-2.2.2-3.1.10-201201182132.patch
+++ b/3.1.10/4420_grsecurity-2.2.2-3.1.10-201201201822.patch
@@ -6620,7 +6620,7 @@ index 6557769..ef6ae89 100644
if (err)
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
-index 54edb207..f5101b9 100644
+index 54edb207..db27073 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -13,7 +13,9 @@
@@ -6679,12 +6679,13 @@ index 54edb207..f5101b9 100644
movl %ebp,%ebp /* zero extension */
pushq_cfi $__USER32_DS
/*CFI_REL_OFFSET ss,0*/
-@@ -134,25 +156,38 @@ ENTRY(ia32_sysenter_target)
+@@ -134,25 +156,39 @@ ENTRY(ia32_sysenter_target)
CFI_REL_OFFSET rsp,0
pushfq_cfi
/*CFI_REL_OFFSET rflags,0*/
- movl 8*3-THREAD_SIZE+TI_sysenter_return(%rsp), %r10d
- CFI_REGISTER rip,r10
++ orl $X86_EFLAGS_IF,(%rsp)
+ GET_THREAD_INFO(%r11)
+ movl TI_sysenter_return(%r11), %r11d
+ CFI_REGISTER rip,r11
@@ -6724,7 +6725,7 @@ index 54edb207..f5101b9 100644
CFI_REMEMBER_STATE
jnz sysenter_tracesys
cmpq $(IA32_NR_syscalls-1),%rax
-@@ -162,13 +197,15 @@ sysenter_do_call:
+@@ -162,13 +198,15 @@ sysenter_do_call:
sysenter_dispatch:
call *ia32_sys_call_table(,%rax,8)
movq %rax,RAX-ARGOFFSET(%rsp)
@@ -6743,7 +6744,7 @@ index 54edb207..f5101b9 100644
/* clear IF, that popfq doesn't enable interrupts early */
andl $~0x200,EFLAGS-R11(%rsp)
movl RIP-R11(%rsp),%edx /* User %eip */
-@@ -194,6 +231,9 @@ sysexit_from_sys_call:
+@@ -194,6 +232,9 @@ sysexit_from_sys_call:
movl %eax,%esi /* 2nd arg: syscall number */
movl $AUDIT_ARCH_I386,%edi /* 1st arg: audit arch */
call audit_syscall_entry
@@ -6753,7 +6754,7 @@ index 54edb207..f5101b9 100644
movl RAX-ARGOFFSET(%rsp),%eax /* reload syscall number */
cmpq $(IA32_NR_syscalls-1),%rax
ja ia32_badsys
-@@ -205,7 +245,7 @@ sysexit_from_sys_call:
+@@ -205,7 +246,7 @@ sysexit_from_sys_call:
.endm
.macro auditsys_exit exit
@@ -6762,7 +6763,7 @@ index 54edb207..f5101b9 100644
jnz ia32_ret_from_sys_call
TRACE_IRQS_ON
sti
-@@ -215,12 +255,12 @@ sysexit_from_sys_call:
+@@ -215,12 +256,12 @@ sysexit_from_sys_call:
movzbl %al,%edi /* zero-extend that into %edi */
inc %edi /* first arg, 0->1(AUDITSC_SUCCESS), 1->2(AUDITSC_FAILURE) */
call audit_syscall_exit
@@ -6777,7 +6778,7 @@ index 54edb207..f5101b9 100644
jz \exit
CLEAR_RREGS -ARGOFFSET
jmp int_with_check
-@@ -238,7 +278,7 @@ sysexit_audit:
+@@ -238,7 +279,7 @@ sysexit_audit:
sysenter_tracesys:
#ifdef CONFIG_AUDITSYSCALL
@@ -6786,7 +6787,7 @@ index 54edb207..f5101b9 100644
jz sysenter_auditsys
#endif
SAVE_REST
-@@ -246,6 +286,9 @@ sysenter_tracesys:
+@@ -246,6 +287,9 @@ sysenter_tracesys:
movq $-ENOSYS,RAX(%rsp)/* ptrace can change this for a bad syscall */
movq %rsp,%rdi /* &pt_regs -> arg1 */
call syscall_trace_enter
@@ -6796,7 +6797,7 @@ index 54edb207..f5101b9 100644
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
RESTORE_REST
cmpq $(IA32_NR_syscalls-1),%rax
-@@ -277,19 +320,20 @@ ENDPROC(ia32_sysenter_target)
+@@ -277,19 +321,20 @@ ENDPROC(ia32_sysenter_target)
ENTRY(ia32_cstar_target)
CFI_STARTPROC32 simple
CFI_SIGNAL_FRAME
@@ -6819,7 +6820,7 @@ index 54edb207..f5101b9 100644
movl %eax,%eax /* zero extension */
movq %rax,ORIG_RAX-ARGOFFSET(%rsp)
movq %rcx,RIP-ARGOFFSET(%rsp)
-@@ -305,13 +349,19 @@ ENTRY(ia32_cstar_target)
+@@ -305,13 +350,19 @@ ENTRY(ia32_cstar_target)
/* no need to do an access_ok check here because r8 has been
32bit zero extended */
/* hardware stack frame is complete now */
@@ -6842,7 +6843,7 @@ index 54edb207..f5101b9 100644
CFI_REMEMBER_STATE
jnz cstar_tracesys
cmpq $IA32_NR_syscalls-1,%rax
-@@ -321,13 +371,15 @@ cstar_do_call:
+@@ -321,13 +372,15 @@ cstar_do_call:
cstar_dispatch:
call *ia32_sys_call_table(,%rax,8)
movq %rax,RAX-ARGOFFSET(%rsp)
@@ -6861,7 +6862,7 @@ index 54edb207..f5101b9 100644
RESTORE_ARGS 0,-ARG_SKIP,0,0,0
movl RIP-ARGOFFSET(%rsp),%ecx
CFI_REGISTER rip,rcx
-@@ -355,7 +407,7 @@ sysretl_audit:
+@@ -355,7 +408,7 @@ sysretl_audit:
cstar_tracesys:
#ifdef CONFIG_AUDITSYSCALL
@@ -6870,7 +6871,7 @@ index 54edb207..f5101b9 100644
jz cstar_auditsys
#endif
xchgl %r9d,%ebp
-@@ -364,6 +416,9 @@ cstar_tracesys:
+@@ -364,6 +417,9 @@ cstar_tracesys:
movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
movq %rsp,%rdi /* &pt_regs -> arg1 */
call syscall_trace_enter
@@ -6880,7 +6881,7 @@ index 54edb207..f5101b9 100644
LOAD_ARGS32 ARGOFFSET, 1 /* reload args from stack in case ptrace changed it */
RESTORE_REST
xchgl %ebp,%r9d
-@@ -409,20 +464,21 @@ ENTRY(ia32_syscall)
+@@ -409,20 +465,21 @@ ENTRY(ia32_syscall)
CFI_REL_OFFSET rip,RIP-RIP
PARAVIRT_ADJUST_EXCEPTION_FRAME
SWAPGS
@@ -6910,7 +6911,7 @@ index 54edb207..f5101b9 100644
jnz ia32_tracesys
cmpq $(IA32_NR_syscalls-1),%rax
ja ia32_badsys
-@@ -441,6 +497,9 @@ ia32_tracesys:
+@@ -441,6 +498,9 @@ ia32_tracesys:
movq $-ENOSYS,RAX(%rsp) /* ptrace can change this for a bad syscall */
movq %rsp,%rdi /* &pt_regs -> arg1 */
call syscall_trace_enter
@@ -6920,7 +6921,7 @@ index 54edb207..f5101b9 100644
LOAD_ARGS32 ARGOFFSET /* reload args from stack in case ptrace changed it */
RESTORE_REST
cmpq $(IA32_NR_syscalls-1),%rax
-@@ -455,6 +514,7 @@ ia32_badsys:
+@@ -455,6 +515,7 @@ ia32_badsys:
quiet_ni_syscall:
movq $-ENOSYS,%rax
@@ -48367,7 +48368,7 @@ index 3a1dafd..c7fed72 100644
+}
+#endif
diff --git a/fs/proc/base.c b/fs/proc/base.c
-index 5eb0206..fe01db4 100644
+index 5eb0206..f8f1974 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -107,6 +107,22 @@ struct pid_entry {
@@ -48393,17 +48394,102 @@ index 5eb0206..fe01db4 100644
#define NOD(NAME, MODE, IOP, FOP, OP) { \
.name = (NAME), \
.len = sizeof(NAME) - 1, \
-@@ -209,6 +225,9 @@ static struct mm_struct *__check_mem_permission(struct task_struct *task)
- if (task == current)
- return mm;
+@@ -194,65 +210,7 @@ static int proc_root_link(struct inode *inode, struct path *path)
+ return result;
+ }
+
+-static struct mm_struct *__check_mem_permission(struct task_struct *task)
+-{
+- struct mm_struct *mm;
+-
+- mm = get_task_mm(task);
+- if (!mm)
+- return ERR_PTR(-EINVAL);
+-
+- /*
+- * A task can always look at itself, in case it chooses
+- * to use system calls instead of load instructions.
+- */
+- if (task == current)
+- return mm;
+-
+- /*
+- * If current is actively ptrace'ing, and would also be
+- * permitted to freshly attach with ptrace now, permit it.
+- */
+- if (task_is_stopped_or_traced(task)) {
+- int match;
+- rcu_read_lock();
+- match = (ptrace_parent(task) == current);
+- rcu_read_unlock();
+- if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH))
+- return mm;
+- }
+-
+- /*
+- * No one else is allowed.
+- */
+- mmput(mm);
+- return ERR_PTR(-EPERM);
+-}
+-
+-/*
+- * If current may access user memory in @task return a reference to the
+- * corresponding mm, otherwise ERR_PTR.
+- */
+-static struct mm_struct *check_mem_permission(struct task_struct *task)
+-{
+- struct mm_struct *mm;
+- int err;
+-
+- /*
+- * Avoid racing if task exec's as we might get a new mm but validate
+- * against old credentials.
+- */
+- err = mutex_lock_killable(&task->signal->cred_guard_mutex);
+- if (err)
+- return ERR_PTR(err);
+-
+- mm = __check_mem_permission(task);
+- mutex_unlock(&task->signal->cred_guard_mutex);
+-
+- return mm;
+-}
+-
+-struct mm_struct *mm_for_maps(struct task_struct *task)
++static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
+ {
+ struct mm_struct *mm;
+ int err;
+@@ -262,16 +220,23 @@ struct mm_struct *mm_for_maps(struct task_struct *task)
+ return ERR_PTR(err);
+
+ mm = get_task_mm(task);
+- if (mm && mm != current->mm &&
+- !ptrace_may_access(task, PTRACE_MODE_READ)) {
+- mmput(mm);
+- mm = ERR_PTR(-EACCES);
++ if (mm) {
++ if ((mm != current->mm && !ptrace_may_access(task, mode)) ||
++ (gr_handle_proc_ptrace(task) || gr_acl_handle_procpidmem(task))) {
++ mmput(mm);
++ mm = ERR_PTR(-EACCES);
++ }
+ }
+ mutex_unlock(&task->signal->cred_guard_mutex);
+
+ return mm;
+ }
-+ if (gr_handle_proc_ptrace(task) || gr_acl_handle_procpidmem(task))
-+ return ERR_PTR(-EPERM);
++struct mm_struct *mm_for_maps(struct task_struct *task)
++{
++ return mm_access(task, PTRACE_MODE_READ);
++}
+
- /*
- * If current is actively ptrace'ing, and would also be
- * permitted to freshly attach with ptrace now, permit it.
-@@ -282,6 +301,9 @@ static int proc_pid_cmdline(struct task_struct *task, char * buffer)
+ static int proc_pid_cmdline(struct task_struct *task, char * buffer)
+ {
+ int res = 0;
+@@ -282,6 +247,9 @@ static int proc_pid_cmdline(struct task_struct *task, char * buffer)
if (!mm->arg_end)
goto out_mm; /* Shh! No looking before we're done */
@@ -48413,7 +48499,7 @@ index 5eb0206..fe01db4 100644
len = mm->arg_end - mm->arg_start;
if (len > PAGE_SIZE)
-@@ -309,12 +331,28 @@ out:
+@@ -309,12 +277,28 @@ out:
return res;
}
@@ -48442,7 +48528,7 @@ index 5eb0206..fe01db4 100644
do {
nwords += 2;
} while (mm->saved_auxv[nwords - 2] != 0); /* AT_NULL */
-@@ -328,7 +366,7 @@ static int proc_pid_auxv(struct task_struct *task, char *buffer)
+@@ -328,7 +312,7 @@ static int proc_pid_auxv(struct task_struct *task, char *buffer)
}
@@ -48451,7 +48537,7 @@ index 5eb0206..fe01db4 100644
/*
* Provides a wchan file via kallsyms in a proper one-value-per-file format.
* Returns the resolved symbol. If that fails, simply return the address.
-@@ -367,7 +405,7 @@ static void unlock_trace(struct task_struct *task)
+@@ -367,7 +351,7 @@ static void unlock_trace(struct task_struct *task)
mutex_unlock(&task->signal->cred_guard_mutex);
}
@@ -48460,7 +48546,7 @@ index 5eb0206..fe01db4 100644
#define MAX_STACK_TRACE_DEPTH 64
-@@ -558,7 +596,7 @@ static int proc_pid_limits(struct task_struct *task, char *buffer)
+@@ -558,7 +542,7 @@ static int proc_pid_limits(struct task_struct *task, char *buffer)
return count;
}
@@ -48469,7 +48555,7 @@ index 5eb0206..fe01db4 100644
static int proc_pid_syscall(struct task_struct *task, char *buffer)
{
long nr;
-@@ -587,7 +625,7 @@ static int proc_pid_syscall(struct task_struct *task, char *buffer)
+@@ -587,7 +571,7 @@ static int proc_pid_syscall(struct task_struct *task, char *buffer)
/************************************************************************/
/* permission checks */
@@ -48478,7 +48564,7 @@ index 5eb0206..fe01db4 100644
{
struct task_struct *task;
int allowed = 0;
-@@ -597,7 +635,10 @@ static int proc_fd_access_allowed(struct inode *inode)
+@@ -597,7 +581,10 @@ static int proc_fd_access_allowed(struct inode *inode)
*/
task = get_proc_task(inode);
if (task) {
@@ -48490,7 +48576,154 @@ index 5eb0206..fe01db4 100644
put_task_struct(task);
}
return allowed;
-@@ -978,6 +1019,9 @@ static ssize_t environ_read(struct file *file, char __user *buf,
+@@ -816,38 +803,39 @@ static const struct file_operations proc_single_file_operations = {
+
+ static int mem_open(struct inode* inode, struct file* file)
+ {
+- file->private_data = (void*)((long)current->self_exec_id);
++ struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
++ struct mm_struct *mm;
++
++ if (!task)
++ return -ESRCH;
++
++ mm = mm_access(task, PTRACE_MODE_ATTACH);
++ put_task_struct(task);
++
++ if (IS_ERR(mm))
++ return PTR_ERR(mm);
++
+ /* OK to pass negative loff_t, we can catch out-of-range */
+ file->f_mode |= FMODE_UNSIGNED_OFFSET;
++ file->private_data = mm;
++
+ return 0;
+ }
+
+ static ssize_t mem_read(struct file * file, char __user * buf,
+ size_t count, loff_t *ppos)
+ {
+- struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
++ int ret;
+ char *page;
+ unsigned long src = *ppos;
+- int ret = -ESRCH;
+- struct mm_struct *mm;
++ struct mm_struct *mm = file->private_data;
+
+- if (!task)
+- goto out_no_task;
++ if (!mm)
++ return 0;
+
+- ret = -ENOMEM;
+ page = (char *)__get_free_page(GFP_TEMPORARY);
+ if (!page)
+- goto out;
+-
+- mm = check_mem_permission(task);
+- ret = PTR_ERR(mm);
+- if (IS_ERR(mm))
+- goto out_free;
+-
+- ret = -EIO;
+-
+- if (file->private_data != (void*)((long)current->self_exec_id))
+- goto out_put;
++ return -ENOMEM;
+
+ ret = 0;
+
+@@ -874,42 +862,28 @@ static ssize_t mem_read(struct file * file, char __user * buf,
+ }
+ *ppos = src;
+
+-out_put:
+- mmput(mm);
+-out_free:
+ free_page((unsigned long) page);
+-out:
+- put_task_struct(task);
+-out_no_task:
+ return ret;
+ }
+
++#define mem_write NULL
++
++#ifndef mem_write
++/* They were right the first time */
+ static ssize_t mem_write(struct file * file, const char __user *buf,
+ size_t count, loff_t *ppos)
+ {
+ int copied;
+ char *page;
+- struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode);
+ unsigned long dst = *ppos;
+- struct mm_struct *mm;
++ struct mm_struct *mm = file->private_data;
+
+- copied = -ESRCH;
+- if (!task)
+- goto out_no_task;
++ if (!mm)
++ return 0;
+
+- copied = -ENOMEM;
+ page = (char *)__get_free_page(GFP_TEMPORARY);
+ if (!page)
+- goto out_task;
+-
+- mm = check_mem_permission(task);
+- copied = PTR_ERR(mm);
+- if (IS_ERR(mm))
+- goto out_free;
+-
+- copied = -EIO;
+- if (file->private_data != (void *)((long)current->self_exec_id))
+- goto out_mm;
++ return -ENOMEM;
+
+ copied = 0;
+ while (count > 0) {
+@@ -933,15 +907,10 @@ static ssize_t mem_write(struct file * file, const char __user *buf,
+ }
+ *ppos = dst;
+
+-out_mm:
+- mmput(mm);
+-out_free:
+ free_page((unsigned long) page);
+-out_task:
+- put_task_struct(task);
+-out_no_task:
+ return copied;
+ }
++#endif
+
+ loff_t mem_lseek(struct file *file, loff_t offset, int orig)
+ {
+@@ -959,11 +928,20 @@ loff_t mem_lseek(struct file *file, loff_t offset, int orig)
+ return file->f_pos;
+ }
+
++static int mem_release(struct inode *inode, struct file *file)
++{
++ struct mm_struct *mm = file->private_data;
++
++ mmput(mm);
++ return 0;
++}
++
+ static const struct file_operations proc_mem_operations = {
+ .llseek = mem_lseek,
+ .read = mem_read,
+ .write = mem_write,
+ .open = mem_open,
++ .release = mem_release,
+ };
+
+ static ssize_t environ_read(struct file *file, char __user *buf,
+@@ -978,6 +956,9 @@ static ssize_t environ_read(struct file *file, char __user *buf,
if (!task)
goto out_no_task;
@@ -48500,7 +48733,7 @@ index 5eb0206..fe01db4 100644
ret = -ENOMEM;
page = (char *)__get_free_page(GFP_TEMPORARY);
if (!page)
-@@ -1613,7 +1657,7 @@ static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
+@@ -1613,7 +1594,7 @@ static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
path_put(&nd->path);
/* Are we allowed to snoop on the tasks file descriptors? */
@@ -48509,7 +48742,7 @@ index 5eb0206..fe01db4 100644
goto out;
error = PROC_I(inode)->op.proc_get_link(inode, &nd->path);
-@@ -1652,8 +1696,18 @@ static int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int b
+@@ -1652,8 +1633,18 @@ static int proc_pid_readlink(struct dentry * dentry, char __user * buffer, int b
struct path path;
/* Are we allowed to snoop on the tasks file descriptors? */
@@ -48530,7 +48763,7 @@ index 5eb0206..fe01db4 100644
error = PROC_I(inode)->op.proc_get_link(inode, &path);
if (error)
-@@ -1718,7 +1772,11 @@ struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *t
+@@ -1718,7 +1709,11 @@ struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *t
rcu_read_lock();
cred = __task_cred(task);
inode->i_uid = cred->euid;
@@ -48542,7 +48775,7 @@ index 5eb0206..fe01db4 100644
rcu_read_unlock();
}
security_task_to_inode(task, inode);
-@@ -1736,6 +1794,9 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+@@ -1736,6 +1731,9 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
struct inode *inode = dentry->d_inode;
struct task_struct *task;
const struct cred *cred;
@@ -48552,7 +48785,7 @@ index 5eb0206..fe01db4 100644
generic_fillattr(inode, stat);
-@@ -1743,13 +1804,41 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+@@ -1743,13 +1741,41 @@ int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
stat->uid = 0;
stat->gid = 0;
task = pid_task(proc_pid(inode), PIDTYPE_PID);
@@ -48595,7 +48828,7 @@ index 5eb0206..fe01db4 100644
}
rcu_read_unlock();
return 0;
-@@ -1786,11 +1875,20 @@ int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
+@@ -1786,11 +1812,20 @@ int pid_revalidate(struct dentry *dentry, struct nameidata *nd)
if (task) {
if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
@@ -48616,7 +48849,7 @@ index 5eb0206..fe01db4 100644
rcu_read_unlock();
} else {
inode->i_uid = 0;
-@@ -1908,7 +2006,8 @@ static int proc_fd_info(struct inode *inode, struct path *path, char *info)
+@@ -1908,7 +1943,8 @@ static int proc_fd_info(struct inode *inode, struct path *path, char *info)
int fd = proc_fd(inode);
if (task) {
@@ -48626,7 +48859,7 @@ index 5eb0206..fe01db4 100644
put_task_struct(task);
}
if (files) {
-@@ -2176,11 +2275,21 @@ static const struct file_operations proc_fd_operations = {
+@@ -2176,11 +2212,21 @@ static const struct file_operations proc_fd_operations = {
*/
static int proc_fd_permission(struct inode *inode, int mask)
{
@@ -48650,7 +48883,7 @@ index 5eb0206..fe01db4 100644
return rv;
}
-@@ -2290,6 +2399,9 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
+@@ -2290,6 +2336,9 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
if (!task)
goto out_no_task;
@@ -48660,7 +48893,7 @@ index 5eb0206..fe01db4 100644
/*
* Yes, it does not scale. And it should not. Don't add
* new entries into /proc/<tgid>/ without very good reasons.
-@@ -2334,6 +2446,9 @@ static int proc_pident_readdir(struct file *filp,
+@@ -2334,6 +2383,9 @@ static int proc_pident_readdir(struct file *filp,
if (!task)
goto out_no_task;
@@ -48670,7 +48903,7 @@ index 5eb0206..fe01db4 100644
ret = 0;
i = filp->f_pos;
switch (i) {
-@@ -2604,7 +2719,7 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
+@@ -2604,7 +2656,7 @@ static void *proc_self_follow_link(struct dentry *dentry, struct nameidata *nd)
static void proc_self_put_link(struct dentry *dentry, struct nameidata *nd,
void *cookie)
{
@@ -48679,7 +48912,7 @@ index 5eb0206..fe01db4 100644
if (!IS_ERR(s))
__putname(s);
}
-@@ -2802,7 +2917,7 @@ static const struct pid_entry tgid_base_stuff[] = {
+@@ -2802,7 +2854,7 @@ static const struct pid_entry tgid_base_stuff[] = {
REG("autogroup", S_IRUGO|S_IWUSR, proc_pid_sched_autogroup_operations),
#endif
REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
@@ -48688,7 +48921,7 @@ index 5eb0206..fe01db4 100644
INF("syscall", S_IRUGO, proc_pid_syscall),
#endif
INF("cmdline", S_IRUGO, proc_pid_cmdline),
-@@ -2827,10 +2942,10 @@ static const struct pid_entry tgid_base_stuff[] = {
+@@ -2827,10 +2879,10 @@ static const struct pid_entry tgid_base_stuff[] = {
#ifdef CONFIG_SECURITY
DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations),
#endif
@@ -48701,7 +48934,7 @@ index 5eb0206..fe01db4 100644
ONE("stack", S_IRUGO, proc_pid_stack),
#endif
#ifdef CONFIG_SCHEDSTATS
-@@ -2864,6 +2979,9 @@ static const struct pid_entry tgid_base_stuff[] = {
+@@ -2864,6 +2916,9 @@ static const struct pid_entry tgid_base_stuff[] = {
#ifdef CONFIG_HARDWALL
INF("hardwall", S_IRUGO, proc_pid_hardwall),
#endif
@@ -48711,7 +48944,7 @@ index 5eb0206..fe01db4 100644
};
static int proc_tgid_base_readdir(struct file * filp,
-@@ -2989,7 +3107,14 @@ static struct dentry *proc_pid_instantiate(struct inode *dir,
+@@ -2989,7 +3044,14 @@ static struct dentry *proc_pid_instantiate(struct inode *dir,
if (!inode)
goto out;
@@ -48726,7 +48959,7 @@ index 5eb0206..fe01db4 100644
inode->i_op = &proc_tgid_base_inode_operations;
inode->i_fop = &proc_tgid_base_operations;
inode->i_flags|=S_IMMUTABLE;
-@@ -3031,7 +3156,11 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct
+@@ -3031,7 +3093,11 @@ struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct
if (!task)
goto out;
@@ -48738,7 +48971,7 @@ index 5eb0206..fe01db4 100644
put_task_struct(task);
out:
return result;
-@@ -3096,6 +3225,11 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
+@@ -3096,6 +3162,11 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
{
unsigned int nr;
struct task_struct *reaper;
@@ -48750,7 +48983,7 @@ index 5eb0206..fe01db4 100644
struct tgid_iter iter;
struct pid_namespace *ns;
-@@ -3119,8 +3253,27 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
+@@ -3119,8 +3190,27 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
for (iter = next_tgid(ns, iter);
iter.task;
iter.tgid += 1, iter = next_tgid(ns, iter)) {
@@ -48779,7 +49012,7 @@ index 5eb0206..fe01db4 100644
put_task_struct(iter.task);
goto out;
}
-@@ -3148,7 +3301,7 @@ static const struct pid_entry tid_base_stuff[] = {
+@@ -3148,7 +3238,7 @@ static const struct pid_entry tid_base_stuff[] = {
REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
#endif
REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
@@ -48788,7 +49021,7 @@ index 5eb0206..fe01db4 100644
INF("syscall", S_IRUGO, proc_pid_syscall),
#endif
INF("cmdline", S_IRUGO, proc_pid_cmdline),
-@@ -3172,10 +3325,10 @@ static const struct pid_entry tid_base_stuff[] = {
+@@ -3172,10 +3262,10 @@ static const struct pid_entry tid_base_stuff[] = {
#ifdef CONFIG_SECURITY
DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations),
#endif
@@ -60890,22 +61123,10 @@ index e9eaec5..bfeb9bb 100644
static inline void set_mems_allowed(nodemask_t nodemask)
diff --git a/include/linux/cred.h b/include/linux/cred.h
-index 4030896..a5c9f09 100644
+index 4030896..8d6f342 100644
--- a/include/linux/cred.h
+++ b/include/linux/cred.h
-@@ -196,6 +196,11 @@ do { \
- __validate_process_creds(current, __FILE__, __LINE__); \
- } while(0)
-
-+#define validate_task_creds(task) \
-+do { \
-+ __validate_process_creds((task), __FILE__, __LINE__); \
-+} while(0)
-+
- extern void validate_creds_for_do_exit(struct task_struct *);
- #else
- static inline void validate_creds(const struct cred *cred)
-@@ -207,6 +212,9 @@ static inline void validate_creds_for_do_exit(struct task_struct *tsk)
+@@ -207,6 +207,9 @@ static inline void validate_creds_for_do_exit(struct task_struct *tsk)
static inline void validate_process_creds(void)
{
}
@@ -63309,7 +63530,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 41d0237..5a64056 100644
+index 41d0237..51dd96c 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -100,6 +100,7 @@ struct bio_list;
@@ -63418,13 +63639,14 @@ index 41d0237..5a64056 100644
#ifdef CONFIG_DEBUG_MUTEXES
/* mutex deadlock detection */
struct mutex_waiter *blocked_on;
-@@ -1537,6 +1563,21 @@ struct task_struct {
+@@ -1537,6 +1563,22 @@ struct task_struct {
unsigned long default_timer_slack_ns;
struct list_head *scm_work_list;
+
+#ifdef CONFIG_GRKERNSEC
+ /* grsecurity */
++ const struct cred *delayed_cred;
+ struct dentry *gr_chroot_dentry;
+ struct acl_subject_label *acl;
+ struct acl_role_label *role;
@@ -63440,7 +63662,7 @@ index 41d0237..5a64056 100644
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
/* Index of current stored address in ret_stack */
int curr_ret_stack;
-@@ -1571,6 +1612,57 @@ struct task_struct {
+@@ -1571,6 +1613,57 @@ struct task_struct {
#endif
};
@@ -63498,7 +63720,7 @@ index 41d0237..5a64056 100644
/* Future-safe accessor for struct task_struct's cpus_allowed. */
#define tsk_cpus_allowed(tsk) (&(tsk)->cpus_allowed)
-@@ -2074,7 +2166,9 @@ void yield(void);
+@@ -2074,7 +2167,9 @@ void yield(void);
extern struct exec_domain default_exec_domain;
union thread_union {
@@ -63508,7 +63730,7 @@ index 41d0237..5a64056 100644
unsigned long stack[THREAD_SIZE/sizeof(long)];
};
-@@ -2107,6 +2201,7 @@ extern struct pid_namespace init_pid_ns;
+@@ -2107,6 +2202,7 @@ extern struct pid_namespace init_pid_ns;
*/
extern struct task_struct *find_task_by_vpid(pid_t nr);
@@ -63516,7 +63738,7 @@ index 41d0237..5a64056 100644
extern struct task_struct *find_task_by_pid_ns(pid_t nr,
struct pid_namespace *ns);
-@@ -2243,7 +2338,7 @@ extern void __cleanup_sighand(struct sighand_struct *);
+@@ -2243,7 +2339,7 @@ extern void __cleanup_sighand(struct sighand_struct *);
extern void exit_itimers(struct signal_struct *);
extern void flush_itimer_signals(void);
@@ -63525,7 +63747,7 @@ index 41d0237..5a64056 100644
extern void daemonize(const char *, ...);
extern int allow_signal(int);
-@@ -2408,13 +2503,17 @@ static inline unsigned long *end_of_stack(struct task_struct *p)
+@@ -2408,13 +2504,17 @@ static inline unsigned long *end_of_stack(struct task_struct *p)
#endif
@@ -65360,7 +65582,7 @@ index c8e00f8..1135c4e 100644
if (nsops < 1 || semid < 0)
diff --git a/ipc/shm.c b/ipc/shm.c
-index 02ecf2c..c8f5627 100644
+index 02ecf2c..be05b1e 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -69,6 +69,14 @@ static void shm_destroy (struct ipc_namespace *ns, struct shmid_kernel *shp);
@@ -65427,7 +65649,20 @@ index 02ecf2c..c8f5627 100644
lru_add_drain_all(); /* drain pagevecs to lru lists */
shp = shm_lock_check(ns, shmid);
-@@ -1004,9 +1019,21 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
+@@ -981,6 +996,12 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
+ f_mode = FMODE_READ | FMODE_WRITE;
+ }
+ if (shmflg & SHM_EXEC) {
++
++#ifdef CONFIG_PAX_MPROTECT
++ if (current->mm->pax_flags & MF_PAX_MPROTECT)
++ goto out;
++#endif
++
+ prot |= PROT_EXEC;
+ acc_mode |= S_IXUGO;
+ }
+@@ -1004,9 +1025,21 @@ long do_shmat(int shmid, char __user *shmaddr, int shmflg, ulong *raddr)
if (err)
goto out_unlock;
@@ -65822,7 +66057,7 @@ index 42e8fa0..9e7406b 100644
return -ENOMEM;
diff --git a/kernel/cred.c b/kernel/cred.c
-index 8ef31f5..7957d07 100644
+index 8ef31f5..bed28ea 100644
--- a/kernel/cred.c
+++ b/kernel/cred.c
@@ -158,6 +158,8 @@ static void put_cred_rcu(struct rcu_head *rcu)
@@ -65843,7 +66078,23 @@ index 8ef31f5..7957d07 100644
kdebug("exit_creds(%u,%p,%p,{%d,%d})", tsk->pid, tsk->real_cred, tsk->cred,
atomic_read(&tsk->cred->usage),
read_cred_subscribers(tsk->cred));
-@@ -220,6 +224,8 @@ const struct cred *get_task_cred(struct task_struct *task)
+@@ -204,6 +208,15 @@ void exit_creds(struct task_struct *tsk)
+ validate_creds(cred);
+ put_cred(cred);
+ }
++
++#ifdef CONFIG_GRKERNSEC_SETXID
++ cred = (struct cred *) tsk->delayed_cred;
++ if (cred) {
++ tsk->delayed_cred = NULL;
++ validate_creds(cred);
++ put_cred(cred);
++ }
++#endif
+ }
+
+ /**
+@@ -220,6 +233,8 @@ const struct cred *get_task_cred(struct task_struct *task)
{
const struct cred *cred;
@@ -65852,7 +66103,7 @@ index 8ef31f5..7957d07 100644
rcu_read_lock();
do {
-@@ -239,6 +245,8 @@ struct cred *cred_alloc_blank(void)
+@@ -239,6 +254,8 @@ struct cred *cred_alloc_blank(void)
{
struct cred *new;
@@ -65861,38 +66112,23 @@ index 8ef31f5..7957d07 100644
new = kmem_cache_zalloc(cred_jar, GFP_KERNEL);
if (!new)
return NULL;
-@@ -281,13 +289,15 @@ error:
+@@ -281,12 +298,15 @@ error:
*
* Call commit_creds() or abort_creds() to clean up.
*/
--struct cred *prepare_creds(void)
+
-+static struct cred *__prepare_creds(struct task_struct *task)
+ struct cred *prepare_creds(void)
{
-- struct task_struct *task = current;
+ struct task_struct *task = current;
const struct cred *old;
struct cred *new;
-- validate_process_creds();
+ pax_track_stack();
+
-+ validate_task_creds(task);
+ validate_process_creds();
new = kmem_cache_alloc(cred_jar, GFP_KERNEL);
- if (!new)
-@@ -322,6 +332,11 @@ error:
- abort_creds(new);
- return NULL;
- }
-+
-+struct cred *prepare_creds(void)
-+{
-+ return __prepare_creds(current);
-+}
- EXPORT_SYMBOL(prepare_creds);
-
- /*
-@@ -333,6 +348,8 @@ struct cred *prepare_exec_creds(void)
+@@ -333,6 +353,8 @@ struct cred *prepare_exec_creds(void)
struct thread_group_cred *tgcred = NULL;
struct cred *new;
@@ -65901,7 +66137,7 @@ index 8ef31f5..7957d07 100644
#ifdef CONFIG_KEYS
tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
if (!tgcred)
-@@ -385,6 +402,8 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
+@@ -385,6 +407,8 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags)
struct cred *new;
int ret;
@@ -65910,14 +66146,14 @@ index 8ef31f5..7957d07 100644
if (
#ifdef CONFIG_KEYS
!p->cred->thread_keyring &&
-@@ -470,11 +489,12 @@ error_put:
+@@ -470,11 +494,13 @@ error_put:
* Always returns 0 thus allowing this function to be tail-called at the end
* of, say, sys_setgid().
*/
-int commit_creds(struct cred *new)
-+static int __commit_creds(struct task_struct *task, struct cred *new)
++static int __commit_creds(struct cred *new)
{
-- struct task_struct *task = current;
+ struct task_struct *task = current;
const struct cred *old = task->real_cred;
+ pax_track_stack();
@@ -65925,7 +66161,7 @@ index 8ef31f5..7957d07 100644
kdebug("commit_creds(%p{%d,%d})", new,
atomic_read(&new->usage),
read_cred_subscribers(new));
-@@ -489,6 +509,8 @@ int commit_creds(struct cred *new)
+@@ -489,6 +515,8 @@ int commit_creds(struct cred *new)
get_cred(new); /* we will require a ref for the subj creds too */
@@ -65934,22 +66170,66 @@ index 8ef31f5..7957d07 100644
/* dumpability changes */
if (old->euid != new->euid ||
old->egid != new->egid ||
-@@ -538,6 +560,87 @@ int commit_creds(struct cred *new)
+@@ -538,6 +566,92 @@ int commit_creds(struct cred *new)
put_cred(old);
return 0;
}
-+
+#ifdef CONFIG_GRKERNSEC_SETXID
-+static int set_task_user(struct user_namespace *user_ns, struct cred *new)
++extern int set_user(struct cred *new);
++
++void gr_delayed_cred_worker(void)
+{
-+ struct user_struct *new_user;
++ const struct cred *new = current->delayed_cred;
++ struct cred *ncred;
+
-+ new_user = alloc_uid(user_ns, new->uid);
-+ if (!new_user)
-+ return -EAGAIN;
-+ free_uid(new->user);
-+ new->user = new_user;
-+ return 0;
++ current->delayed_cred = NULL;
++
++ if (current_uid() && new != NULL) {
++ // from doing get_cred on it when queueing this
++ put_cred(new);
++ return;
++ } else if (new == NULL)
++ return;
++
++ ncred = prepare_creds();
++ if (!ncred)
++ goto die;
++ // uids
++ ncred->uid = new->uid;
++ ncred->euid = new->euid;
++ ncred->suid = new->suid;
++ ncred->fsuid = new->fsuid;
++ // gids
++ ncred->gid = new->gid;
++ ncred->egid = new->egid;
++ ncred->sgid = new->sgid;
++ ncred->fsgid = new->fsgid;
++ // groups
++ if (set_groups(ncred, new->group_info) < 0) {
++ abort_creds(ncred);
++ goto die;
++ }
++ // caps
++ ncred->securebits = new->securebits;
++ ncred->cap_inheritable = new->cap_inheritable;
++ ncred->cap_permitted = new->cap_permitted;
++ ncred->cap_effective = new->cap_effective;
++ ncred->cap_bset = new->cap_bset;
++
++ if (set_user(ncred)) {
++ abort_creds(ncred);
++ goto die;
++ }
++
++ // from doing get_cred on it when queueing this
++ put_cred(new);
++
++ __commit_creds(ncred);
++ return;
++die:
++ // from doing get_cred on it when queueing this
++ put_cred(new);
++ do_group_exit(SIGKILL);
+}
+#endif
+
@@ -65957,8 +66237,6 @@ index 8ef31f5..7957d07 100644
+{
+#ifdef CONFIG_GRKERNSEC_SETXID
+ struct task_struct *t;
-+ struct cred *ncred;
-+ const struct cred *old;
+
+ /* we won't get called with tasklist_lock held for writing
+ and interrupts disabled as the cred struct in that case is
@@ -65970,59 +66248,22 @@ index 8ef31f5..7957d07 100644
+ read_lock(&tasklist_lock);
+ for (t = next_thread(current); t != current;
+ t = next_thread(t)) {
-+ old = __task_cred(t);
-+ if (old->uid)
-+ continue;
-+ ncred = __prepare_creds(t);
-+ if (!ncred)
-+ goto die;
-+ // uids
-+ ncred->uid = new->uid;
-+ ncred->euid = new->euid;
-+ ncred->suid = new->suid;
-+ ncred->fsuid = new->fsuid;
-+ // gids
-+ ncred->gid = new->gid;
-+ ncred->egid = new->egid;
-+ ncred->sgid = new->sgid;
-+ ncred->fsgid = new->fsgid;
-+ // groups
-+ if (set_groups(ncred, new->group_info) < 0) {
-+ abort_creds(ncred);
-+ goto die;
-+ }
-+ // caps
-+ ncred->securebits = new->securebits;
-+ ncred->cap_inheritable = new->cap_inheritable;
-+ ncred->cap_permitted = new->cap_permitted;
-+ ncred->cap_effective = new->cap_effective;
-+ ncred->cap_bset = new->cap_bset;
-+
-+ if (set_task_user(old->user_ns, ncred)) {
-+ abort_creds(ncred);
-+ goto die;
++ if (t->delayed_cred == NULL) {
++ t->delayed_cred = get_cred(new);
++ set_tsk_need_resched(t);
+ }
-+
-+ __commit_creds(t, ncred);
+ }
+ read_unlock(&tasklist_lock);
+ rcu_read_unlock();
+ }
+#endif
-+ return __commit_creds(current, new);
-+#ifdef CONFIG_GRKERNSEC_SETXID
-+die:
-+ read_unlock(&tasklist_lock);
-+ rcu_read_unlock();
-+ abort_creds(new);
-+ do_group_exit(SIGKILL);
-+#endif
++ return __commit_creds(new);
+}
+
EXPORT_SYMBOL(commit_creds);
/**
-@@ -549,6 +652,8 @@ EXPORT_SYMBOL(commit_creds);
+@@ -549,6 +663,8 @@ EXPORT_SYMBOL(commit_creds);
*/
void abort_creds(struct cred *new)
{
@@ -66031,7 +66272,7 @@ index 8ef31f5..7957d07 100644
kdebug("abort_creds(%p{%d,%d})", new,
atomic_read(&new->usage),
read_cred_subscribers(new));
-@@ -572,6 +677,8 @@ const struct cred *override_creds(const struct cred *new)
+@@ -572,6 +688,8 @@ const struct cred *override_creds(const struct cred *new)
{
const struct cred *old = current->cred;
@@ -66040,7 +66281,7 @@ index 8ef31f5..7957d07 100644
kdebug("override_creds(%p{%d,%d})", new,
atomic_read(&new->usage),
read_cred_subscribers(new));
-@@ -601,6 +708,8 @@ void revert_creds(const struct cred *old)
+@@ -601,6 +719,8 @@ void revert_creds(const struct cred *old)
{
const struct cred *override = current->cred;
@@ -66049,7 +66290,7 @@ index 8ef31f5..7957d07 100644
kdebug("revert_creds(%p{%d,%d})", old,
atomic_read(&old->usage),
read_cred_subscribers(old));
-@@ -647,6 +756,8 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
+@@ -647,6 +767,8 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon)
const struct cred *old;
struct cred *new;
@@ -66058,7 +66299,7 @@ index 8ef31f5..7957d07 100644
new = kmem_cache_alloc(cred_jar, GFP_KERNEL);
if (!new)
return NULL;
-@@ -701,6 +812,8 @@ EXPORT_SYMBOL(prepare_kernel_cred);
+@@ -701,6 +823,8 @@ EXPORT_SYMBOL(prepare_kernel_cred);
*/
int set_security_override(struct cred *new, u32 secid)
{
@@ -66067,7 +66308,7 @@ index 8ef31f5..7957d07 100644
return security_kernel_act_as(new, secid);
}
EXPORT_SYMBOL(set_security_override);
-@@ -720,6 +833,8 @@ int set_security_override_from_ctx(struct cred *new, const char *secctx)
+@@ -720,6 +844,8 @@ int set_security_override_from_ctx(struct cred *new, const char *secctx)
u32 secid;
int ret;
@@ -69005,10 +69246,30 @@ index 5c9ccd3..a35e22b 100644
default:
diff --git a/kernel/sched.c b/kernel/sched.c
-index b50b0f0..1c6c591 100644
+index b50b0f0..91e9aed 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
-@@ -4264,6 +4264,8 @@ static void __sched __schedule(void)
+@@ -4254,6 +4254,19 @@ pick_next_task(struct rq *rq)
+ BUG(); /* the idle class will always have a runnable task */
+ }
+
++#ifdef CONFIG_GRKERNSEC_SETXID
++extern void gr_delayed_cred_worker(void);
++static inline void gr_cred_schedule(void)
++{
++ if (unlikely(current->delayed_cred))
++ gr_delayed_cred_worker();
++}
++#else
++static inline void gr_cred_schedule(void)
++{
++}
++#endif
++
+ /*
+ * __schedule() is the main scheduler function.
+ */
+@@ -4264,6 +4277,8 @@ static void __sched __schedule(void)
struct rq *rq;
int cpu;
@@ -69017,7 +69278,16 @@ index b50b0f0..1c6c591 100644
need_resched:
preempt_disable();
cpu = smp_processor_id();
-@@ -4950,6 +4952,8 @@ int can_nice(const struct task_struct *p, const int nice)
+@@ -4273,6 +4288,8 @@ need_resched:
+
+ schedule_debug(prev);
+
++ gr_cred_schedule();
++
+ if (sched_feat(HRTICK))
+ hrtick_clear(rq);
+
+@@ -4950,6 +4967,8 @@ int can_nice(const struct task_struct *p, const int nice)
/* convert nice value [19,-20] to rlimit style value [1,40] */
int nice_rlim = 20 - nice;
@@ -69026,7 +69296,7 @@ index b50b0f0..1c6c591 100644
return (nice_rlim <= task_rlimit(p, RLIMIT_NICE) ||
capable(CAP_SYS_NICE));
}
-@@ -4983,7 +4987,8 @@ SYSCALL_DEFINE1(nice, int, increment)
+@@ -4983,7 +5002,8 @@ SYSCALL_DEFINE1(nice, int, increment)
if (nice > 19)
nice = 19;
@@ -69036,7 +69306,7 @@ index b50b0f0..1c6c591 100644
return -EPERM;
retval = security_task_setnice(current, nice);
-@@ -5127,6 +5132,7 @@ recheck:
+@@ -5127,6 +5147,7 @@ recheck:
unsigned long rlim_rtprio =
task_rlimit(p, RLIMIT_RTPRIO);
@@ -69301,7 +69571,7 @@ index fca82c3..1db9690 100644
struct tasklet_struct *list;
diff --git a/kernel/sys.c b/kernel/sys.c
-index 1dbbe69..e96e1dd 100644
+index 1dbbe69..6d0c5d8 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -157,6 +157,12 @@ static int set_one_prio(struct task_struct *p, int niceval, int error)
@@ -69338,6 +69608,15 @@ index 1dbbe69..e96e1dd 100644
if (nsown_capable(CAP_SETGID))
new->gid = new->egid = new->sgid = new->fsgid = gid;
else if (gid == old->gid || gid == old->sgid)
+@@ -617,7 +630,7 @@ error:
+ /*
+ * change the user struct in a credentials set to match the new UID
+ */
+-static int set_user(struct cred *new)
++int set_user(struct cred *new)
+ {
+ struct user_struct *new_user;
+
@@ -687,6 +700,9 @@ SYSCALL_DEFINE2(setreuid, uid_t, ruid, uid_t, euid)
goto error;
}