Chapter 16: Linux Commands: Permissions (chmod, chown) and Links (ln)

Chapter Objectives

By the end of this chapter, you will be able to:

  • Understand the Linux file permission model, including user, group, and other access rights.
  • Analyze and interpret file permissions using the ls -l command.
  • Implement permission changes using chmod in both symbolic and octal notation.
  • Configure file and directory ownership using the chown and chgrp commands.
  • Create and differentiate between symbolic (soft) and hard links using the ln command.
  • Debug common permission-related errors and resolve broken links in an embedded environment.

Introduction

In the intricate world of Embedded Linux, the system’s stability, security, and reliability hinge on a foundational concept: file permissions. While seemingly basic, the mechanisms that control who can read, write, and execute files are the bedrock of the entire operating system. For an embedded engineer, mastering file permissions is not a trivial pursuit; it is a critical skill. Imagine a medical device where a logging process inadvertently gains the ability to modify a core calibration file, or a network appliance where a script accessible by a web server can be altered to execute malicious code. These scenarios, which could lead to catastrophic failure, are prevented by a robust and correctly implemented permission scheme.

This chapter delves into the essential commands that govern file access and organization: chmod, chown, and ln. We will move beyond simple command execution and explore the “why” behind these tools. You will learn how the Linux kernel decides whether to grant or deny access to a resource, a process that happens thousands of times a second on a running system. We will investigate how ownership dictates responsibility and control, a vital concept when managing system services and user-level applications on your Raspberry Pi 5. Furthermore, we will explore how file system links provide the flexibility to organize and share code, libraries, and configuration files without creating redundant, difficult-to-maintain copies. By mastering these commands, you will gain the ability to build more secure, organized, and professional embedded systems.

Technical Background

The Linux Security Model: A Triad of Permissions

At the heart of the Linux operating system lies a simple yet powerful security model built upon three layers of access control for every file and directory. This model is often referred to as the UGO model, which stands for User, Group, and Other. To understand any file’s permissions, you must first understand these three entities and the rights they can be granted.

The User is the owner of the file. By default, the user who creates a file becomes its owner. The owner has the most direct control and is typically the primary person or process responsible for the file’s content and purpose.

The Group is a collection of users who share a common set of permissions for the file. This is an incredibly powerful concept for collaborative projects or for granting specific access to system services. For instance, you might have a group called developers that has write access to all source code files, or a group named www-data that has read access to web server content. A file can only belong to one group at a time, but a user can be a member of multiple groups.

Finally, Other refers to everyone else—any user on the system who is not the file’s owner and does not belong to the file’s group. This category represents the “rest of the world” and is typically granted the most restrictive permissions.

graph TD
    subgraph "File: script.sh"
        direction LR
        UGO --> User
        UGO --> Group
        UGO --> Other
    end

    subgraph Permissions
        direction TB
        User_Perms["<b>User (Owner)</b><br><i>r w x</i>"]
        Group_Perms["<b>Group</b><br><i>r - x</i>"]
        Other_Perms["<b>Other</b><br><i>r - -</i>"]
    end

    User -- "Has Permissions" --> User_Perms
    Group -- "Has Permissions" --> Group_Perms
    Other -- "Has Permissions" --> Other_Perms
    
  
    UGO("<b>U G O</b><br>Permission<br>Structure")
    
    classDef user fill:#8b5cf6,stroke:#8b5cf6,stroke-width:1px,color:#ffffff
    classDef group fill:#0d9488,stroke:#0d9488,stroke-width:1px,color:#ffffff
    classDef other fill:#f59e0b,stroke:#f59e0b,stroke-width:1px,color:#ffffff
    
    class User,User_Perms user
    class Group,Group_Perms group
    class Other,Other_Perms other

For each of these three entities (User, Group, Other), there are three fundamental permissions that can be granted or denied:

  1. Read (r): The ability to view the contents of a file or, for a directory, to list its contents.
  2. Write (w): The ability to modify or delete a file. For a directory, this permission allows creating, deleting, or renaming files within that directory.
  3. Execute (x): The ability to run a file as a program or script. For a directory, the execute permission is crucial; it grants the ability to cd into the directory and access its files and subdirectories. Without execute permission on a directory, even if you have read permission, you cannot access its contents.

