summaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorOndrej Mosnacek <omosnace@redhat.com>2019-01-25 05:06:51 -0500
committerPaul Moore <paul@paul-moore.com>2019-01-25 17:31:14 -0500
commitfede148324c34360ce8c30a9a5bdfac5574b2a59 (patch)
tree6908514ddcc623ad8776f9f58897ee1d07c8f8f1 /security
parent994fb0651d02e49567e7550eb574981b387fc06f (diff)
selinux: log invalid contexts in AVCs
In case a file has an invalid context set, in an AVC record generated upon access to such file, the target context is always reported as unlabeled. This patch adds new optional fields to the AVC record (srawcon and trawcon) that report the actual context string if it differs from the one reported in scontext/tcontext. This is useful for diagnosing SELinux denials involving invalid contexts. To trigger an AVC that illustrates this situation: # setenforce 0 # touch /tmp/testfile # setfattr -n security.selinux -v system_u:object_r:banana_t:s0 /tmp/testfile # runcon system_u:system_r:sshd_t:s0 cat /tmp/testfile AVC before: type=AVC msg=audit(1547801083.248:11): avc: denied { open } for pid=1149 comm="cat" path="/tmp/testfile" dev="tmpfs" ino=6608 scontext=system_u:system_r:sshd_t:s0 tcontext=system_u:object_r:unlabeled_t:s15:c0.c1023 tclass=file permissive=1 AVC after: type=AVC msg=audit(1547801083.248:11): avc: denied { open } for pid=1149 comm="cat" path="/tmp/testfile" dev="tmpfs" ino=6608 scontext=system_u:system_r:sshd_t:s0 tcontext=system_u:object_r:unlabeled_t:s15:c0.c1023 tclass=file permissive=1 trawcon=system_u:object_r:banana_t:s0 Note that it is also possible to encounter this situation with the 'scontext' field - e.g. when a new policy is loaded while a process is running, whose context is not valid in the new policy. Link: https://bugzilla.redhat.com/show_bug.cgi?id=1135683 Cc: Daniel Walsh <dwalsh@redhat.com> Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com> Reviewed-by: Stephen Smalley <sds@tycho.nsa.gov> Signed-off-by: Paul Moore <paul@paul-moore.com>
Diffstat (limited to 'security')
-rw-r--r--security/selinux/avc.c15
-rw-r--r--security/selinux/include/security.h3
-rw-r--r--security/selinux/ss/services.c37
3 files changed, 50 insertions, 5 deletions
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 5ebad47391c9..3a27418b20d7 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -734,6 +734,21 @@ static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
734 734
735 if (sad->denied) 735 if (sad->denied)
736 audit_log_format(ab, " permissive=%u", sad->result ? 0 : 1); 736 audit_log_format(ab, " permissive=%u", sad->result ? 0 : 1);
737
738 /* in case of invalid context report also the actual context string */
739 rc = security_sid_to_context_inval(sad->state, sad->ssid, &scontext,
740 &scontext_len);
741 if (!rc && scontext) {
742 audit_log_format(ab, " srawcon=%s", scontext);
743 kfree(scontext);
744 }
745
746 rc = security_sid_to_context_inval(sad->state, sad->tsid, &scontext,
747 &scontext_len);
748 if (!rc && scontext) {
749 audit_log_format(ab, " trawcon=%s", scontext);
750 kfree(scontext);
751 }
737} 752}
738 753
739/* This is the slow part of avc audit with big stack footprint */ 754/* This is the slow part of avc audit with big stack footprint */
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index ba8eedf42b90..f68fb25b5702 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -255,6 +255,9 @@ int security_sid_to_context(struct selinux_state *state, u32 sid,
255int security_sid_to_context_force(struct selinux_state *state, 255int security_sid_to_context_force(struct selinux_state *state,
256 u32 sid, char **scontext, u32 *scontext_len); 256 u32 sid, char **scontext, u32 *scontext_len);
257 257
258int security_sid_to_context_inval(struct selinux_state *state,
259 u32 sid, char **scontext, u32 *scontext_len);
260
258int security_context_to_sid(struct selinux_state *state, 261int security_context_to_sid(struct selinux_state *state,
259 const char *scontext, u32 scontext_len, 262 const char *scontext, u32 scontext_len,
260 u32 *out_sid, gfp_t gfp); 263 u32 *out_sid, gfp_t gfp);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index dd44126c8d14..9be05c3e99dc 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1281,7 +1281,8 @@ const char *security_get_initial_sid_context(u32 sid)
1281 1281
1282static int security_sid_to_context_core(struct selinux_state *state, 1282static int security_sid_to_context_core(struct selinux_state *state,
1283 u32 sid, char **scontext, 1283 u32 sid, char **scontext,
1284 u32 *scontext_len, int force) 1284 u32 *scontext_len, int force,
1285 int only_invalid)
1285{ 1286{
1286 struct policydb *policydb; 1287 struct policydb *policydb;
1287 struct sidtab *sidtab; 1288 struct sidtab *sidtab;
@@ -1326,8 +1327,14 @@ static int security_sid_to_context_core(struct selinux_state *state,
1326 rc = -EINVAL; 1327 rc = -EINVAL;
1327 goto out_unlock; 1328 goto out_unlock;
1328 } 1329 }
1329 rc = context_struct_to_string(policydb, context, scontext, 1330 if (only_invalid && !context->len) {
1330 scontext_len); 1331 scontext = NULL;
1332 scontext_len = 0;
1333 rc = 0;
1334 } else {
1335 rc = context_struct_to_string(policydb, context, scontext,
1336 scontext_len);
1337 }
1331out_unlock: 1338out_unlock:
1332 read_unlock(&state->ss->policy_rwlock); 1339 read_unlock(&state->ss->policy_rwlock);
1333out: 1340out:
@@ -1349,14 +1356,34 @@ int security_sid_to_context(struct selinux_state *state,
1349 u32 sid, char **scontext, u32 *scontext_len) 1356 u32 sid, char **scontext, u32 *scontext_len)
1350{ 1357{
1351 return security_sid_to_context_core(state, sid, scontext, 1358 return security_sid_to_context_core(state, sid, scontext,
1352 scontext_len, 0); 1359 scontext_len, 0, 0);
1353} 1360}
1354 1361
1355int security_sid_to_context_force(struct selinux_state *state, u32 sid, 1362int security_sid_to_context_force(struct selinux_state *state, u32 sid,
1356 char **scontext, u32 *scontext_len) 1363 char **scontext, u32 *scontext_len)
1357{ 1364{
1358 return security_sid_to_context_core(state, sid, scontext, 1365 return security_sid_to_context_core(state, sid, scontext,
1359 scontext_len, 1); 1366 scontext_len, 1, 0);
1367}
1368
1369/**
1370 * security_sid_to_context_inval - Obtain a context for a given SID if it
1371 * is invalid.
1372 * @sid: security identifier, SID
1373 * @scontext: security context
1374 * @scontext_len: length in bytes
1375 *
1376 * Write the string representation of the context associated with @sid
1377 * into a dynamically allocated string of the correct size, but only if the
1378 * context is invalid in the current policy. Set @scontext to point to
1379 * this string (or NULL if the context is valid) and set @scontext_len to
1380 * the length of the string (or 0 if the context is valid).
1381 */
1382int security_sid_to_context_inval(struct selinux_state *state, u32 sid,
1383 char **scontext, u32 *scontext_len)
1384{
1385 return security_sid_to_context_core(state, sid, scontext,
1386 scontext_len, 1, 1);
1360} 1387}
1361 1388
1362/* 1389/*