Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gcc 11 cleanup #12237

Merged
merged 1 commit into from
Jun 23, 2021
Merged

gcc 11 cleanup #12237

merged 1 commit into from
Jun 23, 2021

Conversation

AttilaFueloep
Copy link
Contributor

Motivation and Context

Building with gcc 11.1.0 fails due to warnings.

Description

Disable false positive warnings, fix a wrong prototype.

Closes #12130
Closes #12188

How Has This Been Tested?

Just a local build.

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Performance enhancement (non-breaking change which improves efficiency)
  • Code cleanup (non-breaking change which makes code smaller or more readable)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Library ABI change (libzfs, libzfs_core, libnvpair, libuutil and libzfsbootenv)
  • Documentation (a change to man pages or other documentation)

Checklist:

@AttilaFueloep
Copy link
Contributor Author

Not sure if the #pragma approach is acceptable, if not please advice.

@felixdoerre Shouldn't we check the return value of mlock() in contrib/pam_zfs_key/pam_zfs_key.c?

@felixdoerre
Copy link
Contributor

Yes, probably we should treat a failure in mlock like an allocation failure and just free pw->value and pw and return NULL.

@AttilaFueloep
Copy link
Contributor Author

A bit more detail.

Not sure where the warning in contrib/pam_zfs_key/pam_zfs_key.c is comming from, the code indicates that pw can't be used uninitialized. Neither casting the return value to (void) nor casting the first argument of mlock() to (const void *) got rid of the warning.

