Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 56ac42bc authored by Huw Davies's avatar Huw Davies Committed by Paul Moore
Browse files

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: default avatarHuw Davies <huw@codeweavers.com>
Signed-off-by: default avatarPaul Moore <paul@paul-moore.com>
parent 1f440c99
Loading
Loading
Loading
Loading
+6 −1
Original line number Diff line number Diff line
@@ -97,8 +97,13 @@ struct inet_request_sock {
	u32                     ir_mark;
	union {
		struct ip_options_rcu	*opt;
#if IS_ENABLED(CONFIG_IPV6)
		struct {
			struct ipv6_txoptions	*ipv6_opt;
			struct sk_buff		*pktopts;
		};
#endif
	};
};

static inline struct inet_request_sock *inet_rsk(const struct request_sock *sk)
+9 −3
Original line number Diff line number Diff line
@@ -216,14 +216,17 @@ static int dccp_v6_send_response(const struct sock *sk, struct request_sock *req
	skb = dccp_make_response(sk, dst, req);
	if (skb != NULL) {
		struct dccp_hdr *dh = dccp_hdr(skb);
		struct ipv6_txoptions *opt;

		dh->dccph_checksum = dccp_v6_csum_finish(skb,
							 &ireq->ir_v6_loc_addr,
							 &ireq->ir_v6_rmt_addr);
		fl6.daddr = ireq->ir_v6_rmt_addr;
		rcu_read_lock();
		err = ip6_xmit(sk, skb, &fl6, rcu_dereference(np->opt),
			       np->tclass);
		opt = ireq->ipv6_opt;
		if (!opt)
			opt = rcu_dereference(np->opt);
		err = ip6_xmit(sk, skb, &fl6, opt, np->tclass);
		rcu_read_unlock();
		err = net_xmit_eval(err);
	}
@@ -236,6 +239,7 @@ static int dccp_v6_send_response(const struct sock *sk, struct request_sock *req
static void dccp_v6_reqsk_destructor(struct request_sock *req)
{
	dccp_feat_list_purge(&dccp_rsk(req)->dreq_featneg);
	kfree(inet_rsk(req)->ipv6_opt);
	kfree_skb(inet_rsk(req)->pktopts);
}

@@ -494,6 +498,8 @@ static struct sock *dccp_v6_request_recv_sock(const struct sock *sk,
	 * Yes, keeping reference count would be much more clever, but we make
	 * one more one thing there: reattach optmem to newsk.
	 */
	opt = ireq->ipv6_opt;
	if (!opt)
		opt = rcu_dereference(np->opt);
	if (opt) {
		opt = ipv6_dup_options(newsk, opt);
+3 −0
Original line number Diff line number Diff line
@@ -6146,6 +6146,9 @@ struct request_sock *inet_reqsk_alloc(const struct request_sock_ops *ops,

		kmemcheck_annotate_bitfield(ireq, flags);
		ireq->opt = NULL;
#if IS_ENABLED(CONFIG_IPV6)
		ireq->pktopts = NULL;
#endif
		atomic64_set(&ireq->ir_cookie, 0);
		ireq->ireq_state = TCP_NEW_SYN_RECV;
		write_pnet(&ireq->ireq_net, sock_net(sk_listener));
+9 −3
Original line number Diff line number Diff line
@@ -443,6 +443,7 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
{
	struct inet_request_sock *ireq = inet_rsk(req);
	struct ipv6_pinfo *np = inet6_sk(sk);
	struct ipv6_txoptions *opt;
	struct flowi6 *fl6 = &fl->u.ip6;
	struct sk_buff *skb;
	int err = -ENOMEM;
@@ -463,8 +464,10 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,
			fl6->flowlabel = ip6_flowlabel(ipv6_hdr(ireq->pktopts));

		rcu_read_lock();
		err = ip6_xmit(sk, skb, fl6, rcu_dereference(np->opt),
			       np->tclass);
		opt = ireq->ipv6_opt;
		if (!opt)
			opt = rcu_dereference(np->opt);
		err = ip6_xmit(sk, skb, fl6, opt, np->tclass);
		rcu_read_unlock();
		err = net_xmit_eval(err);
	}
@@ -476,6 +479,7 @@ static int tcp_v6_send_synack(const struct sock *sk, struct dst_entry *dst,

static void tcp_v6_reqsk_destructor(struct request_sock *req)
{
	kfree(inet_rsk(req)->ipv6_opt);
	kfree_skb(inet_rsk(req)->pktopts);
}

@@ -1107,6 +1111,8 @@ static struct sock *tcp_v6_syn_recv_sock(const struct sock *sk, struct sk_buff *
	   but we make one more one thing there: reattach optmem
	   to newsk.
	 */
	opt = ireq->ipv6_opt;
	if (!opt)
		opt = rcu_dereference(np->opt);
	if (opt) {
		opt = ipv6_dup_options(newsk, opt);