Skip to contentSkip to conversation

sock: Reset dst when changing sk_mark via setsockopt

PATCH Superseded David Barmann 2 participants 2 messages Nov 8, 2018

Subsystems (3)

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 sock: Reset dst when changing sk_mark via setsockopt

When setting the SO_MARK socket option, the dst needs to be reset so that a new route lookup is performed.

This fixes the case where an application wants to change routing by setting a new sk_mark. If this is done after some packets have already been sent, the dst is cached and has no effect.

---
 net/core/sock.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
net/core/sock.c +4 -2
index 7b304e454a38..c74b10be86cb 100644
@@ -952,10 +952,12 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
 			clear_bit(SOCK_PASSSEC, &sock->flags);
 		break;
 	case SO_MARK:
-		if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
+		if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) {
 			ret = -EPERM;
-		else
+		} else {
 			sk->sk_mark = val;
+			sk_dst_reset(sk);
+		}
 		break;
 
 	case SO_RXQ_OVFL:
Signature · 1 line
2.14.5
#1 lore raw
Quoted 17 lines · David Barmann

When setting the SO_MARK socket option, the dst needs to be reset so that a new route lookup is performed.

This fixes the case where an application wants to change routing by setting a new sk_mark. If this is done after some packets have already been sent, the dst is cached and has no effect.

---
 net/core/sock.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
net/core/sock.c +0 -0
index 7b304e454a38..c74b10be86cb 100644

net/core/sock.c int sock_setsockopt(struct socket *sock, int level, int optname, · line 959

Quoted 10 lines
net/core/sock.c +3 -2
@@ -952,10 +952,12 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
 			clear_bit(SOCK_PASSSEC, &sock->flags);
 		break;
 	case SO_MARK:
-		if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
+		if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) {
 			ret = -EPERM;
-		else
+		} else {
 			sk->sk_mark = val;
+			sk_dst_reset(sk);

There is no need to force a sk_dst_reset(sk) if sk_mark was not changed.

I already gave you this feedback, please do not ignore it.

Thanks.