linux-renesas-soc.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] drm: property: Replace strncpy() with strscpy_pad()
@ 2021-07-31  1:32 Laurent Pinchart
  2021-08-02  8:24 ` Daniel Vetter
  0 siblings, 1 reply; 2+ messages in thread
From: Laurent Pinchart @ 2021-07-31  1:32 UTC (permalink / raw)
  To: dri-devel
  Cc: linux-renesas-soc, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Kees Cook

strncpy() is widely regarded as unsafe due to the fact that it may leave
the destination string without a nul-termination when the source string
size is too large. When compiling the kernel with W=1, the gcc warns
about this:

drivers/gpu/drm/drm_property.c: In function ‘drm_property_create’:
drivers/gpu/drm/drm_property.c:130:2: warning: ‘strncpy’ specified bound 32 equals destination size [-Wstringop-truncation]
  130 |  strncpy(property->name, name, DRM_PROP_NAME_LEN);
      |  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

There are three occurrences of strncpy() in drm_property.c. None of them
are actually unsafe, as the very next line forces nul-termination of the
destination buffer. The warning is thus a false positive, but adds noise
to the kernel log. It can easily be silenced by using strscpy_pad()
instead. Do so.

One of the three occurrences, in drm_property_add_enum(), fills a char
array that is later copied to userspace with copy_to_user() in
drm_mode_getproperty_ioctl(). To avoid leaking kernel data,
strscpy_pad() is required. Similarly, a second occurrence, in
drm_mode_getproperty_ioctl(), copies the string to an ioctl data buffer
that isn't previously zero'ed, to strscpy_pad() is also required. The
last occurrence, in drm_property_create(), would be safe to replace with
strscpy(), as the destination buffer is copied to userspace with
strscpy_pad(). However, given that this isn't in a hot path, let's avoid
future data leaks in case someone copies the whole char array blindly.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
---
 drivers/gpu/drm/drm_property.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
index 27c824a6eb60..32404891446e 100644
--- a/drivers/gpu/drm/drm_property.c
+++ b/drivers/gpu/drm/drm_property.c
@@ -127,8 +127,7 @@ struct drm_property *drm_property_create(struct drm_device *dev,
 	property->num_values = num_values;
 	INIT_LIST_HEAD(&property->enum_list);
 
-	strncpy(property->name, name, DRM_PROP_NAME_LEN);
-	property->name[DRM_PROP_NAME_LEN-1] = '\0';
+	strscpy_pad(property->name, name, DRM_PROP_NAME_LEN);
 
 	list_add_tail(&property->head, &dev->mode_config.property_list);
 
@@ -421,8 +420,7 @@ int drm_property_add_enum(struct drm_property *property,
 	if (!prop_enum)
 		return -ENOMEM;
 
-	strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
-	prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
+	strscpy_pad(prop_enum->name, name, DRM_PROP_NAME_LEN);
 	prop_enum->value = value;
 
 	property->values[index] = value;
@@ -475,8 +473,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
 	if (!property)
 		return -ENOENT;
 
-	strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
-	out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
+	strscpy_pad(out_resp->name, property->name, DRM_PROP_NAME_LEN);
 	out_resp->flags = property->flags;
 
 	value_count = property->num_values;
-- 
Regards,

Laurent Pinchart


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] drm: property: Replace strncpy() with strscpy_pad()
  2021-07-31  1:32 [PATCH] drm: property: Replace strncpy() with strscpy_pad() Laurent Pinchart
@ 2021-08-02  8:24 ` Daniel Vetter
  0 siblings, 0 replies; 2+ messages in thread
From: Daniel Vetter @ 2021-08-02  8:24 UTC (permalink / raw)
  To: Laurent Pinchart
  Cc: dri-devel, linux-renesas-soc, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, Kees Cook

On Sat, Jul 31, 2021 at 04:32:41AM +0300, Laurent Pinchart wrote:
> strncpy() is widely regarded as unsafe due to the fact that it may leave
> the destination string without a nul-termination when the source string
> size is too large. When compiling the kernel with W=1, the gcc warns
> about this:
> 
> drivers/gpu/drm/drm_property.c: In function ‘drm_property_create’:
> drivers/gpu/drm/drm_property.c:130:2: warning: ‘strncpy’ specified bound 32 equals destination size [-Wstringop-truncation]
>   130 |  strncpy(property->name, name, DRM_PROP_NAME_LEN);
>       |  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
> 
> There are three occurrences of strncpy() in drm_property.c. None of them
> are actually unsafe, as the very next line forces nul-termination of the
> destination buffer. The warning is thus a false positive, but adds noise
> to the kernel log. It can easily be silenced by using strscpy_pad()
> instead. Do so.
> 
> One of the three occurrences, in drm_property_add_enum(), fills a char
> array that is later copied to userspace with copy_to_user() in
> drm_mode_getproperty_ioctl(). To avoid leaking kernel data,
> strscpy_pad() is required. Similarly, a second occurrence, in
> drm_mode_getproperty_ioctl(), copies the string to an ioctl data buffer
> that isn't previously zero'ed, to strscpy_pad() is also required. The
> last occurrence, in drm_property_create(), would be safe to replace with
> strscpy(), as the destination buffer is copied to userspace with
> strscpy_pad(). However, given that this isn't in a hot path, let's avoid
> future data leaks in case someone copies the whole char array blindly.

+1 on just playing it safe.

> Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>

> ---
>  drivers/gpu/drm/drm_property.c | 9 +++------
>  1 file changed, 3 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_property.c b/drivers/gpu/drm/drm_property.c
> index 27c824a6eb60..32404891446e 100644
> --- a/drivers/gpu/drm/drm_property.c
> +++ b/drivers/gpu/drm/drm_property.c
> @@ -127,8 +127,7 @@ struct drm_property *drm_property_create(struct drm_device *dev,
>  	property->num_values = num_values;
>  	INIT_LIST_HEAD(&property->enum_list);
>  
> -	strncpy(property->name, name, DRM_PROP_NAME_LEN);
> -	property->name[DRM_PROP_NAME_LEN-1] = '\0';
> +	strscpy_pad(property->name, name, DRM_PROP_NAME_LEN);
>  
>  	list_add_tail(&property->head, &dev->mode_config.property_list);
>  
> @@ -421,8 +420,7 @@ int drm_property_add_enum(struct drm_property *property,
>  	if (!prop_enum)
>  		return -ENOMEM;
>  
> -	strncpy(prop_enum->name, name, DRM_PROP_NAME_LEN);
> -	prop_enum->name[DRM_PROP_NAME_LEN-1] = '\0';
> +	strscpy_pad(prop_enum->name, name, DRM_PROP_NAME_LEN);
>  	prop_enum->value = value;
>  
>  	property->values[index] = value;
> @@ -475,8 +473,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
>  	if (!property)
>  		return -ENOENT;
>  
> -	strncpy(out_resp->name, property->name, DRM_PROP_NAME_LEN);
> -	out_resp->name[DRM_PROP_NAME_LEN-1] = 0;
> +	strscpy_pad(out_resp->name, property->name, DRM_PROP_NAME_LEN);
>  	out_resp->flags = property->flags;
>  
>  	value_count = property->num_values;
> -- 
> Regards,
> 
> Laurent Pinchart
> 

-- 
Daniel Vetter
Software Engineer, Intel Corporation
http://blog.ffwll.ch

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2021-08-02  8:24 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-31  1:32 [PATCH] drm: property: Replace strncpy() with strscpy_pad() Laurent Pinchart
2021-08-02  8:24 ` Daniel Vetter

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).