diff options
author | Thomas Haller <thaller@redhat.com> | 2022-05-09 15:05:12 +0200 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2022-05-11 17:06:12 +0200 |
commit | a34bad8b520d85281e583e81be74129b08e20d77 (patch) | |
tree | 0a69b5c1b7b1c1f1cbd99c3521f12d7a28ef42d7 | |
parent | d6e6443b864499d95f198714ad289cb74c158b30 (diff) |
platform: use flexible array members for "NMPlatformIPAddress.address_ptr"/"NMPlatformIPRoute.network_ptr"
Try to workaround a coverity warning:
30. NetworkManager-1.39.3/src/core/vpn/nm-vpn-connection.c:2000:
overrun-buffer-val: Overrunning array "address.ax.address_ptr" of 1
bytes by passing it to a function which accesses it at byte offset 3.
-rw-r--r-- | src/libnm-glib-aux/nm-shared-utils.c | 7 | ||||
-rw-r--r-- | src/libnm-glib-aux/nm-shared-utils.h | 2 | ||||
-rw-r--r-- | src/libnm-platform/nm-platform.h | 28 |
3 files changed, 24 insertions, 13 deletions
diff --git a/src/libnm-glib-aux/nm-shared-utils.c b/src/libnm-glib-aux/nm-shared-utils.c index 50512ee10f..b8102cc8bc 100644 --- a/src/libnm-glib-aux/nm-shared-utils.c +++ b/src/libnm-glib-aux/nm-shared-utils.c @@ -37,6 +37,13 @@ const void *const _NM_PTRARRAY_EMPTY[1] = {NULL}; const NMIPAddr nm_ip_addr_zero = {}; +/* We use _nm_alignas(NMIPAddr). Ensure that this struct has the same + * alignment as in_addr_t and struct in6_addr. */ +G_STATIC_ASSERT(_nm_alignof(NMIPAddr) == 4); +G_STATIC_ASSERT(_nm_alignof(in_addr_t) == 4); +G_STATIC_ASSERT(_nm_alignof(struct in_addr) == 4); +G_STATIC_ASSERT(_nm_alignof(struct in6_addr) == 4); + /* this initializes a struct in_addr/in6_addr and allows for untrusted * arguments (like unsuitable @addr_family or @src_len). It's almost safe * in the sense that it verifies input arguments strictly. Also, it diff --git a/src/libnm-glib-aux/nm-shared-utils.h b/src/libnm-glib-aux/nm-shared-utils.h index 80f6bcddb9..0e123cf1c0 100644 --- a/src/libnm-glib-aux/nm-shared-utils.h +++ b/src/libnm-glib-aux/nm-shared-utils.h @@ -216,7 +216,7 @@ nm_ether_addr_equal(const NMEtherAddr *a, const NMEtherAddr *b) typedef struct { union { - guint8 addr_ptr[1]; + guint8 addr_ptr[sizeof(struct in6_addr)]; in_addr_t addr4; struct in_addr addr4_struct; struct in6_addr addr6; diff --git a/src/libnm-platform/nm-platform.h b/src/libnm-platform/nm-platform.h index 7113607e88..b19b933f2a 100644 --- a/src/libnm-platform/nm-platform.h +++ b/src/libnm-platform/nm-platform.h @@ -333,6 +333,9 @@ typedef enum { * should be configured. */ \ bool a_force_commit : 1; \ \ + /* Don't have a bitfield as last field in __NMPlatformIPAddress_COMMON. It would then + * be unclear how the following fields get merged. We could also use a zero bitfield, + * but instead we just have there the uint8 field. */ \ guint8 plen; \ ; @@ -343,10 +346,7 @@ typedef enum { **/ typedef struct { __NMPlatformIPAddress_COMMON; - union { - guint8 address_ptr[1]; - guint32 __dummy_for_32bit_alignment; - }; + _nm_alignas(NMIPAddr) guint8 address_ptr[]; } NMPlatformIPAddress; /** @@ -358,11 +358,15 @@ struct _NMPlatformIP4Address { /* Whether the address is ready to be configured. By default, an address is, but this * flag may indicate that the address is just for tracking purpose only, but the ACD - * state is not yet ready for the address to be configured. */ + * state is not yet ready for the address to be configured. + * + * This bit fits actually in an alignment gap between __NMPlatformIPAddress_COMMON and + * "address" field. Usually "address" must be the first field after __NMPlatformIPAddress_COMMON, + * but there is a gap. We have a static assertion that checks this, so all is good. */ bool a_acd_not_ready : 1; /* The local address IFA_LOCAL. */ - in_addr_t address; + _nm_alignas(NMIPAddr) in_addr_t address; /* The IFA_ADDRESS PTP peer address. This field is rather important, because * it constitutes the identifier for the IPv4 address (e.g. you can add two @@ -390,7 +394,7 @@ struct _NMPlatformIP4Address { **/ struct _NMPlatformIP6Address { __NMPlatformIPAddress_COMMON; - struct in6_addr address; + _nm_alignas(NMIPAddr) struct in6_addr address; struct in6_addr peer_address; }; @@ -526,16 +530,16 @@ typedef union { * * This is not the original type, if type_coerced is 0 then * it means RTN_UNSPEC otherwise the type value is preserved. - * */ \ + */ \ + /* Don't have a bitfield as last field in __NMPlatformIPAddress_COMMON. It would then + * be unclear how the following fields get merged. We could also use a zero bitfield, + * but instead we just have there the uint8 field. */ \ guint8 type_coerced; \ ; typedef struct { __NMPlatformIPRoute_COMMON; - union { - guint8 network_ptr[1]; - guint32 __dummy_for_32bit_alignment; - }; + _nm_alignas(NMIPAddr) guint8 network_ptr[]; } NMPlatformIPRoute; #define NM_PLATFORM_IP_ROUTE_CAST(route) \ |