Skip to content

Commit 54ff9ef

Browse files
marceloleitnerdavem330
authored andcommitted
ipv4, ipv6: kill ip_mc_{join, leave}_group and ipv6_sock_mc_{join, drop}
in favor of their inner __ ones, which doesn't grab rtnl. As these functions need to operate on a locked socket, we can't be grabbing rtnl by then. It's too late and doing so causes reversed locking. So this patch: - move rtnl handling to callers instead while already fixing some reversed locking situations, like on vxlan and ipvs code. - renames __ ones to not have the __ mark: __ip_mc_{join,leave}_group -> ip_mc_{join,leave}_group __ipv6_sock_mc_{join,drop} -> ipv6_sock_mc_{join,drop} Signed-off-by: Marcelo Ricardo Leitner <[email protected]> Acked-by: Hannes Frederic Sowa <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent baf606d commit 54ff9ef

File tree

11 files changed

+51
-87
lines changed

11 files changed

+51
-87
lines changed

drivers/net/vxlan.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1097,7 +1097,6 @@ EXPORT_SYMBOL_GPL(vxlan_sock_release);
10971097

10981098
/* Callback to update multicast group membership when first VNI on
10991099
* multicast asddress is brought up
1100-
* Done as workqueue because ip_mc_join_group acquires RTNL.
11011100
*/
11021101
static void vxlan_igmp_join(struct work_struct *work)
11031102
{
@@ -1107,6 +1106,7 @@ static void vxlan_igmp_join(struct work_struct *work)
11071106
union vxlan_addr *ip = &vxlan->default_dst.remote_ip;
11081107
int ifindex = vxlan->default_dst.remote_ifindex;
11091108

1109+
rtnl_lock();
11101110
lock_sock(sk);
11111111
if (ip->sa.sa_family == AF_INET) {
11121112
struct ip_mreqn mreq = {
@@ -1122,6 +1122,7 @@ static void vxlan_igmp_join(struct work_struct *work)
11221122
#endif
11231123
}
11241124
release_sock(sk);
1125+
rtnl_unlock();
11251126

11261127
vxlan_sock_release(vs);
11271128
dev_put(vxlan->dev);
@@ -1136,6 +1137,7 @@ static void vxlan_igmp_leave(struct work_struct *work)
11361137
union vxlan_addr *ip = &vxlan->default_dst.remote_ip;
11371138
int ifindex = vxlan->default_dst.remote_ifindex;
11381139

1140+
rtnl_lock();
11391141
lock_sock(sk);
11401142
if (ip->sa.sa_family == AF_INET) {
11411143
struct ip_mreqn mreq = {
@@ -1152,6 +1154,7 @@ static void vxlan_igmp_leave(struct work_struct *work)
11521154
}
11531155

11541156
release_sock(sk);
1157+
rtnl_unlock();
11551158

11561159
vxlan_sock_release(vs);
11571160
dev_put(vxlan->dev);

include/linux/igmp.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,7 @@ struct ip_mc_list {
111111

112112
extern int ip_check_mc_rcu(struct in_device *dev, __be32 mc_addr, __be32 src_addr, u16 proto);
113113
extern int igmp_rcv(struct sk_buff *);
114-
extern int __ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr);
115114
extern int ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr);
116-
extern int __ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr);
117115
extern int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr);
118116
extern void ip_mc_drop_socket(struct sock *sk);
119117
extern int ip_mc_source(int add, int omode, struct sock *sk,

include/net/ipv6.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -942,10 +942,6 @@ void ipv6_sysctl_unregister(void);
942942

943943
int ipv6_sock_mc_join(struct sock *sk, int ifindex,
944944
const struct in6_addr *addr);
945-
int __ipv6_sock_mc_join(struct sock *sk, int ifindex,
946-
const struct in6_addr *addr);
947945
int ipv6_sock_mc_drop(struct sock *sk, int ifindex,
948946
const struct in6_addr *addr);
949-
int __ipv6_sock_mc_drop(struct sock *sk, int ifindex,
950-
const struct in6_addr *addr);
951947
#endif /* _NET_IPV6_H */

net/ipv4/devinet.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -560,9 +560,9 @@ static int ip_mc_config(struct sock *sk, bool join, const struct in_ifaddr *ifa)
560560

561561
lock_sock(sk);
562562
if (join)
563-
ret = __ip_mc_join_group(sk, &mreq);
563+
ret = ip_mc_join_group(sk, &mreq);
564564
else
565-
ret = __ip_mc_leave_group(sk, &mreq);
565+
ret = ip_mc_leave_group(sk, &mreq);
566566
release_sock(sk);
567567

568568
return ret;

net/ipv4/igmp.c

Lines changed: 8 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1850,7 +1850,10 @@ static void ip_mc_clear_src(struct ip_mc_list *pmc)
18501850
pmc->sfcount[MCAST_EXCLUDE] = 1;
18511851
}
18521852

1853-
int __ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr)
1853+
/* Join a multicast group
1854+
*/
1855+
1856+
int ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr)
18541857
{
18551858
__be32 addr = imr->imr_multiaddr.s_addr;
18561859
struct ip_mc_socklist *iml, *i;
@@ -1898,20 +1901,6 @@ int __ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr)
18981901
done:
18991902
return err;
19001903
}
1901-
EXPORT_SYMBOL(__ip_mc_join_group);
1902-
1903-
/* Join a multicast group
1904-
*/
1905-
int ip_mc_join_group(struct sock *sk, struct ip_mreqn *imr)
1906-
{
1907-
int ret;
1908-
1909-
rtnl_lock();
1910-
ret = __ip_mc_join_group(sk, imr);
1911-
rtnl_unlock();
1912-
1913-
return ret;
1914-
}
19151904
EXPORT_SYMBOL(ip_mc_join_group);
19161905

19171906
static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,
@@ -1934,7 +1923,7 @@ static int ip_mc_leave_src(struct sock *sk, struct ip_mc_socklist *iml,
19341923
return err;
19351924
}
19361925

1937-
int __ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
1926+
int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
19381927
{
19391928
struct inet_sock *inet = inet_sk(sk);
19401929
struct ip_mc_socklist *iml;
@@ -1979,18 +1968,6 @@ int __ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
19791968
out:
19801969
return ret;
19811970
}
1982-
EXPORT_SYMBOL(__ip_mc_leave_group);
1983-
1984-
int ip_mc_leave_group(struct sock *sk, struct ip_mreqn *imr)
1985-
{
1986-
int ret;
1987-
1988-
rtnl_lock();
1989-
ret = __ip_mc_leave_group(sk, imr);
1990-
rtnl_unlock();
1991-
1992-
return ret;
1993-
}
19941971
EXPORT_SYMBOL(ip_mc_leave_group);
19951972

19961973
int ip_mc_source(int add, int omode, struct sock *sk, struct
@@ -2010,7 +1987,7 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
20101987
if (!ipv4_is_multicast(addr))
20111988
return -EINVAL;
20121989

2013-
rtnl_lock();
1990+
ASSERT_RTNL();
20141991

20151992
imr.imr_multiaddr.s_addr = mreqs->imr_multiaddr;
20161993
imr.imr_address.s_addr = mreqs->imr_interface;
@@ -2124,9 +2101,8 @@ int ip_mc_source(int add, int omode, struct sock *sk, struct
21242101
ip_mc_add_src(in_dev, &mreqs->imr_multiaddr, omode, 1,
21252102
&mreqs->imr_sourceaddr, 1);
21262103
done:
2127-
rtnl_unlock();
21282104
if (leavegroup)
2129-
return ip_mc_leave_group(sk, &imr);
2105+
err = ip_mc_leave_group(sk, &imr);
21302106
return err;
21312107
}
21322108

@@ -2148,7 +2124,7 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
21482124
msf->imsf_fmode != MCAST_EXCLUDE)
21492125
return -EINVAL;
21502126

2151-
rtnl_lock();
2127+
ASSERT_RTNL();
21522128

21532129
imr.imr_multiaddr.s_addr = msf->imsf_multiaddr;
21542130
imr.imr_address.s_addr = msf->imsf_interface;
@@ -2210,7 +2186,6 @@ int ip_mc_msfilter(struct sock *sk, struct ip_msfilter *msf, int ifindex)
22102186
pmc->sfmode = msf->imsf_fmode;
22112187
err = 0;
22122188
done:
2213-
rtnl_unlock();
22142189
if (leavegroup)
22152190
err = ip_mc_leave_group(sk, &imr);
22162191
return err;

