Skip to content

Commit 56ac42b

Browse files
hdmdaviespcmoore
authored andcommitted
ipv6: Allow request socks to contain IPv6 options.
If set, these will take precedence over the parent's options during both sending and child creation. If they're not set, the parent's options (if any) will be used. This is to allow the security_inet_conn_request() hook to modify the IPv6 options in just the same way that it already may do for IPv4. Signed-off-by: Huw Davies <[email protected]> Signed-off-by: Paul Moore <[email protected]>
1 parent 1f440c9 commit 56ac42b

File tree

4 files changed

+27
-7
lines changed

4 files changed

+27
-7
lines changed

include/net/inet_sock.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,12 @@ struct inet_request_sock {
9797
u32 ir_mark;
9898
union {
9999
struct ip_options_rcu *opt;
100-
struct sk_buff *pktopts;
100+
#if IS_ENABLED(CONFIG_IPV6)
101+
struct {
102+
struct ipv6_txoptions *ipv6_opt;
103+
struct sk_buff *pktopts;
104+
};
105+
#endif
101106
};
102107
};
103108

net/dccp/ipv6.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -216,14 +216,17 @@ static int dccp_v6_send_response(const struct sock *sk, struct request_sock *req
216216
skb = dccp_make_response(sk, dst, req);
217217
if (skb != NULL) {
218218
struct dccp_hdr *dh = dccp_hdr(skb);
219+
struct ipv6_txoptions *opt;
219220

220221
dh->dccph_checksum = dccp_v6_csum_finish(skb,
221222
&ireq->ir_v6_loc_addr,
222223
&ireq->ir_v6_rmt_addr);
223224
fl6.daddr = ireq->ir_v6_rmt_addr;
224225
rcu_read_lock();
225-
err = ip6_xmit(sk, skb, &fl6, rcu_dereference(np->opt),
226-
np->tclass);
226+
opt = ireq->ipv6_opt;
227+
if (!opt)
228+
opt = rcu_dereference(np->opt);
229+
err = ip6_xmit(sk, skb, &fl6, opt, np->tclass);
227230
rcu_read_unlock();
228231
err = net_xmit_eval(err);
229232
}
@@ -236,6 +239,7 @@ static int dccp_v6_send_response(const struct sock *sk, struct request_sock *req
236239
static void dccp_v6_reqsk_destructor(struct request_sock *req)
237240
{
238241
dccp_feat_list_purge(&dccp_rsk(req)->dreq_featneg);
242+
kfree(inet_rsk(req)->ipv6_opt);
239243
kfree_skb(inet_rsk(req)->pktopts);
240244
}
241245

@@ -494,7 +498,9 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk,
494498
* Yes, keeping reference count would be much more clever, but we make
495499
* one more one thing there: reattach optmem to newsk.
496500
*/
497-
opt = rcu_dereference(np->opt);
501+
opt = ireq->ipv6_opt;
502+
if (!opt)
503+
opt = rcu_dereference(np->opt);
498504
if (opt) {
499505
opt = ipv6_dup_options(newsk, opt);
500506
RCU_INIT_POINTER(newnp->opt, opt);

net/ipv4/tcp_input.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6146,6 +6146,9 @@ struct request_sock *inet_reqsk_alloc(const struct request_sock_ops *ops,
61466146

61476147
kmemcheck_annotate_bitfield(ireq, flags);
61486148
ireq->opt = NULL;
6149+
#if IS_ENABLED(CONFIG_IPV6)
6150+
ireq->pktopts = NULL;
6151+
#endif
61496152
atomic64_set(&ireq->ir_cookie, 0);
61506153
ireq->ireq_state = TCP_NEW_SYN_RECV;
61516154
write_pnet(&ireq->ireq_net, sock_net(sk_listener));

net/ipv6/tcp_ipv6.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
443443
{
444444
struct inet_request_sock *ireq = inet_rsk(req);
445445
struct ipv6_pinfo *np = inet6_sk(sk);
446+
struct ipv6_txoptions *opt;
446447
struct flowi6 *fl6 = &fl->u.ip6;
447448
struct sk_buff *skb;
448449
int err = -ENOMEM;
@@ -463,8 +464,10 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
463464
fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts));
464465

465466
rcu_read_lock();
466-
err = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt),
467-
np->tclass);
467+
opt = ireq->ipv6_opt;
468+
if (!opt)
469+
opt = rcu_dereference(np->opt);
470+
err = ip6_xmit(sk, skb, fl6, opt, np->tclass);
468471
rcu_read_unlock();
469472
err = net_xmit_eval(err);
470473
}
@@ -476,6 +479,7 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
476479

477480
static void tcp_v6_reqsk_destructor(struct request_sock *req)
478481
{
482+
kfree(inet_rsk(req)->ipv6_opt);
479483
kfree_skb(inet_rsk(req)->pktopts);
480484
}
481485

@@ -1107,7 +1111,9 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
11071111
but we make one more one thing there: reattach optmem
11081112
to newsk.
11091113
*/
1110-
opt = rcu_dereference(np->opt);
1114+
opt = ireq->ipv6_opt;
1115+
if (!opt)
1116+
opt = rcu_dereference(np->opt);
11111117
if (opt) {
11121118
opt = ipv6_dup_options(newsk, opt);
11131119
RCU_INIT_POINTER(newnp->opt, opt);

0 commit comments

Comments
 (0)