Skip to content

Commit 710584b

Browse files
author
James Morris
committed
Merge branch 'smack-for-4.11' of git://github.com/cschaufler/smack-next into next
2 parents c659af7 + 83a1e53 commit 710584b

File tree

3 files changed

+95
-27
lines changed

3 files changed

+95
-27
lines changed

security/smack/smack.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ struct inode_smack {
114114
struct smack_known *smk_mmap; /* label of the mmap domain */
115115
struct mutex smk_lock; /* initialization lock */
116116
int smk_flags; /* smack inode flags */
117+
struct rcu_head smk_rcu; /* for freeing inode_smack */
117118
};
118119

119120
struct task_smack {
@@ -173,6 +174,8 @@ struct smk_port_label {
173174
unsigned short smk_port; /* the port number */
174175
struct smack_known *smk_in; /* inbound label */
175176
struct smack_known *smk_out; /* outgoing label */
177+
short smk_sock_type; /* Socket type */
178+
short smk_can_reuse;
176179
};
177180
#endif /* SMACK_IPV6_PORT_LABELING */
178181

security/smack/smack_lsm.c

Lines changed: 87 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#define SMK_SENDING 2
5353

5454
#ifdef SMACK_IPV6_PORT_LABELING
55+
DEFINE_MUTEX(smack_ipv6_lock);
5556
static LIST_HEAD(smk_ipv6_port_list);
5657
#endif
5758
static struct kmem_cache *smack_inode_cache;
@@ -347,8 +348,6 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead,
347348
struct smack_rule *orp;
348349
int rc = 0;
349350

350-
INIT_LIST_HEAD(nhead);
351-
352351
list_for_each_entry_rcu(orp, ohead, list) {
353352
nrp = kzalloc(sizeof(struct smack_rule), gfp);
354353
if (nrp == NULL) {
@@ -375,8 +374,6 @@ static int smk_copy_relabel(struct list_head *nhead, struct list_head *ohead,
375374
struct smack_known_list_elem *nklep;
376375
struct smack_known_list_elem *oklep;
377376

378-
INIT_LIST_HEAD(nhead);
379-
380377
list_for_each_entry(oklep, ohead, list) {
381378
nklep = kzalloc(sizeof(struct smack_known_list_elem), gfp);
382379
if (nklep == NULL) {
@@ -1009,15 +1006,39 @@ static int smack_inode_alloc_security(struct inode *inode)
10091006
}
10101007

10111008
/**
1012-
* smack_inode_free_security - free an inode blob
1009+
* smack_inode_free_rcu - Free inode_smack blob from cache
1010+
* @head: the rcu_head for getting inode_smack pointer
1011+
*
1012+
* Call back function called from call_rcu() to free
1013+
* the i_security blob pointer in inode
1014+
*/
1015+
static void smack_inode_free_rcu(struct rcu_head *head)
1016+
{
1017+
struct inode_smack *issp;
1018+
1019+
issp = container_of(head, struct inode_smack, smk_rcu);
1020+
kmem_cache_free(smack_inode_cache, issp);
1021+
}
1022+
1023+
/**
1024+
* smack_inode_free_security - free an inode blob using call_rcu()
10131025
* @inode: the inode with a blob
10141026
*
1015-
* Clears the blob pointer in inode
1027+
* Clears the blob pointer in inode using RCU
10161028
*/
10171029
static void smack_inode_free_security(struct inode *inode)
10181030
{
1019-
kmem_cache_free(smack_inode_cache, inode->i_security);
1020-
inode->i_security = NULL;
1031+
struct inode_smack *issp = inode->i_security;
1032+
1033+
/*
1034+
* The inode may still be referenced in a path walk and
1035+
* a call to smack_inode_permission() can be made
1036+
* after smack_inode_free_security() is called.
1037+
* To avoid race condition free the i_security via RCU
1038+
* and leave the current inode->i_security pointer intact.
1039+
* The inode will be freed after the RCU grace period too.
1040+
*/
1041+
call_rcu(&issp->smk_rcu, smack_inode_free_rcu);
10211042
}
10221043

10231044
/**
@@ -1626,6 +1647,9 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd,
16261647
struct smk_audit_info ad;
16271648
struct inode *inode = file_inode(file);
16281649

1650+
if (unlikely(IS_PRIVATE(inode)))
1651+
return 0;
1652+
16291653
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
16301654
smk_ad_setfield_u_fs_path(&ad, file->f_path);
16311655

@@ -1655,6 +1679,9 @@ static int smack_file_lock(struct file *file, unsigned int cmd)
16551679
int rc;
16561680
struct inode *inode = file_inode(file);
16571681

1682+
if (unlikely(IS_PRIVATE(inode)))
1683+
return 0;
1684+
16581685
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
16591686
smk_ad_setfield_u_fs_path(&ad, file->f_path);
16601687
rc = smk_curacc(smk_of_inode(inode), MAY_LOCK, &ad);
@@ -1681,6 +1708,9 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
16811708
int rc = 0;
16821709
struct inode *inode = file_inode(file);
16831710

1711+
if (unlikely(IS_PRIVATE(inode)))
1712+
return 0;
1713+
16841714
switch (cmd) {
16851715
case F_GETLK:
16861716
break;
@@ -1734,6 +1764,9 @@ static int smack_mmap_file(struct file *file,
17341764
if (file == NULL)
17351765
return 0;
17361766

1767+
if (unlikely(IS_PRIVATE(file_inode(file))))
1768+
return 0;
1769+
17371770
isp = file_inode(file)->i_security;
17381771
if (isp->smk_mmap == NULL)
17391772
return 0;
@@ -1934,12 +1967,9 @@ static int smack_file_open(struct file *file, const struct cred *cred)
19341967
struct smk_audit_info ad;
19351968
int rc;
19361969

1937-
if (smack_privileged(CAP_MAC_OVERRIDE))
1938-
return 0;
1939-
19401970
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
19411971
smk_ad_setfield_u_fs_path(&ad, file->f_path);
1942-
rc = smk_access(tsp->smk_task, smk_of_inode(inode), MAY_READ, &ad);
1972+
rc = smk_tskacc(tsp, smk_of_inode(inode), MAY_READ, &ad);
19431973
rc = smk_bu_credfile(cred, file, MAY_READ, rc);
19441974

19451975
return rc;
@@ -2353,6 +2383,20 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
23532383
*/
23542384
static void smack_sk_free_security(struct sock *sk)
23552385
{
2386+
#ifdef SMACK_IPV6_PORT_LABELING
2387+
struct smk_port_label *spp;
2388+
2389+
if (sk->sk_family == PF_INET6) {
2390+
rcu_read_lock();
2391+
list_for_each_entry_rcu(spp, &smk_ipv6_port_list, list) {
2392+
if (spp->smk_sock != sk)
2393+
continue;
2394+
spp->smk_can_reuse = 1;
2395+
break;
2396+
}
2397+
rcu_read_unlock();
2398+
}
2399+
#endif
23562400
kfree(sk->sk_security);
23572401
}
23582402

@@ -2603,17 +2647,20 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
26032647
* on the bound socket. Take the changes to the port
26042648
* as well.
26052649
*/
2606-
list_for_each_entry(spp, &smk_ipv6_port_list, list) {
2650+
rcu_read_lock();
2651+
list_for_each_entry_rcu(spp, &smk_ipv6_port_list, list) {
26072652
if (sk != spp->smk_sock)
26082653
continue;
26092654
spp->smk_in = ssp->smk_in;
26102655
spp->smk_out = ssp->smk_out;
2656+
rcu_read_unlock();
26112657
return;
26122658
}
26132659
/*
26142660
* A NULL address is only used for updating existing
26152661
* bound entries. If there isn't one, it's OK.
26162662
*/
2663+
rcu_read_unlock();
26172664
return;
26182665
}
26192666

@@ -2629,16 +2676,23 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
26292676
* Look for an existing port list entry.
26302677
* This is an indication that a port is getting reused.
26312678
*/
2632-
list_for_each_entry(spp, &smk_ipv6_port_list, list) {
2633-
if (spp->smk_port != port)
2679+
rcu_read_lock();
2680+
list_for_each_entry_rcu(spp, &smk_ipv6_port_list, list) {
2681+
if (spp->smk_port != port || spp->smk_sock_type != sock->type)
26342682
continue;
2683+
if (spp->smk_can_reuse != 1) {
2684+
rcu_read_unlock();
2685+
return;
2686+
}
26352687
spp->smk_port = port;
26362688
spp->smk_sock = sk;
26372689
spp->smk_in = ssp->smk_in;
26382690
spp->smk_out = ssp->smk_out;
2691+
spp->smk_can_reuse = 0;
2692+
rcu_read_unlock();
26392693
return;
26402694
}
2641-
2695+
rcu_read_unlock();
26422696
/*
26432697
* A new port entry is required.
26442698
*/
@@ -2650,8 +2704,12 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
26502704
spp->smk_sock = sk;
26512705
spp->smk_in = ssp->smk_in;
26522706
spp->smk_out = ssp->smk_out;
2707+
spp->smk_sock_type = sock->type;
2708+
spp->smk_can_reuse = 0;
26532709

2654-
list_add(&spp->list, &smk_ipv6_port_list);
2710+
mutex_lock(&smack_ipv6_lock);
2711+
list_add_rcu(&spp->list, &smk_ipv6_port_list);
2712+
mutex_unlock(&smack_ipv6_lock);
26552713
return;
26562714
}
26572715

@@ -2702,14 +2760,16 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
27022760
return 0;
27032761

27042762
port = ntohs(address->sin6_port);
2705-
list_for_each_entry(spp, &smk_ipv6_port_list, list) {
2706-
if (spp->smk_port != port)
2763+
rcu_read_lock();
2764+
list_for_each_entry_rcu(spp, &smk_ipv6_port_list, list) {
2765+
if (spp->smk_port != port || spp->smk_sock_type != sk->sk_type)
27072766
continue;
27082767
object = spp->smk_in;
27092768
if (act == SMK_CONNECTING)
27102769
ssp->smk_packet = spp->smk_out;
27112770
break;
27122771
}
2772+
rcu_read_unlock();
27132773

27142774
return smk_ipv6_check(skp, object, address, act);
27152775
}
@@ -3438,6 +3498,13 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
34383498
case PIPEFS_MAGIC:
34393499
isp->smk_inode = smk_of_current();
34403500
break;
3501+
case SOCKFS_MAGIC:
3502+
/*
3503+
* Socket access is controlled by the socket
3504+
* structures associated with the task involved.
3505+
*/
3506+
isp->smk_inode = &smack_known_star;
3507+
break;
34413508
default:
34423509
isp->smk_inode = sbsp->smk_root;
34433510
break;
@@ -3454,19 +3521,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
34543521
*/
34553522
switch (sbp->s_magic) {
34563523
case SMACK_MAGIC:
3457-
case PIPEFS_MAGIC:
3458-
case SOCKFS_MAGIC:
34593524
case CGROUP_SUPER_MAGIC:
34603525
/*
34613526
* Casey says that it's a little embarrassing
34623527
* that the smack file system doesn't do
34633528
* extended attributes.
34643529
*
3465-
* Casey says pipes are easy (?)
3466-
*
3467-
* Socket access is controlled by the socket
3468-
* structures associated with the task involved.
3469-
*
34703530
* Cgroupfs is special
34713531
*/
34723532
final = &smack_known_star;
@@ -3849,7 +3909,7 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap,
38493909
* ambient value.
38503910
*/
38513911
rcu_read_lock();
3852-
list_for_each_entry(skp, &smack_known_list, list) {
3912+
list_for_each_entry_rcu(skp, &smack_known_list, list) {
38533913
if (sap->attr.mls.lvl != skp->smk_netlabel.attr.mls.lvl)
38543914
continue;
38553915
/*

security/smack/smackfs.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ enum smk_inos {
6767
/*
6868
* List locks
6969
*/
70+
static DEFINE_MUTEX(smack_master_list_lock);
7071
static DEFINE_MUTEX(smack_cipso_lock);
7172
static DEFINE_MUTEX(smack_ambient_lock);
7273
static DEFINE_MUTEX(smk_net4addr_lock);
@@ -262,12 +263,16 @@ static int smk_set_access(struct smack_parsed_rule *srp,
262263
* it needs to get added for reporting.
263264
*/
264265
if (global) {
266+
mutex_unlock(rule_lock);
265267
smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
266268
if (smlp != NULL) {
267269
smlp->smk_rule = sp;
270+
mutex_lock(&smack_master_list_lock);
268271
list_add_rcu(&smlp->list, &smack_rule_list);
272+
mutex_unlock(&smack_master_list_lock);
269273
} else
270274
rc = -ENOMEM;
275+
return rc;
271276
}
272277
}
273278

0 commit comments

Comments
 (0)