Attached patch is Whitetank support for:
- mmaped shared memory
- POSIX semaphores
- hardening patch

mmaped shm + posix sem are allowed by uncommenting OPENAIS_POSIX_IPC
define in Makefile.inc (by default uncommented). Also please note, that
this is supported only on Linux (nether FreeBSD or Darwin has shared
semaphores support).

I choose definition of OPENAIS_POSIX_IPC rather then testing of
_POSIX_THREAD_PROCESS_SHARED simply because it is currently very easy to
 just recompile code and get old/new version on Linux (and of course,
patch can be easily transformed by simple sed script).

Regards,
  Honza
>From 2e0357991169728667b317ffe933751e278348e9 Mon Sep 17 00:00:00 2001
From: Jan Friesse <[email protected]>
Date: Thu, 27 May 2010 15:48:43 +0200
Subject: [PATCH 1/3] Support for MMAPed shared memory

---
 branches/whitetank/Makefile.inc      |    6 +++
 branches/whitetank/exec/ipc.c        |   58 +++++++++++++++++++++++++++++
 branches/whitetank/include/ipc_gen.h |    8 ++++
 branches/whitetank/lib/util.c        |   66 +++++++++++++++++++++++++++++++++-
 4 files changed, 137 insertions(+), 1 deletions(-)

diff --git a/branches/whitetank/Makefile.inc b/branches/whitetank/Makefile.inc
index c94e820..5d3add9 100644
--- a/branches/whitetank/Makefile.inc
+++ b/branches/whitetank/Makefile.inc
@@ -64,6 +64,9 @@ endif
 
 # OPENAIS_PROFILE
 
+# Use POSIX IPC (sem_post, mmaped shm) instead of SYS V IPC (semop, shm)
+OPENAIS_POSIX_IPC=1
+
 # default CFLAGS, LDFLAGS
 #
 CFLAGS = 
@@ -101,6 +104,9 @@ ifeq (${OPENAIS_COMPAT}, LINUX)
        override CFLAGS += -DOPENAIS_LINUX
        override LDFLAGS += -ldl -lpthread
        override DYFLAGS += -rdynamic
+ifdef OPENAIS_POSIX_IPC
+       override CFLAGS += -DOPENAIS_POSIX_IPC
+endif
 endif
 ifeq (${OPENAIS_COMPAT}, BSD)
        override CFLAGS += -DOPENAIS_BSD
diff --git a/branches/whitetank/exec/ipc.c b/branches/whitetank/exec/ipc.c
index 5337d25..1456fcc 100644
--- a/branches/whitetank/exec/ipc.c
+++ b/branches/whitetank/exec/ipc.c
@@ -89,6 +89,12 @@
 
 #include "util.h"
 
+#ifdef OPENAIS_POSIX_IPC
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#endif
+
 #ifdef OPENAIS_SOLARIS
 #define MSG_NOSIGNAL 0
 #endif
