Linux Kernel Architecture

(Jacob Rumans) #1

Chapter 11: Extended Attributes and Access Control Lists


it in more detail. It is, however, important to observe that they work independently of the underlying
filesystem.

Permission Checks


For permission checks that involve access control lists, the kernel usually needs support from the underly-
ing filesystems: Either they implementallpermission checks by themselves (via thepermissionfunction
ofstruct inode_operations), or they provide a callback method forgeneric_permission. The latter
method is preferred by most filesystems in the kernel.

The callback is used ingeneric_permissionas follows (note thatcheck_acldenotes the callback
function):

fs/namei.c
int generic_permission(struct inode *inode, int mask,
int (*check_acl)(struct inode *inode, int mask))
{
...
if (IS_POSIXACL(inode) && (mode & S_IRWXG) && check_acl) {
int error = check_acl(inode, mask);
if (error == -EACCES)
goto check_capabilities;
else if (error != -EAGAIN)
return error;
}
...
}

IS_POSIXACLchecks if the (mount-time) flagMS_POSIXACLis set signaling that ACLs need to be used.

Even if a filesystem provides a specialized function to perform the ACL permission check, the individual
routines usually boil down to some technical work like obtaining the ACL data. The real permission
checks are again delegated to the standard functionposix_acl_permissionprovided by the kernel.

Accordingly,posix_acl_permissionneeds to be discussed in more detail. Given a pointer to an inode,
a pointer to (the in-memory representation of) an access control list, and the right to check for (MAY_READ,
MAY_WRITEorMAY_EXECinmode), the function returns 0 if access is granted or an appropriate error code
otherwise. The implementation is as follows:

fs/posix_acl.c
int
posix_acl_permission(struct inode *inode, const struct posix_acl *acl, int want)
{
const struct posix_acl_entry *pa, *pe, *mask_obj;
int found = 0;

FOREACH_ACL_ENTRY(pa, acl, pe) {
switch(pa->e_tag) {
case ACL_USER_OBJ:
/* (May have been checked already) */
if (inode->i_uid == current->fsuid)
goto check_perm;
Free download pdf