diff mbox series

[XEN,v2] xen/hypercalls: address violations of MISRA C:2012 Rule 8.3

Message ID 7e3abd4c0ef5127a07a60de1bf090a8aefac8e5c.1692717906.git.federico.serafini@bugseng.com (mailing list archive)
State Superseded
Headers show
Series [XEN,v2] xen/hypercalls: address violations of MISRA C:2012 Rule 8.3 | expand

Commit Message

Federico Serafini Aug. 23, 2023, 7:04 a.m. UTC
Make function declarations and definitions consistent to address
violations of MISRA C:2012 Rule 8.3 ("All declarations of an object or
function shall use the same names and type qualifiers").

No functional change.

Signed-off-by: Federico Serafini <federico.serafini@bugseng.com>
---
Changes in v2:
- change compat_grant_table_op() definition instead of the declaration;
- use unsigned int for multicall()'s parameter in accordance with XEN coding
  style.
---
 xen/common/compat/grant_table.c | 22 +++++++++++-----------
 xen/common/multicall.c          |  2 +-
 xen/include/hypercall-defs.c    |  4 ++--
 3 files changed, 14 insertions(+), 14 deletions(-)

Comments

Jan Beulich Aug. 23, 2023, 7:11 a.m. UTC | #1
On 23.08.2023 09:04, Federico Serafini wrote:
> Make function declarations and definitions consistent to address
> violations of MISRA C:2012 Rule 8.3 ("All declarations of an object or
> function shall use the same names and type qualifiers").
> 
> No functional change.
> 
> Signed-off-by: Federico Serafini <federico.serafini@bugseng.com>

Reviewed-by: Jan Beulich <jbeulich@suse.com>
Andrew Cooper Aug. 23, 2023, 7:28 a.m. UTC | #2
On 23/08/2023 8:04 am, Federico Serafini wrote:
> Make function declarations and definitions consistent to address
> violations of MISRA C:2012 Rule 8.3 ("All declarations of an object or
> function shall use the same names and type qualifiers").
>
> No functional change.
>
> Signed-off-by: Federico Serafini <federico.serafini@bugseng.com>
> ---
> Changes in v2:
> - change compat_grant_table_op() definition instead of the declaration;
> - use unsigned int for multicall()'s parameter in accordance with XEN coding
>   style.

Nack.

You were correct in v1, and the request to change it was erroneous.

> diff --git a/xen/include/hypercall-defs.c b/xen/include/hypercall-defs.c
> index 6d361ddfce..d1892fd14f 100644
> --- a/xen/include/hypercall-defs.c
> +++ b/xen/include/hypercall-defs.c
> @@ -135,8 +135,8 @@ xenoprof_op(int op, void *arg)
>  #ifdef CONFIG_COMPAT
>  prefix: compat
>  set_timer_op(uint32_t lo, int32_t hi)
> -multicall(multicall_entry_compat_t *call_list, uint32_t nr_calls)
> -memory_op(unsigned int cmd, void *arg)
> +multicall(multicall_entry_compat_t *call_list, unsigned int nr_calls)

This, unfortunately for many reasons, is an ABI with guests.

It is buggy that the entire file doesn't use unsigned long (i.e. one
full GPR width) to begin with.  It these types alone which cause
explicit truncation of the guest-provided hypercall parameter values.

But it is even more buggy to take something that at least truncates to a
fixed width, and replace it with something that explicitly does not have
a fixed width.

~Andrew
Jan Beulich Aug. 23, 2023, 7:35 a.m. UTC | #3
On 23.08.2023 09:28, Andrew Cooper wrote:
> On 23/08/2023 8:04 am, Federico Serafini wrote:
>> Make function declarations and definitions consistent to address
>> violations of MISRA C:2012 Rule 8.3 ("All declarations of an object or
>> function shall use the same names and type qualifiers").
>>
>> No functional change.
>>
>> Signed-off-by: Federico Serafini <federico.serafini@bugseng.com>
>> ---
>> Changes in v2:
>> - change compat_grant_table_op() definition instead of the declaration;
>> - use unsigned int for multicall()'s parameter in accordance with XEN coding
>>   style.
> 
> Nack.

Oh, I'm sorry, I committed this just before seeing your reply. I'll
revert right away, until we can settle the discussion.

> You were correct in v1, and the request to change it was erroneous.
> 
>> diff --git a/xen/include/hypercall-defs.c b/xen/include/hypercall-defs.c
>> index 6d361ddfce..d1892fd14f 100644
>> --- a/xen/include/hypercall-defs.c
>> +++ b/xen/include/hypercall-defs.c
>> @@ -135,8 +135,8 @@ xenoprof_op(int op, void *arg)
>>  #ifdef CONFIG_COMPAT
>>  prefix: compat
>>  set_timer_op(uint32_t lo, int32_t hi)
>> -multicall(multicall_entry_compat_t *call_list, uint32_t nr_calls)
>> -memory_op(unsigned int cmd, void *arg)
>> +multicall(multicall_entry_compat_t *call_list, unsigned int nr_calls)
> 
> This, unfortunately for many reasons, is an ABI with guests.
> 
> It is buggy that the entire file doesn't use unsigned long (i.e. one
> full GPR width) to begin with.  It these types alone which cause
> explicit truncation of the guest-provided hypercall parameter values.
> 
> But it is even more buggy to take something that at least truncates to a
> fixed width, and replace it with something that explicitly does not have
> a fixed width.

I disagree on all the points you make. Handling compat guests is quite
fine to use unsigned int in hypercall prototypes. Fixed width isn't
needed (just like you don't demand uint64_t, but suggest unsigned long),
and wider than 32 bits (i.e. long) isn't needed either because can't
pass in wider values anyway.

Jan
Stefano Stabellini Aug. 25, 2023, 10:21 p.m. UTC | #4
On Wed, 23 Aug 2023, Jan Beulich wrote:
> On 23.08.2023 09:28, Andrew Cooper wrote:
> > On 23/08/2023 8:04 am, Federico Serafini wrote:
> >> Make function declarations and definitions consistent to address
> >> violations of MISRA C:2012 Rule 8.3 ("All declarations of an object or
> >> function shall use the same names and type qualifiers").
> >>
> >> No functional change.
> >>
> >> Signed-off-by: Federico Serafini <federico.serafini@bugseng.com>
> >> ---
> >> Changes in v2:
> >> - change compat_grant_table_op() definition instead of the declaration;
> >> - use unsigned int for multicall()'s parameter in accordance with XEN coding
> >>   style.
> > 
> > Nack.
> 
> Oh, I'm sorry, I committed this just before seeing your reply. I'll
> revert right away, until we can settle the discussion.
> 
> > You were correct in v1, and the request to change it was erroneous.
> > 
> >> diff --git a/xen/include/hypercall-defs.c b/xen/include/hypercall-defs.c
> >> index 6d361ddfce..d1892fd14f 100644
> >> --- a/xen/include/hypercall-defs.c
> >> +++ b/xen/include/hypercall-defs.c
> >> @@ -135,8 +135,8 @@ xenoprof_op(int op, void *arg)
> >>  #ifdef CONFIG_COMPAT
> >>  prefix: compat
> >>  set_timer_op(uint32_t lo, int32_t hi)
> >> -multicall(multicall_entry_compat_t *call_list, uint32_t nr_calls)
> >> -memory_op(unsigned int cmd, void *arg)
> >> +multicall(multicall_entry_compat_t *call_list, unsigned int nr_calls)
> > 
> > This, unfortunately for many reasons, is an ABI with guests.
> > 
> > It is buggy that the entire file doesn't use unsigned long (i.e. one
> > full GPR width) to begin with.  It these types alone which cause
> > explicit truncation of the guest-provided hypercall parameter values.
> > 
> > But it is even more buggy to take something that at least truncates to a
> > fixed width, and replace it with something that explicitly does not have
> > a fixed width.
> 
> I disagree on all the points you make. Handling compat guests is quite
> fine to use unsigned int in hypercall prototypes. Fixed width isn't
> needed (just like you don't demand uint64_t, but suggest unsigned long),
> and wider than 32 bits (i.e. long) isn't needed either because can't
> pass in wider values anyway.

There are two points that Andrew made:
1) uint32_t should have been register-width (AKA register_t on ARM)
2) unsigned int is worse than uint32_t because is not fixed-width

As a general rule I would say that it is better not to introduce any ABI
changes as part of a clean-up patch for MISRA. (ABI changes could be
done but separately.)

In regard to 1) I don't think it is a good idea to change nr_calls to a
type of different size. Even if it is the right thing to do. If it is,
let's discuss it as a separate patch: you wouldn't want this type of
change to be hidden inside a innocuous MISRA C patch anyway.

In regard to 2), assuming "unsigned int" is exactly equivalent to
uint32_t on all supported arches, then I am in two minds here. Just one
year ago I would have agreed with Andrew and strongly requested an
explicitly-sized type as argument. Then I discovered that all the RISC-V
APIs are based on long, int and similar, and it seems to be working
quite well for them.  See for instance:
https://github.com/riscv-non-isa/riscv-sbi-doc/blob/master/riscv-sbi.pdf

