int cap_capset_check (struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted) { /* Derived from kernel/capability.c:sys_capset. */ /* verify restrictions on target's new Inheritable set */ if (!cap_issubset (*inheritable, cap_combine (target->cap_inheritable, current->cap_permitted))) { return -EPERM; } /* verify restrictions on target's new Permitted set */ if (!cap_issubset (*permitted, cap_combine (target->cap_permitted, current->cap_permitted))) { return -EPERM; } /* verify the _new_Effective_ is a subset of the _new_Permitted_ */ if (!cap_issubset (*effective, *permitted)) { return -EPERM; } return 0; }
void krg_cap_finish_exec(struct linux_binprm *bprm) { /* The model needs changes with filesystem support ... */ #if 0 kernel_krg_cap_t *caps = ¤t->krg_caps; kernel_cap_t new_krg_permitted, new_krg_effective; /* added by David Margery (c) Inria 2004 */ /* Updated by Pascal Gallard (c) Inria 2005 */ task_lock(current); new_krg_permitted = cap_intersect(caps->inheritable_permitted, bprm->krg_cap_permitted); new_krg_permitted = cap_combine(new_krg_permitted, bprm->krg_cap_forced); new_krg_effective = cap_intersect(bprm->krg_cap_effective, new_krg_permitted); new_krg_effective = cap_intersect(caps->inheritable_effective, new_krg_effective); caps->permitted = new_krg_permitted; caps->effective = new_krg_effective; task_unlock(current); #endif /* 0 */ }
void cap_bprm_compute_creds (struct linux_binprm *bprm) { /* Derived from fs/exec.c:compute_creds. */ 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 (!cap_issubset (new_permitted, current->cap_permitted)) { current->mm->dumpable = 0; lock_kernel (); if (must_not_trace_exec (current) || atomic_read (¤t->fs->count) > 1 || atomic_read (¤t->files->count) > 1 || atomic_read (¤t->sig->count) > 1) { 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 */ if (do_unlock) unlock_kernel (); current->keep_capabilities = 0; }
void cap_bprm_apply_creds (struct linux_binprm *bprm, int unsafe) { /* Derived from fs/exec.c:compute_creds. */ kernel_cap_t new_permitted, working; 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)) { current->mm->dumpable = 0; if (unsafe & ~LSM_UNSAFE_PTRACE_CAP) { if (!capable(CAP_SETUID)) { bprm->e_uid = current->uid; bprm->e_gid = current->gid; } if (!capable (CAP_SETPCAP)) { new_permitted = cap_intersect (new_permitted, current->cap_permitted); } } } current->suid = current->euid = current->fsuid = bprm->e_uid; current->sgid = current->egid = current->fsgid = bprm->e_gid; /* 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->keep_capabilities = 0; }
* @inheritable: A pointer to the proposed new inheritable capabilities set * @permitted: A pointer to the proposed new permitted capabilities set * * This function validates and applies a proposed mass change to the current * process's capability sets. The changes are made to the proposed new * credentials, and assuming no error, will be committed by the caller of LSM. */ int cap_capset(struct cred *new, const struct cred *old, const kernel_cap_t *effective, const kernel_cap_t *inheritable, const kernel_cap_t *permitted) { if (cap_inh_is_capped() && !cap_issubset(*inheritable, cap_combine(old->cap_inheritable, old->cap_permitted))) /* incapable of using this inheritable set */ return -EPERM; if (!cap_issubset(*inheritable, cap_combine(old->cap_inheritable, old->cap_bset))) /* no new pI capabilities outside bounding set */ return -EPERM; /* verify restrictions on target's new Permitted set */ if (!cap_issubset(*permitted, old->cap_permitted)) return -EPERM; /* verify the _new_Effective_ is a subset of the _new_Permitted_ */ if (!cap_issubset(*effective, *permitted))
asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data) { kernel_cap_t inheritable, permitted, effective; __u32 version; struct task_struct *target; int error, pid; if (get_user(version, &header->version)) return -EFAULT; if (version != _LINUX_CAPABILITY_VERSION) { version = _LINUX_CAPABILITY_VERSION; if (put_user(version, &header->version)) return -EFAULT; return -EINVAL; } if (get_user(pid, &header->pid)) return -EFAULT; if (pid && !capable(CAP_SETPCAP)) return -EPERM; if (copy_from_user(&effective, &data->effective, sizeof(effective)) || copy_from_user(&inheritable, &data->inheritable, sizeof(inheritable)) || copy_from_user(&permitted, &data->permitted, sizeof(permitted))) return -EFAULT; error = -EPERM; spin_lock(&task_capability_lock); if (pid > 0 && pid != current->pid) { read_lock(&tasklist_lock); target = find_task_by_pid(pid); /* identify target of query */ if (!target) { error = -ESRCH; goto out; } } else { target = current; } /* verify restrictions on target's new Inheritable set */ if (!cap_issubset(inheritable, cap_combine(target->cap_inheritable, current->cap_permitted))) { goto out; } /* verify restrictions on target's new Permitted set */ if (!cap_issubset(permitted, cap_combine(target->cap_permitted, current->cap_permitted))) { goto out; } /* verify the _new_Effective_ is a subset of the _new_Permitted_ */ if (!cap_issubset(effective, permitted)) { goto out; } /* having verified that the proposed changes are legal, we now put them into effect. */ error = 0; if (pid < 0) { if (pid == -1) /* all procs other than current and init */ cap_set_all(&effective, &inheritable, &permitted); else /* all procs in process group */ cap_set_pg(-pid, &effective, &inheritable, &permitted); goto spin_out; } else { /* FIXME: do we need to have a write lock here..? */ target->cap_effective = effective; target->cap_inheritable = inheritable; target->cap_permitted = permitted; } out: if (target != current) { read_unlock(&tasklist_lock); } spin_out: spin_unlock(&task_capability_lock); return error; }