aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2009-09-03 02:09:29 -0400
committerDavid S. Miller <davem@davemloft.net>2009-09-03 02:45:58 -0400
commit3eb0027594e25f5947f074ae53fea30c15c5a7f6 (patch)
tree44c996526d1957051f35889ee0eb5f560311da6f
parentab08999d6029bb2c79c16be5405d63d2bedbdfea (diff)
NET: Fix possible corruption in bpqether driver
The bpq ether driver is modifying the data art of the skb by first dropping the KISS byte (a command byte for the radio) then prepending the length + 4 of the remaining AX.25 packet to be transmitted as a little endian 16-bit number. If the high byte of the length has a different value than the dropped KISS byte users of clones of the skb may observe this as corruption. This was observed with by running listen(8) -a which uses a packet socket which clones transmit packets. The corruption will then typically be displayed for as a KISS "TX Delay" command for AX.25 packets in the range of 252..508 bytes or any other KISS command for yet larger packets. Fixed by using skb_cow to create a private copy should the skb be cloned. Using skb_cow also allows us to cleanup the old logic to ensure sufficient headroom in the skb. While at it, replace a return of 0 from bpq_xmit with the proper constant NETDEV_TX_OK which is now being used everywhere else in this function. Affected: all 2.2, 2.4 and 2.6 kernels. Signed-off-by: Ralf Baechle <ralf@linux-mips.org> Reported-by: Jann Traschewski <jann@gmx.de> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/hamradio/bpqether.c26
1 files changed, 10 insertions, 16 deletions
diff --git a/drivers/net/hamradio/bpqether.c b/drivers/net/hamradio/bpqether.c
index 3c7cc7f45800..fe893c91a01b 100644
--- a/drivers/net/hamradio/bpqether.c
+++ b/drivers/net/hamradio/bpqether.c
@@ -249,7 +249,6 @@ drop:
249 */ 249 */
250static netdev_tx_t bpq_xmit(struct sk_buff *skb, struct net_device *dev) 250static netdev_tx_t bpq_xmit(struct sk_buff *skb, struct net_device *dev)
251{ 251{
252 struct sk_buff *newskb;
253 unsigned char *ptr; 252 unsigned char *ptr;
254 struct bpqdev *bpq; 253 struct bpqdev *bpq;
255 int size; 254 int size;
@@ -263,28 +262,23 @@ static netdev_tx_t bpq_xmit(struct sk_buff *skb, struct net_device *dev)
263 return NETDEV_TX_OK; 262 return NETDEV_TX_OK;
264 } 263 }
265 264
266 skb_pull(skb, 1); 265 skb_pull(skb, 1); /* Drop KISS byte */
267 size = skb->len; 266 size = skb->len;
268 267
269 /* 268 /*
270 * The AX.25 code leaves enough room for the ethernet header, but 269 * We're about to mess with the skb which may still shared with the
271 * sendto() does not. 270 * generic networking code so unshare and ensure it's got enough
271 * space for the BPQ headers.
272 */ 272 */
273 if (skb_headroom(skb) < AX25_BPQ_HEADER_LEN) { /* Ough! */ 273 if (skb_cow(skb, AX25_BPQ_HEADER_LEN)) {
274 if ((newskb = skb_realloc_headroom(skb, AX25_BPQ_HEADER_LEN)) == NULL) { 274 if (net_ratelimit())
275 printk(KERN_WARNING "bpqether: out of memory\n"); 275 pr_err("bpqether: out of memory\n");
276 kfree_skb(skb);
277 return NETDEV_TX_OK;
278 }
279
280 if (skb->sk != NULL)
281 skb_set_owner_w(newskb, skb->sk);
282
283 kfree_skb(skb); 276 kfree_skb(skb);
284 skb = newskb; 277
278 return NETDEV_TX_OK;
285 } 279 }
286 280
287 ptr = skb_push(skb, 2); 281 ptr = skb_push(skb, 2); /* Make space for length */
288 282
289 *ptr++ = (size + 5) % 256; 283 *ptr++ = (size + 5) % 256;
290 *ptr++ = (size + 5) / 256; 284 *ptr++ = (size + 5) / 256;