From a3cf8587b6fafdfed16fe0870efddcf6c0746c88 Mon Sep 17 00:00:00 2001 From: Shaun Tancheff Date: Fri, 27 Jan 2023 01:08:23 -0600 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. Test-Parameters: trivial HPE-bug-id: LUS-11455 Signed-off-by: Shaun Tancheff Change-Id: I4aa8f38678cd1522004d98b58a3f440d8a38589c Reviewed-on: https://review.whamcloud.com/c/fs/lustre-release/+/49801 Tested-by: jenkins Tested-by: Maloo Reviewed-by: Andreas Dilger Reviewed-by: Oleg Drokin Reviewed-by: Patrick Farrell --- libcfs/include/libcfs/libcfs.h | 8 ++++++++ lnet/include/uapi/linux/lnet/lnet-idl.h | 2 +- lnet/lnet/api-ni.c | 2 +- lnet/lnet/peer.c | 3 ++- lnet/utils/wirecheck.c | 11 ++++++++++- lustre/utils/wirecheck.c | 4 ++-- 6 files changed, 24 insertions(+), 6 deletions(-) diff --git a/libcfs/include/libcfs/libcfs.h b/libcfs/include/libcfs/libcfs.h index 5a90865..7b552d4 100644 --- a/libcfs/include/libcfs/libcfs.h +++ b/libcfs/include/libcfs/libcfs.h @@ -133,4 +133,12 @@ void libcfs_vfree_atomic(const void *addr); #define INTERVAL_TREE_ROOT RB_ROOT #endif /* HAVE_INTERVAL_TREE_CACHED */ +#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-idl.h b/lnet/include/uapi/linux/lnet/lnet-idl.h index ff44538..450c66a 100644 --- a/lnet/include/uapi/linux/lnet/lnet-idl.h +++ b/lnet/include/uapi/linux/lnet/lnet-idl.h @@ -309,7 +309,7 @@ struct lnet_ping_info { __u32 pi_features; lnet_pid_t pi_pid; __u32 pi_nnis; /* number of nid4 entries */ - struct lnet_ni_status pi_ni[0]; + struct lnet_ni_status pi_ni[]; } __attribute__((packed)); #define LNET_PING_INFO_HDR_SIZE \ diff --git a/lnet/lnet/api-ni.c b/lnet/lnet/api-ni.c index c0ce984..58ebd4d 100644 --- a/lnet/lnet/api-ni.c +++ b/lnet/lnet/api-ni.c @@ -952,7 +952,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)); /* Acceptor connection request */ BUILD_BUG_ON(LNET_PROTO_ACCEPTOR_VERSION != 1); diff --git a/lnet/lnet/peer.c b/lnet/lnet/peer.c index 6c2cedb..37ffb23 100644 --- a/lnet/lnet/peer.c +++ b/lnet/lnet/peer.c @@ -2440,7 +2440,8 @@ void lnet_peer_push_event(struct lnet_event *ev) } /* Success */ - memcpy(&lp->lp_data->pb_info, &pbuf->pb_info, infobytes); + unsafe_memcpy(&lp->lp_data->pb_info, &pbuf->pb_info, infobytes, + FLEXIBLE_OBJECT); lp->lp_state |= LNET_PEER_DATA_PRESENT; CDEBUG(D_NET, "Received Push %s %u\n", libcfs_nidstr(&lp->lp_primary_nid), diff --git a/lnet/utils/wirecheck.c b/lnet/utils/wirecheck.c index 4edc523..e67d75c 100644 --- a/lnet/utils/wirecheck.c +++ b/lnet/utils/wirecheck.c @@ -58,6 +58,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"); \ @@ -78,6 +81,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); \ @@ -194,7 +203,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 c5d0590..5b910c9 100644 --- a/lustre/utils/wirecheck.c +++ b/lustre/utils/wirecheck.c @@ -145,7 +145,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)); \ @@ -2238,7 +2238,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