--- x/net/ipv4/cipso_ipv4.c +++ y/net/ipv4/cipso_ipv4.c @@ -1848,6 +1848,7 @@ static int cipso_v4_get_actual_opt_len(c * values on failure. * */ +DEFINE_SPINLOCK(setattr_spinlock); int cipso_v4_sock_setattr(struct sock *sk, const struct cipso_v4_doi *doi_def, const struct netlbl_lsm_secattr *secattr, @@ -1899,6 +1900,7 @@ int cipso_v4_sock_setattr(struct sock *s kfree(buf); buf = NULL; + spin_lock(&setattr_spinlock); sk_inet = inet_sk(sk); old = rcu_dereference_protected(sk_inet->inet_opt, sk_locked); @@ -1912,6 +1914,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(&setattr_spinlock); return 0; @@ -1975,10 +1978,12 @@ int cipso_v4_req_setattr(struct request_ kfree(buf); buf = NULL; + spin_lock(&setattr_spinlock); req_inet = inet_rsk(req); opt = unrcu_pointer(xchg(&req_inet->ireq_opt, RCU_INITIALIZER(opt))); if (opt) kfree_rcu(opt, rcu); + spin_unlock(&setattr_spinlock); return 0; @@ -2057,9 +2062,11 @@ void cipso_v4_sock_delattr(struct sock * struct inet_sock *sk_inet; int hdr_delta; + spin_lock(&setattr_spinlock); sk_inet = inet_sk(sk); hdr_delta = cipso_v4_delopt(&sk_inet->inet_opt); + spin_unlock(&setattr_spinlock); 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; @@ -2077,7 +2084,9 @@ void cipso_v4_sock_delattr(struct sock * */ void cipso_v4_req_delattr(struct request_sock *req) { + spin_lock(&setattr_spinlock); cipso_v4_delopt(&inet_rsk(req)->ireq_opt); + spin_unlock(&setattr_spinlock); } /** --- x/include/net/sock.h +++ y/include/net/sock.h @@ -2922,6 +2922,7 @@ extern __u32 sysctl_rmem_max; extern __u32 sysctl_wmem_default; extern __u32 sysctl_rmem_default; +extern spinlock_t setattr_spinlock; #define SKB_FRAG_PAGE_ORDER get_order(32768) DECLARE_STATIC_KEY_FALSE(net_high_order_alloc_disable_key); --- 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(&setattr_spinlock); 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(&setattr_spinlock); break; } case IP_CHECKSUM: