From 0eb3d8cc8cc064ed1f54707d6db4e40bf217c037 Mon Sep 17 00:00:00 2001 From: liangbotong Date: Mon, 15 May 2023 09:56:47 +0800 Subject: [PATCH] btdev code rectification 1. The header comment contains the copyright license, feature description, author, and creation date 2. Rectification of deep nesting of code blocks of functions 3. Rectification of code specification problems 4. Rectify resource leakage 5. Rectifying reliability risks Signed-off-by: liangbotong --- newip/src/linux-5.10/drivers/net/bt/btdev.c | 448 ++++++++++++-------- newip/src/linux-5.10/drivers/net/bt/btdev.h | 64 ++- 2 files changed, 316 insertions(+), 196 deletions(-) diff --git a/newip/src/linux-5.10/drivers/net/bt/btdev.c b/newip/src/linux-5.10/drivers/net/bt/btdev.c index ce42929..4eaff9b 100644 --- a/newip/src/linux-5.10/drivers/net/bt/btdev.c +++ b/newip/src/linux-5.10/drivers/net/bt/btdev.c @@ -1,6 +1,13 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. + * + * Description: Bluetooth virtual network device used in + * the NewIP over Bluetooth communication scenario. + * + * Author: Yang Yanjun + * + * Data: 2023-03-14 */ #include "btdev.h" @@ -11,6 +18,10 @@ static int bt_seq_show(struct seq_file *m, void *v) { struct bt_virnet *vnet = NULL; + if (unlikely(!bt_drv)) { + pr_err("bt seq show: invalid bt_drv"); + return -EINVAL; + } pr_devel("bt seq_show"); seq_printf(m, "Total device: %d (bitmap: 0x%X) Ring size: %d\n", bt_get_total_device(bt_drv), bt_drv->bitmap, @@ -31,6 +42,11 @@ static int bt_seq_show(struct seq_file *m, void *v) static int bt_proc_open(struct inode *inode, struct file *file) { pr_devel("bt proc_open"); + if (unlikely(!inode) || unlikely(!file)) { + pr_err("bt proc open: invalid parameter"); + return -EINVAL; + } + return single_open(file, bt_seq_show, PDE_DATA(inode)); } @@ -40,76 +56,85 @@ static struct proc_ops bt_proc_fops = { .proc_lseek = seq_lseek, .proc_release = single_release}; +static int __bt_virnet_open(struct file *filp, struct bt_virnet *vnet) +{ + struct net_device *ndev; + + if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { + if (unlikely(!atomic_dec_and_test(&vnet->io_file + ->read_open_limit))) + goto read_twice_already; + } else if ((filp->f_flags & O_ACCMODE) == O_WRONLY) { + if (unlikely(!atomic_dec_and_test(&vnet->io_file + ->write_open_limit))) + goto write_twice_already; + } else if ((filp->f_flags & O_ACCMODE) == O_RDWR) { + if (unlikely(!atomic_dec_and_test(&vnet->io_file + ->read_open_limit))) + goto read_twice_already; + if (unlikely(!atomic_dec_and_test(&vnet->io_file + ->write_open_limit))) + goto write_twice_already; + } + + rtnl_lock(); + ndev = vnet->ndev; + if (unlikely(!(ndev->flags & IFF_UP))) { + int ret = dev_change_flags(ndev, ndev->flags | IFF_UP, NULL); + + if (unlikely(ret < 0)) { + rtnl_unlock(); + pr_err("bt dev_change_flags error: ret=%d", ret); + return -EBUSY; + } + } + rtnl_unlock(); + + SET_STATE(vnet, BT_VIRNET_STATE_CONNECTED); + filp->private_data = vnet; + return OK; + +read_twice_already: + atomic_inc(&vnet->io_file->read_open_limit); + pr_err("file %s has been opened for read twice already", + bt_virnet_get_cdev_name(vnet)); + return -EBUSY; + +write_twice_already: + atomic_inc(&vnet->io_file->write_open_limit); + pr_err("file %s has been opened for write twice already", + bt_virnet_get_cdev_name(vnet)); + return -EBUSY; +} + static int bt_io_file_open(struct inode *node, struct file *filp) { struct bt_virnet *vnet = NULL; - int ret = OK; + + if (unlikely(!node) || unlikely(!filp)) { + pr_err("bt io file open: invalid parameter"); + return -EINVAL; + } pr_devel("bt io file open called"); list_for_each_entry(vnet, &bt_drv->devices_table->head, virnet_entry) { - if (bt_virnet_get_cdev(vnet) == node->i_cdev) { - struct net_device *ndev; - - if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { - if (unlikely(!atomic_dec_and_test(&vnet->io_file - ->read_open_limit))) { - atomic_inc(&vnet->io_file->read_open_limit); - pr_err("file %s has been opened for read twice already", - bt_virnet_get_cdev_name(vnet)); - return -EBUSY; - } - } else if ((filp->f_flags & O_ACCMODE) == O_WRONLY) { - if (unlikely(!atomic_dec_and_test(&vnet->io_file - ->write_open_limit))) { - atomic_inc(&vnet->io_file->write_open_limit); - pr_err("file %s has been opened for write twice already", - bt_virnet_get_cdev_name(vnet)); - return -EBUSY; - } - } else if ((filp->f_flags & O_ACCMODE) == O_RDWR) { - if (unlikely(!atomic_dec_and_test(&vnet->io_file - ->read_open_limit))) { - atomic_inc(&vnet->io_file->read_open_limit); - pr_err("file %s has been opened for read twice already", - bt_virnet_get_cdev_name(vnet)); - return -EBUSY; - } - - if (unlikely(!atomic_dec_and_test(&vnet->io_file - ->write_open_limit))) { - atomic_inc(&vnet->io_file->write_open_limit); - pr_err("file %s has been opened for write twice already", - bt_virnet_get_cdev_name(vnet)); - return -EBUSY; - } - } - - rtnl_lock(); - ndev = vnet->ndev; - if (unlikely(!(ndev->flags & IFF_UP))) { - ret = dev_change_flags(ndev, ndev->flags | IFF_UP, NULL); - if (unlikely(ret < 0)) { - rtnl_unlock(); - pr_err("bt dev_change_flags error: ret=%d", ret); - return -EBUSY; - } - } - rtnl_unlock(); - - SET_STATE(vnet, BT_VIRNET_STATE_CONNECTED); - filp->private_data = vnet; - return OK; - } + if (bt_virnet_get_cdev(vnet) == node->i_cdev) + return __bt_virnet_open(filp, vnet); } - return -EIO; } static int bt_io_file_release(struct inode *node, struct file *filp) { - struct bt_virnet *vnet = filp->private_data; + struct bt_virnet *vnet = NULL; + + if (unlikely(!filp) || unlikely(!filp->private_data)) { + pr_err("bt io file release: invalid parameter"); + return -EINVAL; + } + vnet = filp->private_data; pr_devel("bt io file release called"); if ((filp->f_flags & O_ACCMODE) == O_RDONLY) { @@ -130,12 +155,17 @@ static ssize_t bt_io_file_read(struct file *filp, char __user *buffer, size_t size, loff_t *off) { - struct bt_virnet *vnet = filp->private_data; + struct bt_virnet *vnet = NULL; ssize_t out_sz; struct sk_buff *skb = NULL; pr_devel("bt io file read called"); + if (unlikely(!filp) || unlikely(!buffer) || unlikely(!filp->private_data)) { + pr_devel("bt io file read: invalid parameter"); + return -EINVAL; + } + vnet = filp->private_data; while (unlikely(bt_ring_is_empty(vnet->tx_ring))) { if (filp->f_flags & O_NONBLOCK) return -EAGAIN; @@ -146,6 +176,10 @@ static ssize_t bt_io_file_read(struct file *filp, } skb = bt_ring_current(vnet->tx_ring); + if (unlikely(!skb)) { + pr_devel("bt io file read: invalid skb"); + return -EINVAL; + } out_sz = skb->len - MACADDR_LEN; if (unlikely(out_sz > size)) { pr_err("io file read: buffer too small: skb's len=%ld buffer's len=%ld", @@ -174,20 +208,25 @@ static ssize_t bt_io_file_write(struct file *filp, const char __user *buffer, size_t size, loff_t *off) { - struct bt_virnet *vnet = filp->private_data; + struct bt_virnet *vnet = NULL; struct sk_buff *skb = NULL; int ret; int len; ssize_t in_sz; + if (unlikely(!filp) || unlikely(!buffer) || unlikely(!filp->private_data)) { + pr_err("bt io file write: invalid parameter"); + return -EINVAL; + } pr_devel("bt io file write called: %lu bytes", size); + vnet = filp->private_data; in_sz = size + MACADDR_LEN; - skb = netdev_alloc_skb(bt_virnet_get_ndev(vnet), in_sz + 2); + skb = netdev_alloc_skb(bt_virnet_get_ndev(vnet), in_sz + NEWIP_TYPE_SIZE); if (unlikely(!skb)) return -ENOMEM; - skb_reserve(skb, 2); + skb_reserve(skb, NEWIP_TYPE_SIZE); skb_put(skb, in_sz); memset(skb->data, 0, MACADDR_LEN); @@ -212,6 +251,10 @@ static ssize_t bt_io_file_write(struct file *filp, static int bt_virnet_change_mtu(struct net_device *dev, int mtu) { + if (unlikely(!dev) || unlikely(mtu < 0) || unlikely(mtu > BT_MAX_MTU)) { + pr_devel("bt virnet change mtu: invalid parameter"); + return -EINVAL; + } pr_devel("bt virnet change mtu called"); dev->mtu = mtu; return OK; @@ -221,6 +264,10 @@ static int bt_set_mtu(struct net_device *dev, int mtu) { int err = OK; + if (unlikely(mtu < 0) || unlikely(mtu > BT_MAX_MTU)) { + pr_devel("bt set mtu: invalid parameter"); + return -EINVAL; + } pr_devel("bt set_mtu called"); rtnl_lock(); err = dev_set_mtu(dev, mtu); @@ -236,8 +283,6 @@ static int bt_cmd_enable_virnet(struct bt_virnet *vnet, unsigned long arg) { int ret; - WARN_ON(!vnet); - if (unlikely(vnet->state != BT_VIRNET_STATE_DISABLED)) { pr_err("bt enable can only be set at DISABLED state"); return -EINVAL; // enable failed @@ -260,7 +305,6 @@ static int bt_cmd_disable_virnet(struct bt_virnet *vnet, unsigned long arg) { int ret; - WARN_ON(!vnet); if (unlikely(vnet->state != BT_VIRNET_STATE_CONNECTED)) { pr_err("bt disable can only be set at CONNECTED state"); return -EINVAL; @@ -284,8 +328,6 @@ static int bt_cmd_change_mtu(struct bt_virnet *vnet, unsigned long arg) int mtu; int ret; - WARN_ON(!vnet); - if (unlikely(get_user(mtu, (int __user *)arg))) { pr_err("get_user failed"); return -EIO; @@ -325,9 +367,13 @@ static long bt_io_file_ioctl(struct file *filep, unsigned long arg) { long ret; + struct bt_virnet *vnet = NULL; - struct bt_virnet *vnet = filep->private_data; - + if (unlikely(!filep) || unlikely(!filep->private_data)) { + pr_err("bt io file ioctl: invalid parameter"); + return -EINVAL; + } + vnet = filep->private_data; pr_devel("bt io file ioctl called"); switch (cmd) { case BT_IOC_CHANGE_MTU: @@ -352,9 +398,14 @@ static long bt_io_file_ioctl(struct file *filep, static unsigned int bt_io_file_poll(struct file *filp, poll_table *wait) { - struct bt_virnet *vnet = filp->private_data; + struct bt_virnet *vnet = NULL; unsigned int mask = 0; + if (unlikely(!filp) || unlikely(!wait) || unlikely(!filp->private_data)) { + pr_err("bt io file poll: invalid parameter"); + return -EINVAL; + } + vnet = filp->private_data; poll_wait(filp, &vnet->rx_queue, wait); poll_wait(filp, &vnet->tx_queue, wait); @@ -381,6 +432,11 @@ static int bt_mng_file_open(struct inode *node, struct file *filp) { pr_devel("bt mng file open called"); + if (unlikely(!filp)) { + pr_err("bt mng file open: invalid filp"); + return -EINVAL; + } + if (unlikely(!atomic_dec_and_test(&bt_drv->mng_file->open_limit))) { atomic_inc(&bt_drv->mng_file->open_limit); pr_err("file %s has been opened already", @@ -393,8 +449,13 @@ static int bt_mng_file_open(struct inode *node, struct file *filp) static int bt_mng_file_release(struct inode *node, struct file *filp) { - struct bt_drv *drv = filp->private_data; + struct bt_drv *drv = NULL; + if (unlikely(!filp) || unlikely(!filp->private_data)) { + pr_err("bt mng file release: invalid parameter"); + return -EINVAL; + } + drv = filp->private_data; pr_devel("bt mng file release called"); atomic_inc(&drv->mng_file->open_limit); @@ -409,31 +470,24 @@ static int bt_cmd_create_virnet(struct bt_drv *bt_mng, unsigned long arg) struct bt_uioc_args vp; unsigned long size; - WARN_ON(!bt_mng); - mutex_lock(&bt_mng->bitmap_lock); - id = bt_get_unused_id(&bt_mng->bitmap); + id = bt_get_unused_id(bt_mng->bitmap); pr_devel("create io_file: get unused bit: %d", id); if (unlikely(bt_mng->devices_table->num == BT_VIRNET_MAX_NUM)) { pr_err("reach the limit of max virnets"); - mutex_unlock(&bt_mng->bitmap_lock); - return -EIO; + goto virnet_create_failed; } vnet = bt_virnet_create(bt_mng, id); if (unlikely(!vnet)) { pr_err("bt virnet create failed"); - mutex_unlock(&bt_mng->bitmap_lock); - return -EIO; + goto virnet_create_failed; } - vnet->bt_table_head = bt_mng->devices_table; ret = bt_table_add_device(bt_mng->devices_table, vnet); if (unlikely(ret < 0)) { pr_err("bt table add device failed: ret=%d", ret); - bt_virnet_destroy(vnet); - mutex_unlock(&bt_mng->bitmap_lock); - return -EIO; // failed to create + goto add_device_failed; } bt_set_bit(&bt_mng->bitmap, id); @@ -449,19 +503,29 @@ static int bt_cmd_create_virnet(struct bt_drv *bt_mng, unsigned long arg) size = copy_to_user((void __user *)arg, &vp, sizeof(struct bt_uioc_args)); if (unlikely(size)) { pr_err("copy_to_user failed: left size=%lu", size); - return -EIO; + goto copy_to_user_failed; } return OK; + +copy_to_user_failed: + mutex_lock(&bt_mng->bitmap_lock); + bt_clear_bit(&bt_mng->bitmap, id); + +add_device_failed: + bt_virnet_destroy(vnet); + +virnet_create_failed: + mutex_unlock(&bt_mng->bitmap_lock); + return -EIO; } static int bt_cmd_delete_virnet(struct bt_drv *bt_mng, unsigned long arg) { - int id; + int err; struct bt_virnet *vnet = NULL; struct bt_uioc_args vp; unsigned long size; - - WARN_ON(!bt_mng); + dev_t number; size = copy_from_user(&vp, (void __user *)arg, sizeof(struct bt_uioc_args)); @@ -477,17 +541,17 @@ static int bt_cmd_delete_virnet(struct bt_drv *bt_mng, unsigned long arg) } mutex_lock(&bt_mng->bitmap_lock); - id = MINOR(bt_virnet_get_cdev_number(vnet)); + err = bt_virnet_get_cdev_number(vnet, &number); + if (likely(!err)) + bt_clear_bit(&bt_mng->bitmap, (u32)MINOR(number)); bt_table_remove_device(bt_mng->devices_table, vnet); bt_virnet_destroy(vnet); - bt_clear_bit(&bt_mng->bitmap, id); mutex_unlock(&bt_mng->bitmap_lock); return OK; } static int bt_cmd_query_all_virnets(struct bt_drv *bt_mng, unsigned long arg) { - WARN_ON(!bt_mng); if (unlikely(put_user(bt_mng->bitmap, (u32 *)arg))) { pr_err("put_user failed"); return -EIO; @@ -497,9 +561,7 @@ static int bt_cmd_query_all_virnets(struct bt_drv *bt_mng, unsigned long arg) static int bt_cmd_delete_all_virnets(struct bt_drv *bt_mng, unsigned long arg) { - WARN_ON(!bt_mng); - bt_table_delete_all(bt_mng); - return OK; + return bt_table_delete_all(bt_mng); } static long bt_mng_file_ioctl(struct file *filep, @@ -507,9 +569,13 @@ static long bt_mng_file_ioctl(struct file *filep, unsigned long arg) { int ret; + struct bt_drv *bt_mng = NULL; - struct bt_drv *bt_mng = filep->private_data; - + if (unlikely(!filep) || unlikely(!filep->private_data)) { + pr_err("bt mng file ioctl: invalid parameter"); + return -EINVAL; + } + bt_mng = filep->private_data; pr_devel("bt mng file ioctl called"); switch (cmd) { case BT_IOC_CREATE: @@ -543,11 +609,18 @@ static netdev_tx_t bt_virnet_xmit(struct sk_buff *skb, { int ret; struct bt_virnet *vnet = NULL; - int len = skb->len; + + if (unlikely(!skb) || unlikely(!dev)) { + pr_err("virnet xmit: invalid parameter"); + return -EINVAL; + } pr_alert("alert: bt virnet_xmit: called"); vnet = bt_table_find(bt_drv->devices_table, dev->name); - WARN_ON(!vnet); + if (unlikely(!vnet)) { + pr_err("virnet xmit: bt_table_find failed"); + return -EINVAL; + } ret = bt_virnet_produce_data(vnet, (void *)skb); @@ -558,7 +631,7 @@ static netdev_tx_t bt_virnet_xmit(struct sk_buff *skb, } vnet->ndev->stats.tx_packets++; - vnet->ndev->stats.tx_bytes += len; + vnet->ndev->stats.tx_bytes += skb->len; return NETDEV_TX_OK; } @@ -586,8 +659,10 @@ static int bt_table_add_device(struct bt_table *tbl, struct bt_virnet *vn) { struct bt_virnet *vnet = NULL; - WARN_ON(!tbl); - WARN_ON(!vn); + if (unlikely(!tbl)) { + pr_err("bt table add device: invalid parameter"); + return -EINVAL; + } vnet = bt_table_find(tbl, bt_virnet_get_ndev_name(vn)); if (unlikely(vnet)) { @@ -605,8 +680,9 @@ static int bt_table_add_device(struct bt_table *tbl, struct bt_virnet *vn) static void bt_table_remove_device(struct bt_table *tbl, struct bt_virnet *vn) { - WARN_ON(!tbl); - WARN_ON(!vn); + if (unlikely(!tbl)) + return; + mutex_lock(&tbl->tbl_lock); list_del(&vn->virnet_entry); --tbl->num; @@ -617,10 +693,10 @@ static struct bt_virnet *bt_table_find(struct bt_table *tbl, const char *ifa_nam { struct bt_virnet *vnet = NULL; - WARN_ON(!tbl); - - if (unlikely(!ifa_name)) + if (unlikely(!tbl) || unlikely(!ifa_name)) { + pr_err("bt table find: invalid parameter"); return NULL; + } list_for_each_entry(vnet, &tbl->head, virnet_entry) { if (!strcmp(bt_virnet_get_ndev_name(vnet), ifa_name)) @@ -631,25 +707,31 @@ static struct bt_virnet *bt_table_find(struct bt_table *tbl, const char *ifa_nam static void __bt_table_delete_all(struct bt_drv *drv) { - u32 id; + int err; + dev_t number; struct bt_virnet *vnet = NULL, *tmp_vnet = NULL; - WARN_ON(!drv); + if (unlikely(!bt_drv->devices_table)) + return; + list_for_each_entry_safe(vnet, tmp_vnet, &drv->devices_table->head, virnet_entry) { - id = MINOR(bt_virnet_get_cdev_number(vnet)); + err = bt_virnet_get_cdev_number(vnet, &number); + if (likely(!err)) + bt_clear_bit(&drv->bitmap, (u32)MINOR(number)); list_del(&vnet->virnet_entry); - bt_clear_bit(&drv->bitmap, id); bt_virnet_destroy(vnet); } drv->devices_table->num = 0; } -static void bt_table_delete_all(struct bt_drv *bt_drv) +static int bt_table_delete_all(struct bt_drv *bt_drv) { - WARN_ON(!bt_drv); + if (unlikely(!bt_drv->devices_table)) + return -EINVAL; + mutex_lock(&bt_drv->bitmap_lock); mutex_lock(&bt_drv->devices_table->tbl_lock); @@ -657,11 +739,11 @@ static void bt_table_delete_all(struct bt_drv *bt_drv) mutex_unlock(&bt_drv->devices_table->tbl_lock); mutex_unlock(&bt_drv->bitmap_lock); + return OK; } static void bt_table_destroy(struct bt_drv *bt_drv) { - WARN_ON(!bt_drv); __bt_table_delete_all(bt_drv); kfree(bt_drv->devices_table); bt_drv->devices_table = NULL; @@ -699,21 +781,22 @@ static struct bt_ring *bt_ring_create(void) static int bt_ring_is_empty(const struct bt_ring *ring) { - WARN_ON(!ring); + if (unlikely(!ring)) + return -EINVAL; + return ring->head == ring->tail; } static int bt_ring_is_full(const struct bt_ring *ring) { - WARN_ON(!ring); + if (unlikely(!ring)) + return -EINVAL; + return (ring->head + 1) % ring->size == ring->tail; } static void bt_ring_produce(struct bt_ring *ring, void *data) { - WARN_ON(!ring); - WARN_ON(!data); - smp_mb(); // Make sure the read and write order is correct ring->data[ring->head] = data; ring->head = (ring->head + 1) % ring->size; @@ -724,14 +807,17 @@ static void *bt_ring_current(struct bt_ring *ring) { void *data = NULL; - WARN_ON(!ring); + if (unlikely(!ring)) + return data; + data = ring->data[ring->tail]; return data; } static void bt_ring_consume(struct bt_ring *ring) { - WARN_ON(!ring); + if (unlikely(!ring)) + return; smp_rmb(); // Make sure the read order is correct ring->tail = (ring->tail + 1) % ring->size; @@ -740,15 +826,15 @@ static void bt_ring_consume(struct bt_ring *ring) static void bt_ring_destroy(struct bt_ring *ring) { - WARN_ON(!ring); + if (unlikely(!ring)) + return; + kfree(ring->data); kfree(ring); } static int bt_virnet_produce_data(struct bt_virnet *dev, void *data) { - WARN_ON(!dev); - WARN_ON(!data); if (unlikely(bt_ring_is_full(dev->tx_ring))) { pr_devel("ring is full"); return -ENFILE; @@ -783,7 +869,9 @@ static struct class *bt_dev_class_create(void) static void bt_dev_class_destroy(struct class *cls) { - WARN_ON(!cls); + if (unlikely(!cls)) + return; + class_destroy(cls); } @@ -794,8 +882,10 @@ static int bt_cdev_device_create(struct bt_cdev *dev, struct device *device = NULL; dev_t devno = MKDEV(BT_DEV_MAJOR, id); - WARN_ON(!dev); - WARN_ON(!cls); + if (unlikely(!cls)) { + pr_err("not a valid cls"); + return -EINVAL; + } pr_devel("bt cdev_device_create: id=%d", id); @@ -812,7 +902,6 @@ static int bt_cdev_device_create(struct bt_cdev *dev, static void bt_cdev_device_destroy(struct bt_cdev *dev) { - WARN_ON(!dev); device_destroy(dev->bt_class, dev->cdev->dev); } @@ -824,20 +913,18 @@ static struct bt_cdev *bt_cdev_create(const struct file_operations *ops, struct bt_cdev *dev = NULL; struct cdev *chrdev = NULL; - WARN_ON(!ops); - pr_devel("bt cdev create called"); dev = kmalloc(sizeof(*dev), GFP_KERNEL); if (unlikely(!dev)) { pr_err("bt cdev_create alloc failed: oom"); - goto err1; + goto dev_alloc_failed; } chrdev = cdev_alloc(); if (unlikely(!chrdev)) { pr_err("bt cdev_create: cdev_alloc() failed: oom"); - goto err2; + goto cdev_alloc_failed; } cdev_init(chrdev, ops); @@ -846,22 +933,23 @@ static struct bt_cdev *bt_cdev_create(const struct file_operations *ops, ret = cdev_add(chrdev, MKDEV(BT_DEV_MAJOR, minor), 1); if (unlikely(ret < 0)) { pr_err("cdev add failed"); - goto err3; + goto cdev_add_failed; } if (unlikely(bt_cdev_device_create(dev, bt_drv->bt_class, minor) < 0)) { pr_err("bt cdev_device_create failed"); - goto err3; + goto cdev_device_create_failed; } return dev; -err3: +cdev_device_create_failed: cdev_del(chrdev); -err2: +cdev_add_failed: +cdev_alloc_failed: kfree(dev); -err1: +dev_alloc_failed: return NULL; } @@ -872,17 +960,16 @@ static void bt_cdev_delete(struct bt_cdev *bt_cdev) { dev_t devno; - WARN_ON(!bt_cdev); - if (unlikely(bt_cdev)) { + if (likely(bt_cdev)) { devno = bt_cdev->cdev->dev; - unregister_chrdev(MAJOR(devno), bt_cdev->dev_filename + 5); + /* BT_DEV_PATH_PREFIX + ID --> /dev/btn1 */ + unregister_chrdev(MAJOR(devno), bt_cdev->dev_filename + strlen(BT_DEV_PATH_PREFIX)); bt_cdev_device_destroy(bt_cdev); cdev_del(bt_cdev->cdev); } else { pr_err("bt cdev_delete: cdev is null"); - return; } } @@ -994,6 +1081,10 @@ static struct net_device *bt_net_device_create(u32 id) int err; char ifa_name[IFNAMSIZ]; + if (unlikely(id < 0) || unlikely(id > BT_VIRNET_MAX_NUM)) { + pr_err("bt net device create: invalid id"); + return NULL; + } snprintf(ifa_name, sizeof(ifa_name), "%s%d", BT_VIRNET_NAME_PREFIX, id); ndev = alloc_netdev(0, ifa_name, NET_NAME_UNKNOWN, ether_setup); if (unlikely(!ndev)) { @@ -1022,16 +1113,16 @@ static struct net_device *bt_net_device_create(u32 id) */ static void bt_net_device_destroy(struct net_device *dev) { - WARN_ON(!dev); unregister_netdev(dev); free_netdev(dev); } static struct bt_io_file *bt_get_io_file(struct bt_drv *drv, int id) { - WARN_ON(id < 1); - WARN_ON(id > BT_VIRNET_MAX_NUM); - return drv->io_files[id - 1]; + if (id >= 1 && id <= BT_VIRNET_MAX_NUM) + return drv->io_files[id - 1]; + + return NULL; } /** @@ -1043,25 +1134,25 @@ static struct bt_virnet *bt_virnet_create(struct bt_drv *bt_mng, u32 id) if (unlikely(!vnet)) { pr_err("error: bt_virnet init failed"); - goto failure1; + goto out_of_memory; } vnet->tx_ring = bt_ring_create(); if (unlikely(!vnet->tx_ring)) { pr_err("create ring failed"); - goto failure2; + goto bt_ring_create_failed; } vnet->ndev = bt_net_device_create(id); if (unlikely(!vnet->ndev)) { pr_err("create net device failed"); - goto failure3; + goto net_device_create_failed; } vnet->io_file = bt_get_io_file(bt_mng, id); if (unlikely(!vnet->io_file)) { pr_err("create cdev failed"); - goto failure4; + goto get_io_file_failed; } init_waitqueue_head(&vnet->rx_queue); @@ -1070,22 +1161,21 @@ static struct bt_virnet *bt_virnet_create(struct bt_drv *bt_mng, u32 id) SET_STATE(vnet, BT_VIRNET_STATE_CREATED); return vnet; -failure4: +get_io_file_failed: bt_net_device_destroy(vnet->ndev); -failure3: +net_device_create_failed: bt_ring_destroy(vnet->tx_ring); -failure2: +bt_ring_create_failed: kfree(vnet); -failure1: +out_of_memory: return NULL; } static void bt_virnet_destroy(struct bt_virnet *vnet) { - WARN_ON(!vnet); bt_ring_destroy(vnet->tx_ring); bt_net_device_destroy(vnet->ndev); @@ -1094,16 +1184,19 @@ static void bt_virnet_destroy(struct bt_virnet *vnet) kfree(vnet); } -static void bt_module_release(void) +static void __exit bt_module_release(void) { - bt_table_destroy(bt_drv); - bt_delete_io_files(bt_drv); - bt_delete_mng_file(bt_drv->mng_file); - bt_dev_class_destroy(bt_drv->bt_class); - bt_cdev_region_destroy(BT_DEV_MAJOR, BT_VIRNET_MAX_NUM); + if (likely(bt_drv)) { + bt_table_destroy(bt_drv); + bt_delete_io_files(bt_drv); + bt_delete_mng_file(bt_drv->mng_file); + bt_dev_class_destroy(bt_drv->bt_class); + + kfree(bt_drv); + bt_drv = NULL; + } - kfree(bt_drv); - bt_drv = NULL; + bt_cdev_region_destroy(BT_DEV_MAJOR, BT_VIRNET_MAX_NUM); remove_proc_entry("bt_info_proc", NULL); } @@ -1112,47 +1205,48 @@ static void bt_module_release(void) */ static int __init bt_module_init(void) { - int mid; + int mid = 0; struct proc_dir_entry *entry = NULL; pr_devel("bt module_init called"); bt_drv = kmalloc(sizeof(*bt_drv), GFP_KERNEL); if (unlikely(!bt_drv)) { pr_err("module init: alloc struct bt_drv failed: oom"); - goto failure1; + goto out_of_memory; } if (unlikely(bt_cdev_region_init(BT_DEV_MAJOR, BT_VIRNET_MAX_NUM) < 0)) { pr_err("bt_cdev_region_init: failed"); - goto failure2; + goto cdev_region_failed; } bt_drv->devices_table = bt_table_init(); if (unlikely(!bt_drv->devices_table)) { pr_err("bt_table_init(): failed"); - goto failure2; + goto table_init_failed; } bt_drv->bt_class = bt_dev_class_create(); - if (IS_ERR(bt_drv->bt_class)) { + if (unlikely(!bt_drv->bt_class)) { pr_err("class create failed"); - goto failure3; + goto class_create_failed; } bt_drv->io_files = bt_create_io_files(); + if (unlikely(!bt_drv->io_files)) { + pr_err("bt_create_io_files: failed"); + goto io_files_create_failed; + } mutex_init(&bt_drv->bitmap_lock); bt_drv->bitmap = 0; mutex_lock(&bt_drv->bitmap_lock); - mid = bt_get_unused_id(&bt_drv->bitmap); - pr_devel("create mng_file: get unused bit: %d", mid); - bt_drv->mng_file = bt_create_mng_file(mid); if (unlikely(!bt_drv->mng_file)) { pr_err("bt_ctrl_cdev_init failed"); mutex_unlock(&bt_drv->bitmap_lock); - goto failure4; + goto mng_file_create_failed; } bt_set_bit(&bt_drv->bitmap, mid); mutex_unlock(&bt_drv->bitmap_lock); @@ -1160,24 +1254,30 @@ static int __init bt_module_init(void) entry = proc_create_data("bt_info_proc", 0, NULL, &bt_proc_fops, NULL); if (unlikely(!entry)) { pr_err("create proc data failed"); - goto failure5; + goto proc_create_failed; } return OK; -failure5: +proc_create_failed: bt_delete_mng_file(bt_drv->mng_file); -failure4: +mng_file_create_failed: + bt_delete_io_files(bt_drv); + +io_files_create_failed: bt_dev_class_destroy(bt_drv->bt_class); -failure3: +class_create_failed: bt_table_destroy(bt_drv); -failure2: +table_init_failed: + bt_cdev_region_destroy(BT_DEV_MAJOR, BT_VIRNET_MAX_NUM); + +cdev_region_failed: kfree(bt_drv); -failure1: +out_of_memory: return -1; } diff --git a/newip/src/linux-5.10/drivers/net/bt/btdev.h b/newip/src/linux-5.10/drivers/net/bt/btdev.h index 4c4d965..07a7c2e 100644 --- a/newip/src/linux-5.10/drivers/net/bt/btdev.h +++ b/newip/src/linux-5.10/drivers/net/bt/btdev.h @@ -1,6 +1,13 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* - * Copyright (c) 2022 Huawei Device Co., Ltd. + * Copyright (c) 2023 Huawei Device Co., Ltd. + * + * Description: Bluetooth virtual network device used in + * the NewIP over Bluetooth communication scenario. + * + * Author: Yang Yanjun + * + * Data: 2023-03-14 */ #ifndef _BTDEV_H_ @@ -46,7 +53,9 @@ #define STRTOLL_BASE 10 #define BT_DEV_ID_OFFSET (sizeof(BT_DEV_PATH_PREFIX) - 1) #define BT_STATISTIC_KTIME_MAX ULONG_MAX - +#define NEWIP_TYPE_SIZE 2 /* newip type eadd */ +#define BT_MAX_MTU 65535 +#define UNKNOWN_NAME "unknown" /** * for debug */ @@ -111,7 +120,6 @@ struct bt_virnet { struct bt_io_file *io_file; struct net_device *ndev; struct list_head virnet_entry; - struct bt_table *bt_table_head; enum bt_virnet_state state; struct semaphore sem; wait_queue_head_t rx_queue, tx_queue; @@ -142,13 +150,12 @@ static const char *bt_virnet_state_rep[BT_VIRNET_STAET_NUM] = { /** * inline functions */ -static inline int bt_get_unused_id(const u32 *bitmap) +static inline int bt_get_unused_id(u32 bitmap) { int i; - WARN_ON(!bitmap); for (i = 0; i < BT_VIRNET_MAX_NUM + 1; ++i) { - if (!(*bitmap & (1 << i))) + if (!(bitmap & (1 << i))) return i; } return -1; // all used @@ -156,63 +163,73 @@ static inline int bt_get_unused_id(const u32 *bitmap) static inline void bt_set_bit(u32 *bitmap, u32 idx) { - WARN_ON(!bitmap); - *bitmap |= (1 << idx); + if (bitmap && idx <= BT_VIRNET_MAX_NUM) + *bitmap |= (1 << idx); } static inline void bt_clear_bit(u32 *bitmap, u32 idx) { - WARN_ON(!bitmap); - *bitmap &= ~(1 << idx); + if (bitmap && idx <= BT_VIRNET_MAX_NUM) + *bitmap &= ~(1 << idx); } #define SET_STATE(vn, st) bt_virnet_set_state(vn, st) static inline void bt_virnet_set_state(struct bt_virnet *vn, enum bt_virnet_state state) { - WARN_ON(!vn); vn->state = state; } static inline const struct cdev *bt_virnet_get_cdev(const struct bt_virnet *vn) { - WARN_ON(!vn); + if (unlikely(!vn->io_file) || unlikely(!vn->io_file->bt_cdev)) + return NULL; + return vn->io_file->bt_cdev->cdev; } -static inline const dev_t bt_virnet_get_cdev_number(const struct bt_virnet *vn) +static inline const int bt_virnet_get_cdev_number(const struct bt_virnet *vn, dev_t *number) { - WARN_ON(!vn); - return vn->io_file->bt_cdev->cdev->dev; + if (unlikely(!vn->io_file) || unlikely(!vn->io_file->bt_cdev) || + unlikely(!vn->io_file->bt_cdev->cdev) || unlikely(!number)) + return -EINVAL; + + *number = vn->io_file->bt_cdev->cdev->dev; + return OK; } static inline const char *bt_virnet_get_cdev_name(const struct bt_virnet *vn) { - WARN_ON(!vn); + if (unlikely(!vn->io_file) || unlikely(!vn->io_file->bt_cdev) || + unlikely(!vn->io_file->bt_cdev->dev_filename)) + return UNKNOWN_NAME; + return vn->io_file->bt_cdev->dev_filename; } static inline struct net_device *bt_virnet_get_ndev(const struct bt_virnet *vn) { - WARN_ON(!vn); return vn->ndev; } static inline const char *bt_virnet_get_ndev_name(const struct bt_virnet *vn) { - WARN_ON(!vn); + if (unlikely(!vn->ndev) || unlikely(!vn->ndev->name)) + return UNKNOWN_NAME; + return vn->ndev->name; } static inline const char *bt_virnet_get_state_rep(const struct bt_virnet *vn) { - WARN_ON(!vn); return bt_virnet_state_rep[vn->state]; } static inline int bt_get_total_device(const struct bt_drv *bt_drv) { - WARN_ON(!bt_drv); + if (unlikely(!bt_drv->devices_table)) + return -EINVAL; + return bt_drv->devices_table->num; } @@ -220,7 +237,10 @@ static inline int bt_virnet_get_ring_packets(const struct bt_virnet *vn) { int packets = 0; - WARN_ON(!vn); + if (unlikely(!vn->tx_ring) || unlikely(!vn->tx_ring->head) || + unlikely(!vn->tx_ring->tail)) + return -EINVAL; + packets = vn->tx_ring->head - vn->tx_ring->tail; if (unlikely(packets < 0)) packets += BT_RING_BUFFER_SIZE; @@ -231,7 +251,7 @@ static inline int bt_virnet_get_ring_packets(const struct bt_virnet *vn) static struct bt_table *bt_table_init(void); static int bt_table_add_device(struct bt_table *tbl, struct bt_virnet *vn); static void bt_table_remove_device(struct bt_table *tbl, struct bt_virnet *vn); -static void bt_table_delete_all(struct bt_drv *bt_drv); +static int bt_table_delete_all(struct bt_drv *bt_drv); static struct bt_virnet *bt_table_find(struct bt_table *tbl, const char *ifa_name); static void bt_table_destroy(struct bt_drv *bt_drv); static void bt_delete_io_files(struct bt_drv *bt_mng); -- Gitee