summaryrefslogtreecommitdiff
path: root/security/selinux/ss/services.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/selinux/ss/services.c')
-rw-r--r--security/selinux/ss/services.c83
1 files changed, 55 insertions, 28 deletions
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index d9f58b5d0f49..d185754c2786 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -46,6 +46,7 @@
#include <linux/in.h>
#include <linux/sched.h>
#include <linux/audit.h>
+#include <linux/parser.h>
#include <linux/vmalloc.h>
#include <linux/lsm_hooks.h>
#include <net/netlabel.h>
@@ -952,7 +953,7 @@ static void avd_init(struct selinux_policy *policy, struct av_decision *avd)
}
static void update_xperms_extended_data(u8 specified,
- struct extended_perms_data *from,
+ const struct extended_perms_data *from,
struct extended_perms_data *xp_data)
{
unsigned int i;
@@ -973,6 +974,8 @@ static void update_xperms_extended_data(u8 specified,
void services_compute_xperms_decision(struct extended_perms_decision *xpermd,
struct avtab_node *node)
{
+ u16 specified;
+
switch (node->datum.u.xperms->specified) {
case AVTAB_XPERMS_IOCTLFUNCTION:
if (xpermd->base_perm != AVC_EXT_IOCTL ||
@@ -997,17 +1000,19 @@ void services_compute_xperms_decision(struct extended_perms_decision *xpermd,
return;
}
- if (node->key.specified == AVTAB_XPERMS_ALLOWED) {
+ specified = node->key.specified & ~(AVTAB_ENABLED | AVTAB_ENABLED_OLD);
+
+ if (specified == AVTAB_XPERMS_ALLOWED) {
xpermd->used |= XPERMS_ALLOWED;
update_xperms_extended_data(node->datum.u.xperms->specified,
&node->datum.u.xperms->perms,
xpermd->allowed);
- } else if (node->key.specified == AVTAB_XPERMS_AUDITALLOW) {
+ } else if (specified == AVTAB_XPERMS_AUDITALLOW) {
xpermd->used |= XPERMS_AUDITALLOW;
update_xperms_extended_data(node->datum.u.xperms->specified,
&node->datum.u.xperms->perms,
xpermd->auditallow);
- } else if (node->key.specified == AVTAB_XPERMS_DONTAUDIT) {
+ } else if (specified == AVTAB_XPERMS_DONTAUDIT) {
xpermd->used |= XPERMS_DONTAUDIT;
update_xperms_extended_data(node->datum.u.xperms->specified,
&node->datum.u.xperms->perms,
@@ -1904,11 +1909,17 @@ retry:
goto out_unlock;
}
/* Obtain the sid for the context. */
- rc = sidtab_context_to_sid(sidtab, &newcontext, out_sid);
- if (rc == -ESTALE) {
- rcu_read_unlock();
- context_destroy(&newcontext);
- goto retry;
+ if (context_equal(scontext, &newcontext))
+ *out_sid = ssid;
+ else if (context_equal(tcontext, &newcontext))
+ *out_sid = tsid;
+ else {
+ rc = sidtab_context_to_sid(sidtab, &newcontext, out_sid);
+ if (rc == -ESTALE) {
+ rcu_read_unlock();
+ context_destroy(&newcontext);
+ goto retry;
+ }
}
out_unlock:
rcu_read_unlock();
@@ -2568,13 +2579,14 @@ out:
* @name: interface name
* @if_sid: interface SID
*/
-int security_netif_sid(char *name, u32 *if_sid)
+int security_netif_sid(const char *name, u32 *if_sid)
{
struct selinux_policy *policy;
struct policydb *policydb;
struct sidtab *sidtab;
int rc;
struct ocontext *c;
+ bool wildcard_support;
if (!selinux_initialized()) {
*if_sid = SECINITSID_NETIF;
@@ -2587,11 +2599,18 @@ retry:
policy = rcu_dereference(selinux_state.policy);
policydb = &policy->policydb;
sidtab = policy->sidtab;
+ wildcard_support = ebitmap_get_bit(&policydb->policycaps, POLICYDB_CAP_NETIF_WILDCARD);
c = policydb->ocontexts[OCON_NETIF];
while (c) {
- if (strcmp(name, c->u.name) == 0)
- break;
+ if (wildcard_support) {
+ if (match_wildcard(c->u.name, name))
+ break;
+ } else {
+ if (strcmp(c->u.name, name) == 0)
+ break;
+ }
+
c = c->next;
}
@@ -2611,17 +2630,15 @@ out:
return rc;
}
-static int match_ipv6_addrmask(u32 *input, u32 *addr, u32 *mask)
+static bool match_ipv6_addrmask(const u32 input[4], const u32 addr[4], const u32 mask[4])
{
- int i, fail = 0;
+ int i;
for (i = 0; i < 4; i++)
- if (addr[i] != (input[i] & mask[i])) {
- fail = 1;
- break;
- }
+ if (addr[i] != (input[i] & mask[i]))
+ return false;
- return !fail;
+ return true;
}
/**
@@ -2632,7 +2649,7 @@ static int match_ipv6_addrmask(u32 *input, u32 *addr, u32 *mask)
* @out_sid: security identifier
*/
int security_node_sid(u16 domain,
- void *addrp,
+ const void *addrp,
u32 addrlen,
u32 *out_sid)
{
@@ -2661,7 +2678,7 @@ retry:
if (addrlen != sizeof(u32))
goto out;
- addr = *((u32 *)addrp);
+ addr = *((const u32 *)addrp);
c = policydb->ocontexts[OCON_NODE];
while (c) {
@@ -2726,7 +2743,7 @@ out:
*/
int security_get_user_sids(u32 fromsid,
- char *username,
+ const char *username,
u32 **sids,
u32 *nel)
{
@@ -2861,6 +2878,7 @@ static inline int __security_genfs_sid(struct selinux_policy *policy,
struct genfs *genfs;
struct ocontext *c;
int cmp = 0;
+ bool wildcard;
while (path[0] == '/' && path[1] == '/')
path++;
@@ -2877,11 +2895,20 @@ static inline int __security_genfs_sid(struct selinux_policy *policy,
if (!genfs || cmp)
return -ENOENT;
+ wildcard = ebitmap_get_bit(&policy->policydb.policycaps,
+ POLICYDB_CAP_GENFS_SECLABEL_WILDCARD);
for (c = genfs->head; c; c = c->next) {
- size_t len = strlen(c->u.name);
- if ((!c->v.sclass || sclass == c->v.sclass) &&
- (strncmp(c->u.name, path, len) == 0))
- break;
+ if (!c->v.sclass || sclass == c->v.sclass) {
+ if (wildcard) {
+ if (match_wildcard(c->u.name, path))
+ break;
+ } else {
+ size_t len = strlen(c->u.name);
+
+ if ((strncmp(c->u.name, path, len)) == 0)
+ break;
+ }
+ }
}
if (!c)
@@ -3048,7 +3075,7 @@ err:
}
-int security_set_bools(u32 len, int *values)
+int security_set_bools(u32 len, const int *values)
{
struct selinux_state *state = &selinux_state;
struct selinux_policy *newpolicy, *oldpolicy;
@@ -3347,7 +3374,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type,
__func__, xfrm_sid);
goto out;
}
- rc = (mls_context_cmp(nlbl_ctx, xfrm_ctx) ? 0 : -EACCES);
+ rc = (mls_context_equal(nlbl_ctx, xfrm_ctx) ? 0 : -EACCES);
if (rc)
goto out;