forked from luck/tmp_suning_uos_patched
Merge branch 'next-smack' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull smack updates from James Morris: "Bug fixes for IPv6 handling and other issues and two memory use improvements." * 'next-smack' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: Smack: Fix kbuild reported build error smack: Check address length before reading address family Smack: Fix IPv6 handling of 0 secmark Smack: Create smack_rule cache to optimize memory usage smack: removal of global rule list
This commit is contained in:
commit
800c608c97
|
@ -348,6 +348,7 @@ extern struct list_head smack_onlycap_list;
|
|||
|
||||
#define SMACK_HASH_SLOTS 16
|
||||
extern struct hlist_head smack_known_hash[SMACK_HASH_SLOTS];
|
||||
extern struct kmem_cache *smack_rule_cache;
|
||||
|
||||
static inline struct task_smack *smack_cred(const struct cred *cred)
|
||||
{
|
||||
|
|
|
@ -59,6 +59,7 @@ DEFINE_MUTEX(smack_ipv6_lock);
|
|||
static LIST_HEAD(smk_ipv6_port_list);
|
||||
#endif
|
||||
static struct kmem_cache *smack_inode_cache;
|
||||
struct kmem_cache *smack_rule_cache;
|
||||
int smack_enabled;
|
||||
|
||||
#define A(s) {"smack"#s, sizeof("smack"#s) - 1, Opt_##s}
|
||||
|
@ -354,7 +355,7 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead,
|
|||
int rc = 0;
|
||||
|
||||
list_for_each_entry_rcu(orp, ohead, list) {
|
||||
nrp = kzalloc(sizeof(struct smack_rule), gfp);
|
||||
nrp = kmem_cache_zalloc(smack_rule_cache, gfp);
|
||||
if (nrp == NULL) {
|
||||
rc = -ENOMEM;
|
||||
break;
|
||||
|
@ -1931,7 +1932,7 @@ static void smack_cred_free(struct cred *cred)
|
|||
list_for_each_safe(l, n, &tsp->smk_rules) {
|
||||
rp = list_entry(l, struct smack_rule, list);
|
||||
list_del(&rp->list);
|
||||
kfree(rp);
|
||||
kmem_cache_free(smack_rule_cache, rp);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2805,13 +2806,17 @@ static int smack_socket_socketpair(struct socket *socka,
|
|||
*
|
||||
* Records the label bound to a port.
|
||||
*
|
||||
* Returns 0
|
||||
* Returns 0 on success, and error code otherwise
|
||||
*/
|
||||
static int smack_socket_bind(struct socket *sock, struct sockaddr *address,
|
||||
int addrlen)
|
||||
{
|
||||
if (sock->sk != NULL && sock->sk->sk_family == PF_INET6)
|
||||
if (sock->sk != NULL && sock->sk->sk_family == PF_INET6) {
|
||||
if (addrlen < SIN6_LEN_RFC2133 ||
|
||||
address->sa_family != AF_INET6)
|
||||
return -EINVAL;
|
||||
smk_ipv6_port_label(sock, address);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif /* SMACK_IPV6_PORT_LABELING */
|
||||
|
@ -2847,12 +2852,13 @@ static int smack_socket_connect(struct socket *sock, struct sockaddr *sap,
|
|||
|
||||
switch (sock->sk->sk_family) {
|
||||
case PF_INET:
|
||||
if (addrlen < sizeof(struct sockaddr_in))
|
||||
if (addrlen < sizeof(struct sockaddr_in) ||
|
||||
sap->sa_family != AF_INET)
|
||||
return -EINVAL;
|
||||
rc = smack_netlabel_send(sock->sk, (struct sockaddr_in *)sap);
|
||||
break;
|
||||
case PF_INET6:
|
||||
if (addrlen < sizeof(struct sockaddr_in6))
|
||||
if (addrlen < SIN6_LEN_RFC2133 || sap->sa_family != AF_INET6)
|
||||
return -EINVAL;
|
||||
#ifdef SMACK_IPV6_SECMARK_LABELING
|
||||
rsp = smack_ipv6host_label(sip);
|
||||
|
@ -3682,9 +3688,16 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
|
|||
|
||||
switch (sock->sk->sk_family) {
|
||||
case AF_INET:
|
||||
if (msg->msg_namelen < sizeof(struct sockaddr_in) ||
|
||||
sip->sin_family != AF_INET)
|
||||
return -EINVAL;
|
||||
rc = smack_netlabel_send(sock->sk, sip);
|
||||
break;
|
||||
#if IS_ENABLED(CONFIG_IPV6)
|
||||
case AF_INET6:
|
||||
if (msg->msg_namelen < SIN6_LEN_RFC2133 ||
|
||||
sap->sin6_family != AF_INET6)
|
||||
return -EINVAL;
|
||||
#ifdef SMACK_IPV6_SECMARK_LABELING
|
||||
rsp = smack_ipv6host_label(sap);
|
||||
if (rsp != NULL)
|
||||
|
@ -3694,6 +3707,7 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
|
|||
#ifdef SMACK_IPV6_PORT_LABELING
|
||||
rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING);
|
||||
#endif
|
||||
#endif /* IS_ENABLED(CONFIG_IPV6) */
|
||||
break;
|
||||
}
|
||||
return rc;
|
||||
|
@ -3906,6 +3920,8 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
|
|||
#ifdef SMACK_IPV6_SECMARK_LABELING
|
||||
if (skb && skb->secmark != 0)
|
||||
skp = smack_from_secid(skb->secmark);
|
||||
else if (smk_ipv6_localhost(&sadd))
|
||||
break;
|
||||
else
|
||||
skp = smack_ipv6host_label(&sadd);
|
||||
if (skp == NULL)
|
||||
|
@ -4758,6 +4774,12 @@ static __init int smack_init(void)
|
|||
if (!smack_inode_cache)
|
||||
return -ENOMEM;
|
||||
|
||||
smack_rule_cache = KMEM_CACHE(smack_rule, 0);
|
||||
if (!smack_rule_cache) {
|
||||
kmem_cache_destroy(smack_inode_cache);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set the security state for the initial task.
|
||||
*/
|
||||
|
|
|
@ -67,7 +67,6 @@ enum smk_inos {
|
|||
/*
|
||||
* List locks
|
||||
*/
|
||||
static DEFINE_MUTEX(smack_master_list_lock);
|
||||
static DEFINE_MUTEX(smack_cipso_lock);
|
||||
static DEFINE_MUTEX(smack_ambient_lock);
|
||||
static DEFINE_MUTEX(smk_net4addr_lock);
|
||||
|
@ -134,15 +133,7 @@ LIST_HEAD(smk_net6addr_list);
|
|||
|
||||
/*
|
||||
* Rule lists are maintained for each label.
|
||||
* This master list is just for reading /smack/load and /smack/load2.
|
||||
*/
|
||||
struct smack_master_list {
|
||||
struct list_head list;
|
||||
struct smack_rule *smk_rule;
|
||||
};
|
||||
|
||||
static LIST_HEAD(smack_rule_list);
|
||||
|
||||
struct smack_parsed_rule {
|
||||
struct smack_known *smk_subject;
|
||||
struct smack_known *smk_object;
|
||||
|
@ -211,7 +202,6 @@ static void smk_netlabel_audit_set(struct netlbl_audit *nap)
|
|||
* @srp: the rule to add or replace
|
||||
* @rule_list: the list of rules
|
||||
* @rule_lock: the rule list lock
|
||||
* @global: if non-zero, indicates a global rule
|
||||
*
|
||||
* Looks through the current subject/object/access list for
|
||||
* the subject/object pair and replaces the access that was
|
||||
|
@ -223,10 +213,9 @@ static void smk_netlabel_audit_set(struct netlbl_audit *nap)
|
|||
*/
|
||||
static int smk_set_access(struct smack_parsed_rule *srp,
|
||||
struct list_head *rule_list,
|
||||
struct mutex *rule_lock, int global)
|
||||
struct mutex *rule_lock)
|
||||
{
|
||||
struct smack_rule *sp;
|
||||
struct smack_master_list *smlp;
|
||||
int found = 0;
|
||||
int rc = 0;
|
||||
|
||||
|
@ -247,7 +236,7 @@ static int smk_set_access(struct smack_parsed_rule *srp,
|
|||
}
|
||||
|
||||
if (found == 0) {
|
||||
sp = kzalloc(sizeof(*sp), GFP_KERNEL);
|
||||
sp = kmem_cache_zalloc(smack_rule_cache, GFP_KERNEL);
|
||||
if (sp == NULL) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
|
@ -258,22 +247,6 @@ static int smk_set_access(struct smack_parsed_rule *srp,
|
|||
sp->smk_access = srp->smk_access1 & ~srp->smk_access2;
|
||||
|
||||
list_add_rcu(&sp->list, rule_list);
|
||||
/*
|
||||
* If this is a global as opposed to self and a new rule
|
||||
* it needs to get added for reporting.
|
||||
*/
|
||||
if (global) {
|
||||
mutex_unlock(rule_lock);
|
||||
smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
|
||||
if (smlp != NULL) {
|
||||
smlp->smk_rule = sp;
|
||||
mutex_lock(&smack_master_list_lock);
|
||||
list_add_rcu(&smlp->list, &smack_rule_list);
|
||||
mutex_unlock(&smack_master_list_lock);
|
||||
} else
|
||||
rc = -ENOMEM;
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
|
@ -540,9 +513,9 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
|
|||
|
||||
if (rule_list == NULL)
|
||||
rc = smk_set_access(&rule, &rule.smk_subject->smk_rules,
|
||||
&rule.smk_subject->smk_rules_lock, 1);
|
||||
&rule.smk_subject->smk_rules_lock);
|
||||
else
|
||||
rc = smk_set_access(&rule, rule_list, rule_lock, 0);
|
||||
rc = smk_set_access(&rule, rule_list, rule_lock);
|
||||
|
||||
if (rc)
|
||||
goto out;
|
||||
|
@ -636,21 +609,23 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max)
|
|||
|
||||
static void *load2_seq_start(struct seq_file *s, loff_t *pos)
|
||||
{
|
||||
return smk_seq_start(s, pos, &smack_rule_list);
|
||||
return smk_seq_start(s, pos, &smack_known_list);
|
||||
}
|
||||
|
||||
static void *load2_seq_next(struct seq_file *s, void *v, loff_t *pos)
|
||||
{
|
||||
return smk_seq_next(s, v, pos, &smack_rule_list);
|
||||
return smk_seq_next(s, v, pos, &smack_known_list);
|
||||
}
|
||||
|
||||
static int load_seq_show(struct seq_file *s, void *v)
|
||||
{
|
||||
struct list_head *list = v;
|
||||
struct smack_master_list *smlp =
|
||||
list_entry_rcu(list, struct smack_master_list, list);
|
||||
struct smack_rule *srp;
|
||||
struct smack_known *skp =
|
||||
list_entry_rcu(list, struct smack_known, list);
|
||||
|
||||
smk_rule_show(s, smlp->smk_rule, SMK_LABELLEN);
|
||||
list_for_each_entry_rcu(srp, &skp->smk_rules, list)
|
||||
smk_rule_show(s, srp, SMK_LABELLEN);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -2352,10 +2327,12 @@ static const struct file_operations smk_access_ops = {
|
|||
static int load2_seq_show(struct seq_file *s, void *v)
|
||||
{
|
||||
struct list_head *list = v;
|
||||
struct smack_master_list *smlp =
|
||||
list_entry_rcu(list, struct smack_master_list, list);
|
||||
struct smack_rule *srp;
|
||||
struct smack_known *skp =
|
||||
list_entry_rcu(list, struct smack_known, list);
|
||||
|
||||
smk_rule_show(s, smlp->smk_rule, SMK_LONGLABEL);
|
||||
list_for_each_entry_rcu(srp, &skp->smk_rules, list)
|
||||
smk_rule_show(s, srp, SMK_LONGLABEL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user