Deleted Added
full compact
2c2
< /* $FreeBSD: head/sys/net/if_gre.c 219206 2011-03-02 21:39:08Z bz $ */
---
> /* $FreeBSD: head/sys/net/if_gre.c 223223 2011-06-18 09:34:03Z bz $ */
50a51
> #include <sys/libkern.h>
93a95,102
> #define MTAG_COOKIE_GRE 1307983903
> #define MTAG_GRE_NESTING 1
> struct mtag_gre_nesting {
> uint16_t count;
> uint16_t max;
> struct ifnet *ifp[];
> };
>
199d207
< sc->called = 0;
242a251,253
> struct m_tag *mtag;
> struct mtag_gre_nesting *gt;
> size_t len;
248c259
< int extra = 0;
---
> int extra = 0, max;
251,252c262,264
< * gre may cause infinite recursion calls when misconfigured.
< * We'll prevent this by introducing upper limit.
---
> * gre may cause infinite recursion calls when misconfigured. High
> * nesting level may cause stack exhaustion. We'll prevent this by
> * detecting loops and by introducing upper limit.
254,259c266,321
< if (++(sc->called) > max_gre_nesting) {
< printf("%s: gre_output: recursively called too many "
< "times(%d)\n", if_name(GRE2IFP(sc)), sc->called);
< m_freem(m);
< error = EIO; /* is there better errno? */
< goto end;
---
> mtag = m_tag_locate(m, MTAG_COOKIE_GRE, MTAG_GRE_NESTING, NULL);
> if (mtag != NULL) {
> struct ifnet **ifp2;
>
> gt = (struct mtag_gre_nesting *)(mtag + 1);
> gt->count++;
> if (gt->count > min(gt->max,max_gre_nesting)) {
> printf("%s: hit maximum recursion limit %u on %s\n",
> __func__, gt->count - 1, ifp->if_xname);
> m_freem(m);
> error = EIO; /* is there better errno? */
> goto end;
> }
>
> ifp2 = gt->ifp;
> for (max = gt->count - 1; max > 0; max--) {
> if (*ifp2 == ifp)
> break;
> ifp2++;
> }
> if (*ifp2 == ifp) {
> printf("%s: detected loop with nexting %u on %s\n",
> __func__, gt->count-1, ifp->if_xname);
> m_freem(m);
> error = EIO; /* is there better errno? */
> goto end;
> }
> *ifp2 = ifp;
>
> } else {
> /*
> * Given that people should NOT increase max_gre_nesting beyond
> * their real needs, we allocate once per packet rather than
> * allocating an mtag once per passing through gre.
> *
> * Note: the sysctl does not actually check for saneness, so we
> * limit the maximum numbers of possible recursions here.
> */
> max = imin(max_gre_nesting, 256);
> /* If someone sets the sysctl <= 0, we want at least 1. */
> max = imax(max, 1);
> len = sizeof(struct mtag_gre_nesting) +
> max * sizeof(struct ifnet *);
> mtag = m_tag_alloc(MTAG_COOKIE_GRE, MTAG_GRE_NESTING, len,
> M_NOWAIT);
> if (mtag == NULL) {
> m_freem(m);
> error = ENOMEM;
> goto end;
> }
> gt = (struct mtag_gre_nesting *)(mtag + 1);
> bzero(gt, len);
> gt->count = 1;
> gt->max = max;
> *gt->ifp = ifp;
> m_tag_prepend(m, mtag);
447d508
< sc->called = 0;