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

Commit 1ec82054 authored by Sean Tranchetti's avatar Sean Tranchetti
Browse files

net: qualcomm: rmnet: Don't reference skb->data directly



In preparation for receiving non-linear SKBs from lower level drivers,
don't access skb->data in functions that will be used on the RX path
unless we know the SKB is linear.

Change-Id: I99429550966d4384d0725b9c72662469a1036552
Signed-off-by: default avatarSean Tranchetti <stranche@codeaurora.org>
parent 3b3e314b
Loading
Loading
Loading
Loading
+12 −8
Original line number Original line Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
 *
 *
 * RMNET Data ingress/egress handler
 * RMNET Data ingress/egress handler
 *
 *
@@ -45,13 +45,15 @@ EXPORT_TRACEPOINT_SYMBOL(rmnet_err);


static int rmnet_check_skb_can_gro(struct sk_buff *skb)
static int rmnet_check_skb_can_gro(struct sk_buff *skb)
{
{
	unsigned char *data = rmnet_map_data_ptr(skb);

	switch (skb->protocol) {
	switch (skb->protocol) {
	case htons(ETH_P_IP):
	case htons(ETH_P_IP):
		if (ip_hdr(skb)->protocol == IPPROTO_TCP)
		if (((struct iphdr *)data)->protocol == IPPROTO_TCP)
			return 0;
			return 0;
		break;
		break;
	case htons(ETH_P_IPV6):
	case htons(ETH_P_IPV6):
		if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP)
		if (((struct ipv6hdr *)data)->nexthdr == IPPROTO_TCP)
			return 0;
			return 0;
		/* Fall through */
		/* Fall through */
	}
	}
@@ -61,7 +63,7 @@ static int rmnet_check_skb_can_gro(struct sk_buff *skb)


void rmnet_set_skb_proto(struct sk_buff *skb)
void rmnet_set_skb_proto(struct sk_buff *skb)
{
{
	switch (skb->data[0] & 0xF0) {
	switch (rmnet_map_data_ptr(skb)[0] & 0xF0) {
	case RMNET_IP_VERSION_4:
	case RMNET_IP_VERSION_4:
		skb->protocol = htons(ETH_P_IP);
		skb->protocol = htons(ETH_P_IP);
		break;
		break;
@@ -129,11 +131,13 @@ static void
__rmnet_map_ingress_handler(struct sk_buff *skb,
__rmnet_map_ingress_handler(struct sk_buff *skb,
			    struct rmnet_port *port)
			    struct rmnet_port *port)
{
{
	struct rmnet_map_header *qmap;
	struct rmnet_endpoint *ep;
	struct rmnet_endpoint *ep;
	u16 len, pad;
	u16 len, pad;
	u8 mux_id;
	u8 mux_id;


	if (RMNET_MAP_GET_CD_BIT(skb)) {
	qmap = (struct rmnet_map_header *)rmnet_map_data_ptr(skb);
	if (qmap->cd_bit) {
		if (port->data_format & RMNET_INGRESS_FORMAT_DL_MARKER) {
		if (port->data_format & RMNET_INGRESS_FORMAT_DL_MARKER) {
			if (!rmnet_map_flow_command(skb, port, false))
			if (!rmnet_map_flow_command(skb, port, false))
				return;
				return;
@@ -145,9 +149,9 @@ __rmnet_map_ingress_handler(struct sk_buff *skb,
		goto free_skb;
		goto free_skb;
	}
	}


	mux_id = RMNET_MAP_GET_MUX_ID(skb);
	mux_id = qmap->mux_id;
	pad = RMNET_MAP_GET_PAD(skb);
	pad = qmap->pad_len;
	len = RMNET_MAP_GET_LENGTH(skb) - pad;
	len = ntohs(qmap->pkt_len) - pad;


	if (mux_id >= RMNET_MAX_LOGICAL_EP)
	if (mux_id >= RMNET_MAX_LOGICAL_EP)
		goto free_skb;
		goto free_skb;
+15 −1
Original line number Original line Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. */
/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. */


#ifndef _RMNET_MAP_H_
#ifndef _RMNET_MAP_H_
#define _RMNET_MAP_H_
#define _RMNET_MAP_H_
@@ -134,6 +134,20 @@ struct rmnet_map_dl_ind {
#define RMNET_MAP_NO_PAD_BYTES        0
#define RMNET_MAP_NO_PAD_BYTES        0
#define RMNET_MAP_ADD_PAD_BYTES       1
#define RMNET_MAP_ADD_PAD_BYTES       1


static inline unsigned char *rmnet_map_data_ptr(struct sk_buff *skb)
{
	return skb->data;
}

static inline struct rmnet_map_control_command *
rmnet_map_get_cmd_start(struct sk_buff *skb)
{
	unsigned char *data = rmnet_map_data_ptr(skb);

	data += sizeof(struct rmnet_map_header);
	return (struct rmnet_map_control_command *)data;
}

struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb,
struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb,
				      struct rmnet_port *port);
				      struct rmnet_port *port);
struct rmnet_map_header *rmnet_map_add_map_header(struct sk_buff *skb,
struct rmnet_map_header *rmnet_map_add_map_header(struct sk_buff *skb,
+10 −8
Original line number Original line Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. */
/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. */


#include <linux/netdevice.h>
#include <linux/netdevice.h>
#include "rmnet_config.h"
#include "rmnet_config.h"
@@ -22,6 +22,7 @@ static u8 rmnet_map_do_flow_control(struct sk_buff *skb,
				    struct rmnet_port *port,
				    struct rmnet_port *port,
				    int enable)
				    int enable)
{
{
	struct rmnet_map_header *qmap;
	struct rmnet_map_control_command *cmd;
	struct rmnet_map_control_command *cmd;
	struct rmnet_endpoint *ep;
	struct rmnet_endpoint *ep;
	struct net_device *vnd;
	struct net_device *vnd;
@@ -31,8 +32,9 @@ static u8 rmnet_map_do_flow_control(struct sk_buff *skb,
	u8 mux_id;
	u8 mux_id;
	int r;
	int r;


	mux_id = RMNET_MAP_GET_MUX_ID(skb);
	qmap = (struct rmnet_map_header *)rmnet_map_data_ptr(skb);
	cmd = RMNET_MAP_GET_CMD_START(skb);
	mux_id = qmap->mux_id;
	cmd = rmnet_map_get_cmd_start(skb);


	if (mux_id >= RMNET_MAX_LOGICAL_EP) {
	if (mux_id >= RMNET_MAX_LOGICAL_EP) {
		kfree_skb(skb);
		kfree_skb(skb);
@@ -77,7 +79,7 @@ static void rmnet_map_send_ack(struct sk_buff *skb,


	skb->protocol = htons(ETH_P_MAP);
	skb->protocol = htons(ETH_P_MAP);


	cmd = RMNET_MAP_GET_CMD_START(skb);
	cmd = rmnet_map_get_cmd_start(skb);
	cmd->cmd_type = type & 0x03;
	cmd->cmd_type = type & 0x03;


	netif_tx_lock(dev);
	netif_tx_lock(dev);
@@ -124,7 +126,7 @@ static void rmnet_map_process_flow_start(struct sk_buff *skb,


	skb_pull(skb, RMNET_MAP_CMD_SIZE);
	skb_pull(skb, RMNET_MAP_CMD_SIZE);


	dlhdr = (struct rmnet_map_dl_ind_hdr *)skb->data;
	dlhdr = (struct rmnet_map_dl_ind_hdr *)rmnet_map_data_ptr(skb);


	port->stats.dl_hdr_last_seq = dlhdr->le.seq;
	port->stats.dl_hdr_last_seq = dlhdr->le.seq;
	port->stats.dl_hdr_last_bytes = dlhdr->le.bytes;
	port->stats.dl_hdr_last_bytes = dlhdr->le.bytes;
@@ -165,7 +167,7 @@ static void rmnet_map_process_flow_end(struct sk_buff *skb,


	skb_pull(skb, RMNET_MAP_CMD_SIZE);
	skb_pull(skb, RMNET_MAP_CMD_SIZE);


	dltrl = (struct rmnet_map_dl_ind_trl *)skb->data;
	dltrl = (struct rmnet_map_dl_ind_trl *)rmnet_map_data_ptr(skb);


	port->stats.dl_trl_last_seq = dltrl->seq_le;
	port->stats.dl_trl_last_seq = dltrl->seq_le;
	port->stats.dl_trl_count++;
	port->stats.dl_trl_count++;
@@ -190,7 +192,7 @@ void rmnet_map_command(struct sk_buff *skb, struct rmnet_port *port)
	unsigned char command_name;
	unsigned char command_name;
	unsigned char rc = 0;
	unsigned char rc = 0;


	cmd = RMNET_MAP_GET_CMD_START(skb);
	cmd = rmnet_map_get_cmd_start(skb);
	command_name = cmd->command_name;
	command_name = cmd->command_name;


	switch (command_name) {
	switch (command_name) {
@@ -217,7 +219,7 @@ int rmnet_map_flow_command(struct sk_buff *skb, struct rmnet_port *port,
	struct rmnet_map_control_command *cmd;
	struct rmnet_map_control_command *cmd;
	unsigned char command_name;
	unsigned char command_name;


	cmd = RMNET_MAP_GET_CMD_START(skb);
	cmd = rmnet_map_get_cmd_start(skb);
	command_name = cmd->command_name;
	command_name = cmd->command_name;


	switch (command_name) {
	switch (command_name) {
+12 −10
Original line number Original line Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
 *
 *
 * RMNET Data MAP protocol
 * RMNET Data MAP protocol
 *
 *
@@ -51,14 +51,14 @@ rmnet_map_ipv4_dl_csum_trailer(struct sk_buff *skb,
	void *txporthdr;
	void *txporthdr;
	__be16 addend;
	__be16 addend;


	ip4h = (struct iphdr *)(skb->data);
	ip4h = (struct iphdr *)rmnet_map_data_ptr(skb);
	if ((ntohs(ip4h->frag_off) & IP_MF) ||
	if ((ntohs(ip4h->frag_off) & IP_MF) ||
	    ((ntohs(ip4h->frag_off) & IP_OFFSET) > 0)) {
	    ((ntohs(ip4h->frag_off) & IP_OFFSET) > 0)) {
		priv->stats.csum_fragmented_pkt++;
		priv->stats.csum_fragmented_pkt++;
		return -EOPNOTSUPP;
		return -EOPNOTSUPP;
	}
	}


	txporthdr = skb->data + ip4h->ihl * 4;
	txporthdr = rmnet_map_data_ptr(skb) + ip4h->ihl * 4;


	csum_field = rmnet_map_get_csum_field(ip4h->protocol, txporthdr);
	csum_field = rmnet_map_get_csum_field(ip4h->protocol, txporthdr);


@@ -122,12 +122,12 @@ rmnet_map_ipv6_dl_csum_trailer(struct sk_buff *skb,
	u16 csum_value, csum_value_final;
	u16 csum_value, csum_value_final;
	__be16 ip6_hdr_csum, addend;
	__be16 ip6_hdr_csum, addend;
	struct ipv6hdr *ip6h;
	struct ipv6hdr *ip6h;
	void *txporthdr;
	void *txporthdr, *data = rmnet_map_data_ptr(skb);
	u32 length;
	u32 length;


	ip6h = (struct ipv6hdr *)(skb->data);
	ip6h = data;


	txporthdr = skb->data + sizeof(struct ipv6hdr);
	txporthdr = data + sizeof(struct ipv6hdr);
	csum_field = rmnet_map_get_csum_field(ip6h->nexthdr, txporthdr);
	csum_field = rmnet_map_get_csum_field(ip6h->nexthdr, txporthdr);


	if (!csum_field) {
	if (!csum_field) {
@@ -138,7 +138,7 @@ rmnet_map_ipv6_dl_csum_trailer(struct sk_buff *skb,
	csum_value = ~ntohs(csum_trailer->csum_value);
	csum_value = ~ntohs(csum_trailer->csum_value);
	ip6_hdr_csum = (__force __be16)
	ip6_hdr_csum = (__force __be16)
			~ntohs((__force __be16)ip_compute_csum(ip6h,
			~ntohs((__force __be16)ip_compute_csum(ip6h,
			       (int)(txporthdr - (void *)(skb->data))));
			       (int)(txporthdr - data)));
	ip6_payload_csum = csum16_sub((__force __sum16)csum_value,
	ip6_payload_csum = csum16_sub((__force __sum16)csum_value,
				      ip6_hdr_csum);
				      ip6_hdr_csum);


@@ -311,12 +311,13 @@ struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb,
{
{
	struct rmnet_map_header *maph;
	struct rmnet_map_header *maph;
	struct sk_buff *skbn;
	struct sk_buff *skbn;
	unsigned char *data = rmnet_map_data_ptr(skb);
	u32 packet_len;
	u32 packet_len;


	if (skb->len == 0)
	if (skb->len == 0)
		return NULL;
		return NULL;


	maph = (struct rmnet_map_header *)skb->data;
	maph = (struct rmnet_map_header *)data;
	packet_len = ntohs(maph->pkt_len) + sizeof(struct rmnet_map_header);
	packet_len = ntohs(maph->pkt_len) + sizeof(struct rmnet_map_header);


	if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4)
	if (port->data_format & RMNET_FLAGS_INGRESS_MAP_CKSUMV4)
@@ -335,7 +336,7 @@ struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb,


	skb_reserve(skbn, RMNET_MAP_DEAGGR_HEADROOM);
	skb_reserve(skbn, RMNET_MAP_DEAGGR_HEADROOM);
	skb_put(skbn, packet_len);
	skb_put(skbn, packet_len);
	memcpy(skbn->data, skb->data, packet_len);
	memcpy(skbn->data, data, packet_len);
	skb_pull(skb, packet_len);
	skb_pull(skb, packet_len);


	return skbn;
	return skbn;
@@ -357,7 +358,8 @@ int rmnet_map_checksum_downlink_packet(struct sk_buff *skb, u16 len)
		return -EOPNOTSUPP;
		return -EOPNOTSUPP;
	}
	}


	csum_trailer = (struct rmnet_map_dl_csum_trailer *)(skb->data + len);
	csum_trailer = (struct rmnet_map_dl_csum_trailer *)
		       (rmnet_map_data_ptr(skb) + len);


	if (!csum_trailer->valid) {
	if (!csum_trailer->valid) {
		priv->stats.csum_valid_unset++;
		priv->stats.csum_valid_unset++;