Skip to content

Commit

Permalink
xfrm: take care of request sockets
Browse files Browse the repository at this point in the history
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: ca6fb06 ("tcp: attach SYNACK messages to request sockets instead of listener")
Reported-by: Dave Jones <[email protected]>
Signed-off-by: Eric Dumazet <[email protected]>
Cc: Steffen Klassert <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Eric Dumazet authored and davem330 committed Dec 7, 2015
1 parent 69ce648 commit bd5eb35
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 4 deletions.
27 changes: 23 additions & 4 deletions include/net/inet_sock.h
Original file line number Diff line number Diff line change
Expand Up @@ -210,18 +210,37 @@ struct inet_sock {
#define IP_CMSG_ORIGDSTADDR BIT(6)
#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.
*/
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)
sk = inet_reqsk(sk)->rsk_listener;
#endif
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)
{
return (struct inet_sock *)sk;
Expand Down
2 changes: 2 additions & 0 deletions net/xfrm/xfrm_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -2198,6 +2198,7 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
xdst = NULL;
route = NULL;

sk = sk_const_to_full_sk(sk);
if (sk && sk->sk_policy[XFRM_POLICY_OUT]) {
num_pols = 1;
pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
Expand Down Expand Up @@ -2477,6 +2478,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
}

pol = NULL;
sk = sk_to_full_sk(sk);
if (sk && sk->sk_policy[dir]) {
pol = xfrm_sk_policy_lookup(sk, dir, &fl);
if (IS_ERR(pol)) {
Expand Down

0 comments on commit bd5eb35

Please sign in to comment.