Running modern Git on ancient Synology kernels
Git push to my Gitea failed with the following message:
remote: error: unable to get random bytes for temporary file: Function not implemented
remote: error: unable to create temporary file: Function not implemented
Instead of generating random bits from /dev/urandom, modern Git now calls the getrandom syscall via libc, which has been available from Kernel 3.17 and up. Unfortunately for me Synology does not update to newer Kernel versions, instead they backport patches to the old version that came with the device, which is good for stability, but bad if you need to run a more modern Git version.
LD_PRELOAD shim
Claude suggested to replace the NAS, second best option was to build this small shim as SO file against libmusl and mount it into Gitea’s container:
// file: getrandom_shim.c
#define _GNU_SOURCE
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
ssize_t getrandom(void *buf, size_t buflen, unsigned int flags) {
(void)flags;
int fd = open("/dev/urandom", O_RDONLY);
if (fd < 0) { errno = EIO; return -1; }
ssize_t n = read(fd, buf, buflen);
close(fd);
return n;
}
We take this small shim that redirects the syscall to the old /dev/urandom device and compile it against alpine, which uses musl:
/volume1/docker/shim# docker run --rm -v "$PWD":/src -w /src alpine:3.19 sh -c \
"apk add --no-cache gcc musl-dev && gcc -shared -fPIC -O2 -o getrandom_shim.so getrandom_shim.c"
/volume1/docker/shim# chmod 644 getrandom_shim.so
Once the shim is built, we can now add these two lines the Gitea docker-compose.yaml to inject it into the dynamic linker before all the other symbols are resolved and redeploy:
environment:
- LD_PRELOAD=/usr/local/lib/getrandom_shim.so
…
volumes:
- /volume1/docker/shim/getrandom_shim.so:/usr/local/lib/getrandom_shim.so:ro
Git is now working properly again. This post is put under the playground category deliberately, because I don’t know yet whether I want to keep it like this or not.