On Fri, Apr 20, 2012 at 10:11:37AM -0700, Jeff Kirsher wrote:
> From: Alexander Duyck <alexander.h.du...@intel.com>
> 
> The fcoe_recv_frame path makes a call to skb_linearize without verifying
> that it has actually linearized the frame.  This can lead to memory
> corruption issues if we use the frame assuming it is 3K, instead of a
> smaller 512 or 1K sized frame.
> 
> In order to ensure that the linearize call result is tested I have moved it
> into the location that was previously taken in fcoe_rcv which was verifying
> we had at least the header.  This way instead of breaking things up into
> two calls to __pskb_pull_tail we rip the bandage off in one tear and just
> take care of all of the linearization in a single call.
> 
> A better fix would be to have the FCoE path handle non-linear sk_buffs, but
> I am not confident enough in my understanding of FCoE to rewrite it to
> handle it.  I will leave that to the FCoE maintainers to handle.
> 
> Signed-off-by: Alexander Duyck <alexander.h.du...@intel.com>
> Tested-by: Ross Brattain <ross.b.bratt...@intel.com>
> Signed-off-by: Jeff Kirsher <jeffrey.t.kirs...@intel.com>
> 
> ---
> drivers/scsi/fcoe/fcoe.c |    8 ++++----
>  1 files changed, 4 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/scsi/fcoe/fcoe.c b/drivers/scsi/fcoe/fcoe.c
> index e959960..5d37ce6 100644
> --- a/drivers/scsi/fcoe/fcoe.c
> +++ b/drivers/scsi/fcoe/fcoe.c
> @@ -1336,11 +1336,12 @@ static int fcoe_rcv(struct sk_buff *skb, struct 
> net_device *netdev,
>       }
>  
>       /*
> -      * Check for minimum frame length, and make sure required FCoE
> +      * Check for minimum frame length, and make sure FCoE frame
>        * and FC headers are pulled into the linear data area.
> +      *
> +      * This is not ideal, and FCoE should learn to handle non-linear frames
>        */
> -     if (unlikely((skb->len < FCOE_MIN_FRAME) ||
> -                  !pskb_may_pull(skb, FCOE_HEADER_LEN)))
> +     if (unlikely((skb->len < FCOE_MIN_FRAME) || skb_linearize(skb)))
>               goto err;
>  
this moves the call to skb_linearize into softirq context however.  Is that safe
to do?  I can't find any other code point that does this, so I can't say for
certain.  It looks ok, but I'm not sure.

Also, this is going to increase softirq execution time. FCOE_MIN_FRAME is
defined as 38 bytes, so it seems to me that that the pskb_may_pull will likely
return very quickly, whereas the the linearize call has lots of potential to
take a long time.  

Might it be better to insead, just reduce fcoe_rcv to a minimum effort routine
that parses out the fh_ox_id value from the skb to determine the destination cpu
of the frame? Then we can move all the other validation work that fcoe_rcv does
up to fcoe_recv_frame, where we run in process context?  I like the idea of not
having to do two pulls/linearizations, but I think it might be better to do it
out of the softirq handler if we can.

Regards
Neil
>       skb_set_transport_header(skb, sizeof(struct fcoe_hdr));
> @@ -1676,7 +1677,6 @@ static void fcoe_recv_frame(struct sk_buff *skb)
>                       skb->dev ? skb->dev->name : "<NULL>");
>  
>       port = lport_priv(lport);
> -     skb_linearize(skb); /* check for skb_is_nonlinear is within 
> skb_linearize */
>  
>       /*
>        * Frame length checks and setting up the header pointers
> _______________________________________________
> devel mailing list
> devel@open-fcoe.org
> https://lists.open-fcoe.org/mailman/listinfo/devel
> 
_______________________________________________
devel mailing list
devel@open-fcoe.org
https://lists.open-fcoe.org/mailman/listinfo/devel

Reply via email to