Skip to contentSkip to conversation

newrole auditing of failures due to user actions

PATCH In review Michael C Thompson 3 participants 7 messages Sep 28, 2006 SELinux security module

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 newrole auditing of failures due to user actions

This patch introduces two new point in the code where audit records are generated for newrole. Both points are when the attempt to newrole fails.

The first point is when the default type could not be determine for the specified role - this is audited because, as sgrubb pointed out, it is currently non-tracked path to probe the policy.

The second point is when the desired context to change to is invalid.

There record format remains unchanged. Failing to validate the desired context will result in the old and new contexts being recorded intact to the log. For the default type, the old and new contexts have not yet been obtained, so they are recorded in the log as XXX_context=?

----

newrole/newrole.c +45 -24
@@ -47,7 +47,9 @@
  *
  *************************************************************************/
 
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif
 #include <stdio.h>
 #include <stdlib.h>		/* for malloc(), realloc(), free() */
 #include <pwd.h>		/* for getpwuid() */
@@ -394,6 +396,41 @@
 		cap_free(new_caps);
 	}
 }
+
+/* Send audit message */
+int send_audit_message(int success, security_context_t old_context,
+			security_context_t new_context, const char *ttyn)
+{
+	char *msg = NULL;
+	int rc;
+	int audit_fd = audit_open();
+
+	if (audit_fd < 0) {
+		fprintf(stderr, _("Error connecting to audit system.\n"));
+		rc = -1;
+		goto out;
+	}
+	if (asprintf(&msg, "newrole: old-context=%s new-context=%s",
+				old_context ? old_context : "?",
+				new_context ? new_context : "?") < 0) {
+		fprintf(stderr, _("Error allocating memory.\n"));
+		rc = -1;
+		goto out;
+	}
+	rc = audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE,
+			msg, NULL, NULL, ttyn, success);
+	if (rc <= 0) {
+		fprintf(stderr, _("Error sending audit message.\n"));
+		rc = -1;
+		goto out;
+	}
+	rc = 0;
+out:
+	free(msg);
+	close(audit_fd);
+	return rc;
+}
+
 #endif
 
 /************************************************************************
@@ -536,6 +573,9 @@
 	if (role_s && !type_s) {
 		if (get_default_type(role_s, &type_s)) {
 			fprintf(stderr, _("Couldn't get default type.\n"));
+#ifdef LOG_AUDIT_PRIV
+			send_audit_message(0, old_context, new_context, ttyn);
+#endif
 			exit(-1);
 		}
 #ifdef CANTSPELLGDB
@@ -715,6 +755,9 @@
 
 	if (security_check_context(new_context) < 0) {
 		fprintf(stderr, _("%s is not a valid context\n"), new_context);
+#ifdef LOG_AUDIT_PRIV
+		send_audit_message(0, old_context, new_context, ttyn);
+#endif
 		exit(-1);
 	}
 
@@ -874,30 +917,8 @@
 		exit(-1);
 	}
 #ifdef LOG_AUDIT_PRIV
-	/* Send audit message */
-	{
-		char *msg;
-		int rc;
-		int audit_fd = audit_open();
-		if (audit_fd < 0) {
-			fprintf(stderr,
-				_("Error connecting to audit system.\n"));
-			exit(-1);
-		}
-		if (asprintf(&msg, "newrole: old-context=%s new-context=%s",
-			     old_context, new_context) < 0) {
-			fprintf(stderr, _("Error allocating memory.\n"));
-			exit(-1);
-		}
-		rc = audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE,
-					    msg, NULL, NULL, ttyn, 1);
-		if (rc <= 0) {
-			fprintf(stderr, _("Error sending audit message.\n"));
-			exit(-1);
-		}
-		free(msg);
-		close(audit_fd);
-	}
+	if (send_audit_message(1, old_context, new_context, ttyn))
+		exit(-1);
 #endif
 	freecon(old_context);
 	execv(pw->pw_shell, argv + optind - 1);
#1 lore raw
Quoted 1 line · Michael C Thompson

This patch introduces two new point in the code where audit records are generated for newrole. Both points are when the attempt to newrole fails.

Forgot to copy the SELinux mailing list.

Quoted 129 lines

The first point is when the default type could not be determine for the specified role - this is audited because, as sgrubb pointed out, it is currently non-tracked path to probe the policy.

The second point is when the desired context to change to is invalid.

There record format remains unchanged. Failing to validate the desired context will result in the old and new contexts being recorded intact to the log. For the default type, the old and new contexts have not yet been obtained, so they are recorded in the log as XXX_context=?

----

------------------------------------------------------------------------

newrole/newrole.c +45 -26
@@ -47,7 +47,9 @@
  *
  *************************************************************************/
 
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif
 #include <stdio.h>
 #include <stdlib.h>		/* for malloc(), realloc(), free() */
 #include <pwd.h>		/* for getpwuid() */
@@ -394,6 +396,41 @@
 		cap_free(new_caps);
 	}
 }
