mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 21:38:32 +08:00
[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>
This commit is contained in:
parent
b9e2cc0f0e
commit
30a584d944
@ -784,24 +784,20 @@ static int llc_ui_recvmsg(struct kiocb *iocb, struct socket *sock,
|
|||||||
copied += used;
|
copied += used;
|
||||||
len -= used;
|
len -= used;
|
||||||
|
|
||||||
if (used + offset < skb->len)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!(flags & MSG_PEEK)) {
|
if (!(flags & MSG_PEEK)) {
|
||||||
sk_eat_skb(sk, skb, 0);
|
sk_eat_skb(sk, skb, 0);
|
||||||
*seq = 0;
|
*seq = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* For non stream protcols we get one packet per recvmsg call */
|
||||||
|
if (sk->sk_type != SOCK_STREAM)
|
||||||
|
goto copy_uaddr;
|
||||||
|
|
||||||
|
/* Partial read */
|
||||||
|
if (used + offset < skb->len)
|
||||||
|
continue;
|
||||||
} while (len > 0);
|
} while (len > 0);
|
||||||
|
|
||||||
/*
|
|
||||||
* According to UNIX98, msg_name/msg_namelen are ignored
|
|
||||||
* on connected socket. -ANK
|
|
||||||
* But... af_llc still doesn't have separate sets of methods for
|
|
||||||
* SOCK_DGRAM and SOCK_STREAM :-( So we have to do this test, will
|
|
||||||
* eventually fix this tho :-) -acme
|
|
||||||
*/
|
|
||||||
if (sk->sk_type == SOCK_DGRAM)
|
|
||||||
goto copy_uaddr;
|
|
||||||
out:
|
out:
|
||||||
release_sock(sk);
|
release_sock(sk);
|
||||||
return copied;
|
return copied;
|
||||||
|
@ -51,10 +51,10 @@ void llc_save_primitive(struct sock *sk, struct sk_buff* skb, u8 prim)
|
|||||||
{
|
{
|
||||||
struct sockaddr_llc *addr;
|
struct sockaddr_llc *addr;
|
||||||
|
|
||||||
if (skb->sk->sk_type == SOCK_STREAM) /* See UNIX98 */
|
|
||||||
return;
|
|
||||||
/* save primitive for use by the user. */
|
/* save primitive for use by the user. */
|
||||||
addr = llc_ui_skb_cb(skb);
|
addr = llc_ui_skb_cb(skb);
|
||||||
|
|
||||||
|
memset(addr, 0, sizeof(*addr));
|
||||||
addr->sllc_family = sk->sk_family;
|
addr->sllc_family = sk->sk_family;
|
||||||
addr->sllc_arphrd = skb->dev->type;
|
addr->sllc_arphrd = skb->dev->type;
|
||||||
addr->sllc_test = prim == LLC_TEST_PRIM;
|
addr->sllc_test = prim == LLC_TEST_PRIM;
|
||||||
|
Loading…
Reference in New Issue
Block a user