未验证 提交 78484381 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!1634 [sync] PR-1604: net: nfc: Fix CVE-2023-3863

Merge Pull Request from: @openeuler-sync-bot 
 

Origin pull request: 
https://gitee.com/openeuler/kernel/pulls/1604 
 
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/1634 

Reviewed-by: Yue Haibing <yuehaibing@huawei.com> 
Signed-off-by: Jialin Zhang <zhangjialin11@huawei.com> 
...@@ -202,7 +202,6 @@ void nfc_llcp_sock_link(struct llcp_sock_list *l, struct sock *s); ...@@ -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_sock_unlink(struct llcp_sock_list *l, struct sock *s);
void nfc_llcp_socket_remote_param_init(struct nfc_llcp_sock *sock); 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_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); int nfc_llcp_local_put(struct nfc_llcp_local *local);
u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local, u8 nfc_llcp_get_sdp_ssap(struct nfc_llcp_local *local,
struct nfc_llcp_sock *sock); struct nfc_llcp_sock *sock);
......
...@@ -359,6 +359,7 @@ int nfc_llcp_send_symm(struct nfc_dev *dev) ...@@ -359,6 +359,7 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)
struct sk_buff *skb; struct sk_buff *skb;
struct nfc_llcp_local *local; struct nfc_llcp_local *local;
u16 size = 0; u16 size = 0;
int err;
pr_debug("Sending SYMM\n"); pr_debug("Sending SYMM\n");
...@@ -370,8 +371,10 @@ int nfc_llcp_send_symm(struct nfc_dev *dev) ...@@ -370,8 +371,10 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)
size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE; size += dev->tx_headroom + dev->tx_tailroom + NFC_HEADER_SIZE;
skb = alloc_skb(size, GFP_KERNEL); skb = alloc_skb(size, GFP_KERNEL);
if (skb == NULL) if (skb == NULL) {
return -ENOMEM; err = -ENOMEM;
goto out;
}
skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE); skb_reserve(skb, dev->tx_headroom + NFC_HEADER_SIZE);
...@@ -381,8 +384,11 @@ int nfc_llcp_send_symm(struct nfc_dev *dev) ...@@ -381,8 +384,11 @@ int nfc_llcp_send_symm(struct nfc_dev *dev)
nfc_llcp_send_to_raw_sock(local, skb, NFC_DIRECTION_TX); 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); nfc_llcp_recv, local);
out:
nfc_llcp_local_put(local);
return err;
} }
int nfc_llcp_send_connect(struct nfc_llcp_sock *sock) int nfc_llcp_send_connect(struct nfc_llcp_sock *sock)
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
static u8 llcp_magic[3] = {0x46, 0x66, 0x6d}; static u8 llcp_magic[3] = {0x46, 0x66, 0x6d};
static LIST_HEAD(llcp_devices); 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); 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, ...@@ -143,7 +145,7 @@ static void nfc_llcp_socket_release(struct nfc_llcp_local *local, bool device,
write_unlock(&local->raw_sockets.lock); 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); kref_get(&local->ref);
...@@ -170,7 +172,6 @@ static void local_release(struct kref *ref) ...@@ -170,7 +172,6 @@ static void local_release(struct kref *ref)
local = container_of(ref, struct nfc_llcp_local, ref); local = container_of(ref, struct nfc_llcp_local, ref);
list_del(&local->list);
local_cleanup(local); local_cleanup(local);
kfree(local); kfree(local);
} }
...@@ -283,12 +284,33 @@ static void nfc_llcp_sdreq_timer(struct timer_list *t) ...@@ -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 *nfc_llcp_find_local(struct nfc_dev *dev)
{ {
struct nfc_llcp_local *local; struct nfc_llcp_local *local;
struct nfc_llcp_local *res = NULL;
spin_lock(&llcp_devices_lock);
list_for_each_entry(local, &llcp_devices, list) 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; return local;
}
spin_unlock(&llcp_devices_lock);
pr_debug("No device found\n"); pr_warn("Shutting down device not found\n");
return NULL; return NULL;
} }
...@@ -609,12 +631,15 @@ u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len) ...@@ -609,12 +631,15 @@ u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len)
*general_bytes_len = local->gb_len; *general_bytes_len = local->gb_len;
nfc_llcp_local_put(local);
return local->gb; return local->gb;
} }
int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len)
{ {
struct nfc_llcp_local *local; struct nfc_llcp_local *local;
int err;
if (gb_len < 3 || gb_len > NFC_MAX_GT_LEN) if (gb_len < 3 || gb_len > NFC_MAX_GT_LEN)
return -EINVAL; return -EINVAL;
...@@ -631,12 +656,16 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) ...@@ -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)) { if (memcmp(local->remote_gb, llcp_magic, 3)) {
pr_err("MAC does not support LLCP\n"); 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[3],
local->remote_gb_len - 3); local->remote_gb_len - 3);
out:
nfc_llcp_local_put(local);
return err;
} }
static u8 nfc_llcp_dsap(struct sk_buff *pdu) 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) ...@@ -1522,6 +1551,8 @@ int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb)
__nfc_llcp_recv(local, skb); __nfc_llcp_recv(local, skb);
nfc_llcp_local_put(local);
return 0; return 0;
} }
...@@ -1538,6 +1569,8 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev) ...@@ -1538,6 +1569,8 @@ void nfc_llcp_mac_is_down(struct nfc_dev *dev)
/* Close and purge all existing sockets */ /* Close and purge all existing sockets */
nfc_llcp_socket_release(local, true, 0); 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, 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, ...@@ -1563,6 +1596,8 @@ void nfc_llcp_mac_is_up(struct nfc_dev *dev, u32 target_idx,
mod_timer(&local->link_timer, mod_timer(&local->link_timer,
jiffies + msecs_to_jiffies(local->remote_lto)); jiffies + msecs_to_jiffies(local->remote_lto));
} }
nfc_llcp_local_put(local);
} }
int nfc_llcp_register_device(struct nfc_dev *ndev) int nfc_llcp_register_device(struct nfc_dev *ndev)
...@@ -1613,7 +1648,7 @@ 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) 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) { if (local == NULL) {
pr_debug("No such device\n"); pr_debug("No such device\n");
......
...@@ -99,7 +99,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) ...@@ -99,7 +99,7 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)
} }
llcp_sock->dev = dev; 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->nfc_protocol = llcp_addr.nfc_protocol;
llcp_sock->service_name_len = min_t(unsigned int, llcp_sock->service_name_len = min_t(unsigned int,
llcp_addr.service_name_len, llcp_addr.service_name_len,
...@@ -181,7 +181,7 @@ static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr *addr, ...@@ -181,7 +181,7 @@ static int llcp_raw_sock_bind(struct socket *sock, struct sockaddr *addr,
} }
llcp_sock->dev = dev; 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->nfc_protocol = llcp_addr.nfc_protocol;
nfc_llcp_sock_link(&local->raw_sockets, sk); nfc_llcp_sock_link(&local->raw_sockets, sk);
...@@ -698,24 +698,22 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, ...@@ -698,24 +698,22 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
if (dev->dep_link_up == false) { if (dev->dep_link_up == false) {
ret = -ENOLINK; ret = -ENOLINK;
device_unlock(&dev->dev); device_unlock(&dev->dev);
goto put_dev; goto sock_llcp_put_local;
} }
device_unlock(&dev->dev); device_unlock(&dev->dev);
if (local->rf_mode == NFC_RF_INITIATOR && if (local->rf_mode == NFC_RF_INITIATOR &&
addr->target_idx != local->target_idx) { addr->target_idx != local->target_idx) {
ret = -ENOLINK; ret = -ENOLINK;
goto put_dev; goto sock_llcp_put_local;
} }
llcp_sock->dev = dev; 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); llcp_sock->ssap = nfc_llcp_get_local_ssap(local);
if (llcp_sock->ssap == LLCP_SAP_MAX) { if (llcp_sock->ssap == LLCP_SAP_MAX) {
nfc_llcp_local_put(llcp_sock->local);
llcp_sock->local = NULL;
ret = -ENOMEM; ret = -ENOMEM;
goto put_dev; goto sock_llcp_nullify;
} }
llcp_sock->reserved_ssap = llcp_sock->ssap; llcp_sock->reserved_ssap = llcp_sock->ssap;
...@@ -760,8 +758,13 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, ...@@ -760,8 +758,13 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr,
sock_llcp_release: sock_llcp_release:
nfc_llcp_put_ssap(local, llcp_sock->ssap); nfc_llcp_put_ssap(local, llcp_sock->ssap);
nfc_llcp_local_put(llcp_sock->local);
sock_llcp_nullify:
llcp_sock->local = NULL; llcp_sock->local = NULL;
llcp_sock->dev = NULL;
sock_llcp_put_local:
nfc_llcp_local_put(local);
put_dev: put_dev:
nfc_put_device(dev); nfc_put_device(dev);
......
...@@ -1039,11 +1039,14 @@ static int nfc_genl_llc_get_params(struct sk_buff *skb, struct genl_info *info) ...@@ -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); msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
if (!msg) { if (!msg) {
rc = -ENOMEM; rc = -ENOMEM;
goto exit; goto put_local;
} }
rc = nfc_genl_send_params(msg, local, info->snd_portid, info->snd_seq); rc = nfc_genl_send_params(msg, local, info->snd_portid, info->snd_seq);
put_local:
nfc_llcp_local_put(local);
exit: exit:
device_unlock(&dev->dev); device_unlock(&dev->dev);
...@@ -1105,7 +1108,7 @@ static int nfc_genl_llc_set_params(struct sk_buff *skb, struct genl_info *info) ...@@ -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 (info->attrs[NFC_ATTR_LLC_PARAM_LTO]) {
if (dev->dep_link_up) { if (dev->dep_link_up) {
rc = -EINPROGRESS; rc = -EINPROGRESS;
goto exit; goto put_local;
} }
local->lto = nla_get_u8(info->attrs[NFC_ATTR_LLC_PARAM_LTO]); 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) ...@@ -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]) if (info->attrs[NFC_ATTR_LLC_PARAM_MIUX])
local->miux = cpu_to_be16(miux); local->miux = cpu_to_be16(miux);
put_local:
nfc_llcp_local_put(local);
exit: exit:
device_unlock(&dev->dev); device_unlock(&dev->dev);
...@@ -1172,7 +1178,7 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info) ...@@ -1172,7 +1178,7 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)
if (rc != 0) { if (rc != 0) {
rc = -EINVAL; rc = -EINVAL;
goto exit; goto put_local;
} }
if (!sdp_attrs[NFC_SDP_ATTR_URI]) 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) ...@@ -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); sdreq = nfc_llcp_build_sdreq_tlv(tid, uri, uri_len);
if (sdreq == NULL) { if (sdreq == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
goto exit; goto put_local;
} }
tlvs_len += sdreq->tlv_len; tlvs_len += sdreq->tlv_len;
...@@ -1201,10 +1207,14 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info) ...@@ -1201,10 +1207,14 @@ static int nfc_genl_llc_sdreq(struct sk_buff *skb, struct genl_info *info)
if (hlist_empty(&sdreq_list)) { if (hlist_empty(&sdreq_list)) {
rc = -EINVAL; rc = -EINVAL;
goto exit; goto put_local;
} }
rc = nfc_llcp_send_snl_sdreq(local, &sdreq_list, tlvs_len); rc = nfc_llcp_send_snl_sdreq(local, &sdreq_list, tlvs_len);
put_local:
nfc_llcp_local_put(local);
exit: exit:
device_unlock(&dev->dev); device_unlock(&dev->dev);
......
...@@ -52,6 +52,7 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len); ...@@ -52,6 +52,7 @@ int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len);
u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len); u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len);
int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb); int nfc_llcp_data_received(struct nfc_dev *dev, struct sk_buff *skb);
struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev); struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev);
int nfc_llcp_local_put(struct nfc_llcp_local *local);
int __init nfc_llcp_init(void); int __init nfc_llcp_init(void);
void nfc_llcp_exit(void); void nfc_llcp_exit(void);
void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp); void nfc_llcp_free_sdp_tlv(struct nfc_llcp_sdp_tlv *sdp);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册