aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Emelyanov <xemul@openvz.org>2007-10-18 05:14:58 -0700
committerDavid S. Miller <davem@davemloft.net>2007-10-18 05:14:58 -0700
commit04028045a12ba941c579d0f3238489333ac18ea4 (patch)
treee12d202ef1e17047742ddb9a70731ebc651f6c11
parent009e8c965fd72a78636b9a96c7015109c5c70176 (diff)
[IPV6]: Lost locking when inserting a flowlabel in ipv6_fl_list
The new flowlabels should be inserted into the sock list under the ip6_sk_fl_lock. This was lost in one place. This list is naturally protected with the socket lock, but the fl6_sock_lookup() is called without it, so another protection is required. Signed-off-by: Pavel Emelyanov <xemul@openvz.org> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/ipv6/ip6_flowlabel.c20
1 files changed, 12 insertions, 8 deletions
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 217d60f9fc8..8550df20f98 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -409,6 +409,16 @@ static int ipv6_opt_cmp(struct ipv6_txoptions *o1, struct ipv6_txoptions *o2)
return 0;
}
+static inline void fl_link(struct ipv6_pinfo *np, struct ipv6_fl_socklist *sfl,
+ struct ip6_flowlabel *fl)
+{
+ write_lock_bh(&ip6_sk_fl_lock);
+ sfl->fl = fl;
+ sfl->next = np->ipv6_fl_list;
+ np->ipv6_fl_list = sfl;
+ write_unlock_bh(&ip6_sk_fl_lock);
+}
+
int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
{
int err;
@@ -513,11 +523,7 @@ int ipv6_flowlabel_opt(struct sock *sk, char __user *optval, int optlen)
fl1->linger = fl->linger;
if ((long)(fl->expires - fl1->expires) > 0)
fl1->expires = fl->expires;
- write_lock_bh(&ip6_sk_fl_lock);
- sfl1->fl = fl1;
- sfl1->next = np->ipv6_fl_list;
- np->ipv6_fl_list = sfl1;
- write_unlock_bh(&ip6_sk_fl_lock);
+ fl_link(np, sfl1, fl1);
fl_free(fl);
return 0;
@@ -545,9 +551,7 @@ release:
}
}
- sfl1->fl = fl;
- sfl1->next = np->ipv6_fl_list;
- np->ipv6_fl_list = sfl1;
+ fl_link(np, sfl1, fl);
return 0;
default: