From 4975b3167a7524042fe9f683788c955112a6b345 Mon Sep 17 00:00:00 2001 From: Michael Blizek Date: Sun, 20 Dec 2009 14:22:30 +0100 Subject: [PATCH] memory corruption bugfixes --- net/cor/common.c | 18 ++++--- net/cor/cpacket_parse.c | 136 ++++++++++++++++++++++++------------------------ net/cor/neighbor.c | 33 ++---------- net/cor/sock.c | 2 +- 4 files changed, 84 insertions(+), 105 deletions(-) diff --git a/net/cor/common.c b/net/cor/common.c index 43f42fe0935..fbda8c46368 100644 --- a/net/cor/common.c +++ b/net/cor/common.c @@ -287,6 +287,8 @@ found: return 0; } +#define PAGESIZE (1 << PAGE_SHIFT) + static int ringbuffer_init(struct ringbuffer *buf) { int i; @@ -296,7 +298,7 @@ static int ringbuffer_init(struct ringbuffer *buf) memset(buf, 0, sizeof(struct ringbuffer)); for (i=0;ibuffers[i] = (char *) alloc_page(GFP_KERNEL); + buf->buffers[i] = kmalloc(PAGESIZE, GFP_KERNEL); if (buf->buffers[i] == 0) goto out_err; } @@ -304,8 +306,9 @@ static int ringbuffer_init(struct ringbuffer *buf) return 0; out_err: + printk(KERN_ERR "ringbuffer init failed (oom?)"); while (--i >= 0){ - free_page((unsigned long) (buf->buffers[i])); + kfree(buf->buffers[i]); } memset(buf, 0, sizeof(struct ringbuffer)); @@ -319,13 +322,10 @@ static void ringbuffer_destroy(struct ringbuffer *buf) for (i=0;ibuffers[i] == 0) continue; - - free_page((unsigned long) (buf->buffers[i])); + kfree(buf->buffers[i]); } } -#define PAGESIZE (1 << PAGE_SHIFT) - int ringbuffer_put(struct ringbuffer *buf, char *src, int len, int usercopy) { __u32 maxwrite = (buf->read_offset - buf->write_offset - 1 + @@ -534,15 +534,19 @@ void conn_init_sock_source(struct conn *conn) void conn_init_sock_target(struct conn *conn) { + int rc; + BUG_ON(conn == 0); conn->targettype = TARGET_SOCK; memset(&(conn->target.sock), 0, sizeof(conn->target.sock)); + #warning todo check rc + rc = ringbuffer_init(&(conn->target.sock.rbuf)); + mutex_init(&(conn->target.sock.lock)); init_waitqueue_head(&(conn->target.sock.wait)); - ringbuffer_init(&(conn->target.sock.rbuf)); skb_queue_head_init(&(conn->target.sock.queue)); } diff --git a/net/cor/cpacket_parse.c b/net/cor/cpacket_parse.c index e90af249d7e..e4211b09984 100644 --- a/net/cor/cpacket_parse.c +++ b/net/cor/cpacket_parse.c @@ -82,29 +82,29 @@ static void send_resp(struct conn *conn, __u16 respcode, } } -static void send_resp_bin(struct conn *conn, char *data, __u32 len) +static void send_resp_bin(struct conn *rconn, char *buf, __u32 len) { - struct conn *rconn = conn->reversedir; + struct conn *sconn = rconn->reversedir; __u32 code = cpu_to_be16(CDR_BINDATA); __u32 len_be = cpu_to_be32(len); - if (rconn->targettype == TARGET_SOCK) { - mutex_lock(&(rconn->target.sock.lock)); - ringbuffer_put(&(rconn->target.sock.rbuf), + if (sconn->targettype == TARGET_SOCK) { + mutex_lock(&(sconn->target.sock.lock)); + ringbuffer_put(&(sconn->target.sock.rbuf), (char *) &code, 2, 0); - ringbuffer_put(&(rconn->target.sock.rbuf), + ringbuffer_put(&(sconn->target.sock.rbuf), (char *) &len_be, 4, 0); - ringbuffer_put(&(rconn->target.sock.rbuf), data, len, 0); - mutex_unlock(&(rconn->target.sock.lock)); - } else if (rconn->targettype == TARGET_OUT) { + ringbuffer_put(&(sconn->target.sock.rbuf), buf, len, 0); + mutex_unlock(&(sconn->target.sock.lock)); + } else if (sconn->targettype == TARGET_OUT) { #warning todo } else { BUG(); } } -static void parse_list_neigh(struct conn *conn) +static void parse_list_neigh(struct conn *rconn) { __u32 limit; __u32 offset; @@ -112,20 +112,20 @@ static void parse_list_neigh(struct conn *conn) char *buf; - if (conn->target.unconnected.paramlen < 8) { - send_resp(conn, CDR_EXECFAILED, CDR_EXECFAILED_CMD_TOO_SHORT); + if (rconn->target.unconnected.paramlen < 8) { + send_resp(rconn, CDR_EXECFAILED, CDR_EXECFAILED_CMD_TOO_SHORT); return; } - ((char *)&limit)[0] = conn->target.unconnected.cmdparams[0]; - ((char *)&limit)[1] = conn->target.unconnected.cmdparams[1]; - ((char *)&limit)[2] = conn->target.unconnected.cmdparams[2]; - ((char *)&limit)[3] = conn->target.unconnected.cmdparams[3]; + ((char *)&limit)[0] = rconn->target.unconnected.cmdparams[0]; + ((char *)&limit)[1] = rconn->target.unconnected.cmdparams[1]; + ((char *)&limit)[2] = rconn->target.unconnected.cmdparams[2]; + ((char *)&limit)[3] = rconn->target.unconnected.cmdparams[3]; - ((char *)&offset)[0] = conn->target.unconnected.cmdparams[4]; - ((char *)&offset)[1] = conn->target.unconnected.cmdparams[5]; - ((char *)&offset)[2] = conn->target.unconnected.cmdparams[6]; - ((char *)&offset)[3] = conn->target.unconnected.cmdparams[7]; + ((char *)&offset)[0] = rconn->target.unconnected.cmdparams[4]; + ((char *)&offset)[1] = rconn->target.unconnected.cmdparams[5]; + ((char *)&offset)[2] = rconn->target.unconnected.cmdparams[6]; + ((char *)&offset)[3] = rconn->target.unconnected.cmdparams[7]; limit = be32_to_cpu(limit); offset = be32_to_cpu(offset); @@ -133,47 +133,47 @@ static void parse_list_neigh(struct conn *conn) buf = kmalloc(2048, GFP_KERNEL); if (unlikely(buf == 0)) { - send_resp(conn, CDR_EXECFAILED, + send_resp(rconn, CDR_EXECFAILED, CDR_EXECFAILED_TEMPORARILY_OUT_OF_RESSOURCES); return; } - send_resp(conn, CDR_EXECOK, CDR_EXECOK_OK); + send_resp(rconn, CDR_EXECOK, CDR_EXECOK_OK); len = generate_neigh_list(buf, 2048, limit, offset); - send_resp_bin(conn, buf, len); + send_resp_bin(rconn, buf, len); } -static void parse_connect_port(struct conn *conn) +static void parse_connect_port(struct conn *rconn) { __be64 addr; int rc; - BUG_ON(0 == conn->target.unconnected.cmdparams); + BUG_ON(0 == rconn->target.unconnected.cmdparams); - if (conn->target.unconnected.paramlen < 8) { - send_resp(conn, CDR_EXECFAILED, CDR_EXECFAILED_CMD_TOO_SHORT); + if (rconn->target.unconnected.paramlen < 8) { + send_resp(rconn, CDR_EXECFAILED, CDR_EXECFAILED_CMD_TOO_SHORT); return; } - memcpy((char *) &addr, conn->target.unconnected.cmdparams, 8); + memcpy((char *) &addr, rconn->target.unconnected.cmdparams, 8); - rc = connect_port(conn, addr); + rc = connect_port(rconn, addr); if (rc == 2) { - send_resp(conn, CDR_EXECFAILED, + send_resp(rconn, CDR_EXECFAILED, CDR_EXECFAILED_TARGETADDR_DOESNTEXIST); } else if (rc != 3) { - send_resp(conn, CDR_EXECFAILED, + send_resp(rconn, CDR_EXECFAILED, CDR_EXECFAILED_LISTENERQUEUE_FULL); } else if (rc == 0) { - send_resp(conn, CDR_EXECOK, CDR_EXECOK_OK); + send_resp(rconn, CDR_EXECOK, CDR_EXECOK_OK); } else if (unlikely(rc != 0)) { BUG(); } } -static void parse_connect_nb(struct conn *conn) +static void parse_connect_nb(struct conn *rconn) { __u16 addrtypelen; __u16 addrlen; @@ -181,61 +181,61 @@ static void parse_connect_nb(struct conn *conn) __u8 *addr; int rc; - BUG_ON(0 == conn->target.unconnected.cmdparams); + BUG_ON(0 == rconn->target.unconnected.cmdparams); - if (conn->target.unconnected.paramlen < 4) { - send_resp(conn, CDR_EXECFAILED, CDR_EXECFAILED_CMD_TOO_SHORT); + if (rconn->target.unconnected.paramlen < 4) { + send_resp(rconn, CDR_EXECFAILED, CDR_EXECFAILED_CMD_TOO_SHORT); return; } - ((char *)&addrtypelen)[0] = conn->target.unconnected.cmdparams[0]; - ((char *)&addrtypelen)[1] = conn->target.unconnected.cmdparams[1]; + ((char *)&addrtypelen)[0] = rconn->target.unconnected.cmdparams[0]; + ((char *)&addrtypelen)[1] = rconn->target.unconnected.cmdparams[1]; - ((char *)&addrlen)[0] = conn->target.unconnected.cmdparams[2]; - ((char *)&addrlen)[1] = conn->target.unconnected.cmdparams[3]; + ((char *)&addrlen)[0] = rconn->target.unconnected.cmdparams[2]; + ((char *)&addrlen)[1] = rconn->target.unconnected.cmdparams[3]; addrtypelen = be16_to_cpu(addrtypelen); addrlen = be16_to_cpu(addrlen); if ((4 + (__u32) addrtypelen + (__u32) addrlen) > - conn->target.unconnected.paramlen) { - send_resp(conn, CDR_EXECFAILED, CDR_EXECFAILED_CMD_TOO_SHORT); + rconn->target.unconnected.paramlen) { + send_resp(rconn, CDR_EXECFAILED, CDR_EXECFAILED_CMD_TOO_SHORT); return; } - addrtype = conn->target.unconnected.cmdparams + 4; + addrtype = rconn->target.unconnected.cmdparams + 4; addr = addrtype + addrtypelen; - rc = connect_neigh(conn, addrtypelen, addrtype, addrlen, addr); + rc = connect_neigh(rconn, addrtypelen, addrtype, addrlen, addr); if (rc == 2) { - send_resp(conn, CDR_EXECFAILED, + send_resp(rconn, CDR_EXECFAILED, CDR_EXECFAILED_TARGETADDRTYPE_UNKNOWN); } else if (rc == 3) { - send_resp(conn, CDR_EXECFAILED, + send_resp(rconn, CDR_EXECFAILED, CDR_EXECFAILED_TARGETADDR_DOESNTEXIST); } else if (rc == 4) { - send_resp(conn, CDR_EXECFAILED, + send_resp(rconn, CDR_EXECFAILED, CDR_EXECFAILED_TEMPORARILY_OUT_OF_RESSOURCES); } else if (rc == 0) { - send_resp(conn, CDR_EXECOK, CDR_EXECOK_OK); + send_resp(rconn, CDR_EXECOK, CDR_EXECOK_OK); } else if (unlikely(rc != 0)) { BUG(); } } -static void parse_cmd(struct conn *conn) +static void parse_cmd(struct conn *rconn) { - __u16 code = conn->target.unconnected.cmd; + __u16 code = rconn->target.unconnected.cmd; if (code == CD_CONNECT_NB) { - parse_connect_nb(conn); + parse_connect_nb(rconn); } else if (code == CD_CONNECT_PORT) { - parse_connect_port(conn); + parse_connect_port(rconn); } else if (code == CD_LIST_NEIGH) { - parse_list_neigh(conn); + parse_list_neigh(rconn); } else { - send_resp(conn, CDR_EXECFAILED, CDR_EXECFAILED_UNKNOWN_COMMAND); + send_resp(rconn, CDR_EXECFAILED, CDR_EXECFAILED_UNKNOWN_COMMAND); } } @@ -289,12 +289,12 @@ static void read_hdr(struct data *data, struct conn *rconn) char *buf; int readoffset; int pull; - + pull = min(6 - rconn->target.unconnected.cmdread, data_len(data)); - + if (pull == 0) return; - + BUG_ON(pull < 0); buf = data_pull(data, pull); @@ -318,23 +318,23 @@ static void read_hdr(struct data *data, struct conn *rconn) void parse(struct data *data, struct conn *rconn) { __u8 *cmd; - + BUG_ON(TARGET_UNCONNECTED != rconn->targettype); - - if (0 == rconn->target.unconnected.cmdparams) + + if (rconn->target.unconnected.cmdparams == 0) rconn->target.unconnected.cmdparams = kmalloc(MAX_CONN_CMD_LEN, GFP_KERNEL); - + cmd = rconn->target.unconnected.cmdparams; - if (0 == rconn->target.unconnected.cmdread) { + if (rconn->target.unconnected.cmdread == 0) { rconn->target.unconnected.cmd = 0; rconn->target.unconnected.paramlen = 0; } - if (6 > rconn->target.unconnected.cmdread) { + if (rconn->target.unconnected.cmdread < 6) { read_hdr(data, rconn); - if (6 > rconn->target.unconnected.cmdread) + if (rconn->target.unconnected.cmdread < 6) return; if (rconn->target.unconnected.paramlen > MAX_CONN_CMD_LEN) { @@ -342,18 +342,18 @@ void parse(struct data *data, struct conn *rconn) CDR_EXECFAILED_CMD_TOO_LONG); } } - + if (rconn->target.unconnected.paramlen > MAX_CONN_CMD_LEN) { read_discard(data, rconn); return; } - - if (6 <= rconn->target.unconnected.cmdread && + + if (rconn->target.unconnected.cmdread >= 6 && rconn->target.unconnected.paramlen > rconn->target.unconnected.cmdread - 6) { read_cmd(data, rconn); } - + if (rconn->target.unconnected.paramlen == rconn->target.unconnected.cmdread - 6) { rconn->target.unconnected.cmdread = 0; diff --git a/net/cor/neighbor.c b/net/cor/neighbor.c index 29ad4b6aa54..51819191a6a 100644 --- a/net/cor/neighbor.c +++ b/net/cor/neighbor.c @@ -208,7 +208,7 @@ __u32 generate_neigh_list(char *buf, __u32 buflen, __u32 limit, __u32 offset) if (total != cnt) goto cont; - if (buflen - buf_offset - 6 - 2 - curr->addrlen < 0) + if (unlikely(buflen - buf_offset - 6 - 2 - curr->addrlen < 0)) goto cont; put_u16(buf + buf_offset, 1, 1);/* numaddr */ @@ -222,7 +222,7 @@ __u32 generate_neigh_list(char *buf, __u32 buflen, __u32 limit, __u32 offset) buf[buf_offset] = 'd'; buf_offset += 1; memcpy(buf + buf_offset, curr->addr, curr->addrlen); /* addr */ - buf_offset += curr->addrlen; + buf_offset += curr->addrlen; BUG_ON(buf_offset > buflen); @@ -357,7 +357,6 @@ static void apply_announce_cmds(char *msg, __u32 len, struct net_device *dev, static int check_announce_cmds(char *msg, __u32 len) { - printk(KERN_ERR "check %d %d", (int) msg, len); while (len >= 8) { __u32 cmd; __u32 cmdlen; @@ -391,8 +390,6 @@ static void parse_announce(char *msg, __u32 len, struct net_device *dev, __u32 min_cor_version; __u32 max_cor_version; - printk(KERN_ERR "parse_announce"); - if (len < 16) return; @@ -409,18 +406,13 @@ static void parse_announce(char *msg, __u32 len, struct net_device *dev, msg += 4; len -= 4; - printk(KERN_ERR "merge_announce1"); if (min_announce_version != 0) return; if (min_cor_version != 0) return; - /*printk(KERN_ERR "merge_announce2");*/ - printk(KERN_ERR "check %d %d", (int) msg, len); if (check_announce_cmds(msg, len)) { - printk(KERN_ERR "merge_announce2 err"); return; } - printk(KERN_ERR "merge_announce3"); apply_announce_cmds(msg, len, dev, source_hw); } @@ -443,13 +435,9 @@ struct kmem_cache *announce_in_slab; static void merge_announce(struct announce_in *ann) { - printk(KERN_ERR "merge_announce0 %d", (int) ann); - printk(KERN_ERR "merge_announce0.5 %d", ann->total_size); - char *msg = kmalloc(GFP_KERNEL, ann->total_size); + char *msg = kmalloc(ann->total_size, GFP_KERNEL); __u32 copy = 0; - printk(KERN_ERR "merge_announce"); - if (msg == 0) { /* try again when next packet arrives */ return; @@ -500,8 +488,6 @@ static int _rcv_announce(struct sk_buff *skb, struct announce_in *ann) __u32 prevoffset = 0; __u32 prevlen = 0; - printk(KERN_ERR "rcv_announce2"); - struct sk_buff *curr = ann->skbs.next; if (len + offset > ann->total_size) { @@ -538,8 +524,6 @@ static int _rcv_announce(struct sk_buff *skb, struct announce_in *ann) } } - printk(KERN_ERR "rcv_announce3"); - /** * Calculate how much data was really received, by substracting * the bytes we already have. @@ -553,30 +537,21 @@ static int _rcv_announce(struct sk_buff *skb, struct announce_in *ann) (offset + len) > curroffset)) len = curroffset - offset; - printk(KERN_ERR "rcv_announce4"); - ann->received_size += len; BUG_ON(ann->received_size > ann->total_size); __skb_queue_before(&(ann->skbs), curr, skb); ann->last_received_packet = get_jiffies_64(); - printk(KERN_ERR "rcv_announce5"); - if (ann->received_size == ann->total_size) merge_announce(ann); - else if (ann->skbs.qlen >= 16) { - printk(KERN_ERR "rcv_announce7"); + else if (ann->skbs.qlen >= 16) return 1; - } - - printk(KERN_ERR "rcv_announce6"); return 0; } void rcv_announce(struct sk_buff *skb) { - printk(KERN_ERR "rcv_announce"); struct skb_procstate *ps = skb_pstate(skb); struct announce_in *curr = 0; struct announce_in *leastactive = 0; diff --git a/net/cor/sock.c b/net/cor/sock.c index 14e820e2de3..1103f1902f3 100644 --- a/net/cor/sock.c +++ b/net/cor/sock.c @@ -461,7 +461,7 @@ int cor_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, break; } - if (sconn->sourcetype == TARGET_UNCONNECTED) { + if (sconn->sourcetype == SOURCE_NONE) { copied = -EPIPE; break; } -- 2.11.4.GIT