In order to change his/her own password, the user needs to somehow get the new password hash written to /etc/shadow
(or /etc/passwd
on legacy systems with no shadow password implementation).
If the user is allowed write access to the file, then the user can change anything within that file: the user could change anyone's passwords, impersonate any user, and trivially gain root access. This is clearly not acceptable.
The solution is a "gatekeeper" that has the power to let the user perform one specific act with root-level access, namely change his/her own password only.
The /bin/passwd
program is such a gatekeeper program. It is written very carefully to ensure that it will allow the changing of the user's own password only, unless the user is root (or, in some cases, has appropriate extra privileges). When the gatekeeper program is ready, its permissions are set so that the users can execute it, but not modify the program's contents. Then the setuid root permission is added to the program: it causes any process running that specific program to have root access for the duration of that specific process only.
Sometimes the permissions of setuid root programs are set to 4111, or ---s--x--x
, so that non-root users are only allowed to execute the program, but not to read its contents in any other way.
There are some protections for setuid programs that are built-in to the operating system: for example, you cannot attach a debugger to a process that is running a setuid root program unless you are root. And if a setuid program happens to be readable by regular users, and a user attempts to make a copy of that program, the copy will usually lose the setuid permission bit; and even if it didn't, the copy will (normally) be owned by the user that made the copy, so it will no longer be setuid root but setuid [username], and most likely cannot do its job anyway.