aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-10-25 03:45:31 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-10-25 03:45:31 -0400
commit36b8d186e6cc8e32cb5227f5645a58e1bc0af190 (patch)
tree1000ad26e189e6ff2c53fb7eeff605f59c7ad94e /fs
parentcd85b557414fe4cd44ea6608825e96612a5fe2b2 (diff)
parentc45ed235abf1b0b6666417e3c394f18717976acd (diff)
Merge branch 'next' of git://selinuxproject.org/~jmorris/linux-security
* 'next' of git://selinuxproject.org/~jmorris/linux-security: (95 commits) TOMOYO: Fix incomplete read after seek. Smack: allow to access /smack/access as normal user TOMOYO: Fix unused kernel config option. Smack: fix: invalid length set for the result of /smack/access Smack: compilation fix Smack: fix for /smack/access output, use string instead of byte Smack: domain transition protections (v3) Smack: Provide information for UDS getsockopt(SO_PEERCRED) Smack: Clean up comments Smack: Repair processing of fcntl Smack: Rule list lookup performance Smack: check permissions from user space (v2) TOMOYO: Fix quota and garbage collector. TOMOYO: Remove redundant tasklist_lock. TOMOYO: Fix domain transition failure warning. TOMOYO: Remove tomoyo_policy_memory_lock spinlock. TOMOYO: Simplify garbage collector. TOMOYO: Fix make namespacecheck warnings. target: check hex2bin result encrypted-keys: check hex2bin result ...
Diffstat (limited to 'fs')
-rw-r--r--fs/attr.c5
-rw-r--r--fs/btrfs/xattr.c50
-rw-r--r--fs/cifs/xattr.c40
-rw-r--r--fs/ext2/xattr_security.c34
-rw-r--r--fs/ext3/xattr_security.c36
-rw-r--r--fs/ext4/xattr_security.c36
-rw-r--r--fs/gfs2/inode.c38
-rw-r--r--fs/jffs2/security.c35
-rw-r--r--fs/jfs/xattr.c57
-rw-r--r--fs/ocfs2/xattr.c38
-rw-r--r--fs/reiserfs/xattr_security.c4
-rw-r--r--fs/xattr.c63
-rw-r--r--fs/xfs/xfs_iops.c39
13 files changed, 278 insertions, 197 deletions
diff --git a/fs/attr.c b/fs/attr.c
index 538e27959d3f..7ee7ba488313 100644
--- a/fs/attr.c
+++ b/fs/attr.c
@@ -13,6 +13,7 @@
13#include <linux/fsnotify.h> 13#include <linux/fsnotify.h>
14#include <linux/fcntl.h> 14#include <linux/fcntl.h>
15#include <linux/security.h> 15#include <linux/security.h>
16#include <linux/evm.h>
16 17
17/** 18/**
18 * inode_change_ok - check if attribute changes to an inode are allowed 19 * inode_change_ok - check if attribute changes to an inode are allowed
@@ -237,8 +238,10 @@ int notify_change(struct dentry * dentry, struct iattr * attr)
237 else 238 else
238 error = simple_setattr(dentry, attr); 239 error = simple_setattr(dentry, attr);
239 240
240 if (!error) 241 if (!error) {
241 fsnotify_change(dentry, ia_valid); 242 fsnotify_change(dentry, ia_valid);
243 evm_inode_post_setattr(dentry, ia_valid);
244 }
242 245
243 return error; 246 return error;
244} 247}
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
index 69565e5fc6a0..426aa464f1af 100644
--- a/fs/btrfs/xattr.c
+++ b/fs/btrfs/xattr.c
@@ -383,36 +383,36 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
383 XATTR_REPLACE); 383 XATTR_REPLACE);
384} 384}
385 385
386int btrfs_xattr_security_init(struct btrfs_trans_handle *trans, 386int btrfs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
387 struct inode *inode, struct inode *dir, 387 void *fs_info)
388 const struct qstr *qstr)
389{ 388{
390 int err; 389 const struct xattr *xattr;
391 size_t len; 390 struct btrfs_trans_handle *trans = fs_info;
392 void *value;
393 char *suffix;
394 char *name; 391 char *name;
392 int err = 0;
395 393
396 err = security_inode_init_security(inode, dir, qstr, &suffix, &value, 394 for (xattr = xattr_array; xattr->name != NULL; xattr++) {
397 &len); 395 name = kmalloc(XATTR_SECURITY_PREFIX_LEN +
398 if (err) { 396 strlen(xattr->name) + 1, GFP_NOFS);
399 if (err == -EOPNOTSUPP) 397 if (!name) {
400 return 0; 398 err = -ENOMEM;
401 return err; 399 break;
402 } 400 }
403
404 name = kmalloc(XATTR_SECURITY_PREFIX_LEN + strlen(suffix) + 1,
405 GFP_NOFS);
406 if (!name) {
407 err = -ENOMEM;
408 } else {
409 strcpy(name, XATTR_SECURITY_PREFIX); 401 strcpy(name, XATTR_SECURITY_PREFIX);
410 strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix); 402 strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name);
411 err = __btrfs_setxattr(trans, inode, name, value, len, 0); 403 err = __btrfs_setxattr(trans, inode, name,
404 xattr->value, xattr->value_len, 0);
412 kfree(name); 405 kfree(name);
406 if (err < 0)
407 break;
413 } 408 }
414
415 kfree(suffix);
416 kfree(value);
417 return err; 409 return err;
418} 410}
411
412int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
413 struct inode *inode, struct inode *dir,
414 const struct qstr *qstr)
415{
416 return security_inode_init_security(inode, dir, qstr,
417 &btrfs_initxattrs, trans);
418}
diff --git a/fs/cifs/xattr.c b/fs/cifs/xattr.c
index 2a22fb2989e4..c32308882148 100644
--- a/fs/cifs/xattr.c
+++ b/fs/cifs/xattr.c
@@ -22,6 +22,7 @@
22#include <linux/fs.h> 22#include <linux/fs.h>
23#include <linux/posix_acl_xattr.h> 23#include <linux/posix_acl_xattr.h>
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/xattr.h>
25#include "cifsfs.h" 26#include "cifsfs.h"
26#include "cifspdu.h" 27#include "cifspdu.h"
27#include "cifsglob.h" 28#include "cifsglob.h"
@@ -31,16 +32,8 @@
31#define MAX_EA_VALUE_SIZE 65535 32#define MAX_EA_VALUE_SIZE 65535
32#define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib" 33#define CIFS_XATTR_DOS_ATTRIB "user.DosAttrib"
33#define CIFS_XATTR_CIFS_ACL "system.cifs_acl" 34#define CIFS_XATTR_CIFS_ACL "system.cifs_acl"
34#define CIFS_XATTR_USER_PREFIX "user."
35#define CIFS_XATTR_SYSTEM_PREFIX "system."
36#define CIFS_XATTR_OS2_PREFIX "os2."
37#define CIFS_XATTR_SECURITY_PREFIX "security."
38#define CIFS_XATTR_TRUSTED_PREFIX "trusted."
39#define XATTR_TRUSTED_PREFIX_LEN 8
40#define XATTR_SECURITY_PREFIX_LEN 9
41/* BB need to add server (Samba e.g) support for security and trusted prefix */
42
43 35
36/* BB need to add server (Samba e.g) support for security and trusted prefix */
44 37
45int cifs_removexattr(struct dentry *direntry, const char *ea_name) 38int cifs_removexattr(struct dentry *direntry, const char *ea_name)
46{ 39{
@@ -76,8 +69,8 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
76 } 69 }
77 if (ea_name == NULL) { 70 if (ea_name == NULL) {
78 cFYI(1, "Null xattr names not supported"); 71 cFYI(1, "Null xattr names not supported");
79 } else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) 72 } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)
80 && (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4))) { 73 && (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN))) {
81 cFYI(1, 74 cFYI(1,
82 "illegal xattr request %s (only user namespace supported)", 75 "illegal xattr request %s (only user namespace supported)",
83 ea_name); 76 ea_name);
@@ -88,7 +81,7 @@ int cifs_removexattr(struct dentry *direntry, const char *ea_name)
88 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 81 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
89 goto remove_ea_exit; 82 goto remove_ea_exit;
90 83
91 ea_name += 5; /* skip past user. prefix */ 84 ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
92 rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, NULL, 85 rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, NULL,
93 (__u16)0, cifs_sb->local_nls, 86 (__u16)0, cifs_sb->local_nls,
94 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 87 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -149,21 +142,23 @@ int cifs_setxattr(struct dentry *direntry, const char *ea_name,
149 142
150 if (ea_name == NULL) { 143 if (ea_name == NULL) {
151 cFYI(1, "Null xattr names not supported"); 144 cFYI(1, "Null xattr names not supported");
152 } else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) { 145 } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)
146 == 0) {
153 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 147 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
154 goto set_ea_exit; 148 goto set_ea_exit;
155 if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0) 149 if (strncmp(ea_name, CIFS_XATTR_DOS_ATTRIB, 14) == 0)
156 cFYI(1, "attempt to set cifs inode metadata"); 150 cFYI(1, "attempt to set cifs inode metadata");
157 151
158 ea_name += 5; /* skip past user. prefix */ 152 ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
159 rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, 153 rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,
160 (__u16)value_size, cifs_sb->local_nls, 154 (__u16)value_size, cifs_sb->local_nls,
161 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 155 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
162 } else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) { 156 } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN)
157 == 0) {
163 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 158 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
164 goto set_ea_exit; 159 goto set_ea_exit;
165 160
166 ea_name += 4; /* skip past os2. prefix */ 161 ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */
167 rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value, 162 rc = CIFSSMBSetEA(xid, pTcon, full_path, ea_name, ea_value,
168 (__u16)value_size, cifs_sb->local_nls, 163 (__u16)value_size, cifs_sb->local_nls,
169 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 164 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -269,7 +264,8 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
269 /* return alt name if available as pseudo attr */ 264 /* return alt name if available as pseudo attr */
270 if (ea_name == NULL) { 265 if (ea_name == NULL) {
271 cFYI(1, "Null xattr names not supported"); 266 cFYI(1, "Null xattr names not supported");
272 } else if (strncmp(ea_name, CIFS_XATTR_USER_PREFIX, 5) == 0) { 267 } else if (strncmp(ea_name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN)
268 == 0) {
273 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 269 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
274 goto get_ea_exit; 270 goto get_ea_exit;
275 271
@@ -277,15 +273,15 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
277 cFYI(1, "attempt to query cifs inode metadata"); 273 cFYI(1, "attempt to query cifs inode metadata");
278 /* revalidate/getattr then populate from inode */ 274 /* revalidate/getattr then populate from inode */
279 } /* BB add else when above is implemented */ 275 } /* BB add else when above is implemented */
280 ea_name += 5; /* skip past user. prefix */ 276 ea_name += XATTR_USER_PREFIX_LEN; /* skip past user. prefix */
281 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value, 277 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,
282 buf_size, cifs_sb->local_nls, 278 buf_size, cifs_sb->local_nls,
283 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 279 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
284 } else if (strncmp(ea_name, CIFS_XATTR_OS2_PREFIX, 4) == 0) { 280 } else if (strncmp(ea_name, XATTR_OS2_PREFIX, XATTR_OS2_PREFIX_LEN) == 0) {
285 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR) 281 if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_NO_XATTR)
286 goto get_ea_exit; 282 goto get_ea_exit;
287 283
288 ea_name += 4; /* skip past os2. prefix */ 284 ea_name += XATTR_OS2_PREFIX_LEN; /* skip past os2. prefix */
289 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value, 285 rc = CIFSSMBQAllEAs(xid, pTcon, full_path, ea_name, ea_value,
290 buf_size, cifs_sb->local_nls, 286 buf_size, cifs_sb->local_nls,
291 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); 287 cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
@@ -339,10 +335,10 @@ ssize_t cifs_getxattr(struct dentry *direntry, const char *ea_name,
339 cFYI(1, "Query CIFS ACL not supported yet"); 335 cFYI(1, "Query CIFS ACL not supported yet");
340#endif /* CONFIG_CIFS_ACL */ 336#endif /* CONFIG_CIFS_ACL */
341 } else if (strncmp(ea_name, 337 } else if (strncmp(ea_name,
342 CIFS_XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) { 338 XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN) == 0) {
343 cFYI(1, "Trusted xattr namespace not supported yet"); 339 cFYI(1, "Trusted xattr namespace not supported yet");
344 } else if (strncmp(ea_name, 340 } else if (strncmp(ea_name,
345 CIFS_XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) { 341 XATTR_SECURITY_PREFIX, XATTR_SECURITY_PREFIX_LEN) == 0) {
346 cFYI(1, "Security xattr namespace not supported yet"); 342 cFYI(1, "Security xattr namespace not supported yet");
347 } else 343 } else
348 cFYI(1, 344 cFYI(1,
diff --git a/fs/ext2/xattr_security.c b/fs/ext2/xattr_security.c
index 5d979b4347b0..c922adc8ef41 100644
--- a/fs/ext2/xattr_security.c
+++ b/fs/ext2/xattr_security.c
@@ -46,28 +46,30 @@ ext2_xattr_security_set(struct dentry *dentry, const char *name,
46 value, size, flags); 46 value, size, flags);
47} 47}
48 48
49int 49int ext2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
50ext2_init_security(struct inode *inode, struct inode *dir, 50 void *fs_info)
51 const struct qstr *qstr)
52{ 51{
53 int err; 52 const struct xattr *xattr;
54 size_t len; 53 int err = 0;
55 void *value;
56 char *name;
57 54
58 err = security_inode_init_security(inode, dir, qstr, &name, &value, &len); 55 for (xattr = xattr_array; xattr->name != NULL; xattr++) {
59 if (err) { 56 err = ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY,
60 if (err == -EOPNOTSUPP) 57 xattr->name, xattr->value,
61 return 0; 58 xattr->value_len, 0);
62 return err; 59 if (err < 0)
60 break;
63 } 61 }
64 err = ext2_xattr_set(inode, EXT2_XATTR_INDEX_SECURITY,
65 name, value, len, 0);
66 kfree(name);
67 kfree(value);
68 return err; 62 return err;
69} 63}
70 64
65int
66ext2_init_security(struct inode *inode, struct inode *dir,
67 const struct qstr *qstr)
68{
69 return security_inode_init_security(inode, dir, qstr,
70 &ext2_initxattrs, NULL);
71}
72
71const struct xattr_handler ext2_xattr_security_handler = { 73const struct xattr_handler ext2_xattr_security_handler = {
72 .prefix = XATTR_SECURITY_PREFIX, 74 .prefix = XATTR_SECURITY_PREFIX,
73 .list = ext2_xattr_security_list, 75 .list = ext2_xattr_security_list,
diff --git a/fs/ext3/xattr_security.c b/fs/ext3/xattr_security.c
index b8d9f83aa5c5..3c218b8a51d4 100644
--- a/fs/ext3/xattr_security.c
+++ b/fs/ext3/xattr_security.c
@@ -48,28 +48,32 @@ ext3_xattr_security_set(struct dentry *dentry, const char *name,
48 name, value, size, flags); 48 name, value, size, flags);
49} 49}
50 50
51int 51int ext3_initxattrs(struct inode *inode, const struct xattr *xattr_array,
52ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir, 52 void *fs_info)
53 const struct qstr *qstr)
54{ 53{
55 int err; 54 const struct xattr *xattr;
56 size_t len; 55 handle_t *handle = fs_info;
57 void *value; 56 int err = 0;
58 char *name;
59 57
60 err = security_inode_init_security(inode, dir, qstr, &name, &value, &len); 58 for (xattr = xattr_array; xattr->name != NULL; xattr++) {
61 if (err) { 59 err = ext3_xattr_set_handle(handle, inode,
62 if (err == -EOPNOTSUPP) 60 EXT3_XATTR_INDEX_SECURITY,
63 return 0; 61 xattr->name, xattr->value,
64 return err; 62 xattr->value_len, 0);
63 if (err < 0)
64 break;
65 } 65 }
66 err = ext3_xattr_set_handle(handle, inode, EXT3_XATTR_INDEX_SECURITY,
67 name, value, len, 0);
68 kfree(name);
69 kfree(value);
70 return err; 66 return err;
71} 67}
72 68
69int
70ext3_init_security(handle_t *handle, struct inode *inode, struct inode *dir,
71 const struct qstr *qstr)
72{
73 return security_inode_init_security(inode, dir, qstr,
74 &ext3_initxattrs, handle);
75}
76
73const struct xattr_handler ext3_xattr_security_handler = { 77const struct xattr_handler ext3_xattr_security_handler = {
74 .prefix = XATTR_SECURITY_PREFIX, 78 .prefix = XATTR_SECURITY_PREFIX,
75 .list = ext3_xattr_security_list, 79 .list = ext3_xattr_security_list,
diff --git a/fs/ext4/xattr_security.c b/fs/ext4/xattr_security.c
index 007c3bfbf094..34e4350dd4d9 100644
--- a/fs/ext4/xattr_security.c
+++ b/fs/ext4/xattr_security.c
@@ -48,28 +48,32 @@ ext4_xattr_security_set(struct dentry *dentry, const char *name,
48 name, value, size, flags); 48 name, value, size, flags);
49} 49}
50 50
51int 51int ext4_initxattrs(struct inode *inode, const struct xattr *xattr_array,
52ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir, 52 void *fs_info)
53 const struct qstr *qstr)
54{ 53{
55 int err; 54 const struct xattr *xattr;
56 size_t len; 55 handle_t *handle = fs_info;
57 void *value; 56 int err = 0;
58 char *name;
59 57
60 err = security_inode_init_security(inode, dir, qstr, &name, &value, &len); 58 for (xattr = xattr_array; xattr->name != NULL; xattr++) {
61 if (err) { 59 err = ext4_xattr_set_handle(handle, inode,
62 if (err == -EOPNOTSUPP) 60 EXT4_XATTR_INDEX_SECURITY,
63 return 0; 61 xattr->name, xattr->value,
64 return err; 62 xattr->value_len, 0);
63 if (err < 0)
64 break;
65 } 65 }
66 err = ext4_xattr_set_handle(handle, inode, EXT4_XATTR_INDEX_SECURITY,
67 name, value, len, 0);
68 kfree(name);
69 kfree(value);
70 return err; 66 return err;
71} 67}
72 68
69int
70ext4_init_security(handle_t *handle, struct inode *inode, struct inode *dir,
71 const struct qstr *qstr)
72{
73 return security_inode_init_security(inode, dir, qstr,
74 &ext4_initxattrs, handle);
75}
76
73const struct xattr_handler ext4_xattr_security_handler = { 77const struct xattr_handler ext4_xattr_security_handler = {
74 .prefix = XATTR_SECURITY_PREFIX, 78 .prefix = XATTR_SECURITY_PREFIX,
75 .list = ext4_xattr_security_list, 79 .list = ext4_xattr_security_list,
diff --git a/fs/gfs2/inode.c b/fs/gfs2/inode.c
index 900cf986aadc..6525b804d5ec 100644
--- a/fs/gfs2/inode.c
+++ b/fs/gfs2/inode.c
@@ -624,31 +624,29 @@ fail:
624 return error; 624 return error;
625} 625}
626 626
627static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip, 627int gfs2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
628 const struct qstr *qstr) 628 void *fs_info)
629{ 629{
630 int err; 630 const struct xattr *xattr;
631 size_t len; 631 int err = 0;
632 void *value; 632
633 char *name; 633 for (xattr = xattr_array; xattr->name != NULL; xattr++) {
634 634 err = __gfs2_xattr_set(inode, xattr->name, xattr->value,
635 err = security_inode_init_security(&ip->i_inode, &dip->i_inode, qstr, 635 xattr->value_len, 0,
636 &name, &value, &len); 636 GFS2_EATYPE_SECURITY);
637 637 if (err < 0)
638 if (err) { 638 break;
639 if (err == -EOPNOTSUPP)
640 return 0;
641 return err;
642 } 639 }
643
644 err = __gfs2_xattr_set(&ip->i_inode, name, value, len, 0,
645 GFS2_EATYPE_SECURITY);
646 kfree(value);
647 kfree(name);
648
649 return err; 640 return err;
650} 641}
651 642
643static int gfs2_security_init(struct gfs2_inode *dip, struct gfs2_inode *ip,
644 const struct qstr *qstr)
645{
646 return security_inode_init_security(&ip->i_inode, &dip->i_inode, qstr,
647 &gfs2_initxattrs, NULL);
648}
649
652/** 650/**
653 * gfs2_create_inode - Create a new inode 651 * gfs2_create_inode - Create a new inode
654 * @dir: The parent directory 652 * @dir: The parent directory
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c
index cfeb7164b085..0f20208df602 100644
--- a/fs/jffs2/security.c
+++ b/fs/jffs2/security.c
@@ -22,26 +22,29 @@
22#include <linux/security.h> 22#include <linux/security.h>
23#include "nodelist.h" 23#include "nodelist.h"
24 24
25/* ---- Initial Security Label Attachment -------------- */ 25/* ---- Initial Security Label(s) Attachment callback --- */
26int jffs2_init_security(struct inode *inode, struct inode *dir, 26int jffs2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
27 const struct qstr *qstr) 27 void *fs_info)
28{ 28{
29 int rc; 29 const struct xattr *xattr;
30 size_t len; 30 int err = 0;
31 void *value;
32 char *name;
33 31
34 rc = security_inode_init_security(inode, dir, qstr, &name, &value, &len); 32 for (xattr = xattr_array; xattr->name != NULL; xattr++) {
35 if (rc) { 33 err = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY,
36 if (rc == -EOPNOTSUPP) 34 xattr->name, xattr->value,
37 return 0; 35 xattr->value_len, 0);
38 return rc; 36 if (err < 0)
37 break;
39 } 38 }
40 rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, value, len, 0); 39 return err;
40}
41 41
42 kfree(name); 42/* ---- Initial Security Label(s) Attachment ----------- */
43 kfree(value); 43int jffs2_init_security(struct inode *inode, struct inode *dir,
44 return rc; 44 const struct qstr *qstr)
45{
46 return security_inode_init_security(inode, dir, qstr,
47 &jffs2_initxattrs, NULL);
45} 48}
46 49
47/* ---- XATTR Handler for "security.*" ----------------- */ 50/* ---- XATTR Handler for "security.*" ----------------- */
diff --git a/fs/jfs/xattr.c b/fs/jfs/xattr.c
index e87fedef23db..26683e15b3ac 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -1089,38 +1089,37 @@ int jfs_removexattr(struct dentry *dentry, const char *name)
1089} 1089}
1090 1090
1091#ifdef CONFIG_JFS_SECURITY 1091#ifdef CONFIG_JFS_SECURITY
1092int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir, 1092int jfs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
1093 const struct qstr *qstr) 1093 void *fs_info)
1094{ 1094{
1095 int rc; 1095 const struct xattr *xattr;
1096 size_t len; 1096 tid_t *tid = fs_info;
1097 void *value;
1098 char *suffix;
1099 char *name; 1097 char *name;
1100 1098 int err = 0;
1101 rc = security_inode_init_security(inode, dir, qstr, &suffix, &value, 1099
1102 &len); 1100 for (xattr = xattr_array; xattr->name != NULL; xattr++) {
1103 if (rc) { 1101 name = kmalloc(XATTR_SECURITY_PREFIX_LEN +
1104 if (rc == -EOPNOTSUPP) 1102 strlen(xattr->name) + 1, GFP_NOFS);
1105 return 0; 1103 if (!name) {
1106 return rc; 1104 err = -ENOMEM;
1107 } 1105 break;
1108 name = kmalloc(XATTR_SECURITY_PREFIX_LEN + 1 + strlen(suffix), 1106 }
1109 GFP_NOFS); 1107 strcpy(name, XATTR_SECURITY_PREFIX);
1110 if (!name) { 1108 strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name);
1111 rc = -ENOMEM; 1109
1112 goto kmalloc_failed; 1110 err = __jfs_setxattr(*tid, inode, name,
1111 xattr->value, xattr->value_len, 0);
1112 kfree(name);
1113 if (err < 0)
1114 break;
1113 } 1115 }
1114 strcpy(name, XATTR_SECURITY_PREFIX); 1116 return err;
1115 strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix); 1117}
1116
1117 rc = __jfs_setxattr(tid, inode, name, value, len, 0);
1118
1119 kfree(name);
1120kmalloc_failed:
1121 kfree(suffix);
1122 kfree(value);
1123 1118
1124 return rc; 1119int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir,
1120 const struct qstr *qstr)
1121{
1122 return security_inode_init_security(inode, dir, qstr,
1123 &jfs_initxattrs, &tid);
1125} 1124}
1126#endif 1125#endif
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 81ecf9c0bf0a..194fb22ef79d 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -7185,20 +7185,9 @@ int ocfs2_init_security_and_acl(struct inode *dir,
7185{ 7185{
7186 int ret = 0; 7186 int ret = 0;
7187 struct buffer_head *dir_bh = NULL; 7187 struct buffer_head *dir_bh = NULL;
7188 struct ocfs2_security_xattr_info si = {
7189 .enable = 1,
7190 };
7191 7188
7192 ret = ocfs2_init_security_get(inode, dir, qstr, &si); 7189 ret = ocfs2_init_security_get(inode, dir, qstr, NULL);
7193 if (!ret) { 7190 if (!ret) {
7194 ret = ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY,
7195 si.name, si.value, si.value_len,
7196 XATTR_CREATE);
7197 if (ret) {
7198 mlog_errno(ret);
7199 goto leave;
7200 }
7201 } else if (ret != -EOPNOTSUPP) {
7202 mlog_errno(ret); 7191 mlog_errno(ret);
7203 goto leave; 7192 goto leave;
7204 } 7193 }
@@ -7255,6 +7244,22 @@ static int ocfs2_xattr_security_set(struct dentry *dentry, const char *name,
7255 name, value, size, flags); 7244 name, value, size, flags);
7256} 7245}
7257 7246
7247int ocfs2_initxattrs(struct inode *inode, const struct xattr *xattr_array,
7248 void *fs_info)
7249{
7250 const struct xattr *xattr;
7251 int err = 0;
7252
7253 for (xattr = xattr_array; xattr->name != NULL; xattr++) {
7254 err = ocfs2_xattr_set(inode, OCFS2_XATTR_INDEX_SECURITY,
7255 xattr->name, xattr->value,
7256 xattr->value_len, XATTR_CREATE);
7257 if (err)
7258 break;
7259 }
7260 return err;
7261}
7262
7258int ocfs2_init_security_get(struct inode *inode, 7263int ocfs2_init_security_get(struct inode *inode,
7259 struct inode *dir, 7264 struct inode *dir,
7260 const struct qstr *qstr, 7265 const struct qstr *qstr,
@@ -7263,8 +7268,13 @@ int ocfs2_init_security_get(struct inode *inode,
7263 /* check whether ocfs2 support feature xattr */ 7268 /* check whether ocfs2 support feature xattr */
7264 if (!ocfs2_supports_xattr(OCFS2_SB(dir->i_sb))) 7269 if (!ocfs2_supports_xattr(OCFS2_SB(dir->i_sb)))
7265 return -EOPNOTSUPP; 7270 return -EOPNOTSUPP;
7266 return security_inode_init_security(inode, dir, qstr, &si->name, 7271 if (si)
7267 &si->value, &si->value_len); 7272 return security_old_inode_init_security(inode, dir, qstr,
7273 &si->name, &si->value,
7274 &si->value_len);
7275
7276 return security_inode_init_security(inode, dir, qstr,
7277 &ocfs2_initxattrs, NULL);
7268} 7278}
7269 7279
7270int ocfs2_init_security_set(handle_t *handle, 7280int ocfs2_init_security_set(handle_t *handle,
diff --git a/fs/reiserfs/xattr_security.c b/fs/reiserfs/xattr_security.c
index ef66c18a9332..534668fa41be 100644
--- a/fs/reiserfs/xattr_security.c
+++ b/fs/reiserfs/xattr_security.c
@@ -66,8 +66,8 @@ int reiserfs_security_init(struct inode *dir, struct inode *inode,
66 if (IS_PRIVATE(dir)) 66 if (IS_PRIVATE(dir))
67 return 0; 67 return 0;
68 68
69 error = security_inode_init_security(inode, dir, qstr, &sec->name, 69 error = security_old_inode_init_security(inode, dir, qstr, &sec->name,
70 &sec->value, &sec->length); 70 &sec->value, &sec->length);
71 if (error) { 71 if (error) {
72 if (error == -EOPNOTSUPP) 72 if (error == -EOPNOTSUPP)
73 error = 0; 73 error = 0;
diff --git a/fs/xattr.c b/fs/xattr.c
index f060663ab70c..67583de8218c 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -14,6 +14,7 @@
14#include <linux/mount.h> 14#include <linux/mount.h>
15#include <linux/namei.h> 15#include <linux/namei.h>
16#include <linux/security.h> 16#include <linux/security.h>
17#include <linux/evm.h>
17#include <linux/syscalls.h> 18#include <linux/syscalls.h>
18#include <linux/module.h> 19#include <linux/module.h>
19#include <linux/fsnotify.h> 20#include <linux/fsnotify.h>
@@ -166,6 +167,64 @@ out_noalloc:
166} 167}
167EXPORT_SYMBOL_GPL(xattr_getsecurity); 168EXPORT_SYMBOL_GPL(xattr_getsecurity);
168 169
170/*
171 * vfs_getxattr_alloc - allocate memory, if necessary, before calling getxattr
172 *
173 * Allocate memory, if not already allocated, or re-allocate correct size,
174 * before retrieving the extended attribute.
175 *
176 * Returns the result of alloc, if failed, or the getxattr operation.
177 */
178ssize_t
179vfs_getxattr_alloc(struct dentry *dentry, const char *name, char **xattr_value,
180 size_t xattr_size, gfp_t flags)
181{
182 struct inode *inode = dentry->d_inode;
183 char *value = *xattr_value;
184 int error;
185
186 error = xattr_permission(inode, name, MAY_READ);
187 if (error)
188 return error;
189
190 if (!inode->i_op->getxattr)
191 return -EOPNOTSUPP;
192
193 error = inode->i_op->getxattr(dentry, name, NULL, 0);
194 if (error < 0)
195 return error;
196
197 if (!value || (error > xattr_size)) {
198 value = krealloc(*xattr_value, error + 1, flags);
199 if (!value)
200 return -ENOMEM;
201 memset(value, 0, error + 1);
202 }
203
204 error = inode->i_op->getxattr(dentry, name, value, error);
205 *xattr_value = value;
206 return error;
207}
208
209/* Compare an extended attribute value with the given value */
210int vfs_xattr_cmp(struct dentry *dentry, const char *xattr_name,
211 const char *value, size_t size, gfp_t flags)
212{
213 char *xattr_value = NULL;
214 int rc;
215
216 rc = vfs_getxattr_alloc(dentry, xattr_name, &xattr_value, 0, flags);
217 if (rc < 0)
218 return rc;
219
220 if ((rc != size) || (memcmp(xattr_value, value, rc) != 0))
221 rc = -EINVAL;
222 else
223 rc = 0;
224 kfree(xattr_value);
225 return rc;
226}
227
169ssize_t 228ssize_t
170vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size) 229vfs_getxattr(struct dentry *dentry, const char *name, void *value, size_t size)
171{ 230{
@@ -243,8 +302,10 @@ vfs_removexattr(struct dentry *dentry, const char *name)
243 error = inode->i_op->removexattr(dentry, name); 302 error = inode->i_op->removexattr(dentry, name);
244 mutex_unlock(&inode->i_mutex); 303 mutex_unlock(&inode->i_mutex);
245 304
246 if (!error) 305 if (!error) {
247 fsnotify_xattr(dentry); 306 fsnotify_xattr(dentry);
307 evm_inode_post_removexattr(dentry, name);
308 }
248 return error; 309 return error;
249} 310}
250EXPORT_SYMBOL_GPL(vfs_removexattr); 311EXPORT_SYMBOL_GPL(vfs_removexattr);
diff --git a/fs/xfs/xfs_iops.c b/fs/xfs/xfs_iops.c
index 673704fab748..28856accb4fa 100644
--- a/fs/xfs/xfs_iops.c
+++ b/fs/xfs/xfs_iops.c
@@ -102,37 +102,38 @@ xfs_mark_inode_dirty(
102 102
103} 103}
104 104
105
106int xfs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
107 void *fs_info)
108{
109 const struct xattr *xattr;
110 struct xfs_inode *ip = XFS_I(inode);
111 int error = 0;
112
113 for (xattr = xattr_array; xattr->name != NULL; xattr++) {
114 error = xfs_attr_set(ip, xattr->name, xattr->value,
115 xattr->value_len, ATTR_SECURE);
116 if (error < 0)
117 break;
118 }
119 return error;
120}
121
105/* 122/*
106 * Hook in SELinux. This is not quite correct yet, what we really need 123 * Hook in SELinux. This is not quite correct yet, what we really need
107 * here (as we do for default ACLs) is a mechanism by which creation of 124 * here (as we do for default ACLs) is a mechanism by which creation of
108 * these attrs can be journalled at inode creation time (along with the 125 * these attrs can be journalled at inode creation time (along with the
109 * inode, of course, such that log replay can't cause these to be lost). 126 * inode, of course, such that log replay can't cause these to be lost).
110 */ 127 */
128
111STATIC int 129STATIC int
112xfs_init_security( 130xfs_init_security(
113 struct inode *inode, 131 struct inode *inode,
114 struct inode *dir, 132 struct inode *dir,
115 const struct qstr *qstr) 133 const struct qstr *qstr)
116{ 134{
117 struct xfs_inode *ip = XFS_I(inode); 135 return security_inode_init_security(inode, dir, qstr,
118 size_t length; 136 &xfs_initxattrs, NULL);
119 void *value;
120 unsigned char *name;
121 int error;
122
123 error = security_inode_init_security(inode, dir, qstr, (char **)&name,
124 &value, &length);
125 if (error) {
126 if (error == -EOPNOTSUPP)
127 return 0;
128 return -error;
129 }
130
131 error = xfs_attr_set(ip, name, value, length, ATTR_SECURE);
132
133 kfree(name);
134 kfree(value);
135 return error;
136} 137}
137 138
138static void 139static void