Changeset 34
- 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
| r33 |
r34 |
|
| 7 | 7 | |
|---|
| 8 | 8 | ifeq ($(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 |
|---|
| 10 | 11 | LDFLAGS ?= -g |
|---|
| 11 | 12 | else |
|---|
| | 13 | # if no DEBUG and no CFLAGS are already set, then compile with -O3 |
|---|
| 12 | 14 | CFLAGS ?= -O3 |
|---|
| 13 | 15 | endif |
|---|
| … | … | |
| 33 | 35 | ALL_SUBDIRS = src include bindings/java examples man tests |
|---|
| 34 | 36 | |
|---|
| | 37 | C_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 | |
|---|
| 35 | 39 | all: |
|---|
| 36 | 40 | for i in $(SUBDIRS) ; do \ |
|---|
| … | … | |
| 55 | 59 | $(MAKE) -C bindings/java $@ |
|---|
| 56 | 60 | |
|---|
| | 61 | indent: |
|---|
| | 62 | find src include tests \ |
|---|
| | 63 | \( -name '*.[ch]' -type f -exec indent $(C_INDENT_OPTS) '{}' \; \) |
|---|
| | 64 | |
|---|
| 57 | 65 | clean: |
|---|
| 58 | 66 | for i in $(ALL_SUBDIRS) ; do \ |
|---|
| … | … | |
| 60 | 68 | done |
|---|
| 61 | 69 | |
|---|
| 62 | | .PHONY: all example test install install-example javadoc clean |
|---|
| | 70 | .PHONY: all example tests install install-example javadoc indent clean |
|---|
| r27 |
r34 |
|
| 1 | 1 | /* Author: David Windsor <dwindsor@tresys.com> |
|---|
| 2 | | * |
|---|
| | 2 | * |
|---|
| 3 | 3 | * Copyright (C) 2006, 2007 Tresys Technology, LLC |
|---|
| 4 | 4 | * Developed Under US JFCOM Sponsorship |
|---|
| … | … | |
| 37 | 37 | |
|---|
| 38 | 38 | /* 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" |
|---|
| 40 | 40 | |
|---|
| 41 | 41 | static struct sipc_func_table mqueue_funcs = { |
|---|
| … | … | |
| 72 | 72 | if (SIPC_MQUEUE_MSG_SZ < 0) |
|---|
| 73 | 73 | 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. |
|---|
| 79 | 79 | * This function should only be called by a helper application |
|---|
| 80 | 80 | * and not by the sender or reciever. */ |
|---|
| 81 | 81 | int sipc_mqueue_create(sipc_t *sipc) |
|---|
| 82 | 82 | { |
|---|
| 83 | | int msqid; |
|---|
| | 83 | int msqid; |
|---|
| 84 | 84 | |
|---|
| 85 | 85 | msqid = mqueue_create(sipc->key); |
|---|
| … | … | |
| 95 | 95 | void sipc_mqueue_detach(sipc_t *sipc) |
|---|
| 96 | 96 | { |
|---|
| 97 | | free(sipc->data); |
|---|
| | 97 | free(sipc->data); |
|---|
| 98 | 98 | sipc->data = NULL; |
|---|
| 99 | 99 | } |
|---|
| … | … | |
| 116 | 116 | return -1; |
|---|
| 117 | 117 | } |
|---|
| 118 | | |
|---|
| | 118 | |
|---|
| 119 | 119 | return 0; |
|---|
| 120 | 120 | } |
|---|
| … | … | |
| 135 | 135 | |
|---|
| 136 | 136 | 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); |
|---|
| 140 | 140 | if (!mbuf) { |
|---|
| 141 | 141 | sipc_error(sipc, "%s\n", "Out of memory"); |
|---|
| … | … | |
| 153 | 153 | sipc_error(sipc, "%s\n", "Unable to fragment message data"); |
|---|
| 154 | 154 | goto err; |
|---|
| 155 | | } |
|---|
| 156 | | |
|---|
| | 155 | } |
|---|
| | 156 | |
|---|
| 157 | 157 | bzero(mbuf->mtext, packet_sz); |
|---|
| 158 | | mbuf->mtype = SIPC_SYSV_MQUEUES; |
|---|
| | 158 | mbuf->mtype = SIPC_DATA_READY; |
|---|
| 159 | 159 | memcpy(mbuf->mtext, packet, packet_sz); |
|---|
| 160 | | |
|---|
| | 160 | |
|---|
| 161 | 161 | /* Send the message */ |
|---|
| 162 | 162 | if (msgsnd(sipc->msqid, mbuf, packet_sz, 0) < 0) { |
|---|
| 163 | 163 | sipc_error(sipc, "msgsnd: %s\n", strerror(errno)); |
|---|
| 164 | 164 | goto err; |
|---|
| 165 | | } |
|---|
| 166 | | free(packet); |
|---|
| | 165 | } |
|---|
| | 166 | free(packet); |
|---|
| 167 | 167 | } while (!msg_done(sipc)); |
|---|
| 168 | 168 | |
|---|
| … | … | |
| 179 | 179 | return -1; |
|---|
| 180 | 180 | } |
|---|
| 181 | | |
|---|
| | 181 | |
|---|
| 182 | 182 | int sipc_mqueue_recv_data(sipc_t *sipc, char **data, int *len) |
|---|
| 183 | 183 | { |
|---|
| 184 | 184 | 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); |
|---|
| 186 | 186 | struct msgbuf *mbuf = NULL; |
|---|
| 187 | 187 | |
|---|
| 188 | | if (!data) |
|---|
| | 188 | if (!sipc || !data || !len) |
|---|
| 189 | 189 | goto err; |
|---|
| 190 | 190 | if (sipc->role != SIPC_RECEIVER) { |
|---|
| … | … | |
| 192 | 192 | goto err; |
|---|
| 193 | 193 | } |
|---|
| 194 | | |
|---|
| | 194 | |
|---|
| 195 | 195 | mbuf = calloc(1, SIPC_MQUEUE_MSG_SZ); |
|---|
| 196 | 196 | if (!mbuf) { |
|---|
| … | … | |
| 205 | 205 | /* Receive and validate the length of message marker */ |
|---|
| 206 | 206 | 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) { |
|---|
| 208 | 208 | sipc_error(sipc, "msgrcv: %s\n", strerror(errno)); |
|---|
| 209 | 209 | goto err; |
|---|
| … | … | |
| 228 | 228 | } |
|---|
| 229 | 229 | } |
|---|
| 230 | | |
|---|
| 231 | | /* Receive the message payload. |
|---|
| | 230 | |
|---|
| | 231 | /* Receive the message payload. |
|---|
| 232 | 232 | * Stop when we have received the total number of bytes |
|---|
| 233 | 233 | * 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) { |
|---|
| 235 | 235 | sipc_error(sipc, "msgrcv: %s\n", strerror(errno)); |
|---|
| 236 | 236 | goto err; |
|---|
| 237 | 237 | } |
|---|
| 238 | | |
|---|
| | 238 | |
|---|
| 239 | 239 | *len += recv_sz; |
|---|
| 240 | 240 | 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, |
|---|
| 242 | 242 | * resize to +1 message */ |
|---|
| 243 | 243 | alloc_sz += next_alloc_sz(*len, recv_sz, msgtxt_sz, sipc->msg_len); |
|---|
| 244 | 244 | |
|---|
| 245 | 245 | char *tdata = realloc(*data, alloc_sz); |
|---|
| 246 | | if (!(*tdata)) { |
|---|
| | 246 | if (!tdata) { |
|---|
| 247 | 247 | sipc_error(sipc, "%s\n", "Out of memory"); |
|---|
| 248 | 248 | free(*data); |
|---|
| … | … | |
| 251 | 251 | } |
|---|
| 252 | 252 | *data = tdata; |
|---|
| 253 | | |
|---|
| | 253 | |
|---|
| 254 | 254 | /* memset(*data+idx, 0x0, recv_sz); */ |
|---|
| 255 | 255 | memcpy(*data+idx, mbuf->mtext, recv_sz); |
|---|
| 256 | 256 | idx += recv_sz; |
|---|
| 257 | | |
|---|
| | 257 | |
|---|
| 258 | 258 | /* Check to see if we have received the entire message */ |
|---|
| 259 | 259 | if (*len >= sipc->msg_len) |
|---|
| … | … | |
| 261 | 261 | |
|---|
| 262 | 262 | /* 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) { |
|---|
| 264 | 264 | sipc_error(sipc, "msgrcv: %s\n", strerror(errno)); |
|---|
| 265 | 265 | goto err; |
|---|
| … | … | |
| 268 | 268 | *len += recv_sz; |
|---|
| 269 | 269 | } |
|---|
| 270 | | |
|---|
| | 270 | |
|---|
| 271 | 271 | retv = 0; |
|---|
| 272 | 272 | err: |
|---|
| … | … | |
| 277 | 277 | |
|---|
| 278 | 278 | void sipc_mqueue_error(const char *fmt, va_list ap) |
|---|
| 279 | | { |
|---|
| | 279 | { |
|---|
| 280 | 280 | vfprintf(stderr, fmt, ap); |
|---|
| 281 | 281 | } |
|---|
| … | … | |
| 296 | 296 | (void)fclose(f); |
|---|
| 297 | 297 | 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); |
|---|
| 303 | 303 | } |
|---|
| 304 | 304 | |
|---|
| 305 | 305 | /* Send end of transmission marker */ |
|---|
| 306 | 306 | static int mqueue_send_end_xmit(sipc_t *sipc) |
|---|
| 307 | | { |
|---|
| | 307 | { |
|---|
| 308 | 308 | 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) { |
|---|
| 312 | 313 | sipc_error(sipc, "msgsnd: %s\n", strerror(errno)); |
|---|
| 313 | 314 | return -1; |
|---|
| … | … | |
| 320 | 321 | static int qlog(int x) |
|---|
| 321 | 322 | { |
|---|
| 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; |
|---|
| 329 | 329 | } |
|---|
| 330 | 330 | |
|---|
| … | … | |
| 332 | 332 | { |
|---|
| 333 | 333 | 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 | } |
|---|
| 339 | 344 | |
|---|
| 340 | 345 | mbuf->mtype = SIPC_MSG_LEN; |
|---|
| … | … | |
| 342 | 347 | sprintf(mbuf->mtext, "%d", len); |
|---|
| 343 | 348 | |
|---|
| 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; |
|---|
| 349 | 353 | } |
|---|
| 350 | 354 | free(mbuf); |
|---|
| … | … | |
| 356 | 360 | static int is_end_xmit(struct msgbuf *mbuf) |
|---|
| 357 | 361 | { |
|---|
| 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; |
|---|
| 362 | 366 | } |
|---|
| 363 | 367 | |
|---|
| … | … | |
| 366 | 370 | if (mbuf->mtype == SIPC_MSG_LEN) |
|---|
| 367 | 371 | return 1; |
|---|
| 368 | | |
|---|
| | 372 | |
|---|
| 369 | 373 | return 0; |
|---|
| 370 | 374 | } |
|---|
| … | … | |
| 374 | 378 | static int msg_done(sipc_t *sipc) |
|---|
| 375 | 379 | { |
|---|
| 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. |
|---|
| 382 | 386 | * This function allocates space for the fragmented piece of data. |
|---|
| 383 | 387 | * The caller is responsible for freeign this memory. */ |
|---|
| … | … | |
| 389 | 393 | if (!packet) |
|---|
| 390 | 394 | return NULL; |
|---|
| 391 | | |
|---|
| | 395 | |
|---|
| 392 | 396 | memcpy(packet, (sipc->data)+(sipc->copied), len); |
|---|
| 393 | 397 | sipc->copied += len; |
|---|
| 394 | | |
|---|
| | 398 | |
|---|
| 395 | 399 | return packet; |
|---|
| 396 | 400 | } |
|---|
| 397 | 401 | |
|---|
| 398 | 402 | /* Determine the next packet's size. |
|---|
| 399 | | * A packet should not contain extra padding. |
|---|
| | 403 | * A packet should not contain extra padding. |
|---|
| 400 | 404 | * Returns the size of the next packet on success, -1 on failure. */ |
|---|
| 401 | 405 | static size_t next_packet_sz(int recv, int max_packet_sz, int msg_len) |
|---|
| … | … | |
| 404 | 408 | return -1; |
|---|
| 405 | 409 | |
|---|
| 406 | | if (recv + max_packet_sz > msg_len) |
|---|
| | 410 | if (recv + max_packet_sz > msg_len) |
|---|
| 407 | 411 | return msg_len - recv; |
|---|
| 408 | 412 | else |
|---|
| 409 | 413 | return max_packet_sz; |
|---|
| 410 | | |
|---|
| | 414 | |
|---|
| 411 | 415 | } |
|---|
| 412 | 416 | |
|---|
| … | … | |
| 419 | 423 | return -1; |
|---|
| 420 | 424 | |
|---|
| 421 | | if (need > msg_len) |
|---|
| | 425 | if (need > msg_len) |
|---|
| 422 | 426 | return max_packet_sz; |
|---|
| 423 | 427 | |
|---|
| r30 |
r34 |
|
| 187 | 187 | int mtype = 0; |
|---|
| 188 | 188 | |
|---|
| 189 | | if (!sipc) |
|---|
| | 189 | if (!sipc || !data || !len) |
|---|
| 190 | 190 | return -1; |
|---|
| 191 | 191 | |
|---|
| r33 |
r34 |
|
| 97 | 97 | char ipc_type_str[128]; |
|---|
| 98 | 98 | |
|---|
| | 99 | /* Cleanup handle here */ |
|---|
| | 100 | sipc_close(reader_ipc); |
|---|
| | 101 | sipc_close(writer_ipc); |
|---|
| | 102 | |
|---|
| 99 | 103 | /* Build the destroyer app's argv */ |
|---|
| 100 | 104 | bzero(ipc_type_str, 128); |
|---|
| … | … | |
| 123 | 127 | } |
|---|
| 124 | 128 | |
|---|
| | 129 | static 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 | |
|---|
| 125 | 145 | static void test_mqueue(void) |
|---|
| 126 | 146 | { |
|---|
| … | … | |
| 133 | 153 | return; |
|---|
| 134 | 154 | case 0: |
|---|
| | 155 | sipc_close(reader_ipc); |
|---|
| 135 | 156 | do_child(); |
|---|
| 136 | 157 | exit(0); |
|---|
| … | … | |
| 145 | 166 | |
|---|
| 146 | 167 | CU_TestInfo mqueue_tests[] = { |
|---|
| 147 | | {"mqueue", test_mqueue} |
|---|
| | 168 | {"unforked mqueue", test_unforked_mqueue}, |
|---|
| | 169 | {"forked mqueue", test_mqueue} |
|---|
| 148 | 170 | , |
|---|
| 149 | 171 | CU_TEST_INFO_NULL |
|---|
| … | … | |
| 164 | 186 | break; |
|---|
| 165 | 187 | } |
|---|
| 166 | | |
|---|
| 167 | | /* Cleanup handle here */ |
|---|
| 168 | | sipc_close(reader_ipc); |
|---|
| 169 | 188 | } |
|---|
| 170 | 189 | |
|---|
| r33 |
r34 |
|
| 46 | 46 | CU_get_number_of_suites_run(), |
|---|
| 47 | 47 | CU_get_number_of_tests_run()); |
|---|
| 48 | | err: |
|---|
| | 48 | |
|---|
| 49 | 49 | CU_cleanup_registry(); |
|---|
| 50 | 50 | return CU_get_error(); |
|---|
Download in other formats:
* Generating other formats may take time.