pam_zfs_key.c: In function ‘alloc_pw_string’:
pam_zfs_key.c:107:16: error: ‘<unknown>’ may be used uninitialized [-Werror=maybe-uninitialized]
  107 |         (mlock(pw->value, pw->len);
      |                ^~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../include/sys/zfs_context.h:106,
                 from ../../include/sys/dmu.h:45,
                 from ../../include/sys/dmu_tx.h:33,
                 from ../../include/sys/dsl_crypt.h:23,
                 from pam_zfs_key.c:28:
/usr/include/sys/mman.h:103:12: note: by argument 1 of type ‘const void *’ to ‘mlock’ declared here
  103 | extern int mlock (const void *__addr, size_t __len) __THROW;
      |            ^~~~~

The extern declaration in include/sys/crypto/api.h does not match the definition in module/icp/api/kcf_misc_api.c

../../module/icp/api/kcf_miscapi.c:65:22: error: argument 1 of type ‘char *’ declared as a pointer [-Werror=array-parameter=]
   65 | crypto_mech2id(char *mechname)
      |                ~~~~~~^~~~~~~~
In file included from ../../module/icp/api/kcf_miscapi.c:28:
../../include/sys/crypto/api.h:61:61: note: previously declared as an array ‘char[32]’
   61 | extern crypto_mech_type_t crypto_mech2id(crypto_mech_name_t name);
      |                                          ~~~~~~~~~~~~~~~~~~~^~~~

The warnings in module/os/linux/zfs/zio_crypt.c stem from the fact that we truncated the dnode to 64 bytes to get rid of the non-portable union at the end. Since we don't access the union it's a false positive.

../../module/os/linux/zfs/zio_crypt.c:1060:54: error: array subscript ‘dnode_phys_t {aka struct dnode_phys}[0]’ is partly outside array bounds of ‘uint8_t[64]’ {aka ‘unsigned char[64]’} [-Werror=array-bounds]
 1060 |                 adnp->dn_datablkszsec = BSWAP_16(adnp->dn_datablkszsec);
      |                                                      ^~
...

@AttilaFueloep
Copy link
Contributor Author

@felixdoerre All right, will open a PR once this is merged.

@dioni21
Copy link
Contributor

dioni21 commented Jun 14, 2021

Aren't we just hiding the real problems with the above patch? I can also compile if I simply disable the -Werror option, but the warning may have something important to say.

In particular, I do not like the idea of using a generic char * when we have a better restrained type crypto_mech_name_t

@dioni21
Copy link
Contributor

dioni21 commented Jun 14, 2021

BTW: You do not have to make another PR, just add new commits (even forced ones) to the same branch (AttilaFueloep:zfs-icp-gcc11).

@AttilaFueloep
Copy link
Contributor Author

@dioni21

Aren't we just hiding the real problems with the above patch?

/*
* crypto_mech2id()
*
* Arguments:
* . mechname: A null-terminated string identifying the mechanism name.
*

So a char * is adequate. It is cast to a void * later on anyhow.

BTW: You do not have to make another PR

PRs should be limited to fixing distinct problems.

@behlendorf
Copy link
Contributor

Not sure if the #pragma approach is acceptable, if not please advice.

As a general rule we have tried to avoid using #pragma GCC diagnostic and have only fallen back to it as a last resort (which was needed in a few cases).

I briefly looked at the alloc_pw_string() function and I'm not sure why gcc is claiming it can be used uninitialized. That doesn't look possible to me, perhaps the code could be changed slightly so it gets the analysis right.

@AttilaFueloep
Copy link
Contributor Author

Given the weird location of the arrow (^~~~) at mlock and the error: ‘<unknown>’ text, I've the impression that something else is going on. I'll try to shuffle the code a bit, let's see if it helps. That leaves the truncated dnode problem, not sure what to change there to get gcc happy.

@AttilaFueloep
Copy link
Contributor Author

That leaves the truncated dnode problem,

Well, I could introduce a new struct, say dnode_trunc and cast the array to that. Not sure if this is worthwhile though.

@AttilaFueloep
Copy link
Contributor Author

Managed to get rid of the #pragmas. Reshuffling the code in pam_zfs_key.c didn't help, I ended up zeroing pw->value before calling mlock() on it. I think this shouldn't be too bad.

@AttilaFueloep AttilaFueloep changed the title Fix gcc 11 false positive diagnostic warnings gcc 11 cleanup Jun 14, 2021
@dioni21
Copy link
Contributor

dioni21 commented Jun 15, 2021

Reshuffling the code in pam_zfs_key.c didn't help, I ended up zeroing pw->value before calling mlock() on it. I think this shouldn't be too bad.

Not bad, but hurts my brain optimizer. :-)

Did you try a cast to (const void *) when calling mlock?

Or, at least, use calloc instead of malloc + memset.

And in extern crypto_mech_type_t crypto_mech2id(char *name); I would also use const char *

Anyway, this may be just me doing yet another bikeshedding. :-(

Thanks for your work, @AttilaFueloep !

@AttilaFueloep
Copy link
Contributor Author

@dioni21

Did you try a cast to (const void *) when calling mlock?

Yep.

Or, at least, use calloc instead of malloc + memset.

Yeah, good idea.

And in extern crypto_mech_type_t crypto_mech2id(char *name); I would also use const char *

While I generally agree, this would involve refactoring the whole call chain, which I think is outside the scope of this PR.

Comment on lines 273 to 275
* This structure holds only the portable fields of a dnode_phys_t, i.e.
* all fields but excluding the variable sized tail region. It is used to
* calculate the HMAC of a dnode_phys_t in zio_crypt_do_dnode_hmac_updates().
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems a little unfortunate to have to duplicate this. Could we embed it in the dnode_phys_t instead? Though I guess since it's on-disk it won't be changing very often.

Copy link
Contributor Author

@AttilaFueloep AttilaFueloep Jun 17, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that was my concern and reasoning as well. I do type embedding frequently in Go but I failed to figure how to do it in C without requiring Microsoft extensions (gcc/clang -fms-extensions flag). Even in C11 you can't have an anonymous struct member of a previously defined type. Am I missing something obvious here? Or are you thinking of doing some #define ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the cleanest way is to do something like

struct dnode_phys {
    dnode_phys_core_t dn_core;
    union {
        ...
   }
}

The downside is that you have to change all the code that's accessing it to add .dn_core :( . (And the "solution" to that of doing #define dn_type dn_core.dn_type seems worse.)

I'm guessing that the compiler's complaint about the current code is that you have a dnode_phys_t* that points to an array that is not large enough to hold a dnode_phys_t. I think the proposed solution is decent but I wonder if there's another way to do this. Maybe if we allocated a larger buffer to point to (might have to be on the heap due to the linux kernel's limited stack space). That would be a little slower but it might not be significantly so.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The downside is that you have to change all the code that's accessing it to add .dn_core :( . (And the "solution" to that of doing #define dn_type dn_core.dn_type seems worse.)

Yeah, fully agree. It would be so nice if we could just say

struct dnode_phys {
    struct dnode_phys_core;
    union {
        ...
   }
}

but well, maybe in ten years, using C23, that'll work. ;-)

I'm guessing that the compiler's complaint about the current code is that you have a dnode_phys_t* that points to an array that is not large enough to hold a dnode_phys_t.

Exactly, ‘dnode_phys_t {aka struct dnode_phys}[0]’ is partly outside array bounds. The full warning is here at the bottom.

Maybe if we allocated a larger buffer to point to

That didn't occur to me, but your right, using a dnode_phys_t and just limiting the HMAC calculation to the first 64 bytes of that may be a cleaner solution. IIRC the stack size in Linux is 16k and a dnode_phys_t is 512 bytes, so limited stack space shouldn't be a concern. The only drawbacks I can see is 448 more bytes on the stack and maybe slightly less clearer code. I'll push a changed version. Which approach to choose I leave up to you, I'm fine either way.

Copy link
Contributor

@behlendorf behlendorf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's unfortunate we need to use the additional space on the stack for this, but I agree it shouldn't be a problem here. Things are a bit tighter on i386 with uses 8k stacks, but I believe we'll still be OK there as well. This does seem like the cleanest way to handle this to me.

@AttilaFueloep
Copy link
Contributor Author

All right. I'll hold-up squashing until a second reviewer had a chance to look at it.

@ahrens
Copy link
Member

ahrens commented Jun 22, 2021

Thanks for doing that, looks great!

Compiling with gcc 11.1.0 produces three new warnings.

Change the code slightly to avoid them.

Signed-off-by: Attila Fülöp <[email protected]>
Closes openzfs#12130
Closes openzfs#12188
@AttilaFueloep
Copy link
Contributor Author

My pleasure. Squashed, rebased and updated commit comment.

@behlendorf behlendorf added the Status: Accepted Ready to integrate (reviewed, tested) label Jun 23, 2021
@mmaybee mmaybee merged commit 1b610ae into openzfs:master Jun 23, 2021
behlendorf pushed a commit that referenced this pull request Jun 24, 2021
Compiling with gcc 11.1.0 produces three new warnings.
Change the code slightly to avoid them.

Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Matthew Ahrens <[email protected]>
Signed-off-by: Attila Fülöp <[email protected]>
Closes #12130
Closes #12188
Closes #12237
rincebrain pushed a commit to rincebrain/zfs that referenced this pull request Oct 23, 2021
Compiling with gcc 11.1.0 produces three new warnings.
Change the code slightly to avoid them.

Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Matthew Ahrens <[email protected]>
Signed-off-by: Attila Fülöp <[email protected]>
Closes openzfs#12130
Closes openzfs#12188
Closes openzfs#12237
rincebrain pushed a commit to rincebrain/zfs that referenced this pull request Oct 24, 2021
Compiling with gcc 11.1.0 produces three new warnings.
Change the code slightly to avoid them.

Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Matthew Ahrens <[email protected]>
Signed-off-by: Attila Fülöp <[email protected]>
Closes openzfs#12130
Closes openzfs#12188
Closes openzfs#12237
tonyhutter pushed a commit that referenced this pull request Nov 1, 2021
Compiling with gcc 11.1.0 produces three new warnings.
Change the code slightly to avoid them.

Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Matthew Ahrens <[email protected]>
Signed-off-by: Attila Fülöp <[email protected]>
Closes #12130
Closes #12188
Closes #12237
tonyhutter pushed a commit to tonyhutter/zfs that referenced this pull request Nov 13, 2021
Compiling with gcc 11.1.0 produces three new warnings.
Change the code slightly to avoid them.

Reviewed-by: Brian Behlendorf <[email protected]>
Reviewed-by: Matthew Ahrens <[email protected]>
Signed-off-by: Attila Fülöp <[email protected]>
Closes openzfs#12130
Closes openzfs#12188
Closes openzfs#12237
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Accepted Ready to integrate (reviewed, tested)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Error building - crypto_mech_name_t zfs/hkdf.c:81: possible wrong sized buffer ?
6 participants