In the first attempt, the preinit loader used a negative system-call return value to carry an error-return code. This was convenient, but doing so ruins portability because POSIX-compliant programs have to retrieve the error code from the global errno variable, and only expect system calls to return -1 on error. (I personally think that this original design is a mistake that complicates everything but it's not going to change and we have to adapt to it).
The -1 for "an error occurred" has always seemed like an oddity to me too, especially when the kernel itself already uses the negative range for distinguishing between different errors. It's especially problematic in the common use-case of cleaning up after a system call before determining whether an error occurred, because instead of simply doing this...
ret = some_syscall(...);
...do some cleanup...
if(ret < 0) { ...error case... }
...it also requires that you store errno if the cleanup code may change it (and if you always do that, then it's wasted in the non-error case.) I've seen more than one instance where the authors of an application/library decided to add another wrapper on top of the POSIX ones to essentially "undo" this stupidity by making their wrapped calls return a negatively-biased errno.