diff mbox series

dm ioctl: replace deprecated strncpy with strscpy_pad

Message ID 20230925-strncpy-drivers-md-dm-ioctl-c-v1-1-f0bfa093ef14@google.com (mailing list archive)
State Mainlined
Commit 0ffb645ea821fbad4215b6a5681b823639c24660
Headers show
Series dm ioctl: replace deprecated strncpy with strscpy_pad | expand

Commit Message

Justin Stitt Sept. 25, 2023, 6:54 a.m. UTC
`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 expect `spec->target_type` to be NUL-terminated based on its use with
a format string after `dm_table_add_target()` is called
| 	r = dm_table_add_target(table, spec->target_type,
| 				(sector_t) spec->sector_start,
| 				(sector_t) spec->length,
| 				target_params);
... wherein `spec->target_type` is passed as parameter `type` and later
printed with DMERR:
|       DMERR("%s: %s: unknown target type", dm_device_name(t->md), type);

It appears that `spec` is not zero-allocated and thus NUL-padding may be
required in this ioctl context.

Considering the above, a suitable replacement is `strscpy_pad` due to
the fact that it guarantees NUL-termination whilst 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 only.
---
 drivers/md/dm-ioctl.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)


---
base-commit: 6465e260f48790807eef06b583b38ca9789b6072
change-id: 20230925-strncpy-drivers-md-dm-ioctl-c-ea5c10e77981

Best regards,
--
Justin Stitt <justinstitt@google.com>

Comments

Kees Cook Sept. 25, 2023, 6:19 p.m. UTC | #1
On Mon, Sep 25, 2023 at 06:54:51AM +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 expect `spec->target_type` to be NUL-terminated based on its use with
> a format string after `dm_table_add_target()` is called
> | 	r = dm_table_add_target(table, spec->target_type,
> | 				(sector_t) spec->sector_start,
> | 				(sector_t) spec->length,
> | 				target_params);
> ... wherein `spec->target_type` is passed as parameter `type` and later
> printed with DMERR:
> |       DMERR("%s: %s: unknown target type", dm_device_name(t->md), type);
> 
> It appears that `spec` is not zero-allocated and thus NUL-padding may be
> required in this ioctl context.

Yeah... this one was a bit odd. I see the memory being filled from
userspace in copy_params(), so it's unlikely there was any kernel memory
content leaking, but I think the old code may have been buggy:

		strncpy(spec->target_type, ti->type->name,
			sizeof(spec->target_type) - 1);

I can't find any reason to think that
spec->target_type[sizeof(spec->target_type) - 1] would be %NUL after
this code runs.

get_result_buffer() is basically:
        return ((void *) param) + param->data_start;

then:

        outptr = outbuf = get_result_buffer(param, param_size, &len);
	...
                spec = (struct dm_target_spec *) outptr;

and before that:

        r = copy_params(user, &param_kernel, ioctl_flags, &param, &param_flags);

        if (r)
                return r;

        input_param_size = param->data_size;
        r = validate_params(cmd, param);
        if (r)
                goto out;

        param->data_size = offsetof(struct dm_ioctl, data);
        r = fn(file, param, input_param_size);

Notably validate_params() %NUL-terminates some _other_ strings, but
doesn't clear the param->data area.

So I think this is actually fixing a bug too, but I can't quite tell.

Regardless, the change looks correct:

Reviewed-by: Kees Cook <keescook@chromium.org>

> 
> Considering the above, a suitable replacement is `strscpy_pad` due to
> the fact that it guarantees NUL-termination whilst 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 only.
> ---
>  drivers/md/dm-ioctl.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
> index 21ebb6c39394..e65058e0ed06 100644
> --- a/drivers/md/dm-ioctl.c
> +++ b/drivers/md/dm-ioctl.c
> @@ -1295,8 +1295,8 @@ static void retrieve_status(struct dm_table *table,
>  		spec->status = 0;
>  		spec->sector_start = ti->begin;
>  		spec->length = ti->len;
> -		strncpy(spec->target_type, ti->type->name,
> -			sizeof(spec->target_type) - 1);
> +		strscpy_pad(spec->target_type, ti->type->name,
> +			sizeof(spec->target_type));
>  
>  		outptr += sizeof(struct dm_target_spec);
>  		remaining = len - (outptr - outbuf);
> 
> ---
> base-commit: 6465e260f48790807eef06b583b38ca9789b6072
> change-id: 20230925-strncpy-drivers-md-dm-ioctl-c-ea5c10e77981
> 
> Best regards,
> --
> Justin Stitt <justinstitt@google.com>
> 
>
Kees Cook Oct. 24, 2023, 9:18 p.m. UTC | #2
On Mon, 25 Sep 2023 06:54:51 +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 expect `spec->target_type` to be NUL-terminated based on its use with
> a format string after `dm_table_add_target()` is called
> | 	r = dm_table_add_target(table, spec->target_type,
> | 				(sector_t) spec->sector_start,
> | 				(sector_t) spec->length,
> | 				target_params);
> ... wherein `spec->target_type` is passed as parameter `type` and later
> printed with DMERR:
> |       DMERR("%s: %s: unknown target type", dm_device_name(t->md), type);
> 
> [...]

Applied to for-next/hardening, thanks!

[1/1] dm ioctl: replace deprecated strncpy with strscpy_pad
      https://git.kernel.org/kees/c/0f3f34ea3798

Take care,
diff mbox series

Patch

diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 21ebb6c39394..e65058e0ed06 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1295,8 +1295,8 @@  static void retrieve_status(struct dm_table *table,
 		spec->status = 0;
 		spec->sector_start = ti->begin;
 		spec->length = ti->len;
-		strncpy(spec->target_type, ti->type->name,
-			sizeof(spec->target_type) - 1);
+		strscpy_pad(spec->target_type, ti->type->name,
+			sizeof(spec->target_type));
 
 		outptr += sizeof(struct dm_target_spec);
 		remaining = len - (outptr - outbuf);