--- 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. * */ +static 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; @@ -1976,9 +1979,11 @@ int cipso_v4_req_setattr(struct request_ buf = NULL; req_inet = inet_rsk(req); + spin_lock(&setattr_spinlock); opt = unrcu_pointer(xchg(&req_inet->ireq_opt, RCU_INITIALIZER(opt))); if (opt) kfree_rcu(opt, rcu); + spin_unlock(&setattr_spinlock); return 0; @@ -2000,11 +2005,15 @@ req_setattr_failure: */ static int cipso_v4_delopt(struct ip_options_rcu __rcu **opt_ptr) { - struct ip_options_rcu *opt = rcu_dereference_protected(*opt_ptr, 1); + struct ip_options_rcu *opt; int hdr_delta = 0; - if (!opt || opt->opt.cipso == 0) + spin_lock(&setattr_spinlock); + opt = rcu_dereference_protected(*opt_ptr, 1); + if (!opt || opt->opt.cipso == 0) { + spin_unlock(&setattr_spinlock); return 0; + } if (opt->opt.srr || opt->opt.rr || opt->opt.ts || opt->opt.router_alert) { u8 cipso_len; u8 cipso_off; @@ -2040,6 +2049,7 @@ static int cipso_v4_delopt(struct ip_opt hdr_delta = opt->opt.optlen; kfree_rcu(opt, rcu); } + spin_unlock(&setattr_spinlock); return hdr_delta; }