lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Sun, 10 May 2020 16:00:41 +0000 From: David Laight <David.Laight@...LAB.COM> To: "netdev@...r.kernel.org" <netdev@...r.kernel.org> Subject: [PATCH net-next] net/ipv4/raw Optimise ipv4 raw sends when IP_HDRINCL set. The final routing for ipv4 packets may be done with the IP address from the message header not that from the address buffer. If the addresses are different FLOWI_FLAG_KNOWN_NH must be set so that a temporary 'struct rtable' entry is created to send the message. However the allocate + free (under RCU) is relatively expensive and can be avoided by a quick check shows the addresses match. Signed-off-by: David Laight <david.laight@...lab.com> --- This makes a considerable difference when we are sending a lot of RTP streams from a raw socket. IP_HDRINCL has to be set so that the calculated UDP checksum is right. net/ipv4/raw.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 3183413..0a81376 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c @@ -495,6 +495,27 @@ static int raw_getfrag(void *from, char *to, int offset, int len, int odd, return ip_generic_getfrag(rfv->msg, to, offset, len, odd, skb); } +static bool raw_msg_addr_matches(struct msghdr *msg, __be32 daddr) +{ + const struct iovec *iov; + __be32 msg_daddr; + + /* Check common case of user buffer with header in the first fragment. + * If we return false the message is still sent. + */ + + if (!iter_is_iovec(&msg->msg_iter)) + return false; + iov = msg->msg_iter.iov; + if (!iov || iov->iov_len < 20) + return false; + + if (get_user(msg_daddr, (__be32 __user *)(iov->iov_base + 16))) + return false; + + return daddr == msg_daddr; +} + static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) { struct inet_sock *inet = inet_sk(sk); @@ -626,9 +647,14 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) flowi4_init_output(&fl4, ipc.oif, ipc.sockc.mark, tos, RT_SCOPE_UNIVERSE, hdrincl ? IPPROTO_RAW : sk->sk_protocol, - inet_sk_flowi_flags(sk) | - (hdrincl ? FLOWI_FLAG_KNOWN_NH : 0), + inet_sk_flowi_flags(sk), daddr, saddr, 0, 0, sk->sk_uid); + /* The final message routing may be done with the destination address + * in the user-supplied ipv4 header. If this differs from 'daddr' then + * a temporary destination table entry has to be created. + */ + if (hdrincl && !raw_msg_addr_matches(msg, daddr)) + fl4.flowi4_flags |= FLOWI_FLAG_KNOWN_NH; if (!hdrincl) { rfv.msg = msg; -- 1.8.1.2 - Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK Registration No: 1397386 (Wales)
Powered by blists - more mailing lists