Skip to content
academia.sh

Lesson 12 / 20

Users and Groups

Identity held as a number at the kernel level, the field structure of the account and group files, the distinction between primary and supplementary groups, and name resolution.

Contents

The previous lesson’s output belonged to the backup account for files on the remote machine, and to a different account for local files. The owner and group columns in listing output had been visible from the start, but were never explained.

This lesson closes that gap. What identity is stored as on the system is the input to the next lesson’s permission check: when the kernel answers “can this user read this file,” it compares exactly these values.

Identity Is a Number

The kernel does not know usernames. What every process is associated with is two integers: the user ID (UID) and the group ID (GID). Names exist only for humans and are resolved by programs in user space.

$ id
uid=1001(student) gid=1001(student) groups=1001(student),2001(project)

The output gives three pieces of information: the user ID, the primary group ID, and every group the user belongs to. The names in parentheses are the resolved counterparts of the numbers; the actual value is the number.

The fields can also be requested separately:

$ id -u
1001
$ id -g
1001
$ id -un
student

The -n suffix gives the name instead of the number. The whoami command produces the same result as id -un.

The practical consequence: a file’s owner is not a name, it is a number. If a user is deleted and a new account opens with the same number, the old files appear to belong to the new account. Likewise, files extracted from an archive can land on a different person’s ownership on the target system — what an archive stores is also the number.

Root is the account whose UID value is zero. Its privilege comes not from its name but from this number; the kernel skips most checks for UID zero.

The Account File

Account records are kept in a text file. Each line is one account, and fields are separated by colons:

$ grep -E '^(root|student|backup):' /etc/passwd
root:x:0:0:root:/root:/bin/bash
student:x:1001:1001::/home/student:/bin/bash
backup:x:1002:1002::/home/backup:/bin/bash

The seven fields, in order, are:

Order Field Value in the example
1 Username student
2 Password placeholder x
3 User ID 1001
4 Primary group ID 1001
5 Comment field empty
6 Home directory /home/student
7 Login shell /bin/bash

This file’s format was already read from section five of the manual in the Help Resources lesson; this is the concrete example of what section 5 is for.

The x in the second field is not a password. Password hashes are kept in a separate file that only root can read:

$ ls -l /etc/passwd /etc/shadow
-rw-r--r-- 1 root root   1236 Jul 26 19:14 /etc/passwd
-rw-r----- 1 root shadow  668 Jul 26 19:14 /etc/shadow
$ cat /etc/shadow
cat: /etc/shadow: Permission denied

The reason for the separation shows up in the permission columns: the account file is readable by everyone (rw-r--r--), because every program needs access to the username-to-ID mapping. If password hashes had the same accessibility, anyone could take the hashes and attempt offline cracking. Hashes are therefore separated and are readable only by their owner and the shadow group.

System accounts and human accounts are separated by ID ranges. Low numbers are reserved for services; human accounts start above a threshold that depends on the system’s configuration, but the separation itself is general, and account-creation tools pick the number from within this range.

The shell in the seventh field runs when a session opens. For service accounts where login is not wanted, this field holds a program that terminates immediately when run — the standard way to disable an account.

The Account’s Life Cycle

Account files are not edited by hand; account-management commands update these files consistently. A command that opens a new account writes not to one file but to three at once: a line in the account file, a password record in the shadow file, the primary group in the group file. It also creates the home directory and copies starting configuration files into it from the skeleton directory.

Supplementary group membership can be granted afterward. A common misconception: membership added at that moment is not reflected in the running session. A process’s group list is determined when the session opens and stays fixed for its duration; new membership only takes effect in a new session.

Closing an account and deleting it are separate operations. Closing invalidates the password, or replaces the login shell with a program that terminates the session; identity and file ownership stay in place. Deletion removes the record from the files — but does not clean up the files the user left on the system.

The result is a direct, visible consequence of identity being a number:

$ ls -l /data/report.txt
-rw-r--r-- 1 student student 0 Jul 26 19:54 /data/report.txt
$ sudo userdel student
$ ls -l /data/report.txt
-rw-r--r-- 1 1001 1001 0 Jul 26 19:54 /data/report.txt

A number appears in the owner column instead of a name: ownership has not changed, only the record that would translate the number into a name is gone. Such files silently belong to whoever gets that same number next — what needs handing over or cleaning up when an account is deleted.

The Group File

Groups are kept in a separate file, with four fields:

$ grep -E '^(root|student|backup|project):' /etc/group
root:x:0:
student:x:1001:
project:x:2001:student
backup:x:1002:

The fields, in order, are the group name, the password placeholder, the group ID, and the list of supplementary members.

The last field deserves attention. The student group’s member list is empty, yet the student user is a member of this group. That is not a contradiction: membership comes from two separate places.

The primary group is in the account file’s fourth field. New files a user creates take this group by default.

Supplementary groups come from the group file’s member lists. The line project:x:2001:student makes the student user a supplementary member of the project group.

Total membership is the union of both sources:

$ groups
student project

Giving every user a primary group named after themselves is a common configuration. The reason will be seen in the permission bits lesson: if the primary group were a shared group, every file a user creates would by default be open to that group.

A separate project group has been defined for this course’s project tree. It will be used to open the tree up for sharing in the ownership, group, and special permission bits lessons.

Name Resolution

Identity information does not always come from local files. At organizational scale, accounts can be kept in a directory service on the network, so programs call a resolution layer instead of reading the files directly.

$ getent passwd student
student:x:1001:1001::/home/student:/bin/bash
$ getent group project
project:x:2001:student

The getent command queries every configured source on the system and gives the answer in a standard format. Even when a record sits on a network source rather than in a local file, the output has the same shape; the program calling the command does not need to know where the source is.

In practice this means whether an account exists is tested not by grepping a file but by asking with getent. Not being found in the file does not show that the account does not exist.

Account Management Commands

The commands for creating, modifying, and deleting accounts and groups require root privilege and are documented in the manual’s eighth section. No account will be opened in this course; the related tool family is the subject of the System Administration course.

The one common operation that does not require root privilege is a user changing their own password. How this is possible is an interesting question: the file holding password hashes cannot even be read by an ordinary user, so how is writing to it made possible?

$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 72056 May 30  2024 /usr/bin/passwd

There is an unusual character in the permission string: an s instead of an x at the third position of the owner permissions. This is the subject of the special permission bits lesson, and it will be answered at that topic’s close.

Summary

  • The kernel stores identity as a number; names are resolved in user space, and file ownership is bound to the number.
  • Root’s privilege comes not from its name but from the user ID being zero.
  • The account file carries seven fields: name, password placeholder, user ID, primary group ID, comment, home directory, and login shell.
  • Password hashes sit in a separate, privilege-only-readable file to prevent offline cracking attacks.
  • Membership comes from two sources: the primary group in the account file and the supplementary member lists in the group file.
  • Name resolution is not limited to local files; queries go through a resolution layer.

Next Step

Now that identity is defined, what this identity can do to a file can be asked. The next lesson resolves the nine characters in the first column of listing output: three access types, three user classes, octal notation, and why the same bits mean something entirely different in directories.

To keep your progress and take notes, Log in

My notes

Log in to take notes.

Start typing to search.

↑↓ Esc navigate · open · close