When you view a file’s permissions with the ls -l command, you see a 10-character string that represents this entire model.

The first character indicates the file type (e.g., - for a regular file, d for a directory, l for a symbolic link). The next nine characters are the core of the permission model, organized into three sets of three: rwx for the User, rwx for the Group, and rwx for the Other. If a permission is not granted, its place is held by a hyphen (-). For example, rwxr-xr-- means the User has read, write, and execute permissions; the Group has read and execute permissions; and Other has only read permission.

Changing Permissions with chmod: The Gatekeeper’s Keys

The chmod (change mode) command is your primary tool for modifying these permissions. It offers two distinct but equally powerful methods for defining access rights: symbolic notation and octal notation.

Octal Code Symbolic Equivalent (rwx) Meaning (User, Group, Other) Common Use Case
755 -rwxr-xr-x U: Read, Write, Execute
G: Read, Execute
O: Read, Execute
Executable files and scripts that need to be run by anyone, but only modified by the owner. Standard for programs in /bin or /usr/bin.
644 -rw-r–r– U: Read, Write
G: Read
O: Read
Regular data files that are not executable. Allows the owner to modify the file, while everyone else can only read it. Default for most text files.
700 -rwx—— U: Read, Write, Execute
G: None
O: None
A private script that only the owner should be able to execute and modify. Provides strong isolation.
600 -rw——- U: Read, Write
G: None
O: None
Sensitive data files that should only be accessible by the owner (e.g., SSH private keys, configuration files with passwords).
664 -rw-rw-r– U: Read, Write
G: Read, Write
O: Read
Files that need to be modified by both the owner and members of the file’s group. Useful for collaborative projects.
775 -rwxrwxr-x U: Read, Write, Execute
G: Read, Write, Execute
O: Read, Execute
Directories where group members need to create, delete, and modify files. Common for shared web server directories.

Symbolic notation is more verbose but arguably more intuitive for making specific, targeted changes. It uses a combination of characters to represent the entities, the operation, and the permissions.

  • Entities (Who): u (user), g (group), o (other), a (all – u, g, and o).
  • Operation (Action): + (add permission), - (remove permission), = (set exact permissions).
  • Permissions (What): r (read), w (write), x (execute).

Using this syntax, you can construct commands that read like sentences. For example, chmod u+x myfile.sh translates to “for the user, add the execute permission to myfile.sh.” Similarly, chmod go-w config.txt means “for the group and other, remove the write permission from config.txt.” The = operator is useful for setting permissions explicitly, wiping out the existing ones. chmod a=r data.log sets the permissions so that everyone has read-only access, regardless of the previous settings.

Octal (or numeric) notation is a more concise and often faster way to set permissions, especially when you want to define all nine permission bits at once. It is the preferred method for many experienced developers and is commonly seen in scripts and documentation. This method is based on the binary representation of the rwx bits.

Each permission is assigned a numeric value:

  • r (read) = 4
  • w (write) = 2
  • x (execute) = 1

To determine the octal value for a single entity (User, Group, or Other), you simply add the values of the permissions you want to grant.

  • --- = 0
  • --x = 1
  • -w- = 2
  • -wx = 3 (2 + 1)
  • r-- = 4
  • r-x = 5 (4 + 1)
  • rw- = 6 (4 + 2)
  • rwx = 7 (4 + 2 + 1)

A complete chmod command using octal notation uses a three-digit number representing the permissions for User, Group, and Other, in that order. For example, the command chmod 754 script.sh sets the following permissions:

  • User: 7 (rwx)
  • Group: 5 (r-x)
  • Other: 4 (r--)

This translates to the permission string -rwxr-xr--. Common and useful octal codes include 755 for executable scripts and programs that should be readable by others, and 644 for data files that should be writable only by the owner but readable by everyone. For sensitive files, 600 ensures that only the owner can read and write the file, providing a strong layer of privacy.

Establishing Ownership with chown: The Deed to the File

While chmod controls what can be done with a file, the chown (change owner) command determines who owns it. Ownership is a fundamental aspect of system administration and security. In an embedded context, processes often run as specific, unprivileged users to limit their potential to cause harm if compromised. For example, a web server might run as the user www-data, and it needs to own or have group access to the files it serves.

The chown command’s basic syntax is chown <new_owner> <file>. For instance, chown pi my_app would transfer ownership of the my_app file to the user pi.

A powerful feature of chown is its ability to change both the user and the group owner simultaneously. This is done by specifying the user and group separated by a colon (:). The command chown pi:developers main.c changes the user owner to pi and the group owner to developers. If you only want to change the group, you can use the chgrp command (chgrp developers main.c) or, more concisely, use chown with a leading colon: chown :developers main.c.

graph TD
    A[Start: Check Initial Ownership] --> B{"File: "my_app/config.ini""};
    B -- "ls -l" --> C["Owner: <b>pi</b><br>Group: <b>pi</b>"];

    C --> D["Execute Command:<br><i>sudo chown -R appuser:appgroup my_app/</i>"];
    
    D --> E{"Decision: Is -R (Recursive) flag used?"};
    E -- Yes --> F[Apply to 'my_app' directory AND<br>all files/subdirectories within it];
    E -- No --> G[Apply to 'my_app' directory ONLY];

    F --> H{Result: Check Final Ownership};
    G --> H;
    
    H -- "ls -l my_app/config.ini" --> I["Owner: <b>appuser</b><br>Group: <b>appgroup</b>"];
    I --> J[End: Ownership Transferred];

    classDef startNode fill:#1e3a8a,stroke:#1e3a8a,stroke-width:2px,color:#ffffff
    classDef processNode fill:#0d9488,stroke:#0d9488,stroke-width:1px,color:#ffffff
    classDef decisionNode fill:#f59e0b,stroke:#f59e0b,stroke-width:1px,color:#ffffff
    classDef checkNode fill:#ef4444,stroke:#ef4444,stroke-width:1px,color:#ffffff
    classDef endNode fill:#10b981,stroke:#10b981,stroke-width:2px,color:#ffffff
    
    class A,J startNode;
    class D,F,G processNode;
    class E decisionNode;
    class B,C,H,I checkNode;

The -R (recursive) option is indispensable when working with directories. chown -R pi:pi /opt/my_application will change the ownership of the my_application directory and every file and subdirectory within it to the user pi and group pi. This is a common operation after unpacking an application archive or when setting up a service’s runtime environment.

Warning: Using chown requires superuser privileges (sudo) because changing a file’s owner has significant security implications. A regular user cannot simply give away their file to another user, nor can they take ownership of a file that doesn’t belong to them.

Creating Aliases with ln: Pointers in the Filesystem

The Linux filesystem provides a powerful mechanism for creating references, or “links,” to files. This allows a single file to be accessed from multiple locations in the directory tree without creating duplicate copies of the data. This is essential for creating organized filesystem layouts, managing shared libraries, and deploying applications. There are two types of links: hard links and symbolic (or soft) links. Understanding the difference is crucial.

A hard link is essentially a second name for a file. Both the original name and the hard link point to the same inode, which is the data structure on the disk that stores the file’s metadata (permissions, ownership, size, and pointers to the actual data blocks). Because they point to the same inode, a hard link is indistinguishable from the original file. If you delete the original file, the hard link still works because the inode and the data remain on the disk until all links to that inode are removed.

graph TD
    subgraph Filesystem View
        A["/path/to/<b>original_file</b>"]
        B["/path/to/<b>hard_link</b>"]
        C["/path/to/<b>symbolic_link</b>"]
    end

    subgraph Disk Storage
        D{Inode 12345}
        E["Data Blocks <br><i>File Content</i>"]
        F{Inode 56789}
        G["Path Data <br><i>/path/to/original_file</i>"]
    end

    A -- "Points to" --> D
    B -- "Points to" --> D
    D -- "Contains pointer to" --> E

    C -- "Points to" --> F
    F -- "Contains pointer to" --> G
    G -.-> A

    classDef default fill:#f8fafc,stroke:#64748b,stroke-width:2px,color:#1f2937
    classDef inode fill:#8b5cf6,stroke:#8b5cf6,stroke-width:1px,color:#ffffff
    classDef data fill:#0d9488,stroke:#0d9488,stroke-width:1px,color:#ffffff
    classDef path fill:#eab308,stroke:#eab308,stroke-width:1px,color:#1f2937

    class D,F inode
    class E,G data
    
    style A fill:#1e3a8a,stroke:#1e3a8a,stroke-width:2px,color:#ffffff
    style B fill:#1e3a8a,stroke:#1e3a8a,stroke-width:2px,color:#ffffff
    style C fill:#f59e0b,stroke:#f59e0b,stroke-width:1px,color:#ffffff

