The thing is, I always thought these permissions collapse on each other, starting with the most general one (other -> group -> user).
If it was the case then “other” permissions would apply to everyone.
In other words, if o=rwx who cares what the persmissions for group and user are?
That's different from your previous sentence. Here you're implying that the permissions are or'ed together, e.g. that userX has the read permission if userX owns the file and the file is user-readable, or if a group that userX belongs to owns the file and the file is group-readable, or if the file is other-readable. But that's not how it works. In fact, o=rwx
means that the rwx
permissions apply to others, but it doesn't say anything about entities that are not others.
First, it doesn't directly matter which groups a user belongs to. The kernel doesn't have a notion of users belonging to groups. What the kernel maintains is, for every process, a user ID (the effective UID) and a list of group IDs (the effective GID and the supplementary GIDs). The groups are determined at login time, by the login process — it's the login process that reads the group database (e.g. /etc/group
). User and group IDs are inherited by child processes¹.
When a process tries to open a file, with traditional Unix permissions:
- If the file's owning user is the process's effective UID, then the user permission bits are used.
- Otherwise, if the file's owning group is the process's effective GID or one of the process's supplementary group ID, then the group permission bits are used.
- Otherwise, the other permission bits are used.
Only one set of rwx bits are ever used. User takes precedence over group which takes precedence over other. When there are access control lists, the algorithm described above is generalized:
- If there is an ACL on the file for the process's effective UID, then it is used to determine whether access is granted.
- Otherwise, if there is an ACL on the file for the process's effective GID or one of the process's supplementary group ID, then the group permission bits are used.
- Otherwise, the other permission bits are used.
See also Precedence of ACLS when a user belongs to multiple groups for more details about how ACL entries are used, including the effect of the mask.
Thus -rw----r-- alice interns
indicates a file which can be read and written by Alice, and which can be read by all other users except interns. A file with permissions and ownership ----rwx--- alice interns
is accessible only to interns except Alice (whether she is an intern or not). Since Alice can call chmod
to change the permissions, this does not provide any security; it's an edge case. On systems with ACLs, the generalized mechanism allows removing permissions from specific users or specific groups, which is sometimes useful.
Using a single set of bits, rather than or-ing all the bits for each action (read, write, execute), has several advantages:
- It has the useful effect of allowing removing permissions from a set of users or groups, on systems with ACLs. On systems without ACLs, permissions can be removed from one group.
- It is simpler to implement: check one set of bits, rather than combining several sets of bits together.
- It is simpler to analyse a file's permissions, because fewer operations are involved.
¹ They can change when a setuid or setgid process is executed. This isn't related to the issue at hand.
The key in the user database, /etc/passwd
or something else, is the login name: that’s all that you provide to identify yourself when you log in. From that key, a program can retrieve all the other information stored in the user database; this happens with no regard for any other user in the user database, even other users with the same user id. (Typically, this is done with getpwnam
or getpwnam_r
, either directly or via PAM.)
Thus the login name leads to the stored password, the user id, the (primary) group id, the GECOS information, the home directory and shell. This means that two users can share the same user id, yet have different home directories and shells! (This was commonly used in the past to provide a fall-back, statically-linked shell for root; you’d have the usual root
user with id 0 and shell /bin/bash
or whatever, and another user, say sashroot
, with id 0 and a different shell.)
Hence the answer to
does the group ID field depend on user name or on user ID?
is that it depends only on the user name.
The key in the group database is also the group name. From that key, a program can retrieve all the other information stored in the group database; again this happens with no regard for any other group in the group database. (When determining a user’s secondary groups, the process is more complex than reading the user database: there is no function to list groups to which a given user belongs, so this is typically done in a loop involving getgrent
and endgrent
.)
Thus the group name leads to the group password, group id, and the list of group members, which is a list of user names. To build a user’s set of secondary groups, all the groups are enumerated, and the user’s login name is matched against the group’s members. So not only can two different users with the same user id have different primary groups, they can belong to a different set of secondary groups!
Hence the answer to
In other words, can different usernames for the same user ID have different group IDs, or must all the usernames for the same user ID have the same group ID?
is that a user’s groups only depend on the user name, and different user names can share a user id yet have different primary and secondary groups.
Best Answer
Yes, a superuser process can change its real user ID and real group ID to any value it desires. The values in
/etc/passwd
and/etc/shadow
are the configuration for what values should be set, but not a limitation of possible values.Edit #1
It means programs like
login
will read the values from the files, so the files are configuration files or input files. They are not constraints on what a program can do. A superuser process can pass any value to the kernel, and the kernel will not check any files.A program could call
and this would work, even if neither of the id's are mentioned in any file.