Blame SOURCES/open-lldp-v1.0.1-24-switch-from-sysv-to-posix-shared-memory-apis.patch

89f6b3
From 3124c4b4537083618b82f230b05997c70096c897 Mon Sep 17 00:00:00 2001
89f6b3
From: Chris Leech <cleech@redhat.com>
89f6b3
Date: Mon, 20 Jul 2015 17:32:02 -0700
89f6b3
Subject: [PATCH] switch from sysv to posix shared memory apis
89f6b3
89f6b3
The use of SysV shared memory, to pass state between running instances of
89f6b3
lldpad in the initramfs and then from the root fs, is difficult to work
89f6b3
with from a security policy.  When lldpad runs in the initramfs there is
89f6b3
no security policy loaded.  Then when it's restarted after an SELinux
89f6b3
policy has been loaded, there is no way to correct the context on the
89f6b3
already existing shared memory segment.  This would result in the need
89f6b3
for an overly permissive policy for lldpad.
89f6b3
89f6b3
By switching to POSIX APIs the segment is mapped from a tmpfs file with
89f6b3
a directory entry under /dev/shm/.  This lets us add a file contents
89f6b3
entry to the SELinux policy that matches that path, and a proper
89f6b3
security context can be restored to it before restarting lldpad.
89f6b3
89f6b3
- Chris
89f6b3
---
89f6b3
 Makefile.am          |   2 +-
89f6b3
 include/lldpad_shm.h |   2 +-
89f6b3
 lldpad_shm.c         | 169 ++++++++++++++++++++++++++++++---------------------
89f6b3
 3 files changed, 103 insertions(+), 70 deletions(-)
89f6b3
89f6b3
diff --git a/Makefile.am b/Makefile.am
89f6b3
index 84d68ee..551d4c7 100644
89f6b3
--- a/Makefile.am
89f6b3
+++ b/Makefile.am
89f6b3
@@ -17,7 +17,7 @@ parse_cli.o: CFLAGS+=-U_FORTIFY_SOURCE -Wno-error
89f6b3
 
89f6b3
 ## system requires a shared libconfig
89f6b3
 AM_CFLAGS = -Wall -Werror -Wextra -Wformat=2 $(LIBCONFIG_CFLAGS) $(LIBNL_CFLAGS)
89f6b3
-AM_LDFLAGS = $(LIBCONFIG_LIBS) $(LIBNL_LIBS)
89f6b3
+AM_LDFLAGS = $(LIBCONFIG_LIBS) $(LIBNL_LIBS) -lrt
89f6b3
 
89f6b3
 ## header files to be installed, for programs using the client interface to lldpad 
89f6b3
 lldpad_includedir= ${includedir}/lldpad
89f6b3
diff --git a/include/lldpad_shm.h b/include/lldpad_shm.h
89f6b3
index 00d20eb..587b555 100644
89f6b3
--- a/include/lldpad_shm.h
89f6b3
+++ b/include/lldpad_shm.h
89f6b3
@@ -31,7 +31,7 @@
89f6b3
 #include "lldpad.h"
89f6b3
 #include "lldp_rtnl.h"
89f6b3
 
89f6b3
-#define LLDPAD_SHM_KEY ((('l'<<24) | ('l'<<16) | ('d'<<8) | ('p')) + 'a' + 'd' + 1)
89f6b3
+#define LLDPAD_SHM_PATH "/lldpad.state"
89f6b3
 #define LLDPAD_SHM_SIZE 4096
89f6b3
 
89f6b3
 /* PID value used to indicate pid field is uninitialized */
89f6b3
diff --git a/lldpad_shm.c b/lldpad_shm.c
89f6b3
index 4afcf73..d8bc0c5 100644
89f6b3
--- a/lldpad_shm.c
89f6b3
+++ b/lldpad_shm.c
89f6b3
@@ -29,7 +29,9 @@
89f6b3
 #include <string.h>
89f6b3
 #include <syslog.h>
89f6b3
 #include <sys/ipc.h>
89f6b3
-#include <sys/shm.h>
89f6b3
+#include <sys/mman.h>
89f6b3
+#include <sys/stat.h>
89f6b3
+#include <fcntl.h>
89f6b3
 #include <sys/types.h>
89f6b3
 #include <unistd.h>
89f6b3
 #include <errno.h>