+
+/* Send audit message */
+int send_audit_message(int success, security_context_t old_context,
+			security_context_t new_context, const char *ttyn)
+{
+	char *msg = NULL;
+	int rc;
+	int audit_fd = audit_open();
+
+	if (audit_fd < 0) {
+		fprintf(stderr, _("Error connecting to audit system.\n"));
+		rc = -1;
+		goto out;
+	}
+	if (asprintf(&msg, "newrole: old-context=%s new-context=%s",
+				old_context ? old_context : "?",
+				new_context ? new_context : "?") < 0) {
+		fprintf(stderr, _("Error allocating memory.\n"));
+		rc = -1;
+		goto out;
+	}
+	rc = audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE,
+			msg, NULL, NULL, ttyn, success);
+	if (rc <= 0) {
+		fprintf(stderr, _("Error sending audit message.\n"));
+		rc = -1;
+		goto out;
+	}
+	rc = 0;
+out:
+	free(msg);
+	close(audit_fd);
+	return rc;
+}
+
 #endif
 
 /************************************************************************
@@ -536,6 +573,9 @@
 	if (role_s && !type_s) {
 		if (get_default_type(role_s, &type_s)) {
 			fprintf(stderr, _("Couldn't get default type.\n"));
+#ifdef LOG_AUDIT_PRIV
+			send_audit_message(0, old_context, new_context, ttyn);
+#endif
 			exit(-1);
 		}
 #ifdef CANTSPELLGDB
@@ -715,6 +755,9 @@
 
 	if (security_check_context(new_context) < 0) {
 		fprintf(stderr, _("%s is not a valid context\n"), new_context);
+#ifdef LOG_AUDIT_PRIV
+		send_audit_message(0, old_context, new_context, ttyn);
+#endif
 		exit(-1);
 	}
 
@@ -874,30 +917,8 @@
 		exit(-1);
 	}
 #ifdef LOG_AUDIT_PRIV
-	/* Send audit message */
-	{
-		char *msg;
-		int rc;
-		int audit_fd = audit_open();
-		if (audit_fd < 0) {
-			fprintf(stderr,
-				_("Error connecting to audit system.\n"));
-			exit(-1);
-		}
-		if (asprintf(&msg, "newrole: old-context=%s new-context=%s",
-			     old_context, new_context) < 0) {
-			fprintf(stderr, _("Error allocating memory.\n"));
-			exit(-1);
-		}
-		rc = audit_log_user_message(audit_fd, AUDIT_USER_ROLE_CHANGE,
-					    msg, NULL, NULL, ttyn, 1);
-		if (rc <= 0) {
-			fprintf(stderr, _("Error sending audit message.\n"));
-			exit(-1);
-		}
-		free(msg);
-		close(audit_fd);
-	}
+	if (send_audit_message(1, old_context, new_context, ttyn))
+		exit(-1);
 #endif
 	freecon(old_context);
 	execv(pw->pw_shell, argv + optind - 1);
 
 
------------------------------------------------------------------------
 
--

Linux-audit mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/linux-audit

#2 lore raw
Quoted 4 lines · Michael C Thompson
Quoted 2 lines

This patch introduces two new point in the code where audit records are generated for newrole. Both points are when the attempt to newrole fails.

From an audit perspective I think it does the right thing. ACK.

-Steve

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

#3 lore raw
In reply to Michael C Thompson
Quoted 3 lines · Michael C Thompson
Quoted 2 lines · Michael C Thompson

This patch introduces two new point in the code where audit records are generated for newrole. Both points are when the attempt to newrole fails.

In addition to my prior comments about the #ifdefs:

