Preserving ACLs and EAs in editors and file managers

Technical Note

Andreas Gruenbacher <agruen@suse.de>, SuSE Labs, SuSE Linux AG

Last update: Tue Feb 18

Summary

Extended Attributes (EAs) and Access Control Lists (ACLs) are associated with files. If tools and applications like editors and file managers (Vi, Emacs, Konqueror, Nautilus, etc.) copy files or modify files by creating copies and replacing the original files, EAs and ACLs are lost. To avoid this, support for EAs and ACLs needs to be built into those applications.

Since the code for preserving EAs and ACLs is not completely trivial, library functions have been written, and should be used. This document describes how this can be done.

Important note
The interface of the check callback to the attr_copy_fd() and attr_copy_file() functions has recently changed: Now, the error context is passed as the second parameter.

The Problem

Access Control Lists are used to define more fine-grained file permissions than the file mode permission bits allow. Extended Attributes may be used for associating various pieces of information with files (such as a document's author, etc.). This information is associated with inodes on the file system. If instead of modifying an inode, another inode is allocated, the new inode does not share the same ACLs or EAs. If the new inode replaces the old one in the directory tree, from the user's point of view the file has lost that information.

Most applications should also preserve ACLs and EAs by copying them from one inode to the other. While cp has been modified to preserve ACLs, most other applications are not yet aware of ACLs. (Even cp is unaware of Extended Attributes at the moment.)

As the attr(5) manual page describes, there are currently three classes of Extended Attributes:

Loosing User Attributes may be anything from an annoyance to users to a problem for applications that rely on the attribute's presence.

Loosing Access Control Lists may result in slightly less restrictive permissions for the new file: The owning group of a file may accidentally be granted accesses that would be forbidden by the ACL. The reason for this is that with ACLs, the file mode permission bits define an upper bound on the permissions allowed; the group file mode permission bits define the maximum permissions granted to the owning group or to named users or groups. The effective permissions of the owning group may be more restrictive. If the ACL is lost, the group file mode permission bits are again used to determine the permissions of the owning group. Therefore, if the group file mode permission bits were set differently than the effective permissions of the owning group, the owning group will gain additional permissions.

(This is no problem if the file is owned by an owning group that contains only the file owner, which is the default configuration on some systems.)

Even though Access Control Lists are stored as Extended Attributes, the particular problem just described implies that copying ACLs requires some additional logic; they should not just be copied by copying the EAs that describe them. There are a few situations such as lack of ACL support on the source or target file system that merits attention.

Preserving all the remaining EAs is less complicated, but is also better coded once than individually in each application that needs it.

Scope of the problem

EAs and ACLs are part of the Linux kernel since 2.5.46. The 2.4.20 kernel has most of the EA infrastructure, but neither EA nor ACL support on file systems. Some vendor kernels such as the SuSE Linux 8.1 / SuSE Linux Enterprise Server 8 / United Linux 1 kernel, which are based on the 2.4.19 standard kernel, also have integrated EA and ACL support.

A lot of applications are affected by this problem.

Library functions for copying EAs and ACLs

Functions for copying EAs and ACLs have been added to the libattr and libacl libraries. All functions have a parameter or type “struct error_context *”. This structure is declared as follows:

If a NULL error_context is passed to the library functions, no error messages will be produced. Otherwise if an error occurs, the library functions call the error() handler with errno set to indicate the error. The quote() handler is used to quote special characters in path names or attribute names that are included in error messages. Each call to quote() with return value name is paired with a call to quote_free(name).

Copying Extended Attributes

The following functions have been added to the libattr library for copying Extended Attributes:

These functions copy EAs from one file (or file descriptor) to another. The patch name parameters of attr_copy_fd() are used in error messages only.

The check() callback is called once for each attribute of the source file with the attribute name (e.g., “user.author”). If check returns a non-zero value the attribute is copied, otherwise it is skipped. If check is NULL, the default behavior is to copy all EAs except Access Control Lists. This default behavior may change to exclude other System Attributes that require special treatment if any such attributes should be introduced.

The functions return 0 on success, and -1 otherwise. If the functions fail, errno is set to to indicate the error.

Copying Access Control Lists

The following functions have been added to the libacl library for copying Access Control Lists and preserving permissions:

These functions copy ACLs from one file (or file descriptor) to another. The patch name parameters of perm_copy_fd() are used in error messages only. If preserving ACLs fails, the permissions for the target file are set so that no permissions are granted that were not granted for the source file.

The functions return 0 on success, and -1 otherwise. If the functions fail, errno is set to to indicate the error.

Examples

copyattr.c: Copying Extended Attributes.

copyperm.c: Copying Access Control Lists.

editor.c: How an editor like application could implement preserving Access Control Lists itself. Note that this example makes assumptions that do not hold for EA/ACL copying in general. This code is for reference only; to not reuse.

ea-acl-copy.tar.gz: All of the above, plus Autoconf tests and a Makefile.

Patches

The following patches add the copying functions to the libattr and libacl libraries. The perm_copy patch applies cleanly on top of a couple of other patches that are awaiting CVS check in. The libattr patch should apply cleanly.

attr_copy.diff
perm_copy.diff

RPM Packages

SuSE Linux 8.1-i386 8.1-i386
SuSE Linux next-i386 next-i386

References

Manual pages: getfattr(1), setfattr(1), attr(5), getfacl(1), setfacl(1), acl(5).

SDB article “POSIX Access Control List (ACL) Support”, http://sdb.suse.de/en/sdb/html/81_acl.html