AMSA

Week 6: Users, permissions, file systems and timers

Ferran Aran Domingo
Oriol Agost Batalla
Pablo Fraile Alonso

Goals for today

  • Any questions from the previous session?
  • Understand Linux users and groups.
  • What happens when we use sudo?
  • Work with file permissions.
  • Set up file systems.
  • Schedule tasks with systemd timers.

Users and groups

  • How do they fit with what we already know?

Linux users

  • Each process runs as a user (identified by UID).
  • Files and dirs belong to an owner and a group.
  • The system keeps users in /etc/passwd and passwords (hashes) in /etc/shadow.
  • Most day-to-day work should be done as a regular user.

Why multiple users?

  • Isolation and security

  • Accountability (who did what)

  • Least-privilege principle

Tip

  • In the AMSA VM, you log in as user amsa.

The superuser: root

  • root (UID 0) can read/write anything and change system config.
  • We usually avoid logging in directly as root.
  • Instead, we use sudo to run one command with elevated privileges.

Important

sudo <cmd> runs <cmd> as root.

How does sudo work?

Are this commands familiar? This a situation among many where we need admin rights, and so we run the command with sudo at the beginning.

sudo apt update
sudo apt install -y htop

Caution

If you run tools that create files (e.g., ssh-keygen) with sudo, those files will belong to root and land in root’s home.

Linux groups

  • A group (identified by GID) is a set of users sharing permissions on files/dirs.

  • Each user has a primary group and may also belong to other groups.

  • Useful commands:

    • groups [user] – list which groups is user part of
    • id [user] – the same but also shows UID and GIDs

System databases

/etc/passwd (users)

cat /etc/passwd
# username:x:UID:GID:comment:home:shell
# amsa:x:1002:1003::/home/amsa:/bin/bash


/etc/shadow (passwords)

cat /etc/shadow
# username:password-hash:lastchange:min:max:warn:inactive:expire:reserved


/etc/group (groups)

cat /etc/group
# name:x:GID:user1,user2,...


Creating users

Let’s create and configure a test user

# Create user 'test' with a home dir
sudo useradd -m test
# Create a new group called "testgroup"
sudo groupadd testgroup
# Set a password
sudo passwd test
# Add to 'wheel' group (if desired)
sudo usermod -aG wheel test

Important

When adding a user to a group, for the change to take effect we need to log out and log back in as that user. Another way is to use the su command to change to another user and then back to the affected user. So for example if I add user test to group testgroup, I can do su amsa to switch to user amsa, su test to then switch back to user test which now will be in the testgroup.

Tip

-m creates home dir at /home/

Note

Which groups will a new user have?

Home directories

  • Each user can have a home dir, which by default is located at /home/<username>.

  • Root user’s home dir is not located on /home/root but on /root

amsa@amsa: sudo ssh-keygen
Generating public/private ed25519 key pair.
Enter file in which to save the key (/root/.ssh/id_ed25519):

Important

It is important to understand when to run commands with root and when not to, do not prepend sudo unless you truly want it for root. As a rule of thumb, avoid using root if you can.

Tip

Running the command cd without specifying which directory do we want to go to will take us to our home dir.

Switching users

To switch to another user, we do not need to log out and log back in as the other user. Instead, it is possible to switch user temporarily from the terminal.

# Switch to test user (will ask for `test` user password)
su test

# Using sudo (will ask for our user password)
sudo su test

Note

Why does the first command ask for test user password and the second one ask for our password?

Tip

Use the whoami command to check which is your current user.

File permissions

File permissions model

ls -l /etc/hosts
# -rw-r--r-- 1 root   root  ... /etc/hosts
#  ^  ^  ^     ^      ^
#  u  g  o     owner  group
  • u/g/o → user / group / others
  • r/w/x → read / write / execute

Changing permissions and ownership

To modify permissions we are going to use chmod command.

chmod u+x script.sh 
# User can execute

chmod g-w,o-r private.txt 
# Group can't write, others can't read

chmod -R o-r /home/amsa
# Other can't read on any file/folder under and including `/home/amsa`

For permissions, chown command is used.

sudo chown amsa:amsa myfile.txt
# Now both owner and group are `amsa`

sudo chown -R test:amsa /home/test
# Now owner is test and group is amsa for any file here

We can also use number codes

Just so you know, instead of changing permissions by using their letters, they can also be referred to using numbers.

Permission Value
Read 4
Write 2
Execute 1
No perm 0

So for example, this two commands are equivalent:

chmod u=rwx,g=rx,o=r myscript.sh
chmod 755 myscript.sh

Just one more thing: directories

  • You may have noticed there that before the three groups of permissions, there is a character that can be a d or a -. This indicates if the file is a directory or not.

  • For directories, r means you can list files, w means you can create/delete files, and x means you can enter the directory.

Sudo part 2

Surprise, one more permission: setuid and setgid bits

  • When they are set on an executable file, the process will run with the file owner or group, not the ones of the user who executed the file.
  • When setgid is set on a directory, files created inside inherit the group of the directory. setuid has no effect on directories.
chmod u+s /usr/bin/passwd
chmod g+s /shared_dir

Note

If both bits are set on a file, the process runs with both user and group of the file.

Let’s see an example

We’ll create a little c program that prints the user that owns the process when executed.

#include <stdio.h>
#include <unistd.h>
#include <pwd.h>
int main() {
    printf("This processes is owned by user: %s\n", getpwuid(geteuid())->pw_name);
    return 0;
}

Compile and set ownership.

gcc -o test test.c
sudo chown amsa:amsa test

Now, let’s see what happens when we run it

We’ll run it with sudo, which will make the process be owned by root.

amsa@amsa:~$ sudo ./test
This processes is owned by user: root

Now we set the setuid bit and run it again, which will make the process be owned by amsa, the owner of the file.

amsa@amsa:~$ sudo chmod u+s test
amsa@amsa:~$ sudo ./test
This processes is owned by user: amsa

What sudo actually does

If we take a look at the sudo binary, which we can find by running which sudo, we can see that it has the setuid bit set and is owned by root.

So, if sudo is a process that will be owned by root, if it executes another process, that process will also be owned by root.

Sudoers/wheel

  • Okay, but if anyone can run sudo, then anyone can do anything as root!
  • To prevent this, we only users in certain groups can run sudo.
  • This is configured in /etc/sudoers file, where we’ll usually find a line like this:
%wheel ALL=(ALL) ALL
  • This means that any user in the wheel group can run any command as any user on any host.

Note

Ubuntu does not use wheel group, but sudo or adm instead. The name wheel comes from early Unix systems, and it was chosen because it was a “big wheel” group with special privileges, “big wheel” being a slang term for an important person.

File systems

What is a filesystem?

  • For a disk in our computer to be usable, it needs to be formatted with a filesystem.
  • A filesystem is a way of organizing and storing files on a storage device (like a hard drive or SSD).
  • Different filesystems have different features, performance characteristics, and compatibility with operating systems.

Common file systems

Filesystem Use case Notes
ext4 General Linux systems Most common Linux filesystem
ext2 Older Linux systems No journaling
xfs High-performance systems Good for large files
btrfs Advanced features (snapshots, etc) Still maturing
vfat USB drives, cross-platform Compatible with Windows and macOS
ntfs Windows systems Read/write support in Linux
tmpfs Temporary files in RAM Very fast, data lost on reboot

Example: setting up ext4 on a usb

  • We’ll format a USB drive with ext4 filesystem. First of all We’ll use lsblk to identify the device. Make sure you identify it correctly, as using the wrong device can lead to data loss.

  • Then, we’ll use mkfs.ext4 to format it, and mount to mount it.

  • Assuming the partition is /dev/sdb1, we would do:

sudo mkfs.ext4 /dev/sdb1
sudo mkdir -p /mnt/amsa
sudo mount /dev/sdb1 /mnt/amsa

Warning

Formatting a drive will erase all data on it. Make sure to back up any important data before proceeding.

Systemd timers

