summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--security/selinux/avc.c10
-rw-r--r--security/selinux/hooks.c9
-rw-r--r--security/selinux/include/avc.h6
-rw-r--r--security/selinux/ss/services.c49
4 files changed, 45 insertions, 29 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index e4396a89edc6..cc5fcef9e226 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -832,6 +832,7 @@ int avc_ss_reset(u32 seqno)
* @tsid: target security identifier
* @tclass: target security class
* @requested: requested permissions, interpreted based on @tclass
+ * @flags: AVC_STRICT or 0
* @avd: access vector decisions
*
* Check the AVC to determine whether the @requested permissions are granted
@@ -846,8 +847,9 @@ int avc_ss_reset(u32 seqno)
* should be released for the auditing.
*/
int avc_has_perm_noaudit(u32 ssid, u32 tsid,
- u16 tclass, u32 requested,
- struct av_decision *avd)
+ u16 tclass, u32 requested,
+ unsigned flags,
+ struct av_decision *avd)
{
struct avc_node *node;
struct avc_entry entry, *p_ae;
@@ -874,7 +876,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
denied = requested & ~(p_ae->avd.allowed);
if (!requested || denied) {
- if (selinux_enforcing)
+ if (selinux_enforcing || (flags & AVC_STRICT))
rc = -EACCES;
else
if (node)
@@ -909,7 +911,7 @@ int avc_has_perm(u32 ssid, u32 tsid, u16 tclass,
struct av_decision avd;
int rc;
- rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, &avd);
+ rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd);
avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata);
return rc;
}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index ad8dd4e8657e..b29059ecc045 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -1592,9 +1592,10 @@ static int selinux_vm_enough_memory(long pages)
rc = secondary_ops->capable(current, CAP_SYS_ADMIN);
if (rc == 0)
rc = avc_has_perm_noaudit(tsec->sid, tsec->sid,
- SECCLASS_CAPABILITY,
- CAP_TO_MASK(CAP_SYS_ADMIN),
- NULL);
+ SECCLASS_CAPABILITY,
+ CAP_TO_MASK(CAP_SYS_ADMIN),
+ 0,
+ NULL);
if (rc == 0)
cap_sys_admin = 1;
@@ -4626,7 +4627,7 @@ static int selinux_setprocattr(struct task_struct *p,
if (p->ptrace & PT_PTRACED) {
error = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
SECCLASS_PROCESS,
- PROCESS__PTRACE, &avd);
+ PROCESS__PTRACE, 0, &avd);
if (!error)
tsec->sid = sid;
task_unlock(p);
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index 6ed10c3d3339..e145f6e13b0b 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -102,9 +102,11 @@ void avc_audit(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
struct av_decision *avd, int result, struct avc_audit_data *auditdata);
+#define AVC_STRICT 1 /* Ignore permissive mode. */
int avc_has_perm_noaudit(u32 ssid, u32 tsid,
- u16 tclass, u32 requested,
- struct av_decision *avd);
+ u16 tclass, u32 requested,
+ unsigned flags,
+ struct av_decision *avd);
int avc_has_perm(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index e4249adaa880..b5f017f07a75 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1587,19 +1587,18 @@ int security_get_user_sids(u32 fromsid,
u32 *nel)
{
struct context *fromcon, usercon;
- u32 *mysids, *mysids2, sid;
+ u32 *mysids = NULL, *mysids2, sid;
u32 mynel = 0, maxnel = SIDS_NEL;
struct user_datum *user;
struct role_datum *role;
- struct av_decision avd;
struct ebitmap_node *rnode, *tnode;
int rc = 0, i, j;
- if (!ss_initialized) {
- *sids = NULL;
- *nel = 0;
+ *sids = NULL;
+ *nel = 0;
+
+ if (!ss_initialized)
goto out;
- }
POLICY_RDLOCK;
@@ -1635,17 +1634,9 @@ int security_get_user_sids(u32 fromsid,
if (mls_setup_user_range(fromcon, user, &usercon))
continue;
- rc = context_struct_compute_av(fromcon, &usercon,
- SECCLASS_PROCESS,
- PROCESS__TRANSITION,
- &avd);
- if (rc || !(avd.allowed & PROCESS__TRANSITION))
- continue;
rc = sidtab_context_to_sid(&sidtab, &usercon, &sid);
- if (rc) {
- kfree(mysids);
+ if (rc)
goto out_unlock;
- }
if (mynel < maxnel) {
mysids[mynel++] = sid;
} else {
@@ -1653,7 +1644,6 @@ int security_get_user_sids(u32 fromsid,
mysids2 = kcalloc(maxnel, sizeof(*mysids2), GFP_ATOMIC);
if (!mysids2) {
rc = -ENOMEM;
- kfree(mysids);
goto out_unlock;
}
memcpy(mysids2, mysids, mynel * sizeof(*mysids2));
@@ -1664,11 +1654,32 @@ int security_get_user_sids(u32 fromsid,
}
}
- *sids = mysids;
- *nel = mynel;
-
out_unlock:
POLICY_RDUNLOCK;
+ if (rc || !mynel) {
+ kfree(mysids);
+ goto out;
+ }
+
+ mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL);
+ if (!mysids2) {
+ rc = -ENOMEM;
+ kfree(mysids);
+ goto out;
+ }
+ for (i = 0, j = 0; i < mynel; i++) {
+ rc = avc_has_perm_noaudit(fromsid, mysids[i],
+ SECCLASS_PROCESS,
+ PROCESS__TRANSITION, AVC_STRICT,
+ NULL);
+ if (!rc)
+ mysids2[j++] = mysids[i];
+ cond_resched();
+ }
+ rc = 0;
+ kfree(mysids);
+ *sids = mysids2;
+ *nel = j;
out:
return rc;
}