Skip to content

Commit

Permalink
Add audit messages on type boundary violations
Browse files Browse the repository at this point in the history
The attached patch adds support to generate audit messages on two cases.

The first one is a case when a multi-thread process tries to switch its
performing security context using setcon(3), but new security context is
not bounded by the old one.

  type=SELINUX_ERR msg=audit(1245311998.599:17):        \
      op=security_bounded_transition result=denied      \
      oldcontext=system_u:system_r:httpd_t:s0           \
      newcontext=system_u:system_r:guest_webapp_t:s0

The other one is a case when security_compute_av() masked any permissions
due to the type boundary violation.

  type=SELINUX_ERR msg=audit(1245312836.035:32):	\
      op=security_compute_av reason=bounds              \
      scontext=system_u:object_r:user_webapp_t:s0       \
      tcontext=system_u:object_r:shadow_t:s0:c0         \
      tclass=file perms=getattr,open

Signed-off-by: KaiGai Kohei <kaigai@ak.jp.nec.com>
Acked-by:  Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: James Morris <jmorris@namei.org>
  • Loading branch information
KaiGai Kohei authored and James Morris committed Jun 18, 2009
1 parent caabbdc commit 44c2d9b
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 23 deletions.
2 changes: 1 addition & 1 deletion security/selinux/avc.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
* @tclass: target security class
* @av: access vector
*/
void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
{
const char **common_pts = NULL;
u32 common_base = 0;
Expand Down
3 changes: 0 additions & 3 deletions security/selinux/include/avc.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,6 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
u32 events, u32 ssid, u32 tsid,
u16 tclass, u32 perms);

/* Shows permission in human readable form */
void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av);

/* Exported to selinuxfs */
int avc_get_hash_stats(char *page);
extern unsigned int avc_cache_threshold;
Expand Down
136 changes: 117 additions & 19 deletions security/selinux/ss/services.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@
*
* Added validation of kernel classes and permissions
*
* Updated: KaiGai Kohei <kaigai@ak.jp.nec.com>
*
* Added support for bounds domain and audit messaged on masked permissions
*
* Copyright (C) 2008, 2009 NEC Corporation
* Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
* Copyright (C) 2004-2006 Trusted Computer Solutions, Inc.
* Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC
Expand Down Expand Up @@ -278,6 +283,95 @@ static int constraint_expr_eval(struct context *scontext,
return s[0];
}

/*
* security_dump_masked_av - dumps masked permissions during
* security_compute_av due to RBAC, MLS/Constraint and Type bounds.
*/
static int dump_masked_av_helper(void *k, void *d, void *args)
{
struct perm_datum *pdatum = d;
char **permission_names = args;

BUG_ON(pdatum->value < 1 || pdatum->value > 32);

permission_names[pdatum->value - 1] = (char *)k;

return 0;
}

static void security_dump_masked_av(struct context *scontext,
struct context *tcontext,
u16 tclass,
u32 permissions,
const char *reason)
{
struct common_datum *common_dat;
struct class_datum *tclass_dat;
struct audit_buffer *ab;
char *tclass_name;
char *scontext_name = NULL;
char *tcontext_name = NULL;
char *permission_names[32];
int index, length;
bool need_comma = false;

if (!permissions)
return;

tclass_name = policydb.p_class_val_to_name[tclass - 1];
tclass_dat = policydb.class_val_to_struct[tclass - 1];
common_dat = tclass_dat->comdatum;

/* init permission_names */
if (common_dat &&
hashtab_map(common_dat->permissions.table,
dump_masked_av_helper, permission_names) < 0)
goto out;

if (hashtab_map(tclass_dat->permissions.table,
dump_masked_av_helper, permission_names) < 0)
goto out;

/* get scontext/tcontext in text form */
if (context_struct_to_string(scontext,
&scontext_name, &length) < 0)
goto out;

if (context_struct_to_string(tcontext,
&tcontext_name, &length) < 0)
goto out;

/* audit a message */
ab = audit_log_start(current->audit_context,
GFP_ATOMIC, AUDIT_SELINUX_ERR);
if (!ab)
goto out;

audit_log_format(ab, "op=security_compute_av reason=%s "
"scontext=%s tcontext=%s tclass=%s perms=",
reason, scontext_name, tcontext_name, tclass_name);

for (index = 0; index < 32; index++) {
u32 mask = (1 << index);

if ((mask & permissions) == 0)
continue;

audit_log_format(ab, "%s%s",
need_comma ? "," : "",
permission_names[index]
? permission_names[index] : "????");
need_comma = true;
}
audit_log_end(ab);
out:
/* release scontext/tcontext */
kfree(tcontext_name);
kfree(scontext_name);

return;
}

/*
* security_boundary_permission - drops violated permissions
* on boundary constraint.
Expand Down Expand Up @@ -347,28 +441,12 @@ static void type_attribute_bounds_av(struct context *scontext,
}

if (masked) {
struct audit_buffer *ab;
char *stype_name
= policydb.p_type_val_to_name[source->value - 1];
char *ttype_name
= policydb.p_type_val_to_name[target->value - 1];
char *tclass_name
= policydb.p_class_val_to_name[tclass - 1];

/* mask violated permissions */
avd->allowed &= ~masked;

/* notice to userspace via audit message */
ab = audit_log_start(current->audit_context,
GFP_ATOMIC, AUDIT_SELINUX_ERR);
if (!ab)
return;

audit_log_format(ab, "av boundary violation: "
"source=%s target=%s tclass=%s",
stype_name, ttype_name, tclass_name);
avc_dump_av(ab, tclass, masked);
audit_log_end(ab);
/* audit masked permissions */
security_dump_masked_av(scontext, tcontext,
tclass, masked, "bounds");
}
}

Expand Down Expand Up @@ -711,6 +789,26 @@ int security_bounded_transition(u32 old_sid, u32 new_sid)
}
index = type->bounds;
}

if (rc) {
char *old_name = NULL;
char *new_name = NULL;
int length;

if (!context_struct_to_string(old_context,
&old_name, &length) &&
!context_struct_to_string(new_context,
&new_name, &length)) {
audit_log(current->audit_context,
GFP_ATOMIC, AUDIT_SELINUX_ERR,
"op=security_bounded_transition "
"result=denied "
"oldcontext=%s newcontext=%s",
old_name, new_name);
}
kfree(new_name);
kfree(old_name);
}
out:
read_unlock(&policy_rwlock);

Expand Down

0 comments on commit 44c2d9b

Please sign in to comment.