On 3/27/2019 3:31 PM, Chas Williams wrote:
> 
> 
> On 3/27/19 11:18 AM, Stephen Hemminger wrote:
>> On Tue, 26 Mar 2019 18:38:57 -0400
>> Chas Williams <3ch...@gmail.com> wrote:
>>
>>> On 3/26/19 3:15 PM, Stephen Hemminger wrote:
>>>> If mbuf refcnt was > 1 then rte_vlan_insert() would incorrectly
>>>> modify the original copy. Original code was expecting clone to make
>>>> a copy (it doesn't). Better to let the caller deal with making
>>>> a copy or setting up mbuf chain to allow for header to be added.
>>>>
>>>> Also fix docbook comment about parameters (function takes
>>>> pointer to mbuf).
>>>>
>>>> Fixes: c974021a5949 ("ether: add soft vlan encap/decap")
>>>> Signed-off-by: Stephen Hemminger <sthem...@microsoft.com>
>>>> ---
>>>>    lib/librte_net/rte_ether.h | 15 ++++-----------
>>>>    1 file changed, 4 insertions(+), 11 deletions(-)
>>>>
>>>> diff --git a/lib/librte_net/rte_ether.h b/lib/librte_net/rte_ether.h
>>>> index c2c5e249ffe9..bab2b198fa79 100644
>>>> --- a/lib/librte_net/rte_ether.h
>>>> +++ b/lib/librte_net/rte_ether.h
>>>> @@ -374,7 +374,7 @@ static inline int rte_vlan_strip(struct rte_mbuf *m)
>>>>     * Software version of VLAN unstripping
>>>>     *
>>>>     * @param m
>>>> - *   The packet mbuf.
>>>> + *   Pointer to the packet mbuf.
>>>>     * @return
>>>>     *   - 0: On success
>>>>     *   -EPERM: mbuf is is shared overwriting would be unsafe
>>>> @@ -385,16 +385,9 @@ static inline int rte_vlan_insert(struct rte_mbuf **m)
>>>>            struct ether_hdr *oh, *nh;
>>>>            struct vlan_hdr *vh;
>>>>    
>>>> -  /* Can't insert header if mbuf is shared */
>>>> -  if (rte_mbuf_refcnt_read(*m) > 1) {
>>>> -          struct rte_mbuf *copy;
>>>> -
>>>> -          copy = rte_pktmbuf_clone(*m, (*m)->pool);
>>>> -          if (unlikely(copy == NULL))
>>>> -                  return -ENOMEM;
>>>> -          rte_pktmbuf_free(*m);
>>>> -          *m = copy;
>>>> -  }
>>>> +  /* Can't directly insert header if mbuf is shared */
>>>> +  if (rte_mbuf_refcnt_read(*m) > 1)
>>>
>>> This check probably isn't sufficient. You need something more like:
>>>
>>>           if (rte_mbuf_refcnt_read(mbuf) > 1 ||
>>>               (RTE_MBUF_INDIRECT(mbuf) &&
>>>                rte_mbuf_refcnt_read(rte_mbuf_from_indirect(mbuf)) > 1)) {
>>>
>>> If this is a cloned packet, the refcnt will be 1. So you need to examine
>>> the parent mbuf to see if other clones exist.
>>>
>>
>> The problem is that indirect buffers probably can't be overwritten
>> because of lack of headroom.
>>
>> Actually, why not push the problem into the pktmbuf_headroom logic?
> 
> That's not what the original code is checking and why it is checking. You
> should not modify the data of a packet that has other users. 

+1, commit log mentions from the same problem I think.

> To check
> all the possible users, you need to check your refcnt and if a clone,
> check the parent to see if any other clones exist.  If they do, you
> can't safely modify these packets. Yes, we have run into this bug.  Yes,
> it was hard to find.
> 
> Someone local write a slightly different version of rte_vlan_insert
> that clones the packet and prepends an mbuf so you can safely insert
> the VLAN information. I will see about getting it submitted.

Thanks for it, it looks like duplicating the mbuf was the original intention of
the code.
But if we can't get updated 'rte_vlan_insert' timely, I suggest getting this
patch with extended checks that you suggested. So can it be possible to make new
version of this patch in any case?

Reply via email to