static void selinux_bprm_apply_creds(struct linux_binprm *bprm, int unsafe) { struct task_security_struct *tsec; struct bprm_security_struct *bsec; struct av_decision avd; u32 sid; int rc; secondary_ops->bprm_apply_creds(bprm, unsafe); tsec = current->security; bsec = bprm->security; sid = bsec->sid; tsec->osid = tsec->sid; tsec->unsafe = 0; if (tsec->sid != sid) { /* Check for shared state. If not ok, leave SID unchanged and kill. */ if (unsafe & LSM_UNSAFE_SHARE) { rc = avc_has_perm_noaudit(tsec->sid, sid, SECCLASS_PROCESS, PROCESS__SHARE, NULL, &avd); if (rc) { avc_audit(tsec->sid, sid, SECCLASS_PROCESS, PROCESS__SHARE, &avd, rc, NULL); tsec->unsafe = 1; force_sig_specific(SIGKILL, current); return; } } /* Check for ptracing, and update the task SID if ok. Otherwise, leave SID unchanged and kill. */ if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { rc = avc_has_perm_noaudit(tsec->ptrace_sid, sid, SECCLASS_PROCESS, PROCESS__PTRACE, NULL, &avd); avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS, PROCESS__PTRACE, &avd, rc, NULL); if (rc) { force_sig_specific(SIGKILL, current); tsec->unsafe = 1; } else tsec->sid = sid; } else tsec->sid = sid; } } /* * called after apply_creds without the task lock held */ static void selinux_bprm_final_setup(struct linux_binprm *bprm) { struct task_security_struct *tsec; struct bprm_security_struct *bsec; struct rlimit *rlim, *initrlim; struct itimerval itimer; int rc, i; u32 sid; tsec = current->security; bsec = bprm->security; sid = bsec->sid; if (tsec->unsafe) return; /* Close files for which the new task SID is not authorized. */ flush_unauthorized_files(current->files); /* Check whether the new SID can inherit signal state from the old SID. If not, clear itimers to avoid subsequent signal generation and flush and unblock signals. This must occur _after_ the task SID has been updated so that any kill done after the flush will be checked against the new SID. */ rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS, PROCESS__SIGINH, NULL, NULL); if (rc) { memset(&itimer, 0, sizeof itimer); for (i = 0; i < 3; i++) do_setitimer(i, &itimer, NULL); flush_signals(current); spin_lock_irq(¤t->sighand->siglock); flush_signal_handlers(current, 1); sigemptyset(¤t->blocked); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); } /* Check whether the new SID can inherit resource limits from the old SID. If not, reset all soft limits to the lower of the current task's hard limit and the init task's soft limit. Note that the setting of hard limits (even to lower them) can be controlled by the setrlimit check. The inclusion of the init task's soft limit into the computation is to avoid resetting soft limits higher than the default soft limit for cases where the default is lower than the hard limit, e.g. RLIMIT_CORE or RLIMIT_STACK.*/ rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS, PROCESS__RLIMITINH, NULL, NULL); if (rc) { for (i = 0; i < RLIM_NLIMITS; i++) { rlim = current->signal->rlim + i; initrlim = init_task.signal->rlim+i; rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur); } } /* Wake up the parent if it is waiting so that it can recheck wait permission to the new task SID. */ wake_up_interruptible(¤t->parent->wait_chldexit); }