net/ipv4/ip_sockglue.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -541,9 +541,18 @@ static bool setsockopt_needs_rtnl(int optname)
541541
switch (optname) {
542542
case IP_ADD_MEMBERSHIP:
543543
case IP_ADD_SOURCE_MEMBERSHIP:
544+
case IP_BLOCK_SOURCE:
544545
case IP_DROP_MEMBERSHIP:
546+
case IP_DROP_SOURCE_MEMBERSHIP:
547+
case IP_MSFILTER:
548+
case IP_UNBLOCK_SOURCE:
549+
case MCAST_BLOCK_SOURCE:
550+
case MCAST_MSFILTER:
545551
case MCAST_JOIN_GROUP:
552+
case MCAST_JOIN_SOURCE_GROUP:
546553
case MCAST_LEAVE_GROUP:
554+
case MCAST_LEAVE_SOURCE_GROUP:
555+
case MCAST_UNBLOCK_SOURCE:
547556
return true;
548557
}
549558
return false;
@@ -861,9 +870,9 @@ static int do_ip_setsockopt(struct sock *sk, int level,
861870
}
862871

863872
if (optname == IP_ADD_MEMBERSHIP)
864-
err = __ip_mc_join_group(sk, &mreq);
873+
err = ip_mc_join_group(sk, &mreq);
865874
else
866-
err = __ip_mc_leave_group(sk, &mreq);
875+
err = ip_mc_leave_group(sk, &mreq);
867876
break;
868877
}
869878
case IP_MSFILTER:
@@ -928,7 +937,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
928937
mreq.imr_multiaddr.s_addr = mreqs.imr_multiaddr;
929938
mreq.imr_address.s_addr = mreqs.imr_interface;
930939
mreq.imr_ifindex = 0;
931-
err = __ip_mc_join_group(sk, &mreq);
940+
err = ip_mc_join_group(sk, &mreq);
932941
if (err && err != -EADDRINUSE)
933942
break;
934943
omode = MCAST_INCLUDE;
@@ -960,9 +969,9 @@ static int do_ip_setsockopt(struct sock *sk, int level,
960969
mreq.imr_ifindex = greq.gr_interface;
961970

962971
if (optname == MCAST_JOIN_GROUP)
963-
err = __ip_mc_join_group(sk, &mreq);
972+
err = ip_mc_join_group(sk, &mreq);
964973
else
965-
err = __ip_mc_leave_group(sk, &mreq);
974+
err = ip_mc_leave_group(sk, &mreq);
966975
break;
967976
}
968977
case MCAST_JOIN_SOURCE_GROUP:
@@ -1005,7 +1014,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
10051014
mreq.imr_multiaddr = psin->sin_addr;
10061015
mreq.imr_address.s_addr = 0;
10071016
mreq.imr_ifindex = greqs.gsr_interface;
1008-
err = __ip_mc_join_group(sk, &mreq);
1017+
err = ip_mc_join_group(sk, &mreq);
10091018
if (err && err != -EADDRINUSE)
10101019
break;
10111020
greqs.gsr_interface = mreq.imr_ifindex;

net/ipv6/addrconf.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2473,9 +2473,9 @@ static int ipv6_mc_config(struct sock *sk, bool join,
24732473

24742474
lock_sock(sk);
24752475
if (join)
2476-
ret = __ipv6_sock_mc_join(sk, ifindex, addr);
2476+
ret = ipv6_sock_mc_join(sk, ifindex, addr);
24772477
else
2478-
ret = __ipv6_sock_mc_drop(sk, ifindex, addr);
2478+
ret = ipv6_sock_mc_drop(sk, ifindex, addr);
24792479
release_sock(sk);
24802480

24812481
return ret;

net/ipv6/ipv6_sockglue.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,11 @@ static bool setsockopt_needs_rtnl(int optname)
124124
case IPV6_DROP_MEMBERSHIP:
125125
case MCAST_JOIN_GROUP:
126126
case MCAST_LEAVE_GROUP:
127+
case MCAST_JOIN_SOURCE_GROUP:
128+
case MCAST_LEAVE_SOURCE_GROUP:
129+
case MCAST_BLOCK_SOURCE:
130+
case MCAST_UNBLOCK_SOURCE:
131+
case MCAST_MSFILTER:
127132
return true;
128133
}
129134
return false;
@@ -597,9 +602,9 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
597602
break;
598603

599604
if (optname == IPV6_ADD_MEMBERSHIP)
600-
retv = __ipv6_sock_mc_join(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr);
605+
retv = ipv6_sock_mc_join(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr);
601606
else
602-
retv = __ipv6_sock_mc_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr);
607+
retv = ipv6_sock_mc_drop(sk, mreq.ipv6mr_ifindex, &mreq.ipv6mr_multiaddr);
603608
break;
604609
}
605610
case IPV6_JOIN_ANYCAST:
@@ -638,11 +643,11 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
638643
}
639644
psin6 = (struct sockaddr_in6 *)&greq.gr_group;
640645
if (optname == MCAST_JOIN_GROUP)
641-
retv = __ipv6_sock_mc_join(sk, greq.gr_interface,
642-
&psin6->sin6_addr);
646+
retv = ipv6_sock_mc_join(sk, greq.gr_interface,
647+
&psin6->sin6_addr);
643648
else
644-
retv = __ipv6_sock_mc_drop(sk, greq.gr_interface,
645-
&psin6->sin6_addr);
649+
retv = ipv6_sock_mc_drop(sk, greq.gr_interface,
650+
&psin6->sin6_addr);
646651
break;
647652
}
648653
case MCAST_JOIN_SOURCE_GROUP:
@@ -674,8 +679,8 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
674679
struct sockaddr_in6 *psin6;
675680