Looking at Xen public headers, we have many instances of unsigned long
and unsigned int in use. So now I think both explicitly-sized and
non-explicitly-sized types can work well as long as we are clear on what
they mean, their sizes on all supported arches, and we use them
consistently. (For sure all of the above could be improved in Xen.)

Coming to unsigned int, it should be 32-bit on all supported arches, so
it is down to consistency, which is a bit arbitrary. We have quite a
good mix of unsigned int and uint32_t in hypercall-defs.c, specifically:
10 uint32_t
32 unsigned int

By popular vote, I would go with unsigned int. So, I would keep the
patch as is.
Jan Beulich Aug. 28, 2023, 6:35 a.m. UTC | #5
On 26.08.2023 00:21, Stefano Stabellini wrote:
> Coming to unsigned int, it should be 32-bit on all supported arches,

But this isn't a requirement, even if we're using "unsigned int" in the
C declarations / definitions: If "unsigned int" was wider, all we'd
demand is that hypercall entry code (likely written in assembly anyway)
zero-extend incoming values suitably to fit whatever "unsigned int" is.
Which is no different to Andrew (aiui) suggesting to use "unsigned
long" instead: That'll too require suitable zero-extension up front.

> so
> it is down to consistency, which is a bit arbitrary. We have quite a
> good mix of unsigned int and uint32_t in hypercall-defs.c, specifically:
> 10 uint32_t
> 32 unsigned int
> 
> By popular vote, I would go with unsigned int. So, I would keep the
> patch as is.

