Linux Restrictions, Limits and File System Specifics Explained

 

Linux Restrictions, Limits and File System Specifics Explained

Part 2 —Linux Restrictions, Limits and File System Specifics Explained

255 chars
Max name length
64 KB
Max value size (VFS)
1 disk block
Total limit on ext*
128 KB
Total limit on JFS

Key Terms

VFS (Virtual File System) disk block sticky bit EACCES symbolic link device file FIFO socket unprivileged process os2 namespace

Why Restrictions Exist

Not all file types can carry user EAs. Not all file systems give you the same amount of storage. The Linux VFS layer defines the maximum possible limits, and individual file systems can be more restrictive. Understanding these limits prevents surprising errors at runtime.

Which File Types Can Have User EAs?

User EAs can only be placed on regular files and directories. All other file types are excluded.

File Type User EA Allowed? Reason if Not Allowed
Regular file (-rw-r--r--) Normal permissions apply
Directory (drwxr-xr-x) ✓ * Allowed, but sticky bit restriction applies
Symbolic link (lrwxrwxrwx) Permissions are always 777 and can’t be changed — can’t use permissions to control EA access
Device file (crw-, brw-) Permissions control I/O access — using them for EAs would conflict
Socket (s---) Same reason as device file — permissions serve I/O purpose
FIFO / Named pipe (p---) Same reason as device file

Why Symbolic Links Cannot Have User EAs

On Linux, symbolic links always have permissions lrwxrwxrwx (0777). These permissions have no enforcement meaning — the kernel ignores them. The actual permission check happens on the target file when the symlink is dereferenced.

The problem: EA access control depends on file permissions. If a symlink’s permissions can’t be restricted, then any user could set user EAs on any symlink — there’s no way to say “only the owner can modify this symlink’s EAs”.

The kernel’s solution: Simply ban user EAs on symlinks entirely.

/* This will fail with EPERM (operation not permitted) */
#include <sys/xattr.h>
#include <stdio.h>
#include <string.h>

int main() {
    /* Create a symlink first */
    symlink("/etc/passwd", "/tmp/my_symlink");

    /* Try to set a user EA on the symlink (NOT the target) */
    const char *val = "test";
    int ret = lsetxattr("/tmp/my_symlink", "user.tag", val, strlen(val), 0);
    if (ret == -1) {
        perror("lsetxattr on symlink");
        /* Output: lsetxattr on symlink: Operation not permitted */
    }
    return 0;
}
Note: lsetxattr() is the variant that does NOT dereference symlinks. setxattr() would follow the symlink and set the EA on the target file instead.

Directories: The Sticky Bit Restriction

Even though directories support user EAs, there is a special restriction: an unprivileged process cannot set user EAs on a directory owned by another user if the sticky bit is set on that directory.

Directory ownership & sticky bit scenarios
Scenario A — Allowed

Directory owner: ravi
Sticky bit: Not set
Process user: alice
Directory perms: drwxrwxrwx

✓ Alice can set user EAs

Scenario B — Allowed

Directory owner: alice
Sticky bit: Set
Process user: alice (owner)
Directory perms: drwxrwxrwt

✓ Alice owns it — allowed

Scenario C — Blocked

Directory owner: ravi
Sticky bit: Set
Process user: alice
Directory perms: drwxrwxrwt

✗ EPERM — blocked

The sticky bit on a directory (like /tmp) means “users can’t delete other users’ files here”. The same logic extends to EAs: you can’t modify another user’s EA in a sticky directory.

# /tmp typically has the sticky bit set (shown as 't' in permissions)
$ ls -ld /tmp
drwxrwxrwt 20 root root 4096 Jan 10 09:00 /tmp

# Alice tries to set a user EA on a file owned by ravi inside /tmp
# This will fail with EPERM if /tmp has sticky bit
$ setfattr -n user.tag -v "hello" /tmp/ravis_file.txt
setfattr: /tmp/ravis_file.txt: Operation not permitted

Size Limits on Extended Attributes

Limits exist at two levels: the VFS layer (applies to all file systems) and individual file system limits (may be more restrictive).

Limit VFS Maximum Notes
EA name length 255 characters Includes the namespace prefix (e.g., “user.”)
EA value size 64 KB (65,536 bytes) Single EA value cannot exceed this

File System Specific Limits

File systems can impose tighter constraints than the VFS layer allows.

File System Total EA Bytes Per File Block Sizes Affected Calculation Note
ext2 / ext3 / ext4 1 disk block 1024, 2048, or 4096 bytes Sum of all EA names + values must fit in one block
JFS 128 KB More generous than ext*, also supports os2 namespace
XFS ~4 GB theoretical Practically limited by VFS 64 KB value limit
Btrfs Generous Modern CoW design, good EA storage

Visual: Total EA storage comparison per file

ext4 (4K)

4 KB

JFS

128 KB

VFS limit

64 KB (per single EA value)

Watch out on ext4! If you try to store many EAs on a single file, you will hit the 4096-byte (one disk block) total limit quickly. Each EA name + value + overhead counts toward this. On production systems, keep EAs small and minimal on ext4.

