diff options
Diffstat (limited to 'fs/xattr.c')
-rw-r--r-- | fs/xattr.c | 21 |
1 files changed, 14 insertions, 7 deletions
diff --git a/fs/xattr.c b/fs/xattr.c index 395635100f..38646132ab 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
@@ -48,14 +48,21 @@ xattr_permission(struct inode *inode, const char *name, int mask) | |||
48 | return 0; | 48 | return 0; |
49 | 49 | ||
50 | /* | 50 | /* |
51 | * The trusted.* namespace can only accessed by a privilegued user. | 51 | * The trusted.* namespace can only be accessed by a privileged user. |
52 | */ | 52 | */ |
53 | if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) | 53 | if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN)) |
54 | return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM); | 54 | return (capable(CAP_SYS_ADMIN) ? 0 : -EPERM); |
55 | 55 | ||
56 | /* In user.* namespace, only regular files and directories can have | ||
57 | * extended attributes. For sticky directories, only the owner and | ||
58 | * privileged user can write attributes. | ||
59 | */ | ||
56 | if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) { | 60 | if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)) { |
57 | if (!S_ISREG(inode->i_mode) && | 61 | if (!S_ISREG(inode->i_mode) && !S_ISDIR(inode->i_mode)) |
58 | (!S_ISDIR(inode->i_mode) || inode->i_mode & S_ISVTX)) | 62 | return -EPERM; |
63 | if (S_ISDIR(inode->i_mode) && (inode->i_mode & S_ISVTX) && | ||
64 | (mask & MAY_WRITE) && (current->fsuid != inode->i_uid) && | ||
65 | !capable(CAP_FOWNER)) | ||
59 | return -EPERM; | 66 | return -EPERM; |
60 | } | 67 | } |
61 | 68 | ||
@@ -261,7 +268,7 @@ sys_fsetxattr(int fd, char __user *name, void __user *value, | |||
261 | f = fget(fd); | 268 | f = fget(fd); |
262 | if (!f) | 269 | if (!f) |
263 | return error; | 270 | return error; |
264 | dentry = f->f_dentry; | 271 | dentry = f->f_path.dentry; |
265 | audit_inode(NULL, dentry->d_inode); | 272 | audit_inode(NULL, dentry->d_inode); |
266 | error = setxattr(dentry, name, value, size, flags); | 273 | error = setxattr(dentry, name, value, size, flags); |
267 | fput(f); | 274 | fput(f); |
@@ -344,7 +351,7 @@ sys_fgetxattr(int fd, char __user *name, void __user *value, size_t size) | |||
344 | f = fget(fd); | 351 | f = fget(fd); |
345 | if (!f) | 352 | if (!f) |
346 | return error; | 353 | return error; |
347 | error = getxattr(f->f_dentry, name, value, size); | 354 | error = getxattr(f->f_path.dentry, name, value, size); |
348 | fput(f); | 355 | fput(f); |
349 | return error; | 356 | return error; |
350 | } | 357 | } |
@@ -416,7 +423,7 @@ sys_flistxattr(int fd, char __user *list, size_t size) | |||
416 | f = fget(fd); | 423 | f = fget(fd); |
417 | if (!f) | 424 | if (!f) |
418 | return error; | 425 | return error; |
419 | error = listxattr(f->f_dentry, list, size); | 426 | error = listxattr(f->f_path.dentry, list, size); |
420 | fput(f); | 427 | fput(f); |
421 | return error; | 428 | return error; |
422 | } | 429 | } |
@@ -477,7 +484,7 @@ sys_fremovexattr(int fd, char __user *name) | |||
477 | f = fget(fd); | 484 | f = fget(fd); |
478 | if (!f) | 485 | if (!f) |
479 | return error; | 486 | return error; |
480 | dentry = f->f_dentry; | 487 | dentry = f->f_path.dentry; |
481 | audit_inode(NULL, dentry->d_inode); | 488 | audit_inode(NULL, dentry->d_inode); |
482 | error = removexattr(dentry, name); | 489 | error = removexattr(dentry, name); |
483 | fput(f); | 490 | fput(f); |