If a user wants to execute a command, he has to first log in into a system. But some users in the system have /bin/false or /sbin/nologin set as a default shell in the /etc/password file. If I change /bin/bash to /bin/false in case of my user, I won't be able to log in into the system, so I also won't be able to run commands.

But the shellless users do it anyway:

# ps -eo "%mem,user,group,args" | grep -i dns
 0.0 dnscrypt dnscrypt /usr/sbin/dnscrypt-proxy --daemonize --user dnscrypt --local-address= --resolver-address= --provider-name=2.dnscrypt-cert.opendns.com --provider-key=B735:1140:206F:225D:3E2B:D822:D7FD:691E:A1C3:3CC8:D666:8D0C:BE04:BFAB:CA43:FB79

# cat /etc/passwd | grep -i dns

How can a user without a shell execute a command?


In POSIX, every running process has three User IDs (UIDs) associated with it; the real UID, which identifies the user who launched the process, the effective UID, which is used to determine what resources the process can access, and the saved Set-User-ID (SUID), which is the effective UID the process had when it started (at the point of the last exec() call). Of these, the effective UID is the most significant, since it is the one used when determining access control decisions regarding the process.

Daemons are typically started from init scripts, which are executed by the init system, running with root privileges. Processes may change the real/effective UID via the setuid(), seteuid() and setreuid() system calls. This is the case with the dnscrypt-proxy invocation given as an example1 in the question. The --user dnscrypt option tells dnscrypt-proxy to assume the identity of the user dnscrypt. A privileged process may assume the identity of any user (even changing its saved SUID), whereas unprivileged user processes may only set the effective UID to the real user ID, the effective UID or the saved set-user ID.

The basic uses cases for changing the UIDs is for a privileged process to drop its privileges, either permanently, or temporary. The latter case is needed by programs with the SUID bit set, which need to perform some unprivileged operations using their real UID, then regain their SUID granted privileges. The POSIX.1-1990 standard adopted the traditional System V behaviour for the setuid() function, which specifies setuid() to behave differently for privileged and unprivileged users. When the caller had the appropriate privilege, the function set the calling process' real UID, effective UID, and saved SUID. When the caller did not have the appropriate privilege, the function set only the effective UID, as described above.

In contrast, 4.3BSD did not support the saved SUID, but handles the latter case with separate functions. While setuid() always set both the real and effective UIDs, seteuid() could be used to set only the effective UID (like setuid() in POSIX1-1990 for non-privileged users). Lastly, setreuid() allowed processes to swap their real and effective UIDs, in order to support previously-privileged processes to regain their privileges.

The POSIX:2001 standard introduced a mandatory feature named _POSIX_SAVED_IDS. This allows a SUID application to switch its effective UID back and forth between the values of its saved SUID and effective user ID. More information can be found in the rationale section of the POSIX:2004 specification for setuid(). In Linux, setuid() is implemented like the POSIX version with the _POSIX_SAVED_IDS feature.

1: ps can be made to display the real UID, effective UID and saved SUID with the ruser, euser and suser format specifiers, e.g ps -eo "ruser,euser,suser,args".

  • If understood you well, the real UID is root, the saved UID is dnscrypt-proxy. But I don't get the effective UID. What would that be? Could you write a little bit more about the third UID? – Mikhail Morfikov Jan 9 '14 at 11:31
  • @MikhailMorfikov: "If understood you well, the real UID is root, the saved UID is dnscrypt-proxy." No, while initially, both the real and effective UIDs (and therefore also the saved SUID) are 0 (root), unless dnscrypt-proxy is a SUID binary, when a privileged process calls setuid(), all three associated UIDs are changed, in this case to dnscrypt. The effective UID is the most important one, as it is the one which affects the access control decisions made by the kernel. I updated the answer with additional information. – Thomas Nyman Jan 9 '14 at 13:19
  • this answer should be turn into a wiki answer – Kiwy Jan 9 '14 at 13:23
  • because in my opinion it's usefull and complete and people should be able to complete that as it's not a problem a resolution but a common knowledge on Unix linux system. but that my only opinion, I ay misunderstand the point of a wiki post – Kiwy Jan 9 '14 at 13:29
  • @Kiwy Thanks. I'll consider it, but I also think that when writing an answer, it is as important to consider what information to leave out as it is to consider what information to put it. I wouldn't want the answer to grow out of proportion either. Feel free to suggest edits if you think something important has been left out, you (and other) can still do that even thought it's not a wiki post. – Thomas Nyman Jan 9 '14 at 13:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.