89f6b3
@@ -39,16 +41,7 @@
89f6b3
 
89f6b3
 void mark_lldpad_shm_for_removal()
89f6b3
 {
89f6b3
-	int shmid;
89f6b3
-	struct shmid_ds shminfo;
89f6b3
-
89f6b3
-	shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0);
89f6b3
-
89f6b3
-	if (shmid < 0)
89f6b3
-		return;
89f6b3
-
89f6b3
-	if (shmctl(shmid, IPC_RMID, &shminfo) < 0)
89f6b3
-		return;
89f6b3
+	shm_unlink(LLDPAD_SHM_PATH);
89f6b3
 }
89f6b3
 
89f6b3
 /* return: 1 = success, 0 = failed */
89f6b3
@@ -101,16 +94,21 @@ int lldpad_shm_get_msap(const char *device_name, int type, char *info, size_t *l
89f6b3
 	unsigned num_entries;
89f6b3
 	int version;
89f6b3
 
89f6b3
-	shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0);
89f6b3
-	if (shmid < 0 && errno == ENOENT)
89f6b3
-		shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE,
89f6b3
-			IPC_CREAT | IPC_EXCL | 0x180);
89f6b3
+	shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
89f6b3
 
89f6b3
 	if (shmid < 0)
89f6b3
 		return rval;
89f6b3
 
89f6b3
-	shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0);
89f6b3
-	if ((long) shmaddr == -1)
89f6b3
+	if (ftruncate(shmid, LLDPAD_SHM_SIZE)) {
89f6b3
+		close(shmid);
89f6b3
+		return rval;
89f6b3
+	}
89f6b3
+
89f6b3
+	shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE,
89f6b3
+			                         PROT_READ | PROT_WRITE,
89f6b3
+						 MAP_SHARED, shmid, 0);
89f6b3
+	close(shmid);
89f6b3
+	if (shmaddr == MAP_FAILED)
89f6b3
 		return rval;
89f6b3
 
89f6b3
 	version = (shmaddr->num_entries & SHM_VER_MASK) >> SHM_VER_SHIFT;
89f6b3
@@ -147,7 +145,7 @@ int lldpad_shm_get_msap(const char *device_name, int type, char *info, size_t *l
89f6b3
 		rval = 1;
89f6b3
 	}
89f6b3
 done:
89f6b3
-	shmdt(shmaddr);
89f6b3
+	munmap(shmaddr, LLDPAD_SHM_SIZE);
89f6b3
 
89f6b3
 	return rval;
89f6b3
 }
89f6b3
@@ -162,16 +160,21 @@ int lldpad_shm_set_msap(const char *device_name, int type, char *info, size_t le
89f6b3
 	int version;
89f6b3
 	unsigned num_entries;
89f6b3
 
89f6b3
-	shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0);
89f6b3
-	if (shmid < 0 && errno == ENOENT)
89f6b3
-		shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE,
89f6b3
-			IPC_CREAT | IPC_EXCL | 0x180);
89f6b3
+	shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
89f6b3
 
89f6b3
 	if (shmid < 0)
89f6b3
 		return rval;
89f6b3
 
89f6b3
-	shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0);
89f6b3
-	if ((long) shmaddr == -1)
89f6b3
+	if (ftruncate(shmid, LLDPAD_SHM_SIZE)) {
89f6b3
+		close(shmid);
89f6b3
+		return rval;
89f6b3
+	}
89f6b3
+
89f6b3
+	shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE,
89f6b3
+			                         PROT_READ | PROT_WRITE,
89f6b3
+						 MAP_SHARED, shmid, 0);
89f6b3
+	close(shmid);
89f6b3
+	if (shmaddr == MAP_FAILED)
89f6b3
 		return rval;
89f6b3
 
89f6b3
 	version = (shmaddr->num_entries & SHM_VER_MASK) >> SHM_VER_SHIFT;
89f6b3
@@ -212,7 +215,7 @@ int lldpad_shm_set_msap(const char *device_name, int type, char *info, size_t le
89f6b3
 	}
89f6b3
 
89f6b3
 done:
89f6b3
-	shmdt(shmaddr);
89f6b3
+	munmap(shmaddr, LLDPAD_SHM_SIZE);
89f6b3
 
89f6b3
 	return rval;
