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

Commit 8a73cd09 authored by Gerrit Renker's avatar Gerrit Renker Committed by David S. Miller
Browse files

[DCCP]: calling dccp_v{4,6}_reqsk_send_ack is a BUG

This patch removes two functions, the send_ack functions of request_sock,
which are not called/used by the DCCP code. It is correct that these
functions are not called, below is a justification why calling these
functions (on a passive socket in the LISTEN/RESPOND state) would mean
a DCCP protocol violation.

A) Background: using request_sock in TCP:
parent f6484f7c
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -131,6 +131,8 @@ extern int dccp_retransmit_skb(struct sock *sk, struct sk_buff *skb);


extern void dccp_send_ack(struct sock *sk);
extern void dccp_send_ack(struct sock *sk);
extern void dccp_send_delayed_ack(struct sock *sk);
extern void dccp_send_delayed_ack(struct sock *sk);
extern void dccp_reqsk_send_ack(struct sk_buff *sk, struct request_sock *rsk);

extern void dccp_send_sync(struct sock *sk, const u64 seq,
extern void dccp_send_sync(struct sock *sk, const u64 seq,
			   const enum dccp_pkt_type pkt_type);
			   const enum dccp_pkt_type pkt_type);


+1 −47
Original line number Original line Diff line number Diff line
@@ -193,52 +193,6 @@ static inline void dccp_do_pmtu_discovery(struct sock *sk,
	} /* else let the usual retransmit timer handle it */
	} /* else let the usual retransmit timer handle it */
}
}


static void dccp_v4_reqsk_send_ack(struct sk_buff *rxskb,
				   struct request_sock *req)
{
	int err;
	struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
	const u32 dccp_hdr_ack_len = sizeof(struct dccp_hdr) +
				     sizeof(struct dccp_hdr_ext) +
				     sizeof(struct dccp_hdr_ack_bits);
	struct sk_buff *skb;

	if (((struct rtable *)rxskb->dst)->rt_type != RTN_LOCAL)
		return;

	skb = alloc_skb(dccp_v4_ctl_socket->sk->sk_prot->max_header, GFP_ATOMIC);
	if (skb == NULL)
		return;

	/* Reserve space for headers. */
	skb_reserve(skb, dccp_v4_ctl_socket->sk->sk_prot->max_header);
	skb->dst = dst_clone(rxskb->dst);

	dh = dccp_zeroed_hdr(skb, dccp_hdr_ack_len);

	/* Build DCCP header and checksum it. */
	dh->dccph_type	   = DCCP_PKT_ACK;
	dh->dccph_sport	   = rxdh->dccph_dport;
	dh->dccph_dport	   = rxdh->dccph_sport;
	dh->dccph_doff	   = dccp_hdr_ack_len / 4;
	dh->dccph_x	   = 1;

	dccp_hdr_set_seq(dh, DCCP_SKB_CB(rxskb)->dccpd_ack_seq);
	dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
			 DCCP_SKB_CB(rxskb)->dccpd_seq);

	bh_lock_sock(dccp_v4_ctl_socket->sk);
	err = ip_build_and_send_pkt(skb, dccp_v4_ctl_socket->sk,
				    rxskb->nh.iph->daddr,
				    rxskb->nh.iph->saddr, NULL);
	bh_unlock_sock(dccp_v4_ctl_socket->sk);

	if (err == NET_XMIT_CN || err == 0) {
		DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
		DCCP_INC_STATS_BH(DCCP_MIB_OUTRSTS);
	}
}

static int dccp_v4_send_response(struct sock *sk, struct request_sock *req,
static int dccp_v4_send_response(struct sock *sk, struct request_sock *req,
				 struct dst_entry *dst)
				 struct dst_entry *dst)
{
{
@@ -1014,7 +968,7 @@ static struct request_sock_ops dccp_request_sock_ops __read_mostly = {
	.family		= PF_INET,
	.family		= PF_INET,
	.obj_size	= sizeof(struct dccp_request_sock),
	.obj_size	= sizeof(struct dccp_request_sock),
	.rtx_syn_ack	= dccp_v4_send_response,
	.rtx_syn_ack	= dccp_v4_send_response,
	.send_ack	= dccp_v4_reqsk_send_ack,
	.send_ack	= dccp_reqsk_send_ack,
	.destructor	= dccp_v4_reqsk_destructor,
	.destructor	= dccp_v4_reqsk_destructor,
	.send_reset	= dccp_v4_ctl_send_reset,
	.send_reset	= dccp_v4_ctl_send_reset,
};
};
+1 −56
Original line number Original line Diff line number Diff line
@@ -37,8 +37,6 @@
static struct socket *dccp_v6_ctl_socket;
static struct socket *dccp_v6_ctl_socket;


static void dccp_v6_ctl_send_reset(struct sk_buff *skb);
static void dccp_v6_ctl_send_reset(struct sk_buff *skb);
static void dccp_v6_reqsk_send_ack(struct sk_buff *skb,
				   struct request_sock *req);
static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb);
static void dccp_v6_send_check(struct sock *sk, int len, struct sk_buff *skb);


static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
static int dccp_v6_do_rcv(struct sock *sk, struct sk_buff *skb);
@@ -493,7 +491,7 @@ static struct request_sock_ops dccp6_request_sock_ops = {
	.family		= AF_INET6,
	.family		= AF_INET6,
	.obj_size	= sizeof(struct dccp6_request_sock),
	.obj_size	= sizeof(struct dccp6_request_sock),
	.rtx_syn_ack	= dccp_v6_send_response,
	.rtx_syn_ack	= dccp_v6_send_response,
	.send_ack	= dccp_v6_reqsk_send_ack,
	.send_ack	= dccp_reqsk_send_ack,
	.destructor	= dccp_v6_reqsk_destructor,
	.destructor	= dccp_v6_reqsk_destructor,
	.send_reset	= dccp_v6_ctl_send_reset,
	.send_reset	= dccp_v6_ctl_send_reset,
};
};
@@ -582,59 +580,6 @@ static void dccp_v6_ctl_send_reset(struct sk_buff *rxskb)
	kfree_skb(skb);
	kfree_skb(skb);
}
}


static void dccp_v6_reqsk_send_ack(struct sk_buff *rxskb,
				   struct request_sock *req)
{
	struct flowi fl;
	struct dccp_hdr *rxdh = dccp_hdr(rxskb), *dh;
	const u32 dccp_hdr_ack_len = sizeof(struct dccp_hdr) +
				     sizeof(struct dccp_hdr_ext) +
				     sizeof(struct dccp_hdr_ack_bits);
	struct sk_buff *skb;

	skb = alloc_skb(dccp_v6_ctl_socket->sk->sk_prot->max_header,
			GFP_ATOMIC);
	if (skb == NULL)
		return;

	skb_reserve(skb, dccp_v6_ctl_socket->sk->sk_prot->max_header);

	dh = dccp_zeroed_hdr(skb, dccp_hdr_ack_len);

	/* Build DCCP header and checksum it. */
	dh->dccph_type	= DCCP_PKT_ACK;
	dh->dccph_sport = rxdh->dccph_dport;
	dh->dccph_dport = rxdh->dccph_sport;
	dh->dccph_doff	= dccp_hdr_ack_len / 4;
	dh->dccph_x	= 1;

	dccp_hdr_set_seq(dh, DCCP_SKB_CB(rxskb)->dccpd_ack_seq);
	dccp_hdr_set_ack(dccp_hdr_ack_bits(skb),
			 DCCP_SKB_CB(rxskb)->dccpd_seq);

	memset(&fl, 0, sizeof(fl));
	ipv6_addr_copy(&fl.fl6_dst, &rxskb->nh.ipv6h->saddr);
	ipv6_addr_copy(&fl.fl6_src, &rxskb->nh.ipv6h->daddr);

	/* FIXME: calculate checksum, IPv4 also should... */

	fl.proto = IPPROTO_DCCP;
	fl.oif = inet6_iif(rxskb);
	fl.fl_ip_dport = dh->dccph_dport;
	fl.fl_ip_sport = dh->dccph_sport;
	security_req_classify_flow(req, &fl);

	if (!ip6_dst_lookup(NULL, &skb->dst, &fl)) {
		if (xfrm_lookup(&skb->dst, &fl, NULL, 0) >= 0) {
			ip6_xmit(dccp_v6_ctl_socket->sk, skb, &fl, NULL, 0);
			DCCP_INC_STATS_BH(DCCP_MIB_OUTSEGS);
			return;
		}
	}

	kfree_skb(skb);
}

static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
static struct sock *dccp_v6_hnd_req(struct sock *sk,struct sk_buff *skb)
{
{
	const struct dccp_hdr *dh = dccp_hdr(skb);
	const struct dccp_hdr *dh = dccp_hdr(skb);
+10 −0
Original line number Original line Diff line number Diff line
@@ -11,6 +11,7 @@
 */
 */


#include <linux/dccp.h>
#include <linux/dccp.h>
#include <linux/kernel.h>
#include <linux/skbuff.h>
#include <linux/skbuff.h>
#include <linux/timer.h>
#include <linux/timer.h>


@@ -283,3 +284,12 @@ int dccp_child_process(struct sock *parent, struct sock *child,
}
}


EXPORT_SYMBOL_GPL(dccp_child_process);
EXPORT_SYMBOL_GPL(dccp_child_process);

void dccp_reqsk_send_ack(struct sk_buff *skb, struct request_sock *rsk)
{
	pr_info(KERN_WARNING "DCCP: ACK packets are never sent in "
			     "LISTEN/RESPOND state\n");
	dump_stack();
}

EXPORT_SYMBOL_GPL(dccp_reqsk_send_ack);