--- x/include/net/inet_sock.h +++ y/include/net/inet_sock.h @@ -227,6 +227,7 @@ struct inet_sock { __be16 inet_sport; struct ip_options_rcu __rcu *inet_opt; atomic_t inet_id; + spinlock_t inet_lock; __u8 tos; __u8 min_ttl; --- x/net/ipv4/af_inet.c +++ y/net/ipv4/af_inet.c @@ -351,6 +351,7 @@ lookup_protocol: inet->pmtudisc = IP_PMTUDISC_WANT; atomic_set(&inet->inet_id, 0); + spin_lock_init(&inet->inet_lock); sock_init_data(sock, sk); --- x/net/ipv4/ip_sockglue.c +++ y/net/ipv4/ip_sockglue.c @@ -1087,6 +1087,7 @@ int do_ip_setsockopt(struct sock *sk, in err = ip_options_get(sock_net(sk), &opt, optval, optlen); if (err) break; + spin_lock(&inet->inet_lock); old = rcu_dereference_protected(inet->inet_opt, lockdep_sock_is_held(sk)); if (inet_test_bit(IS_ICSK, sk)) { @@ -1109,6 +1110,7 @@ int do_ip_setsockopt(struct sock *sk, in rcu_assign_pointer(inet->inet_opt, opt); if (old) kfree_rcu(old, rcu); + spin_unlock(&inet->inet_lock); break; } case IP_CHECKSUM: --- x/net/ipv4/cipso_ipv4.c +++ y/net/ipv4/cipso_ipv4.c @@ -1900,6 +1900,7 @@ int cipso_v4_sock_setattr(struct sock *s buf = NULL; sk_inet = inet_sk(sk); + spin_lock(&sk_inet->inet_lock); old = rcu_dereference_protected(sk_inet->inet_opt, sk_locked); if (inet_test_bit(IS_ICSK, sk)) { @@ -1912,6 +1913,7 @@ int cipso_v4_sock_setattr(struct sock *s rcu_assign_pointer(sk_inet->inet_opt, opt); if (old) kfree_rcu(old, rcu); + spin_unlock(&sk_inet->inet_lock); return 0; @@ -2059,7 +2061,9 @@ void cipso_v4_sock_delattr(struct sock * sk_inet = inet_sk(sk); + spin_lock(&sk_inet->inet_lock); hdr_delta = cipso_v4_delopt(&sk_inet->inet_opt); + spin_unlock(&sk_inet->inet_lock); if (inet_test_bit(IS_ICSK, sk) && hdr_delta > 0) { struct inet_connection_sock *sk_conn = inet_csk(sk); sk_conn->icsk_ext_hdr_len -= hdr_delta;