Quoted 7 lines
Quoted 7 lines
newrole/newrole.c +4 -0
@@ -394,6 +396,41 @@
+/* Send audit message */
+int send_audit_message(int success, security_context_t old_context,
+			security_context_t new_context, const char *ttyn)
+{
Quoted 8 lines

newrole/newrole.c line 411

Quoted 8 lines
newrole/newrole.c +8 -0
+	char *msg = NULL;
+	int rc;
+	int audit_fd = audit_open();
+
+	if (audit_fd < 0) {
+		fprintf(stderr, _("Error connecting to audit system.\n"));
+		rc = -1;
+		goto out;

I think you just want to return -1 here, as there is no cleanup to be done at this point and the out path will try to do a close(audit_fd) i.e. close(-1) in this case, which isn't legal.

Signature · 8 lines
Stephen Smalley
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to [email protected] with
the words "unsubscribe selinux" without quotes as the message.
#4 lore raw
Quoted 17 lines · Stephen Smalley
Quoted 2 lines · Michael C Thompson
Quoted 1 line · Michael C Thompson

This patch introduces two new point in the code where audit records are generated for newrole. Both points are when the attempt to newrole fails.

In addition to my prior comments about the #ifdefs:

Quoted 11 lines
Quoted 11 lines
newrole/newrole.c +8 -0
@@ -394,6 +396,41 @@
+/* Send audit message */
+int send_audit_message(int success, security_context_t old_context,
+			security_context_t new_context, const char *ttyn)
+{
+	char *msg = NULL;
+	int rc;
+	int audit_fd = audit_open();
+
Quoted 8 lines
Quoted 4 lines

newrole/newrole.c line 411

Quoted 4 lines
newrole/newrole.c +4 -0
+	if (audit_fd < 0) {
+		fprintf(stderr, _("Error connecting to audit system.\n"));
+		rc = -1;
+		goto out;

I think you just want to return -1 here, as there is no cleanup to be done at this point and the out path will try to do a close(audit_fd) i.e. close(-1) in this case, which isn't legal.

Ah yes, my fault. I had caught that in one of my previous patch drafts. I will fix this and re-send, copying the proper lists.

Thanks.

--
This message was distributed to subscribers of the selinux mailing list. If you no longer wish to subscribe, send mail to [email protected] with the words "unsubscribe selinux" without quotes as the message.

#5 lore raw
In reply to Michael C Thompson
Quoted 7 lines · Michael C Thompson

This patch introduces two new point in the code where audit records are generated for newrole. Both points are when the attempt to newrole fails.

The first point is when the default type could not be determine for the specified role - this is audited because, as sgrubb pointed out, it is currently non-tracked path to probe the policy.

Quoted 8 lines

The second point is when the desired context to change to is invalid.

There record format remains unchanged. Failing to validate the desired context will result in the old and new contexts being recorded intact to the log. For the default type, the old and new contexts have not yet been obtained, so they are recorded in the log as XXX_context=?

(note: needs to go to selinux list if you want it merged)

newrole/newrole.c +2 -0
@@ -47,7 +47,9 @@
  *
  *************************************************************************/
 
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif
 

I think that the -D_GNU_SOURCE should just be removed from the Makefile.

@@ -394,6 +396,41 @@
cap_free(new_caps);
}
}
+
+/* Send audit message */
+int send_audit_message(int success, security_context_t old_context,
+ security_context_t new_context, const char *ttyn)

You need to wrap the entire function with #ifdef LOG_AUDIT_PRIV,
and provide a trivial inline function in the #else clause, e.g. #else
static inline int send_audit_message(int success, security_context_t old_context,
security_context_t new_context, const char *ttyn)

{
	return 0;
}

#endif

@@ -536,6 +573,9 @@
if (role_s && !type_s) {
if (get_default_type(role_s, &type_s)) {
fprintf(stderr, _("Couldn't get default type.\n"));
+#ifdef LOG_AUDIT_PRIV
+ send_audit_message(0, old_context, new_context, ttyn);
+#endif

You can then drop the #ifdefs here and later, since send_audit_message() will always have a valid definition.

Signature · 2 lines
Stephen Smalley
National Security Agency
#6 lore raw
Quoted 23 lines · Stephen Smalley
Quoted 9 lines · Michael C Thompson

This patch introduces two new point in the code where audit records are generated for newrole. Both points are when the attempt to newrole fails.

The first point is when the default type could not be determine for the specified role - this is audited because, as sgrubb pointed out, it is currently non-tracked path to probe the policy.

The second point is when the desired context to change to is invalid.

There record format remains unchanged. Failing to validate the desired context will result in the old and new contexts being recorded intact to the log. For the default type, the old and new contexts have not yet been obtained, so they are recorded in the log as XXX_context=?

(note: needs to go to selinux list if you want it merged)

newrole/newrole.c +2 -0
@@ -47,7 +47,9 @@
  *
  *************************************************************************/
 
+#ifndef _GNU_SOURCE
 #define _GNU_SOURCE
+#endif
 
Quoted 1 line

I think that the -D_GNU_SOURCE should just be removed from the Makefile.

Done.

Quoted 14 lines
newrole/newrole.c +4 -0
@@ -394,6 +396,41 @@
 		cap_free(new_caps);
 	}
 }
+
+/* Send audit message */
+int send_audit_message(int success, security_context_t old_context,
+			security_context_t new_context, const char *ttyn)
 
 You need to wrap the entire function with #ifdef LOG_AUDIT_PRIV,

and provide a trivial inline function in the #else clause, e.g. #else
static inline int send_audit_message(int success, security_context_t old_context,
security_context_t new_context, const char *ttyn)

Quoted 4 lines
{
	return 0;
}

#endif

Done.

Quoted 10 lines
newrole/newrole.c +3 -0
@@ -536,6 +573,9 @@
 	if (role_s && !type_s) {
 		if (get_default_type(role_s, &type_s)) {
 			fprintf(stderr, _("Couldn't get default type.\n"));
+#ifdef LOG_AUDIT_PRIV
+			send_audit_message(0, old_context, new_context, ttyn);
+#endif
 

You can then drop the #ifdefs here and later, since send_audit_message() will always have a valid definition.

Done.

Thanks,
Mike