Hi,

On Tue, Jan 19, 2016 at 04:31:56PM +0100, Mike Belopuhov wrote:
> Hi,
> 
> We've just run into a vmx panic and code inspection revealed
> that my previous diff contained a mistake, the pullup operation
> is called on a wrong mbuf chain.
> 
> I apologize for overlooking this issue.
> 
> We're not 100% certain that this fixes our exact problem yet
> since we can't reproduce it at will, but the diff appears
> correct to us.  Please test and report any problems.
> 
> Thanks!
> 
> diff --git sys/dev/pci/if_vmx.c sys/dev/pci/if_vmx.c
> index 2a3367c..7710987 100644
> --- sys/dev/pci/if_vmx.c
> +++ sys/dev/pci/if_vmx.c
> @@ -1121,11 +1121,11 @@ vmxnet3_load_mbuf(struct vmxnet3_softc *sc, struct 
> vmxnet3_txring *ring,
>                       return (-1);
>  
>               ip = (struct ip *)(n->m_data + offp);
>               hlen += ip->ip_hl << 2;
>  
> -             *mp = m_pullup(m, hlen + csum_off + 2);
> +             *mp = m_pullup(n, hlen + csum_off + 2);
>               if (*mp == NULL)
>                       return (-1);
>               m = *mp;
>       }
>  
> 

This doesn't look correct.  As discussed with mikeb@ already,

- n, as returned by m_pulldown(), can be a mbuf further down the chain.

- *mp, as returned by m_pullup(), can be a new mbuf with n as a m_next pointer.

- replacing the m pointer with *mp will a) leak the original m and b)
seek to a new mbuf further down the chain, skipping the headers, and
putting an mbuf with missing ethernet headers on the ring.

The manpage doesn't explain the return values of m_pulldown() very
well and it doesn't explain the return value of m_pullup() at all.
We had to consult itojun's paper to verify what it does.

Reyk

Reply via email to