mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	xfrm: take care of request sockets
TCP SYNACK messages might now be attached to request sockets.
XFRM needs to get back to a listener socket.
Adds new helpers that might be used elsewhere :
sk_to_full_sk() and sk_const_to_full_sk()
Note: We also need to add RCU protection for xfrm lookups,
now TCP/DCCP have lockless listener processing. This will
be addressed in separate patches.
Fixes: ca6fb06518 ("tcp: attach SYNACK messages to request sockets instead of listener")
Reported-by: Dave Jones <davej@codemonkey.org.uk>
Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
			
			
This commit is contained in:
		
							parent
							
								
									69ce6487dc
								
							
						
					
					
						commit
						bd5eb35f16
					
				
					 2 changed files with 25 additions and 4 deletions
				
			
		| 
						 | 
					@ -210,18 +210,37 @@ struct inet_sock {
 | 
				
			||||||
#define IP_CMSG_ORIGDSTADDR	BIT(6)
 | 
					#define IP_CMSG_ORIGDSTADDR	BIT(6)
 | 
				
			||||||
#define IP_CMSG_CHECKSUM	BIT(7)
 | 
					#define IP_CMSG_CHECKSUM	BIT(7)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* SYNACK messages might be attached to request sockets.
 | 
					/**
 | 
				
			||||||
 | 
					 * sk_to_full_sk - Access to a full socket
 | 
				
			||||||
 | 
					 * @sk: pointer to a socket
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * SYNACK messages might be attached to request sockets.
 | 
				
			||||||
 * Some places want to reach the listener in this case.
 | 
					 * Some places want to reach the listener in this case.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static inline struct sock *skb_to_full_sk(const struct sk_buff *skb)
 | 
					static inline struct sock *sk_to_full_sk(struct sock *sk)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct sock *sk = skb->sk;
 | 
					#ifdef CONFIG_INET
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (sk && sk->sk_state == TCP_NEW_SYN_RECV)
 | 
						if (sk && sk->sk_state == TCP_NEW_SYN_RECV)
 | 
				
			||||||
		sk = inet_reqsk(sk)->rsk_listener;
 | 
							sk = inet_reqsk(sk)->rsk_listener;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
	return sk;
 | 
						return sk;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* sk_to_full_sk() variant with a const argument */
 | 
				
			||||||
 | 
					static inline const struct sock *sk_const_to_full_sk(const struct sock *sk)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					#ifdef CONFIG_INET
 | 
				
			||||||
 | 
						if (sk && sk->sk_state == TCP_NEW_SYN_RECV)
 | 
				
			||||||
 | 
							sk = ((const struct request_sock *)sk)->rsk_listener;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
						return sk;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static inline struct sock *skb_to_full_sk(const struct sk_buff *skb)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						return sk_to_full_sk(skb->sk);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static inline struct inet_sock *inet_sk(const struct sock *sk)
 | 
					static inline struct inet_sock *inet_sk(const struct sock *sk)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return (struct inet_sock *)sk;
 | 
						return (struct inet_sock *)sk;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2198,6 +2198,7 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
 | 
				
			||||||
	xdst = NULL;
 | 
						xdst = NULL;
 | 
				
			||||||
	route = NULL;
 | 
						route = NULL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sk = sk_const_to_full_sk(sk);
 | 
				
			||||||
	if (sk && sk->sk_policy[XFRM_POLICY_OUT]) {
 | 
						if (sk && sk->sk_policy[XFRM_POLICY_OUT]) {
 | 
				
			||||||
		num_pols = 1;
 | 
							num_pols = 1;
 | 
				
			||||||
		pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
 | 
							pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
 | 
				
			||||||
| 
						 | 
					@ -2477,6 +2478,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pol = NULL;
 | 
						pol = NULL;
 | 
				
			||||||
 | 
						sk = sk_to_full_sk(sk);
 | 
				
			||||||
	if (sk && sk->sk_policy[dir]) {
 | 
						if (sk && sk->sk_policy[dir]) {
 | 
				
			||||||
		pol = xfrm_sk_policy_lookup(sk, dir, &fl);
 | 
							pol = xfrm_sk_policy_lookup(sk, dir, &fl);
 | 
				
			||||||
		if (IS_ERR(pol)) {
 | 
							if (IS_ERR(pol)) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue