22

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?

  • Question is unclear: the links you provide give much information. What about it don't you get? – psusi Aug 6 '11 at 18:42
22

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).

  • Thanks @rozcietrzewiacz. That was very helpful. Can I then assume that current group ID = primary group? – Amelio Vazquez-Reina Aug 7 '11 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! – rozcietrzewiacz Aug 7 '11 at 16:50
17

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

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 is a utility to pretty print your /etc/group file:

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

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.