diff options
author | Daniel Borkmann <dborkman@redhat.com> | 2013-12-30 17:40:50 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-01-02 19:31:09 -0500 |
commit | 4d231b76eef6c4a6bd9c96769e191517765942cb (patch) | |
tree | ae855d6ce8a7d2c67f13e2ab9f9376dc6b2e315d /net | |
parent | 6cd4ce0099da7702f885b6fa9ebb49e3831d90b4 (diff) |
net: llc: fix use after free in llc_ui_recvmsg
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>
Diffstat (limited to 'net')
-rw-r--r-- | net/llc/af_llc.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index 7b01b9f5846c..c71b699eb555 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 | ||