From 29881c4502ba05f46bc12ae8053d4e08d7e2615c Mon Sep 17 00:00:00 2001 From: James Morris Date: Wed, 7 Jan 2009 09:21:54 +1100 Subject: [PATCH] Revert "CRED: Fix regression in cap_capable() as shown up by sys_faccessat() [ver #2]" This reverts commit 14eaddc967b16017d4a1a24d2be6c28ecbe06ed8. David has a better version to come. --- include/linux/capability.h | 17 ++----------- include/linux/security.h | 49 +++++++------------------------------- kernel/capability.c | 2 +- security/capability.c | 1 - security/commoncap.c | 42 ++++++++++---------------------- security/root_plug.c | 1 - security/security.c | 25 ++++--------------- security/selinux/hooks.c | 26 +++++--------------- security/smack/smack_lsm.c | 1 - 9 files changed, 35 insertions(+), 129 deletions(-) diff --git a/include/linux/capability.h b/include/linux/capability.h index 5b8a13214451..e22f48c2a46f 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -529,21 +529,8 @@ extern const kernel_cap_t __cap_init_eff_set; * * Note that this does not set PF_SUPERPRIV on the task. */ -#define has_capability(t, cap) (security_task_capable((t), (cap)) == 0) - -/** - * has_capability_noaudit - Determine if a task has a superior capability available (unaudited) - * @t: The task in question - * @cap: The capability to be tested for - * - * Return true if the specified task has the given superior capability - * currently in effect, false if not, but don't write an audit message for the - * check. - * - * Note that this does not set PF_SUPERPRIV on the task. - */ -#define has_capability_noaudit(t, cap) \ - (security_task_capable_noaudit((t), (cap)) == 0) +#define has_capability(t, cap) (security_capable((t), (cap)) == 0) +#define has_capability_noaudit(t, cap) (security_capable_noaudit((t), (cap)) == 0) extern int capable(int cap); diff --git a/include/linux/security.h b/include/linux/security.h index 76989b8bc34f..3416cb85e77b 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -48,9 +48,7 @@ struct audit_krule; * These functions are in security/capability.c and are used * as the default capabilities functions */ -extern int cap_capable(int cap, int audit); -extern int cap_task_capable(struct task_struct *tsk, const struct cred *cred, - int cap, int audit); +extern int cap_capable(struct task_struct *tsk, int cap, int audit); extern int cap_settime(struct timespec *ts, struct timezone *tz); extern int cap_ptrace_may_access(struct task_struct *child, unsigned int mode); extern int cap_ptrace_traceme(struct task_struct *parent); @@ -1197,18 +1195,9 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) * @permitted contains the permitted capability set. * Return 0 and update @new if permission is granted. * @capable: - * Check whether the current process has the @cap capability in its - * subjective/effective credentials. - * @cap contains the capability . - * @audit: Whether to write an audit message or not - * Return 0 if the capability is granted for @tsk. - * @task_capable: - * Check whether the @tsk process has the @cap capability in its - * objective/real credentials. + * Check whether the @tsk process has the @cap capability. * @tsk contains the task_struct for the process. - * @cred contains the credentials to use. * @cap contains the capability . - * @audit: Whether to write an audit message or not * Return 0 if the capability is granted for @tsk. * @acct: * Check permission before enabling or disabling process accounting. If @@ -1301,9 +1290,7 @@ struct security_operations { const kernel_cap_t *effective, const kernel_cap_t *inheritable, const kernel_cap_t *permitted); - int (*capable) (int cap, int audit); - int (*task_capable) (struct task_struct *tsk, const struct cred *cred, - int cap, int audit); + int (*capable) (struct task_struct *tsk, int cap, int audit); int (*acct) (struct file *file); int (*sysctl) (struct ctl_table *table, int op); int (*quotactl) (int cmds, int type, int id, struct super_block *sb); @@ -1569,9 +1556,8 @@ int security_capset(struct cred *new, const struct cred *old, const kernel_cap_t *effective, const kernel_cap_t *inheritable, const kernel_cap_t *permitted); -int security_capable(int cap); -int security_task_capable(struct task_struct *tsk, int cap); -int security_task_capable_noaudit(struct task_struct *tsk, int cap); +int security_capable(struct task_struct *tsk, int cap); +int security_capable_noaudit(struct task_struct *tsk, int cap); int security_acct(struct file *file); int security_sysctl(struct ctl_table *table, int op); int security_quotactl(int cmds, int type, int id, struct super_block *sb); @@ -1768,31 +1754,14 @@ static inline int security_capset(struct cred *new, return cap_capset(new, old, effective, inheritable, permitted); } -static inline int security_capable(int cap) +static inline int security_capable(struct task_struct *tsk, int cap) { - return cap_capable(cap, SECURITY_CAP_AUDIT); + return cap_capable(tsk, cap, SECURITY_CAP_AUDIT); } -static inline int security_task_capable(struct task_struct *tsk, int cap) +static inline int security_capable_noaudit(struct task_struct *tsk, int cap) { - int ret; - - rcu_read_lock(); - ret = cap_task_capable(tsk, __task_cred(tsk), cap, SECURITY_CAP_AUDIT); - rcu_read_unlock(); - return ret; -} - -static inline -int security_task_capable_noaudit(struct task_struct *tsk, int cap) -{ - int ret; - - rcu_read_lock(); - ret = cap_task_capable(tsk, __task_cred(tsk), cap, - SECURITY_CAP_NOAUDIT); - rcu_read_unlock(); - return ret; + return cap_capable(tsk, cap, SECURITY_CAP_NOAUDIT); } static inline int security_acct(struct file *file) diff --git a/kernel/capability.c b/kernel/capability.c index df62f53f84ac..36b4b4daebec 100644 --- a/kernel/capability.c +++ b/kernel/capability.c @@ -308,7 +308,7 @@ int capable(int cap) BUG(); } - if (security_capable(cap) == 0) { + if (has_capability(current, cap)) { current->flags |= PF_SUPERPRIV; return 1; } diff --git a/security/capability.c b/security/capability.c index fd1493da4f8d..2dce66fcb992 100644 --- a/security/capability.c +++ b/security/capability.c @@ -826,7 +826,6 @@ void security_fixup_ops(struct security_operations *ops) set_to_cap_if_null(ops, capset); set_to_cap_if_null(ops, acct); set_to_cap_if_null(ops, capable); - set_to_cap_if_null(ops, task_capable); set_to_cap_if_null(ops, quotactl); set_to_cap_if_null(ops, quota_on); set_to_cap_if_null(ops, sysctl); diff --git a/security/commoncap.c b/security/commoncap.c index 7f0b2a68717d..79713545cd63 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -43,44 +43,28 @@ int cap_netlink_recv(struct sk_buff *skb, int cap) EXPORT_SYMBOL(cap_netlink_recv); /** - * cap_capable - Determine whether current has a particular effective capability + * cap_capable - Determine whether a task has a particular effective capability + * @tsk: The task to query * @cap: The capability to check for * @audit: Whether to write an audit message or not * * Determine whether the nominated task has the specified capability amongst - * its effective set, returning 0 if it does, -ve if it does not. Note that - * this uses current's subjective/effective credentials. + * its effective set, returning 0 if it does, -ve if it does not. * * NOTE WELL: cap_capable() cannot be used like the kernel's capable() * function. That is, it has the reverse semantics: cap_capable() returns 0 * when a task has a capability, but the kernel's capable() returns 1 for this * case. */ -int cap_capable(int cap, int audit) +int cap_capable(struct task_struct *tsk, int cap, int audit) { - return cap_raised(current_cap(), cap) ? 0 : -EPERM; -} + __u32 cap_raised; -/** - * cap_has_capability - Determine whether a task has a particular effective capability - * @tsk: The task to query - * @cred: The credentials to use - * @cap: The capability to check for - * @audit: Whether to write an audit message or not - * - * Determine whether the nominated task has the specified capability amongst - * its effective set, returning 0 if it does, -ve if it does not. Note that - * this uses the task's objective/real credentials. - * - * NOTE WELL: cap_has_capability() cannot be used like the kernel's - * has_capability() function. That is, it has the reverse semantics: - * cap_has_capability() returns 0 when a task has a capability, but the - * kernel's has_capability() returns 1 for this case. - */ -int cap_task_capable(struct task_struct *tsk, const struct cred *cred, int cap, - int audit) -{ - return cap_raised(cred->cap_effective, cap) ? 0 : -EPERM; + /* Derived from include/linux/sched.h:capable. */ + rcu_read_lock(); + cap_raised = cap_raised(__task_cred(tsk)->cap_effective, cap); + rcu_read_unlock(); + return cap_raised ? 0 : -EPERM; } /** @@ -176,7 +160,7 @@ static inline int cap_inh_is_capped(void) /* they are so limited unless the current task has the CAP_SETPCAP * capability */ - if (cap_capable(CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0) + if (cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0) return 0; #endif return 1; @@ -885,7 +869,7 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, & (new->securebits ^ arg2)) /*[1]*/ || ((new->securebits & SECURE_ALL_LOCKS & ~arg2)) /*[2]*/ || (arg2 & ~(SECURE_ALL_LOCKS | SECURE_ALL_BITS)) /*[3]*/ - || (cap_capable(CAP_SETPCAP, SECURITY_CAP_AUDIT) != 0) /*[4]*/ + || (cap_capable(current, CAP_SETPCAP, SECURITY_CAP_AUDIT) != 0) /*[4]*/ /* * [1] no changing of bits that are locked * [2] no unlocking of locks @@ -966,7 +950,7 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages) { int cap_sys_admin = 0; - if (cap_capable(CAP_SYS_ADMIN, SECURITY_CAP_NOAUDIT) == 0) + if (cap_capable(current, CAP_SYS_ADMIN, SECURITY_CAP_NOAUDIT) == 0) cap_sys_admin = 1; return __vm_enough_memory(mm, pages, cap_sys_admin); } diff --git a/security/root_plug.c b/security/root_plug.c index 559578f8ac66..40fb4f15e27b 100644 --- a/security/root_plug.c +++ b/security/root_plug.c @@ -77,7 +77,6 @@ static struct security_operations rootplug_security_ops = { .capget = cap_capget, .capset = cap_capset, .capable = cap_capable, - .task_capable = cap_task_capable, .bprm_set_creds = cap_bprm_set_creds, diff --git a/security/security.c b/security/security.c index 9bbc8e57b8c6..d85dbb37c972 100644 --- a/security/security.c +++ b/security/security.c @@ -154,31 +154,14 @@ int security_capset(struct cred *new, const struct cred *old, effective, inheritable, permitted); } -int security_capable(int cap) +int security_capable(struct task_struct *tsk, int cap) { - return security_ops->capable(cap, SECURITY_CAP_AUDIT); + return security_ops->capable(tsk, cap, SECURITY_CAP_AUDIT); } -int security_task_capable(struct task_struct *tsk, int cap) +int security_capable_noaudit(struct task_struct *tsk, int cap) { - const struct cred *cred; - int ret; - - cred = get_task_cred(tsk); - ret = security_ops->task_capable(tsk, cred, cap, SECURITY_CAP_AUDIT); - put_cred(cred); - return ret; -} - -int security_task_capable_noaudit(struct task_struct *tsk, int cap) -{ - const struct cred *cred; - int ret; - - cred = get_task_cred(tsk); - ret = security_ops->task_capable(tsk, cred, cap, SECURITY_CAP_NOAUDIT); - put_cred(cred); - return ret; + return security_ops->capable(tsk, cap, SECURITY_CAP_NOAUDIT); } int security_acct(struct file *file) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index eb6c45107a05..df30a7555d8a 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -1433,13 +1433,12 @@ static int current_has_perm(const struct task_struct *tsk, /* Check whether a task is allowed to use a capability. */ static int task_has_capability(struct task_struct *tsk, - const struct cred *cred, int cap, int audit) { struct avc_audit_data ad; struct av_decision avd; u16 sclass; - u32 sid = cred_sid(cred); + u32 sid = task_sid(tsk); u32 av = CAP_TO_MASK(cap); int rc; @@ -1866,27 +1865,15 @@ static int selinux_capset(struct cred *new, const struct cred *old, return cred_has_perm(old, new, PROCESS__SETCAP); } -static int selinux_capable(int cap, int audit) -{ - int rc; - - rc = secondary_ops->capable(cap, audit); - if (rc) - return rc; - - return task_has_capability(current, current_cred(), cap, audit); -} - -static int selinux_task_capable(struct task_struct *tsk, - const struct cred *cred, int cap, int audit) +static int selinux_capable(struct task_struct *tsk, int cap, int audit) { int rc; - rc = secondary_ops->task_capable(tsk, cred, cap, audit); + rc = secondary_ops->capable(tsk, cap, audit); if (rc) return rc; - return task_has_capability(tsk, cred, cap, audit); + return task_has_capability(tsk, cap, audit); } static int selinux_sysctl_get_sid(ctl_table *table, u16 tclass, u32 *sid) @@ -2050,7 +2037,7 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages) { int rc, cap_sys_admin = 0; - rc = selinux_capable(CAP_SYS_ADMIN, SECURITY_CAP_NOAUDIT); + rc = selinux_capable(current, CAP_SYS_ADMIN, SECURITY_CAP_NOAUDIT); if (rc == 0) cap_sys_admin = 1; @@ -2893,7 +2880,7 @@ static int selinux_inode_getsecurity(const struct inode *inode, const char *name * and lack of permission just means that we fall back to the * in-core context value, not a denial. */ - error = selinux_capable(CAP_MAC_ADMIN, SECURITY_CAP_NOAUDIT); + error = selinux_capable(current, CAP_MAC_ADMIN, SECURITY_CAP_NOAUDIT); if (!error) error = security_sid_to_context_force(isec->sid, &context, &size); @@ -5581,7 +5568,6 @@ static struct security_operations selinux_ops = { .capset = selinux_capset, .sysctl = selinux_sysctl, .capable = selinux_capable, - .task_capable = selinux_task_capable, .quotactl = selinux_quotactl, .quota_on = selinux_quota_on, .syslog = selinux_syslog, diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 7f12cc7015b6..6bfaba6177c2 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -2827,7 +2827,6 @@ struct security_operations smack_ops = { .capget = cap_capget, .capset = cap_capset, .capable = cap_capable, - .task_capable = cap_task_capable, .syslog = smack_syslog, .settime = cap_settime, .vm_enough_memory = cap_vm_enough_memory, -- 2.20.1