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

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