Hi Mike,

iscsid is leaking IPC identifiers when the startup fails.

Please apply.

Cheers,

Hannes
-- 
Dr. Hannes Reinecke                   zSeries & Storage
[EMAIL PROTECTED]                             +49 911 74053 688
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg
GF: Markus Rex, HRB 16746 (AG Nürnberg)

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"open-iscsi" group.
To post to this group, send email to open-iscsi@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at http://groups.google.com/group/open-iscsi
-~----------~----~----~----~------~----~------~--~---

Fixup IPC leak in iscsid

If iscsid is terminated due to a failure we're leaking IPC ids.
And we're not clearing the log area, causing iscsid to oops if
invoked twice.

Signed-off-by: Hannes Reinecke <[EMAIL PROTECTED]>

diff --git a/usr/log.c b/usr/log.c
index 9b82c46..013caed 100644
--- a/usr/log.c
+++ b/usr/log.c
@@ -37,6 +37,33 @@ int log_level = 0;
 
 static int log_stop_daemon = 0;
 
+static void free_logarea (void)
+{
+       int shmid;
+
+       if (!la)
+               return;
+
+       if (la->semid != -1)
+               semctl(la->semid, 0, IPC_RMID, la->semarg);
+       if (la->buff) {
+               shmdt(la->buff);
+               shmctl(la->shmid_buff, IPC_RMID, NULL);
+               la->buff = NULL;
+               la->shmid_buff = -1;
+       }
+       if (la->start) {
+               shmdt(la->start);
+               shmctl(la->shmid_msg, IPC_RMID, NULL);
+               la->start = NULL;
+               la->shmid_msg = -1;
+       }
+       shmid = la->shmid;
+       shmdt(la);
+       shmctl(shmid, IPC_RMID, NULL);
+       la = NULL;
+}
+
 static int logarea_init (int size)
 {
        int shmid;
@@ -48,21 +75,28 @@ static int logarea_init (int size)
                return 1;
 
        la = shmat(shmid, NULL, 0);
-       if (!la)
+       if (!la) {
+               shmctl(shmid, IPC_RMID, NULL);
                return 1;
+       }
+       la->shmid = shmid;
+       la->start = NULL;
+       la->buff = NULL;
+       la->semid = -1;
 
        if (size < MAX_MSG_SIZE)
                size = DEFAULT_AREA_SIZE;
 
        if ((shmid = shmget(IPC_PRIVATE, size,
                            0644 | IPC_CREAT | IPC_EXCL)) == -1) {
-               shmdt(la);
+               free_logarea();
                return 1;
        }
+       la->shmid_msg = shmid;
 
-       la->start = shmat(shmid, NULL, 0);
+       la->start = shmat(la->shmid_msg, NULL, 0);
        if (!la->start) {
-               shmdt(la);
+               free_logarea();
                return 1;
        }
        memset(la->start, 0, size);
@@ -74,32 +108,27 @@ static int logarea_init (int size)
 
        if ((shmid = shmget(IPC_PRIVATE, MAX_MSG_SIZE + sizeof(struct logmsg),
                            0644 | IPC_CREAT | IPC_EXCL)) == -1) {
-               shmdt(la->start);
-               shmdt(la);
+               free_logarea();
                return 1;
        }
        la->buff = shmat(shmid, NULL, 0);
        if (!la->buff) {
-               shmdt(la->start);
-               shmdt(la);
+               free_logarea();
                return 1;
        }
 
        if ((la->semid = semget(SEMKEY, 1, 0600 | IPC_CREAT)) < 0) {
-               shmdt(la->buff);
-               shmdt(la->start);
-               shmdt(la);
+               free_logarea();
                return 1;
        }
 
        la->semarg.val=1;
        if (semctl(la->semid, 0, SETVAL, la->semarg) < 0) {
-               shmdt(la->buff);
-               shmdt(la->start);
-               shmdt(la);
+               free_logarea();
                return 1;
        }
 
+       la->shmid_buff = shmid;
        la->ops[0].sem_num = 0;
        la->ops[0].sem_flg = 0;
 
@@ -107,14 +136,6 @@ static int logarea_init (int size)
 
 }
 
-static void free_logarea (void)
-{
-       shmdt(la->buff);
-       shmdt(la->start);
-       shmdt(la);
-       semctl(la->semid, 0, IPC_RMID, la->semarg);
-}
-
 #if LOGDBG
 static void dump_logarea (void)
 {
@@ -196,7 +217,7 @@ int log_dequeue (void * buff)
        int len;
 
        if (la->empty)
-               return 1;
+               return 0;
 
        len = strlen((char *)&src->str) * sizeof(char) +
              sizeof(struct logmsg) + 1;
@@ -215,7 +236,7 @@ int log_dequeue (void * buff)
 
        memset((void *)src, 0, len);
 
-       return la->empty;
+       return len;
 }
 
 /*
@@ -314,19 +335,22 @@ static void __dump_char(int level, unsigned char *buf, 
int *cp, int ch)
 
 static void log_flush(void)
 {
+       int msglen;
+
        while (!la->empty) {
                la->ops[0].sem_op = -1;
                if (semop(la->semid, la->ops, 1) < 0) {
                        syslog(LOG_ERR, "semop up failed %d", errno);
                        exit(1);
                }
-               log_dequeue(la->buff);
+               msglen = log_dequeue(la->buff);
                la->ops[0].sem_op = 1;
                if (semop(la->semid, la->ops, 1) < 0) {
                        syslog(LOG_ERR, "semop down failed");
                        exit(1);
                }
-               log_syslog(la->buff);
+               if (msglen)
+                       log_syslog(la->buff);
        }
 }
 
diff --git a/usr/log.h b/usr/log.h
index 4816a1b..4d2a265 100644
--- a/usr/log.h
+++ b/usr/log.h
@@ -51,6 +51,9 @@ struct logmsg {
 };
 
 struct logarea {
+       int shmid;
+       int shmid_msg;
+       int shmid_buff;
        int empty;
        void *head;
        void *tail;

Reply via email to