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

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