If you also intercept the exec* family calls, you can forbid the user from running any but the trusted executables (so that will exclude e.g. anything written in Python etc).
It does get tricky since you are depending on glibc internals to find out what symbols to override. IIRC some of the exec* functions called each other internally without going through the symbol table, so you cannot override just execve which corresponds to the system call, as execvp will not call the execve function.
Then there's a whole ton of new secure Linux system calls that instead of a full path name take a directory file descriptor + name in that directory. E.g. execveat, openat etc.
So I wouldn't recommend it in a fully hostile (secure) environment.
It does get tricky since you are depending on glibc internals to find out what symbols to override. IIRC some of the exec* functions called each other internally without going through the symbol table, so you cannot override just execve which corresponds to the system call, as execvp will not call the execve function.
Then there's a whole ton of new secure Linux system calls that instead of a full path name take a directory file descriptor + name in that directory. E.g. execveat, openat etc.
So I wouldn't recommend it in a fully hostile (secure) environment.