diff options
author | Jarek Poplawski <jarkao2@gmail.com> | 2008-02-18 01:31:19 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-02-18 01:31:19 -0500 |
commit | f47b7257c7368698eabff6fd7b340071932af640 (patch) | |
tree | d3733ff661cda7c00478348293810b3aeec6a1af /net/ax25/ax25_out.c | |
parent | 9bf1d83e7ee653862ef740435a7f41e8fd6452a9 (diff) |
[AX25] ax25_out: check skb for NULL in ax25_kick()
According to some OOPS reports ax25_kick tries to clone NULL skbs
sometimes. It looks like a race with ax25_clear_queues(). Probably
there is no need to add more than a simple check for this yet.
Another report suggested there are probably also cases where ax25
->paclen == 0 can happen in ax25_output(); this wasn't confirmed
during testing but let's leave this debugging check for some time.
Reported-and-tested-by: Jann Traschewski <jann@gmx.de>
Signed-off-by: Jarek Poplawski <jarkao2@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ax25/ax25_out.c')
-rw-r--r-- | net/ax25/ax25_out.c | 13 |
1 files changed, 11 insertions, 2 deletions
diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c index 92b517af7260..bf706f83a5c9 100644 --- a/net/ax25/ax25_out.c +++ b/net/ax25/ax25_out.c | |||
@@ -117,6 +117,12 @@ void ax25_output(ax25_cb *ax25, int paclen, struct sk_buff *skb) | |||
117 | unsigned char *p; | 117 | unsigned char *p; |
118 | int frontlen, len, fragno, ka9qfrag, first = 1; | 118 | int frontlen, len, fragno, ka9qfrag, first = 1; |
119 | 119 | ||
120 | if (paclen < 16) { | ||
121 | WARN_ON_ONCE(1); | ||
122 | kfree_skb(skb); | ||
123 | return; | ||
124 | } | ||
125 | |||
120 | if ((skb->len - 1) > paclen) { | 126 | if ((skb->len - 1) > paclen) { |
121 | if (*skb->data == AX25_P_TEXT) { | 127 | if (*skb->data == AX25_P_TEXT) { |
122 | skb_pull(skb, 1); /* skip PID */ | 128 | skb_pull(skb, 1); /* skip PID */ |
@@ -251,8 +257,6 @@ void ax25_kick(ax25_cb *ax25) | |||
251 | if (start == end) | 257 | if (start == end) |
252 | return; | 258 | return; |
253 | 259 | ||
254 | ax25->vs = start; | ||
255 | |||
256 | /* | 260 | /* |
257 | * Transmit data until either we're out of data to send or | 261 | * Transmit data until either we're out of data to send or |
258 | * the window is full. Send a poll on the final I frame if | 262 | * the window is full. Send a poll on the final I frame if |
@@ -261,8 +265,13 @@ void ax25_kick(ax25_cb *ax25) | |||
261 | 265 | ||
262 | /* | 266 | /* |
263 | * Dequeue the frame and copy it. | 267 | * Dequeue the frame and copy it. |
268 | * Check for race with ax25_clear_queues(). | ||
264 | */ | 269 | */ |
265 | skb = skb_dequeue(&ax25->write_queue); | 270 | skb = skb_dequeue(&ax25->write_queue); |
271 | if (!skb) | ||
272 | return; | ||
273 | |||
274 | ax25->vs = start; | ||
266 | 275 | ||
267 | do { | 276 | do { |
268 | if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) { | 277 | if ((skbn = skb_clone(skb, GFP_ATOMIC)) == NULL) { |