aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xattr.c
diff options
context:
space:
mode:
authorakpm@osdl.org <akpm@osdl.org>2006-01-09 23:51:56 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-01-10 11:01:29 -0500
commite0ad7b073eb7317e5afe0385b02dcb1d52a1eedf (patch)
treebd4a424efe77bfb94c74bb6e57dcf0a0ff998969 /fs/xattr.c
parent5be196e5f925dab2309530fabce69c2e562b9791 (diff)
[PATCH] move xattr permission checks into the VFS
) From: Christoph Hellwig <hch@lst.de> The xattr code has rather complex permission checks because the rules are very different for different attribute namespaces. This patch moves as much as we can into the generic code. Currently all the major disk based filesystems duplicate these checks, while many minor filesystems or network filesystems lack some or all of them. To do this we need defines for the extended attribute names in common code, I moved them up from JFS which had the nicest defintions. Signed-off-by: Christoph Hellwig <hch@lst.de> Acked-by: Dave Kleikamp <shaggy@austin.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/xattr.c')
-rw-r--r--fs/xattr.c61
1 files changed, 57 insertions, 4 deletions
diff --git a/fs/xattr.c b/fs/xattr.c
index fee804e69a9a..80eca7d3d69f 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -20,6 +20,47 @@
20#include <asm/uaccess.h> 20#include <asm/uaccess.h>
21 21
22 22
23/*
24 * Check permissions for extended attribute access. This is a bit complicated
25 * because different namespaces have very different rules.
26 */
27static int
28xattr_permission(struct inode *inode, const char *name, int mask)
29{
30 /*
31 * We can never set or remove an extended attribute on a read-only
32 * filesystem or on an immutable / append-only inode.
33 */
34 if (mask & MAY_WRITE) {
35 if (IS_RDONLY(inode))
36 return -EROFS;
37 if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
38 return -EPERM;
39 }
40
41 /*
42 * No restriction for security.* and system.* from the VFS. Decision
43 * on these is left to the underlying filesystem / security module.
44 */
45 if (!strncmp(name, XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) ||
46 !strncmp(name, XATTR_SYSTEM_PREFIX, XATTR_SYSTEM_PREFIX_LEN))
47 return 0;
48
49 /*
50 * The trusted.* namespace can only accessed by a privilegued user.
51 */
52 if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
53 return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM);
54
55 if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) {
56 if (!S_ISREG(inode->i_mode) &&
57 (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX))
58 return -EPERM;
59 }
60
61 return permission(inode, mask, NULL);
62}
63
23int 64int
24vfs_setxattr(struct dentry *dentry, char *name, void *value, 65vfs_setxattr(struct dentry *dentry, char *name, void *value,
25 size_t size, int flags) 66 size_t size, int flags)
@@ -27,6 +68,10 @@ vfs_setxattr(struct dentry *dentry, char *name, void *value,
27 struct inode *inode = dentry->d_inode; 68 struct inode *inode = dentry->d_inode;
28 int error; 69 int error;
29 70
71 error = xattr_permission(inode, name, MAY_WRITE);
72 if (error)
73 return error;
74
30 mutex_lock(&inode->i_mutex); 75 mutex_lock(&inode->i_mutex);
31 error = security_inode_setxattr(dentry, name, value, size, flags); 76 error = security_inode_setxattr(dentry, name, value, size, flags);
32 if (error) 77 if (error)
@@ -40,8 +85,8 @@ vfs_setxattr(struct dentry *dentry, char *name, void *value,
40 size, flags); 85 size, flags);
41 } 86 }
42 } else if (!strncmp(name, XATTR_SECURITY_PREFIX, 87 } else if (!strncmp(name, XATTR_SECURITY_PREFIX,
43 sizeof XATTR_SECURITY_PREFIX - 1)) { 88 XATTR_SECURITY_PREFIX_LEN)) {
44 const char *suffix = name + sizeof XATTR_SECURITY_PREFIX - 1; 89 const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
45 error = security_inode_setsecurity(inode, suffix, value, 90 error = security_inode_setsecurity(inode, suffix, value,
46 size, flags); 91 size, flags);
47 if (!error) 92 if (!error)
@@ -59,6 +104,10 @@ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
59 struct inode *inode = dentry->d_inode; 104 struct inode *inode = dentry->d_inode;
60 int error; 105 int error;
61 106
107 error = xattr_permission(inode, name, MAY_READ);
108 if (error)
109 return error;
110
62 error = security_inode_getxattr(dentry, name); 111 error = security_inode_getxattr(dentry, name);
63 if (error) 112 if (error)
64 return error; 113 return error;
@@ -69,8 +118,8 @@ vfs_getxattr(struct dentry *dentry, char *name, void *value, size_t size)
69 error = -EOPNOTSUPP; 118 error = -EOPNOTSUPP;
70 119
71 if (!strncmp(name, XATTR_SECURITY_PREFIX, 120 if (!strncmp(name, XATTR_SECURITY_PREFIX,
72 sizeof XATTR_SECURITY_PREFIX - 1)) { 121 XATTR_SECURITY_PREFIX_LEN)) {
73 const char *suffix = name + sizeof XATTR_SECURITY_PREFIX - 1; 122 const char *suffix = name + XATTR_SECURITY_PREFIX_LEN;
74 int ret = security_inode_getsecurity(inode, suffix, value, 123 int ret = security_inode_getsecurity(inode, suffix, value,
75 size, error); 124 size, error);
76 /* 125 /*
@@ -94,6 +143,10 @@ vfs_removexattr(struct dentry *dentry, char *name)
94 if (!inode->i_op->removexattr) 143 if (!inode->i_op->removexattr)
95 return -EOPNOTSUPP; 144 return -EOPNOTSUPP;
96 145
146 error = xattr_permission(inode, name, MAY_WRITE);
147 if (error)
148 return error;
149
97 error = security_inode_removexattr(dentry, name); 150 error = security_inode_removexattr(dentry, name);
98 if (error) 151 if (error)
99 return error; 152 return error;