linux-can.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH can-next] can: raw: return -ERANGE when filterset does not fit into user space buffer
@ 2020-12-16 17:49 Oliver Hartkopp
  2020-12-17 22:02 ` Phillip Schichtel
  2020-12-18  7:43 ` Marc Kleine-Budde
  0 siblings, 2 replies; 4+ messages in thread
From: Oliver Hartkopp @ 2020-12-16 17:49 UTC (permalink / raw)
  To: linux-can; +Cc: Oliver Hartkopp, Phillip Schichtel

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@schich.tel>
Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
---
 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);
 
-- 
2.29.2


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

* Re: [RFC PATCH can-next] can: raw: return -ERANGE when filterset does not fit into user space buffer
  2020-12-16 17:49 [RFC PATCH can-next] can: raw: return -ERANGE when filterset does not fit into user space buffer Oliver Hartkopp
@ 2020-12-17 22:02 ` Phillip Schichtel
  2020-12-18  7:43 ` Marc Kleine-Budde
  1 sibling, 0 replies; 4+ messages in thread
From: Phillip Schichtel @ 2020-12-17 22:02 UTC (permalink / raw)
  To: Oliver Hartkopp, linux-can

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@schich.tel>
> Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>

Tested-By: Phillip Schichtel <phillip@schich.tel>

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);
>  



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

* Re: [RFC PATCH can-next] can: raw: return -ERANGE when filterset does not fit into user space buffer
  2020-12-16 17:49 [RFC PATCH can-next] can: raw: return -ERANGE when filterset does not fit into user space buffer Oliver Hartkopp
  2020-12-17 22:02 ` Phillip Schichtel
@ 2020-12-18  7:43 ` Marc Kleine-Budde
  2020-12-18 17:52   ` Oliver Hartkopp
  1 sibling, 1 reply; 4+ messages in thread
From: Marc Kleine-Budde @ 2020-12-18  7:43 UTC (permalink / raw)
  To: Oliver Hartkopp, linux-can; +Cc: Phillip Schichtel


[-- Attachment #1.1: Type: text/plain, Size: 1415 bytes --]

On 12/16/20 6:49 PM, 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@schich.tel>
> Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>

Added to linux-can-next/testing. Do we need an update to the in kernel
Documentation?

Marc

-- 
Pengutronix e.K.                 | Marc Kleine-Budde           |
Embedded Linux                   | https://www.pengutronix.de  |
Vertretung West/Dortmund         | Phone: +49-231-2826-924     |
Amtsgericht Hildesheim, HRA 2686 | Fax:   +49-5121-206917-5555 |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

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

* Re: [RFC PATCH can-next] can: raw: return -ERANGE when filterset does not fit into user space buffer
  2020-12-18  7:43 ` Marc Kleine-Budde
@ 2020-12-18 17:52   ` Oliver Hartkopp
  0 siblings, 0 replies; 4+ messages in thread
From: Oliver Hartkopp @ 2020-12-18 17:52 UTC (permalink / raw)
  To: Marc Kleine-Budde, linux-can; +Cc: Phillip Schichtel



On 18.12.20 08:43, Marc Kleine-Budde wrote:
> On 12/16/20 6:49 PM, 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@schich.tel>
>> Signed-off-by: Oliver Hartkopp <socketcan@hartkopp.net>
> 
> Added to linux-can-next/testing. Do we need an update to the in kernel
> Documentation?

Yes. Also thought about it.

Will prepare a patch for the documentation too.

Regards,
Oliver

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

end of thread, other threads:[~2020-12-18 17:56 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-16 17:49 [RFC PATCH can-next] can: raw: return -ERANGE when filterset does not fit into user space buffer Oliver Hartkopp
2020-12-17 22:02 ` Phillip Schichtel
2020-12-18  7:43 ` Marc Kleine-Budde
2020-12-18 17:52   ` Oliver Hartkopp

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).