From patchwork Thu Apr 21 16:34:45 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Coleman X-Patchwork-Id: 110020 Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 62A50A0093; Thu, 21 Apr 2022 18:34:57 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 0BEE440042; Thu, 21 Apr 2022 18:34:57 +0200 (CEST) Received: from mail-pf1-f180.google.com (mail-pf1-f180.google.com [209.85.210.180]) by mails.dpdk.org (Postfix) with ESMTP id D0DAB40040 for ; Thu, 21 Apr 2022 18:34:55 +0200 (CEST) Received: by mail-pf1-f180.google.com with SMTP id b15so5489337pfm.5 for ; Thu, 21 Apr 2022 09:34:55 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=Lz/MYb5urB4potuhGAW8wFNGR9MC5dHc+SifEHPcxUk=; b=ejKN7BLTLUs0qi0vaiUAQghYEwwiJW7PgoKL8Mlvr1kO9LuP7GEDH0oZhOmDCN9z5p 0YcGsKjn8+jQrkaHwgbNM3iSlsnavFxuIOlvqePQjBCiiAc1zT8rxS/ti11O7bEkFba2 ZHHaSeWFEKKc3lWWwZQKVafwQ8peq6kzTpbbzDiI3FL0VPVuV+V7HsMzMx03HnMyic2O IypgqGBGYlYULuCiRs0ku33CgXMgPYNvt4TCf6/e3GNCNMj5GpZ0/XYk07gXPTHOrUHw 9FKifqGzgM5f3ucUTjsonEjX4gfz1ObfKelMVT0BYi4ACKRtlfSW0w5nVmOt+PJ5xOmi 8p+A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=Lz/MYb5urB4potuhGAW8wFNGR9MC5dHc+SifEHPcxUk=; b=eYh/e1uZaCD3qNnfG0gwrD2buhvXUqSDGO5IZZH+0xduo6rVZIyneqdITklGXKzdp9 GZ9iHvzqU/eD6TJWEHUm2aNN6I0+/jNmQPSMfHVWl2lXeFnvqvGh6RE8HxCFB6/BvejG YFbq0e4G+dbGB9QR7Zb3DecSpLTPHdgyrvbnsr1gncocmQ91jJPu7lAaCOhT42aYOinN 6SLyYOeI14IG39IQXVmGZxmR0cQHwFP7yTRiN5Xns9vzypjWeEcwDDzu7T9Bj3D8ak10 CyDyUEJCMPz0T5Cpq2eQwqe/x+JIvpNWxHPAB5G9zlivBjIiYQlcra07ZCtMGpx5SvzW +tQg== X-Gm-Message-State: AOAM5305hLoxa/8iiE0PnYEzsRKDb03Yd2MAd3qTF9W7Fi42Ma+n0HuD tqY/4mAbzJ1KGYr7RT61w1UlLSPJj4zZFaYN X-Google-Smtp-Source: ABdhPJyeG4Lag7mEhFA8vI+/e8gFRxdmMmqZsoCUeawaX15GmAi9Vzb2fWWzjTpK6liQXHAzz9lgYw== X-Received: by 2002:a63:2266:0:b0:39c:f643:ee69 with SMTP id t38-20020a632266000000b0039cf643ee69mr254099pgm.288.1650558895008; Thu, 21 Apr 2022 09:34:55 -0700 (PDT) Received: from localhost (n219073108118.netvigator.com. [219.73.108.118]) by smtp.gmail.com with ESMTPSA id hi21-20020a17090b30d500b001cd4989ff4csm3290331pjb.19.2022.04.21.09.34.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Apr 2022 09:34:54 -0700 (PDT) From: youcai To: dev@dpdk.org Cc: Ray Kinsella , Stephen Hemminger , Ferruh Yigit , youcai Subject: [PATCH v2] kni: check abi version between kmod and lib Date: Fri, 22 Apr 2022 00:34:45 +0800 Message-Id: <20220421163445.3139491-1-omegacoleman@gmail.com> X-Mailer: git-send-email 2.35.1 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org 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 --- V2: use ABI_VERSION instead of a new magic V2: fix some indent --- kernel/linux/kni/kni_misc.c | 40 ++++++++++++++++++++++++++++++++++++ kernel/linux/kni/meson.build | 4 ++-- lib/kni/meson.build | 1 + lib/kni/rte_kni.c | 17 +++++++++++++++ lib/kni/rte_kni_abi.h | 17 +++++++++++++++ lib/kni/rte_kni_common.h | 3 +++ 6 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 lib/kni/rte_kni_abi.h diff --git a/kernel/linux/kni/kni_misc.c b/kernel/linux/kni/kni_misc.c index 780187d8bf..9a1ed22fed 100644 --- a/kernel/linux/kni/kni_misc.c +++ b/kernel/linux/kni/kni_misc.c @@ -17,6 +17,7 @@ #include #include +#include #include "compat.h" #include "kni_dev.h" @@ -236,12 +237,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 +314,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 +471,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 +511,16 @@ 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 = ABI_VERSION_MAJOR; + if (copy_to_user((void *)ioctl_param, &abi_version, sizeof(uint16_t))) + return -EFAULT; + return 0; +} + static long kni_ioctl(struct file *file, unsigned int ioctl_num, unsigned long ioctl_param) { @@ -505,6 +542,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/kernel/linux/kni/meson.build b/kernel/linux/kni/meson.build index 4c90069e99..c8cd23acd9 100644 --- a/kernel/linux/kni/meson.build +++ b/kernel/linux/kni/meson.build @@ -3,12 +3,12 @@ # For SUSE build check function arguments of ndo_tx_timeout API # Ref: https://jira.devtools.intel.com/browse/DPDK-29263 -kmod_cflags = '' +kmod_cflags = '-DABI_VERSION_MAJOR=@0@'.format(abi_version.split('.')[0]) file_path = kernel_source_dir + '/include/linux/netdevice.h' run_cmd = run_command('grep', 'ndo_tx_timeout', file_path, check: false) if run_cmd.stdout().contains('txqueue') == true - kmod_cflags = '-DHAVE_ARG_TX_QUEUE' + kmod_cflags += ' -DHAVE_ARG_TX_QUEUE' endif diff --git a/lib/kni/meson.build b/lib/kni/meson.build index 8a71d8ba6f..f22a27b15b 100644 --- a/lib/kni/meson.build +++ b/lib/kni/meson.build @@ -14,3 +14,4 @@ endif sources = files('rte_kni.c') headers = files('rte_kni.h', 'rte_kni_common.h') deps += ['ethdev', 'pci'] +cflags += ['-DABI_VERSION_MAJOR=@0@'.format(abi_version.split('.')[0])] diff --git a/lib/kni/rte_kni.c b/lib/kni/rte_kni.c index 7971c56bb4..1c8a610bd4 100644 --- a/lib/kni/rte_kni.c +++ b/lib/kni/rte_kni.c @@ -22,6 +22,7 @@ #include #include #include "rte_kni_fifo.h" +#include "rte_kni_abi.h" #define MAX_MBUF_BURST_NUM 32 @@ -113,6 +114,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 != ABI_VERSION_MAJOR) { + RTE_LOG(ERR, KNI, + "rte_kni kmod ABI version mismatch: " + "need %" PRIu16 " got %" PRIu16 "\n", ABI_VERSION_MAJOR, abi_version); + return -1; + } + return 0; } @@ -255,6 +269,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 +424,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_abi.h b/lib/kni/rte_kni_abi.h new file mode 100644 index 0000000000..7dde394c72 --- /dev/null +++ b/lib/kni/rte_kni_abi.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: (BSD-3-Clause OR LGPL-2.1) */ +/* + * Copyright(c) 2007-2014 Intel Corporation. + */ + +#ifndef _RTE_KNI_ABI_H_ +#define _RTE_KNI_ABI_H_ + +#ifndef ABI_VERSION_MAJOR +#error Need ABI_VERSION_MAJOR being the major part of dpdk/ABI_VERSION +#endif +#define RTE_KNI_ABI_VERSION_MAGIC_MASK 0xAAAA +#define RTE_KNI_ABI_VERSION_MAGIC (((ABI_VERSION_MAJOR) ^ RTE_KNI_ABI_VERSION_MAGIC_MASK)) +#define RTE_KNI_ABI_VERSION_FROM_MAGIC(__magic) (((__magic) ^ RTE_KNI_ABI_VERSION_MAGIC_MASK)) + +#endif + diff --git a/lib/kni/rte_kni_common.h b/lib/kni/rte_kni_common.h index 8d3ee0fa4f..f9432b742c 100644 --- a/lib/kni/rte_kni_common.h +++ b/lib/kni/rte_kni_common.h @@ -102,6 +102,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 +141,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 }