Message ID | 20230921-strncpy-drivers-infiniband-hw-hfi1-chip-c-v1-1-37afcf4964d9@google.com (mailing list archive) |
---|---|
State | Accepted |
Headers | show |
Series | IB/hfi1: replace deprecated strncpy | expand |
On Thu, 21 Sep 2023 07:17:47 +0000, Justin Stitt wrote: > `strncpy` is deprecated for use on NUL-terminated destination strings > [1] and as such we should prefer more robust and less ambiguous string > interfaces. > > We see that `buf` is expected to be NUL-terminated based on it's use > within a trace event wherein `is_misc_err_name` and `is_various_name` > map to `is_name` through `is_table`: > | TRACE_EVENT(hfi1_interrupt, > | TP_PROTO(struct hfi1_devdata *dd, const struct is_table *is_entry, > | int src), > | TP_ARGS(dd, is_entry, src), > | TP_STRUCT__entry(DD_DEV_ENTRY(dd) > | __array(char, buf, 64) > | __field(int, src) > | ), > | TP_fast_assign(DD_DEV_ASSIGN(dd); > | is_entry->is_name(__entry->buf, 64, > | src - is_entry->start); > | __entry->src = src; > | ), > | TP_printk("[%s] source: %s [%d]", __get_str(dev), __entry->buf, > | __entry->src) > | ); > > [...] Applied, thanks! [1/1] IB/hfi1: replace deprecated strncpy https://git.kernel.org/rdma/rdma/c/c2d0c5b28a77d5 Best regards,
On 9/22/2023 5:29 AM, Leon Romanovsky wrote: > > On Thu, 21 Sep 2023 07:17:47 +0000, Justin Stitt wrote: >> `strncpy` is deprecated for use on NUL-terminated destination strings >> [1] and as such we should prefer more robust and less ambiguous string >> interfaces. >> >> We see that `buf` is expected to be NUL-terminated based on it's use >> within a trace event wherein `is_misc_err_name` and `is_various_name` >> map to `is_name` through `is_table`: >> | TRACE_EVENT(hfi1_interrupt, >> | TP_PROTO(struct hfi1_devdata *dd, const struct is_table *is_entry, >> | int src), >> | TP_ARGS(dd, is_entry, src), >> | TP_STRUCT__entry(DD_DEV_ENTRY(dd) >> | __array(char, buf, 64) >> | __field(int, src) >> | ), >> | TP_fast_assign(DD_DEV_ASSIGN(dd); >> | is_entry->is_name(__entry->buf, 64, >> | src - is_entry->start); >> | __entry->src = src; >> | ), >> | TP_printk("[%s] source: %s [%d]", __get_str(dev), __entry->buf, >> | __entry->src) >> | ); >> >> [...] > > Applied, thanks! It is unfortunate that this and the qib patch was accepted so quickly. The replacement is functionally correct. However, I was going to suggest using strscpy() since the return value is never looked at and all use cases only require a NUL-terminated string. Padding is not needed. > > [1/1] IB/hfi1: replace deprecated strncpy > https://git.kernel.org/rdma/rdma/c/c2d0c5b28a77d5 > > Best regards, External recipient
On Fri, Sep 22, 2023 at 09:25:39AM -0500, Dean Luick wrote: > On 9/22/2023 5:29 AM, Leon Romanovsky wrote: > > > > On Thu, 21 Sep 2023 07:17:47 +0000, Justin Stitt wrote: > >> `strncpy` is deprecated for use on NUL-terminated destination strings > >> [1] and as such we should prefer more robust and less ambiguous string > >> interfaces. > >> > >> We see that `buf` is expected to be NUL-terminated based on it's use > >> within a trace event wherein `is_misc_err_name` and `is_various_name` > >> map to `is_name` through `is_table`: > >> | TRACE_EVENT(hfi1_interrupt, > >> | TP_PROTO(struct hfi1_devdata *dd, const struct is_table *is_entry, > >> | int src), > >> | TP_ARGS(dd, is_entry, src), > >> | TP_STRUCT__entry(DD_DEV_ENTRY(dd) > >> | __array(char, buf, 64) > >> | __field(int, src) > >> | ), > >> | TP_fast_assign(DD_DEV_ASSIGN(dd); > >> | is_entry->is_name(__entry->buf, 64, > >> | src - is_entry->start); > >> | __entry->src = src; > >> | ), > >> | TP_printk("[%s] source: %s [%d]", __get_str(dev), __entry->buf, > >> | __entry->src) > >> | ); > >> > >> [...] > > > > Applied, thanks! > > It is unfortunate that this and the qib patch was accepted so quickly. The replacement is functionally correct. However, I was going to suggest using strscpy() since the return value is never looked at and all use cases only require a NUL-terminated string. Padding is not needed. Is the trace buffer already guaranteed to be zeroed? Since this is defined as a fixed-size string in the buffer, it made sense to me to be sure that the unused bytes were 0 before copying them to userspace. -Kees > > > > > [1/1] IB/hfi1: replace deprecated strncpy > > https://git.kernel.org/rdma/rdma/c/c2d0c5b28a77d5 > > > > Best regards, > > External recipient
On 9/23/2023 10:20 PM, Kees Cook wrote: > On Fri, Sep 22, 2023 at 09:25:39AM -0500, Dean Luick wrote: >> On 9/22/2023 5:29 AM, Leon Romanovsky wrote: >>> >>> On Thu, 21 Sep 2023 07:17:47 +0000, Justin Stitt wrote: >>>> `strncpy` is deprecated for use on NUL-terminated destination strings >>>> [1] and as such we should prefer more robust and less ambiguous string >>>> interfaces. >>>> >>>> We see that `buf` is expected to be NUL-terminated based on it's use >>>> within a trace event wherein `is_misc_err_name` and `is_various_name` >>>> map to `is_name` through `is_table`: >>>> | TRACE_EVENT(hfi1_interrupt, >>>> | TP_PROTO(struct hfi1_devdata *dd, const struct is_table *is_entry, >>>> | int src), >>>> | TP_ARGS(dd, is_entry, src), >>>> | TP_STRUCT__entry(DD_DEV_ENTRY(dd) >>>> | __array(char, buf, 64) >>>> | __field(int, src) >>>> | ), >>>> | TP_fast_assign(DD_DEV_ASSIGN(dd); >>>> | is_entry->is_name(__entry->buf, 64, >>>> | src - is_entry->start); >>>> | __entry->src = src; >>>> | ), >>>> | TP_printk("[%s] source: %s [%d]", __get_str(dev), __entry->buf, >>>> | __entry->src) >>>> | ); >>>> >>>> [...] >>> >>> Applied, thanks! >> >> It is unfortunate that this and the qib patch was accepted so quickly. The replacement is functionally correct. However, I was going to suggest using strscpy() since the return value is never looked at and all use cases only require a NUL-terminated string. Padding is not needed. > > Is the trace buffer already guaranteed to be zeroed? Since this is > defined as a fixed-size string in the buffer, it made sense to me to be > sure that the unused bytes were 0 before copying them to userspace. I was not aware that binary trace records were exposed to user space. If so, and the event records are not zeroed (either the buffer as a whole, or individual records), then strscpy_pad() is the correct solution. My quick review of the tracing system suggests that nothing is zeroed and the record is embedded in a larger structure. However, this begs the question for all users of tracing: Aren't alignment holes in the fast assign record a leak? -Dean > > -Kees > >> >>> >>> [1/1] IB/hfi1: replace deprecated strncpy >>> https://git.kernel.org/rdma/rdma/c/c2d0c5b28a77d5 >>> >>> Best regards, >> >> External recipient > External recipient
On Tue, Sep 26, 2023 at 07:56:34AM -0500, Dean Luick wrote: > On 9/23/2023 10:20 PM, Kees Cook wrote: > > On Fri, Sep 22, 2023 at 09:25:39AM -0500, Dean Luick wrote: > >> On 9/22/2023 5:29 AM, Leon Romanovsky wrote: > >>> > >>> On Thu, 21 Sep 2023 07:17:47 +0000, Justin Stitt wrote: > >>>> `strncpy` is deprecated for use on NUL-terminated destination strings > >>>> [1] and as such we should prefer more robust and less ambiguous string > >>>> interfaces. > >>>> > >>>> We see that `buf` is expected to be NUL-terminated based on it's use > >>>> within a trace event wherein `is_misc_err_name` and `is_various_name` > >>>> map to `is_name` through `is_table`: > >>>> | TRACE_EVENT(hfi1_interrupt, > >>>> | TP_PROTO(struct hfi1_devdata *dd, const struct is_table *is_entry, > >>>> | int src), > >>>> | TP_ARGS(dd, is_entry, src), > >>>> | TP_STRUCT__entry(DD_DEV_ENTRY(dd) > >>>> | __array(char, buf, 64) > >>>> | __field(int, src) > >>>> | ), > >>>> | TP_fast_assign(DD_DEV_ASSIGN(dd); > >>>> | is_entry->is_name(__entry->buf, 64, > >>>> | src - is_entry->start); > >>>> | __entry->src = src; > >>>> | ), > >>>> | TP_printk("[%s] source: %s [%d]", __get_str(dev), __entry->buf, > >>>> | __entry->src) > >>>> | ); > >>>> > >>>> [...] > >>> > >>> Applied, thanks! > >> > >> It is unfortunate that this and the qib patch was accepted so quickly. The replacement is functionally correct. However, I was going to suggest using strscpy() since the return value is never looked at and all use cases only require a NUL-terminated string. Padding is not needed. > > > > Is the trace buffer already guaranteed to be zeroed? Since this is > > defined as a fixed-size string in the buffer, it made sense to me to be > > sure that the unused bytes were 0 before copying them to userspace. > > I was not aware that binary trace records were exposed to user space. If so, and the event records are not zeroed (either the buffer as a whole, or individual records), then strscpy_pad() is the correct solution. My quick review of the tracing system suggests that nothing is zeroed and the record is embedded in a larger structure. However, this begs the question for all users of tracing: Aren't alignment holes in the fast assign record a leak? I thought they were passed over direct to userspace somehow, but I haven't looked at the details in a long time. I could very well be misunderstanding it.
diff --git a/drivers/infiniband/hw/hfi1/chip.c b/drivers/infiniband/hw/hfi1/chip.c index 0814291a0412..7b8e1456284f 100644 --- a/drivers/infiniband/hw/hfi1/chip.c +++ b/drivers/infiniband/hw/hfi1/chip.c @@ -5334,7 +5334,7 @@ static const char * const cce_misc_names[] = { static char *is_misc_err_name(char *buf, size_t bsize, unsigned int source) { if (source < ARRAY_SIZE(cce_misc_names)) - strncpy(buf, cce_misc_names[source], bsize); + strscpy_pad(buf, cce_misc_names[source], bsize); else snprintf(buf, bsize, "Reserved%u", source + IS_GENERAL_ERR_START); @@ -5374,7 +5374,7 @@ static const char * const various_names[] = { static char *is_various_name(char *buf, size_t bsize, unsigned int source) { if (source < ARRAY_SIZE(various_names)) - strncpy(buf, various_names[source], bsize); + strscpy_pad(buf, various_names[source], bsize); else snprintf(buf, bsize, "Reserved%u", source + IS_VARIOUS_START); return buf;
`strncpy` is deprecated for use on NUL-terminated destination strings [1] and as such we should prefer more robust and less ambiguous string interfaces. We see that `buf` is expected to be NUL-terminated based on it's use within a trace event wherein `is_misc_err_name` and `is_various_name` map to `is_name` through `is_table`: | TRACE_EVENT(hfi1_interrupt, | TP_PROTO(struct hfi1_devdata *dd, const struct is_table *is_entry, | int src), | TP_ARGS(dd, is_entry, src), | TP_STRUCT__entry(DD_DEV_ENTRY(dd) | __array(char, buf, 64) | __field(int, src) | ), | TP_fast_assign(DD_DEV_ASSIGN(dd); | is_entry->is_name(__entry->buf, 64, | src - is_entry->start); | __entry->src = src; | ), | TP_printk("[%s] source: %s [%d]", __get_str(dev), __entry->buf, | __entry->src) | ); Considering the above, a suitable replacement is `strscpy_pad` due to the fact that it guarantees NUL-termination on the destination buffer while maintaining the NUL-padding behavior that strncpy provides. Link: https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings [1] Link: https://github.com/KSPP/linux/issues/90 Cc: linux-hardening@vger.kernel.org Signed-off-by: Justin Stitt <justinstitt@google.com> --- Note: build-tested --- drivers/infiniband/hw/hfi1/chip.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) --- base-commit: 2cf0f715623872823a72e451243bbf555d10d032 change-id: 20230921-strncpy-drivers-infiniband-hw-hfi1-chip-c-5b9ea605e6c4 Best regards, -- Justin Stitt <justinstitt@google.com>