runevp.c: // gcc runevp.c -o runevp #include #include int main() { int i; for (i=0; i < 5; i++) { if(fork()==0) { execvp("true", NULL); } } return 0; } auditlib.c: // gcc -Wall -fPIC -shared -o auditlib.so auditlib.c #include #include typedef long int Lmid_t; unsigned int la_version(unsigned int version) { return version; } unsigned int la_objopen(struct link_map *map, Lmid_t lmid, uintptr_t *cookie) { return 3; } uintptr_t la_symbind64(Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook, uintptr_t *defcook, unsigned int *flags, const char *symname) { if (strcmp(symname, "execvp") == 0) { printf("symbol binding for '%s'\n", symname); } return sym->st_value; } Any glibc release except glibc 2.35 on ARM: Symbol binding occurs repeatedly (LD_BIND_NOT) $ LD_AUDIT=/path/to/auditlib.so LD_BIND_NOT=1 ./runevp symbol binding for 'execvp' symbol binding for 'execvp' symbol binding for 'execvp' symbol binding for 'execvp' symbol binding for 'execvp' glibc 2.35 on ARM: Symbol binding occurs once (ignores LD_BIND_NOT) $ LD_AUDIT=/path/to/auditlib.so LD_BIND_NOT=1 ./runevp symbol binding for 'execvp'