jedisct1 / libsodium

A modern, portable, easy to use crypto library.
https://libsodium.org
Other
12.06k stars 1.72k forks source link

macOS randombytes_buf infinite loop #1303

Closed calvin2021y closed 10 months ago

calvin2021y commented 10 months ago

I use 13.2.1, x86. get this error with randombytes_buf:

static ssize_t
safe_read(const int fd, void * const buf_, size_t size)
{
    unsigned char *buf = (unsigned char *) buf_;
    ssize_t        readnb =0;
        printf("safe_read=%d\n", fd);
    assert(size > (size_t) 0U);
    assert(size <= SSIZE_MAX);
    do {
                printf("readnb=%zd, size=%zu, errno=%d\n", readnb, size, errno);
        while ((readnb = read(fd, buf, size)) < (ssize_t) 0 &&
               (errno == EINTR || errno == EAGAIN)) {
                printf("readnb=%zd, size=%zu, errno=%d\n", readnb, size, errno);
        }
        if (readnb < (ssize_t) 0) {
            return readnb; /* LCOV_EXCL_LINE */
        }
        if (readnb == (ssize_t) 0) {
            break; /* LCOV_EXCL_LINE */
        }
        size -= (size_t) readnb;
        buf += readnb;
    } while (size > (ssize_t) 0);

    return (ssize_t) (buf - (unsigned char *) buf_);
}
safe_read=4
readnb=0, size=32, errno=0
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
readnb=-1, size=32, errno=35
jedisct1 commented 10 months ago

I was not able to replicate this, no one ever reported this, and this doesn't happen on CI either.

From a vanilla macOS installation with Homebrew, what are the required steps (installation, minimal test case, compilation commands) to replicate this?

calvin2021y commented 10 months ago
rm -rf autom4te.cache configure Makefile.in ./src/Makefile.in ./src/libsodium/Makefile.in ./src/libsodium/include/Makefile.in ./builds/Makefile.in
./autogen.sh -f -s -o

/opt/d/C/sodium/configure --enable-static --disable-shared --without-pthreads --enable-opt

build with flags -UHAVE_AVX512FINTRIN_H -DHAVE_COMMONCRYPTO_COMMONRANDOM_H=1 -DHAVE_GETENTROPY=1 -DHAVE_TMMINTRIN_H -DHAVE_WMMINTRIN_H -Wuninitialized -DSODIUM_STATIC -DDEV_MODE

master branch.

now I will try RANDOMBYTES_DEFAULT_IMPLEMENTATION with &randombytes_internal_implementation

calvin2021y commented 10 months ago

recent I upgrade into clang 16. not sure this related.

jedisct1 commented 10 months ago

Error 35 is EAGAIN, which can only be returned for files opened in non-blocking mode. libsodium never opens files in non-blocking mode. There's just no code that could possibly do that.

Are you sure your application doesn't do something else with file descriptor 4?

calvin2021y commented 10 months ago

It is a huge project, I am not sure other part not touch fd 4.

jedisct1 commented 10 months ago

Please don't mess with the compilation flags, that doesn't help.

And try with 1.0.18-stable release tarballs and just use ./configure as documented.

jedisct1 commented 10 months ago

Did the test suite pass when you typed make check before make install? Because it heavily uses randombytes_buf.

calvin2021y commented 10 months ago

when I make test, get some missing symbol error. I will try fix this and made the test.

jedisct1 commented 10 months ago

????

What symbols are missing?

Was clang installed via Homebrew? Or is it zig cc?

calvin2021y commented 10 months ago

-DRANDOMBYTES_DEFAULT_IMPLEMENTATION=&randombytes_internal_implementation with this patch fix my problem.

diff --git a/src/libsodium/randombytes/randombytes.c b/src/libsodium/randombytes/randombytes.c
index 6741434b..ab2429cf 100644
--- a/src/libsodium/randombytes/randombytes.c
+++ b/src/libsodium/randombytes/randombytes.c
@@ -15,7 +15,7 @@
 #include "randombytes.h"
 #ifndef RANDOMBYTES_CUSTOM_IMPLEMENTATION
 # ifdef RANDOMBYTES_DEFAULT_IMPLEMENTATION
-#  include "randombytes_internal.h"
+#  include "randombytes_internal_random.h"
 # endif
 # include "randombytes_sysrandom.h"
 #endif

the make test error

lld: error: undefined symbol: crypto_aead_aegis128l_aesni_implementation
>>> referenced by aead_aegis128l.c:142 (src/libsodium/crypto_aead/aegis128l/aead_aegis128l.c:142)
>>>               ../../src/libsodium/.libs/libsodium.a(libsodium_la-aead_aegis128l.o):(symbol _crypto_aead_aegis128l_pick_best_implementation+0x22)

