summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <greg@kroah.com>2002-07-19 02:01:00 -0700
committerGreg Kroah-Hartman <greg@kroah.com>2002-07-19 02:01:00 -0700
commit1c0fe622c8847e1caab384a81cf96de2f1ac05d8 (patch)
treeea83fc894fbd386dba63ddeac33c7be5a729978d /kernel
parent2b15fe6334aebd7d3340f8b826acb79b138afa74 (diff)
LSM: Enable the security framework. This includes basic task control hooks.
Diffstat (limited to 'kernel')
-rw-r--r--kernel/capability.c19
-rw-r--r--kernel/exit.c11
-rw-r--r--kernel/fork.c13
-rw-r--r--kernel/kmod.c2
-rw-r--r--kernel/ptrace.c8
-rw-r--r--kernel/sched.c41
-rw-r--r--kernel/signal.c3
-rw-r--r--kernel/sys.c178
-rw-r--r--kernel/uid16.c8
9 files changed, 169 insertions, 114 deletions
diff --git a/kernel/capability.c b/kernel/capability.c
index 5796b182005c..223d22dece42 100644
--- a/kernel/capability.c
+++ b/kernel/capability.c
@@ -63,6 +63,7 @@ asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr)
data.permitted = cap_t(target->cap_permitted);
data.inheritable = cap_t(target->cap_inheritable);
data.effective = cap_t(target->cap_effective);
+ ret = security_ops->capget(target, &data.effective, &data.inheritable, &data.permitted);
out:
read_unlock(&tasklist_lock);
@@ -87,9 +88,7 @@ static inline void cap_set_pg(int pgrp, kernel_cap_t *effective,
for_each_task(target) {
if (target->pgrp != pgrp)
continue;
- target->cap_effective = *effective;
- target->cap_inheritable = *inheritable;
- target->cap_permitted = *permitted;
+ security_ops->capset_set(target, effective, inheritable, permitted);
}
}
@@ -106,9 +105,7 @@ static inline void cap_set_all(kernel_cap_t *effective,
for_each_task(target) {
if (target == current || target->pid == 1)
continue;
- target->cap_effective = *effective;
- target->cap_inheritable = *inheritable;
- target->cap_permitted = *permitted;
+ security_ops->capset_set(target, effective, inheritable, permitted);
}
}
@@ -166,7 +163,9 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
ret = -EPERM;
- /* verify restrictions on target's new Inheritable set */
+ if (security_ops->capset_check(target, &effective, &inheritable, &permitted))
+ goto out;
+
if (!cap_issubset(inheritable, cap_combine(target->cap_inheritable,
current->cap_permitted)))
goto out;
@@ -182,6 +181,8 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
ret = 0;
+ /* having verified that the proposed changes are legal,
+ we now put them into effect. */
if (pid < 0) {
if (pid == -1) /* all procs other than current and init */
cap_set_all(&effective, &inheritable, &permitted);
@@ -189,9 +190,7 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data)
else /* all procs in process group */
cap_set_pg(-pid, &effective, &inheritable, &permitted);
} else {
- target->cap_effective = effective;
- target->cap_inheritable = inheritable;
- target->cap_permitted = permitted;
+ security_ops->capset_set(target, &effective, &inheritable, &permitted);
}
out:
diff --git a/kernel/exit.c b/kernel/exit.c
index c47a4c045fea..f727a3c511c8 100644
--- a/kernel/exit.c
+++ b/kernel/exit.c
@@ -14,6 +14,7 @@
#include <linux/personality.h>
#include <linux/tty.h>
#include <linux/namespace.h>
+#include <linux/security.h>
#include <linux/acct.h>
#include <linux/file.h>
#include <linux/binfmts.h>
@@ -61,6 +62,7 @@ static void release_task(struct task_struct * p)
wait_task_inactive(p);
#endif
atomic_dec(&p->user->processes);
+ security_ops->task_free_security(p);
free_uid(p->user);
unhash_process(p);
@@ -187,10 +189,7 @@ void reparent_to_init(void)
/* cpus_allowed? */
/* rt_priority? */
/* signals? */
- current->cap_effective = CAP_INIT_EFF_SET;
- current->cap_inheritable = CAP_INIT_INH_SET;
- current->cap_permitted = CAP_FULL_SET;
- current->keep_capabilities = 0;
+ security_ops->task_reparent_to_init(current);
memcpy(current->rlim, init_task.rlim, sizeof(*(current->rlim)));
current->user = INIT_USER;
@@ -625,6 +624,10 @@ repeat:
if (((p->exit_signal != SIGCHLD) ^ ((options & __WCLONE) != 0))
&& !(options & __WALL))
continue;
+
+ if (security_ops->task_wait(p))
+ continue;
+
flag = 1;
switch (p->state) {
case TASK_STOPPED:
diff --git a/kernel/fork.c b/kernel/fork.c
index c0fb979902fe..f99f9e69521a 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -24,7 +24,7 @@
#include <linux/file.h>
#include <linux/binfmts.h>
#include <linux/fs.h>
-#include <linux/mm.h>
+#include <linux/security.h>
#include <asm/pgtable.h>
#include <asm/pgalloc.h>
@@ -618,6 +618,10 @@ struct task_struct *do_fork(unsigned long clone_flags,
if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS))
return ERR_PTR(-EINVAL);
+ retval = security_ops->task_create(clone_flags);
+ if (retval)
+ goto fork_out;
+
retval = -ENOMEM;
p = dup_task_struct(current);
if (!p)
@@ -697,13 +701,16 @@ struct task_struct *do_fork(unsigned long clone_flags,
p->array = NULL;
p->lock_depth = -1; /* -1 = no lock */
p->start_time = jiffies;
+ p->security = NULL;
INIT_LIST_HEAD(&p->local_pages);
retval = -ENOMEM;
+ if (security_ops->task_alloc_security(p))
+ goto bad_fork_cleanup;
/* copy all the process information */
if (copy_semundo(clone_flags, p))
- goto bad_fork_cleanup;
+ goto bad_fork_cleanup_security;
if (copy_files(clone_flags, p))
goto bad_fork_cleanup_semundo;
if (copy_fs(clone_flags, p))
@@ -812,6 +819,8 @@ bad_fork_cleanup_files:
exit_files(p); /* blocking */
bad_fork_cleanup_semundo:
exit_semundo(p);
+bad_fork_cleanup_security:
+ security_ops->task_free_security(p);
bad_fork_cleanup:
put_exec_domain(p->thread_info->exec_domain);
if (p->binfmt && p->binfmt->module)
diff --git a/kernel/kmod.c b/kernel/kmod.c
index 05388d9557fa..c3b7e90aecdc 100644
--- a/kernel/kmod.c
+++ b/kernel/kmod.c
@@ -134,7 +134,7 @@ int exec_usermodehelper(char *program_path, char *argv[], char *envp[])
/* Give kmod all effective privileges.. */
curtask->euid = curtask->fsuid = 0;
curtask->egid = curtask->fsgid = 0;
- cap_set_full(curtask->cap_effective);
+ security_ops->task_kmod_set_label();
/* Allow execve args to be in kernel space. */
set_fs(KERNEL_DS);
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 24d41164144e..1a64a0c03b95 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -41,7 +41,9 @@ int ptrace_check_attach(struct task_struct *child, int kill)
int ptrace_attach(struct task_struct *task)
{
+ int retval;
task_lock(task);
+ retval = -EPERM;
if (task->pid <= 1)
goto bad;
if (task == current)
@@ -53,7 +55,6 @@ int ptrace_attach(struct task_struct *task)
(current->uid != task->uid) ||
(current->gid != task->egid) ||
(current->gid != task->sgid) ||
- (!cap_issubset(task->cap_permitted, current->cap_permitted)) ||
(current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
goto bad;
rmb();
@@ -62,6 +63,9 @@ int ptrace_attach(struct task_struct *task)
/* the same process cannot be attached many times */
if (task->ptrace & PT_PTRACED)
goto bad;
+ retval = security_ops->ptrace(current, task);
+ if (retval)
+ goto bad;
/* Go */
task->ptrace |= PT_PTRACED;
@@ -82,7 +86,7 @@ int ptrace_attach(struct task_struct *task)
bad:
task_unlock(task);
- return -EPERM;
+ return retval;
}
int ptrace_detach(struct task_struct *child, unsigned int data)
diff --git a/kernel/sched.c b/kernel/sched.c
index 3b1d88b61521..c8a11b29794e 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -26,6 +26,7 @@
#include <linux/interrupt.h>
#include <linux/completion.h>
#include <linux/kernel_stat.h>
+#include <linux/security.h>
/*
* Convert user-nice values [ -20 ... 0 ... 19 ]
@@ -1123,6 +1124,7 @@ out_unlock:
asmlinkage long sys_nice(int increment)
{
+ int retval;
long nice;
/*
@@ -1144,6 +1146,11 @@ asmlinkage long sys_nice(int increment)
nice = -20;
if (nice > 19)
nice = 19;
+
+ retval = security_ops->task_setnice(current, nice);
+ if (retval)
+ return retval;
+
set_user_nice(current, nice);
return 0;
}
@@ -1236,6 +1243,10 @@ static int setscheduler(pid_t pid, int policy, struct sched_param *param)
!capable(CAP_SYS_NICE))
goto out_unlock;
+ retval = security_ops->task_setscheduler(p, policy, &lp);
+ if (retval)
+ goto out_unlock;
+
array = p->array;
if (array)
deactivate_task(p, task_rq(p));
@@ -1280,8 +1291,11 @@ asmlinkage long sys_sched_getscheduler(pid_t pid)
retval = -ESRCH;
read_lock(&tasklist_lock);
p = find_process_by_pid(pid);
- if (p)
- retval = p->policy;
+ if (p) {
+ retval = security_ops->task_getscheduler(p);
+ if (!retval)
+ retval = p->policy;
+ }
read_unlock(&tasklist_lock);
out_nounlock:
@@ -1302,6 +1316,11 @@ asmlinkage long sys_sched_getparam(pid_t pid, struct sched_param *param)
retval = -ESRCH;
if (!p)
goto out_unlock;
+
+ retval = security_ops->task_getscheduler(p);
+ if (retval)
+ goto out_unlock;
+
lp.sched_priority = p->rt_priority;
read_unlock(&tasklist_lock);
@@ -1509,14 +1528,22 @@ asmlinkage long sys_sched_rr_get_interval(pid_t pid, struct timespec *interval)
retval = -ESRCH;
read_lock(&tasklist_lock);
p = find_process_by_pid(pid);
- if (p)
- jiffies_to_timespec(p->policy & SCHED_FIFO ?
- 0 : TASK_TIMESLICE(p), &t);
+ if (!p)
+ goto out_unlock;
+
+ retval = security_ops->task_getscheduler(p);
+ if (retval)
+ goto out_unlock;
+
+ jiffies_to_timespec(p->policy & SCHED_FIFO ?
+ 0 : TASK_TIMESLICE(p), &t);
read_unlock(&tasklist_lock);
- if (p)
- retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
+ retval = copy_to_user(interval, &t, sizeof(t)) ? -EFAULT : 0;
out_nounlock:
return retval;
+out_unlock:
+ read_unlock(&tasklist_lock);
+ return retval;
}
static void show_task(task_t * p)
diff --git a/kernel/signal.c b/kernel/signal.c
index c08c89e9a62c..90ae5af97bf7 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -548,6 +548,9 @@ printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
ret = -EPERM;
if (bad_signal(sig, info, t))
goto out_nolock;
+ ret = security_ops->task_kill(t, info, sig);
+ if (ret)
+ goto out_nolock;
/* The null signal is a permissions and process existence probe.
No signal is actually delivered. Same goes for zombies. */
diff --git a/kernel/sys.c b/kernel/sys.c
index 2559bef8ed09..37a9525b3f1d 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -19,6 +19,7 @@
#include <linux/tqueue.h>
#include <linux/device.h>
#include <linux/times.h>
+#include <linux/security.h>
#include <asm/uaccess.h>
#include <asm/io.h>
@@ -234,6 +235,7 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)
read_lock(&tasklist_lock);
for_each_task(p) {
+ int no_nice;
if (!proc_sel(p, which, who))
continue;
if (p->uid != current->euid &&
@@ -243,10 +245,17 @@ asmlinkage long sys_setpriority(int which, int who, int niceval)
}
if (error == -ESRCH)
error = 0;
- if (niceval < task_nice(p) && !capable(CAP_SYS_NICE))
+ if (niceval < task_nice(p) && !capable(CAP_SYS_NICE)) {
error = -EACCES;
- else
- set_user_nice(p, niceval);
+ continue;
+ }
+ no_nice = security_ops->task_setnice(p, niceval);
+ if (no_nice) {
+ error = no_nice;
+ continue;
+ }
+ set_user_nice(p, niceval);
+
}
read_unlock(&tasklist_lock);
@@ -416,6 +425,11 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
int old_egid = current->egid;
int new_rgid = old_rgid;
int new_egid = old_egid;
+ int retval;
+
+ retval = security_ops->task_setgid(rgid, egid, (gid_t)-1, LSM_SETID_RE);
+ if (retval)
+ return retval;
if (rgid != (gid_t) -1) {
if ((old_rgid == rgid) ||
@@ -457,6 +471,11 @@ asmlinkage long sys_setregid(gid_t rgid, gid_t egid)
asmlinkage long sys_setgid(gid_t gid)
{
int old_egid = current->egid;
+ int retval;
+
+ retval = security_ops->task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_ID);
+ if (retval)
+ return retval;
if (capable(CAP_SETGID))
{
@@ -481,52 +500,6 @@ asmlinkage long sys_setgid(gid_t gid)
return 0;
}
-/*
- * cap_emulate_setxuid() fixes the effective / permitted capabilities of
- * a process after a call to setuid, setreuid, or setresuid.
- *
- * 1) When set*uiding _from_ one of {r,e,s}uid == 0 _to_ all of
- * {r,e,s}uid != 0, the permitted and effective capabilities are
- * cleared.
- *
- * 2) When set*uiding _from_ euid == 0 _to_ euid != 0, the effective
- * capabilities of the process are cleared.
- *
- * 3) When set*uiding _from_ euid != 0 _to_ euid == 0, the effective
- * capabilities are set to the permitted capabilities.
- *
- * fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should
- * never happen.
- *
- * -astor
- *
- * cevans - New behaviour, Oct '99
- * A process may, via prctl(), elect to keep its capabilities when it
- * calls setuid() and switches away from uid==0. Both permitted and
- * effective sets will be retained.
- * Without this change, it was impossible for a daemon to drop only some
- * of its privilege. The call to setuid(!=0) would drop all privileges!
- * Keeping uid 0 is not an option because uid 0 owns too many vital
- * files..
- * Thanks to Olaf Kirch and Peter Benie for spotting this.
- */
-static inline void cap_emulate_setxuid(int old_ruid, int old_euid,
- int old_suid)
-{
- if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) &&
- (current->uid != 0 && current->euid != 0 && current->suid != 0) &&
- !current->keep_capabilities) {
- cap_clear(current->cap_permitted);
- cap_clear(current->cap_effective);
- }
- if (old_euid == 0 && current->euid != 0) {
- cap_clear(current->cap_effective);
- }
- if (old_euid != 0 && current->euid == 0) {
- current->cap_effective = current->cap_permitted;
- }
-}
-
static int set_user(uid_t new_ruid, int dumpclear)
{
struct user_struct *new_user, *old_user;
@@ -572,6 +545,11 @@ static int set_user(uid_t new_ruid, int dumpclear)
asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
{
int old_ruid, old_euid, old_suid, new_ruid, new_euid;
+ int retval;
+
+ retval = security_ops->task_setuid(ruid, euid, (uid_t)-1, LSM_SETID_RE);
+ if (retval)
+ return retval;
new_ruid = old_ruid = current->uid;
new_euid = old_euid = current->euid;
@@ -608,11 +586,7 @@ asmlinkage long sys_setreuid(uid_t ruid, uid_t euid)
current->suid = current->euid;
current->fsuid = current->euid;
- if (!issecure(SECURE_NO_SETUID_FIXUP)) {
- cap_emulate_setxuid(old_ruid, old_euid, old_suid);
- }
-
- return 0;
+ return security_ops->task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE);
}
@@ -632,6 +606,11 @@ asmlinkage long sys_setuid(uid_t uid)
{
int old_euid = current->euid;
int old_ruid, old_suid, new_ruid, new_suid;
+ int retval;
+
+ retval = security_ops->task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_ID);
+ if (retval)
+ return retval;
old_ruid = new_ruid = current->uid;
old_suid = current->suid;
@@ -652,11 +631,7 @@ asmlinkage long sys_setuid(uid_t uid)
current->fsuid = current->euid = uid;
current->suid = new_suid;
- if (!issecure(SECURE_NO_SETUID_FIXUP)) {
- cap_emulate_setxuid(old_ruid, old_euid, old_suid);
- }
-
- return 0;
+ return security_ops->task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID);
}
@@ -669,6 +644,11 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
int old_ruid = current->uid;
int old_euid = current->euid;
int old_suid = current->suid;
+ int retval;
+
+ retval = security_ops->task_setuid(ruid, euid, suid, LSM_SETID_RES);
+ if (retval)
+ return retval;
if (!capable(CAP_SETUID)) {
if ((ruid != (uid_t) -1) && (ruid != current->uid) &&
@@ -697,11 +677,7 @@ asmlinkage long sys_setresuid(uid_t ruid, uid_t euid, uid_t suid)
if (suid != (uid_t) -1)
current->suid = suid;
- if (!issecure(SECURE_NO_SETUID_FIXUP)) {
- cap_emulate_setxuid(old_ruid, old_euid, old_suid);
- }
-
- return 0;
+ return security_ops->task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES);
}
asmlinkage long sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
@@ -720,6 +696,12 @@ asmlinkage long sys_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid)
*/
asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
{
+ int retval;
+
+ retval = security_ops->task_setgid(rgid, egid, sgid, LSM_SETID_RES);
+ if (retval)
+ return retval;
+
if (!capable(CAP_SETGID)) {
if ((rgid != (gid_t) -1) && (rgid != current->gid) &&
(rgid != current->egid) && (rgid != current->sgid))
@@ -768,6 +750,11 @@ asmlinkage long sys_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid)
asmlinkage long sys_setfsuid(uid_t uid)
{
int old_fsuid;
+ int retval;
+
+ retval = security_ops->task_setuid(uid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
+ if (retval)
+ return retval;
old_fsuid = current->fsuid;
if (uid == current->uid || uid == current->euid ||
@@ -782,24 +769,9 @@ asmlinkage long sys_setfsuid(uid_t uid)
current->fsuid = uid;
}
- /* We emulate fsuid by essentially doing a scaled-down version
- * of what we did in setresuid and friends. However, we only
- * operate on the fs-specific bits of the process' effective
- * capabilities
- *
- * FIXME - is fsuser used for all CAP_FS_MASK capabilities?
- * if not, we might be a bit too harsh here.
- */
-
- if (!issecure(SECURE_NO_SETUID_FIXUP)) {
- if (old_fsuid == 0 && current->fsuid != 0) {
- cap_t(current->cap_effective) &= ~CAP_FS_MASK;
- }
- if (old_fsuid != 0 && current->fsuid == 0) {
- cap_t(current->cap_effective) |=
- (cap_t(current->cap_permitted) & CAP_FS_MASK);
- }
- }
+ retval = security_ops->task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);
+ if (retval)
+ return retval;
return old_fsuid;
}
@@ -810,6 +782,11 @@ asmlinkage long sys_setfsuid(uid_t uid)
asmlinkage long sys_setfsgid(gid_t gid)
{
int old_fsgid;
+ int retval;
+
+ retval = security_ops->task_setgid(gid, (gid_t)-1, (gid_t)-1, LSM_SETID_FS);
+ if (retval)
+ return retval;
old_fsgid = current->fsgid;
if (gid == current->gid || gid == current->egid ||
@@ -904,6 +881,10 @@ asmlinkage long sys_setpgid(pid_t pid, pid_t pgid)
}
ok_pgid:
+ err = security_ops->task_setpgid(p, pgid);
+ if (err)
+ goto out;
+
p->pgrp = pgid;
err = 0;
out:
@@ -924,8 +905,11 @@ asmlinkage long sys_getpgid(pid_t pid)
p = find_task_by_pid(pid);
retval = -ESRCH;
- if (p)
- retval = p->pgrp;
+ if (p) {
+ retval = security_ops->task_getpgid(p);
+ if (!retval)
+ retval = p->pgrp;
+ }
read_unlock(&tasklist_lock);
return retval;
}
@@ -949,8 +933,11 @@ asmlinkage long sys_getsid(pid_t pid)
p = find_task_by_pid(pid);
retval = -ESRCH;
- if(p)
- retval = p->session;
+ if(p) {
+ retval = security_ops->task_getsid(p);
+ if (!retval)
+ retval = p->session;
+ }
read_unlock(&tasklist_lock);
return retval;
}
@@ -1008,12 +995,19 @@ asmlinkage long sys_getgroups(int gidsetsize, gid_t *grouplist)
asmlinkage long sys_setgroups(int gidsetsize, gid_t *grouplist)
{
+ gid_t groups[NGROUPS];
+ int retval;
+
if (!capable(CAP_SETGID))
return -EPERM;
if ((unsigned) gidsetsize > NGROUPS)
return -EINVAL;
- if(copy_from_user(current->groups, grouplist, gidsetsize * sizeof(gid_t)))
+ if(copy_from_user(groups, grouplist, gidsetsize * sizeof(gid_t)))
return -EFAULT;
+ retval = security_ops->task_setgroups(gidsetsize, groups);
+ if (retval)
+ return retval;
+ memcpy(current->groups, groups, gidsetsize * sizeof(gid_t));
current->ngroups = gidsetsize;
return 0;
}
@@ -1158,6 +1152,7 @@ asmlinkage long sys_old_getrlimit(unsigned int resource, struct rlimit *rlim)
asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim)
{
struct rlimit new_rlim, *old_rlim;
+ int retval;
if (resource >= RLIM_NLIMITS)
return -EINVAL;
@@ -1172,6 +1167,11 @@ asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim)
if (new_rlim.rlim_cur > NR_OPEN || new_rlim.rlim_max > NR_OPEN)
return -EPERM;
}
+
+ retval = security_ops->task_setrlimit(resource, &new_rlim);
+ if (retval)
+ return retval;
+
*old_rlim = new_rlim;
return 0;
}
@@ -1243,6 +1243,10 @@ asmlinkage long sys_prctl(int option, unsigned long arg2, unsigned long arg3,
int error = 0;
int sig;
+ error = security_ops->task_prctl(option, arg2, arg3, arg4, arg5);
+ if (error)
+ return error;
+
switch (option) {
case PR_SET_PDEATHSIG:
sig = arg2;
diff --git a/kernel/uid16.c b/kernel/uid16.c
index f76e4fd706e5..63b24096f8c3 100644
--- a/kernel/uid16.c
+++ b/kernel/uid16.c
@@ -12,6 +12,7 @@
#include <linux/prctl.h>
#include <linux/init.h>
#include <linux/highuid.h>
+#include <linux/security.h>
#include <asm/uaccess.h>
@@ -128,6 +129,7 @@ asmlinkage long sys_getgroups16(int gidsetsize, old_gid_t *grouplist)
asmlinkage long sys_setgroups16(int gidsetsize, old_gid_t *grouplist)
{
old_gid_t groups[NGROUPS];
+ gid_t new_groups[NGROUPS];
int i;
if (!capable(CAP_SETGID))
@@ -137,7 +139,11 @@ asmlinkage long sys_setgroups16(int gidsetsize, old_gid_t *grouplist)
if (copy_from_user(groups, grouplist, gidsetsize * sizeof(old_gid_t)))
return -EFAULT;
for (i = 0 ; i < gidsetsize ; i++)
- current->groups[i] = (gid_t)groups[i];
+ new_groups[i] = (gid_t)groups[i];
+ i = security_ops->task_setgroups(gidsetsize, new_groups);
+ if (i)
+ return i;
+ memcpy(current->groups, new_groups, gidsetsize * sizeof(gid_t));
current->ngroups = gidsetsize;
return 0;
}