26

The following links discuss these concepts in different contexts. I have read their definitions, but I still can't tell how they are related, or if some of them are just the same.

Here is one example of the source of my confusion:

According to man id, if I type id, I should get what they call effective and real group IDs.

id uid=501(joe) gid=501(joe) groups=501(joe), 100(users) 

However, Wikipedia refers to the output of id to distinguish between primary and supplementary IDs. Moreover, Wikipedia distinguishes between primary vs supplementary and effective vs real group ids. How do these concepts relate to each other?

Also, is it true that primary group ID = group ID = current group ID?

1
  • Question is unclear: the links you provide give much information. What about it don't you get? Commented Aug 6, 2011 at 18:42

3 Answers 3

30

You mix two different distinctions here:

  1. Between real and effective group ids
  2. Between primary and supplementary users' groups

The first distinction refers to how processes are being run. Normally, when you run a command/program, it is run with the privileges of your user. It has the real group id same as your user's primary group. This can be changed by a process in order to perform some tasks as a member of another special group. To do that, programs use the setgid function that changes their effective group id.

The second distinction refers to users. Each user has his/her primary group. There is only one per user and is referred to as gid in the output of the id command. Apart from that, each user can belong to a number of supplementary groups - and these are listed at the end of id output.

[Edit] :

I agree that the manpage for id is somewhat misleading here. It is probably because it is a stripped-down version of the description provided by the info document. To see it more clearly, run info coreutils "id invocation" (as suggested at the end of the id manual).

2
  • Thanks @rozcietrzewiacz. That was very helpful. Can I then assume that current group ID = primary group? Commented Aug 7, 2011 at 16:35
  • 1
    In general, no. The current "real" group can be changed using the newgrp command - see the second paragraph of the manual in your first link! Commented Aug 7, 2011 at 16:50
19

The kernel view

Conceptually, there are three sets of groups that a process is a member of. Each set is a subset of the following one.

  1. The single group that is the process's default group, which files created by this process will belong to.
  2. The set of groups that are checked when the group requires permission to open a file.
  3. The set of groups that a process running with extra privileges process can draw upon.

For historical reasons, these sets are respectively:

  1. the effective group ID (egid);
  2. the effective group ID plus the supplementary group IDs;
  3. all of the above plus the real group ID and the saved set-group-ID.

Normally, a program has a single user ID. If the executable has the setuid mode bit set, then the program has two user IDs: its effective user ID is the one that matters for file permissions, per-user limits, determining whether the process is running as root and so on. The process can switch between the effective and the real user IDs, if it doesn't need its extra privileges all the time, or if it needs to switch between two non-root users.

The same mechanism exists for group. For groups, there is an additional feature which didn't exist when the system was designed: a process can be a member of any number of groups; these are the supplementary group IDs.

The user database view

Once a user is authenticated, the login process switches to that user, just before launching the user's shell (or whatever program the user requested). Just before switching to the desired user (and losing root privileges), the login process switches to the desired groups.

In early unix versions, a process could only be in a single group. This group is the user's primary group ID, stored in the user database (typically /etc/passwd). This group becomes the real and effective group ID of the shell or other program launched by the login process.

Nowadays, a process can be in multiple groups, so users can be in multiple groups, too. The group database (typically /etc/group) contains a list of users for each group. These groups become supplementary group IDs for the program launched by the login process.

1
1

Many other excellent answers here, but if you're still confused as I was, here's another approach. Please note that I am only a student of this stuff, not a master, so this answer is a work in progress, and not to be considered a solid answer, at least not yet. Consider this answer v0.2.

Groups are simple and complex at the same time.

Key to IDs used below:

KEY Full name -------- Description--------------------------------------------- u User uID = User ID (a unique # associated with each user) g Group gID = Group ID (a unique # associated with each group) While each /etc/passwd entry has one uID and one gID, additional gIDs can be associated with a users via /etc/group. L Login IDs - uID and gID produced from the Login process. ('L' is not exactly standard Linux terminology, but useful for explanations below.) F File IDs - uID and gID retrieved from a file's ownership. ('F' is not exactly standard Linux terminology, but useful for explanations below.) R Real IDs - Who actually runs a process E Effective IDs - Who spoofed via setuid or setgid, runs a process O Original Eff. IDs - Place to save the original Effective ID when changing it (e.g. temporarily downgrading it) so can later restore it. Also called "Saved ID"; (but 'S' was not used for here to help avoid confusion with the 'S' in 'SetUserID' & SetGroupID.) + Supplimentary gIDs - Optional, additional groups (none or more) running this process which can be used to test for permissions. 

User and Group ID names:

Category USER GROUP Notes ----------------- ---- ----- ------------------------------------------- From login: LuID LgID From /etc/passwd lookup From files: FuID FgID Each file has these. Set by creator process. For each running process: Real RuID RgID Actual user starting the program Effective EuID EgID Assigned user starting the program* Saved OuID OgID Saves original effective ID. Supplementary +gID1 (optional, additional groups) +gID2 ... 

How processes acquire IDs:

  1. Login authenticates username and returns LuID and LgID from /etc/passwd.

  2. The first process sets up effective=real=login, i.e.

    EuID=RuID=LuID EgID=RgID=LgID

  3. Forked children inherit RuID, EuID, RgID, and EgID, (& possibly saved & supp), however,

  • If the suid bit (s) is set on the file of the new program to execute, then set effective from file:

    EuID=FuID

  • If the sgid bit (s) is set on the file of the new program to execute, then set effective from file:

    EgID=FgID

Note: The underlying filesystem's suid and nosuid mount options also apply.

4a) If suid was used to set EuID, then EuID can be temporarily changed (e.g. downgraded from root), but first it's original value is saved in OuID so it can be restored later if desired.

4b) If sgid was used to set EgID, then EgID can be temporarily changed (e.g. downgraded from root), but first it's original value is saved in OgID so it can be restored later if desired.


When a file is to be created:

File's new id's are set from effective id's: FuID=EuID and FgID=EgID (Permissions are set from umask.) 

To open for reading:

If FuID = EuID and user-read bit is set, or If FgID = EgID and group-read bit is set, or If FgID = +gID1 and group-read bit is set, or If FgID = +gID2 and group-read bit is set, ... then allow reading. 

To open for writing:

(Same as above but write bit set to allow writing.) 

To open for execution:

(Same as above but execute bit set to allow execution.) 

When a message needs to be sent:

Use RuID and RgID. (Not EuID or EgID). *(Not sure where I read this.)* 

References: man credentials

Extra: Here are utilities to pretty print your /etc/passwd and /etc/group files:

cat /etc/passwd | sort -t: -k3n | awk -F ':' \ 'BEGIN{printf "\n%-20s %-3s %-7s %-8s %s\n", \ "User name" , "pw", "User ID", "Group ID", "Username or comment"}\ BEGIN{printf "%-20s %-3s %-7s %-8s %s\n", \ "----------", "--", "-------", "--------", "--------------------------------"} \ {printf "%-20s %-2s %7d %7d %s\n", $1, $2, $3, $4, $5 }' cat /etc/group | sort -t: -k3n | awk -F ':' \ 'BEGIN{printf "\n%-20s %-3s %-8s %s\n", \ "Group name", "pw", "Group ID", "User list"}\ BEGIN{printf "%-20s %-3s %-8s %s\n", \ "----------", "--", "--------", "---------------------"} \ {printf "%-20s %-2s %8d %s\n", $1, $2, $3, $4 }' 

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.