Commit 29881c45 authored by James Morris's avatar James Morris
Browse files

Revert "CRED: Fix regression in cap_capable() as shown up by sys_faccessat() [ver #2]"

This reverts commit 14eaddc9.

David has a better version to come.
parent 76f7ba35
Loading
Loading
Loading
Loading
+2 −15
Original line number Diff line number Diff line
@@ -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);

+9 −40
Original line number Diff line number Diff line
@@ -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 <include/linux/capability.h>.
 *	@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 <include/linux/capability.h>.
 *	@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)
+1 −1
Original line number Diff line number Diff line
@@ -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;
	}
+0 −1
Original line number Diff line number Diff line
@@ -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);
+13 −29
Original line number Diff line number Diff line
@@ -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);
}
Loading