However, hard links have two significant limitations:

  1. They cannot span across different filesystems (partitions). The link and the file must reside on the same disk partition because inodes are unique only within a single filesystem.
  2. You cannot create a hard link to a directory. This is a design choice to prevent the creation of confusing and potentially infinite directory loops.

A symbolic link (or symlink) is a more flexible and common type of link. Instead of pointing to an inode, a symlink is a special type of file whose content is simply the path to another file or directory. It’s a pointer, or a shortcut.

graph LR
    subgraph Application
        App["Application Binary"]
    end

    subgraph Filesystem Layout in /usr/lib
    direction TB
        A("<b>libcrypto.so</b><br><i>Generic Name</i>")
        B("<b>libcrypto.so.1.1</b><br><i>Versioned Name</i>")
        C("<b>libcrypto-1.1.1k.so</b><br><i>Actual File</i>")
    end

    App -- "Links against" --> A
    A -- "Symlink ->" --> B
    B -- "Symlink ->" --> C

    click A "#" "Generic symlink used by the linker at compile time."
    click B "#" "Major version symlink. Allows multiple minor versions to exist."
    click C "#" "The actual, physical library file."

    classDef default fill:#f8fafc,stroke:#64748b,stroke-width:2px,color:#1f2937
    classDef app fill:#1e3a8a,stroke:#1e3a8a,stroke-width:2px,color:#ffffff
    classDef link fill:#f59e0b,stroke:#f59e0b,stroke-width:1px,color:#ffffff
    classDef file fill:#0d9488,stroke:#0d9488,stroke-width:1px,color:#ffffff

    class App app
    class A,B link
    class C file

When the operating system accesses a symlink, it reads the path stored within it and then follows that path to the destination file. This provides several advantages:

  • Symlinks can point to files on different filesystems.
  • Symlinks can point to directories.
  • It’s always clear which file is the link and which is the original.

The primary drawback of a symlink is its dependency. If the original file is deleted or moved, the symlink becomes “broken” or “dangling.” It still exists, but it points to a location that no longer contains the target file.

The ln command is used to create both types of links. The syntax is ln [options] <target> <link_name>.

  • To create a hard link: ln /path/to/original /path/to/hardlink
  • To create a symbolic link, you use the -s flag: ln -s /path/to/original /path/to/symlink

In embedded systems, symlinks are used extensively. The shared library loader (ld.so) uses symlinks to manage library versions (e.g., libc.so.6 might be a symlink to libc-2.35.so). Application launchers in /usr/bin are often symlinks to the actual executables stored elsewhere, such as in /opt/app/bin. This allows for clean updates; you can install a new version of an application in its own directory and then atomically update the symlink in /usr/bin to point to the new executable, minimizing downtime.

Practical Examples

This section provides hands-on, step-by-step examples for managing permissions and links on your Raspberry Pi 5. Open a terminal to follow along.

Example 1: Managing Script Permissions with chmod

Let’s create a simple shell script and manage its permissions. A common task is to make a script executable only by its owner.

1. Create the Script File

First, create a new directory for our work and create a script file inside it.

Bash
# Create a directory for our chapter work
mkdir ~/ch16_examples
cd ~/ch16_examples

# Create a simple shell script using the nano editor
nano myscript.sh

Inside nano, type the following lines:

Bash
#!/bin/bash
# This is a simple script for our chmod example.
echo "Hello, Embedded Linux World!"
echo "Running as user: $(whoami)"

Press Ctrl+X, then Y, then Enter to save and exit.

2. Examine Initial Permissions

Now, let’s look at the default permissions assigned to the new file.

Bash
ls -l myscript.sh

Expected Output:

Bash
-rw-r--r-- 1 pi pi 103 Jul 08 21:45 myscript.sh

