forked from Minki/linux
Merge branch 'smack-for-4.11' of git://github.com/cschaufler/smack-next into next
This commit is contained in:
commit
710584b9da
|
@ -114,6 +114,7 @@ struct inode_smack {
|
||||||
struct smack_known *smk_mmap; /* label of the mmap domain */
|
struct smack_known *smk_mmap; /* label of the mmap domain */
|
||||||
struct mutex smk_lock; /* initialization lock */
|
struct mutex smk_lock; /* initialization lock */
|
||||||
int smk_flags; /* smack inode flags */
|
int smk_flags; /* smack inode flags */
|
||||||
|
struct rcu_head smk_rcu; /* for freeing inode_smack */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct task_smack {
|
struct task_smack {
|
||||||
|
@ -173,6 +174,8 @@ struct smk_port_label {
|
||||||
unsigned short smk_port; /* the port number */
|
unsigned short smk_port; /* the port number */
|
||||||
struct smack_known *smk_in; /* inbound label */
|
struct smack_known *smk_in; /* inbound label */
|
||||||
struct smack_known *smk_out; /* outgoing label */
|
struct smack_known *smk_out; /* outgoing label */
|
||||||
|
short smk_sock_type; /* Socket type */
|
||||||
|
short smk_can_reuse;
|
||||||
};
|
};
|
||||||
#endif /* SMACK_IPV6_PORT_LABELING */
|
#endif /* SMACK_IPV6_PORT_LABELING */
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,7 @@
|
||||||
#define SMK_SENDING 2
|
#define SMK_SENDING 2
|
||||||
|
|
||||||
#ifdef SMACK_IPV6_PORT_LABELING
|
#ifdef SMACK_IPV6_PORT_LABELING
|
||||||
|
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;
|
||||||
|
@ -347,8 +348,6 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead,
|
||||||
struct smack_rule *orp;
|
struct smack_rule *orp;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
INIT_LIST_HEAD(nhead);
|
|
||||||
|
|
||||||
list_for_each_entry_rcu(orp, ohead, list) {
|
list_for_each_entry_rcu(orp, ohead, list) {
|
||||||
nrp = kzalloc(sizeof(struct smack_rule), gfp);
|
nrp = kzalloc(sizeof(struct smack_rule), gfp);
|
||||||
if (nrp == NULL) {
|
if (nrp == NULL) {
|
||||||
|
@ -375,8 +374,6 @@ static int smk_copy_relabel(struct list_head *nhead, struct list_head *ohead,
|
||||||
struct smack_known_list_elem *nklep;
|
struct smack_known_list_elem *nklep;
|
||||||
struct smack_known_list_elem *oklep;
|
struct smack_known_list_elem *oklep;
|
||||||
|
|
||||||
INIT_LIST_HEAD(nhead);
|
|
||||||
|
|
||||||
list_for_each_entry(oklep, ohead, list) {
|
list_for_each_entry(oklep, ohead, list) {
|
||||||
nklep = kzalloc(sizeof(struct smack_known_list_elem), gfp);
|
nklep = kzalloc(sizeof(struct smack_known_list_elem), gfp);
|
||||||
if (nklep == NULL) {
|
if (nklep == NULL) {
|
||||||
|
@ -1009,15 +1006,39 @@ static int smack_inode_alloc_security(struct inode *inode)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* smack_inode_free_security - free an inode blob
|
* smack_inode_free_rcu - Free inode_smack blob from cache
|
||||||
|
* @head: the rcu_head for getting inode_smack pointer
|
||||||
|
*
|
||||||
|
* Call back function called from call_rcu() to free
|
||||||
|
* the i_security blob pointer in inode
|
||||||
|
*/
|
||||||
|
static void smack_inode_free_rcu(struct rcu_head *head)
|
||||||
|
{
|
||||||
|
struct inode_smack *issp;
|
||||||
|
|
||||||
|
issp = container_of(head, struct inode_smack, smk_rcu);
|
||||||
|
kmem_cache_free(smack_inode_cache, issp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* smack_inode_free_security - free an inode blob using call_rcu()
|
||||||
* @inode: the inode with a blob
|
* @inode: the inode with a blob
|
||||||
*
|
*
|
||||||
* Clears the blob pointer in inode
|
* Clears the blob pointer in inode using RCU
|
||||||
*/
|
*/
|
||||||
static void smack_inode_free_security(struct inode *inode)
|
static void smack_inode_free_security(struct inode *inode)
|
||||||
{
|
{
|
||||||
kmem_cache_free(smack_inode_cache, inode->i_security);
|
struct inode_smack *issp = inode->i_security;
|
||||||
inode->i_security = NULL;
|
|
||||||
|
/*
|
||||||
|
* The inode may still be referenced in a path walk and
|
||||||
|
* a call to smack_inode_permission() can be made
|
||||||
|
* after smack_inode_free_security() is called.
|
||||||
|
* To avoid race condition free the i_security via RCU
|
||||||
|
* and leave the current inode->i_security pointer intact.
|
||||||
|
* The inode will be freed after the RCU grace period too.
|
||||||
|
*/
|
||||||
|
call_rcu(&issp->smk_rcu, smack_inode_free_rcu);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1626,6 +1647,9 @@ static int smack_file_ioctl(struct file *file, unsigned int cmd,
|
||||||
struct smk_audit_info ad;
|
struct smk_audit_info ad;
|
||||||
struct inode *inode = file_inode(file);
|
struct inode *inode = file_inode(file);
|
||||||
|
|
||||||
|
if (unlikely(IS_PRIVATE(inode)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
|
||||||
smk_ad_setfield_u_fs_path(&ad, file->f_path);
|
smk_ad_setfield_u_fs_path(&ad, file->f_path);
|
||||||
|
|
||||||
|
@ -1655,6 +1679,9 @@ static int smack_file_lock(struct file *file, unsigned int cmd)
|
||||||
int rc;
|
int rc;
|
||||||
struct inode *inode = file_inode(file);
|
struct inode *inode = file_inode(file);
|
||||||
|
|
||||||
|
if (unlikely(IS_PRIVATE(inode)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
|
||||||
smk_ad_setfield_u_fs_path(&ad, file->f_path);
|
smk_ad_setfield_u_fs_path(&ad, file->f_path);
|
||||||
rc = smk_curacc(smk_of_inode(inode), MAY_LOCK, &ad);
|
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,
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct inode *inode = file_inode(file);
|
struct inode *inode = file_inode(file);
|
||||||
|
|
||||||
|
if (unlikely(IS_PRIVATE(inode)))
|
||||||
|
return 0;
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case F_GETLK:
|
case F_GETLK:
|
||||||
break;
|
break;
|
||||||
|
@ -1734,6 +1764,9 @@ static int smack_mmap_file(struct file *file,
|
||||||
if (file == NULL)
|
if (file == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (unlikely(IS_PRIVATE(file_inode(file))))
|
||||||
|
return 0;
|
||||||
|
|
||||||
isp = file_inode(file)->i_security;
|
isp = file_inode(file)->i_security;
|
||||||
if (isp->smk_mmap == NULL)
|
if (isp->smk_mmap == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1934,12 +1967,9 @@ static int smack_file_open(struct file *file, const struct cred *cred)
|
||||||
struct smk_audit_info ad;
|
struct smk_audit_info ad;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if (smack_privileged(CAP_MAC_OVERRIDE))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
|
smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH);
|
||||||
smk_ad_setfield_u_fs_path(&ad, file->f_path);
|
smk_ad_setfield_u_fs_path(&ad, file->f_path);
|
||||||
rc = smk_access(tsp->smk_task, smk_of_inode(inode), MAY_READ, &ad);
|
rc = smk_tskacc(tsp, smk_of_inode(inode), MAY_READ, &ad);
|
||||||
rc = smk_bu_credfile(cred, file, MAY_READ, rc);
|
rc = smk_bu_credfile(cred, file, MAY_READ, rc);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
@ -2353,6 +2383,20 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags)
|
||||||
*/
|
*/
|
||||||
static void smack_sk_free_security(struct sock *sk)
|
static void smack_sk_free_security(struct sock *sk)
|
||||||
{
|
{
|
||||||
|
#ifdef SMACK_IPV6_PORT_LABELING
|
||||||
|
struct smk_port_label *spp;
|
||||||
|
|
||||||
|
if (sk->sk_family == PF_INET6) {
|
||||||
|
rcu_read_lock();
|
||||||
|
list_for_each_entry_rcu(spp, &smk_ipv6_port_list, list) {
|
||||||
|
if (spp->smk_sock != sk)
|
||||||
|
continue;
|
||||||
|
spp->smk_can_reuse = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
kfree(sk->sk_security);
|
kfree(sk->sk_security);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2603,17 +2647,20 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
|
||||||
* on the bound socket. Take the changes to the port
|
* on the bound socket. Take the changes to the port
|
||||||
* as well.
|
* as well.
|
||||||
*/
|
*/
|
||||||
list_for_each_entry(spp, &smk_ipv6_port_list, list) {
|
rcu_read_lock();
|
||||||
|
list_for_each_entry_rcu(spp, &smk_ipv6_port_list, list) {
|
||||||
if (sk != spp->smk_sock)
|
if (sk != spp->smk_sock)
|
||||||
continue;
|
continue;
|
||||||
spp->smk_in = ssp->smk_in;
|
spp->smk_in = ssp->smk_in;
|
||||||
spp->smk_out = ssp->smk_out;
|
spp->smk_out = ssp->smk_out;
|
||||||
|
rcu_read_unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* A NULL address is only used for updating existing
|
* A NULL address is only used for updating existing
|
||||||
* bound entries. If there isn't one, it's OK.
|
* bound entries. If there isn't one, it's OK.
|
||||||
*/
|
*/
|
||||||
|
rcu_read_unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2629,16 +2676,23 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
|
||||||
* Look for an existing port list entry.
|
* Look for an existing port list entry.
|
||||||
* This is an indication that a port is getting reused.
|
* This is an indication that a port is getting reused.
|
||||||
*/
|
*/
|
||||||
list_for_each_entry(spp, &smk_ipv6_port_list, list) {
|
rcu_read_lock();
|
||||||
if (spp->smk_port != port)
|
list_for_each_entry_rcu(spp, &smk_ipv6_port_list, list) {
|
||||||
|
if (spp->smk_port != port || spp->smk_sock_type != sock->type)
|
||||||
continue;
|
continue;
|
||||||
|
if (spp->smk_can_reuse != 1) {
|
||||||
|
rcu_read_unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
spp->smk_port = port;
|
spp->smk_port = port;
|
||||||
spp->smk_sock = sk;
|
spp->smk_sock = sk;
|
||||||
spp->smk_in = ssp->smk_in;
|
spp->smk_in = ssp->smk_in;
|
||||||
spp->smk_out = ssp->smk_out;
|
spp->smk_out = ssp->smk_out;
|
||||||
|
spp->smk_can_reuse = 0;
|
||||||
|
rcu_read_unlock();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
/*
|
/*
|
||||||
* A new port entry is required.
|
* A new port entry is required.
|
||||||
*/
|
*/
|
||||||
|
@ -2650,8 +2704,12 @@ static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address)
|
||||||
spp->smk_sock = sk;
|
spp->smk_sock = sk;
|
||||||
spp->smk_in = ssp->smk_in;
|
spp->smk_in = ssp->smk_in;
|
||||||
spp->smk_out = ssp->smk_out;
|
spp->smk_out = ssp->smk_out;
|
||||||
|
spp->smk_sock_type = sock->type;
|
||||||
|
spp->smk_can_reuse = 0;
|
||||||
|
|
||||||
list_add(&spp->list, &smk_ipv6_port_list);
|
mutex_lock(&smack_ipv6_lock);
|
||||||
|
list_add_rcu(&spp->list, &smk_ipv6_port_list);
|
||||||
|
mutex_unlock(&smack_ipv6_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2702,14 +2760,16 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address,
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
port = ntohs(address->sin6_port);
|
port = ntohs(address->sin6_port);
|
||||||
list_for_each_entry(spp, &smk_ipv6_port_list, list) {
|
rcu_read_lock();
|
||||||
if (spp->smk_port != port)
|
list_for_each_entry_rcu(spp, &smk_ipv6_port_list, list) {
|
||||||
|
if (spp->smk_port != port || spp->smk_sock_type != sk->sk_type)
|
||||||
continue;
|
continue;
|
||||||
object = spp->smk_in;
|
object = spp->smk_in;
|
||||||
if (act == SMK_CONNECTING)
|
if (act == SMK_CONNECTING)
|
||||||
ssp->smk_packet = spp->smk_out;
|
ssp->smk_packet = spp->smk_out;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
|
|
||||||
return smk_ipv6_check(skp, object, address, act);
|
return smk_ipv6_check(skp, object, address, act);
|
||||||
}
|
}
|
||||||
|
@ -3438,6 +3498,13 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
|
||||||
case PIPEFS_MAGIC:
|
case PIPEFS_MAGIC:
|
||||||
isp->smk_inode = smk_of_current();
|
isp->smk_inode = smk_of_current();
|
||||||
break;
|
break;
|
||||||
|
case SOCKFS_MAGIC:
|
||||||
|
/*
|
||||||
|
* Socket access is controlled by the socket
|
||||||
|
* structures associated with the task involved.
|
||||||
|
*/
|
||||||
|
isp->smk_inode = &smack_known_star;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
isp->smk_inode = sbsp->smk_root;
|
isp->smk_inode = sbsp->smk_root;
|
||||||
break;
|
break;
|
||||||
|
@ -3454,19 +3521,12 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
|
||||||
*/
|
*/
|
||||||
switch (sbp->s_magic) {
|
switch (sbp->s_magic) {
|
||||||
case SMACK_MAGIC:
|
case SMACK_MAGIC:
|
||||||
case PIPEFS_MAGIC:
|
|
||||||
case SOCKFS_MAGIC:
|
|
||||||
case CGROUP_SUPER_MAGIC:
|
case CGROUP_SUPER_MAGIC:
|
||||||
/*
|
/*
|
||||||
* Casey says that it's a little embarrassing
|
* Casey says that it's a little embarrassing
|
||||||
* that the smack file system doesn't do
|
* that the smack file system doesn't do
|
||||||
* extended attributes.
|
* extended attributes.
|
||||||
*
|
*
|
||||||
* Casey says pipes are easy (?)
|
|
||||||
*
|
|
||||||
* Socket access is controlled by the socket
|
|
||||||
* structures associated with the task involved.
|
|
||||||
*
|
|
||||||
* Cgroupfs is special
|
* Cgroupfs is special
|
||||||
*/
|
*/
|
||||||
final = &smack_known_star;
|
final = &smack_known_star;
|
||||||
|
@ -3849,7 +3909,7 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap,
|
||||||
* ambient value.
|
* ambient value.
|
||||||
*/
|
*/
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
list_for_each_entry(skp, &smack_known_list, list) {
|
list_for_each_entry_rcu(skp, &smack_known_list, list) {
|
||||||
if (sap->attr.mls.lvl != skp->smk_netlabel.attr.mls.lvl)
|
if (sap->attr.mls.lvl != skp->smk_netlabel.attr.mls.lvl)
|
||||||
continue;
|
continue;
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -67,6 +67,7 @@ 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);
|
||||||
|
@ -262,12 +263,16 @@ static int smk_set_access(struct smack_parsed_rule *srp,
|
||||||
* it needs to get added for reporting.
|
* it needs to get added for reporting.
|
||||||
*/
|
*/
|
||||||
if (global) {
|
if (global) {
|
||||||
|
mutex_unlock(rule_lock);
|
||||||
smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
|
smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
|
||||||
if (smlp != NULL) {
|
if (smlp != NULL) {
|
||||||
smlp->smk_rule = sp;
|
smlp->smk_rule = sp;
|
||||||
|
mutex_lock(&smack_master_list_lock);
|
||||||
list_add_rcu(&smlp->list, &smack_rule_list);
|
list_add_rcu(&smlp->list, &smack_rule_list);
|
||||||
|
mutex_unlock(&smack_master_list_lock);
|
||||||
} else
|
} else
|
||||||
rc = -ENOMEM;
|
rc = -ENOMEM;
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user