aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMimi Zohar <zohar@linux.vnet.ibm.com>2011-06-06 15:29:25 -0400
committerMimi Zohar <zohar@linux.vnet.ibm.com>2011-07-18 12:29:38 -0400
commit9d8f13ba3f4833219e50767b022b82cd0da930eb (patch)
tree3ba2367380d009111ea17696162a62320c88d144
parent0f2a55d5bb2372058275b0b343d90dd5d640d045 (diff)
security: new security_inode_init_security API adds function callback
This patch changes the security_inode_init_security API by adding a filesystem specific callback to write security extended attributes. This change is in preparation for supporting the initialization of multiple LSM xattrs and the EVM xattr. Initially the callback function walks an array of xattrs, writing each xattr separately, but could be optimized to write multiple xattrs at once. For existing security_inode_init_security() calls, which have not yet been converted to use the new callback function, such as those in reiserfs and ocfs2, this patch defines security_old_inode_init_security(). Signed-off-by: Mimi Zohar <zohar@us.ibm.com>
-rw-r--r--fs/btrfs/xattr.c50
-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/xfs/linux-2.6/xfs_iops.c39
-rw-r--r--include/linux/security.h17
-rw-r--r--include/linux/xattr.h6
-rw-r--r--mm/shmem.c4
-rw-r--r--security/security.c39
14 files changed, 250 insertions, 183 deletions
diff --git a/fs/btrfs/xattr.c b/fs/btrfs/xattr.c
index 5366fe452ab0..a039e6ed4ce0 100644
--- a/fs/btrfs/xattr.c
+++ b/fs/btrfs/xattr.c
@@ -360,36 +360,36 @@ int btrfs_removexattr(struct dentry *dentry, const char *name)
360 XATTR_REPLACE); 360 XATTR_REPLACE);
361} 361}
362 362
363int btrfs_xattr_security_init(struct btrfs_trans_handle *trans, 363int btrfs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
364 struct inode *inode, struct inode *dir, 364 void *fs_info)
365 const struct qstr *qstr)
366{ 365{
367 int err; 366 const struct xattr *xattr;
368 size_t len; 367 struct btrfs_trans_handle *trans = fs_info;
369 void *value;
370 char *suffix;
371 char *name; 368 char *name;
369 int err = 0;
372 370
373 err = security_inode_init_security(inode, dir, qstr, &suffix, &value, 371 for (xattr = xattr_array; xattr->name != NULL; xattr++) {
374 &len); 372 name = kmalloc(XATTR_SECURITY_PREFIX_LEN +
375 if (err) { 373 strlen(xattr->name) + 1, GFP_NOFS);
376 if (err == -EOPNOTSUPP) 374 if (!name) {
377 return 0; 375 err = -ENOMEM;
378 return err; 376 break;
379 } 377 }
380
381 name = kmalloc(XATTR_SECURITY_PREFIX_LEN + strlen(suffix) + 1,
382 GFP_NOFS);
383 if (!name) {
384 err = -ENOMEM;
385 } else {
386 strcpy(name, XATTR_SECURITY_PREFIX); 378 strcpy(name, XATTR_SECURITY_PREFIX);
387 strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix); 379 strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name);
388 err = __btrfs_setxattr(trans, inode, name, value, len, 0); 380 err = __btrfs_setxattr(trans, inode, name,
381 xattr->value, xattr->value_len, 0);
389 kfree(name); 382 kfree(name);
383 if (err < 0)
384 break;
390 } 385 }
391
392 kfree(suffix);
393 kfree(value);
394 return err; 386 return err;
395} 387}
388
389int btrfs_xattr_security_init(struct btrfs_trans_handle *trans,
390 struct inode *inode, struct inode *dir,
391 const struct qstr *qstr)
392{
393 return security_inode_init_security(inode, dir, qstr,
394 &btrfs_initxattrs, trans);
395}
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 03e0c529063e..1d3a1a651721 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 24838f1eeee5..e982509292f8 100644
--- a/fs/jfs/xattr.c
+++ b/fs/jfs/xattr.c
@@ -1091,38 +1091,37 @@ int jfs_removexattr(struct dentry *dentry, const char *name)
1091} 1091}
1092 1092
1093#ifdef CONFIG_JFS_SECURITY 1093#ifdef CONFIG_JFS_SECURITY
1094int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir, 1094int jfs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
1095 const struct qstr *qstr) 1095 void *fs_info)
1096{ 1096{
1097 int rc; 1097 const struct xattr *xattr;
1098 size_t len; 1098 tid_t *tid = fs_info;
1099 void *value;
1100 char *suffix;
1101 char *name; 1099 char *name;
1102 1100 int err = 0;
1103 rc = security_inode_init_security(inode, dir, qstr, &suffix, &value, 1101
1104 &len); 1102 for (xattr = xattr_array; xattr->name != NULL; xattr++) {
1105 if (rc) { 1103 name = kmalloc(XATTR_SECURITY_PREFIX_LEN +
1106 if (rc == -EOPNOTSUPP) 1104 strlen(xattr->name) + 1, GFP_NOFS);
1107 return 0; 1105 if (!name) {
1108 return rc; 1106 err = -ENOMEM;
1109 } 1107 break;
1110 name = kmalloc(XATTR_SECURITY_PREFIX_LEN + 1 + strlen(suffix), 1108 }
1111 GFP_NOFS); 1109 strcpy(name, XATTR_SECURITY_PREFIX);
1112 if (!name) { 1110 strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name);
1113 rc = -ENOMEM; 1111
1114 goto kmalloc_failed; 1112 err = __jfs_setxattr(*tid, inode, name,
1113 xattr->value, xattr->value_len, 0);
1114 kfree(name);
1115 if (err < 0)
1116 break;
1115 } 1117 }
1116 strcpy(name, XATTR_SECURITY_PREFIX); 1118 return err;
1117 strcpy(name + XATTR_SECURITY_PREFIX_LEN, suffix); 1119}
1118
1119 rc = __jfs_setxattr(tid, inode, name, value, len, 0);
1120
1121 kfree(name);
1122kmalloc_failed:
1123 kfree(suffix);
1124 kfree(value);
1125 1120
1126 return rc; 1121int jfs_init_security(tid_t tid, struct inode *inode, struct inode *dir,
1122 const struct qstr *qstr)
1123{
1124 return security_inode_init_security(inode, dir, qstr,
1125 &jfs_initxattrs, &tid);
1127} 1126}
1128#endif 1127#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/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c
index d44d92cd12b1..27a3658b830f 100644
--- a/fs/xfs/linux-2.6/xfs_iops.c
+++ b/fs/xfs/linux-2.6/xfs_iops.c
@@ -93,37 +93,38 @@ xfs_mark_inode_dirty(
93 mark_inode_dirty(inode); 93 mark_inode_dirty(inode);
94} 94}
95 95
96
97int xfs_initxattrs(struct inode *inode, const struct xattr *xattr_array,
98 void *fs_info)
99{
100 const struct xattr *xattr;
101 struct xfs_inode *ip = XFS_I(inode);
102 int error = 0;
103
104 for (xattr = xattr_array; xattr->name != NULL; xattr++) {
105 error = xfs_attr_set(ip, xattr->name, xattr->value,
106 xattr->value_len, ATTR_SECURE);
107 if (error < 0)
108 break;
109 }
110 return error;
111}
112
96/* 113/*
97 * Hook in SELinux. This is not quite correct yet, what we really need 114 * Hook in SELinux. This is not quite correct yet, what we really need
98 * here (as we do for default ACLs) is a mechanism by which creation of 115 * here (as we do for default ACLs) is a mechanism by which creation of
99 * these attrs can be journalled at inode creation time (along with the 116 * these attrs can be journalled at inode creation time (along with the
100 * inode, of course, such that log replay can't cause these to be lost). 117 * inode, of course, such that log replay can't cause these to be lost).
101 */ 118 */
119
102STATIC int 120STATIC int
103xfs_init_security( 121xfs_init_security(
104 struct inode *inode, 122 struct inode *inode,
105 struct inode *dir, 123 struct inode *dir,
106 const struct qstr *qstr) 124 const struct qstr *qstr)
107{ 125{
108 struct xfs_inode *ip = XFS_I(inode); 126 return security_inode_init_security(inode, dir, qstr,
109 size_t length; 127 &xfs_initxattrs, NULL);
110 void *value;
111 unsigned char *name;
112 int error;
113
114 error = security_inode_init_security(inode, dir, qstr, (char **)&name,
115 &value, &length);
116 if (error) {
117 if (error == -EOPNOTSUPP)
118 return 0;
119 return -error;
120 }
121
122 error = xfs_attr_set(ip, name, value, length, ATTR_SECURE);
123
124 kfree(name);
125 kfree(value);
126 return error;
127} 128}
128 129
129static void 130static void
diff --git a/include/linux/security.h b/include/linux/security.h
index 8ce59ef3e5af..6a20c7025495 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -36,6 +36,7 @@
36#include <linux/key.h> 36#include <linux/key.h>
37#include <linux/xfrm.h> 37#include <linux/xfrm.h>
38#include <linux/slab.h> 38#include <linux/slab.h>
39#include <linux/xattr.h>
39#include <net/flow.h> 40#include <net/flow.h>
40 41
41/* Maximum number of letters for an LSM name string */ 42/* Maximum number of letters for an LSM name string */
@@ -147,6 +148,10 @@ extern int mmap_min_addr_handler(struct ctl_table *table, int write,
147 void __user *buffer, size_t *lenp, loff_t *ppos); 148 void __user *buffer, size_t *lenp, loff_t *ppos);
148#endif 149#endif
149 150
151/* security_inode_init_security callback function to write xattrs */
152typedef int (*initxattrs) (struct inode *inode,
153 const struct xattr *xattr_array, void *fs_data);
154
150#ifdef CONFIG_SECURITY 155#ifdef CONFIG_SECURITY
151 156
152struct security_mnt_opts { 157struct security_mnt_opts {
@@ -1704,8 +1709,11 @@ int security_sb_parse_opts_str(char *options, struct security_mnt_opts *opts);
1704int security_inode_alloc(struct inode *inode); 1709int security_inode_alloc(struct inode *inode);
1705void security_inode_free(struct inode *inode); 1710void security_inode_free(struct inode *inode);
1706int security_inode_init_security(struct inode *inode, struct inode *dir, 1711int security_inode_init_security(struct inode *inode, struct inode *dir,
1707 const struct qstr *qstr, char **name, 1712 const struct qstr *qstr,
1708 void **value, size_t *len); 1713 initxattrs initxattrs, void *fs_data);
1714int security_old_inode_init_security(struct inode *inode, struct inode *dir,
1715 const struct qstr *qstr, char **name,
1716 void **value, size_t *len);
1709int security_inode_create(struct inode *dir, struct dentry *dentry, int mode); 1717int security_inode_create(struct inode *dir, struct dentry *dentry, int mode);
1710int security_inode_link(struct dentry *old_dentry, struct inode *dir, 1718int security_inode_link(struct dentry *old_dentry, struct inode *dir,
1711 struct dentry *new_dentry); 1719 struct dentry *new_dentry);
@@ -2035,9 +2043,8 @@ static inline void security_inode_free(struct inode *inode)
2035static inline int security_inode_init_security(struct inode *inode, 2043static inline int security_inode_init_security(struct inode *inode,
2036 struct inode *dir, 2044 struct inode *dir,
2037 const struct qstr *qstr, 2045 const struct qstr *qstr,
2038 char **name, 2046 initxattrs initxattrs,
2039 void **value, 2047 void *fs_data)
2040 size_t *len)
2041{ 2048{
2042 return -EOPNOTSUPP; 2049 return -EOPNOTSUPP;
2043} 2050}
diff --git a/include/linux/xattr.h b/include/linux/xattr.h
index aed54c50aa66..7a378662ddff 100644
--- a/include/linux/xattr.h
+++ b/include/linux/xattr.h
@@ -67,6 +67,12 @@ struct xattr_handler {
67 size_t size, int flags, int handler_flags); 67 size_t size, int flags, int handler_flags);
68}; 68};
69 69
70struct xattr {
71 char *name;
72 void *value;
73 size_t value_len;
74};
75
70ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t); 76ssize_t xattr_getsecurity(struct inode *, const char *, void *, size_t);
71ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t); 77ssize_t vfs_getxattr(struct dentry *, const char *, void *, size_t);
72ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size); 78ssize_t vfs_listxattr(struct dentry *d, char *list, size_t size);
diff --git a/mm/shmem.c b/mm/shmem.c
index fcedf5464eb7..01c19c62d685 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -1878,7 +1878,7 @@ shmem_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
1878 inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE); 1878 inode = shmem_get_inode(dir->i_sb, dir, mode, dev, VM_NORESERVE);
1879 if (inode) { 1879 if (inode) {
1880 error = security_inode_init_security(inode, dir, 1880 error = security_inode_init_security(inode, dir,
1881 &dentry->d_name, NULL, 1881 &dentry->d_name,
1882 NULL, NULL); 1882 NULL, NULL);
1883 if (error) { 1883 if (error) {
1884 if (error != -EOPNOTSUPP) { 1884 if (error != -EOPNOTSUPP) {
@@ -2018,7 +2018,7 @@ static int shmem_symlink(struct inode *dir, struct dentry *dentry, const char *s
2018 if (!inode) 2018 if (!inode)
2019 return -ENOSPC; 2019 return -ENOSPC;
2020 2020
2021 error = security_inode_init_security(inode, dir, &dentry->d_name, NULL, 2021 error = security_inode_init_security(inode, dir, &dentry->d_name,
2022 NULL, NULL); 2022 NULL, NULL);
2023 if (error) { 2023 if (error) {
2024 if (error != -EOPNOTSUPP) { 2024 if (error != -EOPNOTSUPP) {
diff --git a/security/security.c b/security/security.c
index 4ba6d4cc061f..3464d58a5766 100644
--- a/security/security.c
+++ b/security/security.c
@@ -18,6 +18,8 @@
18#include <linux/security.h> 18#include <linux/security.h>
19#include <linux/ima.h> 19#include <linux/ima.h>
20 20
21#define MAX_LSM_XATTR 1
22
21/* Boot-time LSM user choice */ 23/* Boot-time LSM user choice */
22static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = 24static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] =
23 CONFIG_DEFAULT_SECURITY; 25 CONFIG_DEFAULT_SECURITY;
@@ -339,15 +341,46 @@ void security_inode_free(struct inode *inode)
339} 341}
340 342
341int security_inode_init_security(struct inode *inode, struct inode *dir, 343int security_inode_init_security(struct inode *inode, struct inode *dir,
342 const struct qstr *qstr, char **name, 344 const struct qstr *qstr,
343 void **value, size_t *len) 345 const initxattrs initxattrs, void *fs_data)
346{
347 struct xattr new_xattrs[MAX_LSM_XATTR + 1];
348 struct xattr *lsm_xattr;
349 int ret;
350
351 if (unlikely(IS_PRIVATE(inode)))
352 return -EOPNOTSUPP;
353
354 memset(new_xattrs, 0, sizeof new_xattrs);
355 if (!initxattrs)
356 return security_ops->inode_init_security(inode, dir, qstr,
357 NULL, NULL, NULL);
358 lsm_xattr = new_xattrs;
359 ret = security_ops->inode_init_security(inode, dir, qstr,
360 &lsm_xattr->name,
361 &lsm_xattr->value,
362 &lsm_xattr->value_len);
363 if (ret)
364 goto out;
365 ret = initxattrs(inode, new_xattrs, fs_data);
366out:
367 kfree(lsm_xattr->name);
368 kfree(lsm_xattr->value);
369
370 return (ret == -EOPNOTSUPP) ? 0 : ret;
371}
372EXPORT_SYMBOL(security_inode_init_security);
373
374int security_old_inode_init_security(struct inode *inode, struct inode *dir,
375 const struct qstr *qstr, char **name,
376 void **value, size_t *len)
344{ 377{
345 if (unlikely(IS_PRIVATE(inode))) 378 if (unlikely(IS_PRIVATE(inode)))
346 return -EOPNOTSUPP; 379 return -EOPNOTSUPP;
347 return security_ops->inode_init_security(inode, dir, qstr, name, value, 380 return security_ops->inode_init_security(inode, dir, qstr, name, value,
348 len); 381 len);
349} 382}
350EXPORT_SYMBOL(security_inode_init_security); 383EXPORT_SYMBOL(security_old_inode_init_security);
351 384
352#ifdef CONFIG_SECURITY_PATH 385#ifdef CONFIG_SECURITY_PATH
353int security_path_mknod(struct path *dir, struct dentry *dentry, int mode, 386int security_path_mknod(struct path *dir, struct dentry *dentry, int mode,