diff options
Diffstat (limited to 'fs/xattr.c')
-rw-r--r-- | fs/xattr.c | 80 |
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 | } |
65 | out: | 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 | } |
75 | out: | ||
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 | } |
157 | out: | 171 | out: |
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 | } |
239 | out: | 257 | out: |
240 | if (klist) | 258 | if (klist) |