From patchwork Sun Jan 30 04:39:14 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Linus_L=C3=BCssing?= X-Patchwork-Id: 820 Return-Path: Received: from fmmailgate01.web.de (fmmailgate01.web.de [217.72.192.221]) by open-mesh.org (Postfix) with ESMTP id 20FFC154630 for ; Sun, 30 Jan 2011 05:39:43 +0100 (CET) Received: from smtp08.web.de ( [172.20.5.216]) by fmmailgate01.web.de (Postfix) with ESMTP id 0D30E1867F446; Sun, 30 Jan 2011 05:39:43 +0100 (CET) Received: from [46.126.246.98] (helo=localhost) by smtp08.web.de with asmtp (TLSv1:AES128-SHA:128) (WEB.DE 4.110 #2) id 1PjP4g-0007Kp-00; Sun, 30 Jan 2011 05:39:42 +0100 From: =?UTF-8?q?Linus=20L=C3=BCssing?= To: b.a.t.m.a.n@lists.open-mesh.org Date: Sun, 30 Jan 2011 05:39:14 +0100 Message-Id: <1296362366-3852-7-git-send-email-linus.luessing@saxnet.de> X-Mailer: git-send-email 1.7.2.3 In-Reply-To: <1296362366-3852-1-git-send-email-linus.luessing@saxnet.de> References: <1296362366-3852-1-git-send-email-linus.luessing@saxnet.de> MIME-Version: 1.0 Sender: linus.luessing@web.de X-Sender: linus.luessing@web.de X-Provags-ID: V01U2FsdGVkX1++Y1f4YjjaPs8MEyhajqCRnPkjXE56XL+Dzg5G 35rttMy5BIvTPsSfr6cliTlZxQa/oC7WS0wmpl8xVBo+wXL5ml 48JxhY/nuFKuGQER4cFQ== Cc: =?UTF-8?q?Linus=20L=C3=BCssing?= Subject: [B.A.T.M.A.N.] [PATCH 06/18] batman-adv: Add length check for (received) tracker packets X-BeenThere: b.a.t.m.a.n@lists.open-mesh.org X-Mailman-Version: 2.1.11 Precedence: list Reply-To: The list for a Better Approach To Mobile Ad-hoc Networking List-Id: The list for a Better Approach To Mobile Ad-hoc Networking List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 30 Jan 2011 04:39:43 -0000 Before/while a tracker packet is being searched for next hops for its destination entries, it will also be checked if the number of destination and mcast entries might exceed the tracker_packet_len. Otherwise we might read/write in unallocated memory. Such a broken tracker packet could potentially occure when we are going to reuse route_mcast_tracker_packet for tracker packets received from a neighbour node. In such a case, we are just reducing the stated mcast / dest numbers in the tracker packet to fit the size of the allocated buffer. Signed-off-by: Linus Lüssing --- multicast.c | 25 +++++++++++++++++++++++-- 1 files changed, 23 insertions(+), 2 deletions(-) diff --git a/batman-adv/multicast.c b/batman-adv/multicast.c index f414394..ffeb800 100644 --- a/batman-adv/multicast.c +++ b/batman-adv/multicast.c @@ -403,17 +403,38 @@ out: return ret; } -/* Collect nexthops for all dest entries specified in this tracker packet */ +/* Collect nexthops for all dest entries specified in this tracker packet. + * It also reduces the number of elements in the tracker packet if they exceed + * the buffers length (e.g. because of a received, broken tracker packet) to + * avoid writing in unallocated memory. */ static int tracker_next_hops(struct mcast_tracker_packet *tracker_packet, + int tracker_packet_len, struct dest_entries_list *next_hops, struct bat_priv *bat_priv) { int num_next_hops = 0, ret; struct tracker_packet_state state; + uint8_t *tail = (uint8_t *)tracker_packet + tracker_packet_len; INIT_LIST_HEAD(&next_hops->list); tracker_packet_for_each_dest(&state, tracker_packet) { + /* avoid writing outside of unallocated memory later */ + if (state.dest_entry + ETH_ALEN > tail) { + bat_dbg(DBG_BATMAN, bat_priv, + "mcast tracker packet is broken, too many " + "entries claimed for its length, repairing"); + + tracker_packet->num_mcast_entries = state.mcast_num; + + if (state.dest_num) { + tracker_packet->num_mcast_entries++; + state.mcast_entry->num_dest = state.dest_num; + } + + break; + } + ret = add_router_of_dest(next_hops, state.dest_entry, bat_priv); if (!ret) @@ -521,7 +542,7 @@ void route_mcast_tracker_packet(struct sk_buff *skb, int num_next_hops; num_next_hops = tracker_next_hops((struct mcast_tracker_packet*) - skb->data, &next_hops, bat_priv); + skb->data, skb->len, &next_hops, bat_priv); if (!num_next_hops) return;