Changeset 34

Show
Ignore:
Timestamp:
05/29/08 22:08:39 (6 months ago)
Author:
jtang
Message:

Fix to some of buffer overflows within mqueue.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/libsipc/Makefile

    r33 r34  
    77 
    88ifeq ($(DEBUG), 1) 
    9   CFLAGS ?= -O0 -g3 -gdwarf-2 
     9  # if DEBUG is set, then explicitly compile with -O0 
     10  AM_CFLAGS ?= -O0 -g3 -gdwarf-2 
    1011  LDFLAGS ?= -g 
    1112else 
     13  # if no DEBUG and no CFLAGS are already set, then compile with -O3 
    1214  CFLAGS ?= -O3 
    1315endif 
     
    3335ALL_SUBDIRS = src include bindings/java examples man tests 
    3436 
     37C_INDENT_OPTS   = -npro -nbad -bap -nbbb -nbbo -nbc -br -bli0 -bls -c40 -cbi0 -cd40 -cdw  -ce -ci8 -cli0 -cp40 -ncs -d0 -nbfda -di1 -nfc1 -nfca -i8 -ip0 -l132 -lp -nlps -npcs -pi0 -nprs -npsl -saf -sai -sbi0 -sob -ss -ts8 -ut 
     38 
    3539all: 
    3640        for i in $(SUBDIRS) ; do \ 
     
    5559        $(MAKE) -C bindings/java $@ 
    5660 
     61indent: 
     62        find src include tests \ 
     63                \( -name '*.[ch]' -type f -exec indent $(C_INDENT_OPTS) '{}' \; \) 
     64 
    5765clean: 
    5866        for i in $(ALL_SUBDIRS) ; do \ 
     
    6068        done 
    6169 
    62 .PHONY: all example test install install-example javadoc clean 
     70.PHONY: all example tests install install-example javadoc indent clean 
  • trunk/libsipc/src/sipc_mqueue.c

    r27 r34  
    11/* Author: David Windsor <dwindsor@tresys.com> 
    2 *           
     2* 
    33* Copyright (C) 2006, 2007 Tresys Technology, LLC 
    44* Developed Under US JFCOM Sponsorship 
     
    3737 
    3838/* procfs entry for max size of a message */ 
    39 #define MQ_PROC "/proc/sys/fs/mqueue/msgsize_max"  
     39#define MQ_PROC "/proc/sys/fs/mqueue/msgsize_max" 
    4040 
    4141static struct sipc_func_table mqueue_funcs = { 
     
    7272        if (SIPC_MQUEUE_MSG_SZ < 0) 
    7373                return -1; 
    74          
    75         return 0; 
    76 } 
    77  
    78 /* Create a message queue having the specified key.  
     74 
     75        return 0; 
     76} 
     77 
     78/* Create a message queue having the specified key. 
    7979 * This function should only be called by a helper application 
    8080 * and not by the sender or reciever. */ 
    8181int sipc_mqueue_create(sipc_t *sipc) 
    8282{ 
    83         int msqid; 
     83       int msqid; 
    8484 
    8585        msqid = mqueue_create(sipc->key); 
     
    9595void sipc_mqueue_detach(sipc_t *sipc) 
    9696{ 
    97         free(sipc->data);      
     97        free(sipc->data); 
    9898        sipc->data = NULL; 
    9999} 
     
    116116                return -1; 
    117117        } 
    118          
     118 
    119119        return 0; 
    120120} 
     
    135135 
    136136        if (sipc->role != SIPC_SENDER) 
    137                 goto err;        
    138  
    139         mbuf = (struct msgbuf *)calloc(1, SIPC_MQUEUE_MSG_SZ); 
     137                goto err; 
     138 
     139        mbuf = (struct msgbuf *) calloc(1, SIPC_MQUEUE_MSG_SZ); 
    140140        if (!mbuf) { 
    141141                sipc_error(sipc, "%s\n", "Out of memory"); 
     
    153153                        sipc_error(sipc, "%s\n", "Unable to fragment message data"); 
    154154                        goto err; 
    155                 }              
    156                  
     155                } 
     156 
    157157                bzero(mbuf->mtext, packet_sz); 
    158                 mbuf->mtype = SIPC_SYSV_MQUEUES
     158                mbuf->mtype = SIPC_DATA_READY
    159159                memcpy(mbuf->mtext, packet, packet_sz); 
    160                  
     160 
    161161                /* Send the message */ 
    162162                if (msgsnd(sipc->msqid, mbuf, packet_sz, 0) < 0) { 
    163163                        sipc_error(sipc, "msgsnd: %s\n", strerror(errno)); 
    164164                        goto err; 
    165                 }               
    166                 free(packet);  
     165                } 
     166                free(packet); 
    167167        } while (!msg_done(sipc)); 
    168168 
     
    179179        return -1; 
    180180} 
    181      
     181 
    182182int sipc_mqueue_recv_data(sipc_t *sipc, char **data, int *len) 
    183183{ 
    184184        int retv = -1, alloc_sz = 0, idx = 0, recv_sz; 
    185         int msgtxt_sz = SIPC_MQUEUE_MSG_SZ - sizeof(struct msgbuf);     
     185        int msgtxt_sz = SIPC_MQUEUE_MSG_SZ - sizeof(struct msgbuf); 
    186186        struct msgbuf *mbuf = NULL; 
    187187 
    188         if (!data
     188        if (!sipc || !data || !len
    189189                goto err; 
    190190        if (sipc->role != SIPC_RECEIVER) { 
     
    192192                goto err; 
    193193        } 
    194                  
     194 
    195195        mbuf = calloc(1, SIPC_MQUEUE_MSG_SZ); 
    196196        if (!mbuf) { 
     
    205205        /* Receive and validate the length of message marker */ 
    206206        if (sipc->msg_len == SIPC_MSGLEN_NOT_SET) { 
    207                 if (msgrcv(sipc->msqid, mbuf, SIPC_MQUEUE_MSG_SZ, 0, 0) < 0) { 
     207                if (msgrcv(sipc->msqid, mbuf, SIPC_MQUEUE_MSG_SZ, SIPC_ANY, 0) < 0) { 
    208208                        sipc_error(sipc, "msgrcv: %s\n", strerror(errno)); 
    209209                        goto err; 
     
    228228                } 
    229229        } 
    230          
    231         /* Receive the message payload.  
     230 
     231        /* Receive the message payload. 
    232232         * Stop when we have received the total number of bytes 
    233233         * or upon receiving the end of message marker. */ 
    234         if ((recv_sz = msgrcv(sipc->msqid, mbuf, SIPC_MQUEUE_MSG_SZ, 0, 0)) < 0) { 
     234        if ((recv_sz = msgrcv(sipc->msqid, mbuf, SIPC_MQUEUE_MSG_SZ, SIPC_ANY, 0)) < 0) { 
    235235                sipc_error(sipc, "msgrcv: %s\n", strerror(errno)); 
    236236                goto err; 
    237237        } 
    238                          
     238 
    239239        *len += recv_sz; 
    240240        while (!is_end_xmit(mbuf)) { 
    241                 /* If this isn't the last packet in the message,  
     241                /* If this isn't the last packet in the message, 
    242242                 * resize to +1 message */ 
    243243                alloc_sz += next_alloc_sz(*len, recv_sz, msgtxt_sz, sipc->msg_len); 
    244244 
    245245                char *tdata = realloc(*data, alloc_sz); 
    246                 if (!(*tdata)) { 
     246                if (!tdata) { 
    247247                        sipc_error(sipc, "%s\n", "Out of memory"); 
    248248                        free(*data); 
     
    251251                } 
    252252                *data = tdata; 
    253                  
     253 
    254254                /* memset(*data+idx, 0x0, recv_sz); */ 
    255255                memcpy(*data+idx, mbuf->mtext, recv_sz); 
    256256                idx += recv_sz; 
    257          
     257 
    258258                /* Check to see if we have received the entire message */ 
    259259                if (*len >= sipc->msg_len) 
     
    261261 
    262262                /* Receive the next message */ 
    263                 if ((recv_sz = msgrcv(sipc->msqid, mbuf, SIPC_MQUEUE_MSG_SZ, 0, 0)) < 0) { 
     263                if ((recv_sz = msgrcv(sipc->msqid, mbuf, SIPC_MQUEUE_MSG_SZ, SIPC_ANY, 0)) < 0) { 
    264264                        sipc_error(sipc, "msgrcv: %s\n", strerror(errno)); 
    265265                        goto err; 
     
    268268                *len += recv_sz; 
    269269        } 
    270          
     270 
    271271        retv = 0; 
    272272err: 
     
    277277 
    278278void sipc_mqueue_error(const char *fmt, va_list ap) 
    279 {       
     279{ 
    280280        vfprintf(stderr, fmt, ap); 
    281281} 
     
    296296                (void)fclose(f); 
    297297                return -1; 
    298       } 
    299         if (fclose(f) == EOF)  
    300                 sipc_error(sipc, "fclose: %s\n", strerror(errno));      
    301          
    302         return atoi(buf);       
     298      } 
     299        if (fclose(f) == EOF) 
     300                sipc_error(sipc, "fclose: %s\n", strerror(errno)); 
     301 
     302        return atoi(buf); 
    303303} 
    304304 
    305305/* Send end of transmission marker */ 
    306306static int mqueue_send_end_xmit(sipc_t *sipc) 
    307 {       
     307{ 
    308308        struct msgbuf mbuf; 
    309         mbuf.mtype = SIPC_END_XMIT;        
    310  
    311         if (msgsnd(sipc->msqid, (struct msgbuf *)&mbuf, sizeof(mbuf), 0) < 0) { 
     309        mbuf.mtype = SIPC_END_XMIT; 
     310        memset(mbuf.mtext, 1, sizeof(mbuf.mtext)); 
     311 
     312        if (msgsnd(sipc->msqid, (struct msgbuf *)&mbuf, sizeof(mbuf.mtext), 0) < 0) { 
    312313                sipc_error(sipc, "msgsnd: %s\n", strerror(errno)); 
    313314                return -1; 
     
    320321static int qlog(int x) 
    321322{ 
    322   int i=0; 
    323   while(x) 
    324     { 
    325       i++; 
    326       x/=10; 
    327     } 
    328   return i; 
     323        int i = 1; 
     324        while(x) { 
     325                i++; 
     326                x /= 10; 
     327        } 
     328        return i; 
    329329} 
    330330 
     
    332332{ 
    333333        struct msgbuf *mbuf; 
    334    
    335         if (len < 0)  
    336                 return -1; 
    337         mbuf=calloc(1,sizeof(struct msgbuf)+qlog(len)+1); 
    338         if (!mbuf) { sipc_error(sipc,"Out of memory!\n"); return -1; } 
     334 
     335        if (len < 0) 
     336                return -1; 
     337        /* msgbuf already has a byte in its mtext field, so no need to 
     338           add one here */ 
     339        mbuf = calloc(1, sizeof(struct msgbuf) + qlog(len)); 
     340        if (!mbuf) { 
     341                sipc_error(sipc,"Out of memory!\n"); 
     342                return -1; 
     343        } 
    339344 
    340345        mbuf->mtype = SIPC_MSG_LEN; 
     
    342347        sprintf(mbuf->mtext, "%d", len); 
    343348 
    344         if (msgsnd(sipc->msqid, mbuf, sizeof(struct msgbuf) +  
    345                    strlen(mbuf->mtext) + 1, 0) < 0) { 
    346           free(mbuf); 
    347           sipc_error(sipc, "msgsnd: %s\n", strerror(errno)); 
    348           return -1; 
     349        if (msgsnd(sipc->msqid, mbuf, strlen(mbuf->mtext) + 1, 0) < 0) { 
     350                free(mbuf); 
     351                sipc_error(sipc, "msgsnd: %s\n", strerror(errno)); 
     352                return -1; 
    349353        } 
    350354        free(mbuf); 
     
    356360static int is_end_xmit(struct msgbuf *mbuf) 
    357361{ 
    358         if (mbuf->mtype == SIPC_END_XMIT) 
    359                 return 1; 
    360  
    361         return 0; 
     362       if (mbuf->mtype == SIPC_END_XMIT) 
     363               return 1; 
     364 
     365       return 0; 
    362366} 
    363367 
     
    366370        if (mbuf->mtype == SIPC_MSG_LEN) 
    367371                return 1; 
    368          
     372 
    369373        return 0; 
    370374} 
     
    374378static int msg_done(sipc_t *sipc) 
    375379{ 
    376         return sipc->copied >= sipc->msg_len ? 1 : 0; 
    377 } 
    378  
    379  
    380 /* Splits data in sipc into a chunk the size of the maximum                                                   
    381  * allowed for a message in a message queue.  
     380       return sipc->copied >= sipc->msg_len ? 1 : 0; 
     381} 
     382 
     383 
     384/* Splits data in sipc into a chunk the size of the maximum 
     385 * allowed for a message in a message queue. 
    382386 * This function allocates space for the fragmented piece of data. 
    383387 * The caller is responsible for freeign this memory. */ 
     
    389393        if (!packet) 
    390394                return NULL; 
    391          
     395 
    392396        memcpy(packet, (sipc->data)+(sipc->copied), len); 
    393397        sipc->copied += len; 
    394          
     398 
    395399        return packet; 
    396400} 
    397401 
    398402/* Determine the next packet's size. 
    399  * A packet should not contain extra padding.  
     403 * A packet should not contain extra padding. 
    400404 * Returns the size of the next packet on success, -1 on failure. */ 
    401405static size_t next_packet_sz(int recv, int max_packet_sz, int msg_len) 
     
    404408                return -1; 
    405409 
    406         if (recv + max_packet_sz > msg_len)   
     410        if (recv + max_packet_sz > msg_len) 
    407411                return msg_len - recv; 
    408412        else 
    409413                return max_packet_sz; 
    410          
     414 
    411415} 
    412416 
     
    419423                return -1; 
    420424 
    421         if (need > msg_len)  
     425        if (need > msg_len) 
    422426                return max_packet_sz; 
    423427 
  • trunk/libsipc/src/sipc_shm.c

    r30 r34  
    187187        int mtype = 0; 
    188188         
    189         if (!sipc
     189        if (!sipc || !data || !len
    190190                return -1; 
    191191 
  • trunk/libsipc/tests/mqueue.c

    r33 r34  
    9797        char ipc_type_str[128]; 
    9898 
     99        /* Cleanup handle here */ 
     100        sipc_close(reader_ipc); 
     101        sipc_close(writer_ipc); 
     102 
    99103        /* Build the destroyer app's argv */ 
    100104        bzero(ipc_type_str, 128); 
     
    123127} 
    124128 
     129static void test_unforked_mqueue(void) { 
     130        static char message[] = "HELLO,"; 
     131        size_t message_len = sizeof(message); 
     132        char *data = sipc_get_data_ptr(writer_ipc); 
     133        int recv_len; 
     134        char *recv_data; 
     135 
     136        CU_ASSERT_PTR_NOT_NULL_FATAL(data); 
     137        strcpy(data, message); 
     138        CU_ASSERT(sipc_send_data(writer_ipc, message_len) == 0); 
     139        CU_ASSERT(sipc_recv_data(reader_ipc, &recv_data, &recv_len) == 0); 
     140        CU_ASSERT(recv_len >= message_len); 
     141        CU_ASSERT(memcmp(recv_data, message, message_len) == 0); 
     142        CU_ASSERT(sipc_shm_recv_done(reader_ipc) == 0); 
     143} 
     144 
    125145static void test_mqueue(void) 
    126146{ 
     
    133153                return; 
    134154        case 0: 
     155                sipc_close(reader_ipc); 
    135156                do_child(); 
    136157                exit(0); 
     
    145166 
    146167CU_TestInfo mqueue_tests[] = { 
    147         {"mqueue", test_mqueue} 
     168        {"unforked mqueue", test_unforked_mqueue}, 
     169        {"forked mqueue", test_mqueue} 
    148170        , 
    149171        CU_TEST_INFO_NULL 
     
    164186                        break; 
    165187        } 
    166  
    167         /* Cleanup handle here */ 
    168         sipc_close(reader_ipc); 
    169188} 
    170189 
  • trunk/libsipc/tests/test_ipc.c

    r33 r34  
    4646               CU_get_number_of_suites_run(), 
    4747               CU_get_number_of_tests_run()); 
    48 err: 
     48 
    4949        CU_cleanup_registry(); 
    5050        return CU_get_error();