Why timers?

  • A systemd timer schedules another systemd unit, usually a service.
  • The service defines what runs; the timer defines when it runs.
  • Timers use the same tools we already know: systemctl and journalctl.

Tip

Unlike a long-running daemon, a timer consumes almost no resources while it waits.

Two units, one job

amsa-demo.timer  ──activates──▶  amsa-demo.service
      when                         what
  • Units with the same base name are paired automatically.
  • The timer may also activate a differently named unit with Unit=.
  • A timer does not contain shell commands: ExecStart= belongs in the service.

1. Define what runs

Create /etc/systemd/system/amsa-demo.service:

[Unit]
Description=AMSA timer example

[Service]
Type=oneshot
User=amsa
ExecStart=/usr/bin/date --iso-8601=seconds

Note

Type=oneshot means the command runs once and exits. Its standard output goes to the systemd journal.

2. Define when it runs

Create /etc/systemd/system/amsa-demo.timer:

[Unit]
Description=Run the AMSA example every minute

[Timer]
OnBootSec=1min
OnUnitActiveSec=1min

[Install]
WantedBy=timers.target
  • OnBootSec= schedules the first run relative to boot.
  • OnUnitActiveSec= schedules the next run relative to the previous activation.
  • WantedBy=timers.target starts this timer automatically at boot when enabled.

Note

These options end in Sec because a number without a unit means seconds. Other time units are accepted too, such as 500ms, 2min, 1h, or 1day.

3. Load and start the timer

sudo systemctl daemon-reload
sudo systemctl enable --now amsa-demo.timer
  • daemon-reload makes systemd reread unit files.
  • --now also starts it immediately.

Important

Enable the timer, not the service. The timer starts the service when required.

Inspect timers and their output

# Show the next and previous activation times
systemctl list-timers --all

# Inspect this timer
systemctl status amsa-demo.timer

# Read the output from the service
journalctl -u amsa-demo.service

Tip

To test without waiting: sudo systemctl start amsa-demo.service.

Calendar schedules

Use OnCalendar= when a task must run at a wall-clock time:

[Timer]
OnCalendar=Mon..Fri 09:00
Persistent=true
Value Meaning
Mon..Fri 09:00 At 09:00 every Monday through Friday
daily Every day at 00:00 (midnight)
*-*-* 02:30:00 At 02:30 every day
Sat *-*-* 12:00:00 At 12:00 every Saturday

Here, * means “any value” in the year-month-day date fields, while .. specifies a range.

More on calendar schedules

Tip

See the official systemd.time calendar-event documentation for the complete OnCalendar= syntax and more examples. Also, you can check an expression before using with systemd-analyze calendar 'Mon..Fri 09:00'

Note

Persistent=true runs a missed calendar event when the timer becomes active again, for example after the machine was powered off.

Manage the timer

# Stop it now, but keep it enabled for the next boot
sudo systemctl stop amsa-demo.timer

# Stop it and disable future automatic starts
sudo systemctl disable --now amsa-demo.timer

# After editing either unit
sudo systemctl daemon-reload
sudo systemctl restart amsa-demo.timer

Warning

A system timer runs its service as root by default. Set User= when the task does not need root privileges.

Timer troubleshooting

systemctl status amsa-demo.timer
systemctl status amsa-demo.service
journalctl -u amsa-demo.timer -u amsa-demo.service
systemctl list-timers --all

Check these first:

  • Did you run daemon-reload after editing the files?
  • Is the timer active, and when is its next trigger?
  • Did the service run and fail?
  • Does ExecStart= use an absolute executable path?

Quiz

  • If you run sudo ssh-keygen, where do keys go and why?
  • Decode -rwxr-xr--.
  • And drwxr-sr-x?
  • What does the file /etc/passwd contain?
  • Which unit defines what runs, and which defines when?
  • How do you find the next activation time and the service output?
  • What does Persistent=true change?

References

Additional Exercices

  • Change a file’s permissions so only the owner can read/write it.
  • Find which user owns the most files in your system.
  • Create a timer that writes the current date to the journal every two minutes.

Activity 3.2

Ready to have some fun? Check out the second part of the third AMSA activity here!