Well, I wouldn't quite say "as is": It clearly wants splitting for the
two entirely unrelated changes. Then the uncontroversial part can go
in right away, while we settle on the controversial aspect.

As to "popular vote" - ./CODING_STYLE also matters here, and favors
non-fixed-width types over fixed-width ones. And as per above imo
there's no technical reason to use fixed-width types here. Yet I
understand Andrew takes a different perspective ...

Jan
Stefano Stabellini Aug. 28, 2023, 9:52 p.m. UTC | #6
On Mon, 28 Aug 2023, Jan Beulich wrote:
> On 26.08.2023 00:21, Stefano Stabellini wrote:
> > Coming to unsigned int, it should be 32-bit on all supported arches,
> 
> But this isn't a requirement, even if we're using "unsigned int" in the
> C declarations / definitions: If "unsigned int" was wider, all we'd
> demand is that hypercall entry code (likely written in assembly anyway)
> zero-extend incoming values suitably to fit whatever "unsigned int" is.
> Which is no different to Andrew (aiui) suggesting to use "unsigned
> long" instead: That'll too require suitable zero-extension up front.

What you wrote assumes that "unsigned int" can only be 32-bit or wider,
such as 64-bit. However, I think that by the C standard there is no
guarantee. For instance, it could be smaller, e.g. 16-bit.

There is also another assumption: if "unsigned int" was indeed 64-bit we
could detect that a guest is 32-bit, assume that a 32-bit guest would
interpret "unsigned int" as 32-bit and only pass 32-bit, and zero-extend
the rest.

I don't think it is a good idea to make unwritten assumption about the
"unsigned int" size of the guest and as you know different OSes can
assign different sizes to the same C type.

This is why I think that in general if we wanted to use non-fixed-width
as part of an ABI we would need to do a better job at writing down all
of these assumptions. Without anything written down, it is easier to use
fixed-width types.

That said, in this case, we have been using "unsigned int" for years and
it is fixed width for all the arches we support, so I think we should
continue to use it for consistency, but ideally also help improve the
documentation to write down all the unwritten assumptions we rely on.


> > so
> > it is down to consistency, which is a bit arbitrary. We have quite a
> > good mix of unsigned int and uint32_t in hypercall-defs.c, specifically:
> > 10 uint32_t
> > 32 unsigned int
> > 
> > By popular vote, I would go with unsigned int. So, I would keep the
> > patch as is.
> 
> Well, I wouldn't quite say "as is": It clearly wants splitting for the
> two entirely unrelated changes. Then the uncontroversial part can go
> in right away, while we settle on the controversial aspect.