@@ -138,9 +144,13 @@ struct conn_info {
        enum conn_state state;
        int notify_flow_control_enabled;
        int refcount;
+#ifndef OPENAIS_POSIX_IPC
        key_t shmkey;
+#endif
        key_t semkey;
+#ifndef OPENAIS_POSIX_IPC
        int shmid;
+#endif
        int semid;
        unsigned int pending_semops;
        pthread_mutex_t mutex;
@@ -246,8 +256,12 @@ static inline int conn_info_destroy (struct conn_info 
*conn_info)
        /*
         * Destroy shared memory segment and semaphore
         */
+#ifndef OPENAIS_POSIX_IPC
        shmdt (conn_info->mem);
        res = shmctl (conn_info->shmid, IPC_RMID, NULL);
+#else
+       munmap (conn_info->mem, sizeof (struct shared_memory));
+#endif
        semctl (conn_info->semid, 0, IPC_RMID);
 
        /*
@@ -541,6 +555,40 @@ retry_recv:
        return (0);
 }
 
+#ifdef OPENAIS_POSIX_IPC
+static int
+memory_map (const char *path, size_t bytes, void **buf)
+{
+       int fd;
+       void *addr;
+       int res;
+
+       fd = open (path, O_RDWR, 0600);
+
+       unlink (path);
+
+       if (fd == -1) {
+               return (-1);
+       }
+
+       res = ftruncate (fd, bytes);
+       if (res == -1) {
+               close (fd);
+               return (-1);
+       }
+
+       addr = mmap (NULL, bytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+
+       res = close (fd);
+       if (res) {
+               return (-1);
+       }
+
+       *buf = addr;
+       return (0);
+}
+#endif
+
 static int poll_handler_connection (
        poll_handle handle,
        int fd,
@@ -585,16 +633,22 @@ static int poll_handler_connection (
 
                pthread_mutex_init (&conn_info->mutex, NULL);
                req_setup = (mar_req_setup_t *)conn_info->setup_msg;
+#ifndef OPENAIS_POSIX_IPC
                conn_info->shmkey = req_setup->shmkey;
+#endif
                conn_info->semkey = req_setup->semkey;
                conn_info->service = req_setup->service;
                conn_info->refcount = 0;
                conn_info->notify_flow_control_enabled = 0;
                conn_info->setup_bytes_read = 0;
 
+#ifndef OPENAIS_POSIX_IPC
                conn_info->shmid = shmget (conn_info->shmkey,
                        sizeof (struct shared_memory), 0600);
                conn_info->mem = shmat (conn_info->shmid, NULL, 0);
+#else
+               res = memory_map (req_setup->shm_file, sizeof (struct 
shared_memory), (void *)&conn_info->mem);
+#endif
                conn_info->semid = semget (conn_info->semkey, 3, 0600);
                conn_info->pending_semops = 0;
 
@@ -899,8 +953,12 @@ void openais_ipc_exit (void)
 
                conn_info = list_entry (list, struct conn_info, list);
 
+#ifndef OPENAIS_POSIX_IPC
                shmdt (conn_info->mem);
                shmctl (conn_info->shmid, IPC_RMID, NULL);
+#else
+               munmap (conn_info->mem, sizeof (struct shared_memory));
+#endif
                semctl (conn_info->semid, 0, IPC_RMID);
        
                pthread_kill (conn_info->thread, SIGUSR1);
diff --git a/branches/whitetank/include/ipc_gen.h 
b/branches/whitetank/include/ipc_gen.h
index a6235ee..c81d9c7 100644
--- a/branches/whitetank/include/ipc_gen.h
+++ b/branches/whitetank/include/ipc_gen.h
@@ -37,6 +37,10 @@
 
 #include "mar_gen.h"
 
+#ifdef OPENAIS_POSIX_IPC
+#include <semaphore.h>
+#endif
+
 enum service_types {
        EVS_SERVICE = 0,
        CLM_SERVICE = 1,
@@ -81,7 +85,11 @@ typedef struct {
 
 typedef struct {
        int service __attribute__((aligned(8)));
+#ifndef OPENAIS_POSIX_IPC
        unsigned long long shmkey __attribute__((aligned(8)));
+#else
+       char shm_file[128] __attribute__((aligned(8)));
+#endif
        unsigned long long semkey __attribute__((aligned(8)));
 } mar_req_setup_t __attribute__((aligned(8)));
 
diff --git a/branches/whitetank/lib/util.c b/branches/whitetank/lib/util.c
index f285eb5..7dfbc86 100644
--- a/branches/whitetank/lib/util.c
+++ b/branches/whitetank/lib/util.c
@@ -70,6 +70,10 @@
 #define IPC_SEMWAIT_TIMEOUT 2
 #endif
 
+#ifdef OPENAIS_POSIX_IPC
+#include <sys/mman.h>
+#endif
+
 enum SA_HANDLE_STATE {
        SA_HANDLE_STATE_EMPTY,
        SA_HANDLE_STATE_PENDINGREMOVAL,
@@ -85,7 +89,9 @@ struct saHandle {
 
 struct ipc_segment {
        int fd;
+#ifndef OPENAIS_POSIX_IPC
        int shmid;
+#endif
        int semid;
        int flow_control_state;
        struct shared_memory *shared_memory;
@@ -285,6 +291,43 @@ union semun {
 };
 #endif
 
+#ifdef OPENAIS_POSIX_IPC
+static int
+memory_map (char *path, const char *file, void **buf, size_t bytes)
+{
+       int fd;
+       void *addr;
+       int res;
+
+       sprintf (path, "/dev/shm/%s", file);
+
+       fd = mkstemp (path);
+       if (fd == -1) {
+               sprintf (path, "/var/run/%s", file);
+               fd = mkstemp (path);
+               if (fd == -1) {
+                       return (-1);
+               }
+       }
+
+       res = ftruncate (fd, bytes);
+       if (res == -1) {
+               close (fd);
+               return (-1);
+       }
+
+       addr = mmap (NULL, bytes, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+
+       res = close (fd);
+       if (res) {
+               return (-1);
+       }
+
+       *buf = addr;
+       return (0);
+}
+#endif
+
 SaAisErrorT
 openais_service_connect (
        enum service_types service,
@@ -294,7 +337,11 @@ openais_service_connect (
        struct sockaddr_un address;
        SaAisErrorT error;
        struct ipc_segment *ipc_segment;
+#ifndef OPENAIS_POSIX_IPC
        key_t shmkey = 0;
+#else
+       char shm_path[128];
+#endif
        key_t semkey = 0;
        int res;
        mar_req_setup_t req_setup;
@@ -335,11 +382,13 @@ openais_service_connect (
        /*
         * Allocate a shared memory segment
         */
+#ifndef OPENAIS_POSIX_IPC
        do {
                shmkey = random();
                ipc_segment->shmid = shmget (shmkey, sizeof (struct 
shared_memory),
                        IPC_CREAT|IPC_EXCL|0600);
        } while (ipc_segment->shmid == -1);
+#endif
 
        /*
         * Allocate a semaphore segment
@@ -353,11 +402,18 @@ openais_service_connect (
        /*
         * Attach to shared memory segment
         */
+#ifndef OPENAIS_POSIX_IPC
        ipc_segment->shared_memory = shmat (ipc_segment->shmid, NULL, 0);
        if (ipc_segment->shared_memory == (void *)-1) {
                goto error_exit;
        }
-       
+#else
+       res = memory_map (shm_path, "openais_shm-XXXXXX", (void 
*)&ipc_segment->shared_memory,
+               sizeof (struct shared_memory));
+       if (res == -1) {
+               return (-1);
+       }
+#endif
        semun.val = 0;
        res = semctl (ipc_segment->semid, 0, SETVAL, semun);
        if (res != 0) {
@@ -374,7 +430,11 @@ openais_service_connect (
                goto error_exit;
        }
 
+#ifndef OPENAIS_POSIX_IPC
        req_setup.shmkey = shmkey;
+#else
+       strcpy (req_setup.shm_file, shm_path);
+#endif
        req_setup.semkey = semkey;
        req_setup.service = service;
 
@@ -403,8 +463,12 @@ openais_service_connect (
 
 error_exit:
        close (request_fd);
+#ifndef OPENAIS_POSIX_IPC
        if (ipc_segment->shmid > 0)
                shmctl (ipc_segment->shmid, IPC_RMID, NULL);
+#else
+       munmap (ipc_segment->shared_memory, sizeof (struct shared_memory));
+#endif
        if (ipc_segment->semid > 0)
                semctl (ipc_segment->semid, 0, IPC_RMID);
        return (res_setup.error);
-- 
1.5.5.6

>From 3cdfb579645439eb5d729ed7e270c717ada257c2 Mon Sep 17 00:00:00 2001
From: Jan Friesse <[email protected]>
Date: Mon, 31 May 2010 10:02:03 +0200
Subject: [PATCH 2/3] Support for POSIX semaphores

---
 branches/whitetank/exec/ipc.c        |   65 +++++++++++++++++---
 branches/whitetank/include/ipc_gen.h |    7 ++-
 branches/whitetank/lib/util.c        |  111 +++++++++++++++++++++++-----------
 3 files changed, 138 insertions(+), 45 deletions(-)

diff --git a/branches/whitetank/exec/ipc.c b/branches/whitetank/exec/ipc.c
index 1456fcc..b890825 100644
--- a/branches/whitetank/exec/ipc.c
+++ b/branches/whitetank/exec/ipc.c
@@ -146,12 +146,10 @@ struct conn_info {
        int refcount;
 #ifndef OPENAIS_POSIX_IPC
        key_t shmkey;
-#endif
        key_t semkey;
-#ifndef OPENAIS_POSIX_IPC
        int shmid;
-#endif
        int semid;
+#endif
        unsigned int pending_semops;
        pthread_mutex_t mutex;
        struct shared_memory *mem;
@@ -167,7 +165,9 @@ static int shared_mem_dispatch_bytes_left (struct conn_info 
*conn_info);
 
 static void outq_flush (struct conn_info *conn_info);
 
+#ifndef OPENAIS_POSIX_IPC
 static int priv_change (struct conn_info *conn_info);
+#endif
 
 static void ipc_disconnect (struct conn_info *conn_info);
 
@@ -259,10 +259,13 @@ static inline int conn_info_destroy (struct conn_info 
*conn_info)
 #ifndef OPENAIS_POSIX_IPC
        shmdt (conn_info->mem);
        res = shmctl (conn_info->shmid, IPC_RMID, NULL);
+       semctl (conn_info->semid, 0, IPC_RMID);
 #else
+       sem_destroy (&conn_info->mem->sem0);
+       sem_destroy (&conn_info->mem->sem1);
+       sem_destroy (&conn_info->mem->sem2);
        munmap (conn_info->mem, sizeof (struct shared_memory));
 #endif
-       semctl (conn_info->semid, 0, IPC_RMID);
 
        /*
         * Free allocated data needed to retry exiting library IPC connection
@@ -313,7 +316,9 @@ record_proc_state(const char *file, const char *function, 
int line, const char *
 static void *pthread_ipc_consumer (void *conn)
 {
        struct conn_info *conn_info = (struct conn_info *)conn;
+#ifndef OPENAIS_POSIX_IPC
        struct sembuf sop;
+#endif
        int res;
        mar_req_header_t *header;
        struct res_overlay res_overlay;
@@ -323,14 +328,17 @@ static void *pthread_ipc_consumer (void *conn)
        int flow_control = 0;
 
        for (;;) {
+#ifndef OPENAIS_POSIX_IPC
                sop.sem_num = 0;
                sop.sem_op = -1;
                sop.sem_flg = 0;
+#endif
 retry_semop:
                if (ipc_thread_active (conn_info) == 0) {
                        openais_conn_refcount_dec (conn_info);
                        pthread_exit (0);
                }
+#ifndef OPENAIS_POSIX_IPC
                res = semop (conn_info->semid, &sop, 1);
                if ((res == -1) && (errno == EINTR || errno == EAGAIN)) {
                        goto retry_semop;
@@ -339,7 +347,12 @@ retry_semop:
                        openais_conn_refcount_dec (conn_info);
                        pthread_exit (0);
                }
-
+#else
+               res = sem_wait (&conn_info->mem->sem0);
+               if (res == -1 && errno == EINTR) {
+                       goto retry_semop;
+               }
+#endif
                openais_conn_refcount_inc (conn_info);
 
                header = (mar_req_header_t *)conn_info->mem->req_buffer;
@@ -635,8 +648,8 @@ static int poll_handler_connection (
                req_setup = (mar_req_setup_t *)conn_info->setup_msg;
 #ifndef OPENAIS_POSIX_IPC
                conn_info->shmkey = req_setup->shmkey;
-#endif
                conn_info->semkey = req_setup->semkey;
+#endif
                conn_info->service = req_setup->service;
                conn_info->refcount = 0;
                conn_info->notify_flow_control_enabled = 0;
@@ -646,10 +659,10 @@ static int poll_handler_connection (
                conn_info->shmid = shmget (conn_info->shmkey,
                        sizeof (struct shared_memory), 0600);
                conn_info->mem = shmat (conn_info->shmid, NULL, 0);
+               conn_info->semid = semget (conn_info->semkey, 3, 0600);
 #else
                res = memory_map (req_setup->shm_file, sizeof (struct 
shared_memory), (void *)&conn_info->mem);
 #endif
-               conn_info->semid = semget (conn_info->semkey, 3, 0600);
                conn_info->pending_semops = 0;
 
                /*
@@ -696,11 +709,13 @@ static int poll_handler_connection (
                        case MESSAGE_REQ_OUTQ_FLUSH:
                                outq_flush (conn_info);
                                break;
+#ifndef OPENAIS_POSIX_IPC
                        case MESSAGE_REQ_CHANGE_EUID:
                                if (priv_change (conn_info) == -1) {
                                        ipc_disconnect (conn_info);
                                }
                                break;
+#endif
                        default:
                                res = 0;
                                break;
@@ -956,11 +971,14 @@ void openais_ipc_exit (void)
 #ifndef OPENAIS_POSIX_IPC
                shmdt (conn_info->mem);
                shmctl (conn_info->shmid, IPC_RMID, NULL);
+               semctl (conn_info->semid, 0, IPC_RMID);
 #else
+               sem_destroy (&conn_info->mem->sem0);
+               sem_destroy (&conn_info->mem->sem1);
+               sem_destroy (&conn_info->mem->sem2);
                munmap (conn_info->mem, sizeof (struct shared_memory));
 #endif
-               semctl (conn_info->semid, 0, IPC_RMID);
-       
+
                pthread_kill (conn_info->thread, SIGUSR1);
        }
 }
@@ -978,10 +996,13 @@ void *openais_conn_private_data_get (void *conn)
 int openais_response_send (void *conn, void *msg, int mlen)
 {
        struct conn_info *conn_info = (struct conn_info *)conn;
+#ifndef OPENAIS_POSIX_IPC
        struct sembuf sop;
+#endif
        int res;
 
        memcpy (conn_info->mem->res_buffer, msg, mlen);
+#ifndef OPENAIS_POSIX_IPC
        sop.sem_num = 1;
        sop.sem_op = 1;
        sop.sem_flg = 0;
@@ -994,13 +1015,21 @@ retry_semop:
        if ((res == -1) && (errno == EINVAL || errno == EIDRM)) {
                return (0);
        }
+#else
+       res = sem_post (&conn_info->mem->sem1);
+       if (res == -1) {
+               return (-1);
+       }
+#endif
        return (0);
 }
 
 int openais_response_iov_send (void *conn, struct iovec *iov, int iov_len)
 {
        struct conn_info *conn_info = (struct conn_info *)conn;
+#ifndef OPENAIS_POSIX_IPC
        struct sembuf sop;
+#endif
        int res;
        int write_idx = 0;
        int i;
@@ -1010,6 +1039,7 @@ int openais_response_iov_send (void *conn, struct iovec 
*iov, int iov_len)
                write_idx += iov[i].iov_len;
        }
 
+#ifndef OPENAIS_POSIX_IPC
        sop.sem_num = 1;
        sop.sem_op = 1;
        sop.sem_flg = 0;
@@ -1022,6 +1052,12 @@ retry_semop:
        if ((res == -1) && (errno == EINVAL || errno == EIDRM)) {
                return (0);
        }
+#else
+       res = sem_post (&conn_info->mem->sem1);
+       if (res == -1) {
+               return (-1);
+       }
+#endif
        return (0);
 }
 
@@ -1069,7 +1105,9 @@ int memcpy_dwrap (struct conn_info *conn_info, void *msg, 
int len)
 void msg_send (void *conn, struct iovec *iov, int iov_len, int locked)
 {
        struct conn_info *conn_info = (struct conn_info *)conn;
+#ifndef OPENAIS_POSIX_IPC
        struct sembuf sop;
+#endif
        int res;
        int i;
        char buf;
@@ -1094,6 +1132,7 @@ void msg_send (void *conn, struct iovec *iov, int 
iov_len, int locked)
        if (res == -1) {
                ipc_disconnect (conn_info);
        }
+#ifndef OPENAIS_POSIX_IPC
        sop.sem_num = 2;
        sop.sem_op = 1;
        sop.sem_flg = 0;
@@ -1106,6 +1145,12 @@ retry_semop:
        if ((res == -1) && (errno == EINVAL || errno == EIDRM)) {
                return;
        }
+#else
+       res = sem_post (&conn_info->mem->sem2);
+       if (res == -1) {
+               return ;
+       }
+#endif
 }
 
 static void outq_flush (struct conn_info *conn_info) {
@@ -1143,6 +1188,7 @@ static void outq_flush (struct conn_info *conn_info) {
        pthread_mutex_unlock (&conn_info->mutex);
 }
 
+#ifndef OPENAIS_POSIX_IPC
 static int priv_change (struct conn_info *conn_info)
 {
        mar_req_priv_change req_priv_change;
@@ -1186,6 +1232,7 @@ retry_recv:
        }
        return (0);
 }
+#endif
 
 static void msg_send_or_queue (void *conn, struct iovec *iov, int iov_len)
 {
diff --git a/branches/whitetank/include/ipc_gen.h 
b/branches/whitetank/include/ipc_gen.h
index c81d9c7..251de1f 100644
--- a/branches/whitetank/include/ipc_gen.h
+++ b/branches/whitetank/include/ipc_gen.h
@@ -72,6 +72,11 @@ struct shared_memory {
        unsigned char dispatch_buffer[DISPATCH_SIZE];
        unsigned int read;
        unsigned int write;
+#ifdef OPENAIS_POSIX_IPC
+       sem_t sem0;
+       sem_t sem1;
+       sem_t sem2;
+#endif
 };
 
 enum res_init_types {
@@ -87,10 +92,10 @@ typedef struct {
        int service __attribute__((aligned(8)));
 #ifndef OPENAIS_POSIX_IPC
        unsigned long long shmkey __attribute__((aligned(8)));
+       unsigned long long semkey __attribute__((aligned(8)));
 #else
        char shm_file[128] __attribute__((aligned(8)));
 #endif
-       unsigned long long semkey __attribute__((aligned(8)));
 } mar_req_setup_t __attribute__((aligned(8)));
 
 typedef struct {
diff --git a/branches/whitetank/lib/util.c b/branches/whitetank/lib/util.c
index 7dfbc86..e111557 100644
--- a/branches/whitetank/lib/util.c
+++ b/branches/whitetank/lib/util.c
@@ -91,8 +91,8 @@ struct ipc_segment {
        int fd;
 #ifndef OPENAIS_POSIX_IPC
        int shmid;
-#endif
        int semid;
+#endif
        int flow_control_state;
        struct shared_memory *shared_memory;
        uid_t euid;
@@ -249,6 +249,7 @@ error_exit:
        return (0);
 }
 
+#ifndef OPENAIS_POSIX_IPC
 static int 
 priv_change_send (struct ipc_segment *ipc_segment)
 {
@@ -280,7 +281,7 @@ priv_change_send (struct ipc_segment *ipc_segment)
        ipc_segment->euid = req_priv_change.euid;
        return (0);
 }
-       
+#endif
        
 #if defined(_SEM_SEMUN_UNDEFINED)
 union semun {
@@ -339,14 +340,14 @@ openais_service_connect (
        struct ipc_segment *ipc_segment;
 #ifndef OPENAIS_POSIX_IPC
        key_t shmkey = 0;
+       key_t semkey = 0;
+       union semun semun;
 #else
        char shm_path[128];
 #endif
-       key_t semkey = 0;
        int res;
        mar_req_setup_t req_setup;
        mar_res_setup_t res_setup;
-       union semun semun;
 
        res_setup.error = SA_AIS_ERR_LIBRARY;
 
@@ -379,16 +380,15 @@ openais_service_connect (
        }
        bzero (ipc_segment, sizeof (struct ipc_segment));
 
+#ifndef OPENAIS_POSIX_IPC
        /*
         * Allocate a shared memory segment
         */
-#ifndef OPENAIS_POSIX_IPC
        do {
                shmkey = random();
                ipc_segment->shmid = shmget (shmkey, sizeof (struct 
shared_memory),
                        IPC_CREAT|IPC_EXCL|0600);
        } while (ipc_segment->shmid == -1);
-#endif
 
        /*
         * Allocate a semaphore segment
@@ -402,18 +402,11 @@ openais_service_connect (
        /*
         * Attach to shared memory segment
         */
-#ifndef OPENAIS_POSIX_IPC
        ipc_segment->shared_memory = shmat (ipc_segment->shmid, NULL, 0);
        if (ipc_segment->shared_memory == (void *)-1) {
                goto error_exit;
        }
-#else
-       res = memory_map (shm_path, "openais_shm-XXXXXX", (void 
*)&ipc_segment->shared_memory,
-               sizeof (struct shared_memory));
-       if (res == -1) {
-               return (-1);
-       }
-#endif
+
        semun.val = 0;
        res = semctl (ipc_segment->semid, 0, SETVAL, semun);
        if (res != 0) {
@@ -429,13 +422,36 @@ openais_service_connect (
        if (res != 0) {
                goto error_exit;
        }
+#else
+       /*
+        * Attach to shared memory segment
+        */
+       res = memory_map (shm_path, "openais_shm-XXXXXX", (void 
*)&ipc_segment->shared_memory,
+               sizeof (struct shared_memory));
+       if (res == -1) {
+               return (-1);
+       }
+
+       /*
+        * Initialize semaphores
+        */
+       if (sem_init (&ipc_segment->shared_memory->sem0, 1, 0) == -1) {
+               return (-1);
+       }
+       if (sem_init (&ipc_segment->shared_memory->sem1, 1, 0) == -1) {
+               return (-1);
+       }
+       if (sem_init (&ipc_segment->shared_memory->sem2, 1, 0) == -1) {
+               return (-1);
+       }
+#endif
 
 #ifndef OPENAIS_POSIX_IPC
        req_setup.shmkey = shmkey;
+       req_setup.semkey = semkey;
 #else
        strcpy (req_setup.shm_file, shm_path);
 #endif
-       req_setup.semkey = semkey;
        req_setup.service = service;
 
        error = openais_send (request_fd, &req_setup, sizeof (mar_req_setup_t));
@@ -466,11 +482,14 @@ error_exit:
 #ifndef OPENAIS_POSIX_IPC
        if (ipc_segment->shmid > 0)
                shmctl (ipc_segment->shmid, IPC_RMID, NULL);
+       if (ipc_segment->semid > 0)
+               semctl (ipc_segment->semid, 0, IPC_RMID);
 #else
+       sem_destroy (&ipc_segment->shared_memory->sem0);
+       sem_destroy (&ipc_segment->shared_memory->sem1);
+       sem_destroy (&ipc_segment->shared_memory->sem2);
        munmap (ipc_segment->shared_memory, sizeof (struct shared_memory));
 #endif
-       if (ipc_segment->semid > 0)
-               semctl (ipc_segment->semid, 0, IPC_RMID);
        return (res_setup.error);
 }
 
@@ -535,23 +554,22 @@ ipc_sem_wait (
        struct ipc_segment *ipc_segment,
        int sem_num)
 {
+#ifndef OPENAIS_POSIX_IPC
        struct sembuf sop;
-#if defined(OPENAIS_LINUX)
+#else
        struct timespec timeout;
        struct pollfd pfd;
+       sem_t *sem;
 #endif
        int res;
 
+#ifndef OPENAIS_POSIX_IPC
        sop.sem_num = sem_num;
        sop.sem_op = -1;
        sop.sem_flg = 0;
 
 retry_semop:
-#if defined(OPENAIS_LINUX)
-       timeout.tv_sec = IPC_SEMWAIT_TIMEOUT;
-       timeout.tv_nsec = 0;
-
-       res = semtimedop (ipc_segment->semid, &sop, 1, &timeout);
+       res = semop (ipc_segment->semid, &sop, 1);
        if (res == -1 && errno == EINTR) {
                goto retry_semop;
        } else
@@ -559,7 +577,28 @@ retry_semop:
                priv_change_send (ipc_segment);
                goto retry_semop;
        } else
-       if (res == -1 && errno == EAGAIN) {
+       if (res == -1) {
+               return (SA_AIS_ERR_LIBRARY);
+       }
+#else
+       switch (sem_num) {
+       case 0:
+               sem = &ipc_segment->shared_memory->sem0;
+               break;
+       case 1:
+               sem = &ipc_segment->shared_memory->sem1;
+               break;
+       case 2:
+               sem = &ipc_segment->shared_memory->sem2;
+               break;
+       }
+
+retry_semwait:
+       timeout.tv_sec = time (NULL) + IPC_SEMWAIT_TIMEOUT;
+       timeout.tv_nsec = 0;
+
+       res = sem_timedwait (sem, &timeout);
+       if (res == -1 && errno == ETIMEDOUT) {
                pfd.fd = ipc_segment->fd;
                pfd.events = 0;
 
@@ -575,19 +614,10 @@ retry_semop:
                        }
                }
 
-                goto retry_semop;
+                goto retry_semwait;
        } else
-       if (res == -1) {
-               return (SA_AIS_ERR_LIBRARY);
-       }
-#else
-       res = semop (ipc_segment->semid, &sop, 1);
        if (res == -1 && errno == EINTR) {
-               goto retry_semop;
-       } else
-       if (res == -1 && errno == EACCES) {
-               priv_change_send (ipc_segment);
-               goto retry_semop;
+               goto retry_semwait;
        } else
        if (res == -1) {
                return (SA_AIS_ERR_LIBRARY);
@@ -697,7 +727,9 @@ openais_msg_send (
        int iov_len)
 {
        struct ipc_segment *ipc_segment = (struct ipc_segment *)ipc_context;
+#ifndef OPENAIS_POSIX_IPC
        struct sembuf sop;
+#endif
        int i;
        int res;
        int req_buffer_idx = 0;
@@ -711,6 +743,8 @@ openais_msg_send (
                        iov[i].iov_len);
                req_buffer_idx += iov[i].iov_len;
        }
+
+#ifndef OPENAIS_POSIX_IPC
        /*
         * Signal semaphore #0 indicting a new message from client
         * to server request queue
@@ -731,6 +765,13 @@ retry_semop:
        if (res == -1) {
                return (SA_AIS_ERR_LIBRARY);
        }
+#else
+       res = sem_post (&ipc_segment->shared_memory->sem0);
+       if (res == -1) {
+               return (-1);
+       }
+#endif
+
        return (SA_AIS_OK);
 }
 
-- 
1.5.5.6

>From 45077b237e1f0431af8ddcf54ca897f62d42b14a Mon Sep 17 00:00:00 2001
From: Jan Friesse <[email protected]>
Date: Mon, 31 May 2010 15:06:43 +0200
Subject: [PATCH 3/3] IPC hardening

Backport of almost same patch as in corosync for solve a segfault
issue in openais on exit.

Semop implementation doesn't has this problem because semop is little
more clever and doesn't segfault on uninitialized semaphore.
---
 branches/whitetank/exec/ipc.c |   14 ++++++++++++--
 1 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/branches/whitetank/exec/ipc.c b/branches/whitetank/exec/ipc.c
index b890825..ba920a5 100644
--- a/branches/whitetank/exec/ipc.c
+++ b/branches/whitetank/exec/ipc.c
@@ -962,6 +962,9 @@ void openais_ipc_exit (void)
 {
        struct list_head *list;
        struct conn_info *conn_info;
+#ifdef OPENAIS_POSIX_IPC
+       void *retval;
+#endif
 
        for (list = conn_info_list_head.next; list != &conn_info_list_head;
                list = list->next) {
@@ -972,14 +975,21 @@ void openais_ipc_exit (void)
                shmdt (conn_info->mem);
                shmctl (conn_info->shmid, IPC_RMID, NULL);
                semctl (conn_info->semid, 0, IPC_RMID);
+
+               pthread_kill (conn_info->thread, SIGUSR1);
 #else
+               if (conn_info->state != CONN_STATE_THREAD_ACTIVE && 
conn_info->state != CONN_STATE_THREAD_REQUEST_EXIT)
+                       continue;
+
+               ipc_disconnect (conn_info);
+
+               pthread_join (conn_info->thread, &retval);
+
                sem_destroy (&conn_info->mem->sem0);
                sem_destroy (&conn_info->mem->sem1);
                sem_destroy (&conn_info->mem->sem2);
                munmap (conn_info->mem, sizeof (struct shared_memory));
 #endif
-
-               pthread_kill (conn_info->thread, SIGUSR1);
        }
 }
 
-- 
1.5.5.6

_______________________________________________
Openais mailing list
[email protected]
https://lists.linux-foundation.org/mailman/listinfo/openais

Reply via email to