m_tag_delete_chain do something bad in FreeBSD MAC Framework and IPSEC confliction

zhouyi zhou zhouyi04 at ios.cn
Sun Mar 26 03:17:10 UTC 2006


Dear Colleques:

I reexamined the cause of the conflict between MAC and IPSEC.
The reason is the perform of m_tag_delete_chain(to, NULL) in functions
 m_move_pkthdr and m_dup_pkthdr will
cause IPSEC to do something bad to mbuf's label.

And you can  comments out the m_tag_delete_chain in
 function m_move_pkthdr and m_dup_pkthdr.
And do follows to not allocate MAC label to the mbufs act as "to" in m_move_pkthdr
, and m_dup_pkthdr:

static int
mb_ctor_mbuf(void *mem, int size, void *arg, int how)
{
        struct mbuf *m;
        struct mb_args *args;
#ifdef MAC
        int error;
#endif
        int flags;
        short type;

#ifdef INVARIANTS
        trash_ctor(mem, size, arg, how);
#endif
        m = (struct mbuf *)mem;
        args = (struct mb_args *)arg;
        flags = args->flags;
        type = args->type;

        m->m_type = type;
        m->m_next = NULL;
        m->m_nextpkt = NULL;
        m->m_flags = flags;
        if (flags & M_PKTHDR) {
                m->m_data = m->m_pktdat;
                m->m_pkthdr.rcvif = NULL;
                m->m_pkthdr.csum_flags = 0;
               SLIST_INIT(&m->m_pkthdr.tags);
#ifdef MAC
                /* If the label init fails, fail the alloc */
                if(!(flags&M_PROTO1)){
                error = mac_init_mbuf(m, how);
                if (error)
                        return (error);
                }
#endif
        } else
                m->m_data = m->m_dat;
        mbstat.m_mbufs += 1;    /* XXX */
        return (0);
}

and 

mb_ctor_pack(void *mem, int size, void *arg, int how)
{
        struct mbuf *m;
        struct mb_args *args;
#ifdef MAC
        int error;
#endif
        int flags;
        short type;

        m = (struct mbuf *)mem;
        args = (struct mb_args *)arg;
        flags = args->flags;
        type = args->type;

#ifdef INVARIANTS
        trash_ctor(m->m_ext.ext_buf, MCLBYTES, arg, how);
#endif
        m->m_type = type;
        m->m_next = NULL;
        m->m_nextpkt = NULL;
        m->m_data = m->m_ext.ext_buf;
        m->m_flags = flags|M_EXT;
        m->m_ext.ext_free = NULL;
        m->m_ext.ext_args = NULL;
        m->m_ext.ext_size = MCLBYTES;
        m->m_ext.ext_type = EXT_PACKET;
        m->m_ext.ref_cnt = NULL;        /* Lazy counter assign. */

        if (flags & M_PKTHDR) {
                m->m_pkthdr.rcvif = NULL;
                m->m_pkthdr.csum_flags = 0;
                SLIST_INIT(&m->m_pkthdr.tags);
#ifdef MAC
                /* If the label init fails, fail the alloc */
                if(!(flags&M_PROTO1)){
                error = mac_init_mbuf(m, how);
                if (error)
                        return (error);
                }

#endif
        }
        mbstat.m_mbufs += 1;    /* XXX */
        mbstat.m_mclusts += 1;  /* XXX */
        return (0);
}

And in very place there is a m_move_pkthdr or m_dup_pkthdr:
For example in function m_defrag in uipc_mbuf.c 
        if (m0->m_pkthdr.len > MHLEN)
                m_final = m_getcl(how, MT_DATA, M_PKTHDR|M_PROTO1);
        else
                m_final = m_gethdrnolabel(how, MT_DATA);

        if (m_final == NULL)
                goto nospace;

        if (m_dup_pkthdr(m_final, m0, how) == 0)
                goto nospace;
// The definition of m_gethdrnolabel is as follows:
struct mbuf *
m_gethdrnolabel(int how, short type)
{
        struct mb_args args;

        args.flags = M_PKTHDR|M_PROTO1;
        args.type = type;
        return (uma_zalloc_arg(zone_mbuf, &args, how));
}

Sincerely 
Zhouyi Zhou
Institute of Software
Chinese Academy of Sciences


More information about the freebsd-bugs mailing list