Skip to content

Commit e781905

Browse files
Mike Manningdavem330
authored andcommitted
net: ensure unbound stream socket to be chosen when not in a VRF
The commit a04a480 ("net: Require exact match for TCP socket lookups if dif is l3mdev") only ensures that the correct socket is selected for packets in a VRF. However, there is no guarantee that the unbound socket will be selected for packets when not in a VRF. By checking for a device match in compute_score() also for the case when there is no bound device and attaching a score to this, the unbound socket is selected. And if a failure is returned when there is no device match, this ensures that bound sockets are never selected, even if there is no unbound socket. Signed-off-by: Mike Manning <mmanning@vyatta.att-mail.com> Reviewed-by: David Ahern <dsahern@gmail.com> Tested-by: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 3c82a21 commit e781905

File tree

4 files changed

+31
-16
lines changed

4 files changed

+31
-16
lines changed

include/net/inet_hashtables.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,17 @@ static inline void inet_ehash_locks_free(struct inet_hashinfo *hashinfo)
189189
hashinfo->ehash_locks = NULL;
190190
}
191191

192+
static inline bool inet_sk_bound_dev_eq(struct net *net, int bound_dev_if,
193+
int dif, int sdif)
194+
{
195+
#if IS_ENABLED(CONFIG_NET_L3_MASTER_DEV)
196+
return inet_bound_dev_eq(!!net->ipv4.sysctl_tcp_l3mdev_accept,
197+
bound_dev_if, dif, sdif);
198+
#else
199+
return inet_bound_dev_eq(true, bound_dev_if, dif, sdif);
200+
#endif
201+
}
202+
192203
struct inet_bind_bucket *
193204
inet_bind_bucket_create(struct kmem_cache *cachep, struct net *net,
194205
struct inet_bind_hashbucket *head,

include/net/inet_sock.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,14 @@ static inline int inet_sk_bound_l3mdev(const struct sock *sk)
143143
return 0;
144144
}
145145

146+
static inline bool inet_bound_dev_eq(bool l3mdev_accept, int bound_dev_if,
147+
int dif, int sdif)
148+
{
149+
if (!bound_dev_if)
150+
return !sdif || l3mdev_accept;
151+
return bound_dev_if == dif || bound_dev_if == sdif;
152+
}
153+
146154
struct inet_cork {
147155
unsigned int flags;
148156
__be32 addr;

net/ipv4/inet_hashtables.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
235235
{
236236
int score = -1;
237237
struct inet_sock *inet = inet_sk(sk);
238+
bool dev_match;
238239

239240
if (net_eq(sock_net(sk), net) && inet->inet_num == hnum &&
240241
!ipv6_only_sock(sk)) {
@@ -245,15 +246,12 @@ static inline int compute_score(struct sock *sk, struct net *net,
245246
return -1;
246247
score += 4;
247248
}
248-
if (sk->sk_bound_dev_if || exact_dif) {
249-
bool dev_match = (sk->sk_bound_dev_if == dif ||
250-
sk->sk_bound_dev_if == sdif);
249+
dev_match = inet_sk_bound_dev_eq(net, sk->sk_bound_dev_if,
250+
dif, sdif);
251+
if (!dev_match)
252+
return -1;
253+
score += 4;
251254

252-
if (!dev_match)
253-
return -1;
254-
if (sk->sk_bound_dev_if)
255-
score += 4;
256-
}
257255
if (sk->sk_incoming_cpu == raw_smp_processor_id())
258256
score++;
259257
}

net/ipv6/inet6_hashtables.c

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ static inline int compute_score(struct sock *sk, struct net *net,
9999
const int dif, const int sdif, bool exact_dif)
100100
{
101101
int score = -1;
102+
bool dev_match;
102103

103104
if (net_eq(sock_net(sk), net) && inet_sk(sk)->inet_num == hnum &&
104105
sk->sk_family == PF_INET6) {
@@ -109,15 +110,12 @@ static inline int compute_score(struct sock *sk, struct net *net,
109110
return -1;
110111
score++;
111112
}
112-
if (sk->sk_bound_dev_if || exact_dif) {
113-
bool dev_match = (sk->sk_bound_dev_if == dif ||
114-
sk->sk_bound_dev_if == sdif);
113+
dev_match = inet_sk_bound_dev_eq(net, sk->sk_bound_dev_if,
114+
dif, sdif);
115+
if (!dev_match)
116+
return -1;
117+
score++;
115118

116-
if (!dev_match)
117-
return -1;
118-
if (sk->sk_bound_dev_if)
119-
score++;
120-
}
121119
if (sk->sk_incoming_cpu == raw_smp_processor_id())
122120
score++;
123121
}

0 commit comments

Comments
 (0)