forked from luck/tmp_suning_uos_patched
selinux: always return a secid from the network caches if we find one
Previously if we couldn't find an entry in the cache and we failed to allocate memory for a new cache entry we would fail the network object label lookup; this is obviously not ideal. This patch fixes this so that we return the object label even if we can't cache the object at this point in time due to memory pressure. The GitHub issue tracker is below: * https://github.com/SELinuxProject/selinux-kernel/issues/3 Signed-off-by: Paul Moore <paul@paul-moore.com>
This commit is contained in:
parent
f07ea1d4ed
commit
9b80c36353
|
@ -135,9 +135,9 @@ static void sel_netif_destroy(struct sel_netif *netif)
|
||||||
*/
|
*/
|
||||||
static int sel_netif_sid_slow(struct net *ns, int ifindex, u32 *sid)
|
static int sel_netif_sid_slow(struct net *ns, int ifindex, u32 *sid)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret = 0;
|
||||||
struct sel_netif *netif;
|
struct sel_netif *netif;
|
||||||
struct sel_netif *new = NULL;
|
struct sel_netif *new;
|
||||||
struct net_device *dev;
|
struct net_device *dev;
|
||||||
|
|
||||||
/* NOTE: we always use init's network namespace since we don't
|
/* NOTE: we always use init's network namespace since we don't
|
||||||
|
@ -154,32 +154,27 @@ static int sel_netif_sid_slow(struct net *ns, int ifindex, u32 *sid)
|
||||||
netif = sel_netif_find(ns, ifindex);
|
netif = sel_netif_find(ns, ifindex);
|
||||||
if (netif != NULL) {
|
if (netif != NULL) {
|
||||||
*sid = netif->nsec.sid;
|
*sid = netif->nsec.sid;
|
||||||
ret = 0;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = security_netif_sid(&selinux_state, dev->name, sid);
|
||||||
|
if (ret != 0)
|
||||||
|
goto out;
|
||||||
new = kzalloc(sizeof(*new), GFP_ATOMIC);
|
new = kzalloc(sizeof(*new), GFP_ATOMIC);
|
||||||
if (new == NULL) {
|
if (new) {
|
||||||
ret = -ENOMEM;
|
new->nsec.ns = ns;
|
||||||
goto out;
|
new->nsec.ifindex = ifindex;
|
||||||
|
new->nsec.sid = *sid;
|
||||||
|
if (sel_netif_insert(new))
|
||||||
|
kfree(new);
|
||||||
}
|
}
|
||||||
ret = security_netif_sid(&selinux_state, dev->name, &new->nsec.sid);
|
|
||||||
if (ret != 0)
|
|
||||||
goto out;
|
|
||||||
new->nsec.ns = ns;
|
|
||||||
new->nsec.ifindex = ifindex;
|
|
||||||
ret = sel_netif_insert(new);
|
|
||||||
if (ret != 0)
|
|
||||||
goto out;
|
|
||||||
*sid = new->nsec.sid;
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
spin_unlock_bh(&sel_netif_lock);
|
spin_unlock_bh(&sel_netif_lock);
|
||||||
dev_put(dev);
|
dev_put(dev);
|
||||||
if (unlikely(ret)) {
|
if (unlikely(ret))
|
||||||
pr_warn("SELinux: failure in %s(), unable to determine network interface label (%d)\n",
|
pr_warn("SELinux: failure in %s(), unable to determine network interface label (%d)\n",
|
||||||
__func__, ifindex);
|
__func__, ifindex);
|
||||||
kfree(new);
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -199,9 +199,9 @@ static void sel_netnode_insert(struct sel_netnode *node)
|
||||||
*/
|
*/
|
||||||
static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid)
|
static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid)
|
||||||
{
|
{
|
||||||
int ret = -ENOMEM;
|
int ret;
|
||||||
struct sel_netnode *node;
|
struct sel_netnode *node;
|
||||||
struct sel_netnode *new = NULL;
|
struct sel_netnode *new;
|
||||||
|
|
||||||
spin_lock_bh(&sel_netnode_lock);
|
spin_lock_bh(&sel_netnode_lock);
|
||||||
node = sel_netnode_find(addr, family);
|
node = sel_netnode_find(addr, family);
|
||||||
|
@ -210,38 +210,36 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid)
|
||||||
spin_unlock_bh(&sel_netnode_lock);
|
spin_unlock_bh(&sel_netnode_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
new = kzalloc(sizeof(*new), GFP_ATOMIC);
|
new = kzalloc(sizeof(*new), GFP_ATOMIC);
|
||||||
if (new == NULL)
|
|
||||||
goto out;
|
|
||||||
switch (family) {
|
switch (family) {
|
||||||
case PF_INET:
|
case PF_INET:
|
||||||
ret = security_node_sid(&selinux_state, PF_INET,
|
ret = security_node_sid(&selinux_state, PF_INET,
|
||||||
addr, sizeof(struct in_addr), sid);
|
addr, sizeof(struct in_addr), sid);
|
||||||
new->nsec.addr.ipv4 = *(__be32 *)addr;
|
if (new)
|
||||||
|
new->nsec.addr.ipv4 = *(__be32 *)addr;
|
||||||
break;
|
break;
|
||||||
case PF_INET6:
|
case PF_INET6:
|
||||||
ret = security_node_sid(&selinux_state, PF_INET6,
|
ret = security_node_sid(&selinux_state, PF_INET6,
|
||||||
addr, sizeof(struct in6_addr), sid);
|
addr, sizeof(struct in6_addr), sid);
|
||||||
new->nsec.addr.ipv6 = *(struct in6_addr *)addr;
|
if (new)
|
||||||
|
new->nsec.addr.ipv6 = *(struct in6_addr *)addr;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
BUG();
|
BUG();
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
}
|
}
|
||||||
if (ret != 0)
|
if (ret == 0 && new) {
|
||||||
goto out;
|
new->nsec.family = family;
|
||||||
|
new->nsec.sid = *sid;
|
||||||
|
sel_netnode_insert(new);
|
||||||
|
} else
|
||||||
|
kfree(new);
|
||||||
|
|
||||||
new->nsec.family = family;
|
|
||||||
new->nsec.sid = *sid;
|
|
||||||
sel_netnode_insert(new);
|
|
||||||
|
|
||||||
out:
|
|
||||||
spin_unlock_bh(&sel_netnode_lock);
|
spin_unlock_bh(&sel_netnode_lock);
|
||||||
if (unlikely(ret)) {
|
if (unlikely(ret))
|
||||||
pr_warn("SELinux: failure in %s(), unable to determine network node label\n",
|
pr_warn("SELinux: failure in %s(), unable to determine network node label\n",
|
||||||
__func__);
|
__func__);
|
||||||
kfree(new);
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -147,9 +147,9 @@ static void sel_netport_insert(struct sel_netport *port)
|
||||||
*/
|
*/
|
||||||
static int sel_netport_sid_slow(u8 protocol, u16 pnum, u32 *sid)
|
static int sel_netport_sid_slow(u8 protocol, u16 pnum, u32 *sid)
|
||||||
{
|
{
|
||||||
int ret = -ENOMEM;
|
int ret;
|
||||||
struct sel_netport *port;
|
struct sel_netport *port;
|
||||||
struct sel_netport *new = NULL;
|
struct sel_netport *new;
|
||||||
|
|
||||||
spin_lock_bh(&sel_netport_lock);
|
spin_lock_bh(&sel_netport_lock);
|
||||||
port = sel_netport_find(protocol, pnum);
|
port = sel_netport_find(protocol, pnum);
|
||||||
|
@ -158,25 +158,23 @@ static int sel_netport_sid_slow(u8 protocol, u16 pnum, u32 *sid)
|
||||||
spin_unlock_bh(&sel_netport_lock);
|
spin_unlock_bh(&sel_netport_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
new = kzalloc(sizeof(*new), GFP_ATOMIC);
|
|
||||||
if (new == NULL)
|
|
||||||
goto out;
|
|
||||||
ret = security_port_sid(&selinux_state, protocol, pnum, sid);
|
ret = security_port_sid(&selinux_state, protocol, pnum, sid);
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
goto out;
|
goto out;
|
||||||
|
new = kzalloc(sizeof(*new), GFP_ATOMIC);
|
||||||
new->psec.port = pnum;
|
if (new) {
|
||||||
new->psec.protocol = protocol;
|
new->psec.port = pnum;
|
||||||
new->psec.sid = *sid;
|
new->psec.protocol = protocol;
|
||||||
sel_netport_insert(new);
|
new->psec.sid = *sid;
|
||||||
|
sel_netport_insert(new);
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
spin_unlock_bh(&sel_netport_lock);
|
spin_unlock_bh(&sel_netport_lock);
|
||||||
if (unlikely(ret)) {
|
if (unlikely(ret))
|
||||||
pr_warn("SELinux: failure in %s(), unable to determine network port label\n",
|
pr_warn("SELinux: failure in %s(), unable to determine network port label\n",
|
||||||
__func__);
|
__func__);
|
||||||
kfree(new);
|
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user