The output shows that the owner (pi) has read and write permissions (rw-), while the group (pi) and others have only read permission (r--). Crucially, no one has execute (x) permission. If you try to run it, you’ll get an error.

Bash
./myscript.sh

Expected Output:

Bash
bash: ./myscript.sh: Permission denied

3. Make the Script Executable (Symbolic Method)

Let’s add execute permission for the user (owner) only.

Bash
chmod u+x myscript.sh

Now, check the permissions again:

Bash
ls -l myscript.sh

Expected Output:

Bash
-rwxr--r-- 1 pi pi 103 Jul 08 21:45 myscript.sh

The x has been added to the user’s permission block. Now the script will run successfully.

Bash
./myscript.sh

Expected Output:

Bash
Hello, Embedded Linux World!
Running as user: pi

4. Set Permissions with Octal Notation

A more common permission set for a script that is safe for others to run (but not modify) is 755. This gives the owner full control (rwx), while the group and others can read and execute (r-x).

Bash
# Let's first reset permissions to something else
chmod 644 myscript.sh

# Now set them using octal notation
chmod 755 myscript.sh

# Verify the result
ls -l myscript.sh

Expected Output:

Bash
-rwxr-xr-x 1 pi pi 103 Jul 08 21:45 myscript.sh

This single command precisely sets all nine permission bits to the desired state, demonstrating the efficiency of the octal method.

Example 2: Managing Ownership with chown

Imagine you are deploying an application that will be run by a dedicated service user. For security, the application’s files should be owned by that user.

1. Create a New User and Group

First, we need to create a new user for our application. We’ll call the user appuser. The adduser command will also create a corresponding group.

Tip: You need sudo to create users and change ownership to other users.

Bash
sudo adduser --system --no-create-home appuser

The --system flag creates a system user, which is appropriate for running services. --no-create-home prevents the creation of a home directory, as it’s not needed.

2. Create Application Files

Let’s create a mock application directory and a configuration file.

Bash
# As the 'pi' user
mkdir -p my_app/config
touch my_app/config/settings.conf
touch my_app/app.bin

# Check initial ownership
ls -ld my_app
ls -l my_app/config/settings.conf

Expected Output:

You will see that the owner and group for all these files is pi.

Bash
drwxr-xr-x 2 pi pi 4096 Jul 08 21:45 my_app
-rw-r--r-- 1 pi pi    0 Jul 08 21:45 my_app/config/settings.conf

3. Change Ownership Recursively

Now, let’s transfer ownership of the entire application directory to our new appuser.

Bash
# Use sudo to change ownership to another user
# The -R flag makes the change recursive
sudo chown -R appuser:appuser my_app/

# Verify the new ownership
ls -ld my_app
ls -l my_app/config/settings.conf
ls -l my_app/app.bin

Expected Output:

The owner and group for the directory and all its contents are now appuser.

Bash
drwxr-xr-x 2 appuser appuser 4096 Jul 08 21:45 my_app
-rw-r--r-- 1 appuser appuser    0 Jul 08 21:45 my_app/config/settings.conf
-rw-r--r-- 1 appuser appuser    0 Jul 08 21:45 my_app/app.bin

This is a critical step in securing an embedded application. By ensuring files are owned by the correct unprivileged user, you limit the “blast radius” if that application is ever compromised.

Example 3: Using Symbolic and Hard Links with ln

This example will demonstrate the practical differences between hard and symbolic links.

1. Create a Source File

First, create a file that will be the target of our links.

Bash
echo "This is the original data." > original_file.txt

2. Create a Hard Link

Now, create a hard link to this file.

Bash
ln original_file.txt hardlink.txt

# List the files with their inode numbers
ls -li

Expected Output:

Notice that original_file.txt and hardlink.txt have the exact same inode number (the number in the first column). They also have the same permissions, owner, and size. The number 2 in the third column is the link count—it indicates that two directory entries point to this inode.

Bash
131252 -rw-r--r-- 2 pi pi 27 Jul 08 21:45 hardlink.txt
131252 -rw-r--r-- 2 pi pi 27 Jul 08 21:45 original_file.txt

3. Create a Symbolic Link

Next, create a symbolic link to the original file.

Bash
ln -s original_file.txt symlink.txt

# List the files again
ls -li

Expected Output:

