aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/netfilter/core.c7
-rw-r--r--net/netfilter/nf_queue.c17
2 files changed, 15 insertions, 9 deletions
diff --git a/net/netfilter/core.c b/net/netfilter/core.c
index 91d66d2f8cd9..0c5b796ef527 100644
--- a/net/netfilter/core.c
+++ b/net/netfilter/core.c
@@ -181,8 +181,11 @@ next_hook:
181 } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) { 181 } else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {
182 ret = nf_queue(skb, elem, pf, hook, indev, outdev, okfn, 182 ret = nf_queue(skb, elem, pf, hook, indev, outdev, okfn,
183 verdict >> NF_VERDICT_BITS); 183 verdict >> NF_VERDICT_BITS);
184 if (ret == -ECANCELED) 184 if (ret < 0) {
185 goto next_hook; 185 if (ret == -ECANCELED)
186 goto next_hook;
187 kfree_skb(skb);
188 }
186 ret = 0; 189 ret = 0;
187 } 190 }
188 rcu_read_unlock(); 191 rcu_read_unlock();
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c
index ad25c7e726bc..5c4b730a2e68 100644
--- a/net/netfilter/nf_queue.c
+++ b/net/netfilter/nf_queue.c
@@ -163,9 +163,8 @@ static int __nf_queue(struct sk_buff *skb,
163 163
164 /* If it's going away, ignore hook. */ 164 /* If it's going away, ignore hook. */
165 if (!try_module_get(entry->elem->owner)) { 165 if (!try_module_get(entry->elem->owner)) {
166 rcu_read_unlock(); 166 status = -ECANCELED;
167 kfree(entry); 167 goto err_unlock;
168 return -ECANCELED;
169 } 168 }
170 /* Bump dev refs so they don't vanish while packet is out */ 169 /* Bump dev refs so they don't vanish while packet is out */
171 if (indev) 170 if (indev)
@@ -198,7 +197,6 @@ static int __nf_queue(struct sk_buff *skb,
198err_unlock: 197err_unlock:
199 rcu_read_unlock(); 198 rcu_read_unlock();
200err: 199err:
201 kfree_skb(skb);
202 kfree(entry); 200 kfree(entry);
203 return status; 201 return status;
204} 202}
@@ -229,7 +227,6 @@ int nf_queue(struct sk_buff *skb,
229 } 227 }
230 228
231 segs = skb_gso_segment(skb, 0); 229 segs = skb_gso_segment(skb, 0);
232 kfree_skb(skb);
233 /* Does not use PTR_ERR to limit the number of error codes that can be 230 /* Does not use PTR_ERR to limit the number of error codes that can be
234 * returned by nf_queue. For instance, callers rely on -ECANCELED to mean 231 * returned by nf_queue. For instance, callers rely on -ECANCELED to mean
235 * 'ignore this hook'. 232 * 'ignore this hook'.
@@ -253,8 +250,11 @@ int nf_queue(struct sk_buff *skb,
253 segs = nskb; 250 segs = nskb;
254 } while (segs); 251 } while (segs);
255 252
253 /* also free orig skb if only some segments were queued */
256 if (unlikely(err && queued)) 254 if (unlikely(err && queued))
257 err = 0; 255 err = 0;
256 if (err == 0)
257 kfree_skb(skb);
258 return err; 258 return err;
259} 259}
260 260
@@ -300,8 +300,11 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict)
300 err = __nf_queue(skb, elem, entry->pf, entry->hook, 300 err = __nf_queue(skb, elem, entry->pf, entry->hook,
301 entry->indev, entry->outdev, entry->okfn, 301 entry->indev, entry->outdev, entry->okfn,
302 verdict >> NF_VERDICT_BITS); 302 verdict >> NF_VERDICT_BITS);
303 if (err == -ECANCELED) 303 if (err < 0) {
304 goto next_hook; 304 if (err == -ECANCELED)
305 goto next_hook;
306 kfree_skb(skb);
307 }
305 break; 308 break;
306 case NF_STOLEN: 309 case NF_STOLEN:
307 default: 310 default: