Re: [RFC PATCH can-next] can: raw: return -ERANGE when filterset does not fit into user space buffer

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Wed, 2020-12-16 at 18:49 +0100, Oliver Hartkopp wrote:
> Multiple filters (struct can_filter) can be set with the setsockopt()
> function, which was originally intended as a write-only operation.
> 
> As getsockopt() also provides a CAN_RAW_FILTER option to read back
> the
> given filters, the caller has to provide an appropriate user space
> buffer.
> In the case this buffer is too small the getsockopt() silently
> truncates
> the filter information and gives no information about the needed
> space.
> This is safe but not convenient for the programmer.
> 
> In net/core/sock.c the SO_PEERGROUPS sockopt had a similar
> requirement
> and solved it by returning -ERANGE in the case that the provided data
> does not fit into the given user space buffer and fills the required
> size
> into optlen, so that the caller can retry with a matching buffer
> length.
> 
> This patch adopts this approach for CAN_RAW_FILTER getsockopt().
> 
> Reported-by: Phillip Schichtel <phillip@xxxxxxxxxx>
> Signed-off-by: Oliver Hartkopp <socketcan@xxxxxxxxxxxx>

Tested-By: Phillip Schichtel <phillip@xxxxxxxxxx>

Successfully tested this in my Java bindings.

~ Phillip

> ---
>  net/can/raw.c | 16 ++++++++++++----
>  1 file changed, 12 insertions(+), 4 deletions(-)
> 
> diff --git a/net/can/raw.c b/net/can/raw.c
> index 6ec8aa1d0da4..37b47a39a3ed 100644
> --- a/net/can/raw.c
> +++ b/net/can/raw.c
> @@ -663,14 +663,22 @@ static int raw_getsockopt(struct socket *sock,
> int level, int optname,
>         case CAN_RAW_FILTER:
>                 lock_sock(sk);
>                 if (ro->count > 0) {
>                         int fsize = ro->count * sizeof(struct
> can_filter);
>  
> -                       if (len > fsize)
> -                               len = fsize;
> -                       if (copy_to_user(optval, ro->filter, len))
> -                               err = -EFAULT;
> +                       /* user space buffer to small for filter
> list? */
> +                       if (len < fsize) {
> +                               /* return -ERANGE and needed space in
> optlen */
> +                               err = -ERANGE;
> +                               if (put_user(fsize, optlen))
> +                                       err = -EFAULT;
> +                       } else {
> +                               if (len > fsize)
> +                                       len = fsize;
> +                               if (copy_to_user(optval, ro->filter,
> len))
> +                                       err = -EFAULT;
> +                       }
>                 } else {
>                         len = 0;
>                 }
>                 release_sock(sk);
>  





[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux