From patchwork Sun Apr 24 08:51:53 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Coleman X-Patchwork-Id: 110187 X-Patchwork-Delegate: thomas@monjalon.net 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 89A85A00C4; Sun, 24 Apr 2022 10:52:12 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 759074014F; Sun, 24 Apr 2022 10:52:12 +0200 (CEST) Received: from mail-pg1-f181.google.com (mail-pg1-f181.google.com [209.85.215.181]) by mails.dpdk.org (Postfix) with ESMTP id 605794003F for ; Sun, 24 Apr 2022 10:52:10 +0200 (CEST) Received: by mail-pg1-f181.google.com with SMTP id g9so10926415pgc.10 for ; Sun, 24 Apr 2022 01:52:10 -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=Qtp4WyrzCjtYC7xZUtQEEn7xlCEupyB49KHjxmhIrOw=; b=OTtgFh9y/UHrjaQL042QUMeC3NvrDTTWL65EiA5CXklPNaR0DCG4O+n0cn6G5ctxmf ibwzWbCvD5M98m+K2spC7Jrkcm3nCFSg938byEDQN8ej6LcZa85M3ybwM4abqzUO1RiU SzeYaJjn/IdHnNhTLMzSMTcM/RP1MHSOycmIOtOGa6aQUAf6r2BrbKgO3yqLn4Uqt8bi NfYqg4Ot9xM21/ksdZUrdHkILlJgnlWPuOSvIbQVAp9QOrB0VKLoFA+xw0oixxlTsUCx w054OJHiuzXYaz2hjBLjx114uRcKt9V97mlixaO76Lt0sHv4wygv6l9T7+QjgUrjgKYn 84Vw== 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=Qtp4WyrzCjtYC7xZUtQEEn7xlCEupyB49KHjxmhIrOw=; b=7crEd7nzH6te4EqhCdFoPPOA0Ro4E6AFJF0S9ZnaLYOmScO1a9rGbxHuMlLhU68zcn 3tThuAIKoSBJI5DhOBsO5Vm0hn38A/NrNwAtt0XSgzWPsvJI7CPs6kZppvD1TQP4RPk1 llOJBVk4GP83GrVT8t8QcsK5lH18/wjSCWVOe3pX00wqJ9Ahu3iFseoCB/FhOkTS3ywP apo4m9qj7ocAT+utrc45hPWA5aJJpPOSFteYZ+UsjRBHU8KY+WJHFP8Xaj4qmfCizP4e lQNbC83d87ppoYo8grE5U9tQNdWKT6R96cKYNs7jV0WiGWk6vyZJk2cmcpjHgmYBRzNW 0MZA== X-Gm-Message-State: AOAM533Q2LORCQqfuuEKyxWqFFlcY1m4azjL88Wf1lZtawjcb+c7In6H hA6swIbv6/EklGkEt6yZRQ7M/ex4f28Tw4lT4q1c1A== X-Google-Smtp-Source: ABdhPJwH03YvfaePFI7p/yT2dQbWIhJi3kxuhay2EQxV8W8umThkjG5FTlBPihBrsiiLyZ7n7Bbm9Q== X-Received: by 2002:a63:214e:0:b0:399:1123:a388 with SMTP id s14-20020a63214e000000b003991123a388mr10618244pgm.66.1650790329453; Sun, 24 Apr 2022 01:52:09 -0700 (PDT) Received: from localhost (210-61-91-200.hinet-ip.hinet.net. [210.61.91.200]) by smtp.gmail.com with ESMTPSA id s19-20020aa78d53000000b004fdaae08497sm7506405pfe.28.2022.04.24.01.52.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 24 Apr 2022 01:52:08 -0700 (PDT) From: youcai To: dev@dpdk.org Cc: Ray Kinsella , Stephen Hemminger , Ferruh Yigit , youcai Subject: [PATCH v3] kni: check abi version between kmod and lib Date: Sun, 24 Apr 2022 16:51:53 +0800 Message-Id: <20220424085153.925314-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 --- V3: fix code format issues V2: use ABI_VERSION instead of a new magic V2: fix some indent --- kernel/linux/kni/kni_misc.c | 42 ++++++++++++++++++++++++++++++++++++ kernel/linux/kni/meson.build | 4 ++-- lib/kni/meson.build | 1 + lib/kni/rte_kni.c | 18 ++++++++++++++++ lib/kni/rte_kni_abi.h | 17 +++++++++++++++ lib/kni/rte_kni_common.h | 3 +++ 6 files changed, 83 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..d92500414d 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,26 @@ 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 +316,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 +473,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 +513,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 +544,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..9bdeeb3806 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,20 @@ 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 +270,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 +425,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 }