89f6b3
 }
89f6b3
@@ -226,16 +229,21 @@ int lldpad_shm_get_dcbx(const char *device_name)
89f6b3
 	unsigned num_entries;
89f6b3
 	int version;
89f6b3
 
89f6b3
-	shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0);
89f6b3
-	if (shmid < 0 && errno == ENOENT)
89f6b3
-		shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE,
89f6b3
-			IPC_CREAT | IPC_EXCL | 0x180);
89f6b3
+	shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
89f6b3
 
89f6b3
 	if (shmid < 0)
89f6b3
 		return rval;
89f6b3
 
89f6b3
-	shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0);
89f6b3
-	if ((long) shmaddr == -1)
89f6b3
+	if (ftruncate(shmid, LLDPAD_SHM_SIZE)) {
89f6b3
+		close(shmid);
89f6b3
+		return rval;
89f6b3
+	}
89f6b3
+
89f6b3
+	shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE,
89f6b3
+			                         PROT_READ | PROT_WRITE,
89f6b3
+						 MAP_SHARED, shmid, 0);
89f6b3
+	close(shmid);
89f6b3
+	if (shmaddr == MAP_FAILED)
89f6b3
 		return rval;
89f6b3
 
89f6b3
 	version = (shmaddr->num_entries & SHM_VER_MASK) >> SHM_VER_SHIFT;
89f6b3
@@ -264,7 +272,7 @@ int lldpad_shm_get_dcbx(const char *device_name)
89f6b3
 	}
89f6b3
 
89f6b3
 done:
89f6b3
-	shmdt(shmaddr);
89f6b3
+	munmap(shmaddr, LLDPAD_SHM_SIZE);
89f6b3
 
89f6b3
 	return rval;
89f6b3
 }
89f6b3
@@ -279,16 +287,21 @@ int lldpad_shm_set_dcbx(const char *device_name, int dcbx_mode)
89f6b3
 	unsigned num_entries;
89f6b3
 	int version;
89f6b3
 
89f6b3
-	shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0);
89f6b3
-	if (shmid < 0 && errno == ENOENT)
89f6b3
-		shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE,
89f6b3
-			IPC_CREAT | IPC_EXCL | 0x180);
89f6b3
+	shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
89f6b3
 
89f6b3
 	if (shmid < 0)
89f6b3
 		return rval;
89f6b3
 
89f6b3
-	shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0);
89f6b3
-	if ((long) shmaddr == -1)
89f6b3
+	if (ftruncate(shmid, LLDPAD_SHM_SIZE)) {
89f6b3
+		close(shmid);
89f6b3
+		return rval;
89f6b3
+	}
89f6b3
+
89f6b3
+	shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE,
89f6b3
+			                         PROT_READ | PROT_WRITE,
89f6b3
+						 MAP_SHARED, shmid, 0);
89f6b3
+	close(shmid);
89f6b3
+	if (shmaddr == MAP_FAILED)
89f6b3
 		return rval;
89f6b3
 
89f6b3
 	version = (shmaddr->num_entries & SHM_VER_MASK) >> SHM_VER_SHIFT;
89f6b3
@@ -330,7 +343,7 @@ int lldpad_shm_set_dcbx(const char *device_name, int dcbx_mode)
89f6b3
 	}
89f6b3
 
89f6b3
 done:
89f6b3
-	shmdt(shmaddr);
89f6b3
+	munmap(shmaddr, LLDPAD_SHM_SIZE);
89f6b3
 
89f6b3
 	return rval;
89f6b3
 }
89f6b3
@@ -346,16 +359,21 @@ pid_t lldpad_shm_getpid()
89f6b3
 	pid_t rval = -1;
89f6b3
 	int version;
89f6b3
 
89f6b3
-	shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0);
89f6b3
-	if (shmid < 0 && errno == ENOENT)
89f6b3
-		shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE,
89f6b3
-			IPC_CREAT | IPC_EXCL | 0x180);
89f6b3
+	shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
89f6b3
 
89f6b3
 	if (shmid < 0)
89f6b3
 		return rval;
89f6b3
 
