aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xattr.c
diff options
context:
space:
mode:
authorStephen Smalley <sds@tycho.nsa.gov>2005-09-03 18:55:18 -0400
committerLinus Torvalds <torvalds@evo.osdl.org>2005-09-05 03:05:52 -0400
commitf549d6c18c0e8e6cf1bf0e7a47acc1daf7e2cec1 (patch)
tree40d827736575f2a8c489761599e9a1e5e45005be /fs/xattr.c
parentb5bf6c55edf94e9c7fc01724d5b271f78eaf1d3f (diff)
[PATCH] Generic VFS fallback for security xattrs
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>
Diffstat (limited to 'fs/xattr.c')
-rw-r--r--fs/xattr.c80
1 files changed, 49 insertions, 31 deletions
diff --git a/fs/xattr.c b/fs/xattr.c
index 6acd5c63da91..dc8bc7624f26 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -51,20 +51,29 @@ setxattr(struct dentry *d, char __user *name, void __user *value,
51 } 51 }
52 } 52 }
53 53
54 down(&d->d_inode->i_sem);
55 error = security_inode_setxattr(d, kname, kvalue, size, flags);
56 if (error)
57 goto out;
54 error = -EOPNOTSUPP; 58 error = -EOPNOTSUPP;
55 if (d->d_inode->i_op && d->d_inode->i_op->setxattr) { 59 if (d->d_inode->i_op && d->d_inode->i_op->setxattr) {
56 down(&d->d_inode->i_sem); 60 error = d->d_inode->i_op->setxattr(d, kname, kvalue,
57 error = security_inode_setxattr(d, kname, kvalue, size, flags); 61 size, flags);
58 if (error)
59 goto out;
60 error = d->d_inode->i_op->setxattr(d, kname, kvalue, size, flags);
61 if (!error) { 62 if (!error) {
62 fsnotify_xattr(d); 63 fsnotify_xattr(d);
63 security_inode_post_setxattr(d, kname, kvalue, size, flags); 64 security_inode_post_setxattr(d, kname, kvalue,
65 size, flags);
64 } 66 }
65out: 67 } else if (!strncmp(kname, XATTR_SECURITY_PREFIX,
66 up(&d->d_inode->i_sem); 68 sizeof XATTR_SECURITY_PREFIX - 1)) {
69 const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1;
70 error = security_inode_setsecurity(d->d_inode, suffix, kvalue,
71 size, flags);
72 if (!error)
73 fsnotify_xattr(d);
67 } 74 }
75out:
76 up(&d->d_inode->i_sem);
68 if (kvalue) 77 if (kvalue)
69 kfree(kvalue); 78 kfree(kvalue);
70 return error; 79 return error;
@@ -139,20 +148,25 @@ getxattr(struct dentry *d, char __user *name, void __user *value, size_t size)
139 return -ENOMEM; 148 return -ENOMEM;
140 } 149 }
141 150
151 error = security_inode_getxattr(d, kname);
152 if (error)
153 goto out;
142 error = -EOPNOTSUPP; 154 error = -EOPNOTSUPP;
143 if (d->d_inode->i_op && d->d_inode->i_op->getxattr) { 155 if (d->d_inode->i_op && d->d_inode->i_op->getxattr)
144 error = security_inode_getxattr(d, kname);
145 if (error)
146 goto out;
147 error = d->d_inode->i_op->getxattr(d, kname, kvalue, size); 156 error = d->d_inode->i_op->getxattr(d, kname, kvalue, size);
148 if (error > 0) { 157 else if (!strncmp(kname, XATTR_SECURITY_PREFIX,
149 if (size && copy_to_user(value, kvalue, error)) 158 sizeof XATTR_SECURITY_PREFIX - 1)) {
150 error = -EFAULT; 159 const char *suffix = kname + sizeof XATTR_SECURITY_PREFIX - 1;
151 } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) { 160 error = security_inode_getsecurity(d->d_inode, suffix, kvalue,
152 /* The file system tried to returned a value bigger 161 size);
153 than XATTR_SIZE_MAX bytes. Not possible. */ 162 }
154 error = -E2BIG; 163 if (error > 0) {
155 } 164 if (size && copy_to_user(value, kvalue, error))
165 error = -EFAULT;
166 } else if (error == -ERANGE && size >= XATTR_SIZE_MAX) {
167 /* The file system tried to returned a value bigger
168 than XATTR_SIZE_MAX bytes. Not possible. */
169 error = -E2BIG;
156 } 170 }
157out: 171out:
158 if (kvalue) 172 if (kvalue)
@@ -221,20 +235,24 @@ listxattr(struct dentry *d, char __user *list, size_t size)
221 return -ENOMEM; 235 return -ENOMEM;
222 } 236 }
223 237
238 error = security_inode_listxattr(d);
239 if (error)
240 goto out;
224 error = -EOPNOTSUPP; 241 error = -EOPNOTSUPP;
225 if (d->d_inode->i_op && d->d_inode->i_op->listxattr) { 242 if (d->d_inode->i_op && d->d_inode->i_op->listxattr) {
226 error = security_inode_listxattr(d);
227 if (error)
228 goto out;
229 error = d->d_inode->i_op->listxattr(d, klist, size); 243 error = d->d_inode->i_op->listxattr(d, klist, size);
230 if (error > 0) { 244 } else {
231 if (size && copy_to_user(list, klist, error)) 245 error = security_inode_listsecurity(d->d_inode, klist, size);
232 error = -EFAULT; 246 if (size && error >= size)
233 } else if (error == -ERANGE && size >= XATTR_LIST_MAX) { 247 error = -ERANGE;
234 /* The file system tried to returned a list bigger 248 }
235 than XATTR_LIST_MAX bytes. Not possible. */ 249 if (error > 0) {
236 error = -E2BIG; 250 if (size && copy_to_user(list, klist, error))
237 } 251 error = -EFAULT;
252 } else if (error == -ERANGE && size >= XATTR_LIST_MAX) {
253 /* The file system tried to returned a list bigger
254 than XATTR_LIST_MAX bytes. Not possible. */
255 error = -E2BIG;
238 } 256 }
239out: 257out:
240 if (klist) 258 if (klist)