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

sha2: fix aliasing violation #24

Merged

Conversation

thesamesam
Copy link
Contributor

@thesamesam thesamesam commented Apr 11, 2024

sha2: fix aliasing violation

&context->buffer is uint8_t*, but we try to access it as sha2_word64*, which
is an aliasing violation (undefined behaviour).

Use memcpy instead to avoid being miscompiled by e.g. >= GCC 12. This is
just as fast with any modern compiler.

Bug: https://gcc.gnu.org/PR114698
Bug: NetBSD/pkgsrc#122
Bug: archiecobbs/libnbcompat#4
Bug: https://bugs.launchpad.net/ubuntu-power-systems/+bug/2033405
Signed-off-by: Sam James sam@gentoo.org

@thesamesam
Copy link
Contributor Author

I've used the same patch from the linked bugs but it's also the obvious patch for the problem.

@peter-bergner
Copy link

See also Canonical Bug: #2033405

Copy link
Contributor

@hartwork hartwork left a comment

Choose a reason for hiding this comment

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

Hi @thesamesam,

I'm with you that this violates strict aliasing and should be fixed.

From a quick look at the unpatched code my impression is that:

  • context->bitcount is SHA256_CTX.bitcount in function SHA256_Final which is of type uint64_t, 8 bytes.
  • context->bitcount is SHA512_CTX.bitcount in function SHA512_Last which is of type uint64_t[2], 2 times 8 bytes.
  • sha2_word64 is either uint64_t or u_int64_t, both 8 bytes.

From that I would superficially include:

  • Changing this to memcpy should be safe and copy the exact same amounts of bytes as before and intended, assuming a "friendly compiler".
  • That the compiler is "likely" to do the right thing even unpatched, even with -O3.

What I do not yet understand is:

  • If this is a theoretical or a practical problem at runtime also?
  • How to invoke GCC to make it detect this issue — I tried and it kept silent.

What do you think?

Best, Sebastian

CC @eribertomota

@thesamesam
Copy link
Contributor Author

thesamesam commented May 2, 2024

If this is a theoretical or a practical problem at runtime also?

Please see https://gcc.gnu.org/PR114698 where this actually did break dcfldd itself, but also NetBSD/pkgsrc#122 and archiecobbs/libnbcompat#4 where the same file is used in other projects and it led to wrong results.

I did mention that in the commit message but maybe it wasn't explicit.

How to invoke GCC to make it detect this issue — I tried and it kept silent.

Unfortunately, GCC's strict aliasing warnings are known to be deficient and easy to fool. See https://gcc.gnu.org/PR113151. You can sometimes get GCC to warn on things by using -Wstrict-aliasing=2 but then it has more risk of FPs and it still is easy to fool.

@davidpolverari
Copy link
Collaborator

Hi, @hartwork!

What I do not yet understand is:

* If this is a theoretical or a practical problem at runtime also?

* How to invoke GCC to make it detect this issue — I tried and it kept silent.

I also tried to reproduce the issue presented on https://gcc.gnu.org/PR114698 by using a Debian Sid ppc64el image emulated under QEMU. I had no wrong results after building dcfldd using GCC 13 with -O3. I will have another (and closer) look at it as soon as I have time.

Regards,
David

@davidpolverari
Copy link
Collaborator

davidpolverari commented May 2, 2024

... I had no wrong results after building dcfldd using GCC 13 with -O3. I will have another (and closer) look at it as soon as I have time.

Well, I must had done something wrong last time I tested, because I had tests failing now after building with -O3 on ppc64el with GCC 13. Looking at it now.

Copy link
Collaborator

@davidpolverari davidpolverari left a comment

Choose a reason for hiding this comment

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

LGTM and it worked on Debian Sid ppc64el, built with GCC 13.

src/sha2.c Outdated Show resolved Hide resolved
src/sha2.c Outdated Show resolved Hide resolved
`&context->buffer` is `uint8_t*`, but we try to access it as `sha2_word64*`, which
is an aliasing violation (undefined behaviour).

Use memcpy instead to avoid being miscompiled by e.g. >= GCC 12. This is
just as fast with any modern compiler.

Bug: https://gcc.gnu.org/PR114698
Bug: NetBSD/pkgsrc#122
Bug: archiecobbs/libnbcompat#4
Bug: https://bugs.launchpad.net/ubuntu-power-systems/+bug/2033405
Signed-off-by: Sam James <sam@gentoo.org>
@davidpolverari davidpolverari merged commit 5f076fa into resurrecting-open-source-projects:master May 2, 2024
@davidpolverari
Copy link
Collaborator

Thanks for your help!

thesamesam added a commit to thesamesam/dcfldd that referenced this pull request May 2, 2024
When reviewing resurrecting-open-source-projects#24,
@davidpolverari pointed out a mistake I made in one revision - oops.

While fixing that, I noticed:
```
sha2.c: In function ‘SHA384_End’:
sha2.c:1052:45: error: argument to ‘sizeof’ in ‘memset’ call is the same expression as the destination; did you mean to dereference it? [-Werror=sizeof-pointer-memaccess]
 1052 |                 MEMSET_BZERO(context, sizeof(context));
      |                                             ^
sha2.c:176:49: note: in definition of macro ‘MEMSET_BZERO’
  176 | #define MEMSET_BZERO(p,l)       memset((p), 0, (l))
      |                                                 ^
cc1: some warnings being treated as errors
```

Let's fix that too, while we're at it.

Signed-off-by: Sam James <sam@gentoo.org>
@thesamesam
Copy link
Contributor Author

Thank you!

davidpolverari pushed a commit that referenced this pull request May 2, 2024
When reviewing #24,
@davidpolverari pointed out a mistake I made in one revision - oops.

While fixing that, I noticed:
```
sha2.c: In function ‘SHA384_End’:
sha2.c:1052:45: error: argument to ‘sizeof’ in ‘memset’ call is the same expression as the destination; did you mean to dereference it? [-Werror=sizeof-pointer-memaccess]
 1052 |                 MEMSET_BZERO(context, sizeof(context));
      |                                             ^
sha2.c:176:49: note: in definition of macro ‘MEMSET_BZERO’
  176 | #define MEMSET_BZERO(p,l)       memset((p), 0, (l))
      |                                                 ^
cc1: some warnings being treated as errors
```

Let's fix that too, while we're at it.

Signed-off-by: Sam James <sam@gentoo.org>
@hartwork
Copy link
Contributor

hartwork commented May 3, 2024

@davidpolverari is there a chance to release 1.9.2 with this critical patch? Without a new release, all downstreams will have to bundle the patch downstream and become aware some way also. A new release would help awareness while reducing multiplication of work. What do you think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants