aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <dborkman@redhat.com>2013-12-30 17:40:50 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-01-15 18:28:50 -0500
commite7c28ed53545ee8972baf31c89a4e801be228e99 (patch)
treebe81be3fbf86c502f235ab355ba9ddf3fef482d2
parent6a0827c4051600d836b16ed9cb6caf78b26573bc (diff)
net: llc: fix use after free in llc_ui_recvmsg
[ Upstream commit 4d231b76eef6c4a6bd9c96769e191517765942cb ] While commit 30a584d944fb fixes datagram interface in LLC, a use after free bug has been introduced for SOCK_STREAM sockets that do not make use of MSG_PEEK. The flow is as follow ... if (!(flags & MSG_PEEK)) { ... sk_eat_skb(sk, skb, false); ... } ... if (used + offset < skb->len) continue; ... where sk_eat_skb() calls __kfree_skb(). Therefore, cache original length and work on skb_len to check partial reads. Fixes: 30a584d944fb ("[LLX]: SOCK_DGRAM interface fixes") Signed-off-by: Daniel Borkmann <dborkman@redhat.com> Cc: Stephen Hemminger <stephen@networkplumber.org> Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--net/llc/af_llc.c5
1 files changed, 3 insertions, 2 deletions
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index 88709882c464..c3ee80547066 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -715,7 +715,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
715 unsigned long cpu_flags; 715 unsigned long cpu_flags;
716 size_t copied = 0; 716 size_t copied = 0;
717 u32 peek_seq = 0; 717 u32 peek_seq = 0;
718 u32 *seq; 718 u32 *seq, skb_len;
719 unsigned long used; 719 unsigned long used;
720 int target; /* Read at least this many bytes */ 720 int target; /* Read at least this many bytes */
721 long timeo; 721 long timeo;
@@ -812,6 +812,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
812 } 812 }
813 continue; 813 continue;
814 found_ok_skb: 814 found_ok_skb:
815 skb_len = skb->len;
815 /* Ok so how much can we use? */ 816 /* Ok so how much can we use? */
816 used = skb->len - offset; 817 used = skb->len - offset;
817 if (len < used) 818 if (len < used)
@@ -844,7 +845,7 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
844 } 845 }
845 846
846 /* Partial read */ 847 /* Partial read */
847 if (used + offset < skb->len) 848 if (used + offset < skb_len)
848 continue; 849 continue;
849 } while (len > 0); 850 } while (len > 0);
850 851