676681
psin6 = (struct sockaddr_in6 *)&greqs.gsr_group;
677-
retv = __ipv6_sock_mc_join(sk, greqs.gsr_interface,
678-
&psin6->sin6_addr);
682+
retv = ipv6_sock_mc_join(sk, greqs.gsr_interface,
683+
&psin6->sin6_addr);
679684
/* prior join w/ different source is ok */
680685
if (retv && retv != -EADDRINUSE)
681686
break;

net/ipv6/mcast.c

Lines changed: 3 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ static int unsolicited_report_interval(struct inet6_dev *idev)
132132
return iv > 0 ? iv : 1;
133133
}
134134

135-
int __ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
135+
int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
136136
{
137137
struct net_device *dev = NULL;
138138
struct ipv6_mc_socklist *mc_lst;
@@ -199,24 +199,12 @@ int __ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *add
199199

200200
return 0;
201201
}
202-
EXPORT_SYMBOL(__ipv6_sock_mc_join);
203-
204-
int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
205-
{
206-
int ret;
207-
208-
rtnl_lock();
209-
ret = __ipv6_sock_mc_join(sk, ifindex, addr);
210-
rtnl_unlock();
211-
212-
return ret;
213-
}
214202
EXPORT_SYMBOL(ipv6_sock_mc_join);
215203

216204
/*
217205
* socket leave on multicast group
218206
*/
219-
int __ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
207+
int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
220208
{
221209
struct ipv6_pinfo *np = inet6_sk(sk);
222210
struct ipv6_mc_socklist *mc_lst;
@@ -255,18 +243,6 @@ int __ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *add
255243

256244
return -EADDRNOTAVAIL;
257245
}
258-
EXPORT_SYMBOL(__ipv6_sock_mc_drop);
259-
260-
int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr)
261-
{
262-
int ret;
263-
264-
rtnl_lock();
265-
ret = __ipv6_sock_mc_drop(sk, ifindex, addr);
266-
rtnl_unlock();
267-
268-
return ret;
269-
}
270246
EXPORT_SYMBOL(ipv6_sock_mc_drop);
271247

272248
/* called with rcu_read_lock() */
@@ -460,7 +436,7 @@ int ip6_mc_source(int add, int omode, struct sock *sk,
460436
read_unlock_bh(&idev->lock);
461437
rcu_read_unlock();
462438
if (leavegroup)
463-
return ipv6_sock_mc_drop(sk, pgsr->gsr_interface, group);
439+
err = ipv6_sock_mc_drop(sk, pgsr->gsr_interface, group);
464440
return err;
465441
}
466442

net/netfilter/ipvs/ip_vs_sync.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1405,9 +1405,11 @@ join_mcast_group(struct sock *sk, struct in_addr *addr, char *ifname)
14051405

14061406
mreq.imr_ifindex = dev->ifindex;
14071407

1408+
rtnl_lock();
14081409
lock_sock(sk);
14091410
ret = ip_mc_join_group(sk, &mreq);
14101411
release_sock(sk);
1412+
rtnl_unlock();
14111413

14121414
return ret;
14131415
}

net/tipc/udp_media.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -246,11 +246,11 @@ static int enable_mcast(struct udp_bearer *ub, struct udp_media_addr *remote)
246246
return 0;
247247
mreqn.imr_multiaddr = remote->ipv4;
248248
mreqn.imr_ifindex = ub->ifindex;
249-
err = __ip_mc_join_group(sk, &mreqn);
249+
err = ip_mc_join_group(sk, &mreqn);
250250
} else {
251251
if (!ipv6_addr_is_multicast(&remote->ipv6))
252252
return 0;
253-
err = __ipv6_sock_mc_join(sk, ub->ifindex, &remote->ipv6);
253+
err = ipv6_sock_mc_join(sk, ub->ifindex, &remote->ipv6);
254254
}
255255
return err;
256256
}

0 commit comments

Comments
 (0)