Checking & Handling Limits in C Code

When you call setxattr(), you may hit these limits. The kernel returns specific errors:

Error Code Meaning
ENOSPC No space left — per-file EA block is full (ext4)
E2BIG Value exceeds the 64 KB VFS limit
ERANGE Buffer too small when reading EA value
ENODATA EA with the given name does not exist
EPERM Operation not permitted (e.g., symlink, sticky dir)
EACCES Permission denied (no read/write on file)
ENOTSUP File system does not support EAs
#include <sys/xattr.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

/*
 * Safely set a user EA with proper error handling.
 * Returns 0 on success, -1 on failure.
 */
int safe_set_ea(const char *path, const char *ea_name, const char *value) {
    if (setxattr(path, ea_name, value, strlen(value), 0) == -1) {
        switch (errno) {
        case ENOSPC:
            fprintf(stderr, "Error: EA block full on this file (ext4 limit)\n");
            break;
        case E2BIG:
            fprintf(stderr, "Error: EA value too large (>64KB)\n");
            break;
        case EPERM:
            fprintf(stderr, "Error: Not permitted (symlink or sticky dir?)\n");
            break;
        case EACCES:
            fprintf(stderr, "Error: No write permission on file\n");
            break;
        case ENOTSUP:
            fprintf(stderr, "Error: File system does not support EAs\n");
            break;
        default:
            perror("setxattr");
            break;
        }
        return -1;
    }
    return 0;
}

int main() {
    /* Works fine: small value, regular file */
    safe_set_ea("/tmp/test.txt", "user.status", "active");

    /* This would fail on ext4 if EA block is already full */
    char big_value[5000];
    memset(big_value, 'A', sizeof(big_value) - 1);
    big_value[4999] = '\0';
    safe_set_ea("/tmp/test.txt", "user.big_data", big_value);

    return 0;
}

Checking EA Support at Runtime

Before your program relies on EAs, you can probe whether the file system supports them:

#include <sys/xattr.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>

/*
 * Returns 1 if the given path's filesystem supports user EAs.
 * Returns 0 if not supported.
 */
int ea_supported(const char *path) {
    /* Try to set a test EA */
    int ret = setxattr(path, "user.__ea_probe__", "1", 1, 0);
    if (ret == -1) {
        if (errno == ENOTSUP || errno == EOPNOTSUPP)
            return 0;
        /* Other errors (EACCES etc.) — FS supports EAs but we have other issues */
        if (errno == EACCES)
            return 1;  /* FS supports EAs, we just lack permission */
    } else {
        /* Clean up the test EA */
        removexattr(path, "user.__ea_probe__");
    }
    return 1;
}

int main() {
    const char *paths[] = { "/tmp/test.txt", "/proc/self", NULL };
    for (int i = 0; paths[i] != NULL; i++) {
        printf("EA support on '%s': %s\n",
               paths[i],
               ea_supported(paths[i]) ? "YES" : "NO");
    }
    return 0;
}

The os2 Namespace (JFS Only)

JFS supports a fifth namespace called os2, which is not available on any other Linux file system. It exists only to provide backward compatibility with OS/2 file system extended attributes.

  • Only available on JFS.
  • No privilege required to create os2 EAs.
  • Exists for legacy compatibility — not for new development.
In practice, you will almost never use the os2 namespace. It is there because JFS was ported from OS/2’s High Performance File System (HPFS) which natively supported extended attributes.

Interview Questions
Q1. What is the maximum size of an EA name and value according to the Linux VFS layer?
The VFS imposes a maximum EA name length of 255 characters (including the namespace prefix like “user.”) and a maximum EA value size of 64 KB (65,536 bytes). Individual file systems may be more restrictive.
Q2. Why is there a one-disk-block limit on EAs for ext2/ext3/ext4?
The ext* file systems store all EAs for a file in a single extra disk block attached to the i-node. The block size is typically 1024, 2048, or 4096 bytes. All EA names and values combined must fit within this one block. This is a design limitation of the ext* EA storage format, not the VFS layer.
Q3. Why can’t you place user EAs on device files or FIFOs?
For device files (character/block), sockets, and FIFOs, the file permissions serve a specific purpose: controlling which processes can perform I/O on the underlying object. Using these same permissions to control EA access would create a conflict. The kernel avoids this conflict by simply disallowing user EAs on these file types.
Q4. What errno do you get when the EA block is full on ext4?
ENOSPC — “No space left on device”. Even if the disk has plenty of space, the per-file EA block is full. You must remove existing EAs before adding new ones, or switch to a file system with more generous EA storage (e.g., XFS or JFS).
Q5. How does the sticky bit on a directory affect EA operations?
If a directory has the sticky bit set (like /tmp), an unprivileged process cannot set user EAs on a file in that directory if it is owned by a different user. The sticky bit is normally used to prevent users from deleting others’ files; this same protection extends to EA modification.
Q6. What is the os2 namespace and which file system supports it?
The os2 namespace is a special EA namespace supported only on JFS. It provides backward compatibility with OS/2 file system EAs. No privilege is needed to create os2 EAs. It is not available on any other Linux file system.

Leave a Reply

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