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

!1604 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/5LGGZAJFGQ7GMAJWNGCSQVWZZ2K26FKH/ 
Backport CVE-2023-3863 fix commits.

v2:
  - Resend the patchset.

Krzysztof Kozlowski (1):
  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/1604

 

Reviewed-by: default avatarYue Haibing <yuehaibing@huawei.com>
Signed-off-by: default avatarJialin Zhang <zhangjialin11@huawei.com>
parents 8cbc665c d0ea613f
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -202,7 +202,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
@@ -359,6 +359,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");

@@ -370,8 +371,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);

@@ -381,8 +384,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
@@ -17,6 +17,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);

@@ -143,7 +145,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);

@@ -170,7 +172,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);
}
@@ -283,12 +284,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;
}
@@ -609,12 +631,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;
@@ -631,12 +656,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)
@@ -1522,6 +1551,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;
}

@@ -1538,6 +1569,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,
@@ -1563,6 +1596,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)
@@ -1613,7 +1648,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");
+12 −9
Original line number Diff line number Diff line
@@ -99,7 +99,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,
@@ -181,7 +181,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);
@@ -698,24 +698,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;
@@ -760,8 +758,13 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,

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

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
@@ -1039,11 +1039,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);

@@ -1105,7 +1108,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]);
@@ -1117,6 +1120,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);

@@ -1172,7 +1178,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])
@@ -1191,7 +1197,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;
@@ -1201,10 +1207,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