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;
 
        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

Reply via email to