lld: error: undefined symbol: crypto_stream_chacha20_dolbeau_ssse3_implementation
>>> referenced by stream_chacha20.c:0 (src/libsodium/crypto_stream/chacha20/stream_chacha20.c:0)
>>>               ../../src/libsodium/.libs/libsodium.a(libsodium_la-stream_chacha20.o):(symbol _crypto_stream_chacha20_pick_best_implementation+0x2d)

lld: error: undefined symbol: crypto_stream_chacha20_dolbeau_avx2_implementation
>>> referenced by stream_chacha20.c:0 (src/libsodium/crypto_stream/chacha20/stream_chacha20.c:0)
>>>               ../../src/libsodium/.libs/libsodium.a(libsodium_la-stream_chacha20.o):(symbol _crypto_stream_chacha20_pick_best_implementation+0x1b)

lld: error: undefined symbol: crypto_aead_aegis256_aesni_implementation
>>> referenced by aead_aegis256.c:141 (src/libsodium/crypto_aead/aegis256/aead_aegis256.c:141)
>>>               ../../src/libsodium/.libs/libsodium.a(libsodium_la-aead_aegis256.o):(symbol _crypto_aead_aegis256_pick_best_implementation+0x22)

lld: error: undefined symbol: _sodium_blake2b_compress_ssse3
>>> referenced by blake2b-ref.c:0 (src/libsodium/crypto_generichash/blake2b/ref/blake2b-ref.c:0)
>>>               ../../src/libsodium/.libs/libsodium.a(libsodium_la-blake2b-ref.o):(symbol _sodium_blake2b_pick_best_implementation+0x3a)

lld: error: undefined symbol: _sodium_blake2b_compress_sse41
>>> referenced by blake2b-ref.c:0 (src/libsodium/crypto_generichash/blake2b/ref/blake2b-ref.c:0)
>>>               ../../src/libsodium/.libs/libsodium.a(libsodium_la-blake2b-ref.o):(symbol _sodium_blake2b_pick_best_implementation+0x1f)

lld: error: undefined symbol: _sodium_blake2b_compress_avx2
>>> referenced by blake2b-ref.c:0 (src/libsodium/crypto_generichash/blake2b/ref/blake2b-ref.c:0)
>>>               ../../src/libsodium/.libs/libsodium.a(libsodium_la-blake2b-ref.o):(symbol _sodium_blake2b_pick_best_implementation+0xd)

lld: error: undefined symbol: crypto_onetimeauth_poly1305_sse2_implementation
>>> referenced by onetimeauth_poly1305.c:86 (src/libsodium/crypto_onetimeauth/poly1305/onetimeauth_poly1305.c:86)
>>>               ../../src/libsodium/.libs/libsodium.a(libsodium_la-onetimeauth_poly1305.o):(symbol _crypto_onetimeauth_poly1305_pick_best_implementation+0x1b)

lld: error: undefined symbol: _sodium_argon2_fill_segment_ssse3
>>> referenced by argon2-core.c:0 (src/libsodium/crypto_pwhash/argon2/argon2-core.c:0)
>>>               ../../src/libsodium/.libs/libsodium.a(libsodium_la-argon2-core.o):(symbol _crypto_pwhash_argon2_pick_best_implementation+0x28)

lld: error: undefined symbol: _sodium_argon2_fill_segment_avx2
>>> referenced by argon2-core.c:0 (src/libsodium/crypto_pwhash/argon2/argon2-core.c:0)
>>>               ../../src/libsodium/.libs/libsodium.a(libsodium_la-argon2-core.o):(symbol _crypto_pwhash_argon2_pick_best_implementation+0xd)

lld: error: undefined symbol: crypto_stream_salsa20_xmm6int_avx2_implementation
>>> referenced by stream_salsa20.c:89 (src/libsodium/crypto_stream/salsa20/stream_salsa20.c:89)
>>>               ../../src/libsodium/.libs/libsodium.a(libsodium_la-stream_salsa20.o):(symbol _crypto_stream_salsa20_pick_best_implementation+0x1b)
clang-16: error: linker command failed with exit code 1 (use -v to see invocation)
jedisct1 commented 10 months ago

If you invent your own way to compile it, you are on your own.

Please compile as documented.

Either just with ./configure && make check && make install, or with zig build -Doptimize=ReleaseFast.

jedisct1 commented 10 months ago

Also, start from a fresh clone of the repository, or type make distclean before ./configure to get rid of a previous failed compilation.

calvin2021y commented 10 months ago

I use ./configure && make check && make install, get this result.

# TOTAL: 82
# PASS:  82

I find for the default systemrandom, it work after start init process. late on a client request get this error. so could be some code change the fd. (is there a way to reopen it?)

and '-DRANDOMBYTES_DEFAULT_IMPLEMENTATION=&randombytes_internal_implementation' is safe to use for apple OSX, iOS ?

jedisct1 commented 10 months ago

Once again, no need to touch the compiler flags.

There's a function to change the RNG, and it's documented: https://doc.libsodium.org/advanced/custom_rng

You should call it before sodium_init().

And try calling sodium_init() as soon as possible, before you fork(), spawn threads or whatever.