diff mbox series

[v2,1/2] libselinux: safely access shared memory in selinux_status_updated()

Message ID 20200825153205.224136-2-cgzones@googlemail.com (mailing list archive)
State Accepted
Headers show
Series selinux_status_ changes | expand

Commit Message

Christian Göttsche Aug. 25, 2020, 3:32 p.m. UTC
Access the shared nenory safe in regard to consistent view of the SELinux
kernel status page - not in regard to thread-safety.

Signed-off-by: Christian Göttsche <cgzones@googlemail.com>
---
 libselinux/src/sestatus.c | 40 ++++++++++++++++++++++++---------------
 1 file changed, 25 insertions(+), 15 deletions(-)

Comments

Stephen Smalley Aug. 26, 2020, 12:52 p.m. UTC | #1
On Tue, Aug 25, 2020 at 11:32 AM Christian Göttsche
<cgzones@googlemail.com> wrote:
>
> Access the shared nenory safe in regard to consistent view of the SELinux

s/nenory/memory/

> kernel status page - not in regard to thread-safety.
>
> Signed-off-by: Christian Göttsche <cgzones@googlemail.com>

Acked-by: Stephen Smalley <stephen.smalley.work@gmail.com>
diff mbox series

Patch

diff --git a/libselinux/src/sestatus.c b/libselinux/src/sestatus.c
index 814e86ee..ca2d3bbf 100644
--- a/libselinux/src/sestatus.c
+++ b/libselinux/src/sestatus.c
@@ -91,7 +91,9 @@  static inline uint32_t read_sequence(struct selinux_status_t *status)
 int selinux_status_updated(void)
 {
 	uint32_t	curr_seqno;
-	int		result = 0;
+	uint32_t	tmp_seqno;
+	uint32_t	enforcing;
+	uint32_t	policyload;
 
 	if (selinux_status == NULL) {
 		errno = EINVAL;
@@ -117,21 +119,29 @@  int selinux_status_updated(void)
 	if (last_seqno & 0x0001)
 		last_seqno = curr_seqno;
 
-	if (last_seqno != curr_seqno)
-	{
-		if (avc_enforcing != (int) 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;
+	if (last_seqno == curr_seqno)
+		return 0;
+
+	/* sequence must not be changed during references */
+	do {
+		enforcing = selinux_status->enforcing;
+		policyload = selinux_status->policyload;
+		tmp_seqno = curr_seqno;
+		curr_seqno = read_sequence(selinux_status);
+	} while (tmp_seqno != curr_seqno);
+
+	if (avc_enforcing != (int) enforcing) {
+		if (avc_process_setenforce(enforcing) < 0)
+			return -1;
+	}
+	if (last_policyload != policyload) {
+		if (avc_process_policyload(policyload) < 0)
+			return -1;
+		last_policyload = policyload;
 	}
-	return result;
+	last_seqno = curr_seqno;
+
+	return 1;
 }
 
 /*