All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] libselinux: Use sestatus if open
@ 2020-07-14 20:29 Mike Palmiotto
  2020-07-14 20:29 ` Mike Palmiotto
  2020-07-14 21:03 ` Stephen Smalley
  0 siblings, 2 replies; 17+ messages in thread
From: Mike Palmiotto @ 2020-07-14 20:29 UTC (permalink / raw)
  To: selinux

Commit bc2a8f418e3b ("libselinux: add selinux_status_* interfaces for
/selinux/status") introduced the selinux_status page mechanism, which
allows for mmap()'ing of selinux status state as a replacement for
avc_netlink.

The mechanism was initially intended for use by userspace object
managers which were calculating access decisions in-tree and did not
rely on the libselinux AVC implementation. In order to properly make use
of sestatus within avc_has_perm, the status mechanism needs to properly
set avc internals during status events; else, avc_enforcing is never
updated upon sestatus changes.

This commit moves the netlink notice logic out into convenience
functions, which are then called by the sestatus code. Since sestatus
uses netlink as a fallback, we can change the avc_netlink_check_nb()
call in avc_has_perm_noaudit to check the status page if it is
available. If it is not, we fall back to

Signed-off-by: Mike Palmiotto <mike.palmiotto@crunchydata.com>
---
 libselinux/src/avc.c          |  2 +-
 libselinux/src/avc_internal.c | 71 ++++++++++++++++++++++-------------
 libselinux/src/avc_internal.h |  4 ++
 libselinux/src/sestatus.c     | 18 +++++++--
 4 files changed, 65 insertions(+), 30 deletions(-)

diff --git a/libselinux/src/avc.c b/libselinux/src/avc.c
index b4648b2d..1fceac20 100644
--- a/libselinux/src/avc.c
+++ b/libselinux/src/avc.c
@@ -766,7 +766,7 @@ int avc_has_perm_noaudit(security_id_t ssid,
 		avd_init(avd);
 
 	if (!avc_using_threads && !avc_app_main_loop) {
-		(void)avc_netlink_check_nb();
+		(void)selinux_status_updated();
 	}
 
 	if (!aeref) {
diff --git a/libselinux/src/avc_internal.c b/libselinux/src/avc_internal.c
index 568a3d92..aee01a8a 100644
--- a/libselinux/src/avc_internal.c
+++ b/libselinux/src/avc_internal.c
@@ -53,6 +53,49 @@ int avc_enforcing = 1;
 int avc_setenforce = 0;
 int avc_netlink_trouble = 0;
 
+/* process setenforce events for netlink and sestatus */
+int avc_process_setenforce(int enforcing)
+{
+	int rc = 0;
+
+	avc_log(SELINUX_INFO,
+		"%s:  received setenforce notice (enforcing=%d)\n",
+		avc_prefix, enforcing);
+	if (avc_setenforce)
+		goto out;
+	avc_enforcing = enforcing;
+	if (avc_enforcing && (rc = avc_ss_reset(0)) < 0) {
+		avc_log(SELINUX_ERROR,
+			"%s:  cache reset returned %d (errno %d)\n",
+			avc_prefix, rc, errno);
+		return rc;
+	}
+
+out:
+	return selinux_netlink_setenforce(enforcing);
+}
+
+/* process policyload events for netlink and sestatus */
+int avc_process_policyload(uint32_t seqno)
+{
+	int rc = 0;
+
+	avc_log(SELINUX_INFO,
+		"%s:  received policyload notice (seqno=%u)\n",
+		avc_prefix, seqno);
+	rc = avc_ss_reset(seqno);
+	if (rc < 0) {
+		avc_log(SELINUX_ERROR,
+			"%s:  cache reset returned %d (errno %d)\n",
+			avc_prefix, rc, errno);
+		return rc;
+	}
+
+	selinux_flush_class_cache();
+
+	return selinux_netlink_policyload(seqno);
+}
+
 /* netlink socket code */
 static int fd = -1;
 
@@ -177,20 +220,7 @@ static int avc_netlink_process(void *buf)
 
 	case SELNL_MSG_SETENFORCE:{
 		struct selnl_msg_setenforce *msg = NLMSG_DATA(nlh);
-		msg->val = !!msg->val;
-		avc_log(SELINUX_INFO,
-			"%s:  received setenforce notice (enforcing=%d)\n",
-			avc_prefix, msg->val);
-		if (avc_setenforce)
-			break;
-		avc_enforcing = msg->val;
-		if (avc_enforcing && (rc = avc_ss_reset(0)) < 0) {
-			avc_log(SELINUX_ERROR,
-				"%s:  cache reset returned %d (errno %d)\n",
-				avc_prefix, rc, errno);
-			return rc;
-		}
-		rc = selinux_netlink_setenforce(msg->val);
+		rc = avc_process_setenforce(!!msg->val);
 		if (rc < 0)
 			return rc;
 		break;
@@ -198,18 +228,7 @@ static int avc_netlink_process(void *buf)
 
 	case SELNL_MSG_POLICYLOAD:{
 		struct selnl_msg_policyload *msg = NLMSG_DATA(nlh);
-		avc_log(SELINUX_INFO,
-			"%s:  received policyload notice (seqno=%u)\n",
-			avc_prefix, msg->seqno);
-		rc = avc_ss_reset(msg->seqno);
-		if (rc < 0) {
-			avc_log(SELINUX_ERROR,
-				"%s:  cache reset returned %d (errno %d)\n",
-				avc_prefix, rc, errno);
-			return rc;
-		}
-		selinux_flush_class_cache();
-		rc = selinux_netlink_policyload(msg->seqno);
+		rc = avc_process_policyload(msg->seqno);
 		if (rc < 0)
 			return rc;
 		break;
diff --git a/libselinux/src/avc_internal.h b/libselinux/src/avc_internal.h
index 3f8a6bb1..da67affc 100644
--- a/libselinux/src/avc_internal.h
+++ b/libselinux/src/avc_internal.h
@@ -32,6 +32,10 @@ extern void (*avc_func_get_lock) (void *);
 extern void (*avc_func_release_lock) (void *);
 extern void (*avc_func_free_lock) (void *);
 
+/* selinux status processing for netlink and sestatus */
+extern int avc_process_setenforce(int enforcing);
+extern int avc_process_policyload(uint32_t seqno);
+
 static inline void set_callbacks(const struct avc_memory_callback *mem_cb,
 				 const struct avc_log_callback *log_cb,
 				 const struct avc_thread_callback *thread_cb,
diff --git a/libselinux/src/sestatus.c b/libselinux/src/sestatus.c
index 86267ff8..4bd2086c 100644
--- a/libselinux/src/sestatus.c
+++ b/libselinux/src/sestatus.c
@@ -39,6 +39,7 @@ struct selinux_status_t
 static struct selinux_status_t *selinux_status = NULL;
 static int			selinux_status_fd;
 static uint32_t			last_seqno;
+static uint32_t			last_policyload;
 
 static uint32_t			fallback_sequence;
 static int			fallback_enforcing;
@@ -116,6 +117,15 @@ int selinux_status_updated(void)
 
 	if (last_seqno != curr_seqno)
 	{
+		if (avc_enforcing != !!selinux_status->enforcing) {
+			if (avc_process_setenforce(!!selinux_status->enforcing) < 0)
+				return -1;
+		}
+		if (last_policyload != selinux_status->policyload) {
+			if (avc_process_policyload(selinux_status->policyload) < 0)
+				return -1;
+			last_policyload = selinux_status->policyload;
+		}
 		last_seqno = curr_seqno;
 		result = 1;
 	}
@@ -131,7 +141,6 @@ int selinux_status_updated(void)
 int selinux_status_getenforce(void)
 {
 	uint32_t	seqno;
-	uint32_t	enforcing;
 
 	if (selinux_status == NULL) {
 		errno = EINVAL;
@@ -149,11 +158,11 @@ int selinux_status_getenforce(void)
 	do {
 		seqno = read_sequence(selinux_status);
 
-		enforcing = selinux_status->enforcing;
+		avc_enforcing = !!selinux_status->enforcing;
 
 	} while (seqno != read_sequence(selinux_status));
 
-	return enforcing ? 1 : 0;
+	return avc_enforcing;
 }
 
 /*
@@ -285,6 +294,9 @@ int selinux_status_open(int fallback)
 	return 0;
 
 error:
+	avc_log(SELINUX_WARNING,
+		"%s: could not open selinux status page: %d (%s)\n",
+		avc_prefix, errno, strerror(errno));
 	/*
 	 * If caller wants fallback routine, we try to provide
 	 * an equivalent functionality using existing netlink
-- 
2.27.0


^ permalink raw reply related	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2020-07-16 15:44 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-14 20:29 [PATCH] libselinux: Use sestatus if open Mike Palmiotto
2020-07-14 20:29 ` Mike Palmiotto
2020-07-14 21:03 ` Stephen Smalley
2020-07-14 21:20   ` Mike Palmiotto
2020-07-14 21:35     ` Stephen Smalley
2020-07-14 22:42       ` Mike Palmiotto
2020-07-15 16:04         ` Mike Palmiotto
2020-07-15 16:49           ` Stephen Smalley
2020-07-15 17:10             ` Mike Palmiotto
2020-07-15 18:52               ` Mike Palmiotto
2020-07-15 19:49                 ` Stephen Smalley
2020-07-15 22:45                   ` Mike Palmiotto
2020-07-16 12:39                     ` Stephen Smalley
2020-07-16 13:36                       ` Mike Palmiotto
2020-07-16 15:12                         ` Stephen Smalley
2020-07-16 15:27                           ` Stephen Smalley
2020-07-16 15:44                             ` Mike Palmiotto

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.