OK from me


> As to "popular vote" - ./CODING_STYLE also matters here, and favors
> non-fixed-width types over fixed-width ones. And as per above imo
> there's no technical reason to use fixed-width types here. Yet I
> understand Andrew takes a different perspective ...

I think internal interfaces and public ABIs can have different policies
and I understand the point that a public ABI should use only fixed-width
types. That's not where we are today, but I would understand that
argument.
Jan Beulich Aug. 29, 2023, 6:29 a.m. UTC | #7
On 28.08.2023 23:52, Stefano Stabellini wrote:
> On Mon, 28 Aug 2023, Jan Beulich wrote:
>> On 26.08.2023 00:21, Stefano Stabellini wrote:
>>> Coming to unsigned int, it should be 32-bit on all supported arches,
>>
>> But this isn't a requirement, even if we're using "unsigned int" in the
>> C declarations / definitions: If "unsigned int" was wider, all we'd
>> demand is that hypercall entry code (likely written in assembly anyway)
>> zero-extend incoming values suitably to fit whatever "unsigned int" is.
>> Which is no different to Andrew (aiui) suggesting to use "unsigned
>> long" instead: That'll too require suitable zero-extension up front.
> 
> What you wrote assumes that "unsigned int" can only be 32-bit or wider,
> such as 64-bit. However, I think that by the C standard there is no
> guarantee. For instance, it could be smaller, e.g. 16-bit.

Of course, but in Xen (just like e.g. Linux does) we inherently assume
sizeof(int) >= 4.

Jan
diff mbox series

Patch

