From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id C171C45A9D; Wed, 2 Oct 2024 17:47:07 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 668A840B9D; Wed, 2 Oct 2024 17:45:04 +0200 (CEST) Received: from mail-il1-f180.google.com (mail-il1-f180.google.com [209.85.166.180]) by mails.dpdk.org (Postfix) with ESMTP id DABE640687 for ; Wed, 2 Oct 2024 17:44:54 +0200 (CEST) Received: by mail-il1-f180.google.com with SMTP id e9e14a558f8ab-3a363706905so6492135ab.3 for ; Wed, 02 Oct 2024 08:44:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=networkplumber-org.20230601.gappssmtp.com; s=20230601; t=1727883894; x=1728488694; darn=dpdk.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=ITvw+xP73Q4h+neEOJzkW8pwBa54BcfexQXUS0/gJBc=; b=wSz3AR2gfUKvk+Yn+XOwEQQvV+F4Ux6IBDXBcfJRilqItBk3+0suqiDRpA0iMHJL8+ 39R69wGEijBrUGDvmhlS4zaX9TfHSHbwt10fNShiyioliKV2SoaEllT7nMD/h9H1mnzc KQfi8tEJhmAvVBYAxrzbxEhPL9xwxsifyIt6VSREKihMqaITJMEtWRMcN3G3lzstPoVU ihNYQiyTCxrsI+Y+H1ZtaWerUxAQTbv/0w3+6MnNKdge10jrmKE0Htph3/86O/pLvesi 4yIveMAEi274Apc2qaQXI5Veo0uvbdq0W59BXFUJl55tvbxc2mZYid1fErPB0VjQqAzT SPZg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1727883894; x=1728488694; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ITvw+xP73Q4h+neEOJzkW8pwBa54BcfexQXUS0/gJBc=; b=M7KIPTjlQsKY382n6XnokUTPx+xfVNmJ8EI1RwrxaeTJJkMW7wQnRVvnvNEWTCbngQ GOGvJ4bZ0TMU6tuRYhivpjjDi+tpLP8VwQjfgI2s24eaTGFQtyfNF29PDOPXrPLBnDCh 9VCVXXYFubBAySN2Qcr3Ck+FEkRTmV+2zzfVhvxg1g1i1UFRE5fowKTiM6lxv9VEQzsT Z7oOqxkK7o5fkLl+O6hzY+yGwHpQIPLQhxGGMfOqimZJ7+wWeLNQjItLEtQ+UUXXVLGH Y3lfLJsN3ADmraTzgOxdqCxBXyNIDLlq1anxUlIg3vTYNqqdZ1IbGP1DqHX6NhSHfQUo c9CQ== X-Gm-Message-State: AOJu0Yyhal5J0r01Xh4v8YaPCvr8o+uM5Jot2nAVWoPPx/0Ww0oJXiYD Rzjn94cUD1sWuYFcOGpTeGjHKdJHepi/OKXCuIu9B3f1Wn9FFGgOlTSqEGM/swX33uuY9qODrgK o79U= X-Google-Smtp-Source: AGHT+IGq4bqtkLzhPAH8YHFAEy4qid9uOJw0Hh0aBoJMcx2YV0Sj6GOEZlzWuPlx7FT6nDt/TO6gAw== X-Received: by 2002:a05:6e02:16c9:b0:3a0:52f9:9170 with SMTP id e9e14a558f8ab-3a365915503mr34457775ab.1.1727883894097; Wed, 02 Oct 2024 08:44:54 -0700 (PDT) Received: from hermes.local (204-195-96-226.wavecable.com. [204.195.96.226]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-7e6db2927c7sm10247363a12.1.2024.10.02.08.44.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 02 Oct 2024 08:44:53 -0700 (PDT) From: Stephen Hemminger To: dev@dpdk.org Cc: Stephen Hemminger , Chengwen Feng , Anatoly Burakov , Tyler Retzlaff Subject: [PATCH v6 17/17] eal: add function attributes for allocation functions Date: Wed, 2 Oct 2024 08:43:01 -0700 Message-ID: <20241002154429.64357-18-stephen@networkplumber.org> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20241002154429.64357-1-stephen@networkplumber.org> References: <20240927204742.546164-1-stephen@networkplumber.org> <20241002154429.64357-1-stephen@networkplumber.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 The allocation functions take a alignment argument that can be useful to hint the compiler optimizer. This is supported by GCC and Clang but only useful with GCC because Clang gives warning if alignment is 0. Newer versions of GCC have a malloc attribute that can be used to find mismatches between allocation and free; the typical problem caught is a pointer allocated with rte_malloc() that is then incorrectly freed using free(). The name of the DPDK wrapper macros for these attributes are chosen to be similar to what GLIBC is using in cdefs.h. Note: The rte_free function prototype was moved ahead of the allocation functions since the dealloc attribute now refers to it. Signed-off-by: Stephen Hemminger Acked-by: Chengwen Feng Acked-by: Anatoly Burakov --- doc/guides/rel_notes/release_24_11.rst | 8 ++++ lib/eal/include/rte_common.h | 34 +++++++++++++++ lib/eal/include/rte_malloc.h | 59 ++++++++++++++++---------- 3 files changed, 78 insertions(+), 23 deletions(-) diff --git a/doc/guides/rel_notes/release_24_11.rst b/doc/guides/rel_notes/release_24_11.rst index 0ff70d9057..f27a37eac4 100644 --- a/doc/guides/rel_notes/release_24_11.rst +++ b/doc/guides/rel_notes/release_24_11.rst @@ -55,6 +55,14 @@ New Features Also, make sure to start the actual text at the margin. ======================================================= +* **Hardened rte_malloc and related functions.** + + * Added function attributes to ``rte_malloc`` and similar functions + that can catch some obvious bugs at compile time (with GCC 11.0 or later). + Examples: calling ``free()`` on pointer that was allocated with ``rte_malloc`` + (and vice versa); freeing the same pointer twice in the same routine; + freeing an object that was not created by allocation; etc. + Removed Items ------------- diff --git a/lib/eal/include/rte_common.h b/lib/eal/include/rte_common.h index eec0400dad..a53051072e 100644 --- a/lib/eal/include/rte_common.h +++ b/lib/eal/include/rte_common.h @@ -228,6 +228,40 @@ typedef uint16_t unaligned_uint16_t; #define __rte_alloc_size(...) #endif +/** + * Tells the compiler that the function returns a value that points to + * memory aligned by a function argument. + * + * Note: not enabled on Clang because it warns if align argument is zero. + */ +#if defined(RTE_CC_GCC) +#define __rte_alloc_align(argno) \ + __attribute__((alloc_align(argno))) +#else +#define __rte_alloc_align(argno) +#endif + +/** + * Tells the compiler this is a function like malloc and that the pointer + * returned cannot alias any other pointer (ie new memory). + */ +#if defined(RTE_CC_GCC) || defined(RTE_CC_CLANG) +#define __rte_malloc __attribute__((__malloc__)) +#else +#define __rte_malloc +#endif + +/** + * With recent GCC versions also able to track that proper + * deallocator function is used for this pointer. + */ +#if defined(RTE_TOOLCHAIN_GCC) && (GCC_VERSION >= 110000) +#define __rte_dealloc(dealloc, argno) \ + __attribute__((malloc(dealloc, argno))) +#else +#define __rte_dealloc(dealloc, argno) +#endif + #define RTE_PRIORITY_LOG 101 #define RTE_PRIORITY_BUS 110 #define RTE_PRIORITY_CLASS 120 diff --git a/lib/eal/include/rte_malloc.h b/lib/eal/include/rte_malloc.h index 1f91e7bdde..176a94d1bf 100644 --- a/lib/eal/include/rte_malloc.h +++ b/lib/eal/include/rte_malloc.h @@ -31,6 +31,26 @@ struct rte_malloc_socket_stats { size_t heap_allocsz_bytes; /**< Total allocated bytes on heap */ }; +/** + * Function attribut for prototypes that expect to release memory with rte_free() + */ +#define __rte_dealloc_free __rte_dealloc(rte_free, 1) + +/** + * Frees the memory space pointed to by the provided pointer. + * + * This pointer must have been returned by a previous call to + * rte_malloc(), rte_zmalloc(), rte_calloc() or rte_realloc(). The behaviour of + * rte_free() is undefined if the pointer does not match this requirement. + * + * If the pointer is NULL, the function does nothing. + * + * @param ptr + * The pointer to memory to be freed. + */ +void +rte_free(void *ptr); + /** * This function allocates memory from the huge-page area of memory. The memory * is not cleared. In NUMA systems, the memory allocated resides on the same @@ -54,7 +74,8 @@ struct rte_malloc_socket_stats { */ void * rte_malloc(const char *type, size_t size, unsigned align) - __rte_alloc_size(2); + __rte_alloc_size(2) __rte_alloc_align(3) + __rte_malloc __rte_dealloc_free; /** * Allocate zeroed memory from the heap. @@ -81,7 +102,8 @@ rte_malloc(const char *type, size_t size, unsigned align) */ void * rte_zmalloc(const char *type, size_t size, unsigned align) - __rte_alloc_size(2); + __rte_alloc_size(2) __rte_alloc_align(3) + __rte_malloc __rte_dealloc_free; /** * Replacement function for calloc(), using huge-page memory. Memory area is @@ -108,7 +130,8 @@ rte_zmalloc(const char *type, size_t size, unsigned align) */ void * rte_calloc(const char *type, size_t num, size_t size, unsigned align) - __rte_alloc_size(2, 3); + __rte_alloc_size(2, 3) __rte_alloc_align(4) + __rte_malloc __rte_dealloc_free; /** * Replacement function for realloc(), using huge-page memory. Reserved area @@ -132,7 +155,8 @@ rte_calloc(const char *type, size_t num, size_t size, unsigned align) */ void * rte_realloc(void *ptr, size_t size, unsigned int align) - __rte_alloc_size(2); + __rte_alloc_size(2) __rte_alloc_align(3) + __rte_malloc __rte_dealloc_free; /** * Replacement function for realloc(), using huge-page memory. Reserved area @@ -158,7 +182,8 @@ rte_realloc(void *ptr, size_t size, unsigned int align) */ void * rte_realloc_socket(void *ptr, size_t size, unsigned int align, int socket) - __rte_alloc_size(2); + __rte_alloc_size(2) __rte_alloc_align(3) + __rte_malloc __rte_dealloc_free; /** * This function allocates memory from the huge-page area of memory. The memory @@ -185,7 +210,8 @@ rte_realloc_socket(void *ptr, size_t size, unsigned int align, int socket) */ void * rte_malloc_socket(const char *type, size_t size, unsigned align, int socket) - __rte_alloc_size(2); + __rte_alloc_size(2) __rte_alloc_align(3) + __rte_malloc __rte_dealloc_free; /** * Allocate zeroed memory from the heap. @@ -214,7 +240,8 @@ rte_malloc_socket(const char *type, size_t size, unsigned align, int socket) */ void * rte_zmalloc_socket(const char *type, size_t size, unsigned align, int socket) - __rte_alloc_size(2); + __rte_alloc_size(2) __rte_alloc_align(3) + __rte_malloc __rte_dealloc_free; /** * Replacement function for calloc(), using huge-page memory. Memory area is @@ -243,22 +270,8 @@ rte_zmalloc_socket(const char *type, size_t size, unsigned align, int socket) */ void * rte_calloc_socket(const char *type, size_t num, size_t size, unsigned align, int socket) - __rte_alloc_size(2, 3); - -/** - * Frees the memory space pointed to by the provided pointer. - * - * This pointer must have been returned by a previous call to - * rte_malloc(), rte_zmalloc(), rte_calloc() or rte_realloc(). The behaviour of - * rte_free() is undefined if the pointer does not match this requirement. - * - * If the pointer is NULL, the function does nothing. - * - * @param ptr - * The pointer to memory to be freed. - */ -void -rte_free(void *ptr); + __rte_alloc_size(2, 3) __rte_alloc_align(4) + __rte_malloc __rte_dealloc_free; /** * If malloc debug is enabled, check a memory block for header -- 2.45.2