aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--fs/jfs/xattr.c15
-rw-r--r--fs/xattr.c61
-rw-r--r--include/linux/xattr.h15
3 files changed, 72 insertions, 19 deletions
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index 23aa5066b5a4..9dde36a1eb5d 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -83,21 +83,6 @@ struct ea_buffer {
83#define EA_NEW 0x0004 83#define EA_NEW 0x0004
84#define EA_MALLOC 0x0008 84#define EA_MALLOC 0x0008
85 85
86/* Namespaces */
87#define XATTR_SYSTEM_PREFIX "system."
88#define XATTR_SYSTEM_PREFIX_LEN (sizeof (XATTR_SYSTEM_PREFIX) - 1)
89
90#define XATTR_USER_PREFIX "user."
91#define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1)
92
93#define XATTR_OS2_PREFIX "os2."
94#define XATTR_OS2_PREFIX_LEN (sizeof (XATTR_OS2_PREFIX) - 1)
95
96/* XATTR_SECURITY_PREFIX is defined in include/linux/xattr.h */
97#define XATTR_SECURITY_PREFIX_LEN (sizeof (XATTR_SECURITY_PREFIX) - 1)
98
99#define XATTR_TRUSTED_PREFIX "trusted."
100#define XATTR_TRUSTED_PREFIX_LEN (sizeof (XATTR_TRUSTED_PREFIX) - 1)
101 86
102/* 87/*
103 * These three routines are used to recognize on-disk extended attributes 88 * These three routines are used to recognize on-disk extended attributes
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;
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index 366f0ab4219f..cda8a96e2fa0 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -13,7 +13,22 @@
13#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */ 13#define XATTR_CREATE 0x1 /* set value, fail if attr already exists */
14#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */ 14#define XATTR_REPLACE 0x2 /* set value, fail if attr does not exist */
15 15
16/* Namespaces */
17#define XATTR_OS2_PREFIX "os2."
18#define XATTR_OS2_PREFIX_LEN (sizeof (XATTR_OS2_PREFIX) - 1)
19
16#define XATTR_SECURITY_PREFIX "security." 20#define XATTR_SECURITY_PREFIX "security."
21#define XATTR_SECURITY_PREFIX_LEN (sizeof (XATTR_SECURITY_PREFIX) - 1)
22
23#define XATTR_SYSTEM_PREFIX "system."
24#define XATTR_SYSTEM_PREFIX_LEN (sizeof (XATTR_SYSTEM_PREFIX) - 1)
25
26#define XATTR_TRUSTED_PREFIX "trusted."
27#define XATTR_TRUSTED_PREFIX_LEN (sizeof (XATTR_TRUSTED_PREFIX) - 1)
28
29#define XATTR_USER_PREFIX "user."
30#define XATTR_USER_PREFIX_LEN (sizeof (XATTR_USER_PREFIX) - 1)
31
17 32
18struct xattr_handler { 33struct xattr_handler {
19 char *prefix; 34 char *prefix;