The symbolic link has its own unique inode number. Its file type is l, and its size is small (the number of characters in the path it stores). The link count of the original file remains 2.

Bash
131252 -rw-r--r-- 2 pi pi   27 Jul 08 21:45 hardlink.txt
131252 -rw-r--r-- 2 pi pi   27 Jul 08 21:45 original_file.txt
131253 lrwxrwxrwx 1 pi pi   19 Jul 08 21:45 symlink.txt -> original_file.txt

4. Test the Behavior When Deleting the Original

This is where the difference becomes clear. Let’s remove the original file.

Bash
rm original_file.txt

# See what's left
ls -li

Expected Output:

  • The hard link hardlink.txt is unaffected. Its link count has dropped to 1, but it still points to the original data. You can view its contents with cat hardlink.txt.
  • The symbolic link symlink.txt is now broken. ls will often color it red to indicate this. It still points to the name original_file.txt, but that file no longer exists.
Bash
131252 -rw-r--r-- 1 pi pi   27 Jul 08 21:45 hardlink.txt
131253 lrwxrwxrwx 1 pi pi   19 Jul 08 21:45 symlink.txt -> original_file.txt

If you try to cat symlink.txt, you will get a “No such file or directory” error. This experiment clearly illustrates that hard links are direct references to data, while symbolic links are references to a name.

Common Mistakes & Troubleshooting

Even experienced developers can stumble over permission and link issues. Here are some common pitfalls and how to navigate them.

Mistake / Issue Symptom(s) Troubleshooting / Solution
Using chmod 777 as a quick fix. An application fails with a Permission denied error. The “fix” works but introduces a massive security hole. Follow the Principle of Least Privilege.
1. Identify the user/group that needs access (e.g., appuser).
2. Set correct ownership: sudo chown -R appuser:appuser /path/to/app.
3. Set minimal permissions: chmod 755 for executables, 640 for configs.
Forgetting execute (x) permission on directories. A user has read (r) permission on a directory but gets Permission denied when trying to cd into it or ls -l its contents. Add execute permission to the directory.
The x bit on a directory allows it to be traversed. To allow users to enter a directory and access files, they need r-x.
Example: chmod g+x /shared/data
Creating absolute instead of relative symlinks. A symlink like ln -s /home/pi/app/lib.so ... works on the dev machine, but breaks when the app directory is moved to /opt/ on the target. Use relative paths for relocatable code.
Change into the directory where the link will live and use a relative path from there.
Example: cd /opt/app/bin
ln -s ../lib/lib.so .
Editing a symlink instead of its target file. You edit a config file via a symlink, e.g., nano /etc/app.conf. After saving, the link is gone and is now a regular file. The original file is unchanged. Always resolve the link’s path first.
1. Check if it’s a link: ls -l /etc/app.conf.
2. Find the real file: readlink -f /etc/app.conf.
3. Edit the real file directly to ensure changes are applied correctly.
Ownership issues after extracting an archive. You extract a .tar.gz file as root. All the extracted files are owned by root:root, and the application user cannot access them. Recursively change ownership after extraction.
After extracting, immediately run chown to set the correct ownership for the application’s dedicated user.
sudo chown -R appuser:appgroup /opt/my_new_app

