get_eeprom_page_reply_cb() memcpy()'s request->length bytes out of the ETHTOOL_A_MODULE_EEPROM_DATA attribute without checking how many bytes the kernel actually put into it. If the reply carries fewer bytes than requested, the copy reads past the end of the message payload. Use mnl_attr_get_payload_len() to learn the real size of the data attribute, like other parsers in the tree (e.g. netlink/rss.c, netlink/fec.c), and clamp request->length to it before allocating and copying the data. Signed-off-by: Prabhakar Pujeri --- netlink/module-eeprom.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/netlink/module-eeprom.c b/netlink/module-eeprom.c index 40882ca..7e2af4e 100644 --- a/netlink/module-eeprom.c +++ b/netlink/module-eeprom.c @@ -133,6 +133,7 @@ static int get_eeprom_page_reply_cb(const struct nlmsghdr *nlhdr, void *data) struct ethtool_module_eeprom *request = data; DECLARE_ATTR_TB_INFO(tb); u8 *eeprom_data; + u32 data_len; int ret; ret = mnl_attr_parse(nlhdr, GENL_HDRLEN, attr_cb, &tb_info); @@ -142,6 +143,13 @@ static int get_eeprom_page_reply_cb(const struct nlmsghdr *nlhdr, void *data) if (!tb[ETHTOOL_A_MODULE_EEPROM_DATA]) return MNL_CB_ERROR; + /* The kernel may return fewer bytes than requested; never read + * beyond the data actually present in the attribute. + */ + data_len = mnl_attr_get_payload_len(tb[ETHTOOL_A_MODULE_EEPROM_DATA]); + if (data_len < request->length) + request->length = data_len; + eeprom_data = mnl_attr_get_payload(tb[ETHTOOL_A_MODULE_EEPROM_DATA]); request->data = malloc(request->length); if (!request->data) -- 2.55.0