|
@@ -21,6 +21,7 @@
|
|
|
#include <linux/rtnetlink.h>
|
|
|
#include <linux/slab.h>
|
|
|
|
|
|
+#include <net/sock.h>
|
|
|
#include <net/inet_frag.h>
|
|
|
|
|
|
static void inet_frag_secret_rebuild(unsigned long dummy)
|
|
@@ -277,6 +278,7 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
|
|
|
__releases(&f->lock)
|
|
|
{
|
|
|
struct inet_frag_queue *q;
|
|
|
+ int depth = 0;
|
|
|
|
|
|
hlist_for_each_entry(q, &f->hash[hash], list) {
|
|
|
if (q->net == nf && f->match(q, key)) {
|
|
@@ -284,9 +286,25 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf,
|
|
|
read_unlock(&f->lock);
|
|
|
return q;
|
|
|
}
|
|
|
+ depth++;
|
|
|
}
|
|
|
read_unlock(&f->lock);
|
|
|
|
|
|
- return inet_frag_create(nf, f, key);
|
|
|
+ if (depth <= INETFRAGS_MAXDEPTH)
|
|
|
+ return inet_frag_create(nf, f, key);
|
|
|
+ else
|
|
|
+ return ERR_PTR(-ENOBUFS);
|
|
|
}
|
|
|
EXPORT_SYMBOL(inet_frag_find);
|
|
|
+
|
|
|
+void inet_frag_maybe_warn_overflow(struct inet_frag_queue *q,
|
|
|
+ const char *prefix)
|
|
|
+{
|
|
|
+ static const char msg[] = "inet_frag_find: Fragment hash bucket"
|
|
|
+ " list length grew over limit " __stringify(INETFRAGS_MAXDEPTH)
|
|
|
+ ". Dropping fragment.\n";
|
|
|
+
|
|
|
+ if (PTR_ERR(q) == -ENOBUFS)
|
|
|
+ LIMIT_NETDEBUG(KERN_WARNING "%s%s", prefix, msg);
|
|
|
+}
|
|
|
+EXPORT_SYMBOL(inet_frag_maybe_warn_overflow);
|