All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/2] linux-user: add do_setsockopt SOL_CAN_RAW CAN_RAW_FILTER support
@ 2020-05-06 13:21 Tomas Krcka
  2020-05-06 13:21 ` [PATCH 2/2] linux-user: add do_setsockopt CAN_RAW_FD_FRAMES support Tomas Krcka
  2020-05-12 20:09 ` [PATCH 1/2] linux-user: add do_setsockopt SOL_CAN_RAW CAN_RAW_FILTER support Laurent Vivier
  0 siblings, 2 replies; 6+ messages in thread
From: Tomas Krcka @ 2020-05-06 13:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-trivial, Riku Voipio, Laurent Vivier, Tomas Krcka

Signed-off-by: Tomas Krcka <tomas.krcka@gmail.com>
---
 linux-user/syscall.c | 34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 05f03919ff..88d4c85b70 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -56,6 +56,7 @@
 #include <linux/wireless.h>
 #include <linux/icmp.h>
 #include <linux/icmpv6.h>
+#include <linux/can/raw.h>
 #include <linux/errqueue.h>
 #include <linux/random.h>
 #ifdef CONFIG_TIMERFD
@@ -2111,6 +2112,39 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
             goto unimplemented;
         }
         break;
+    case SOL_CAN_RAW:
+        switch (optname) {
+        case CAN_RAW_FILTER:
+        {
+            if (optlen % sizeof(struct can_filter) != 0) {
+                return -TARGET_EINVAL;
+            }
+
+            struct can_filter  *can_filters = NULL;
+            if (optlen != 0) {
+                can_filters = g_new0(struct can_filter, optlen);
+
+                if (!can_filters) {
+                    return -TARGET_ENOMEM;
+                }
+                if (copy_from_user(can_filters, optval_addr, optlen)) {
+                    g_free(can_filters);
+                    return -TARGET_EFAULT;
+                }
+                for (val = 0; val < optlen / sizeof(struct can_filter); val++) {
+                    can_filters[val].can_id = tswap32(can_filters[val].can_id);
+                    can_filters[val].can_mask = tswap32(can_filters[val].can_mask);
+                }
+            }
+            ret = get_errno(setsockopt(sockfd, level, optname,
+                                        can_filters, optlen));
+            g_free(can_filters);
+            break;
+        }
+        default:
+            goto unimplemented;
+        }
+        break;
     case SOL_RAW:
         switch (optname) {
         case ICMP_FILTER:
-- 
2.17.1



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

* [PATCH 2/2] linux-user: add do_setsockopt CAN_RAW_FD_FRAMES support
  2020-05-06 13:21 [PATCH 1/2] linux-user: add do_setsockopt SOL_CAN_RAW CAN_RAW_FILTER support Tomas Krcka
@ 2020-05-06 13:21 ` Tomas Krcka
  2020-05-12 20:20   ` Laurent Vivier
  2020-05-12 20:09 ` [PATCH 1/2] linux-user: add do_setsockopt SOL_CAN_RAW CAN_RAW_FILTER support Laurent Vivier
  1 sibling, 1 reply; 6+ messages in thread
From: Tomas Krcka @ 2020-05-06 13:21 UTC (permalink / raw)
  To: qemu-devel; +Cc: qemu-trivial, Riku Voipio, Laurent Vivier, Tomas Krcka

Signed-off-by: Tomas Krcka <tomas.krcka@gmail.com>
---
 linux-user/syscall.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/linux-user/syscall.c b/linux-user/syscall.c
index 88d4c85b70..f751ed8b37 100644
--- a/linux-user/syscall.c
+++ b/linux-user/syscall.c
@@ -2141,6 +2141,19 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
             g_free(can_filters);
             break;
         }
+        case CAN_RAW_FD_FRAMES:
+        {
+            val = 0;
+            if (optlen < sizeof(uint32_t)) {
+                return -TARGET_EINVAL;
+            }
+            if (get_user_u32(val, optval_addr)) {
+                return -TARGET_EFAULT;
+            }
+            ret = get_errno(setsockopt(sockfd, level, optname,
+                                    &val, sizeof(val)));
+            break;
+        }
         default:
             goto unimplemented;
         }
-- 
2.17.1



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

* Re: [PATCH 1/2] linux-user: add do_setsockopt SOL_CAN_RAW CAN_RAW_FILTER support
  2020-05-06 13:21 [PATCH 1/2] linux-user: add do_setsockopt SOL_CAN_RAW CAN_RAW_FILTER support Tomas Krcka
  2020-05-06 13:21 ` [PATCH 2/2] linux-user: add do_setsockopt CAN_RAW_FD_FRAMES support Tomas Krcka
@ 2020-05-12 20:09 ` Laurent Vivier
  2020-05-12 21:05   ` Tomas Krcka
  1 sibling, 1 reply; 6+ messages in thread
From: Laurent Vivier @ 2020-05-12 20:09 UTC (permalink / raw)
  To: Tomas Krcka, qemu-devel; +Cc: qemu-trivial, Riku Voipio

Le 06/05/2020 à 15:21, Tomas Krcka a écrit :
> Signed-off-by: Tomas Krcka <tomas.krcka@gmail.com>
> ---
>  linux-user/syscall.c | 34 ++++++++++++++++++++++++++++++++++
>  1 file changed, 34 insertions(+)
> 
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 05f03919ff..88d4c85b70 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -56,6 +56,7 @@
>  #include <linux/wireless.h>
>  #include <linux/icmp.h>
>  #include <linux/icmpv6.h>
> +#include <linux/can/raw.h>
>  #include <linux/errqueue.h>
>  #include <linux/random.h>
>  #ifdef CONFIG_TIMERFD
> @@ -2111,6 +2112,39 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
>              goto unimplemented;
>          }
>          break;
> +    case SOL_CAN_RAW:
> +        switch (optname) {
> +        case CAN_RAW_FILTER:
> +        {
> +            if (optlen % sizeof(struct can_filter) != 0) {
> +                return -TARGET_EINVAL;
> +            }
> +
> +            struct can_filter  *can_filters = NULL;

Move the declaration to the top of the block.

> +            if (optlen != 0) {

If you check, like in kernel, "optlen > CAN_RAW_FILTER_MAX *
sizeof(struct can_filter)", you can exit here (and no need to set
can_filters to NULL).

> +                can_filters = g_new0(struct can_filter, optlen);
> +
> +                if (!can_filters) {

no need to check the result, g_new0() aborts in case of problem.

> +                    return -TARGET_ENOMEM;
> +                }
> +                if (copy_from_user(can_filters, optval_addr, optlen)) {
> +                    g_free(can_filters);
> +                    return -TARGET_EFAULT;
> +                }

It would be cleaner not to use the copy_from_user() as we need to
byte-swap all the fields in the loop below (I know it's done like that
in SOL_ICMPV6...)

> +                for (val = 0; val < optlen / sizeof(struct can_filter); val++) {
> +                    can_filters[val].can_id = tswap32(can_filters[val].can_id);
> +                    can_filters[val].can_mask = tswap32(can_filters[val].can_mask);
> +                }

So, something like:

target_can_filters = lock_user(VERIFY_READ, optval_addr, optlen, 1);
for (val = 0; val < optlen / sizeof(struct can_filter); val++) {
    __get_user(can_filters[val].can_id, \
               &target_can_filters[val].can_id);
    __get_user(can_filters[val].can_mask, \
               &target_can_filters[val].can_mask);
}
unlock_user(target_can_filters);

> +            }
> +            ret = get_errno(setsockopt(sockfd, level, optname,
> +                                        can_filters, optlen));
> +            g_free(can_filters);
> +            break;
> +        }
> +        default:
> +            goto unimplemented;
> +        }
> +        break;
>      case SOL_RAW:
>          switch (optname) {
>          case ICMP_FILTER:
> 

Could you also update getsockopt()?

Thanks,
Laurent




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

* Re: [PATCH 2/2] linux-user: add do_setsockopt CAN_RAW_FD_FRAMES support
  2020-05-06 13:21 ` [PATCH 2/2] linux-user: add do_setsockopt CAN_RAW_FD_FRAMES support Tomas Krcka
@ 2020-05-12 20:20   ` Laurent Vivier
  0 siblings, 0 replies; 6+ messages in thread
From: Laurent Vivier @ 2020-05-12 20:20 UTC (permalink / raw)
  To: Tomas Krcka, qemu-devel; +Cc: qemu-trivial, Riku Voipio

Le 06/05/2020 à 15:21, Tomas Krcka a écrit :
> Signed-off-by: Tomas Krcka <tomas.krcka@gmail.com>
> ---
>  linux-user/syscall.c | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> index 88d4c85b70..f751ed8b37 100644
> --- a/linux-user/syscall.c
> +++ b/linux-user/syscall.c
> @@ -2141,6 +2141,19 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
>              g_free(can_filters);
>              break;
>          }
> +        case CAN_RAW_FD_FRAMES:
> +        {
> +            val = 0;

You don't need to set val to 0.

> +            if (optlen < sizeof(uint32_t)) {

kernel checks for the exact size and fails otherwise.

> +                return -TARGET_EINVAL;
> +            }
> +            if (get_user_u32(val, optval_addr)) {
> +                return -TARGET_EFAULT;
> +            }
> +            ret = get_errno(setsockopt(sockfd, level, optname,
> +                                    &val, sizeof(val)));
> +            break;
> +        }
>          default:
>              goto unimplemented;
>          }
> 

