Commit 6b5f43ea authored by Eric Dumazet's avatar Eric Dumazet Committed by David S. Miller
Browse files

inet: move inet->recverr to inet->inet_flags



IP_RECVERR socket option can now be set/get without locking the socket.

This patch potentially avoid data-races around inet->recverr.

Signed-off-by: default avatarEric Dumazet <edumazet@google.com>
Acked-by: default avatarSoheil Hassas Yeganeh <soheil@google.com>
Reviewed-by: default avatarSimon Horman <horms@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent b4d84bce
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -230,8 +230,7 @@ struct inet_sock {
	__u8			min_ttl;
	__u8			mc_ttl;
	__u8			pmtudisc;
	__u8			recverr:1,
				is_icsk:1,
	__u8			is_icsk:1,
				freebind:1,
				hdrincl:1,
				mc_loop:1,
@@ -270,6 +269,8 @@ enum {
	INET_FLAGS_ORIGDSTADDR	= 6,
	INET_FLAGS_CHECKSUM	= 7,
	INET_FLAGS_RECVFRAGSIZE	= 8,

	INET_FLAGS_RECVERR	= 9,
};

/* cmsg flags for inet */
+1 −3
Original line number Diff line number Diff line
@@ -247,7 +247,6 @@ static int dccp_v4_err(struct sk_buff *skb, u32 info)
	const u8 offset = iph->ihl << 2;
	const struct dccp_hdr *dh;
	struct dccp_sock *dp;
	struct inet_sock *inet;
	const int type = icmp_hdr(skb)->type;
	const int code = icmp_hdr(skb)->code;
	struct sock *sk;
@@ -361,8 +360,7 @@ static int dccp_v4_err(struct sk_buff *skb, u32 info)
	 *							--ANK (980905)
	 */

	inet = inet_sk(sk);
	if (!sock_owned_by_user(sk) && inet->recverr) {
	if (!sock_owned_by_user(sk) && inet_test_bit(RECVERR, sk)) {
		sk->sk_err = err;
		sk_error_report(sk);
	} else { /* Only an error on timeout */
+1 −1
Original line number Diff line number Diff line
@@ -182,7 +182,7 @@ int inet_diag_msg_attrs_fill(struct sock *sk, struct sk_buff *skb,
	r->idiag_inode = sock_i_ino(sk);

	memset(&inet_sockopt, 0, sizeof(inet_sockopt));
	inet_sockopt.recverr	= inet->recverr;
	inet_sockopt.recverr	= inet_test_bit(RECVERR, sk);
	inet_sockopt.is_icsk	= inet->is_icsk;
	inet_sockopt.freebind	= inet->freebind;
	inet_sockopt.hdrincl	= inet->hdrincl;
+10 −13
Original line number Diff line number Diff line
@@ -446,12 +446,11 @@ EXPORT_SYMBOL_GPL(ip_icmp_error);

void ip_local_error(struct sock *sk, int err, __be32 daddr, __be16 port, u32 info)
{
	struct inet_sock *inet = inet_sk(sk);
	struct sock_exterr_skb *serr;
	struct iphdr *iph;
	struct sk_buff *skb;

	if (!inet->recverr)
	if (!inet_test_bit(RECVERR, sk))
		return;

	skb = alloc_skb(sizeof(struct iphdr), GFP_ATOMIC);
@@ -617,9 +616,7 @@ EXPORT_SYMBOL(ip_sock_set_freebind);

void ip_sock_set_recverr(struct sock *sk)
{
	lock_sock(sk);
	inet_sk(sk)->recverr = true;
	release_sock(sk);
	inet_set_bit(RECVERR, sk);
}
EXPORT_SYMBOL(ip_sock_set_recverr);

@@ -978,6 +975,11 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
			return -EINVAL;
		inet_assign_bit(RECVFRAGSIZE, sk, val);
		return 0;
	case IP_RECVERR:
		inet_assign_bit(RECVERR, sk, val);
		if (!val)
			skb_queue_purge(&sk->sk_error_queue);
		return 0;
	}

	err = 0;
@@ -1064,11 +1066,6 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
			goto e_inval;
		inet->pmtudisc = val;
		break;
	case IP_RECVERR:
		inet->recverr = !!val;
		if (!val)
			skb_queue_purge(&sk->sk_error_queue);
		break;
	case IP_RECVERR_RFC4884:
		if (val < 0 || val > 1)
			goto e_inval;
@@ -1575,6 +1572,9 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
	case IP_RECVFRAGSIZE:
		val = inet_test_bit(RECVFRAGSIZE, sk);
		goto copyval;
	case IP_RECVERR:
		val = inet_test_bit(RECVERR, sk);
		goto copyval;
	}

	if (needs_rtnl)
@@ -1649,9 +1649,6 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
		}
		break;
	}
	case IP_RECVERR:
		val = inet->recverr;
		break;
	case IP_RECVERR_RFC4884:
		val = inet->recverr_rfc4884;
		break;
+1 −1
Original line number Diff line number Diff line
@@ -580,7 +580,7 @@ void ping_err(struct sk_buff *skb, int offset, u32 info)
	 *      RFC1122: OK.  Passes ICMP errors back to application, as per
	 *	4.1.3.3.
	 */
	if ((family == AF_INET && !inet_sock->recverr) ||
	if ((family == AF_INET && !inet_test_bit(RECVERR, sk)) ||
	    (family == AF_INET6 && !inet6_sk(sk)->recverr)) {
		if (!harderr || sk->sk_state != TCP_ESTABLISHED)
			goto out;
Loading