Skip to content

Commit

Permalink
[PATCH] Generic VFS fallback for security xattrs
Browse files Browse the repository at this point in the history
This patch modifies the VFS setxattr, getxattr, and listxattr code to fall
back to the security module for security xattrs if the filesystem does not
support xattrs natively.  This allows security modules to export the incore
inode security label information to userspace even if the filesystem does
not provide xattr storage, and eliminates the need to individually patch
various pseudo filesystem types to provide such access.  The patch removes
the existing xattr code from devpts and tmpfs as it is then no longer
needed.

The patch restructures the code flow slightly to reduce duplication between
the normal path and the fallback path, but this should only have one
user-visible side effect - a program may get -EACCES rather than
-EOPNOTSUPP if policy denied access but the filesystem didn't support the
operation anyway.  Note that the post_setxattr hook call is not needed in
the fallback case, as the inode_setsecurity hook call handles the incore
inode security state update directly.  In contrast, we do call fsnotify in
both cases.

Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
Acked-by: James Morris <jmorris@namei.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Stephen Smalley authored and Linus Torvalds committed Sep 5, 2005
1 parent b5bf6c5 commit f549d6c
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 228 deletions.
43 changes: 0 additions & 43 deletions fs/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -783,28 +783,6 @@ config SYSFS

Designers of embedded systems may wish to say N here to conserve space.

config DEVPTS_FS_XATTR
bool "/dev/pts Extended Attributes"
depends on UNIX98_PTYS
help
Extended attributes are name:value pairs associated with inodes by
the kernel or by users (see the attr(5) manual page, or visit
<http://acl.bestbits.at/> for details).

If unsure, say N.

config DEVPTS_FS_SECURITY
bool "/dev/pts Security Labels"
depends on DEVPTS_FS_XATTR
help
Security labels support alternative access control models
implemented by security modules like SELinux. This option
enables an extended attribute handler for file security
labels in the /dev/pts filesystem.

If you are not using a security module that requires using
extended attributes for file security labels, say N.

config TMPFS
bool "Virtual memory file system support (former shm fs)"
help
Expand All @@ -817,27 +795,6 @@ config TMPFS

See <file:Documentation/filesystems/tmpfs.txt> for details.

config TMPFS_XATTR
bool "tmpfs Extended Attributes"
depends on TMPFS
help
Extended attributes are name:value pairs associated with inodes by
the kernel or by users (see the attr(5) manual page, or visit
<http://acl.bestbits.at/> for details).

If unsure, say N.

config TMPFS_SECURITY
bool "tmpfs Security Labels"
depends on TMPFS_XATTR
help
Security labels support alternative access control models
implemented by security modules like SELinux. This option
enables an extended attribute handler for file security
labels in the tmpfs filesystem.
If you are not using a security module that requires using
extended attributes for file security labels, say N.

config HUGETLBFS
bool "HugeTLB file system support"
depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || X86_64 || BROKEN
Expand Down
1 change: 0 additions & 1 deletion fs/devpts/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,3 @@
obj-$(CONFIG_UNIX98_PTYS) += devpts.o

devpts-$(CONFIG_UNIX98_PTYS) := inode.o
devpts-$(CONFIG_DEVPTS_FS_SECURITY) += xattr_security.o
21 changes: 0 additions & 21 deletions fs/devpts/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,9 @@
#include <linux/mount.h>
#include <linux/tty.h>
#include <linux/devpts_fs.h>
#include <linux/xattr.h>

#define DEVPTS_SUPER_MAGIC 0x1cd1

extern struct xattr_handler devpts_xattr_security_handler;

static struct xattr_handler *devpts_xattr_handlers[] = {
#ifdef CONFIG_DEVPTS_FS_SECURITY
&devpts_xattr_security_handler,
#endif
NULL
};

static struct inode_operations devpts_file_inode_operations = {
#ifdef CONFIG_DEVPTS_FS_XATTR
.setxattr = generic_setxattr,
.getxattr = generic_getxattr,
.listxattr = generic_listxattr,
.removexattr = generic_removexattr,
#endif
};

static struct vfsmount *devpts_mnt;
static struct dentry *devpts_root;

Expand Down Expand Up @@ -102,7 +83,6 @@ devpts_fill_super(struct super_block *s, void *data, int silent)
s->s_blocksize_bits = 10;
s->s_magic = DEVPTS_SUPER_MAGIC;
s->s_op = &devpts_sops;
s->s_xattr = devpts_xattr_handlers;
s->s_time_gran = 1;

inode = new_inode(s);
Expand Down Expand Up @@ -175,7 +155,6 @@ int devpts_pty_new(struct tty_struct *tty)
inode->i_gid = config.setgid ? config.gid : current->fsgid;
inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
init_special_inode(inode, S_IFCHR|config.mode, device);
inode->i_op = &devpts_file_inode_operations;
inode->u.generic_ip = tty;

dentry = get_node(number);
Expand Down
47 changes: 0 additions & 47 deletions fs/devpts/xattr_security.c

This file was deleted.

80 changes: 49 additions & 31 deletions fs/xattr.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,29 @@ setxattr(struct dentry *d, char __user *name, void __user *value,
}
}

down(&d->d_inode->i_sem);
error = security_inode_setxattr(d, kname, kvalue, size, flags);
if (error)
goto out;
error = -EOPNOTSUPP;
if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
down(&d->d_inode->i_sem);
error = security_inode_setxattr(d, kname, kvalue, size, flags);
if (error)
goto out;
error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
error = d->d_inode->i_op->setxattr(d, kname, kvalue,
size, flags);
if (!error) {
fsnotify_xattr(d);
security_inode_post_setxattr(d, kname, kvalue, size, flags);
security_inode_post_setxattr(d, kname, kvalue,
size, flags);
}
out:
up(&d->d_inode->i_sem);
} else if (!strncmp(kname, XATTR_SECURITY_PREFIX,
sizeof XATTR_SECURITY_PREFIX - 1)) {
const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1;
error = security_inode_setsecurity(d->d_inode, suffix, kvalue,
size, flags);
if (!error)
fsnotify_xattr(d);
}
out:
up(&d->d_inode->i_sem);
if (kvalue)
kfree(kvalue);
return error;
Expand Down Expand Up @@ -139,20 +148,25 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
return -ENOMEM;
}

