# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.662 -> 1.663 # kernel/uid16.c 1.1 -> 1.2 # kernel/fork.c 1.50 -> 1.51 # include/linux/sched.h 1.71 -> 1.72 # kernel/sys.c 1.20 -> 1.21 # Makefile 1.274 -> 1.275 # kernel/capability.c 1.4 -> 1.5 # init/main.c 1.50 -> 1.51 # kernel/sched.c 1.106 -> 1.107 # arch/i386/kernel/entry.S 1.32 -> 1.33 # arch/i386/kernel/ptrace.c 1.12 -> 1.13 # kernel/kmod.c 1.9 -> 1.10 # arch/i386/config.in 1.41 -> 1.42 # kernel/exit.c 1.35 -> 1.36 # fs/exec.c 1.32 -> 1.33 # kernel/signal.c 1.22 -> 1.23 # include/linux/binfmts.h 1.2 -> 1.3 # kernel/ptrace.c 1.11 -> 1.12 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 02/07/19 greg@kroah.com 1.663 # LSM: Enable the security framework. This includes basic task control hooks. # -------------------------------------------- # diff -Nru a/Makefile b/Makefile --- a/Makefile Fri Jul 19 16:03:47 2002 +++ b/Makefile Fri Jul 19 16:03:47 2002 @@ -157,7 +157,8 @@ export srctree objtree -SUBDIRS := init kernel mm fs ipc lib drivers sound net +SUBDIRS := init kernel mm fs ipc lib drivers sound net security + noconfig_targets := xconfig menuconfig config oldconfig randconfig \ defconfig allyesconfig allnoconfig allmodconfig \ @@ -223,7 +224,7 @@ # --------------------------------------------------------------------------- INIT := init/init.o -CORE_FILES := kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o +CORE_FILES := kernel/kernel.o mm/mm.o fs/fs.o ipc/ipc.o security/built-in.o LIBS := lib/lib.a DRIVERS := drivers/built-in.o sound/sound.o NETWORKS := net/network.o diff -Nru a/arch/i386/config.in b/arch/i386/config.in --- a/arch/i386/config.in Fri Jul 19 16:03:47 2002 +++ b/arch/i386/config.in Fri Jul 19 16:03:47 2002 @@ -423,4 +423,5 @@ endmenu +source security/Config.in source lib/Config.in diff -Nru a/arch/i386/kernel/entry.S b/arch/i386/kernel/entry.S --- a/arch/i386/kernel/entry.S Fri Jul 19 16:03:47 2002 +++ b/arch/i386/kernel/entry.S Fri Jul 19 16:03:47 2002 @@ -744,7 +744,7 @@ .long sys_getdents64 /* 220 */ .long sys_fcntl64 .long sys_ni_syscall /* reserved for TUX */ - .long sys_ni_syscall /* reserved for Security */ + .long sys_security /* reserved for Security */ .long sys_gettid .long sys_readahead /* 225 */ .long sys_setxattr diff -Nru a/arch/i386/kernel/ptrace.c b/arch/i386/kernel/ptrace.c --- a/arch/i386/kernel/ptrace.c Fri Jul 19 16:03:47 2002 +++ b/arch/i386/kernel/ptrace.c Fri Jul 19 16:03:47 2002 @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -158,6 +159,9 @@ if (request == PTRACE_TRACEME) { /* are we already being traced? */ if (current->ptrace & PT_PTRACED) + goto out; + ret = security_ops->ptrace(current->parent, current); + if (ret) goto out; /* set the ptrace bit in the process flags. */ current->ptrace |= PT_PTRACED; diff -Nru a/fs/exec.c b/fs/exec.c --- a/fs/exec.c Fri Jul 19 16:03:47 2002 +++ b/fs/exec.c Fri Jul 19 16:03:47 2002 @@ -623,6 +623,7 @@ { int mode; struct inode * inode = bprm->file->f_dentry->d_inode; + int retval; mode = inode->i_mode; /* @@ -652,27 +653,10 @@ bprm->e_gid = inode->i_gid; } - /* We don't have VFS support for capabilities yet */ - cap_clear(bprm->cap_inheritable); - cap_clear(bprm->cap_permitted); - cap_clear(bprm->cap_effective); - - /* To support inheritance of root-permissions and suid-root - * executables under compatibility mode, we raise all three - * capability sets for the file. - * - * If only the real uid is 0, we only raise the inheritable - * and permitted sets of the executable file. - */ - - if (!issecure(SECURE_NOROOT)) { - if (bprm->e_uid == 0 || current->uid == 0) { - cap_set_full(bprm->cap_inheritable); - cap_set_full(bprm->cap_permitted); - } - if (bprm->e_uid == 0) - cap_set_full(bprm->cap_effective); - } + /* fill in binprm security blob */ + retval = security_ops->bprm_set_security(bprm); + if (retval) + return retval; memset(bprm->buf,0,BINPRM_BUF_SIZE); return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE); @@ -695,16 +679,9 @@ void compute_creds(struct linux_binprm *bprm) { - kernel_cap_t new_permitted, working; int do_unlock = 0; - new_permitted = cap_intersect(bprm->cap_permitted, cap_bset); - working = cap_intersect(bprm->cap_inheritable, - current->cap_inheritable); - new_permitted = cap_combine(new_permitted, working); - - if (bprm->e_uid != current->uid || bprm->e_gid != current->gid || - !cap_issubset(new_permitted, current->cap_permitted)) { + if (bprm->e_uid != current->uid || bprm->e_gid != current->gid) { current->mm->dumpable = 0; lock_kernel(); @@ -716,32 +693,17 @@ bprm->e_uid = current->uid; bprm->e_gid = current->gid; } - if(!capable(CAP_SETPCAP)) { - new_permitted = cap_intersect(new_permitted, - current->cap_permitted); - } } do_unlock = 1; } - - /* For init, we want to retain the capabilities set - * in the init_task struct. Thus we skip the usual - * capability rules */ - if (current->pid != 1) { - current->cap_permitted = new_permitted; - current->cap_effective = - cap_intersect(new_permitted, bprm->cap_effective); - } - - /* AUD: Audit candidate if current->cap_effective is set */ - current->suid = current->euid = current->fsuid = bprm->e_uid; current->sgid = current->egid = current->fsgid = bprm->e_gid; if(do_unlock) unlock_kernel(); - current->keep_capabilities = 0; + + security_ops->bprm_compute_creds(bprm); } @@ -811,6 +773,10 @@ } } #endif + retval = security_ops->bprm_check_security(bprm); + if (retval) + return retval; + /* kernel module loader fixup */ /* so we don't try to load run modprobe in kernel space. */ set_fs(USER_DS); @@ -887,7 +853,7 @@ bprm.sh_bang = 0; bprm.loader = 0; bprm.exec = 0; - + bprm.security = NULL; bprm.mm = mm_alloc(); retval = -ENOMEM; if (!bprm.mm) @@ -905,6 +871,10 @@ if ((retval = bprm.envc) < 0) goto out_mm; + retval = security_ops->bprm_alloc_security(&bprm); + if (retval) + goto out; + retval = prepare_binprm(&bprm); if (retval < 0) goto out; @@ -923,9 +893,11 @@ goto out; retval = search_binary_handler(&bprm,regs); - if (retval >= 0) + if (retval >= 0) { /* execve success */ + security_ops->bprm_free_security(&bprm); return retval; + } out: /* Something went wrong, return the inode and free the argument pages*/ @@ -934,6 +906,9 @@ if (page) __free_page(page); } + + if (bprm.security) + security_ops->bprm_free_security(&bprm); out_mm: mmdrop(bprm.mm); diff -Nru a/include/linux/binfmts.h b/include/linux/binfmts.h --- a/include/linux/binfmts.h Fri Jul 19 16:03:47 2002 +++ b/include/linux/binfmts.h Fri Jul 19 16:03:47 2002 @@ -28,6 +28,7 @@ struct file * file; int e_uid, e_gid; kernel_cap_t cap_inheritable, cap_permitted, cap_effective; + void *security; int argc, envc; char * filename; /* Name of binary */ unsigned long loader, exec; diff -Nru a/include/linux/sched.h b/include/linux/sched.h --- a/include/linux/sched.h Fri Jul 19 16:03:47 2002 +++ b/include/linux/sched.h Fri Jul 19 16:03:47 2002 @@ -354,6 +354,8 @@ void *notifier_data; sigset_t *notifier_mask; + void *security; + /* Thread group tracking */ u32 parent_exec_id; u32 self_exec_id; @@ -587,10 +589,9 @@ unsigned long, const char *, void *); extern void free_irq(unsigned int, void *); -/* - * capable() checks for a particular capability. - * See include/linux/capability.h for defined capabilities. - */ +/* capable prototype and code moved to security.[hc] */ +#include +#if 0 static inline int capable(int cap) { if (cap_raised(current->cap_effective, cap)) { @@ -599,6 +600,7 @@ } return 0; } +#endif /* if 0 */ /* * Routines for handling mm_structs diff -Nru a/init/main.c b/init/main.c --- a/init/main.c Fri Jul 19 16:03:47 2002 +++ b/init/main.c Fri Jul 19 16:03:47 2002 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -390,6 +391,7 @@ fork_init(mempages); proc_caches_init(); + security_scaffolding_startup(); buffer_init(); vfs_caches_init(mempages); radix_tree_init(); diff -Nru a/kernel/capability.c b/kernel/capability.c --- a/kernel/capability.c Fri Jul 19 16:03:47 2002 +++ b/kernel/capability.c Fri Jul 19 16:03:47 2002 @@ -63,6 +63,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 -Nru a/kernel/exit.c b/kernel/exit.c --- a/kernel/exit.c Fri Jul 19 16:03:47 2002 +++ b/kernel/exit.c Fri Jul 19 16:03:47 2002 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -61,6 +62,7 @@ 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 @@ /* 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 @@ 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 -Nru a/kernel/fork.c b/kernel/fork.c --- a/kernel/fork.c Fri Jul 19 16:03:47 2002 +++ b/kernel/fork.c Fri Jul 19 16:03:47 2002 @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include @@ -618,6 +618,10 @@ 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 @@ 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 @@ 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 -Nru a/kernel/kmod.c b/kernel/kmod.c --- a/kernel/kmod.c Fri Jul 19 16:03:47 2002 +++ b/kernel/kmod.c Fri Jul 19 16:03:47 2002 @@ -134,7 +134,7 @@ /* 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 -Nru a/kernel/ptrace.c b/kernel/ptrace.c --- a/kernel/ptrace.c Fri Jul 19 16:03:47 2002 +++ b/kernel/ptrace.c Fri Jul 19 16:03:47 2002 @@ -41,7 +41,9 @@ 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 @@ (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 @@ /* 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 @@ bad: task_unlock(task); - return -EPERM; + return retval; } int ptrace_detach(struct task_struct *child, unsigned int data) diff -Nru a/kernel/sched.c b/kernel/sched.c --- a/kernel/sched.c Fri Jul 19 16:03:47 2002 +++ b/kernel/sched.c Fri Jul 19 16:03:47 2002 @@ -26,6 +26,7 @@ #include #include #include +#include /* * Convert user-nice values [ -20 ... 0 ... 19 ] @@ -1123,6 +1124,7 @@ asmlinkage long sys_nice(int increment) { + int retval; long nice; /* @@ -1144,6 +1146,11 @@ 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 @@ !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 @@ 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 @@ 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,13 +1528,21 @@ 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; } diff -Nru a/kernel/signal.c b/kernel/signal.c --- a/kernel/signal.c Fri Jul 19 16:03:47 2002 +++ b/kernel/signal.c Fri Jul 19 16:03:47 2002 @@ -548,6 +548,9 @@ 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 -Nru a/kernel/sys.c b/kernel/sys.c --- a/kernel/sys.c Fri Jul 19 16:03:47 2002 +++ b/kernel/sys.c Fri Jul 19 16:03:47 2002 @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -234,6 +235,7 @@ 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 @@ } 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 @@ 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_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 @@ 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 @@ 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 @@ 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 @@ { 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 @@ 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 @@ 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 @@ 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_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_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 @@ 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_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 @@ } ok_pgid: + err = security_ops->task_setpgid(p, pgid); + if (err) + goto out; + p->pgrp = pgid; err = 0; out: @@ -924,8 +905,11 @@ 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 @@ 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_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_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 @@ 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; } @@ -1242,6 +1242,10 @@ { 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: diff -Nru a/kernel/uid16.c b/kernel/uid16.c --- a/kernel/uid16.c Fri Jul 19 16:03:47 2002 +++ b/kernel/uid16.c Fri Jul 19 16:03:47 2002 @@ -12,6 +12,7 @@ #include #include #include +#include #include @@ -128,6 +129,7 @@ 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 @@ 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; }