Could you implement getsockopt() too?

Thanks,
Laurent


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

* Re: [PATCH 1/2] linux-user: add do_setsockopt SOL_CAN_RAW CAN_RAW_FILTER support
  2020-05-12 20:09 ` [PATCH 1/2] linux-user: add do_setsockopt SOL_CAN_RAW CAN_RAW_FILTER support Laurent Vivier
@ 2020-05-12 21:05   ` Tomas Krcka
  2020-05-13  8:56     ` Laurent Vivier
  0 siblings, 1 reply; 6+ messages in thread
From: Tomas Krcka @ 2020-05-12 21:05 UTC (permalink / raw)
  To: Laurent Vivier; +Cc: qemu-trivial, Riku Voipio, qemu-devel

Am Di., 12. Mai 2020 um 22:09 Uhr schrieb Laurent Vivier <laurent@vivier.eu>:
>
> Le 06/05/2020 à 15:21, Tomas Krcka a écrit :
> > Signed-off-by: Tomas Krcka <tomas.krcka@gmail.com>
> > ---
> >  linux-user/syscall.c | 34 ++++++++++++++++++++++++++++++++++
> >  1 file changed, 34 insertions(+)
> >
> > diff --git a/linux-user/syscall.c b/linux-user/syscall.c
> > index 05f03919ff..88d4c85b70 100644
> > --- a/linux-user/syscall.c
> > +++ b/linux-user/syscall.c
> > @@ -56,6 +56,7 @@
> >  #include <linux/wireless.h>
> >  #include <linux/icmp.h>
> >  #include <linux/icmpv6.h>
> > +#include <linux/can/raw.h>
> >  #include <linux/errqueue.h>
> >  #include <linux/random.h>
> >  #ifdef CONFIG_TIMERFD
> > @@ -2111,6 +2112,39 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
> >              goto unimplemented;
> >          }
> >          break;
> > +    case SOL_CAN_RAW:
> > +        switch (optname) {
> > +        case CAN_RAW_FILTER:
> > +        {
> > +            if (optlen % sizeof(struct can_filter) != 0) {
> > +                return -TARGET_EINVAL;
> > +            }
> > +
> > +            struct can_filter  *can_filters = NULL;
>
> Move the declaration to the top of the block.
>
> > +            if (optlen != 0) {
>
> If you check, like in kernel, "optlen > CAN_RAW_FILTER_MAX *
> sizeof(struct can_filter)", you can exit here (and no need to set
> can_filters to NULL).
>

The optlen can be 0 and then the can_filter shall be NULL, based on
the socketcan
documentation.
And an additional question, shall I check if optlen is 1 and then use
non-dynamic allocated
filters, as it's done in kernel?

> > +                can_filters = g_new0(struct can_filter, optlen);
> > +
> > +                if (!can_filters) {
>
> no need to check the result, g_new0() aborts in case of problem.
>
> > +                    return -TARGET_ENOMEM;
> > +                }
> > +                if (copy_from_user(can_filters, optval_addr, optlen)) {
> > +                    g_free(can_filters);
> > +                    return -TARGET_EFAULT;
> > +                }
>
> It would be cleaner not to use the copy_from_user() as we need to
> byte-swap all the fields in the loop below (I know it's done like that
> in SOL_ICMPV6...)
>
> > +                for (val = 0; val < optlen / sizeof(struct can_filter); val++) {
> > +                    can_filters[val].can_id = tswap32(can_filters[val].can_id);
> > +                    can_filters[val].can_mask = tswap32(can_filters[val].can_mask);
> > +                }
>
> So, something like:
>
> target_can_filters = lock_user(VERIFY_READ, optval_addr, optlen, 1);
> for (val = 0; val < optlen / sizeof(struct can_filter); val++) {
>     __get_user(can_filters[val].can_id, \
>                &target_can_filters[val].can_id);
>     __get_user(can_filters[val].can_mask, \
>                &target_can_filters[val].can_mask);
> }
> unlock_user(target_can_filters);
>
> > +            }
> > +            ret = get_errno(setsockopt(sockfd, level, optname,
> > +                                        can_filters, optlen));
> > +            g_free(can_filters);
> > +            break;
> > +        }
> > +        default:
> > +            goto unimplemented;
> > +        }
> > +        break;
> >      case SOL_RAW:
> >          switch (optname) {
> >          case ICMP_FILTER:
> >
>
> Could you also update getsockopt()?
Yes, I can.
>
> Thanks,
> Laurent
>
>


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

* Re: [PATCH 1/2] linux-user: add do_setsockopt SOL_CAN_RAW CAN_RAW_FILTER support
  2020-05-12 21:05   ` Tomas Krcka
