Why doesn't su change the user ID of the shell from which it was run?
Simple: because it can't. There is no system call to change the uid of another process. If you don't want to leave the parent shell around waiting for su
to exit, then prefix it with the exec
builtin command, which causes the shell to directly exec without forking first. Of course if you get the password wrong, there will be no shell to return to, so your session will terminate.
As has been pointed out, there is no way to do it. Of course, if there is a will, there is a way: that there is no such syscall is no reason why it couldn't be done. That said, as mtk touched on in a comment, imagine the havoc it could create having a syscall to change the security context of an unrelated process. If nothing else, I see a race condition erupting in three... two... one... (and let's not even get started on what changing the security context of init
or getty
could do.)
One other reason is that su
not only invokes a new shell. It also has the ability to control which shell is launched (using -s
or --shell
), and control it by passing parameters via (in GNU) the -
/-l
/--login
and -c
(--command
) parameters. The parameters passed to su can also have an effect on the new shell's environment. So even if you could just change the security context of the parent process, you would not necessarily want to do so.