All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ray Kinsella <mdr@ashroe.eu>
To: Stephen Coleman <omegacoleman@gmail.com>
Cc: dev@dpdk.org, Ferruh Yigit <ferruh.yigit@xilinx.com>
Subject: Re: kni: check abi version between kmod and lib
Date: Thu, 21 Apr 2022 10:16:31 -0400	[thread overview]
Message-ID: <87fsm6o728.fsf@mdr78.vserver.site> (raw)
In-Reply-To: <CAPTjMhh4d6gs93-3fpwhHT5SKUtyq+7FPOV-M=HtHcczzJ3qCA@mail.gmail.com>


Stephen Coleman <omegacoleman@gmail.com> writes:

> KNI ioctl functions copy data from userspace lib, and this interface
> of kmod is not compatible indeed. If the user use incompatible rte_kni.ko
> bad things happen: sometimes various fields contain garbage value,
> sometimes it cause a kmod soft lockup.
>
> Some common distros ship their own rte_kni.ko, so this is likely to
> happen.
>
> This patch add abi version checking between userland lib and kmod so
> that:
>
> * if kmod ioctl got a wrong abi magic, it refuse to go on
> * if userland lib, probed a wrong abi version via newly added ioctl, it
>   also refuse to go on
>
> Bugzilla ID: 998
>
> Signed-off-by: youcai <omegacoleman@gmail.com>
> ---
>  kernel/linux/kni/kni_misc.c | 38 +++++++++++++++++++++++++++++++++++++
>  lib/kni/rte_kni.c           | 16 ++++++++++++++++
>  lib/kni/rte_kni_common.h    | 11 +++++++++++
>  3 files changed, 65 insertions(+)
>
> diff --git a/kernel/linux/kni/kni_misc.c b/kernel/linux/kni/kni_misc.c
> index 780187d8bf..cd9a05d8c1 100644
> --- a/kernel/linux/kni/kni_misc.c
> +++ b/kernel/linux/kni/kni_misc.c
> @@ -236,12 +236,24 @@ kni_release(struct inode *inode, struct file *file)
>      return 0;
>  }
>
> +static int kni_check_abi_version_magic(uint16_t abi_version_magic) {
> +    if (abi_version_magic != RTE_KNI_ABI_VERSION_MAGIC) {
> +        pr_err("KNI kmod ABI incompatible with librte_kni -- %u\n",
> +               RTE_KNI_ABI_VERSION_FROM_MAGIC(abi_version_magic));
> +        return -1;
> +    }
> +    return 0;
> +}
> +
>  static int
>  kni_check_param(struct kni_dev *kni, struct rte_kni_device_info *dev)
>  {
>      if (!kni || !dev)
>          return -1;
>
> +    if (kni_check_abi_version_magic(dev->abi_version_magic) < 0)
> +        return -1;
> +
>      /* Check if network name has been used */
>      if (!strncmp(kni->name, dev->name, RTE_KNI_NAMESIZE)) {
>          pr_err("KNI name %s duplicated\n", dev->name);
> @@ -301,12 +313,19 @@ kni_ioctl_create(struct net *net, uint32_t ioctl_num,
>      struct rte_kni_device_info dev_info;
>      struct net_device *net_dev = NULL;
>      struct kni_dev *kni, *dev, *n;
> +    uint16_t abi_version_magic;
>
>      pr_info("Creating kni...\n");
>      /* Check the buffer size, to avoid warning */
>      if (_IOC_SIZE(ioctl_num) > sizeof(dev_info))
>          return -EINVAL;
>
> +    /* perform abi check ahead of copy, to avoid possible violation */
> +    if (copy_from_user(&abi_version_magic, (void *)ioctl_param,
> sizeof(uint16_t)))
> +        return -EFAULT;
> +    if (kni_check_abi_version_magic(abi_version_magic) < 0)
> +        return -EINVAL;
> +
>      /* Copy kni info from user space */
>      if (copy_from_user(&dev_info, (void *)ioctl_param, sizeof(dev_info)))
>          return -EFAULT;
> @@ -451,10 +470,17 @@ kni_ioctl_release(struct net *net, uint32_t ioctl_num,
>      int ret = -EINVAL;
>      struct kni_dev *dev, *n;
>      struct rte_kni_device_info dev_info;
> +    uint16_t abi_version_magic;
>
>      if (_IOC_SIZE(ioctl_num) > sizeof(dev_info))
>          return -EINVAL;
>
> +    /* perform abi check ahead of copy, to avoid possible violation */
> +    if (copy_from_user(&abi_version_magic, (void *)ioctl_param,
> sizeof(uint16_t)))
> +        return -EFAULT;
> +    if (kni_check_abi_version_magic(abi_version_magic) < 0)
> +        return -EINVAL;
> +
>      if (copy_from_user(&dev_info, (void *)ioctl_param, sizeof(dev_info)))
>          return -EFAULT;
>
> @@ -484,6 +510,15 @@ kni_ioctl_release(struct net *net, uint32_t ioctl_num,
>      return ret;
>  }
>
> +static int
> +kni_ioctl_abi_version(struct net *net, uint32_t ioctl_num,
> +        unsigned long ioctl_param)
> +{
> +    uint16_t abi_version = RTE_KNI_ABI_VERSION;
> +    copy_to_user((void *)ioctl_param, &abi_version, sizeof(uint16_t));
> +    return 0;
> +}
> +
>  static long
>  kni_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param)
>  {
> @@ -505,6 +540,9 @@ kni_ioctl(struct file *file, unsigned int
> ioctl_num, unsigned long ioctl_param)
>      case _IOC_NR(RTE_KNI_IOCTL_RELEASE):
>          ret = kni_ioctl_release(net, ioctl_num, ioctl_param);
>          break;
> +    case _IOC_NR(RTE_KNI_IOCTL_ABI_VERSION):
> +        ret = kni_ioctl_abi_version(net, ioctl_num, ioctl_param);
> +        break;
>      default:
>          pr_debug("IOCTL default\n");
>          break;
> diff --git a/lib/kni/rte_kni.c b/lib/kni/rte_kni.c
> index 7971c56bb4..d7116e582c 100644
> --- a/lib/kni/rte_kni.c
> +++ b/lib/kni/rte_kni.c
> @@ -113,6 +113,19 @@ rte_kni_init(unsigned int max_kni_ifaces __rte_unused)
>          }
>      }
>
> +    uint16_t abi_version;
> +    int ret = ioctl(kni_fd, RTE_KNI_IOCTL_ABI_VERSION, &abi_version);
> +    if (ret < 0) {
> +        RTE_LOG(ERR, KNI, "Cannot verify rte_kni kmod ABI version:
> ioctl failed\n");
> +        return -1;
> +    }
> +    if (abi_version != RTE_KNI_ABI_VERSION) {
> +        RTE_LOG(ERR, KNI,
> +          "rte_kni kmod ABI version mismatch: "
> +          "need %" PRIu16 " got %" PRIu16 "\n", RTE_KNI_ABI_VERSION,
> abi_version);
> +        return -1;
> +    }
> +
>      return 0;
>  }
>
> @@ -255,6 +268,7 @@ rte_kni_alloc(struct rte_mempool *pktmbuf_pool,
>          kni->ops.port_id = UINT16_MAX;
>
>      memset(&dev_info, 0, sizeof(dev_info));
> +    dev_info.abi_version_magic = RTE_KNI_ABI_VERSION_MAGIC;
>      dev_info.core_id = conf->core_id;
>      dev_info.force_bind = conf->force_bind;
>      dev_info.group_id = conf->group_id;
> @@ -409,6 +423,8 @@ rte_kni_release(struct rte_kni *kni)
>      if (!kni)
>          return -1;
>
> +    dev_info.abi_version_magic = RTE_KNI_ABI_VERSION_MAGIC;
> +
>      kni_list = RTE_TAILQ_CAST(rte_kni_tailq.head, rte_kni_list);
>
>      rte_mcfg_tailq_write_lock();
> diff --git a/lib/kni/rte_kni_common.h b/lib/kni/rte_kni_common.h
> index 8d3ee0fa4f..c353043cb6 100644
> --- a/lib/kni/rte_kni_common.h
> +++ b/lib/kni/rte_kni_common.h
> @@ -26,6 +26,14 @@ extern "C" {
>
>  #define RTE_CACHE_LINE_MIN_SIZE 64
>
> +/*
> + * Ascend this number if ABI is altered between kmod and userland lib
> + */
> +#define RTE_KNI_ABI_VERSION 1

Instead of creating a new magic number, could you reference the
ABI_VERSION instead. 

> +#define RTE_KNI_ABI_VERSION_MAGIC_MASK 0xAAAA
> +#define RTE_KNI_ABI_VERSION_MAGIC (((RTE_KNI_ABI_VERSION) ^
> RTE_KNI_ABI_VERSION_MAGIC_MASK))
> +#define RTE_KNI_ABI_VERSION_FROM_MAGIC(__magic) (((__magic) ^
> RTE_KNI_ABI_VERSION_MAGIC_MASK))
> +
>  /*
>   * Request id.
>   */
> @@ -102,6 +110,8 @@ struct rte_kni_mbuf {
>   */
>
>  struct rte_kni_device_info {
> +    uint16_t abi_version_magic;
> +
>      char name[RTE_KNI_NAMESIZE];  /**< Network device name for KNI */
>
>      phys_addr_t tx_phys;
> @@ -139,6 +149,7 @@ struct rte_kni_device_info {
>  #define RTE_KNI_IOCTL_TEST    _IOWR(0, 1, int)
>  #define RTE_KNI_IOCTL_CREATE  _IOWR(0, 2, struct rte_kni_device_info)
>  #define RTE_KNI_IOCTL_RELEASE _IOWR(0, 3, struct rte_kni_device_info)
> +#define RTE_KNI_IOCTL_ABI_VERSION _IOWR(0, 4, uint16_t)
>
>  #ifdef __cplusplus
>  }


-- 
Regards, Ray K

  reply	other threads:[~2022-04-21 14:16 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-04-21  4:38 kni: check abi version between kmod and lib Stephen Coleman
2022-04-21 14:16 ` Ray Kinsella [this message]
2022-04-21 14:54 ` Stephen Hemminger
2022-04-21 15:40   ` Ray Kinsella
2022-04-21 15:50     ` Stephen Hemminger
2022-04-22  8:46       ` Ray Kinsella
2022-04-22 10:07         ` Stephen Coleman
2022-04-21 16:34 ` [PATCH v2] " youcai
2022-04-24  8:51 ` [PATCH v3] " youcai
2022-04-24 10:35   ` Stephen Coleman
2023-07-04  2:56 ` Stephen Hemminger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87fsm6o728.fsf@mdr78.vserver.site \
    --to=mdr@ashroe.eu \
    --cc=dev@dpdk.org \
    --cc=ferruh.yigit@xilinx.com \
    --cc=omegacoleman@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.