89f6b3
-	shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0);
89f6b3
-	if ((long) shmaddr == -1)
89f6b3
+	if (ftruncate(shmid, LLDPAD_SHM_SIZE)) {
89f6b3
+		close(shmid);
89f6b3
+		return rval;
89f6b3
+	}
89f6b3
+
89f6b3
+	shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE,
89f6b3
+			                         PROT_READ | PROT_WRITE,
89f6b3
+						 MAP_SHARED, shmid, 0);
89f6b3
+	close(shmid);
89f6b3
+	if (shmaddr == MAP_FAILED)
89f6b3
 		return rval;
89f6b3
 
89f6b3
 	version = (shmaddr->num_entries & SHM_VER_MASK) >> SHM_VER_SHIFT;
89f6b3
@@ -366,7 +384,7 @@ pid_t lldpad_shm_getpid()
89f6b3
 
89f6b3
 	rval = shmaddr->pid;
89f6b3
 
89f6b3
-	shmdt(shmaddr);
89f6b3
+	munmap(shmaddr, LLDPAD_SHM_SIZE);
89f6b3
 
89f6b3
 	return rval;
89f6b3
 }
89f6b3
@@ -379,13 +397,16 @@ int lldpad_shm_setpid(pid_t pid)
89f6b3
 	pid_t rval = 0;
89f6b3
 	int version;
89f6b3
 
89f6b3
-	shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0);
89f6b3
+	shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR, S_IRUSR | S_IWUSR);
89f6b3
 
89f6b3
 	if (shmid < 0)
89f6b3
 		return rval;
89f6b3
 
89f6b3
-	shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0);
89f6b3
-	if ((long) shmaddr == -1)
89f6b3
+	shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE,
89f6b3
+			                         PROT_READ | PROT_WRITE,
89f6b3
+						 MAP_SHARED, shmid, 0);
89f6b3
+	close(shmid);
89f6b3
+	if (shmaddr == MAP_FAILED)
89f6b3
 		return rval;
89f6b3
 
89f6b3
 	version = (shmaddr->num_entries & SHM_VER_MASK) >> SHM_VER_SHIFT;
89f6b3
@@ -396,7 +417,7 @@ int lldpad_shm_setpid(pid_t pid)
89f6b3
 
89f6b3
 	shmaddr->pid = pid;
89f6b3
 
89f6b3
-	shmdt(shmaddr);
89f6b3
+	munmap(shmaddr, LLDPAD_SHM_SIZE);
89f6b3
 
89f6b3
 	return 1;
89f6b3
 }
89f6b3
@@ -410,13 +431,16 @@ int clear_dcbx_state()
89f6b3
 	int version;
89f6b3
 	unsigned num_entries;
89f6b3
 
89f6b3
-	shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0);
89f6b3
+	shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR, S_IRUSR | S_IWUSR);
89f6b3
 
89f6b3
 	if (shmid < 0)
89f6b3
 		return 0;
89f6b3
 
89f6b3
-	shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0);
89f6b3
-	if ((long) shmaddr == -1)
89f6b3
+	shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE,
89f6b3
+			                         PROT_READ | PROT_WRITE,
89f6b3
+						 MAP_SHARED, shmid, 0);
89f6b3
+	close(shmid);
89f6b3
+	if (shmaddr == MAP_FAILED)
89f6b3
 		return 0;
89f6b3
 
89f6b3
 	version = (shmaddr->num_entries & SHM_VER_MASK) >> SHM_VER_SHIFT;
89f6b3
@@ -437,7 +461,7 @@ int clear_dcbx_state()
89f6b3
 				sizeof(dcbx_state));
89f6b3
 
89f6b3
 done:
89f6b3
-	shmdt(shmaddr);
89f6b3
+	munmap(shmaddr, LLDPAD_SHM_SIZE);
89f6b3
 	return 1;
89f6b3
 }
89f6b3
 
89f6b3
@@ -451,13 +475,16 @@ int set_dcbx_state(const char *device_name, dcbx_state *state)
89f6b3
 	int version;
89f6b3
 	unsigned num_entries;
89f6b3
 
89f6b3
-	shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0);
89f6b3
+	shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR, S_IRUSR | S_IWUSR);
89f6b3
 
89f6b3
 	if (shmid < 0)
89f6b3
 		return rval;
89f6b3
 