Exercises

  1. Basic Permissions Practice:
    • Objective: Practice using chmod with both symbolic and octal notation.
    • Steps:
      1. Create a file named data.txt.
      2. Use ls -l to view its default permissions.
      3. Using symbolic notation, remove all permissions for the “other” group.
      4. Using symbolic notation, add write permission for the “group”.
      5. Using octal notation, set the permissions so the owner can read/write, the group can only read, and others have no permissions (640).
    • Verification: Use ls -l data.txt after each step to confirm the permissions have changed as expected.
  2. Securing a Log Directory:
    • Objective: Create a directory structure for logs that can only be written to by its owner but can be read by a specific group.
    • Steps:
      1. Create a new group called auditors (sudo addgroup auditors).
      2. Add your current user (pi) to this group (sudo usermod -aG auditors pi). You will need to log out and log back in for the group change to take effect.
      3. Create a directory named log_archive.
      4. Change the ownership of log_archive so it is owned by the pi user and the auditors group.
      5. Set the permissions on the directory so that only the owner can create and delete files within it, but members of the auditors group can list and read files inside. (Hint: This requires a specific combination of r, w, and x permissions on the directory itself).
    • Verification: Try to create a file in the directory as the pi user (should succeed). As a different user (if one exists) or by changing the permissions temporarily, verify that non-owners/non-group members cannot access it.
  3. Shared Library Symlink Management:
    • Objective: Simulate the management of shared library versions using symbolic links.
    • Steps:
      1. Create a directory structure: mkdir -p my_app/lib.
      2. Inside lib, create two dummy library files: touch libfoo.so.1.0 and touch libfoo.so.1.1.
      3. Create a symbolic link named libfoo.so.1 that points to libfoo.so.1.0.
      4. Create another symbolic link named libfoo.so that points to libfoo.so.1. This is a common pattern.
      5. Use ls -l to view the chain of links.
      6. “Upgrade” the library by changing the libfoo.so.1 link to point to libfoo.so.1.1. (Hint: You may need to remove the old link first, or use ln -sf to force the update).
    • Verification: Use ls -l lib and readlink -f my_app/lib/libfoo.so to verify that the final link now resolves to libfoo.so.1.1.
  4. Hard Link Inode Investigation:
    • Objective: Deepen understanding of how hard links relate to inodes and data.
    • Steps:
      1. Create a file named original_data.txt with some text in it.
      2. Use ls -li to find its inode number.
      3. Create a hard link to it named hard_link_copy.txt.
      4. Verify with ls -li that both files share the same inode and the link count is 2.
      5. Edit the contents of hard_link_copy.txt.
      6. Use cat to view the contents of original_data.txt.
    • Verification: Observe that the content of original_data.txt has also changed. This demonstrates that both names point to the exact same data on the disk.
  5. Troubleshooting a Broken Link:
    • Objective: Learn to identify and fix a broken symbolic link.
    • Steps:
      1. Create a file config.json in a directory named conf.
      2. In a separate directory named bin, create a symbolic link named app_config that points to ../conf/config.json.
      3. Verify the link works with ls -l bin/app_config.
      4. Now, rename the conf directory to cfg.
      5. Run ls -l bin/app_config again.
    • Verification: Observe that the link is now broken (often shown in red). Fix the link by removing the old one and creating a new one that points to the correct, new path.

Summary

  • Permissions are fundamental to the security and stability of any Linux system, including embedded devices.
  • The UGO model (User, Group, Other) combined with Read, Write, Execute permissions (rwx) forms the core of file access control.
  • The ls -l command is your essential tool for analyzing file permissions, ownership, and link status.
  • chmod modifies permissions using either intuitive symbolic notation (u+x) or efficient octal notation (755).
  • chown and chgrp manage ownership, a critical step for securing applications by assigning files to unprivileged service accounts.
  • Hard links act as multiple names for the same file inode, cannot cross filesystems, and persist even if the original name is deleted.
  • Symbolic links are pointers to a file path, are highly flexible, can cross filesystems and point to directories, but will break if the target is moved or deleted.
  • Adhering to the Principle of Least Privilege and using relative paths for links within deployable applications are key best practices.

Further Reading

  1. The Linux Command Line, 2nd Edition by William Shotts – An excellent, comprehensive guide to the shell, including a detailed chapter on permissions.
  2. Linux man pages: The official documentation built into your system. Access them with man chmod, man chown, and man ln. They are the ultimate source of truth.
  3. Raspberry Pi Documentation – The Linux command line: Official tutorials from the Raspberry Pi Foundation.
    https://www.raspberrypi.com/documentation/computers/remote-access.html#command-line
  4. GNU Coreutils Manual: The official documentation for the core utilities (chmod, chown, ln, etc.). (https://www.gnu.org/software/coreutils/manual/coreutils.html)
  5. How To Manage File Permissions in Linux – A well-written tutorial from DigitalOcean covering the basics with clear examples. (https://www.digitalocean.com/community/tutorials/how-to-manage-file-permissions-in-linux)
  6. Understanding Linux File Permissions – A detailed article from Red Hat that provides a solid overview of the concepts. (https://docs.redhat.com/en/documentation/red_hat_enterprise_linux/4/html/reference_guide/s2-nfs-security-files)

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top