It is well-known that if I add myself to a new group, that change will not be reflected until I log out and back in:

$ sudo adduser me newgroup
$ groups
me sudo
$ groups me
me sudo newgroup

This odd behavior is because groups is interpreted by the shell and new group membership is not shown. But groups me actually references /etc/group and therefore the new membership is shown.

But what I find curious is that a new shell doesn't notice the change:

$ bash
$ groups
me sudo

The ways I know of to reflect the new group membership are (1) newgrp, or sg or su, (2) log out and back in.

So bash must be passing the group list to its child somehow. It's not in the environment (I tried printenv) and it's not in the kernel's task_struct (that has only gid, egid, sgid, and fsgid).

I can't figure how.

  • Note that you don't really need to log out and log in. You can start a new shell with "an environment similar to what the user would expect had the user logged in directly" with su -l $(whoami). – Arkadiusz Drabczyk Sep 23 '14 at 8:19

Groups are inherited by a process from its parent. Bash has no choice in the matter. A process running as root can obtain new supplementary groups upon request; a process not running as root can only relinquish supplementary groups.

The command groups with no arguments returns its own list of groups (which is inherited from its parent): real group, effective group and supplementary groups. The command group SOMEUSER looks up the groups associated with SOMEUSER in the user and group databases.

When logging in, groups are assigned based on the user and group databases, as part of the login process, before the login process switches from root to the target user. The commands newgrp, su and sg are able to acquire extra groups while it's running because it is setuid root; their code is written in such a way that they'll only grant groups that the user would be granted when logging in (except that root can get whatever group it wants).

In the Linux kernel, the UIDs and GIDs of a process are recorded in a struct cred. The supplementary groups are in the group_info field which points to a struct group_info which contains an array of group IDs.


The groups are assigned during login before privileges are dropped. Your shell can't simply assign new groups to itself, otherwise it would be useless as a security system; what groups a process is in is maintained by the kernel. See the output of cat /proc/$$/status for example and see the Groups: line; that is the definitive list of groups your shell is in ($$ is shortcut for the process ID of the shell).

The groups username command will look through /etc/groups (as you said) and simply show the groups that user is configured to belong to. Without a username the groups command just shows the /proc/$$/status list of groups, i.e. the actual current groups that process belongs to.

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.