89f6b3
-	shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0);
89f6b3
-	if ((long) shmaddr == -1)
89f6b3
+	shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE,
89f6b3
+			                         PROT_READ | PROT_WRITE,
89f6b3
+						 MAP_SHARED, shmid, 0);
89f6b3
+	close(shmid);
89f6b3
+	if (shmaddr == MAP_FAILED)
89f6b3
 		return rval;
89f6b3
 
89f6b3
 	version = (shmaddr->num_entries & SHM_VER_MASK) >> SHM_VER_SHIFT;
89f6b3
@@ -487,7 +514,7 @@ int set_dcbx_state(const char *device_name, dcbx_state *state)
89f6b3
 	}
89f6b3
 
89f6b3
 done:
89f6b3
-	shmdt(shmaddr);
89f6b3
+	munmap(shmaddr, LLDPAD_SHM_SIZE);
89f6b3
 
89f6b3
 	return rval;
89f6b3
 }
89f6b3
@@ -505,13 +532,16 @@ int get_dcbx_state(const char *device_name, dcbx_state *state)
89f6b3
 	int version;
89f6b3
 	unsigned num_entries;
89f6b3
 
89f6b3
-	shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0);
89f6b3
+	shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR, S_IRUSR | S_IWUSR);
89f6b3
 
89f6b3
 	if (shmid < 0)
89f6b3
 		return rval;
89f6b3
 
89f6b3
-	shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0);
89f6b3
-	if ((long) shmaddr == -1)
89f6b3
+	shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE,
89f6b3
+			                         PROT_READ | PROT_WRITE,
89f6b3
+						 MAP_SHARED, shmid, 0);
89f6b3
+	close(shmid);
89f6b3
+	if (shmaddr == MAP_FAILED)
89f6b3
 		return rval;
89f6b3
 
89f6b3
 	version = (shmaddr->num_entries & SHM_VER_MASK) >> SHM_VER_SHIFT;
89f6b3
@@ -537,7 +567,7 @@ int get_dcbx_state(const char *device_name, dcbx_state *state)
89f6b3
 		}
89f6b3
 
89f6b3
 done:
89f6b3
-	shmdt(shmaddr);
89f6b3
+	munmap(shmaddr, LLDPAD_SHM_SIZE);
89f6b3
 
89f6b3
 	return rval;
89f6b3
 }
89f6b3
@@ -562,17 +592,20 @@ int print_lldpad_shm()
89f6b3
 	int ent_size;
89f6b3
 	struct lldpad_shm_entry *entry_ptr = NULL;
89f6b3
 
89f6b3
-	shmid = shmget(LLDPAD_SHM_KEY, LLDPAD_SHM_SIZE, 0);
89f6b3
+	shmid = shm_open(LLDPAD_SHM_PATH, O_RDWR, S_IRUSR | S_IWUSR);
89f6b3
 
89f6b3
 	if (shmid < 0) {
89f6b3
-		printf("failed to shmget\n");
89f6b3
+		printf("failed to shm_open\n");
89f6b3
 		return rval;
89f6b3
 	}
89f6b3
 
89f6b3
-	shmaddr = (struct lldpad_shm_tbl *)shmat(shmid, NULL, 0);
89f6b3
+	shmaddr = (struct lldpad_shm_tbl *) mmap(NULL, LLDPAD_SHM_SIZE,
89f6b3
+			                         PROT_READ | PROT_WRITE,
89f6b3
+						 MAP_SHARED, shmid, 0);
89f6b3
 	shmaddr_ver0 = (struct lldpad_shm_tbl_ver0 *)shmaddr;
89f6b3
-	if ((long) shmaddr == -1) {
89f6b3
-		printf("failed to shmat\n");
89f6b3
+	close(shmid);
89f6b3
+	if (shmaddr == MAP_FAILED) {
89f6b3
+		printf("failed to mmap\n");
89f6b3
 		return rval;
89f6b3
 	}
89f6b3
 
89f6b3
@@ -633,7 +666,7 @@ int print_lldpad_shm()
89f6b3
 	rval = 1;
89f6b3
 
89f6b3
 done:
89f6b3
-	shmdt(shmaddr);
89f6b3
+	munmap(shmaddr, LLDPAD_SHM_SIZE);
89f6b3
 
89f6b3
 	return rval;
89f6b3
 }
89f6b3
-- 
89f6b3
2.1.0
89f6b3