From c9c154b57dc374f454816dd2ad74ce1e277fe788 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Mon, 22 Jan 2024 10:59:32 +0100 Subject: [PATCH 1/3] chore(driver): properly use `strscpy`. Signed-off-by: Federico Di Pierro --- driver/ppm_events.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/driver/ppm_events.c b/driver/ppm_events.c index 451c3c5973..cac7757a04 100644 --- a/driver/ppm_events.c +++ b/driver/ppm_events.c @@ -649,29 +649,33 @@ int val_to_ring(struct event_filler_arguments *args, uint64_t val, uint32_t val_ } else { - len = (int)strlcpy(args->buffer + args->arg_data_offset, + len = (int)strscpy(args->buffer + args->arg_data_offset, (const char *)(unsigned long)val, max_arg_size); - /* WARNING: `strlcpy` returns the length of the string it tries to create - * so `len` could also be greater than `max_arg_size`, but please note that the copied - * charbuf is at max `max_arg_size` (where the last byte is used for the `\0`). - * The copied string is always `\0` terminated but the returned `len` doesn't - * take into consideration the `\0` like `strlen()` function. + /* WARNING: `strscpy` returns the length of the string it creates or -E2BIG in case + * the resulting string would not fit inside the destination string. + * (see https://elixir.bootlin.com/linux/latest/source/lib/string.c#L122 and + * https://lwn.net/Articles/659214/) + * + * The copied string is always null terminated but the returned `len` doesn't + * take account for it. * * Two possible cases here: * * 1. `len < max_arg_size`, the terminator is always there, but `len` doesn't take it into account, - * so we need to increment the `len`. Note that if the source string has exactly `max_arg_size` - * characters the returned `len` is `max_arg_size-1` so we need to do `len++` to obtain the copied size. + * so we need to increment the `len`. * - * 2. `len >= max_arg_size`, the source string is greater than `max_arg_size`. `strlcpy` copied - * `max_arg_size - 1` and added the `\0` at the end, so our final copied `len` is `max_arg_size` we have just - * to resize it and we have done. + * 2. `len == -E2BIG`, the source string is >= than `max_arg_size`. `strscpy` copied + * `max_arg_size - 1` and added the `\0` at the end, so our final copied `len` is `max_arg_size`. */ - if(++len >= max_arg_size) + if (len == -E2BIG) { len = max_arg_size; } + else + { + len++; + } } break; From b0ef7841b47acf680c3cef56e43b8d86e24aefd3 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Mon, 22 Jan 2024 11:03:10 +0100 Subject: [PATCH 2/3] chore(driver): bump API_VERSION patch. Signed-off-by: Federico Di Pierro --- driver/API_VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/driver/API_VERSION b/driver/API_VERSION index cd1d2e94f3..8b22a322d0 100644 --- a/driver/API_VERSION +++ b/driver/API_VERSION @@ -1 +1 @@ -8.0.1 +8.0.2 From 70eee6b1e9634dd30abe75cb186ba6aefea8a1e8 Mon Sep 17 00:00:00 2001 From: Federico Di Pierro Date: Mon, 22 Jan 2024 11:09:38 +0100 Subject: [PATCH 3/3] fix(driver): use strlcpy when `strscpy` was not available. Signed-off-by: Federico Di Pierro --- driver/ppm_events.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/driver/ppm_events.c b/driver/ppm_events.c index cac7757a04..53e78093f2 100644 --- a/driver/ppm_events.c +++ b/driver/ppm_events.c @@ -649,6 +649,8 @@ int val_to_ring(struct event_filler_arguments *args, uint64_t val, uint32_t val_ } else { +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 3, 0) + // strscpy is available since kernel 4.3.0: https://github.com/torvalds/linux/commit/30035e45753b708e7d47a98398500ca005e02b86 len = (int)strscpy(args->buffer + args->arg_data_offset, (const char *)(unsigned long)val, max_arg_size); @@ -676,6 +678,32 @@ int val_to_ring(struct event_filler_arguments *args, uint64_t val, uint32_t val_ { len++; } +#else + // Use old `strlcpy`. + len = (int)strlcpy(args->buffer + args->arg_data_offset, + (const char *)(unsigned long)val, + max_arg_size); + /* WARNING: `strlcpy` returns the length of the string it tries to create + * so `len` could also be greater than `max_arg_size`, but please note that the copied + * charbuf is at max `max_arg_size` (where the last byte is used for the `\0`). + * The copied string is always `\0` terminated but the returned `len` doesn't + * take into consideration the `\0` like `strlen()` function. + * + * Two possible cases here: + * + * 1. `len < max_arg_size`, the terminator is always there, but `len` doesn't take it into account, + * so we need to increment the `len`. Note that if the source string has exactly `max_arg_size` + * characters the returned `len` is `max_arg_size-1` so we need to do `len++` to obtain the copied size. + * + * 2. `len >= max_arg_size`, the source string is greater than `max_arg_size`. `strlcpy` copied + * `max_arg_size - 1` and added the `\0` at the end, so our final copied `len` is `max_arg_size` we have just + * to resize it and we have done. + */ + if(++len >= max_arg_size) + { + len = max_arg_size; + } +#endif } break;