aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2006-08-03 19:38:49 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2006-08-05 01:59:50 -0400
commit30a584d944fbd599d4a8f470f75bf7af1a15b466 (patch)
tree7e90f97222f776db8a01c51256c7071e35523543
parentb9e2cc0f0e47ad351349156018ef8a365e9c6d25 (diff)
[LLX]: SOCK_DGRAM interface fixes
The datagram interface of LLC is broken in a couple of ways. These were discovered when trying to use it to build an out-of-kernel version of STP. First it didn't pass the source address of the received packet in recvfrom(). It needs to copy the source address of received LLC packets into the socket control block. At the same time fix a security issue because there was uninitialized data leakage. Every recvfrom call was just copying out old data. Second, LLC should not merge multiple packets in one receive call on datagram sockets. LLC should preserve packet boundaries on SOCK_DGRAM. This fix goes against the old historical comments about UNIX98 semantics but without this fix SOCK_DGRAM is broken and useless. So either ANK's interpretation was incorect or UNIX98 standard was wrong. Signed-off-by: Stephen Hemminger <shemminger@osdl.org> Acked-by: Arnaldo Carvalho de Melo <acme@mandriva.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/llc/af_llc.c20
-rw-r--r--net/llc/llc_sap.c4
2 files changed, 10 insertions, 14 deletions
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c
index d6cfe84d521b..2652ead96c64 100644
--- a/net/llc/af_llc.c
+++ b/net/llc/af_llc.c
@@ -784,24 +784,20 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
784 copied += used; 784 copied += used;
785 len -= used; 785 len -= used;
786 786
787 if (used + offset < skb->len)
788 continue;
789
790 if (!(flags & MSG_PEEK)) { 787 if (!(flags & MSG_PEEK)) {
791 sk_eat_skb(sk, skb, 0); 788 sk_eat_skb(sk, skb, 0);
792 *seq = 0; 789 *seq = 0;
793 } 790 }
791
792 /* For non stream protcols we get one packet per recvmsg call */
793 if (sk->sk_type != SOCK_STREAM)
794 goto copy_uaddr;
795
796 /* Partial read */
797 if (used + offset < skb->len)
798 continue;
794 } while (len > 0); 799 } while (len > 0);
795 800
796 /*
797 * According to UNIX98, msg_name/msg_namelen are ignored
798 * on connected socket. -ANK
799 * But... af_llc still doesn't have separate sets of methods for
800 * SOCK_DGRAM and SOCK_STREAM :-( So we have to do this test, will
801 * eventually fix this tho :-) -acme
802 */
803 if (sk->sk_type == SOCK_DGRAM)
804 goto copy_uaddr;
805out: 801out:
806 release_sock(sk); 802 release_sock(sk);
807 return copied; 803 return copied;
diff --git a/net/llc/llc_sap.c b/net/llc/llc_sap.c
index 20c4eb5c1ac6..42eb0c3a9780 100644
--- a/net/llc/llc_sap.c
+++ b/net/llc/llc_sap.c
@@ -51,10 +51,10 @@ void llc_save_primitive(struct sock *sk, struct sk_buff* skb, u8 prim)
51{ 51{
52 struct sockaddr_llc *addr; 52 struct sockaddr_llc *addr;
53 53
54 if (skb->sk->sk_type == SOCK_STREAM) /* See UNIX98 */
55 return;
56 /* save primitive for use by the user. */ 54 /* save primitive for use by the user. */
57 addr = llc_ui_skb_cb(skb); 55 addr = llc_ui_skb_cb(skb);
56
57 memset(addr, 0, sizeof(*addr));
58 addr->sllc_family = sk->sk_family; 58 addr->sllc_family = sk->sk_family;
59 addr->sllc_arphrd = skb->dev->type; 59 addr->sllc_arphrd = skb->dev->type;
60 addr->sllc_test = prim == LLC_TEST_PRIM; 60 addr->sllc_test = prim == LLC_TEST_PRIM;