error = security_inode_getxattr(d, kname);
if (error)
goto out;
error = -EOPNOTSUPP;
if (d->d_inode->i_op && d->d_inode->i_op->getxattr) {
error = security_inode_getxattr(d, kname);
if (error)
goto out;
if (d->d_inode->i_op && d->d_inode->i_op->getxattr)
error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
if (error > 0) {
if (size && copy_to_user(value, kvalue, error))
error = -EFAULT;
} else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
/* The file system tried to returned a value bigger
than XATTR_SIZE_MAX bytes. Not possible. */
error = -E2BIG;
}
else if (!strncmp(kname, XATTR_SECURITY_PREFIX,
sizeof XATTR_SECURITY_PREFIX - 1)) {
const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1;
error = security_inode_getsecurity(d->d_inode, suffix, kvalue,
size);
}
if (error > 0) {
if (size && copy_to_user(value, kvalue, error))
error = -EFAULT;
} else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
/* The file system tried to returned a value bigger
than XATTR_SIZE_MAX bytes. Not possible. */
error = -E2BIG;
}
out:
if (kvalue)
Expand Down Expand Up @@ -221,20 +235,24 @@ listxattr(struct dentry *d, char __user *list, size_t size)
return -ENOMEM;
}

error = security_inode_listxattr(d);
if (error)
goto out;
error = -EOPNOTSUPP;
if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
error = security_inode_listxattr(d);
if (error)
goto out;
error = d->d_inode->i_op->listxattr(d, klist, size);
if (error > 0) {
if (size && copy_to_user(list, klist, error))
error = -EFAULT;
} else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
/* The file system tried to returned a list bigger
than XATTR_LIST_MAX bytes. Not possible. */
error = -E2BIG;
}
} else {
error = security_inode_listsecurity(d->d_inode, klist, size);
if (size && error >= size)
error = -ERANGE;
}
if (error > 0) {
if (size && copy_to_user(list, klist, error))
error = -EFAULT;
} else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
/* The file system tried to returned a list bigger
than XATTR_LIST_MAX bytes. Not possible. */
error = -E2BIG;
}
out:
if (klist)
Expand Down
Loading

0 comments on commit f549d6c

Please sign in to comment.