From 506d665a599d2e9fe5f957c507bc3327a051841b Mon Sep 17 00:00:00 2001 From: Shaun Tancheff Date: Mon, 6 Mar 2023 10:33:51 -0500 Subject: [PATCH] LU-16509 lnet: quash memcpy WARN_ONCE false positive Linux v6.1-rc1-4-g6f7630b1b5bc fortify: Capture __bos() results in const temp var In lnet_peer_push_event() the memcpy triggers a WARN_ONCE due to the flexible array at the end of struct lnet_ping_info contained in struct lnet_ping_buffer Use unsafe_memcpy() to avoid this false positive warning. Lustre-change: https://review.whamcloud.com/49801 Lustre-commit: 18e24419599666bd536d072705052a8c64b681ab (tbd) Test-Parameters: trivial HPE-bug-id: LUS-11455 Signed-off-by: Shaun Tancheff Change-Id: I4aa8f38678cd1522004d98b58a3f440d8a38589c Reviewed-on: https://review.whamcloud.com/c/ex/lustre-release/+/50217 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger --- libcfs/include/libcfs/libcfs.h | 8 ++++++++ lnet/include/uapi/linux/lnet/lnet-types.h | 2 +- lnet/lnet/api-ni.c | 2 +- lnet/lnet/peer.c | 5 +++-- lnet/utils/wirecheck.c | 11 ++++++++++- lustre/utils/wirecheck.c | 4 ++-- 6 files changed, 25 insertions(+), 7 deletions(-) diff --git a/libcfs/include/libcfs/libcfs.h b/libcfs/include/libcfs/libcfs.h index bb4219d..fd170a4 100644 --- a/libcfs/include/libcfs/libcfs.h +++ b/libcfs/include/libcfs/libcfs.h @@ -135,4 +135,12 @@ do { \ /* atomic-context safe vfree */ void libcfs_vfree_atomic(const void *addr); +#ifndef unsafe_memcpy +#define unsafe_memcpy(to, from, size, reason) memcpy((to), (from), (size)) +#endif + +#define FLEXIBLE_OBJECT \ + "Struct contains a flexible member, the size of object is checked" \ + "and can be safely copied in a single memcpy()" + #endif /* _LIBCFS_LIBCFS_H_ */ diff --git a/lnet/include/uapi/linux/lnet/lnet-types.h b/lnet/include/uapi/linux/lnet/lnet-types.h index a5fc1d1..4ab1a02 100644 --- a/lnet/include/uapi/linux/lnet/lnet-types.h +++ b/lnet/include/uapi/linux/lnet/lnet-types.h @@ -303,7 +303,7 @@ struct lnet_ping_info { __u32 pi_features; lnet_pid_t pi_pid; __u32 pi_nnis; - struct lnet_ni_status pi_ni[0]; + struct lnet_ni_status pi_ni[]; } WIRE_ATTR; #define LNET_PING_INFO_SIZE(NNIDS) \ diff --git a/lnet/lnet/api-ni.c b/lnet/lnet/api-ni.c index 0cff451..2ba6e5e 100644 --- a/lnet/lnet/api-ni.c +++ b/lnet/lnet/api-ni.c @@ -863,7 +863,7 @@ static void lnet_assert_wire_constants(void) BUILD_BUG_ON((int)offsetof(struct lnet_ping_info, pi_nnis) != 12); BUILD_BUG_ON((int)sizeof(((struct lnet_ping_info *)0)->pi_nnis) != 4); BUILD_BUG_ON((int)offsetof(struct lnet_ping_info, pi_ni) != 16); - BUILD_BUG_ON((int)sizeof(((struct lnet_ping_info *)0)->pi_ni) != 0); + BUILD_BUG_ON(offsetof(struct lnet_ping_info, pi_ni) != sizeof(struct lnet_ping_info)); } static const struct lnet_lnd *lnet_find_lnd_by_type(__u32 type) diff --git a/lnet/lnet/peer.c b/lnet/lnet/peer.c index 4ed553c..6d5cc87 100644 --- a/lnet/lnet/peer.c +++ b/lnet/lnet/peer.c @@ -2400,8 +2400,9 @@ void lnet_peer_push_event(struct lnet_event *ev) } /* Success */ - memcpy(&lp->lp_data->pb_info, &pbuf->pb_info, - LNET_PING_INFO_SIZE(pbuf->pb_info.pi_nnis)); + unsafe_memcpy(&lp->lp_data->pb_info, &pbuf->pb_info, + LNET_PING_INFO_SIZE(pbuf->pb_info.pi_nnis), + FLEXIBLE_OBJECT); lp->lp_state |= LNET_PEER_DATA_PRESENT; CDEBUG(D_NET, "Received Push %s %u\n", libcfs_nid2str(lp->lp_primary_nid), diff --git a/lnet/utils/wirecheck.c b/lnet/utils/wirecheck.c index 98aaee9..b233b6f 100644 --- a/lnet/utils/wirecheck.c +++ b/lnet/utils/wirecheck.c @@ -59,6 +59,9 @@ do { \ #define STRINGIFY(a) #a +#define CHECK_BUILD_TEST(a) \ + printf(" BUILD_BUG_ON("#a");\n") + #define CHECK_DEFINE(a) \ do { \ printf (" BUILD_BUG_ON("#a" != "STRINGIFY(a)");\n"); \ @@ -79,6 +82,12 @@ do { \ CHECK_VALUE((int)sizeof(((s *)0)->m)); \ } while (0) +#define CHECK_MEMBER_IS_FLEXIBLE(s, m) \ +do { \ + CHECK_MEMBER_OFFSET(s, m); \ + CHECK_BUILD_TEST(offsetof(struct s, m) != sizeof(struct s)); \ +} while (0) + #define CHECK_MEMBER(s,m) \ do { \ CHECK_MEMBER_OFFSET(s, m); \ @@ -189,7 +198,7 @@ check_lnet_ping_info(void) CHECK_MEMBER(struct lnet_ping_info, pi_features); CHECK_MEMBER(struct lnet_ping_info, pi_pid); CHECK_MEMBER(struct lnet_ping_info, pi_nnis); - CHECK_MEMBER(struct lnet_ping_info, pi_ni); + CHECK_MEMBER_IS_FLEXIBLE(struct lnet_ping_info, pi_ni); } void diff --git a/lustre/utils/wirecheck.c b/lustre/utils/wirecheck.c index abcee3f..e713a68 100644 --- a/lustre/utils/wirecheck.c +++ b/lustre/utils/wirecheck.c @@ -144,7 +144,7 @@ do { \ CHECK_VALUE((int)sizeof(((s *)0)->m)); \ } while(0) -#define CHECK_MEMBER_IS_FLEXIBLE_OR_ZERO_LENGTH(s, m) \ +#define CHECK_MEMBER_IS_FLEXIBLE(s, m) \ do { \ CHECK_MEMBER_OFFSET(s, m); \ CHECK_BUILD_TEST(offsetof(struct s, m) != sizeof(struct s)); \ @@ -2206,7 +2206,7 @@ check_ll_user_fiemap(void) CHECK_MEMBER(fiemap, fm_mapped_extents); CHECK_MEMBER(fiemap, fm_extent_count); CHECK_MEMBER(fiemap, fm_reserved); - CHECK_MEMBER_IS_FLEXIBLE_OR_ZERO_LENGTH(fiemap, fm_extents); + CHECK_MEMBER_IS_FLEXIBLE(fiemap, fm_extents); CHECK_CDEFINE(FIEMAP_FLAG_SYNC); CHECK_CDEFINE(FIEMAP_FLAG_XATTR); -- 1.8.3.1