Merge branch 'for-linus' of git://selinuxproject.org/~jmorris/linux-security
* 'for-linus' of git://selinuxproject.org/~jmorris/linux-security: capabilities: remove __cap_full_set definition security: remove the security_netlink_recv hook as it is equivalent to capable() ptrace: do not audit capability check when outputing /proc/pid/stat capabilities: remove task_ns_* functions capabitlies: ns_capable can use the cap helpers rather than lsm call capabilities: style only - move capable below ns_capable capabilites: introduce new has_ns_capabilities_noaudit capabilities: call has_ns_capability from has_capability capabilities: remove all _real_ interfaces capabilities: introduce security_capable_noaudit capabilities: reverse arguments to security_capable capabilities: remove the task from capable LSM hook entirely selinux: sparse fix: fix several warnings in the security server cod selinux: sparse fix: fix warnings in netlink code selinux: sparse fix: eliminate warnings for selinuxfs selinux: sparse fix: declare selinux_disable() in security.h selinux: sparse fix: move selinux_complete_init selinux: sparse fix: make selinux_secmark_refcount static SELinux: Fix RCU deref check warning in sel_netport_insert() Manually fix up a semantic mis-merge wrt security_netlink_recv(): - the interface was removed in commitfd77846152
("security: remove the security_netlink_recv hook as it is equivalent to capable()") - a new user of it appeared in commita38f7907b9
("crypto: Add userspace configuration API") causing no automatic merge conflict, but Eric Paris pointed out the issue.
This commit is contained in:
commit
c49c41a413
24 changed files with 134 additions and 203 deletions
|
@ -382,7 +382,7 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|||
type -= CRYPTO_MSG_BASE;
|
||||
link = &crypto_dispatch[type];
|
||||
|
||||
if (security_netlink_recv(skb, CAP_NET_ADMIN))
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if ((type == (CRYPTO_MSG_GETALG - CRYPTO_MSG_BASE) &&
|
||||
|
|
|
@ -432,7 +432,7 @@ pci_read_config(struct file *filp, struct kobject *kobj,
|
|||
u8 *data = (u8*) buf;
|
||||
|
||||
/* Several chips lock up trying to read undefined config space */
|
||||
if (security_capable(&init_user_ns, filp->f_cred, CAP_SYS_ADMIN) == 0) {
|
||||
if (security_capable(filp->f_cred, &init_user_ns, CAP_SYS_ADMIN) == 0) {
|
||||
size = dev->cfg_size;
|
||||
} else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
|
||||
size = 128;
|
||||
|
|
|
@ -112,7 +112,7 @@ scsi_nl_rcv_msg(struct sk_buff *skb)
|
|||
goto next_msg;
|
||||
}
|
||||
|
||||
if (security_netlink_recv(skb, CAP_SYS_ADMIN)) {
|
||||
if (!capable(CAP_SYS_ADMIN)) {
|
||||
err = -EPERM;
|
||||
goto next_msg;
|
||||
}
|
||||
|
|
|
@ -380,7 +380,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
|
|||
|
||||
state = *get_task_state(task);
|
||||
vsize = eip = esp = 0;
|
||||
permitted = ptrace_may_access(task, PTRACE_MODE_READ);
|
||||
permitted = ptrace_may_access(task, PTRACE_MODE_READ | PTRACE_MODE_NOAUDIT);
|
||||
mm = get_task_mm(task);
|
||||
if (mm) {
|
||||
vsize = task_vsize(mm);
|
||||
|
|
|
@ -380,7 +380,6 @@ struct user_namespace;
|
|||
struct user_namespace *current_user_ns(void);
|
||||
|
||||
extern const kernel_cap_t __cap_empty_set;
|
||||
extern const kernel_cap_t __cap_full_set;
|
||||
extern const kernel_cap_t __cap_init_eff_set;
|
||||
|
||||
/*
|
||||
|
@ -544,9 +543,10 @@ extern bool has_capability(struct task_struct *t, int cap);
|
|||
extern bool has_ns_capability(struct task_struct *t,
|
||||
struct user_namespace *ns, int cap);
|
||||
extern bool has_capability_noaudit(struct task_struct *t, int cap);
|
||||
extern bool has_ns_capability_noaudit(struct task_struct *t,
|
||||
struct user_namespace *ns, int cap);
|
||||
extern bool capable(int cap);
|
||||
extern bool ns_capable(struct user_namespace *ns, int cap);
|
||||
extern bool task_ns_capable(struct task_struct *t, int cap);
|
||||
extern bool nsown_capable(int cap);
|
||||
|
||||
/* audit system wants to get cap info from files as well */
|
||||
|
|
|
@ -359,9 +359,11 @@ static inline void put_cred(const struct cred *_cred)
|
|||
|
||||
#ifdef CONFIG_USER_NS
|
||||
#define current_user_ns() (current_cred_xxx(user_ns))
|
||||
#define task_user_ns(task) (task_cred_xxx((task), user_ns))
|
||||
#else
|
||||
extern struct user_namespace init_user_ns;
|
||||
#define current_user_ns() (&init_user_ns)
|
||||
#define task_user_ns(task) (&init_user_ns)
|
||||
#endif
|
||||
|
||||
|
||||
|
|
|
@ -127,8 +127,9 @@ extern void __ptrace_link(struct task_struct *child,
|
|||
struct task_struct *new_parent);
|
||||
extern void __ptrace_unlink(struct task_struct *child);
|
||||
extern void exit_ptrace(struct task_struct *tracer);
|
||||
#define PTRACE_MODE_READ 1
|
||||
#define PTRACE_MODE_ATTACH 2
|
||||
#define PTRACE_MODE_READ 0x01
|
||||
#define PTRACE_MODE_ATTACH 0x02
|
||||
#define PTRACE_MODE_NOAUDIT 0x04
|
||||
/* Returns 0 on success, -errno on denial. */
|
||||
extern int __ptrace_may_access(struct task_struct *task, unsigned int mode);
|
||||
/* Returns true on success, false on denial. */
|
||||
|
|
|
@ -54,8 +54,8 @@ struct user_namespace;
|
|||
* These functions are in security/capability.c and are used
|
||||
* as the default capabilities functions
|
||||
*/
|
||||
extern int cap_capable(struct task_struct *tsk, const struct cred *cred,
|
||||
struct user_namespace *ns, int cap, int audit);
|
||||
extern int cap_capable(const struct cred *cred, struct user_namespace *ns,
|
||||
int cap, int audit);
|
||||
extern int cap_settime(const struct timespec *ts, const struct timezone *tz);
|
||||
extern int cap_ptrace_access_check(struct task_struct *child, unsigned int mode);
|
||||
extern int cap_ptrace_traceme(struct task_struct *parent);
|
||||
|
@ -96,7 +96,6 @@ struct xfrm_user_sec_ctx;
|
|||
struct seq_file;
|
||||
|
||||
extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
|
||||
extern int cap_netlink_recv(struct sk_buff *skb, int cap);
|
||||
|
||||
void reset_security_ops(void);
|
||||
|
||||
|
@ -799,12 +798,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
|
|||
* @skb contains the sk_buff structure for the netlink message.
|
||||
* Return 0 if the information was successfully saved and message
|
||||
* is allowed to be transmitted.
|
||||
* @netlink_recv:
|
||||
* Check permission before processing the received netlink message in
|
||||
* @skb.
|
||||
* @skb contains the sk_buff structure for the netlink message.
|
||||
* @cap indicates the capability required
|
||||
* Return 0 if permission is granted.
|
||||
*
|
||||
* Security hooks for Unix domain networking.
|
||||
*
|
||||
|
@ -1268,7 +1261,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
|
|||
* @capable:
|
||||
* Check whether the @tsk process has the @cap capability in the indicated
|
||||
* credentials.
|
||||
* @tsk contains the task_struct for the process.
|
||||
* @cred contains the credentials to use.
|
||||
* @ns contains the user namespace we want the capability in
|
||||
* @cap contains the capability <include/linux/capability.h>.
|
||||
|
@ -1392,8 +1384,8 @@ struct security_operations {
|
|||
const kernel_cap_t *effective,
|
||||
const kernel_cap_t *inheritable,
|
||||
const kernel_cap_t *permitted);
|
||||
int (*capable) (struct task_struct *tsk, const struct cred *cred,
|
||||
struct user_namespace *ns, int cap, int audit);
|
||||
int (*capable) (const struct cred *cred, struct user_namespace *ns,
|
||||
int cap, int audit);
|
||||
int (*quotactl) (int cmds, int type, int id, struct super_block *sb);
|
||||
int (*quota_on) (struct dentry *dentry);
|
||||
int (*syslog) (int type);
|
||||
|
@ -1563,7 +1555,6 @@ struct security_operations {
|
|||
struct sembuf *sops, unsigned nsops, int alter);
|
||||
|
||||
int (*netlink_send) (struct sock *sk, struct sk_buff *skb);
|
||||
int (*netlink_recv) (struct sk_buff *skb, int cap);
|
||||
|
||||
void (*d_instantiate) (struct dentry *dentry, struct inode *inode);
|
||||
|
||||
|
@ -1675,12 +1666,10 @@ 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(struct user_namespace *ns, const struct cred *cred,
|
||||
int security_capable(const struct cred *cred, struct user_namespace *ns,
|
||||
int cap);
|
||||
int security_real_capable(struct task_struct *tsk, struct user_namespace *ns,
|
||||
int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns,
|
||||
int cap);
|
||||
int security_real_capable_noaudit(struct task_struct *tsk,
|
||||
struct user_namespace *ns, int cap);
|
||||
int security_quotactl(int cmds, int type, int id, struct super_block *sb);
|
||||
int security_quota_on(struct dentry *dentry);
|
||||
int security_syslog(int type);
|
||||
|
@ -1817,7 +1806,6 @@ void security_d_instantiate(struct dentry *dentry, struct inode *inode);
|
|||
int security_getprocattr(struct task_struct *p, char *name, char **value);
|
||||
int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size);
|
||||
int security_netlink_send(struct sock *sk, struct sk_buff *skb);
|
||||
int security_netlink_recv(struct sk_buff *skb, int cap);
|
||||
int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
|
||||
int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
|
||||
void security_release_secctx(char *secdata, u32 seclen);
|
||||
|
@ -1875,32 +1863,15 @@ static inline int security_capset(struct cred *new,
|
|||
return cap_capset(new, old, effective, inheritable, permitted);
|
||||
}
|
||||
|
||||
static inline int security_capable(struct user_namespace *ns,
|
||||
const struct cred *cred, int cap)
|
||||
static inline int security_capable(const struct cred *cred,
|
||||
struct user_namespace *ns, int cap)
|
||||
{
|
||||
return cap_capable(current, cred, ns, cap, SECURITY_CAP_AUDIT);
|
||||
return cap_capable(cred, ns, cap, SECURITY_CAP_AUDIT);
|
||||
}
|
||||
|
||||
static inline int security_real_capable(struct task_struct *tsk, struct user_namespace *ns, int cap)
|
||||
{
|
||||
int ret;
|
||||
|
||||
rcu_read_lock();
|
||||
ret = cap_capable(tsk, __task_cred(tsk), ns, cap, SECURITY_CAP_AUDIT);
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline
|
||||
int security_real_capable_noaudit(struct task_struct *tsk, struct user_namespace *ns, int cap)
|
||||
{
|
||||
int ret;
|
||||
|
||||
rcu_read_lock();
|
||||
ret = cap_capable(tsk, __task_cred(tsk), ns, cap,
|
||||
SECURITY_CAP_NOAUDIT);
|
||||
rcu_read_unlock();
|
||||
return ret;
|
||||
static inline int security_capable_noaudit(const struct cred *cred,
|
||||
struct user_namespace *ns, int cap) {
|
||||
return cap_capable(cred, ns, cap, SECURITY_CAP_NOAUDIT);
|
||||
}
|
||||
|
||||
static inline int security_quotactl(int cmds, int type, int id,
|
||||
|
@ -2517,11 +2488,6 @@ static inline int security_netlink_send(struct sock *sk, struct sk_buff *skb)
|
|||
return cap_netlink_send(sk, skb);
|
||||
}
|
||||
|
||||
static inline int security_netlink_recv(struct sk_buff *skb, int cap)
|
||||
{
|
||||
return cap_netlink_recv(skb, cap);
|
||||
}
|
||||
|
||||
static inline int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
|
|
|
@ -601,13 +601,13 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 msg_type)
|
|||
case AUDIT_TTY_SET:
|
||||
case AUDIT_TRIM:
|
||||
case AUDIT_MAKE_EQUIV:
|
||||
if (security_netlink_recv(skb, CAP_AUDIT_CONTROL))
|
||||
if (!capable(CAP_AUDIT_CONTROL))
|
||||
err = -EPERM;
|
||||
break;
|
||||
case AUDIT_USER:
|
||||
case AUDIT_FIRST_USER_MSG ... AUDIT_LAST_USER_MSG:
|
||||
case AUDIT_FIRST_USER_MSG2 ... AUDIT_LAST_USER_MSG2:
|
||||
if (security_netlink_recv(skb, CAP_AUDIT_WRITE))
|
||||
if (!capable(CAP_AUDIT_WRITE))
|
||||
err = -EPERM;
|
||||
break;
|
||||
default: /* bad msg */
|
||||
|
|
|
@ -287,24 +287,7 @@ SYSCALL_DEFINE2(capset, cap_user_header_t, header, const cap_user_data_t, data)
|
|||
}
|
||||
|
||||
/**
|
||||
* has_capability - Does a task have a capability in init_user_ns
|
||||
* @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 to the initial user namespace, false if not.
|
||||
*
|
||||
* Note that this does not set PF_SUPERPRIV on the task.
|
||||
*/
|
||||
bool has_capability(struct task_struct *t, int cap)
|
||||
{
|
||||
int ret = security_real_capable(t, &init_user_ns, cap);
|
||||
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* has_capability - Does a task have a capability in a specific user ns
|
||||
* has_ns_capability - Does a task have a capability in a specific user ns
|
||||
* @t: The task in question
|
||||
* @ns: target user namespace
|
||||
* @cap: The capability to be tested for
|
||||
|
@ -317,13 +300,58 @@ bool has_capability(struct task_struct *t, int cap)
|
|||
bool has_ns_capability(struct task_struct *t,
|
||||
struct user_namespace *ns, int cap)
|
||||
{
|
||||
int ret = security_real_capable(t, ns, cap);
|
||||
int ret;
|
||||
|
||||
rcu_read_lock();
|
||||
ret = security_capable(__task_cred(t), ns, cap);
|
||||
rcu_read_unlock();
|
||||
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* has_capability_noaudit - Does a task have a capability (unaudited)
|
||||
* has_capability - Does a task have a capability in init_user_ns
|
||||
* @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 to the initial user namespace, false if not.
|
||||
*
|
||||
* Note that this does not set PF_SUPERPRIV on the task.
|
||||
*/
|
||||
bool has_capability(struct task_struct *t, int cap)
|
||||
{
|
||||
return has_ns_capability(t, &init_user_ns, cap);
|
||||
}
|
||||
|
||||
/**
|
||||
* has_ns_capability_noaudit - Does a task have a capability (unaudited)
|
||||
* in a specific user ns.
|
||||
* @t: The task in question
|
||||
* @ns: target user namespace
|
||||
* @cap: The capability to be tested for
|
||||
*
|
||||
* Return true if the specified task has the given superior capability
|
||||
* currently in effect to the specified user namespace, false if not.
|
||||
* Do not write an audit message for the check.
|
||||
*
|
||||
* Note that this does not set PF_SUPERPRIV on the task.
|
||||
*/
|
||||
bool has_ns_capability_noaudit(struct task_struct *t,
|
||||
struct user_namespace *ns, int cap)
|
||||
{
|
||||
int ret;
|
||||
|
||||
rcu_read_lock();
|
||||
ret = security_capable_noaudit(__task_cred(t), ns, cap);
|
||||
rcu_read_unlock();
|
||||
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* has_capability_noaudit - Does a task have a capability (unaudited) in the
|
||||
* initial user ns
|
||||
* @t: The task in question
|
||||
* @cap: The capability to be tested for
|
||||
*
|
||||
|
@ -335,27 +363,9 @@ bool has_ns_capability(struct task_struct *t,
|
|||
*/
|
||||
bool has_capability_noaudit(struct task_struct *t, int cap)
|
||||
{
|
||||
int ret = security_real_capable_noaudit(t, &init_user_ns, cap);
|
||||
|
||||
return (ret == 0);
|
||||
return has_ns_capability_noaudit(t, &init_user_ns, cap);
|
||||
}
|
||||
|
||||
/**
|
||||
* capable - Determine if the current task has a superior capability in effect
|
||||
* @cap: The capability to be tested for
|
||||
*
|
||||
* Return true if the current task has the given superior capability currently
|
||||
* available for use, false if not.
|
||||
*
|
||||
* This sets PF_SUPERPRIV on the task if the capability is available on the
|
||||
* assumption that it's about to be used.
|
||||
*/
|
||||
bool capable(int cap)
|
||||
{
|
||||
return ns_capable(&init_user_ns, cap);
|
||||
}
|
||||
EXPORT_SYMBOL(capable);
|
||||
|
||||
/**
|
||||
* ns_capable - Determine if the current task has a superior capability in effect
|
||||
* @ns: The usernamespace we want the capability in
|
||||
|
@ -374,7 +384,7 @@ bool ns_capable(struct user_namespace *ns, int cap)
|
|||
BUG();
|
||||
}
|
||||
|
||||
if (security_capable(ns, current_cred(), cap) == 0) {
|
||||
if (has_ns_capability(current, ns, cap)) {
|
||||
current->flags |= PF_SUPERPRIV;
|
||||
return true;
|
||||
}
|
||||
|
@ -383,18 +393,20 @@ bool ns_capable(struct user_namespace *ns, int cap)
|
|||
EXPORT_SYMBOL(ns_capable);
|
||||
|
||||
/**
|
||||
* task_ns_capable - Determine whether current task has a superior
|
||||
* capability targeted at a specific task's user namespace.
|
||||
* @t: The task whose user namespace is targeted.
|
||||
* @cap: The capability in question.
|
||||
* capable - Determine if the current task has a superior capability in effect
|
||||
* @cap: The capability to be tested for
|
||||
*
|
||||
* Return true if it does, false otherwise.
|
||||
* Return true if the current task has the given superior capability currently
|
||||
* available for use, false if not.
|
||||
*
|
||||
* This sets PF_SUPERPRIV on the task if the capability is available on the
|
||||
* assumption that it's about to be used.
|
||||
*/
|
||||
bool task_ns_capable(struct task_struct *t, int cap)
|
||||
bool capable(int cap)
|
||||
{
|
||||
return ns_capable(task_cred_xxx(t, user)->user_ns, cap);
|
||||
return ns_capable(&init_user_ns, cap);
|
||||
}
|
||||
EXPORT_SYMBOL(task_ns_capable);
|
||||
EXPORT_SYMBOL(capable);
|
||||
|
||||
/**
|
||||
* nsown_capable - Check superior capability to one's own user_ns
|
||||
|
|
|
@ -172,6 +172,14 @@ int ptrace_check_attach(struct task_struct *child, bool ignore_state)
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int ptrace_has_cap(struct user_namespace *ns, unsigned int mode)
|
||||
{
|
||||
if (mode & PTRACE_MODE_NOAUDIT)
|
||||
return has_ns_capability_noaudit(current, ns, CAP_SYS_PTRACE);
|
||||
else
|
||||
return has_ns_capability(current, ns, CAP_SYS_PTRACE);
|
||||
}
|
||||
|
||||
int __ptrace_may_access(struct task_struct *task, unsigned int mode)
|
||||
{
|
||||
const struct cred *cred = current_cred(), *tcred;
|
||||
|
@ -198,7 +206,7 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)
|
|||
cred->gid == tcred->sgid &&
|
||||
cred->gid == tcred->gid))
|
||||
goto ok;
|
||||
if (ns_capable(tcred->user->user_ns, CAP_SYS_PTRACE))
|
||||
if (ptrace_has_cap(tcred->user->user_ns, mode))
|
||||
goto ok;
|
||||
rcu_read_unlock();
|
||||
return -EPERM;
|
||||
|
@ -207,7 +215,7 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode)
|
|||
smp_rmb();
|
||||
if (task->mm)
|
||||
dumpable = get_dumpable(task->mm);
|
||||
if (!dumpable && !task_ns_capable(task, CAP_SYS_PTRACE))
|
||||
if (!dumpable && !ptrace_has_cap(task_user_ns(task), mode))
|
||||
return -EPERM;
|
||||
|
||||
return security_ptrace_access_check(task, mode);
|
||||
|
@ -277,7 +285,7 @@ static int ptrace_attach(struct task_struct *task, long request,
|
|||
task->ptrace = PT_PTRACED;
|
||||
if (seize)
|
||||
task->ptrace |= PT_SEIZED;
|
||||
if (task_ns_capable(task, CAP_SYS_PTRACE))
|
||||
if (ns_capable(task_user_ns(task), CAP_SYS_PTRACE))
|
||||
task->ptrace |= PT_PTRACE_CAP;
|
||||
|
||||
__ptrace_link(task, current);
|
||||
|
|
|
@ -4330,7 +4330,7 @@ long sched_setaffinity(pid_t pid, const struct cpumask *in_mask)
|
|||
goto out_free_cpus_allowed;
|
||||
}
|
||||
retval = -EPERM;
|
||||
if (!check_same_owner(p) && !task_ns_capable(p, CAP_SYS_NICE))
|
||||
if (!check_same_owner(p) && !ns_capable(task_user_ns(p), CAP_SYS_NICE))
|
||||
goto out_unlock;
|
||||
|
||||
retval = security_task_setscheduler(p);
|
||||
|
|
|
@ -1960,7 +1960,7 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|||
sz_idx = type>>2;
|
||||
kind = type&3;
|
||||
|
||||
if (kind != 2 && security_netlink_recv(skb, CAP_NET_ADMIN))
|
||||
if (kind != 2 && !capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (kind == 2 && nlh->nlmsg_flags&NLM_F_DUMP) {
|
||||
|
|
|
@ -108,7 +108,7 @@ static inline void dnrmg_receive_user_skb(struct sk_buff *skb)
|
|||
if (nlh->nlmsg_len < sizeof(*nlh) || skb->len < nlh->nlmsg_len)
|
||||
return;
|
||||
|
||||
if (security_netlink_recv(skb, CAP_NET_ADMIN))
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
RCV_SKB_FAIL(-EPERM);
|
||||
|
||||
/* Eventually we might send routing messages too */
|
||||
|
|
|
@ -431,7 +431,7 @@ __ipq_rcv_skb(struct sk_buff *skb)
|
|||
if (type <= IPQM_BASE)
|
||||
return;
|
||||
|
||||
if (security_netlink_recv(skb, CAP_NET_ADMIN))
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
RCV_SKB_FAIL(-EPERM);
|
||||
|
||||
spin_lock_bh(&queue_lock);
|
||||
|
|
|
@ -432,7 +432,7 @@ __ipq_rcv_skb(struct sk_buff *skb)
|
|||
if (type <= IPQM_BASE)
|
||||
return;
|
||||
|
||||
if (security_netlink_recv(skb, CAP_NET_ADMIN))
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
RCV_SKB_FAIL(-EPERM);
|
||||
|
||||
spin_lock_bh(&queue_lock);
|
||||
|
|
|
@ -130,7 +130,7 @@ static int nfnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|||
const struct nfnetlink_subsystem *ss;
|
||||
int type, err;
|
||||
|
||||
if (security_netlink_recv(skb, CAP_NET_ADMIN))
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
/* All the messages must at least contain nfgenmsg */
|
||||
|
|
|
@ -524,7 +524,7 @@ static int genl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|||
return -EOPNOTSUPP;
|
||||
|
||||
if ((ops->flags & GENL_ADMIN_PERM) &&
|
||||
security_netlink_recv(skb, CAP_NET_ADMIN))
|
||||
!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if (nlh->nlmsg_flags & NLM_F_DUMP) {
|
||||
|
|
|
@ -2290,7 +2290,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
|
|||
link = &xfrm_dispatch[type];
|
||||
|
||||
/* All operations require privileges, even GET */
|
||||
if (security_netlink_recv(skb, CAP_NET_ADMIN))
|
||||
if (!capable(CAP_NET_ADMIN))
|
||||
return -EPERM;
|
||||
|
||||
if ((type == (XFRM_MSG_GETSA - XFRM_MSG_BASE) ||
|
||||
|
|
|
@ -136,16 +136,16 @@ static int apparmor_capget(struct task_struct *target, kernel_cap_t *effective,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int apparmor_capable(struct task_struct *task, const struct cred *cred,
|
||||
struct user_namespace *ns, int cap, int audit)
|
||||
static int apparmor_capable(const struct cred *cred, struct user_namespace *ns,
|
||||
int cap, int audit)
|
||||
{
|
||||
struct aa_profile *profile;
|
||||
/* cap_capable returns 0 on success, else -EPERM */
|
||||
int error = cap_capable(task, cred, ns, cap, audit);
|
||||
int error = cap_capable(cred, ns, cap, audit);
|
||||
if (!error) {
|
||||
profile = aa_cred_profile(cred);
|
||||
if (!unconfined(profile))
|
||||
error = aa_capable(task, profile, cap, audit);
|
||||
error = aa_capable(current, profile, cap, audit);
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
|
|
@ -998,7 +998,6 @@ void __init security_fixup_ops(struct security_operations *ops)
|
|||
set_to_cap_if_null(ops, sem_semctl);
|
||||
set_to_cap_if_null(ops, sem_semop);
|
||||
set_to_cap_if_null(ops, netlink_send);
|
||||
set_to_cap_if_null(ops, netlink_recv);
|
||||
set_to_cap_if_null(ops, d_instantiate);
|
||||
set_to_cap_if_null(ops, getprocattr);
|
||||
set_to_cap_if_null(ops, setprocattr);
|
||||
|
|
|
@ -56,17 +56,8 @@ int cap_netlink_send(struct sock *sk, struct sk_buff *skb)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int cap_netlink_recv(struct sk_buff *skb, int cap)
|
||||
{
|
||||
if (!cap_raised(current_cap(), cap))
|
||||
return -EPERM;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(cap_netlink_recv);
|
||||
|
||||
/**
|
||||
* cap_capable - Determine whether a task has a particular effective capability
|
||||
* @tsk: The task to query
|
||||
* @cred: The credentials to use
|
||||
* @ns: The user namespace in which we need the capability
|
||||
* @cap: The capability to check for
|
||||
|
@ -80,8 +71,8 @@ EXPORT_SYMBOL(cap_netlink_recv);
|
|||
* cap_has_capability() returns 0 when a task has a capability, but the
|
||||
* kernel's capable() and has_capability() returns 1 for this case.
|
||||
*/
|
||||
int cap_capable(struct task_struct *tsk, const struct cred *cred,
|
||||
struct user_namespace *targ_ns, int cap, int audit)
|
||||
int cap_capable(const struct cred *cred, struct user_namespace *targ_ns,
|
||||
int cap, int audit)
|
||||
{
|
||||
for (;;) {
|
||||
/* The creator of the user namespace has all caps. */
|
||||
|
@ -222,9 +213,8 @@ static inline int cap_inh_is_capped(void)
|
|||
/* they are so limited unless the current task has the CAP_SETPCAP
|
||||
* capability
|
||||
*/
|
||||
if (cap_capable(current, current_cred(),
|
||||
current_cred()->user->user_ns, CAP_SETPCAP,
|
||||
SECURITY_CAP_AUDIT) == 0)
|
||||
if (cap_capable(current_cred(), current_cred()->user->user_ns,
|
||||
CAP_SETPCAP, SECURITY_CAP_AUDIT) == 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
@ -874,7 +864,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(current, current_cred(),
|
||||
|| (cap_capable(current_cred(),
|
||||
current_cred()->user->user_ns, CAP_SETPCAP,
|
||||
SECURITY_CAP_AUDIT) != 0) /*[4]*/
|
||||
/*
|
||||
|
@ -940,7 +930,7 @@ int cap_vm_enough_memory(struct mm_struct *mm, long pages)
|
|||
{
|
||||
int cap_sys_admin = 0;
|
||||
|
||||
if (cap_capable(current, current_cred(), &init_user_ns, CAP_SYS_ADMIN,
|
||||
if (cap_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
|
||||
SECURITY_CAP_NOAUDIT) == 0)
|
||||
cap_sys_admin = 1;
|
||||
return __vm_enough_memory(mm, pages, cap_sys_admin);
|
||||
|
@ -967,7 +957,7 @@ int cap_file_mmap(struct file *file, unsigned long reqprot,
|
|||
int ret = 0;
|
||||
|
||||
if (addr < dac_mmap_min_addr) {
|
||||
ret = cap_capable(current, current_cred(), &init_user_ns, CAP_SYS_RAWIO,
|
||||
ret = cap_capable(current_cred(), &init_user_ns, CAP_SYS_RAWIO,
|
||||
SECURITY_CAP_AUDIT);
|
||||
/* set PF_SUPERPRIV if it turns out we allow the low mmap */
|
||||
if (ret == 0)
|
||||
|
|
|
@ -155,35 +155,16 @@ int security_capset(struct cred *new, const struct cred *old,
|
|||
effective, inheritable, permitted);
|
||||
}
|
||||
|
||||
int security_capable(struct user_namespace *ns, const struct cred *cred,
|
||||
int security_capable(const struct cred *cred, struct user_namespace *ns,
|
||||
int cap)
|
||||
{
|
||||
return security_ops->capable(current, cred, ns, cap,
|
||||
SECURITY_CAP_AUDIT);
|
||||
return security_ops->capable(cred, ns, cap, SECURITY_CAP_AUDIT);
|
||||
}
|
||||
|
||||
int security_real_capable(struct task_struct *tsk, struct user_namespace *ns,
|
||||
int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns,
|
||||
int cap)
|
||||
{
|
||||
const struct cred *cred;
|
||||
int ret;
|
||||
|
||||
cred = get_task_cred(tsk);
|
||||
ret = security_ops->capable(tsk, cred, ns, cap, SECURITY_CAP_AUDIT);
|
||||
put_cred(cred);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int security_real_capable_noaudit(struct task_struct *tsk,
|
||||
struct user_namespace *ns, int cap)
|
||||
{
|
||||
const struct cred *cred;
|
||||
int ret;
|
||||
|
||||
cred = get_task_cred(tsk);
|
||||
ret = security_ops->capable(tsk, cred, ns, cap, SECURITY_CAP_NOAUDIT);
|
||||
put_cred(cred);
|
||||
return ret;
|
||||
return security_ops->capable(cred, ns, cap, SECURITY_CAP_NOAUDIT);
|
||||
}
|
||||
|
||||
int security_quotactl(int cmds, int type, int id, struct super_block *sb)
|
||||
|
@ -994,12 +975,6 @@ int security_netlink_send(struct sock *sk, struct sk_buff *skb)
|
|||
return security_ops->netlink_send(sk, skb);
|
||||
}
|
||||
|
||||
int security_netlink_recv(struct sk_buff *skb, int cap)
|
||||
{
|
||||
return security_ops->netlink_recv(skb, cap);
|
||||
}
|
||||
EXPORT_SYMBOL(security_netlink_recv);
|
||||
|
||||
int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
|
||||
{
|
||||
return security_ops->secid_to_secctx(secid, secdata, seclen);
|
||||
|
|
|
@ -1415,8 +1415,7 @@ static int current_has_perm(const struct task_struct *tsk,
|
|||
#endif
|
||||
|
||||
/* Check whether a task is allowed to use a capability. */
|
||||
static int task_has_capability(struct task_struct *tsk,
|
||||
const struct cred *cred,
|
||||
static int cred_has_capability(const struct cred *cred,
|
||||
int cap, int audit)
|
||||
{
|
||||
struct common_audit_data ad;
|
||||
|
@ -1427,7 +1426,7 @@ static int task_has_capability(struct task_struct *tsk,
|
|||
int rc;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, CAP);
|
||||
ad.tsk = tsk;
|
||||
ad.tsk = current;
|
||||
ad.u.cap = cap;
|
||||
|
||||
switch (CAP_TO_INDEX(cap)) {
|
||||
|
@ -1811,7 +1810,7 @@ static int selinux_ptrace_access_check(struct task_struct *child,
|
|||
if (rc)
|
||||
return rc;
|
||||
|
||||
if (mode == PTRACE_MODE_READ) {
|
||||
if (mode & PTRACE_MODE_READ) {
|
||||
u32 sid = current_sid();
|
||||
u32 csid = task_sid(child);
|
||||
return avc_has_perm(sid, csid, SECCLASS_FILE, FILE__READ, NULL);
|
||||
|
@ -1868,16 +1867,16 @@ static int selinux_capset(struct cred *new, const struct cred *old,
|
|||
* the CAP_SETUID and CAP_SETGID capabilities using the capable hook.
|
||||
*/
|
||||
|
||||
static int selinux_capable(struct task_struct *tsk, const struct cred *cred,
|
||||
struct user_namespace *ns, int cap, int audit)
|
||||
static int selinux_capable(const struct cred *cred, struct user_namespace *ns,
|
||||
int cap, int audit)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = cap_capable(tsk, cred, ns, cap, audit);
|
||||
rc = cap_capable(cred, ns, cap, audit);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return task_has_capability(tsk, cred, cap, audit);
|
||||
return cred_has_capability(cred, cap, audit);
|
||||
}
|
||||
|
||||
static int selinux_quotactl(int cmds, int type, int id, struct super_block *sb)
|
||||
|
@ -1954,8 +1953,7 @@ static int selinux_vm_enough_memory(struct mm_struct *mm, long pages)
|
|||
{
|
||||
int rc, cap_sys_admin = 0;
|
||||
|
||||
rc = selinux_capable(current, current_cred(),
|
||||
&init_user_ns, CAP_SYS_ADMIN,
|
||||
rc = selinux_capable(current_cred(), &init_user_ns, CAP_SYS_ADMIN,
|
||||
SECURITY_CAP_NOAUDIT);
|
||||
if (rc == 0)
|
||||
cap_sys_admin = 1;
|
||||
|
@ -2859,8 +2857,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(current, current_cred(),
|
||||
&init_user_ns, CAP_MAC_ADMIN,
|
||||
error = selinux_capable(current_cred(), &init_user_ns, CAP_MAC_ADMIN,
|
||||
SECURITY_CAP_NOAUDIT);
|
||||
if (!error)
|
||||
error = security_sid_to_context_force(isec->sid, &context,
|
||||
|
@ -2993,7 +2990,7 @@ static int selinux_file_ioctl(struct file *file, unsigned int cmd,
|
|||
|
||||
case KDSKBENT:
|
||||
case KDSKBSENT:
|
||||
error = task_has_capability(current, cred, CAP_SYS_TTY_CONFIG,
|
||||
error = cred_has_capability(cred, CAP_SYS_TTY_CONFIG,
|
||||
SECURITY_CAP_AUDIT);
|
||||
break;
|
||||
|
||||
|
@ -4718,24 +4715,6 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
|
|||
return selinux_nlmsg_perm(sk, skb);
|
||||
}
|
||||
|
||||
static int selinux_netlink_recv(struct sk_buff *skb, int capability)
|
||||
{
|
||||
int err;
|
||||
struct common_audit_data ad;
|
||||
u32 sid;
|
||||
|
||||
err = cap_netlink_recv(skb, capability);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
COMMON_AUDIT_DATA_INIT(&ad, CAP);
|
||||
ad.u.cap = capability;
|
||||
|
||||
security_task_getsecid(current, &sid);
|
||||
return avc_has_perm(sid, sid, SECCLASS_CAPABILITY,
|
||||
CAP_TO_MASK(capability), &ad);
|
||||
}
|
||||
|
||||
static int ipc_alloc_security(struct task_struct *task,
|
||||
struct kern_ipc_perm *perm,
|
||||
u16 sclass)
|
||||
|
@ -5464,7 +5443,6 @@ static struct security_operations selinux_ops = {
|
|||
.vm_enough_memory = selinux_vm_enough_memory,
|
||||
|
||||
.netlink_send = selinux_netlink_send,
|
||||
.netlink_recv = selinux_netlink_recv,
|
||||
|
||||
.bprm_set_creds = selinux_bprm_set_creds,
|
||||
.bprm_committing_creds = selinux_bprm_committing_creds,
|
||||
|
|
Loading…
Reference in a new issue