diff --git a/xen/common/compat/grant_table.c b/xen/common/compat/grant_table.c
index f8177c84c0..e00bc24a34 100644
--- a/xen/common/compat/grant_table.c
+++ b/xen/common/compat/grant_table.c
@@ -57,7 +57,7 @@  CHECK_gnttab_cache_flush;
 #undef xen_gnttab_cache_flush
 
 int compat_grant_table_op(
-    unsigned int cmd, XEN_GUEST_HANDLE_PARAM(void) cmp_uop, unsigned int count)
+    unsigned int cmd, XEN_GUEST_HANDLE_PARAM(void) uop, unsigned int count)
 {
     int rc = 0;
     unsigned int i, cmd_op;
@@ -71,7 +71,7 @@  int compat_grant_table_op(
     {
 #define CASE(name) \
     case GNTTABOP_##name: \
-        if ( unlikely(!guest_handle_okay(guest_handle_cast(cmp_uop, \
+        if ( unlikely(!guest_handle_okay(guest_handle_cast(uop, \
                                                            gnttab_##name##_compat_t), \
                                          count)) ) \
             rc = -EFAULT; \
@@ -119,7 +119,7 @@  int compat_grant_table_op(
 
 #undef CASE
     default:
-        return do_grant_table_op(cmd, cmp_uop, count);
+        return do_grant_table_op(cmd, uop, count);
     }
 
     if ( (int)count < 0 )
@@ -148,7 +148,7 @@  int compat_grant_table_op(
         case GNTTABOP_setup_table:
             if ( unlikely(count > 1) )
                 rc = -EINVAL;
-            else if ( unlikely(__copy_from_guest(&cmp.setup, cmp_uop, 1)) )
+            else if ( unlikely(__copy_from_guest(&cmp.setup, uop, 1)) )
                 rc = -EFAULT;
             else if ( unlikely(!compat_handle_okay(cmp.setup.frame_list, cmp.setup.nr_frames)) )
                 rc = -EFAULT;
@@ -193,7 +193,7 @@  int compat_grant_table_op(
                 } while (0)
                 XLAT_gnttab_setup_table(&cmp.setup, nat.setup);
 #undef XLAT_gnttab_setup_table_HNDL_frame_list
-                if ( unlikely(__copy_to_guest(cmp_uop, &cmp.setup, 1)) )
+                if ( unlikely(__copy_to_guest(uop, &cmp.setup, 1)) )
                     rc = -EFAULT;
                 else
                     i = 1;
@@ -203,7 +203,7 @@  int compat_grant_table_op(
         case GNTTABOP_transfer:
             for ( n = 0; n < COMPAT_ARG_XLAT_SIZE / sizeof(*nat.xfer) && i < count && rc == 0; ++i, ++n )
             {
-                if ( unlikely(__copy_from_guest_offset(&cmp.xfer, cmp_uop, i, 1)) )
+                if ( unlikely(__copy_from_guest_offset(&cmp.xfer, uop, i, 1)) )
                     rc = -EFAULT;
                 else
                 {
@@ -222,7 +222,7 @@  int compat_grant_table_op(
             {
                 XEN_GUEST_HANDLE_PARAM(gnttab_transfer_compat_t) xfer;
 
-                xfer = guest_handle_cast(cmp_uop, gnttab_transfer_compat_t);
+                xfer = guest_handle_cast(uop, gnttab_transfer_compat_t);
                 guest_handle_add_offset(xfer, i);
                 cnt_uop = guest_handle_cast(xfer, void);
                 while ( n-- )
@@ -237,7 +237,7 @@  int compat_grant_table_op(
         case GNTTABOP_copy:
             for ( n = 0; n < COMPAT_ARG_XLAT_SIZE / sizeof(*nat.copy) && i < count && rc == 0; ++i, ++n )
             {
-                if ( unlikely(__copy_from_guest_offset(&cmp.copy, cmp_uop, i, 1)) )
+                if ( unlikely(__copy_from_guest_offset(&cmp.copy, uop, i, 1)) )
                     rc = -EFAULT;
                 else
                 {
@@ -267,7 +267,7 @@  int compat_grant_table_op(
             {
                 XEN_GUEST_HANDLE_PARAM(gnttab_copy_compat_t) copy;
 
-                copy = guest_handle_cast(cmp_uop, gnttab_copy_compat_t);
+                copy = guest_handle_cast(uop, gnttab_copy_compat_t);
                 guest_handle_add_offset(copy, i);
                 cnt_uop = guest_handle_cast(copy, void);
                 while ( n-- )
@@ -285,7 +285,7 @@  int compat_grant_table_op(
                 rc = -EINVAL;
                 break;
             }
-            if ( unlikely(__copy_from_guest(&cmp.get_status, cmp_uop, 1) ||
+            if ( unlikely(__copy_from_guest(&cmp.get_status, uop, 1) ||
                           !compat_handle_okay(cmp.get_status.frame_list,
                                               cmp.get_status.nr_frames)) )
             {
@@ -303,7 +303,7 @@  int compat_grant_table_op(
             if ( rc >= 0 )
             {
                 XEN_GUEST_HANDLE_PARAM(gnttab_get_status_frames_compat_t) get =
-                    guest_handle_cast(cmp_uop,
+                    guest_handle_cast(uop,
                                       gnttab_get_status_frames_compat_t);
 
                 if ( unlikely(__copy_field_to_guest(get, nat.get_status,
diff --git a/xen/common/multicall.c b/xen/common/multicall.c
index 1f0cc4cb26..5330997144 100644
--- a/xen/common/multicall.c
+++ b/xen/common/multicall.c
@@ -34,7 +34,7 @@  static void trace_multicall_call(multicall_entry_t *call)
 }
 
 ret_t do_multicall(
-    XEN_GUEST_HANDLE_PARAM(multicall_entry_t) call_list, uint32_t nr_calls)
+    XEN_GUEST_HANDLE_PARAM(multicall_entry_t) call_list, unsigned int nr_calls)
 {
     struct vcpu *curr = current;
     struct mc_state *mcs = &curr->mc_state;
diff --git a/xen/include/hypercall-defs.c b/xen/include/hypercall-defs.c
index 6d361ddfce..d1892fd14f 100644
--- a/xen/include/hypercall-defs.c
+++ b/xen/include/hypercall-defs.c
@@ -135,8 +135,8 @@  xenoprof_op(int op, void *arg)
 #ifdef CONFIG_COMPAT
 prefix: compat
 set_timer_op(uint32_t lo, int32_t hi)
-multicall(multicall_entry_compat_t *call_list, uint32_t nr_calls)
-memory_op(unsigned int cmd, void *arg)
+multicall(multicall_entry_compat_t *call_list, unsigned int nr_calls)
+memory_op(unsigned int cmd, void *compat)
 #ifdef CONFIG_IOREQ_SERVER
 dm_op(domid_t domid, unsigned int nr_bufs, void *bufs)
 #endif