@ 2020-05-13  8:56     ` Laurent Vivier
  0 siblings, 0 replies; 6+ messages in thread
From: Laurent Vivier @ 2020-05-13  8:56 UTC (permalink / raw)
  To: Tomas Krcka; +Cc: qemu-trivial, Riku Voipio, qemu-devel

Le 12/05/2020 à 23:05, Tomas Krcka a écrit :
> Am Di., 12. Mai 2020 um 22:09 Uhr schrieb Laurent Vivier <laurent@vivier.eu>:
>>
>> Le 06/05/2020 à 15:21, Tomas Krcka a écrit :
>>> Signed-off-by: Tomas Krcka <tomas.krcka@gmail.com>
>>> ---
>>>  linux-user/syscall.c | 34 ++++++++++++++++++++++++++++++++++
>>>  1 file changed, 34 insertions(+)
>>>
>>> diff --git a/linux-user/syscall.c b/linux-user/syscall.c
>>> index 05f03919ff..88d4c85b70 100644
>>> --- a/linux-user/syscall.c
>>> +++ b/linux-user/syscall.c
>>> @@ -56,6 +56,7 @@
>>>  #include <linux/wireless.h>
>>>  #include <linux/icmp.h>
>>>  #include <linux/icmpv6.h>
>>> +#include <linux/can/raw.h>
>>>  #include <linux/errqueue.h>
>>>  #include <linux/random.h>
>>>  #ifdef CONFIG_TIMERFD
>>> @@ -2111,6 +2112,39 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
>>>              goto unimplemented;
>>>          }
>>>          break;
>>> +    case SOL_CAN_RAW:
>>> +        switch (optname) {
>>> +        case CAN_RAW_FILTER:
>>> +        {
>>> +            if (optlen % sizeof(struct can_filter) != 0) {
>>> +                return -TARGET_EINVAL;
>>> +            }
>>> +
>>> +            struct can_filter  *can_filters = NULL;
>>
>> Move the declaration to the top of the block.
>>
>>> +            if (optlen != 0) {
>>
>> If you check, like in kernel, "optlen > CAN_RAW_FILTER_MAX *
>> sizeof(struct can_filter)", you can exit here (and no need to set
>> can_filters to NULL).
>>
> 
> The optlen can be 0 and then the can_filter shall be NULL, based on
> the socketcan
> documentation.

Yes, you're right I misread the kernel code.

But check optlen is lesser than "CAN_RAW_FILTER_MAX * sizeof(struct
can_filter)" to avoir too big g_new0() allocation.

And in fact "g_new0()" is wrong in your code: optlen is the byte size,
not the number of entries. You should use g_malloc0(optlen).

> And an additional question, shall I check if optlen is 1 and then use
> non-dynamic allocated
> filters, as it's done in kernel?

No, keep the code as simple as possible.

Thanks,
Laurent


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

end of thread, other threads:[~2020-05-13  8:57 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-05-06 13:21 [PATCH 1/2] linux-user: add do_setsockopt SOL_CAN_RAW CAN_RAW_FILTER support Tomas Krcka
2020-05-06 13:21 ` [PATCH 2/2] linux-user: add do_setsockopt CAN_RAW_FD_FRAMES support Tomas Krcka
2020-05-12 20:20   ` Laurent Vivier
2020-05-12 20:09 ` [PATCH 1/2] linux-user: add do_setsockopt SOL_CAN_RAW CAN_RAW_FILTER support Laurent Vivier
2020-05-12 21:05   ` Tomas Krcka
2020-05-13  8:56     ` Laurent Vivier

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.