From: Lee Trager Date: Fri, 28 Feb 2025 19:15:27 +0000 (-0800) Subject: eth: fbnic: Update fbnic_tlv_attr_get_string() to work like nla_strscpy() X-Git-Tag: io_uring-6.15-20250403~82^2~179^2~1 X-Git-Url: https://git.kernel.dk/?a=commitdiff_plain;h=e5cf5107c9e4286377d9adae114e524787cbe104;p=linux-block.git eth: fbnic: Update fbnic_tlv_attr_get_string() to work like nla_strscpy() Allow fbnic_tlv_attr_get_string() to return an error code. In the event the source mailbox attribute is missing return -EINVAL. Like nla_strscpy() return -E2BIG when the source string is larger than the destination string. In this case the amount of data copied is equal to dstsize. Signed-off-by: Lee Trager Link: https://patch.msgid.link/20250228191935.3953712-3-lee@trager.us Signed-off-by: Jakub Kicinski --- diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_tlv.c b/drivers/net/ethernet/meta/fbnic/fbnic_tlv.c index 2a174ab062a3..400fb6c80053 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_tlv.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_tlv.c @@ -233,19 +233,40 @@ s64 fbnic_tlv_attr_get_signed(struct fbnic_tlv_msg *attr) /** * fbnic_tlv_attr_get_string - Retrieve string value from result * @attr: Attribute to retrieve data from - * @str: Pointer to an allocated string to store the data - * @max_size: The maximum size which can be in str + * @dst: Pointer to an allocated string to store the data + * @dstsize: The maximum size which can be in dst * - * Return: the size of the string read from firmware + * Return: the size of the string read from firmware or negative error. **/ -size_t fbnic_tlv_attr_get_string(struct fbnic_tlv_msg *attr, char *str, - size_t max_size) +ssize_t fbnic_tlv_attr_get_string(struct fbnic_tlv_msg *attr, char *dst, + size_t dstsize) { - max_size = min_t(size_t, max_size, - (le16_to_cpu(attr->hdr.len) * 4) - sizeof(*attr)); - memcpy(str, &attr->value, max_size); + size_t srclen, len; + ssize_t ret; - return max_size; + if (!attr) + return -EINVAL; + + if (dstsize == 0) + return -E2BIG; + + srclen = le16_to_cpu(attr->hdr.len) - sizeof(*attr); + if (srclen > 0 && attr->value[srclen - 1] == '\0') + srclen--; + + if (srclen >= dstsize) { + len = dstsize - 1; + ret = -E2BIG; + } else { + len = srclen; + ret = len; + } + + memcpy(dst, &attr->value, len); + /* Zero pad end of dst. */ + memset(dst + len, 0, dstsize - len); + + return ret; } /** diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_tlv.h b/drivers/net/ethernet/meta/fbnic/fbnic_tlv.h index 67300ab44353..b29ed2649585 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_tlv.h +++ b/drivers/net/ethernet/meta/fbnic/fbnic_tlv.h @@ -116,8 +116,8 @@ static inline bool fbnic_tlv_attr_get_bool(struct fbnic_tlv_msg *attr) u64 fbnic_tlv_attr_get_unsigned(struct fbnic_tlv_msg *attr); s64 fbnic_tlv_attr_get_signed(struct fbnic_tlv_msg *attr); -size_t fbnic_tlv_attr_get_string(struct fbnic_tlv_msg *attr, char *str, - size_t max_size); +ssize_t fbnic_tlv_attr_get_string(struct fbnic_tlv_msg *attr, char *dst, + size_t dstsize); #define get_unsigned_result(id, location) \ do { \