From f5076c6ba02e8e24c61c40bbf48078929bc0fc79 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 22 Mar 2021 10:44:54 +0100 Subject: can: uapi: can.h: mark union inside struct can_frame packed In commit ea7800565a12 ("can: add optional DLC element to Classical CAN frame structure") the struct can_frame::can_dlc was put into an anonymous union with another u8 variable. For various reasons some members in struct can_frame and canfd_frame including the first 8 byes of data are expected to have the same memory layout. This is enforced by a BUILD_BUG_ON check in af_can.c. Since the above mentioned commit this check fails on ARM kernels compiled with the ARM OABI (which means CONFIG_AEABI not set). In this case -mabi=apcs-gnu is passed to the compiler, which leads to a structure size boundary of 32, instead of 8 compared to CONFIG_AEABI enabled. This means the the union in struct can_frame takes 4 bytes instead of the expected 1. Rong Chen illustrates the problem with pahole in the ARM OABI case: | struct can_frame { | canid_t can_id; /* 0 4 */ | union { | __u8 len; /* 4 1 */ | __u8 can_dlc; /* 4 1 */ | }; /* 4 4 */ | __u8 __pad; /* 8 1 */ | __u8 __res0; /* 9 1 */ | __u8 len8_dlc; /* 10 1 */ | | /* XXX 5 bytes hole, try to pack */ | | __u8 data[8] | __attribute__((__aligned__(8))); /* 16 8 */ | | /* size: 24, cachelines: 1, members: 6 */ | /* sum members: 19, holes: 1, sum holes: 5 */ | /* forced alignments: 1, forced holes: 1, sum forced holes: 5 */ | /* last cacheline: 24 bytes */ | } __attribute__((__aligned__(8))); Marking the anonymous union as __attribute__((packed)) fixes the BUILD_BUG_ON problem on these compilers. Fixes: ea7800565a12 ("can: add optional DLC element to Classical CAN frame structure") Reported-by: kernel test robot Suggested-by: Rong Chen Link: https://lore.kernel.org/linux-can/2c82ec23-3551-61b5-1bd8-178c3407ee83@hartkopp.net/ Link: https://lore.kernel.org/r/20210325125850.1620-3-socketcan@hartkopp.net Signed-off-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- include/uapi/linux/can.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include/uapi/linux') diff --git a/include/uapi/linux/can.h b/include/uapi/linux/can.h index f75238ac6dce..c7535352fef6 100644 --- a/include/uapi/linux/can.h +++ b/include/uapi/linux/can.h @@ -113,7 +113,7 @@ struct can_frame { */ __u8 len; __u8 can_dlc; /* deprecated */ - }; + } __attribute__((packed)); /* disable padding added in some ABIs */ __u8 __pad; /* padding */ __u8 __res0; /* reserved / padding */ __u8 len8_dlc; /* optional DLC for 8 byte payload length (9 .. 15) */ -- cgit v1.2.3 From f0ebc2b6b7df7716749445cda26734b3826a48cf Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 6 Apr 2021 17:28:25 -0700 Subject: ethtool: un-kdocify extended link state Extended link state structures and enums use kdoc headers but then do not describe any of the members. Convert to normal comments. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- include/uapi/linux/ethtool.h | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) (limited to 'include/uapi/linux') diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index cde753bb2093..dc87ba092891 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -579,9 +579,7 @@ struct ethtool_pauseparam { __u32 tx_pause; }; -/** - * enum ethtool_link_ext_state - link extended state - */ +/* Link extended state */ enum ethtool_link_ext_state { ETHTOOL_LINK_EXT_STATE_AUTONEG, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE, @@ -595,10 +593,7 @@ enum ethtool_link_ext_state { ETHTOOL_LINK_EXT_STATE_OVERHEAT, }; -/** - * enum ethtool_link_ext_substate_autoneg - more information in addition to - * ETHTOOL_LINK_EXT_STATE_AUTONEG. - */ +/* More information in addition to ETHTOOL_LINK_EXT_STATE_AUTONEG. */ enum ethtool_link_ext_substate_autoneg { ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED = 1, ETHTOOL_LINK_EXT_SUBSTATE_AN_ACK_NOT_RECEIVED, @@ -608,9 +603,7 @@ enum ethtool_link_ext_substate_autoneg { ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_HCD, }; -/** - * enum ethtool_link_ext_substate_link_training - more information in addition to - * ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE. +/* More information in addition to ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE. */ enum ethtool_link_ext_substate_link_training { ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_FRAME_LOCK_NOT_ACQUIRED = 1, @@ -619,9 +612,7 @@ enum ethtool_link_ext_substate_link_training { ETHTOOL_LINK_EXT_SUBSTATE_LT_REMOTE_FAULT, }; -/** - * enum ethtool_link_ext_substate_logical_mismatch - more information in addition - * to ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH. +/* More information in addition to ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH. */ enum ethtool_link_ext_substate_link_logical_mismatch { ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_BLOCK_LOCK = 1, @@ -631,19 +622,14 @@ enum ethtool_link_ext_substate_link_logical_mismatch { ETHTOOL_LINK_EXT_SUBSTATE_LLM_RS_FEC_IS_NOT_LOCKED, }; -/** - * enum ethtool_link_ext_substate_bad_signal_integrity - more information in - * addition to ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY. +/* More information in addition to ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY. */ enum ethtool_link_ext_substate_bad_signal_integrity { ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS = 1, ETHTOOL_LINK_EXT_SUBSTATE_BSI_UNSUPPORTED_RATE, }; -/** - * enum ethtool_link_ext_substate_cable_issue - more information in - * addition to ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE. - */ +/* More information in addition to ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE. */ enum ethtool_link_ext_substate_cable_issue { ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE = 1, ETHTOOL_LINK_EXT_SUBSTATE_CI_CABLE_TEST_FAILURE, -- cgit v1.2.3 From 83e5feeb385e6d69ae95dd30e0c424afaa17cc6b Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 6 Apr 2021 17:28:26 -0700 Subject: ethtool: document reserved fields in the uAPI Add a note on expected handling of reserved fields, and references to all kdocs. This fixes a bunch of kdoc warnings. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- include/uapi/linux/ethtool.h | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'include/uapi/linux') diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index dc87ba092891..c9c18e88c215 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -26,6 +26,14 @@ * have the same layout for 32-bit and 64-bit userland. */ +/* Note on reserved space. + * Reserved fields must not be accessed directly by user space because + * they may be replaced by a different field in the future. They must + * be initialized to zero before making the request, e.g. via memset + * of the entire structure or implicitly by not being set in a structure + * initializer. + */ + /** * struct ethtool_cmd - DEPRECATED, link control and status * This structure is DEPRECATED, please use struct ethtool_link_settings. @@ -67,6 +75,7 @@ * and other link features that the link partner advertised * through autonegotiation; 0 if unknown or not applicable. * Read-only. + * @reserved: Reserved for future use; see the note on reserved space. * * The link speed in Mbps is split between @speed and @speed_hi. Use * the ethtool_cmd_speed() and ethtool_cmd_speed_set() functions to @@ -155,6 +164,7 @@ static inline __u32 ethtool_cmd_speed(const struct ethtool_cmd *ep) * @bus_info: Device bus address. This should match the dev_name() * string for the underlying bus device, if there is one. May be * an empty string. + * @reserved2: Reserved for future use; see the note on reserved space. * @n_priv_flags: Number of flags valid for %ETHTOOL_GPFLAGS and * %ETHTOOL_SPFLAGS commands; also the number of strings in the * %ETH_SS_PRIV_FLAGS set @@ -356,6 +366,7 @@ struct ethtool_eeprom { * @tx_lpi_timer: Time in microseconds the interface delays prior to asserting * its tx lpi (after reaching 'idle' state). Effective only when eee * was negotiated and tx_lpi_enabled was set. + * @reserved: Reserved for future use; see the note on reserved space. */ struct ethtool_eee { __u32 cmd; @@ -374,6 +385,7 @@ struct ethtool_eee { * @cmd: %ETHTOOL_GMODULEINFO * @type: Standard the module information conforms to %ETH_MODULE_SFF_xxxx * @eeprom_len: Length of the eeprom + * @reserved: Reserved for future use; see the note on reserved space. * * This structure is used to return the information to * properly size memory for a subsequent call to %ETHTOOL_GMODULEEEPROM. @@ -701,6 +713,7 @@ struct ethtool_gstrings { /** * struct ethtool_sset_info - string set information * @cmd: Command number = %ETHTOOL_GSSET_INFO + * @reserved: Reserved for future use; see the note on reserved space. * @sset_mask: On entry, a bitmask of string sets to query, with bits * numbered according to &enum ethtool_stringset. On return, a * bitmask of those string sets queried that are supported. @@ -745,6 +758,7 @@ enum ethtool_test_flags { * @flags: A bitmask of flags from &enum ethtool_test_flags. Some * flags may be set by the user on entry; others may be set by * the driver on return. + * @reserved: Reserved for future use; see the note on reserved space. * @len: On return, the number of test results * @data: Array of test results * @@ -945,6 +959,7 @@ union ethtool_flow_union { * @vlan_etype: VLAN EtherType * @vlan_tci: VLAN tag control information * @data: user defined data + * @padding: Reserved for future use; see the note on reserved space. * * Note, @vlan_etype, @vlan_tci, and @data are only valid if %FLOW_EXT * is set in &struct ethtool_rx_flow_spec @flow_type. @@ -1120,7 +1135,8 @@ struct ethtool_rxfh_indir { * hardware hash key. * @hfunc: Defines the current RSS hash function used by HW (or to be set to). * Valid values are one of the %ETH_RSS_HASH_*. - * @rsvd: Reserved for future extensions. + * @rsvd8: Reserved for future use; see the note on reserved space. + * @rsvd32: Reserved for future use; see the note on reserved space. * @rss_config: RX ring/queue index for each hash value i.e., indirection table * of @indir_size __u32 elements, followed by hash key of @key_size * bytes. @@ -1288,7 +1304,9 @@ struct ethtool_sfeatures { * @so_timestamping: bit mask of the sum of the supported SO_TIMESTAMPING flags * @phc_index: device index of the associated PHC, or -1 if there is none * @tx_types: bit mask of the supported hwtstamp_tx_types enumeration values + * @tx_reserved: Reserved for future use; see the note on reserved space. * @rx_filters: bit mask of the supported hwtstamp_rx_filters enumeration values + * @rx_reserved: Reserved for future use; see the note on reserved space. * * The bits in the 'tx_types' and 'rx_filters' fields correspond to * the 'hwtstamp_tx_types' and 'hwtstamp_rx_filters' enumeration values, @@ -1944,6 +1962,8 @@ enum ethtool_reset_flags { * autonegotiation; 0 if unknown or not applicable. Read-only. * @transceiver: Used to distinguish different possible PHY types, * reported consistently by PHYLIB. Read-only. + * @reserved: Reserved for future use; see the note on reserved space. + * @reserved1: Reserved for future use; see the note on reserved space. * * If autonegotiation is disabled, the speed and @duplex represent the * fixed link mode and are writable if the driver supports multiple -- cgit v1.2.3 From d9c65de0c1e1574d2cc8007dbe02291fe47db1d9 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 6 Apr 2021 17:28:27 -0700 Subject: ethtool: fix kdoc in headers Fix remaining issues with kdoc in the ethtool headers. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- include/uapi/linux/ethtool.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/uapi/linux') diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index c9c18e88c215..5afea692a3f7 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -659,6 +659,7 @@ enum ethtool_link_ext_substate_cable_issue { * now deprecated * @ETH_SS_FEATURES: Device feature names * @ETH_SS_RSS_HASH_FUNCS: RSS hush function names + * @ETH_SS_TUNABLES: tunable names * @ETH_SS_PHY_STATS: Statistic names, for use with %ETHTOOL_GPHYSTATS * @ETH_SS_PHY_TUNABLES: PHY tunable names * @ETH_SS_LINK_MODES: link mode names @@ -668,6 +669,8 @@ enum ethtool_link_ext_substate_cable_issue { * @ETH_SS_TS_TX_TYPES: timestamping Tx types * @ETH_SS_TS_RX_FILTERS: timestamping Rx filters * @ETH_SS_UDP_TUNNEL_TYPES: UDP tunnel types + * + * @ETH_SS_COUNT: number of defined string sets */ enum ethtool_stringset { ETH_SS_TEST = 0, @@ -1962,8 +1965,11 @@ enum ethtool_reset_flags { * autonegotiation; 0 if unknown or not applicable. Read-only. * @transceiver: Used to distinguish different possible PHY types, * reported consistently by PHYLIB. Read-only. + * @master_slave_cfg: Master/slave port mode. + * @master_slave_state: Master/slave port state. * @reserved: Reserved for future use; see the note on reserved space. * @reserved1: Reserved for future use; see the note on reserved space. + * @link_mode_masks: Variable length bitmaps. * * If autonegotiation is disabled, the speed and @duplex represent the * fixed link mode and are writable if the driver supports multiple -- cgit v1.2.3 From 71826654ce40112f0651b6f4e94c422354f4adb6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 19 Mar 2021 23:25:11 +0100 Subject: rfkill: revert back to old userspace API by default Recompiling with the new extended version of struct rfkill_event broke systemd in *two* ways: - It used "sizeof(struct rfkill_event)" to read the event, but then complained if it actually got something != 8, this broke it on new kernels (that include the updated API); - It used sizeof(struct rfkill_event) to write a command, but didn't implement the intended expansion protocol where the kernel returns only how many bytes it accepted, and errored out due to the unexpected smaller size on kernels that didn't include the updated API. Even though systemd has now been fixed, that fix may not be always deployed, and other applications could potentially have similar issues. As such, in the interest of avoiding regressions, revert the default API "struct rfkill_event" back to the original size. Instead, add a new "struct rfkill_event_ext" that extends it by the new field, and even more clearly document that applications should be prepared for extensions in two ways: * write might only accept fewer bytes on older kernels, and will return how many to let userspace know which data may have been ignored; * read might return anything between 8 (the original size) and whatever size the application sized its buffer at, indicating how much event data was supported by the kernel. Perhaps that will help avoid such issues in the future and we won't have to come up with another version of the struct if we ever need to extend it again. Applications that want to take advantage of the new field will have to be modified to use struct rfkill_event_ext instead now, which comes with the danger of them having already been updated to use it from 'struct rfkill_event', but I found no evidence of that, and it's still relatively new. Cc: stable@vger.kernel.org # 5.11 Reported-by: Takashi Iwai Tested-by: Sedat Dilek # LLVM/Clang v12.0.0-r4 (x86-64) Link: https://lore.kernel.org/r/20210319232510.f1a139cfdd9c.Ic5c7c9d1d28972059e132ea653a21a427c326678@changeid Signed-off-by: Johannes Berg --- include/uapi/linux/rfkill.h | 80 ++++++++++++++++++++++++++++++++++++++------- 1 file changed, 68 insertions(+), 12 deletions(-) (limited to 'include/uapi/linux') diff --git a/include/uapi/linux/rfkill.h b/include/uapi/linux/rfkill.h index 03e8af87b364..9b77cfc42efa 100644 --- a/include/uapi/linux/rfkill.h +++ b/include/uapi/linux/rfkill.h @@ -86,34 +86,90 @@ enum rfkill_hard_block_reasons { * @op: operation code * @hard: hard state (0/1) * @soft: soft state (0/1) + * + * Structure used for userspace communication on /dev/rfkill, + * used for events from the kernel and control to the kernel. + */ +struct rfkill_event { + __u32 idx; + __u8 type; + __u8 op; + __u8 soft; + __u8 hard; +} __attribute__((packed)); + +/** + * struct rfkill_event_ext - events for userspace on /dev/rfkill + * @idx: index of dev rfkill + * @type: type of the rfkill struct + * @op: operation code + * @hard: hard state (0/1) + * @soft: soft state (0/1) * @hard_block_reasons: valid if hard is set. One or several reasons from * &enum rfkill_hard_block_reasons. * * Structure used for userspace communication on /dev/rfkill, * used for events from the kernel and control to the kernel. + * + * See the extensibility docs below. */ -struct rfkill_event { +struct rfkill_event_ext { __u32 idx; __u8 type; __u8 op; __u8 soft; __u8 hard; + + /* + * older kernels will accept/send only up to this point, + * and if extended further up to any chunk marked below + */ + __u8 hard_block_reasons; } __attribute__((packed)); -/* - * We are planning to be backward and forward compatible with changes - * to the event struct, by adding new, optional, members at the end. - * When reading an event (whether the kernel from userspace or vice - * versa) we need to accept anything that's at least as large as the - * version 1 event size, but might be able to accept other sizes in - * the future. +/** + * DOC: Extensibility + * + * Originally, we had planned to allow backward and forward compatible + * changes by just adding fields at the end of the structure that are + * then not reported on older kernels on read(), and not written to by + * older kernels on write(), with the kernel reporting the size it did + * accept as the result. + * + * This would have allowed userspace to detect on read() and write() + * which kernel structure version it was dealing with, and if was just + * recompiled it would have gotten the new fields, but obviously not + * accessed them, but things should've continued to work. + * + * Unfortunately, while actually exercising this mechanism to add the + * hard block reasons field, we found that userspace (notably systemd) + * did all kinds of fun things not in line with this scheme: + * + * 1. treat the (expected) short writes as an error; + * 2. ask to read sizeof(struct rfkill_event) but then compare the + * actual return value to RFKILL_EVENT_SIZE_V1 and treat any + * mismatch as an error. + * + * As a consequence, just recompiling with a new struct version caused + * things to no longer work correctly on old and new kernels. + * + * Hence, we've rolled back &struct rfkill_event to the original version + * and added &struct rfkill_event_ext. This effectively reverts to the + * old behaviour for all userspace, unless it explicitly opts in to the + * rules outlined here by using the new &struct rfkill_event_ext. + * + * Userspace using &struct rfkill_event_ext must adhere to the following + * rules * - * One exception is the kernel -- we already have two event sizes in - * that we've made the 'hard' member optional since our only option - * is to ignore it anyway. + * 1. accept short writes, optionally using them to detect that it's + * running on an older kernel; + * 2. accept short reads, knowing that this means it's running on an + * older kernel; + * 3. treat reads that are as long as requested as acceptable, not + * checking against RFKILL_EVENT_SIZE_V1 or such. */ -#define RFKILL_EVENT_SIZE_V1 8 +#define RFKILL_EVENT_SIZE_V1 sizeof(struct rfkill_event) /* ioctl for turning off rfkill-input (if present) */ #define RFKILL_IOC_MAGIC 'R' -- cgit v1.2.3