diff --git a/meson.build b/meson.build index f25ad1a27e..61fba8dc09 100644 --- a/meson.build +++ b/meson.build @@ -380,6 +380,7 @@ possible_common_cc_flags = [ '-Wendif-labels', '-Werror=bool-compare', '-Werror=discarded-qualifiers', + '-Werror=flex-array-member-not-at-end', '-Werror=format=2', '-Werror=format-signedness', '-Werror=implicit-function-declaration', diff --git a/src/boot/measure.c b/src/boot/measure.c index 15f1ba9aff..48e9fb5fc5 100644 --- a/src/boot/measure.c +++ b/src/boot/measure.c @@ -18,10 +18,10 @@ static EFI_STATUS tpm2_measure_to_pcr_and_tagged_event_log( uint32_t event_id, const char16_t *description) { - _cleanup_free_ struct event { + _cleanup_free_ union event { EFI_TCG2_EVENT tcg_event; EFI_TCG2_TAGGED_EVENT tcg_tagged_event; - } _packed_ *event = NULL; + } *event = NULL; size_t desc_len, event_size; assert(tcg); @@ -30,21 +30,17 @@ static EFI_STATUS tpm2_measure_to_pcr_and_tagged_event_log( /* New style stuff we log as EV_EVENT_TAG with a recognizable event tag. */ desc_len = strsize16(description); - event_size = offsetof(EFI_TCG2_EVENT, Event) + offsetof(EFI_TCG2_TAGGED_EVENT, Event) + desc_len; + event_size = offsetof(EFI_TCG2_TAGGED_EVENT, Event) + desc_len; event = xmalloc(event_size); - *event = (struct event) { - .tcg_event = (EFI_TCG2_EVENT) { - .Size = event_size, - .Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER), - .Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION, - .Header.PCRIndex = pcrindex, - .Header.EventType = EV_EVENT_TAG, - }, - .tcg_tagged_event = { - .EventId = event_id, - .EventSize = desc_len, - }, + event->tcg_tagged_event = (EFI_TCG2_TAGGED_EVENT) { + .Size = event_size, + .Header.HeaderSize = sizeof(EFI_TCG2_EVENT_HEADER), + .Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION, + .Header.PCRIndex = pcrindex, + .Header.EventType = EV_EVENT_TAG, + .EventId = event_id, + .EventSize = desc_len, }; memcpy(event->tcg_tagged_event.Event, description, desc_len); diff --git a/src/boot/proto/tcg.h b/src/boot/proto/tcg.h index e243bf8b72..a85288178c 100644 --- a/src/boot/proto/tcg.h +++ b/src/boot/proto/tcg.h @@ -59,6 +59,8 @@ typedef struct { } _packed_ EFI_TCG2_EVENT; typedef struct { + uint32_t Size; + EFI_TCG2_EVENT_HEADER Header; uint32_t EventId; uint32_t EventSize; uint8_t Event[]; diff --git a/src/fundamental/efi-fundamental.h b/src/fundamental/efi-fundamental.h index de7ae6cd8a..f72290e1b3 100644 --- a/src/fundamental/efi-fundamental.h +++ b/src/fundamental/efi-fundamental.h @@ -36,11 +36,10 @@ typedef struct { uint32_t dwLength; uint16_t wRevision; uint16_t wCertificateType; - uint8_t bCertificate[]; -} WIN_CERTIFICATE; +} WIN_CERTIFICATE_HEADER; typedef struct { - WIN_CERTIFICATE Hdr; + WIN_CERTIFICATE_HEADER Hdr; EFI_GUID CertType; uint8_t CertData[]; } WIN_CERTIFICATE_UEFI_GUID; diff --git a/src/libsystemd-network/dhcp-protocol.h b/src/libsystemd-network/dhcp-protocol.h index d7bb203aab..b3b247a567 100644 --- a/src/libsystemd-network/dhcp-protocol.h +++ b/src/libsystemd-network/dhcp-protocol.h @@ -19,22 +19,25 @@ * MIN_V6ONLY_WAIT: The lower boundary for V6ONLY_WAIT. Value: 300 seconds */ #define MIN_V6ONLY_WAIT_USEC (300U * USEC_PER_SEC) -struct DHCPMessage { - uint8_t op; - uint8_t htype; - uint8_t hlen; - uint8_t hops; - be32_t xid; - be16_t secs; - be16_t flags; - be32_t ciaddr; - be32_t yiaddr; - be32_t siaddr; - be32_t giaddr; - uint8_t chaddr[16]; - uint8_t sname[64]; - uint8_t file[128]; +#define DHCP_MESSAGE_HEADER_DEFINITION \ + uint8_t op; \ + uint8_t htype; \ + uint8_t hlen; \ + uint8_t hops; \ + be32_t xid; \ + be16_t secs; \ + be16_t flags; \ + be32_t ciaddr; \ + be32_t yiaddr; \ + be32_t siaddr; \ + be32_t giaddr; \ + uint8_t chaddr[16]; \ + uint8_t sname[64]; \ + uint8_t file[128]; \ be32_t magic; + +struct DHCPMessage { + DHCP_MESSAGE_HEADER_DEFINITION; uint8_t options[]; } _packed_; diff --git a/src/libsystemd-network/test-dhcp-server.c b/src/libsystemd-network/test-dhcp-server.c index 97e4b04475..a067fc0da5 100644 --- a/src/libsystemd-network/test-dhcp-server.c +++ b/src/libsystemd-network/test-dhcp-server.c @@ -82,7 +82,9 @@ static int test_basic(bool bind_to_interface) { static void test_message_handler(void) { _cleanup_(sd_dhcp_server_unrefp) sd_dhcp_server *server = NULL; struct { - DHCPMessage message; + struct { + DHCP_MESSAGE_HEADER_DEFINITION; + } _packed_ message; struct { uint8_t code; uint8_t length; diff --git a/src/sbsign/sbsign.c b/src/sbsign/sbsign.c index b2f0d861ce..74e05d4b40 100644 --- a/src/sbsign/sbsign.c +++ b/src/sbsign/sbsign.c @@ -669,18 +669,18 @@ static int verb_sign(int argc, char *argv[], void *userdata) { end += n; } - uint32_t certsz = offsetof(WIN_CERTIFICATE, bCertificate) + sigsz; + uint32_t certsz = sizeof(WIN_CERTIFICATE_HEADER) + sigsz; n = pwrite(dstfd, - &(WIN_CERTIFICATE) { + &(WIN_CERTIFICATE_HEADER) { .wRevision = htole16(0x200), .wCertificateType = htole16(0x0002), /* PKCS7 signedData */ .dwLength = htole32(ROUND_UP(certsz, 8)), }, - sizeof(WIN_CERTIFICATE), + sizeof(WIN_CERTIFICATE_HEADER), end); if (n < 0) return log_error_errno(errno, "Failed to write certificate header: %m"); - if (n != sizeof(WIN_CERTIFICATE)) + if (n != sizeof(WIN_CERTIFICATE_HEADER)) return log_error_errno(SYNTHETIC_ERRNO(EIO), "Short write while writing certificate header."); end += n; diff --git a/src/shared/ethtool-util.c b/src/shared/ethtool-util.c index b29d2641ef..70066b6104 100644 --- a/src/shared/ethtool-util.c +++ b/src/shared/ethtool-util.c @@ -254,9 +254,9 @@ int ethtool_get_link_info( int ethtool_get_permanent_hw_addr(int *ethtool_fd, const char *ifname, struct hw_addr_data *ret) { _cleanup_close_ int fd = -EBADF; - struct { + union { struct ethtool_perm_addr addr; - uint8_t space[HW_ADDR_MAX_SIZE]; + uint8_t buf[offsetof(struct ethtool_perm_addr, data) + HW_ADDR_MAX_SIZE]; } epaddr = { .addr.cmd = ETHTOOL_GPERMADDR, .addr.size = HW_ADDR_MAX_SIZE, @@ -429,15 +429,9 @@ int ethtool_set_nic_buffer_size(int *ethtool_fd, const char *ifname, const netde static int get_stringset(int ethtool_fd, const char *ifname, enum ethtool_stringset stringset_id, struct ethtool_gstrings **ret) { _cleanup_free_ struct ethtool_gstrings *strings = NULL; - struct { - struct ethtool_sset_info info; - uint32_t space; - } buffer = { - .info.cmd = ETHTOOL_GSSET_INFO, - .info.sset_mask = UINT64_C(1) << stringset_id, - }; + uint8_t buffer[offsetof(struct ethtool_sset_info, data) + sizeof(uint32_t)] = {}; struct ifreq ifr = { - .ifr_data = (void*) &buffer, + .ifr_data = (void*) buffer, }; uint32_t len; @@ -445,17 +439,18 @@ static int get_stringset(int ethtool_fd, const char *ifname, enum ethtool_string assert(ifname); assert(ret); + struct ethtool_sset_info *info = (struct ethtool_sset_info*) buffer; + info->cmd = ETHTOOL_GSSET_INFO; + info->sset_mask = UINT64_C(1) << stringset_id; strscpy(ifr.ifr_name, sizeof(ifr.ifr_name), ifname); if (ioctl(ethtool_fd, SIOCETHTOOL, &ifr) < 0) return -errno; - if (buffer.info.sset_mask == 0) + if (info->sset_mask == 0) return -EOPNOTSUPP; - DISABLE_WARNING_ZERO_LENGTH_BOUNDS; - len = buffer.info.data[0]; - REENABLE_WARNING; + len = *info->data; if (len == 0) return -EOPNOTSUPP; @@ -652,15 +647,10 @@ int ethtool_set_features(int *ethtool_fd, const char *ifname, const int features return 0; } -static int get_glinksettings(int fd, struct ifreq *ifr, struct ethtool_link_usettings **ret) { - struct ecmd { - struct ethtool_link_settings req; - uint32_t link_mode_data[3 * ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32]; - } ecmd = { - .req.cmd = ETHTOOL_GLINKSETTINGS, +static int get_glinksettings(int fd, struct ifreq *ifr, union ethtool_link_usettings **ret) { + union ethtool_link_usettings ecmd = { + .base.cmd = ETHTOOL_GLINKSETTINGS, }; - struct ethtool_link_usettings *u; - unsigned offset; assert(fd >= 0); assert(ifr); @@ -674,48 +664,33 @@ static int get_glinksettings(int fd, struct ifreq *ifr, struct ethtool_link_uset https://github.com/torvalds/linux/commit/3f1ac7a700d039c61d8d8b99f28d605d489a60cf */ - ifr->ifr_data = (void *) &ecmd; + ifr->ifr_data = (void*) &ecmd; if (ioctl(fd, SIOCETHTOOL, ifr) < 0) return -errno; - if (ecmd.req.link_mode_masks_nwords >= 0 || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS) + if (ecmd.base.link_mode_masks_nwords >= 0 || ecmd.base.cmd != ETHTOOL_GLINKSETTINGS) return -EOPNOTSUPP; - ecmd.req.link_mode_masks_nwords = -ecmd.req.link_mode_masks_nwords; + ecmd.base.link_mode_masks_nwords = -ecmd.base.link_mode_masks_nwords; ifr->ifr_data = (void *) &ecmd; if (ioctl(fd, SIOCETHTOOL, ifr) < 0) return -errno; - if (ecmd.req.link_mode_masks_nwords <= 0 || ecmd.req.cmd != ETHTOOL_GLINKSETTINGS) + if (ecmd.base.link_mode_masks_nwords <= 0 || ecmd.base.cmd != ETHTOOL_GLINKSETTINGS) return -EOPNOTSUPP; - u = new(struct ethtool_link_usettings, 1); + union ethtool_link_usettings *u = newdup(union ethtool_link_usettings, &ecmd, 1); if (!u) return -ENOMEM; - *u = (struct ethtool_link_usettings) { - .base = ecmd.req, - }; - - offset = 0; - memcpy(u->link_modes.supported, &ecmd.link_mode_data[offset], 4 * ecmd.req.link_mode_masks_nwords); - - offset += ecmd.req.link_mode_masks_nwords; - memcpy(u->link_modes.advertising, &ecmd.link_mode_data[offset], 4 * ecmd.req.link_mode_masks_nwords); - - offset += ecmd.req.link_mode_masks_nwords; - memcpy(u->link_modes.lp_advertising, &ecmd.link_mode_data[offset], 4 * ecmd.req.link_mode_masks_nwords); - *ret = u; - return 0; } -static int get_gset(int fd, struct ifreq *ifr, struct ethtool_link_usettings **ret) { - struct ethtool_link_usettings *e; +static int get_gset(int fd, struct ifreq *ifr, union ethtool_link_usettings **ret) { struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET, }; @@ -729,11 +704,11 @@ static int get_gset(int fd, struct ifreq *ifr, struct ethtool_link_usettings **r if (ioctl(fd, SIOCETHTOOL, ifr) < 0) return -errno; - e = new(struct ethtool_link_usettings, 1); - if (!e) + union ethtool_link_usettings *u = new(union ethtool_link_usettings, 1); + if (!u) return -ENOMEM; - *e = (struct ethtool_link_usettings) { + *u = (union ethtool_link_usettings) { .base.cmd = ETHTOOL_GSET, .base.link_mode_masks_nwords = 1, .base.speed = ethtool_cmd_speed(&ecmd), @@ -744,24 +719,17 @@ static int get_gset(int fd, struct ifreq *ifr, struct ethtool_link_usettings **r .base.mdio_support = ecmd.mdio_support, .base.eth_tp_mdix = ecmd.eth_tp_mdix, .base.eth_tp_mdix_ctrl = ecmd.eth_tp_mdix_ctrl, - - .link_modes.supported[0] = ecmd.supported, - .link_modes.advertising[0] = ecmd.advertising, - .link_modes.lp_advertising[0] = ecmd.lp_advertising, }; - *ret = e; + u->link_modes.supported[0] = ecmd.supported; + u->link_modes.advertising[0] = ecmd.advertising; + u->link_modes.lp_advertising[0] = ecmd.lp_advertising; + *ret = u; return 0; } -static int set_slinksettings(int fd, struct ifreq *ifr, const struct ethtool_link_usettings *u) { - struct { - struct ethtool_link_settings req; - uint32_t link_mode_data[3 * ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32]; - } ecmd = {}; - unsigned offset; - +static int set_slinksettings(int fd, struct ifreq *ifr, const union ethtool_link_usettings *u) { assert(fd >= 0); assert(ifr); assert(u); @@ -769,23 +737,14 @@ static int set_slinksettings(int fd, struct ifreq *ifr, const struct ethtool_lin if (u->base.cmd != ETHTOOL_GLINKSETTINGS || u->base.link_mode_masks_nwords <= 0) return -EINVAL; - ecmd.req = u->base; - ecmd.req.cmd = ETHTOOL_SLINKSETTINGS; - offset = 0; - memcpy(&ecmd.link_mode_data[offset], u->link_modes.supported, 4 * ecmd.req.link_mode_masks_nwords); - - offset += ecmd.req.link_mode_masks_nwords; - memcpy(&ecmd.link_mode_data[offset], u->link_modes.advertising, 4 * ecmd.req.link_mode_masks_nwords); - - offset += ecmd.req.link_mode_masks_nwords; - memcpy(&ecmd.link_mode_data[offset], u->link_modes.lp_advertising, 4 * ecmd.req.link_mode_masks_nwords); - + union ethtool_link_usettings ecmd = *u; + ecmd.base.cmd = ETHTOOL_SLINKSETTINGS; ifr->ifr_data = (void *) &ecmd; return RET_NERRNO(ioctl(fd, SIOCETHTOOL, ifr)); } -static int set_sset(int fd, struct ifreq *ifr, const struct ethtool_link_usettings *u) { +static int set_sset(int fd, struct ifreq *ifr, const union ethtool_link_usettings *u) { struct ethtool_cmd ecmd = { .cmd = ETHTOOL_SSET, }; @@ -826,7 +785,7 @@ int ethtool_set_glinksettings( NetDevPort port, uint8_t mdi) { - _cleanup_free_ struct ethtool_link_usettings *u = NULL; + _cleanup_free_ union ethtool_link_usettings *u = NULL; struct ifreq ifr = {}; bool changed = false; int r; diff --git a/src/shared/ethtool-util.h b/src/shared/ethtool-util.h index 9aa36da227..8f67e6e2b6 100644 --- a/src/shared/ethtool-util.h +++ b/src/shared/ethtool-util.h @@ -107,10 +107,11 @@ typedef enum NetDevPort { #define ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NBYTES (4 * ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32) /* layout of the struct passed from/to userland */ -struct ethtool_link_usettings { +union ethtool_link_usettings { struct ethtool_link_settings base; struct { + uint8_t header[offsetof(struct ethtool_link_settings, link_mode_masks)]; uint32_t supported[ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32]; uint32_t advertising[ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32]; uint32_t lp_advertising[ETHTOOL_LINK_MODE_MASK_MAX_KERNEL_NU32];