OS X 10.12 and FAIL: random
Closed, DuplicatePublic


I'm building libgcrypt 1.8.6 on OS X 10.12 with triplet x86_64-apple-darwin16.7.0. make check is failing.

Making check in tests
make  check-TESTS
cc:40201:clang:4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2):
PASS: version
PASS: t-secmem
PASS: mpitests
PASS: t-sexp
PASS: t-convert
PASS: t-mpi-bit
PASS: t-mpi-point
PASS: curves
PASS: t-lock
PASS: prime
PASS: basic
PASS: keygen
PASS: pubkey
PASS: hmac
PASS: hashtest
PASS: t-kdf
PASS: keygrip
PASS: fips186-dsa
PASS: aeswrap
PASS: pkcs1v2
dyld: Library not loaded: /Users/jwalton/tmp/ok2delete/lib/libgcrypt.20.dylib
  Referenced from: /Users/jwalton/Build-Scripts/libgcrypt-1.8.6/tests/.libs/random
  Reason: image not found
random: running '/Users/jwalton/Build-Scripts/libgcrypt-1.8.6/tests/.libs/random --in-recursion --early-rng-check' failed
FAIL: random
PASS: dsa-rfc6979
      256 of 1026 tests done
      512 of 1026 tests done
      768 of 1026 tests done
      1024 of 1026 tests done
      1026 tests done

I can't find log files for the self tests. If you know where they are, then please say so.

libgcrypt-1.8.6 $ find . -name '*.log'
libgcrypt-1.8.6 $

Here is config.log:



JW created this task.Aug 2 2020, 8:42 PM
werner added a subscriber: werner.Aug 4 2020, 10:29 AM

There are no log file but you can run the test by hand:

$ cd tests
$ ./random --debug

but I doubt that this will help because it seems that random is not run at all.

gniibe added a subscriber: gniibe.Aug 6 2020, 9:41 AM

I'm afraid that the dynamic linker doesn't allow hardcoding library path in an executable on macOS.
(It is only supported on some limited platforms.)

If so, you need to install (make install), before you invoke make check.

JW added a comment.EditedAug 15 2020, 1:55 AM

I believe the problem here is OS X 10.12's (and above) System Integrity Protection (SIP). SIP protects system integrity by doing things like sanitizing environmental variables for system programs. Sanitizing environmental variables on system programs avoids code injections.

There are two parts to the sentence. First is "sanitizing environmental variables", and that includes DYLD_LIBRARY_PATH. The second part is "for system programs". SIP protects system programs like /bin/make and /bin/sh. SIP does not protect user programs, like $HOME/bin/foobar.

A break due to System Integrity Protection (SIP) makes sense. Linux is OK, and OS X 10.9 is OK. The problem is OS X 10.12, which introduced SIP.

So what is happening (if I am parsing things correctly)...

  1. make check compiles libgcrypt-1.8.6/tests/random.c into libgcrypt-1.8.6/tests/.libs/random (notice addition of .libs)
  2. make is invoked. make is a system program and the environment is sanitized.
  3. make eventually executes libgcrypt-1.8.6/tests/random.
  4. libgcrypt-1.8.6/tests/random wrapper script sets up DYLD_LIBRARY_PATH. It is a user program, so the environment is not sanitized.
  5. libgcrypt-1.8.6/tests/random calls libgcrypt-1.8.6/tests/.libs/random. It is a user program, so the environment is not sanitized.
  6. libgcrypt-1.8.6/tests/.libs/random (compiled from random.c) eventually calls system (cmdline). The environment is sanitized.

At step (5), system runs a command like .../tests/.libs/random --in-recursion --early-rng-check. .../tests/.libs/random is _not_ a system program, but the loader/interpreter is protected from the DYLD_LIBRARY_PATH code injection. Because SIP is protecting the loader/interpreter from code injections, DYLD_LIBRARY_PATH is sanitized.

I don't see an easy fix here. (But I may be parsing things incorrectly).

Even if you call one of the exec* functions, I believe SIP will still scrub the environmental variables. Using exec* instead of system is just trying to do an end-around, so SIP won't allow it either.

We can't fix the linked library for the random test program using otool or install_name because make check is atomic. It builds and runs in one step. If we could get in between the build and the run, then we could probably fix the problem.

I _think_ the way to fix this is to break-out random.c into individual programs, and have the individual program directly test the generator. The individual programs are user programs, and they avoid the system calls. Their environment should be preserved.