Unverified Commit 5854672e authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!2895 netfilter: conntrack: dccp: copy entire header to stack buffer, not just basic one

parents b31404af 6d9812b4
Loading
Loading
Loading
Loading
+49 −3
Original line number Diff line number Diff line
@@ -433,17 +433,47 @@ static u64 dccp_ack_seq(const struct dccp_hdr *dh)
		     ntohl(dhack->dccph_ack_nr_low);
}

struct nf_conntrack_dccp_buf {
	struct dccp_hdr dh;	 /* generic header part */
	struct dccp_hdr_ext ext; /* optional depending dh->dccph_x */
	union {			 /* depends on header type */
		struct dccp_hdr_ack_bits ack;
		struct dccp_hdr_request req;
		struct dccp_hdr_response response;
		struct dccp_hdr_reset rst;
	} u;
};

static struct dccp_hdr *
dccp_header_pointer(const struct sk_buff *skb, int offset, const struct dccp_hdr *dh,
		    struct nf_conntrack_dccp_buf *buf)
{
	unsigned int hdrlen = __dccp_hdr_len(dh);

	if (hdrlen > sizeof(*buf))
		return NULL;

	return skb_header_pointer(skb, offset, hdrlen, buf);
}

static int dccp_packet(struct nf_conn *ct, const struct sk_buff *skb,
		       unsigned int dataoff, enum ip_conntrack_info ctinfo)
{
	enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
	struct dccp_hdr _dh, *dh;
	struct nf_conntrack_dccp_buf _dh;
	u_int8_t type, old_state, new_state;
	enum ct_dccp_roles role;
	unsigned int *timeouts;
	struct dccp_hdr *dh;

	dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
	dh = skb_header_pointer(skb, dataoff, sizeof(*dh), &_dh.dh);
	BUG_ON(dh == NULL);

	/* pull again, including possible 48 bit sequences and subtype header */
	dh = dccp_header_pointer(skb, dataoff, dh, &_dh);
	if (!dh)
		return NF_DROP;

	type = dh->dccph_type;

	if (type == DCCP_PKT_RESET &&
@@ -526,10 +556,20 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl,
		      struct sk_buff *skb, unsigned int dataoff,
		      u_int8_t pf, unsigned int hooknum)
{
	static const unsigned long require_seq48 = 1 << DCCP_PKT_REQUEST |
						   1 << DCCP_PKT_RESPONSE |
						   1 << DCCP_PKT_CLOSEREQ |
						   1 << DCCP_PKT_CLOSE |
						   1 << DCCP_PKT_RESET |
						   1 << DCCP_PKT_SYNC |
						   1 << DCCP_PKT_SYNCACK;
	struct dccp_hdr _dh, *dh;
	unsigned int dccp_len = skb->len - dataoff;
	unsigned int cscov;
	const char *msg;
	u8 type;

	BUILD_BUG_ON(DCCP_PKT_INVALID >= BITS_PER_LONG);

	dh = skb_header_pointer(skb, dataoff, sizeof(_dh), &_dh);
	if (dh == NULL) {
@@ -559,11 +599,17 @@ static int dccp_error(struct net *net, struct nf_conn *tmpl,
		goto out_invalid;
	}

	if (dh->dccph_type >= DCCP_PKT_INVALID) {
	type = dh->dccph_type;
	if (type >= DCCP_PKT_INVALID) {
		msg = "nf_ct_dccp: reserved packet type ";
		goto out_invalid;
	}

	if (test_bit(type, &require_seq48) && !dh->dccph_x) {
		msg = "nf_ct_dccp: type lacks 48bit sequence numbers";
		goto out_invalid;
	}

	return NF_ACCEPT;

out_invalid: