Unverified Commit 35d90a85 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!1595 net: nfc: Fix CVE-2023-3863

Merge Pull Request from: @ci-robot 
 
PR sync from: Ziyang Xuan <william.xuanziyang@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/H6ZQ55XGUXRWXUV5UOR5EIVMPTK4H3Z2/ 
Backport CVE-2023-3863 fix commits.

Aditya Pakki (1):
  nfc: Fix to check for kmemdup failure

Krzysztof Kozlowski (2):
  nfc: llcp: nullify llcp_sock->dev on connect() error paths
  nfc: llcp: simplify llcp_sock_connect() error paths

Lin Ma (1):
  net: nfc: Fix use-after-free caused by nfc_llcp_find_local


-- 
2.25.1
 
https://gitee.com/src-openeuler/kernel/issues/I7NLJR 
 
Link:https://gitee.com/openeuler/kernel/pulls/1595

 

Reviewed-by: default avatarYue Haibing <yuehaibing@huawei.com>
Signed-off-by: default avatarLiu YongQiang <liuyongqiang13@huawei.com>
parents 7f325203 7c9ed847
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -214,7 +214,6 @@ void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s);
void nfc_llcp_sock_unlink(struct llcp_sock_list *l, struct sock *s);
void nfc_llcp_socket_remote_param_init(struct nfc_llcp_sock *sock);
struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local);
int nfc_llcp_local_put(struct nfc_llcp_local *local);
u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
			 struct nfc_llcp_sock *sock);
+9 −3
Original line number Diff line number Diff line
@@ -371,6 +371,7 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)
	struct sk_buff *skb;
	struct nfc_llcp_local *local;
	u16 size = 0;
	int err;

	pr_debug("Sending SYMM\n");

@@ -382,8 +383,10 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)
	size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;

	skb = alloc_skb(size, GFP_KERNEL);
	if (skb == NULL)
		return -ENOMEM;
	if (skb == NULL) {
		err = -ENOMEM;
		goto out;
	}

	skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);

@@ -393,8 +396,11 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)

	nfc_llcp_send_to_raw_sock(local, skb, NFC_DIRECTION_TX);

	return nfc_data_exchange(dev, local->target_idx, skb,
	err = nfc_data_exchange(dev, local->target_idx, skb,
				 nfc_llcp_recv, local);
out:
	nfc_llcp_local_put(local);
	return err;
}

int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
+42 −7
Original line number Diff line number Diff line
@@ -29,6 +29,8 @@
static u8 llcp_magic[3] = {0x46, 0x66, 0x6d};

static LIST_HEAD(llcp_devices);
/* Protects llcp_devices list */
static DEFINE_SPINLOCK(llcp_devices_lock);

static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb);

@@ -155,7 +157,7 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool device,
	write_unlock(&local->raw_sockets.lock);
}

struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
static struct nfc_llcp_local *nfc_llcp_local_get(struct nfc_llcp_local *local)
{
	kref_get(&local->ref);

@@ -182,7 +184,6 @@ static void local_release(struct kref *ref)

	local = container_of(ref, struct nfc_llcp_local, ref);

	list_del(&local->list);
	local_cleanup(local);
	kfree(local);
}
@@ -295,12 +296,33 @@ static void nfc_llcp_sdreq_timer(struct timer_list *t)
struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev)
{
	struct nfc_llcp_local *local;
	struct nfc_llcp_local *res = NULL;

	spin_lock(&llcp_devices_lock);
	list_for_each_entry(local, &llcp_devices, list)
		if (local->dev == dev)
		if (local->dev == dev) {
			res = nfc_llcp_local_get(local);
			break;
		}
	spin_unlock(&llcp_devices_lock);

	return res;
}

static struct nfc_llcp_local *nfc_llcp_remove_local(struct nfc_dev *dev)
{
	struct nfc_llcp_local *local, *tmp;

	spin_lock(&llcp_devices_lock);
	list_for_each_entry_safe(local, tmp, &llcp_devices, list)
		if (local->dev == dev) {
			list_del(&local->list);
			spin_unlock(&llcp_devices_lock);
			return local;
		}
	spin_unlock(&llcp_devices_lock);

	pr_debug("No device found\n");
	pr_warn("Shutting down device not found\n");

	return NULL;
}
@@ -621,12 +643,15 @@ u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len)

	*general_bytes_len = local->gb_len;

	nfc_llcp_local_put(local);

	return local->gb;
}

int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len)
{
	struct nfc_llcp_local *local;
	int err;

	if (gb_len < 3 || gb_len > NFC_MAX_GT_LEN)
		return -EINVAL;
@@ -643,12 +668,16 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len)

	if (memcmp(local->remote_gb, llcp_magic, 3)) {
		pr_err("MAC does not support LLCP\n");
		return -EINVAL;
		err = -EINVAL;
		goto out;
	}

	return nfc_llcp_parse_gb_tlv(local,
	err = nfc_llcp_parse_gb_tlv(local,
				     &local->remote_gb[3],
				     local->remote_gb_len - 3);
out:
	nfc_llcp_local_put(local);
	return err;
}

static u8 nfc_llcp_dsap(struct sk_buff *pdu)
@@ -1534,6 +1563,8 @@ int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb)

	__nfc_llcp_recv(local, skb);

	nfc_llcp_local_put(local);

	return 0;
}

@@ -1550,6 +1581,8 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev)

	/* Close and purge all existing sockets */
	nfc_llcp_socket_release(local, true, 0);

	nfc_llcp_local_put(local);
}

void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
@@ -1575,6 +1608,8 @@ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
		mod_timer(&local->link_timer,
			  jiffies + msecs_to_jiffies(local->remote_lto));
	}

	nfc_llcp_local_put(local);
}

int nfc_llcp_register_device(struct nfc_dev *ndev)
@@ -1625,7 +1660,7 @@ int nfc_llcp_register_device(struct nfc_dev *ndev)

void nfc_llcp_unregister_device(struct nfc_dev *dev)
{
	struct nfc_llcp_local *local = nfc_llcp_find_local(dev);
	struct nfc_llcp_local *local = nfc_llcp_remove_local(dev);

	if (local == NULL) {
		pr_debug("No such device\n");
+20 −12
Original line number Diff line number Diff line
@@ -111,7 +111,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
	}

	llcp_sock->dev = dev;
	llcp_sock->local = nfc_llcp_local_get(local);
	llcp_sock->local = local;
	llcp_sock->nfc_protocol = llcp_addr.nfc_protocol;
	llcp_sock->service_name_len = min_t(unsigned int,
					    llcp_addr.service_name_len,
@@ -193,7 +193,7 @@ static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr *addr,
	}

	llcp_sock->dev = dev;
	llcp_sock->local = nfc_llcp_local_get(local);
	llcp_sock->local = local;
	llcp_sock->nfc_protocol = llcp_addr.nfc_protocol;

	nfc_llcp_sock_link(&local->raw_sockets, sk);
@@ -710,24 +710,22 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
	if (dev->dep_link_up == false) {
		ret = -ENOLINK;
		device_unlock(&dev->dev);
		goto put_dev;
		goto sock_llcp_put_local;
	}
	device_unlock(&dev->dev);

	if (local->rf_mode == NFC_RF_INITIATOR &&
	    addr->target_idx != local->target_idx) {
		ret = -ENOLINK;
		goto put_dev;
		goto sock_llcp_put_local;
	}

	llcp_sock->dev = dev;
	llcp_sock->local = nfc_llcp_local_get(local);
	llcp_sock->local = local;
	llcp_sock->ssap = nfc_llcp_get_local_ssap(local);
	if (llcp_sock->ssap == LLCP_SAP_MAX) {
		nfc_llcp_local_put(llcp_sock->local);
		llcp_sock->local = NULL;
		ret = -ENOMEM;
		goto put_dev;
		goto sock_llcp_nullify;
	}

	llcp_sock->reserved_ssap = llcp_sock->ssap;
@@ -743,6 +741,10 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
	llcp_sock->service_name = kmemdup(addr->service_name,
					  llcp_sock->service_name_len,
					  GFP_KERNEL);
	if (!llcp_sock->service_name) {
		ret = -ENOMEM;
		goto sock_llcp_release;
	}

	nfc_llcp_sock_link(&local->connecting_sockets, sk);

@@ -762,14 +764,20 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
	return ret;

sock_unlink:
	nfc_llcp_put_ssap(local, llcp_sock->ssap);
	nfc_llcp_local_put(llcp_sock->local);
	llcp_sock->local = NULL;

	nfc_llcp_sock_unlink(&local->connecting_sockets, sk);
	kfree(llcp_sock->service_name);
	llcp_sock->service_name = NULL;

sock_llcp_release:
	nfc_llcp_put_ssap(local, llcp_sock->ssap);

sock_llcp_nullify:
	llcp_sock->local = NULL;
	llcp_sock->dev = NULL;

sock_llcp_put_local:
	nfc_llcp_local_put(local);

put_dev:
	nfc_put_device(dev);

+15 −5
Original line number Diff line number Diff line
@@ -1051,11 +1051,14 @@ static int nfc_genl_llc_get_params(struct sk_buff *skb, struct genl_info *info)
	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
	if (!msg) {
		rc = -ENOMEM;
		goto exit;
		goto put_local;
	}

	rc = nfc_genl_send_params(msg, local, info->snd_portid, info->snd_seq);

put_local:
	nfc_llcp_local_put(local);

exit:
	device_unlock(&dev->dev);

@@ -1117,7 +1120,7 @@ static int nfc_genl_llc_set_params(struct sk_buff *skb, struct genl_info *info)
	if (info->attrs[NFC_ATTR_LLC_PARAM_LTO]) {
		if (dev->dep_link_up) {
			rc = -EINPROGRESS;
			goto exit;
			goto put_local;
		}

		local->lto = nla_get_u8(info->attrs[NFC_ATTR_LLC_PARAM_LTO]);
@@ -1129,6 +1132,9 @@ static int nfc_genl_llc_set_params(struct sk_buff *skb, struct genl_info *info)
	if (info->attrs[NFC_ATTR_LLC_PARAM_MIUX])
		local->miux = cpu_to_be16(miux);

put_local:
	nfc_llcp_local_put(local);

exit:
	device_unlock(&dev->dev);

@@ -1183,7 +1189,7 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)

		if (rc != 0) {
			rc = -EINVAL;
			goto exit;
			goto put_local;
		}

		if (!sdp_attrs[NFC_SDP_ATTR_URI])
@@ -1202,7 +1208,7 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)
		sdreq = nfc_llcp_build_sdreq_tlv(tid, uri, uri_len);
		if (sdreq == NULL) {
			rc = -ENOMEM;
			goto exit;
			goto put_local;
		}

		tlvs_len += sdreq->tlv_len;
@@ -1212,10 +1218,14 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)

	if (hlist_empty(&sdreq_list)) {
		rc = -EINVAL;
		goto exit;
		goto put_local;
	}

	rc = nfc_llcp_send_snl_sdreq(local, &sdreq_list, tlvs_len);

put_local:
	nfc_llcp_local_put(local);

exit:
	device_unlock(&dev->dev);

Loading