mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 17:30:02 +00:00
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
3 changed files with 45 additions and 45 deletions
|
@ -348,6 +348,7 @@ extern struct list_head smack_onlycap_list;
|
||||||
|
|
||||||
#define SMACK_HASH_SLOTS 16
|
#define SMACK_HASH_SLOTS 16
|
||||||
extern struct hlist_head smack_known_hash[SMACK_HASH_SLOTS];
|
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)
|
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);
|
static LIST_HEAD(smk_ipv6_port_list);
|
||||||
#endif
|
#endif
|
||||||
static struct kmem_cache *smack_inode_cache;
|
static struct kmem_cache *smack_inode_cache;
|
||||||
|
struct kmem_cache *smack_rule_cache;
|
||||||
int smack_enabled;
|
int smack_enabled;
|
||||||
|
|
||||||
#define A(s) {"smack"#s, sizeof("smack"#s) - 1, Opt_##s}
|
#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;
|
int rc = 0;
|
||||||
|
|
||||||
list_for_each_entry_rcu(orp, ohead, list) {
|
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) {
|
if (nrp == NULL) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
break;
|
break;
|
||||||
|
@ -1931,7 +1932,7 @@ static void smack_cred_free(struct cred *cred)
|
||||||
list_for_each_safe(l, n, &tsp->smk_rules) {
|
list_for_each_safe(l, n, &tsp->smk_rules) {
|
||||||
rp = list_entry(l, struct smack_rule, list);
|
rp = list_entry(l, struct smack_rule, list);
|
||||||
list_del(&rp->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.
|
* 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,
|
static int smack_socket_bind(struct socket *sock, struct sockaddr *address,
|
||||||
int addrlen)
|
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);
|
smk_ipv6_port_label(sock, address);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif /* SMACK_IPV6_PORT_LABELING */
|
#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) {
|
switch (sock->sk->sk_family) {
|
||||||
case PF_INET:
|
case PF_INET:
|
||||||
if (addrlen < sizeof(struct sockaddr_in))
|
if (addrlen < sizeof(struct sockaddr_in) ||
|
||||||
|
sap->sa_family != AF_INET)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
rc = smack_netlabel_send(sock->sk, (struct sockaddr_in *)sap);
|
rc = smack_netlabel_send(sock->sk, (struct sockaddr_in *)sap);
|
||||||
break;
|
break;
|
||||||
case PF_INET6:
|
case PF_INET6:
|
||||||
if (addrlen < sizeof(struct sockaddr_in6))
|
if (addrlen < SIN6_LEN_RFC2133 || sap->sa_family != AF_INET6)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
#ifdef SMACK_IPV6_SECMARK_LABELING
|
#ifdef SMACK_IPV6_SECMARK_LABELING
|
||||||
rsp = smack_ipv6host_label(sip);
|
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) {
|
switch (sock->sk->sk_family) {
|
||||||
case AF_INET:
|
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);
|
rc = smack_netlabel_send(sock->sk, sip);
|
||||||
break;
|
break;
|
||||||
|
#if IS_ENABLED(CONFIG_IPV6)
|
||||||
case AF_INET6:
|
case AF_INET6:
|
||||||
|
if (msg->msg_namelen < SIN6_LEN_RFC2133 ||
|
||||||
|
sap->sin6_family != AF_INET6)
|
||||||
|
return -EINVAL;
|
||||||
#ifdef SMACK_IPV6_SECMARK_LABELING
|
#ifdef SMACK_IPV6_SECMARK_LABELING
|
||||||
rsp = smack_ipv6host_label(sap);
|
rsp = smack_ipv6host_label(sap);
|
||||||
if (rsp != NULL)
|
if (rsp != NULL)
|
||||||
|
@ -3694,6 +3707,7 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg,
|
||||||
#ifdef SMACK_IPV6_PORT_LABELING
|
#ifdef SMACK_IPV6_PORT_LABELING
|
||||||
rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING);
|
rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING);
|
||||||
#endif
|
#endif
|
||||||
|
#endif /* IS_ENABLED(CONFIG_IPV6) */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return rc;
|
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
|
#ifdef SMACK_IPV6_SECMARK_LABELING
|
||||||
if (skb && skb->secmark != 0)
|
if (skb && skb->secmark != 0)
|
||||||
skp = smack_from_secid(skb->secmark);
|
skp = smack_from_secid(skb->secmark);
|
||||||
|
else if (smk_ipv6_localhost(&sadd))
|
||||||
|
break;
|
||||||
else
|
else
|
||||||
skp = smack_ipv6host_label(&sadd);
|
skp = smack_ipv6host_label(&sadd);
|
||||||
if (skp == NULL)
|
if (skp == NULL)
|
||||||
|
@ -4758,6 +4774,12 @@ static __init int smack_init(void)
|
||||||
if (!smack_inode_cache)
|
if (!smack_inode_cache)
|
||||||
return -ENOMEM;
|
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.
|
* Set the security state for the initial task.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -67,7 +67,6 @@ enum smk_inos {
|
||||||
/*
|
/*
|
||||||
* List locks
|
* List locks
|
||||||
*/
|
*/
|
||||||
static DEFINE_MUTEX(smack_master_list_lock);
|
|
||||||
static DEFINE_MUTEX(smack_cipso_lock);
|
static DEFINE_MUTEX(smack_cipso_lock);
|
||||||
static DEFINE_MUTEX(smack_ambient_lock);
|
static DEFINE_MUTEX(smack_ambient_lock);
|
||||||
static DEFINE_MUTEX(smk_net4addr_lock);
|
static DEFINE_MUTEX(smk_net4addr_lock);
|
||||||
|
@ -134,15 +133,7 @@ LIST_HEAD(smk_net6addr_list);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Rule lists are maintained for each label.
|
* 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_parsed_rule {
|
||||||
struct smack_known *smk_subject;
|
struct smack_known *smk_subject;
|
||||||
struct smack_known *smk_object;
|
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
|
* @srp: the rule to add or replace
|
||||||
* @rule_list: the list of rules
|
* @rule_list: the list of rules
|
||||||
* @rule_lock: the rule list lock
|
* @rule_lock: the rule list lock
|
||||||
* @global: if non-zero, indicates a global rule
|
|
||||||
*
|
*
|
||||||
* Looks through the current subject/object/access list for
|
* Looks through the current subject/object/access list for
|
||||||
* the subject/object pair and replaces the access that was
|
* 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,
|
static int smk_set_access(struct smack_parsed_rule *srp,
|
||||||
struct list_head *rule_list,
|
struct list_head *rule_list,
|
||||||
struct mutex *rule_lock, int global)
|
struct mutex *rule_lock)
|
||||||
{
|
{
|
||||||
struct smack_rule *sp;
|
struct smack_rule *sp;
|
||||||
struct smack_master_list *smlp;
|
|
||||||
int found = 0;
|
int found = 0;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
|
@ -247,7 +236,7 @@ static int smk_set_access(struct smack_parsed_rule *srp,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found == 0) {
|
if (found == 0) {
|
||||||
sp = kzalloc(sizeof(*sp), GFP_KERNEL);
|
sp = kmem_cache_zalloc(smack_rule_cache, GFP_KERNEL);
|
||||||
if (sp == NULL) {
|
if (sp == NULL) {
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
goto out;
|
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;
|
sp->smk_access = srp->smk_access1 & ~srp->smk_access2;
|
||||||
|
|
||||||
list_add_rcu(&sp->list, rule_list);
|
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:
|
out:
|
||||||
|
@ -540,9 +513,9 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
|
||||||
|
|
||||||
if (rule_list == NULL)
|
if (rule_list == NULL)
|
||||||
rc = smk_set_access(&rule, &rule.smk_subject->smk_rules,
|
rc = smk_set_access(&rule, &rule.smk_subject->smk_rules,
|
||||||
&rule.smk_subject->smk_rules_lock, 1);
|
&rule.smk_subject->smk_rules_lock);
|
||||||
else
|
else
|
||||||
rc = smk_set_access(&rule, rule_list, rule_lock, 0);
|
rc = smk_set_access(&rule, rule_list, rule_lock);
|
||||||
|
|
||||||
if (rc)
|
if (rc)
|
||||||
goto out;
|
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)
|
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)
|
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)
|
static int load_seq_show(struct seq_file *s, void *v)
|
||||||
{
|
{
|
||||||
struct list_head *list = v;
|
struct list_head *list = v;
|
||||||
struct smack_master_list *smlp =
|
struct smack_rule *srp;
|
||||||
list_entry_rcu(list, struct smack_master_list, list);
|
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;
|
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)
|
static int load2_seq_show(struct seq_file *s, void *v)
|
||||||
{
|
{
|
||||||
struct list_head *list = v;
|
struct list_head *list = v;
|
||||||
struct smack_master_list *smlp =
|
struct smack_rule *srp;
|
||||||
list_entry_rcu(list, struct smack_master_list, list);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue