aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorCasey Schaufler <casey@schaufler-ca.com>2011-01-17 11:05:27 -0500
committerCasey Schaufler <casey@schaufler-ca.com>2011-01-17 11:05:27 -0500
commit7898e1f8e9eb1bee88c92d636e0ab93f2cbe31c6 (patch)
treed4aaa367bb42d0ff9d1e4ba227f248b5b9cd7687 /security
parentaeda4ac3efc29e4d55989abd0a73530453aa69ba (diff)
Subject: [PATCH] Smack: mmap controls for library containment
In the embedded world there are often situations where libraries are updated from a variety of sources, for a variety of reasons, and with any number of security characteristics. These differences might include privilege required for a given library provided interface to function properly, as occurs from time to time in graphics libraries. There are also cases where it is important to limit use of libraries based on the provider of the library and the security aware application may make choices based on that criteria. These issues are addressed by providing an additional Smack label that may optionally be assigned to an object, the SMACK64MMAP attribute. An mmap operation is allowed if there is no such attribute. If there is a SMACK64MMAP attribute the mmap is permitted only if a subject with that label has all of the access permitted a subject with the current task label. Security aware applications may from time to time wish to reduce their "privilege" to avoid accidental use of privilege. One case where this arises is the environment in which multiple sources provide libraries to perform the same functions. An application may know that it should eschew services made available from a particular vendor, or of a particular version. In support of this a secondary list of Smack rules has been added that is local to the task. This list is consulted only in the case where the global list has approved access. It can only further restrict access. Unlike the global last, if no entry is found on the local list access is granted. An application can add entries to its own list by writing to /smack/load-self. The changes appear large as they involve refactoring the list handling to accomodate there being more than one rule list. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Diffstat (limited to 'security')
-rw-r--r--security/smack/smack.h9
-rw-r--r--security/smack/smack_access.c52
-rw-r--r--security/smack/smack_lsm.c269
-rw-r--r--security/smack/smackfs.c370
4 files changed, 522 insertions, 178 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h
index 129c4eb8ffb1..e365d455ceb6 100644
--- a/security/smack/smack.h
+++ b/security/smack/smack.h
@@ -52,13 +52,16 @@ struct socket_smack {
52struct inode_smack { 52struct inode_smack {
53 char *smk_inode; /* label of the fso */ 53 char *smk_inode; /* label of the fso */
54 char *smk_task; /* label of the task */ 54 char *smk_task; /* label of the task */
55 char *smk_mmap; /* label of the mmap domain */
55 struct mutex smk_lock; /* initialization lock */ 56 struct mutex smk_lock; /* initialization lock */
56 int smk_flags; /* smack inode flags */ 57 int smk_flags; /* smack inode flags */
57}; 58};
58 59
59struct task_smack { 60struct task_smack {
60 char *smk_task; /* label used for access control */ 61 char *smk_task; /* label for access control */
61 char *smk_forked; /* label when forked */ 62 char *smk_forked; /* label when forked */
63 struct list_head smk_rules; /* per task access rules */
64 struct mutex smk_rules_lock; /* lock for the rules */
62}; 65};
63 66
64#define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ 67#define SMK_INODE_INSTANT 0x01 /* inode is instantiated */
@@ -202,7 +205,7 @@ struct inode_smack *new_inode_smack(char *);
202/* 205/*
203 * These functions are in smack_access.c 206 * These functions are in smack_access.c
204 */ 207 */
205int smk_access_entry(char *, char *); 208int smk_access_entry(char *, char *, struct list_head *);
206int smk_access(char *, char *, int, struct smk_audit_info *); 209int smk_access(char *, char *, int, struct smk_audit_info *);
207int smk_curacc(char *, u32, struct smk_audit_info *); 210int smk_curacc(char *, u32, struct smk_audit_info *);
208int smack_to_cipso(const char *, struct smack_cipso *); 211int smack_to_cipso(const char *, struct smack_cipso *);
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c
index 7ba8478f599e..86453db4333d 100644
--- a/security/smack/smack_access.c
+++ b/security/smack/smack_access.c
@@ -70,10 +70,11 @@ int log_policy = SMACK_AUDIT_DENIED;
70 * smk_access_entry - look up matching access rule 70 * smk_access_entry - look up matching access rule
71 * @subject_label: a pointer to the subject's Smack label 71 * @subject_label: a pointer to the subject's Smack label
72 * @object_label: a pointer to the object's Smack label 72 * @object_label: a pointer to the object's Smack label
73 * @rule_list: the list of rules to search
73 * 74 *
74 * This function looks up the subject/object pair in the 75 * This function looks up the subject/object pair in the
75 * access rule list and returns pointer to the matching rule if found, 76 * access rule list and returns the access mode. If no
76 * NULL otherwise. 77 * entry is found returns -ENOENT.
77 * 78 *
78 * NOTE: 79 * NOTE:
79 * Even though Smack labels are usually shared on smack_list 80 * Even though Smack labels are usually shared on smack_list
@@ -85,13 +86,13 @@ int log_policy = SMACK_AUDIT_DENIED;
85 * will be on the list, so checking the pointers may be a worthwhile 86 * will be on the list, so checking the pointers may be a worthwhile
86 * optimization. 87 * optimization.
87 */ 88 */
88int smk_access_entry(char *subject_label, char *object_label) 89int smk_access_entry(char *subject_label, char *object_label,
90 struct list_head *rule_list)
89{ 91{
90 u32 may = MAY_NOT; 92 int may = -ENOENT;
91 struct smack_rule *srp; 93 struct smack_rule *srp;
92 94
93 rcu_read_lock(); 95 list_for_each_entry_rcu(srp, rule_list, list) {
94 list_for_each_entry_rcu(srp, &smack_rule_list, list) {
95 if (srp->smk_subject == subject_label || 96 if (srp->smk_subject == subject_label ||
96 strcmp(srp->smk_subject, subject_label) == 0) { 97 strcmp(srp->smk_subject, subject_label) == 0) {
97 if (srp->smk_object == object_label || 98 if (srp->smk_object == object_label ||
@@ -101,7 +102,6 @@ int smk_access_entry(char *subject_label, char *object_label)
101 } 102 }
102 } 103 }
103 } 104 }
104 rcu_read_unlock();
105 105
106 return may; 106 return may;
107} 107}
@@ -129,7 +129,7 @@ int smk_access_entry(char *subject_label, char *object_label)
129int smk_access(char *subject_label, char *object_label, int request, 129int smk_access(char *subject_label, char *object_label, int request,
130 struct smk_audit_info *a) 130 struct smk_audit_info *a)
131{ 131{
132 u32 may = MAY_NOT; 132 int may = MAY_NOT;
133 int rc = 0; 133 int rc = 0;
134 134
135 /* 135 /*
@@ -181,13 +181,14 @@ int smk_access(char *subject_label, char *object_label, int request,
181 * Beyond here an explicit relationship is required. 181 * Beyond here an explicit relationship is required.
182 * If the requested access is contained in the available 182 * If the requested access is contained in the available
183 * access (e.g. read is included in readwrite) it's 183 * access (e.g. read is included in readwrite) it's
184 * good. 184 * good. A negative response from smk_access_entry()
185 */ 185 * indicates there is no entry for this pair.
186 may = smk_access_entry(subject_label, object_label);
187 /*
188 * This is a bit map operation.
189 */ 186 */
190 if ((request & may) == request) 187 rcu_read_lock();
188 may = smk_access_entry(subject_label, object_label, &smack_rule_list);
189 rcu_read_unlock();
190
191 if (may > 0 && (request & may) == request)
191 goto out_audit; 192 goto out_audit;
192 193
193 rc = -EACCES; 194 rc = -EACCES;
@@ -212,12 +213,27 @@ out_audit:
212 */ 213 */
213int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) 214int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
214{ 215{
216 struct task_smack *tsp = current_security();
217 char *sp = smk_of_task(tsp);
218 int may;
215 int rc; 219 int rc;
216 char *sp = smk_of_current();
217 220
221 /*
222 * Check the global rule list
223 */
218 rc = smk_access(sp, obj_label, mode, NULL); 224 rc = smk_access(sp, obj_label, mode, NULL);
219 if (rc == 0) 225 if (rc == 0) {
220 goto out_audit; 226 /*
227 * If there is an entry in the task's rule list
228 * it can further restrict access.
229 */
230 may = smk_access_entry(sp, obj_label, &tsp->smk_rules);
231 if (may < 0)
232 goto out_audit;
233 if ((mode & may) == mode)
234 goto out_audit;
235 rc = -EACCES;
236 }
221 237
222 /* 238 /*
223 * Return if a specific label has been designated as the 239 * Return if a specific label has been designated as the
@@ -228,7 +244,7 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a)
228 goto out_audit; 244 goto out_audit;
229 245
230 if (capable(CAP_MAC_OVERRIDE)) 246 if (capable(CAP_MAC_OVERRIDE))
231 return 0; 247 rc = 0;
232 248
233out_audit: 249out_audit:
234#ifdef CONFIG_AUDIT 250#ifdef CONFIG_AUDIT
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 533bf3255d7f..123a499ded37 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -84,6 +84,56 @@ struct inode_smack *new_inode_smack(char *smack)
84 return isp; 84 return isp;
85} 85}
86 86
87/**
88 * new_task_smack - allocate a task security blob
89 * @smack: a pointer to the Smack label to use in the blob
90 *
91 * Returns the new blob or NULL if there's no memory available
92 */
93static struct task_smack *new_task_smack(char *task, char *forked, gfp_t gfp)
94{
95 struct task_smack *tsp;
96
97 tsp = kzalloc(sizeof(struct task_smack), gfp);
98 if (tsp == NULL)
99 return NULL;
100
101 tsp->smk_task = task;
102 tsp->smk_forked = forked;
103 INIT_LIST_HEAD(&tsp->smk_rules);
104 mutex_init(&tsp->smk_rules_lock);
105
106 return tsp;
107}
108
109/**
110 * smk_copy_rules - copy a rule set
111 * @nhead - new rules header pointer
112 * @ohead - old rules header pointer
113 *
114 * Returns 0 on success, -ENOMEM on error
115 */
116static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead,
117 gfp_t gfp)
118{
119 struct smack_rule *nrp;
120 struct smack_rule *orp;
121 int rc = 0;
122
123 INIT_LIST_HEAD(nhead);
124
125 list_for_each_entry_rcu(orp, ohead, list) {
126 nrp = kzalloc(sizeof(struct smack_rule), gfp);
127 if (nrp == NULL) {
128 rc = -ENOMEM;
129 break;
130 }
131 *nrp = *orp;
132 list_add_rcu(&nrp->list, nhead);
133 }
134 return rc;
135}
136
87/* 137/*
88 * LSM hooks. 138 * LSM hooks.
89 * We he, that is fun! 139 * We he, that is fun!
@@ -102,23 +152,17 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)
102{ 152{
103 int rc; 153 int rc;
104 struct smk_audit_info ad; 154 struct smk_audit_info ad;
105 char *sp, *tsp; 155 char *tsp;
106 156
107 rc = cap_ptrace_access_check(ctp, mode); 157 rc = cap_ptrace_access_check(ctp, mode);
108 if (rc != 0) 158 if (rc != 0)
109 return rc; 159 return rc;
110 160
111 sp = smk_of_current();
112 tsp = smk_of_task(task_security(ctp)); 161 tsp = smk_of_task(task_security(ctp));
113 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); 162 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
114 smk_ad_setfield_u_tsk(&ad, ctp); 163 smk_ad_setfield_u_tsk(&ad, ctp);
115 164
116 /* we won't log here, because rc can be overriden */ 165 rc = smk_curacc(tsp, MAY_READWRITE, &ad);
117 rc = smk_access(sp, tsp, MAY_READWRITE, NULL);
118 if (rc != 0 && capable(CAP_MAC_OVERRIDE))
119 rc = 0;
120
121 smack_log(sp, tsp, MAY_READWRITE, rc, &ad);
122 return rc; 166 return rc;
123} 167}
124 168
@@ -134,23 +178,17 @@ static int smack_ptrace_traceme(struct task_struct *ptp)
134{ 178{
135 int rc; 179 int rc;
136 struct smk_audit_info ad; 180 struct smk_audit_info ad;
137 char *sp, *tsp; 181 char *tsp;
138 182
139 rc = cap_ptrace_traceme(ptp); 183 rc = cap_ptrace_traceme(ptp);
140 if (rc != 0) 184 if (rc != 0)
141 return rc; 185 return rc;
142 186
187 tsp = smk_of_task(task_security(ptp));
143 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); 188 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
144 smk_ad_setfield_u_tsk(&ad, ptp); 189 smk_ad_setfield_u_tsk(&ad, ptp);
145 190
146 sp = smk_of_current(); 191 rc = smk_curacc(tsp, MAY_READWRITE, &ad);
147 tsp = smk_of_task(task_security(ptp));
148 /* we won't log here, because rc can be overriden */
149 rc = smk_access(tsp, sp, MAY_READWRITE, NULL);
150 if (rc != 0 && has_capability(ptp, CAP_MAC_OVERRIDE))
151 rc = 0;
152
153 smack_log(tsp, sp, MAY_READWRITE, rc, &ad);
154 return rc; 192 return rc;
155} 193}
156 194
@@ -474,7 +512,7 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
474{ 512{
475 char *isp = smk_of_inode(inode); 513 char *isp = smk_of_inode(inode);
476 char *dsp = smk_of_inode(dir); 514 char *dsp = smk_of_inode(dir);
477 u32 may; 515 int may;
478 516
479 if (name) { 517 if (name) {
480 *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL); 518 *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL);
@@ -483,14 +521,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
483 } 521 }
484 522
485 if (value) { 523 if (value) {
486 may = smk_access_entry(smk_of_current(), dsp); 524 rcu_read_lock();
525 may = smk_access_entry(smk_of_current(), dsp, &smack_rule_list);
526 rcu_read_unlock();
487 527
488 /* 528 /*
489 * If the access rule allows transmutation and 529 * If the access rule allows transmutation and
490 * the directory requests transmutation then 530 * the directory requests transmutation then
491 * by all means transmute. 531 * by all means transmute.
492 */ 532 */
493 if (((may & MAY_TRANSMUTE) != 0) && smk_inode_transmutable(dir)) 533 if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
534 smk_inode_transmutable(dir))
494 isp = dsp; 535 isp = dsp;
495 536
496 *value = kstrdup(isp, GFP_KERNEL); 537 *value = kstrdup(isp, GFP_KERNEL);
@@ -716,7 +757,8 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
716 if (strcmp(name, XATTR_NAME_SMACK) == 0 || 757 if (strcmp(name, XATTR_NAME_SMACK) == 0 ||
717 strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || 758 strcmp(name, XATTR_NAME_SMACKIPIN) == 0 ||
718 strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || 759 strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 ||
719 strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { 760 strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
761 strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
720 if (!capable(CAP_MAC_ADMIN)) 762 if (!capable(CAP_MAC_ADMIN))
721 rc = -EPERM; 763 rc = -EPERM;
722 /* 764 /*
@@ -773,6 +815,12 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
773 isp->smk_task = nsp; 815 isp->smk_task = nsp;
774 else 816 else
775 isp->smk_task = smack_known_invalid.smk_known; 817 isp->smk_task = smack_known_invalid.smk_known;
818 } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
819 nsp = smk_import(value, size);
820 if (nsp != NULL)
821 isp->smk_mmap = nsp;
822 else
823 isp->smk_mmap = smack_known_invalid.smk_known;
776 } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) 824 } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0)
777 isp->smk_flags |= SMK_INODE_TRANSMUTE; 825 isp->smk_flags |= SMK_INODE_TRANSMUTE;
778 826
@@ -815,7 +863,8 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
815 strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || 863 strcmp(name, XATTR_NAME_SMACKIPIN) == 0 ||
816 strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || 864 strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 ||
817 strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || 865 strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
818 strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { 866 strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 ||
867 strcmp(name, XATTR_NAME_SMACKMMAP)) {
819 if (!capable(CAP_MAC_ADMIN)) 868 if (!capable(CAP_MAC_ADMIN))
820 rc = -EPERM; 869 rc = -EPERM;
821 } else 870 } else
@@ -829,6 +878,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
829 if (rc == 0) { 878 if (rc == 0) {
830 isp = dentry->d_inode->i_security; 879 isp = dentry->d_inode->i_security;
831 isp->smk_task = NULL; 880 isp->smk_task = NULL;
881 isp->smk_mmap = NULL;
832 } 882 }
833 883
834 return rc; 884 return rc;
@@ -1060,6 +1110,113 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
1060} 1110}
1061 1111
1062/** 1112/**
1113 * smk_mmap_list_check - the mmap check
1114 * @sub: subject label
1115 * @obj: object label
1116 * @access: access mode
1117 * @local: the task specific rule list
1118 *
1119 * Returns 0 if acces is permitted, -EACCES otherwise
1120 */
1121static int smk_mmap_list_check(char *sub, char *obj, int access,
1122 struct list_head *local)
1123{
1124 int may;
1125
1126 /*
1127 * If there is not a global rule that
1128 * allows access say no.
1129 */
1130 may = smk_access_entry(sub, obj, &smack_rule_list);
1131 if (may == -ENOENT || (may & access) != access)
1132 return -EACCES;
1133 /*
1134 * If there is a task local rule that
1135 * denies access say no.
1136 */
1137 may = smk_access_entry(sub, obj, local);
1138 if (may != -ENOENT && (may & access) != access)
1139 return -EACCES;
1140
1141 return 0;
1142}
1143
1144/**
1145 * smack_file_mmap :
1146 * Check permissions for a mmap operation. The @file may be NULL, e.g.
1147 * if mapping anonymous memory.
1148 * @file contains the file structure for file to map (may be NULL).
1149 * @reqprot contains the protection requested by the application.
1150 * @prot contains the protection that will be applied by the kernel.
1151 * @flags contains the operational flags.
1152 * Return 0 if permission is granted.
1153 */
1154static int smack_file_mmap(struct file *file,
1155 unsigned long reqprot, unsigned long prot,
1156 unsigned long flags, unsigned long addr,
1157 unsigned long addr_only)
1158{
1159 struct smack_rule *srp;
1160 struct task_smack *tsp;
1161 char *sp;
1162 char *msmack;
1163 struct inode_smack *isp;
1164 struct dentry *dp;
1165 int rc;
1166
1167 /* do DAC check on address space usage */
1168 rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only);
1169 if (rc || addr_only)
1170 return rc;
1171
1172 if (file == NULL || file->f_dentry == NULL)
1173 return 0;
1174
1175 dp = file->f_dentry;
1176
1177 if (dp->d_inode == NULL)
1178 return 0;
1179
1180 isp = dp->d_inode->i_security;
1181 if (isp->smk_mmap == NULL)
1182 return 0;
1183 msmack = isp->smk_mmap;
1184
1185 tsp = current_security();
1186 sp = smk_of_current();
1187 rc = 0;
1188
1189 rcu_read_lock();
1190 /*
1191 * For each Smack rule associated with the subject
1192 * label verify that the SMACK64MMAP also has access
1193 * to that rule's object label.
1194 *
1195 * Because neither of the labels comes
1196 * from the networking code it is sufficient
1197 * to compare pointers.
1198 */
1199 list_for_each_entry_rcu(srp, &smack_rule_list, list) {
1200 if (srp->smk_subject != sp)
1201 continue;
1202 /*
1203 * Matching labels always allows access.
1204 */
1205 if (msmack == srp->smk_object)
1206 continue;
1207
1208 rc = smk_mmap_list_check(msmack, srp->smk_object,
1209 srp->smk_access, &tsp->smk_rules);
1210 if (rc != 0)
1211 break;
1212 }
1213
1214 rcu_read_unlock();
1215
1216 return rc;
1217}
1218
1219/**
1063 * smack_file_set_fowner - set the file security blob value 1220 * smack_file_set_fowner - set the file security blob value
1064 * @file: object in question 1221 * @file: object in question
1065 * 1222 *
@@ -1095,6 +1252,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk,
1095 * struct fown_struct is never outside the context of a struct file 1252 * struct fown_struct is never outside the context of a struct file
1096 */ 1253 */
1097 file = container_of(fown, struct file, f_owner); 1254 file = container_of(fown, struct file, f_owner);
1255
1098 /* we don't log here as rc can be overriden */ 1256 /* we don't log here as rc can be overriden */
1099 rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL); 1257 rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL);
1100 if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) 1258 if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE))
@@ -1145,9 +1303,14 @@ static int smack_file_receive(struct file *file)
1145 */ 1303 */
1146static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) 1304static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp)
1147{ 1305{
1148 cred->security = kzalloc(sizeof(struct task_smack), gfp); 1306 struct task_smack *tsp;
1149 if (cred->security == NULL) 1307
1308 tsp = new_task_smack(NULL, NULL, gfp);
1309 if (tsp == NULL)
1150 return -ENOMEM; 1310 return -ENOMEM;
1311
1312 cred->security = tsp;
1313
1151 return 0; 1314 return 0;
1152} 1315}
1153 1316
@@ -1156,13 +1319,24 @@ static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp)
1156 * smack_cred_free - "free" task-level security credentials 1319 * smack_cred_free - "free" task-level security credentials
1157 * @cred: the credentials in question 1320 * @cred: the credentials in question
1158 * 1321 *
1159 * Smack isn't using copies of blobs. Everyone
1160 * points to an immutable list. The blobs never go away.
1161 * There is no leak here.
1162 */ 1322 */
1163static void smack_cred_free(struct cred *cred) 1323static void smack_cred_free(struct cred *cred)
1164{ 1324{
1165 kfree(cred->security); 1325 struct task_smack *tsp = cred->security;
1326 struct smack_rule *rp;
1327 struct list_head *l;
1328 struct list_head *n;
1329
1330 if (tsp == NULL)
1331 return;
1332 cred->security = NULL;
1333
1334 list_for_each_safe(l, n, &tsp->smk_rules) {
1335 rp = list_entry(l, struct smack_rule, list);
1336 list_del(&rp->list);
1337 kfree(rp);
1338 }
1339 kfree(tsp);
1166} 1340}
1167 1341
1168/** 1342/**
@@ -1178,13 +1352,16 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old,
1178{ 1352{
1179 struct task_smack *old_tsp = old->security; 1353 struct task_smack *old_tsp = old->security;
1180 struct task_smack *new_tsp; 1354 struct task_smack *new_tsp;
1355 int rc;
1181 1356
1182 new_tsp = kzalloc(sizeof(struct task_smack), gfp); 1357 new_tsp = new_task_smack(old_tsp->smk_task, old_tsp->smk_task, gfp);
1183 if (new_tsp == NULL) 1358 if (new_tsp == NULL)
1184 return -ENOMEM; 1359 return -ENOMEM;
1185 1360
1186 new_tsp->smk_task = old_tsp->smk_task; 1361 rc = smk_copy_rules(&new_tsp->smk_rules, &old_tsp->smk_rules, gfp);
1187 new_tsp->smk_forked = old_tsp->smk_task; 1362 if (rc != 0)
1363 return rc;
1364
1188 new->security = new_tsp; 1365 new->security = new_tsp;
1189 return 0; 1366 return 0;
1190} 1367}
@@ -1203,6 +1380,11 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old)
1203 1380
1204 new_tsp->smk_task = old_tsp->smk_task; 1381 new_tsp->smk_task = old_tsp->smk_task;
1205 new_tsp->smk_forked = old_tsp->smk_task; 1382 new_tsp->smk_forked = old_tsp->smk_task;
1383 mutex_init(&new_tsp->smk_rules_lock);
1384 INIT_LIST_HEAD(&new_tsp->smk_rules);
1385
1386
1387 /* cbs copy rule list */
1206} 1388}
1207 1389
1208/** 1390/**
@@ -2419,6 +2601,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
2419 } 2601 }
2420 } 2602 }
2421 isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); 2603 isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp);
2604 isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp);
2422 2605
2423 dput(dp); 2606 dput(dp);
2424 break; 2607 break;
@@ -2478,6 +2661,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value)
2478static int smack_setprocattr(struct task_struct *p, char *name, 2661static int smack_setprocattr(struct task_struct *p, char *name,
2479 void *value, size_t size) 2662 void *value, size_t size)
2480{ 2663{
2664 int rc;
2481 struct task_smack *tsp; 2665 struct task_smack *tsp;
2482 struct task_smack *oldtsp; 2666 struct task_smack *oldtsp;
2483 struct cred *new; 2667 struct cred *new;
@@ -2513,13 +2697,16 @@ static int smack_setprocattr(struct task_struct *p, char *name,
2513 new = prepare_creds(); 2697 new = prepare_creds();
2514 if (new == NULL) 2698 if (new == NULL)
2515 return -ENOMEM; 2699 return -ENOMEM;
2516 tsp = kzalloc(sizeof(struct task_smack), GFP_KERNEL); 2700
2701 tsp = new_task_smack(newsmack, oldtsp->smk_forked, GFP_KERNEL);
2517 if (tsp == NULL) { 2702 if (tsp == NULL) {
2518 kfree(new); 2703 kfree(new);
2519 return -ENOMEM; 2704 return -ENOMEM;
2520 } 2705 }
2521 tsp->smk_task = newsmack; 2706 rc = smk_copy_rules(&tsp->smk_rules, &oldtsp->smk_rules, GFP_KERNEL);
2522 tsp->smk_forked = oldtsp->smk_forked; 2707 if (rc != 0)
2708 return rc;
2709
2523 new->security = tsp; 2710 new->security = tsp;
2524 commit_creds(new); 2711 commit_creds(new);
2525 return size; 2712 return size;
@@ -3221,6 +3408,7 @@ struct security_operations smack_ops = {
3221 .file_ioctl = smack_file_ioctl, 3408 .file_ioctl = smack_file_ioctl,
3222 .file_lock = smack_file_lock, 3409 .file_lock = smack_file_lock,
3223 .file_fcntl = smack_file_fcntl, 3410 .file_fcntl = smack_file_fcntl,
3411 .file_mmap = smack_file_mmap,
3224 .file_set_fowner = smack_file_set_fowner, 3412 .file_set_fowner = smack_file_set_fowner,
3225 .file_send_sigiotask = smack_file_send_sigiotask, 3413 .file_send_sigiotask = smack_file_send_sigiotask,
3226 .file_receive = smack_file_receive, 3414 .file_receive = smack_file_receive,
@@ -3334,23 +3522,20 @@ static __init int smack_init(void)
3334 struct cred *cred; 3522 struct cred *cred;
3335 struct task_smack *tsp; 3523 struct task_smack *tsp;
3336 3524
3337 tsp = kzalloc(sizeof(struct task_smack), GFP_KERNEL); 3525 if (!security_module_enable(&smack_ops))
3526 return 0;
3527
3528 tsp = new_task_smack(smack_known_floor.smk_known,
3529 smack_known_floor.smk_known, GFP_KERNEL);
3338 if (tsp == NULL) 3530 if (tsp == NULL)
3339 return -ENOMEM; 3531 return -ENOMEM;
3340 3532
3341 if (!security_module_enable(&smack_ops)) {
3342 kfree(tsp);
3343 return 0;
3344 }
3345
3346 printk(KERN_INFO "Smack: Initializing.\n"); 3533 printk(KERN_INFO "Smack: Initializing.\n");
3347 3534
3348 /* 3535 /*
3349 * Set the security state for the initial task. 3536 * Set the security state for the initial task.
3350 */ 3537 */
3351 cred = (struct cred *) current->cred; 3538 cred = (struct cred *) current->cred;
3352 tsp->smk_forked = smack_known_floor.smk_known;
3353 tsp->smk_task = smack_known_floor.smk_known;
3354 cred->security = tsp; 3539 cred->security = tsp;
3355 3540
3356 /* initialize the smack_know_list */ 3541 /* initialize the smack_know_list */
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index 362d5eda948b..90d1bbaaa6f3 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -43,6 +43,7 @@ enum smk_inos {
43 SMK_NETLBLADDR = 8, /* single label hosts */ 43 SMK_NETLBLADDR = 8, /* single label hosts */
44 SMK_ONLYCAP = 9, /* the only "capable" label */ 44 SMK_ONLYCAP = 9, /* the only "capable" label */
45 SMK_LOGGING = 10, /* logging */ 45 SMK_LOGGING = 10, /* logging */
46 SMK_LOAD_SELF = 11, /* task specific rules */
46}; 47};
47 48
48/* 49/*
@@ -135,104 +136,30 @@ static void smk_netlabel_audit_set(struct netlbl_audit *nap)
135#define SMK_NETLBLADDRMIN 9 136#define SMK_NETLBLADDRMIN 9
136#define SMK_NETLBLADDRMAX 42 137#define SMK_NETLBLADDRMAX 42
137 138
138/*
139 * Seq_file read operations for /smack/load
140 */
141
142static void *load_seq_start(struct seq_file *s, loff_t *pos)
143{
144 if (*pos == SEQ_READ_FINISHED)
145 return NULL;
146 if (list_empty(&smack_rule_list))
147 return NULL;
148 return smack_rule_list.next;
149}
150
151static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
152{
153 struct list_head *list = v;
154
155 if (list_is_last(list, &smack_rule_list)) {
156 *pos = SEQ_READ_FINISHED;
157 return NULL;
158 }
159 return list->next;
160}
161
162static int load_seq_show(struct seq_file *s, void *v)
163{
164 struct list_head *list = v;
165 struct smack_rule *srp =
166 list_entry(list, struct smack_rule, list);
167
168 seq_printf(s, "%s %s", (char *)srp->smk_subject,
169 (char *)srp->smk_object);
170
171 seq_putc(s, ' ');
172
173 if (srp->smk_access & MAY_READ)
174 seq_putc(s, 'r');
175 if (srp->smk_access & MAY_WRITE)
176 seq_putc(s, 'w');
177 if (srp->smk_access & MAY_EXEC)
178 seq_putc(s, 'x');
179 if (srp->smk_access & MAY_APPEND)
180 seq_putc(s, 'a');
181 if (srp->smk_access & MAY_TRANSMUTE)
182 seq_putc(s, 't');
183 if (srp->smk_access == 0)
184 seq_putc(s, '-');
185
186 seq_putc(s, '\n');
187
188 return 0;
189}
190
191static void load_seq_stop(struct seq_file *s, void *v)
192{
193 /* No-op */
194}
195
196static const struct seq_operations load_seq_ops = {
197 .start = load_seq_start,
198 .next = load_seq_next,
199 .show = load_seq_show,
200 .stop = load_seq_stop,
201};
202
203/**
204 * smk_open_load - open() for /smack/load
205 * @inode: inode structure representing file
206 * @file: "load" file pointer
207 *
208 * For reading, use load_seq_* seq_file reading operations.
209 */
210static int smk_open_load(struct inode *inode, struct file *file)
211{
212 return seq_open(file, &load_seq_ops);
213}
214
215/** 139/**
216 * smk_set_access - add a rule to the rule list 140 * smk_set_access - add a rule to the rule list
217 * @srp: the new rule to add 141 * @srp: the new rule to add
142 * @rule_list: the list of rules
143 * @rule_lock: the rule list lock
218 * 144 *
219 * Looks through the current subject/object/access list for 145 * Looks through the current subject/object/access list for
220 * the subject/object pair and replaces the access that was 146 * the subject/object pair and replaces the access that was
221 * there. If the pair isn't found add it with the specified 147 * there. If the pair isn't found add it with the specified
222 * access. 148 * access.
223 * 149 *
150 * Returns 1 if a rule was found to exist already, 0 if it is new
224 * Returns 0 if nothing goes wrong or -ENOMEM if it fails 151 * Returns 0 if nothing goes wrong or -ENOMEM if it fails
225 * during the allocation of the new pair to add. 152 * during the allocation of the new pair to add.
226 */ 153 */
227static int smk_set_access(struct smack_rule *srp) 154static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
155 struct mutex *rule_lock)
228{ 156{
229 struct smack_rule *sp; 157 struct smack_rule *sp;
230 int ret = 0; 158 int found = 0;
231 int found;
232 mutex_lock(&smack_list_lock);
233 159
234 found = 0; 160 mutex_lock(rule_lock);
235 list_for_each_entry_rcu(sp, &smack_rule_list, list) { 161
162 list_for_each_entry_rcu(sp, rule_list, list) {
236 if (sp->smk_subject == srp->smk_subject && 163 if (sp->smk_subject == srp->smk_subject &&
237 sp->smk_object == srp->smk_object) { 164 sp->smk_object == srp->smk_object) {
238 found = 1; 165 found = 1;
@@ -241,19 +168,21 @@ static int smk_set_access(struct smack_rule *srp)
241 } 168 }
242 } 169 }
243 if (found == 0) 170 if (found == 0)
244 list_add_rcu(&srp->list, &smack_rule_list); 171 list_add_rcu(&srp->list, rule_list);
245 172
246 mutex_unlock(&smack_list_lock); 173 mutex_unlock(rule_lock);
247 174
248 return ret; 175 return found;
249} 176}
250 177
251/** 178/**
252 * smk_write_load - write() for /smack/load 179 * smk_write_load_list - write() for any /smack/load
253 * @file: file pointer, not actually used 180 * @file: file pointer, not actually used
254 * @buf: where to get the data from 181 * @buf: where to get the data from
255 * @count: bytes sent 182 * @count: bytes sent
256 * @ppos: where to start - must be 0 183 * @ppos: where to start - must be 0
184 * @rule_list: the list of rules to write to
185 * @rule_lock: lock for the rule list
257 * 186 *
258 * Get one smack access rule from above. 187 * Get one smack access rule from above.
259 * The format is exactly: 188 * The format is exactly:
@@ -263,21 +192,19 @@ static int smk_set_access(struct smack_rule *srp)
263 * 192 *
264 * writes must be SMK_LABELLEN+SMK_LABELLEN+SMK_ACCESSLEN bytes. 193 * writes must be SMK_LABELLEN+SMK_LABELLEN+SMK_ACCESSLEN bytes.
265 */ 194 */
266static ssize_t smk_write_load(struct file *file, const char __user *buf, 195static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
267 size_t count, loff_t *ppos) 196 size_t count, loff_t *ppos,
197 struct list_head *rule_list,
198 struct mutex *rule_lock)
268{ 199{
269 struct smack_rule *rule; 200 struct smack_rule *rule;
270 char *data; 201 char *data;
271 int rc = -EINVAL; 202 int rc = -EINVAL;
272 203
273 /* 204 /*
274 * Must have privilege.
275 * No partial writes. 205 * No partial writes.
276 * Enough data must be present. 206 * Enough data must be present.
277 */ 207 */
278 if (!capable(CAP_MAC_ADMIN))
279 return -EPERM;
280
281 if (*ppos != 0) 208 if (*ppos != 0)
282 return -EINVAL; 209 return -EINVAL;
283 /* 210 /*
@@ -372,11 +299,13 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf,
372 goto out_free_rule; 299 goto out_free_rule;
373 } 300 }
374 301
375 rc = smk_set_access(rule); 302 rc = count;
376 303 /*
377 if (!rc) 304 * smk_set_access returns true if there was already a rule
378 rc = count; 305 * for the subject/object pair, and false if it was new.
379 goto out; 306 */
307 if (!smk_set_access(rule, rule_list, rule_lock))
308 goto out;
380 309
381out_free_rule: 310out_free_rule:
382 kfree(rule); 311 kfree(rule);
@@ -385,6 +314,108 @@ out:
385 return rc; 314 return rc;
386} 315}
387 316
317
318/*
319 * Seq_file read operations for /smack/load
320 */
321
322static void *load_seq_start(struct seq_file *s, loff_t *pos)
323{
324 if (*pos == SEQ_READ_FINISHED)
325 return NULL;
326 if (list_empty(&smack_rule_list))
327 return NULL;
328 return smack_rule_list.next;
329}
330
331static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
332{
333 struct list_head *list = v;
334
335 if (list_is_last(list, &smack_rule_list)) {
336 *pos = SEQ_READ_FINISHED;
337 return NULL;
338 }
339 return list->next;
340}
341
342static int load_seq_show(struct seq_file *s, void *v)
343{
344 struct list_head *list = v;
345 struct smack_rule *srp =
346 list_entry(list, struct smack_rule, list);
347
348 seq_printf(s, "%s %s", (char *)srp->smk_subject,
349 (char *)srp->smk_object);
350
351 seq_putc(s, ' ');
352
353 if (srp->smk_access & MAY_READ)
354 seq_putc(s, 'r');
355 if (srp->smk_access & MAY_WRITE)
356 seq_putc(s, 'w');
357 if (srp->smk_access & MAY_EXEC)
358 seq_putc(s, 'x');
359 if (srp->smk_access & MAY_APPEND)
360 seq_putc(s, 'a');
361 if (srp->smk_access & MAY_TRANSMUTE)
362 seq_putc(s, 't');
363 if (srp->smk_access == 0)
364 seq_putc(s, '-');
365
366 seq_putc(s, '\n');
367
368 return 0;
369}
370
371static void load_seq_stop(struct seq_file *s, void *v)
372{
373 /* No-op */
374}
375
376static const struct seq_operations load_seq_ops = {
377 .start = load_seq_start,
378 .next = load_seq_next,
379 .show = load_seq_show,
380 .stop = load_seq_stop,
381};
382
383/**
384 * smk_open_load - open() for /smack/load
385 * @inode: inode structure representing file
386 * @file: "load" file pointer
387 *
388 * For reading, use load_seq_* seq_file reading operations.
389 */
390static int smk_open_load(struct inode *inode, struct file *file)
391{
392 return seq_open(file, &load_seq_ops);
393}
394
395/**
396 * smk_write_load - write() for /smack/load
397 * @file: file pointer, not actually used
398 * @buf: where to get the data from
399 * @count: bytes sent
400 * @ppos: where to start - must be 0
401 *
402 */
403static ssize_t smk_write_load(struct file *file, const char __user *buf,
404 size_t count, loff_t *ppos)
405{
406
407 /*
408 * Must have privilege.
409 * No partial writes.
410 * Enough data must be present.
411 */
412 if (!capable(CAP_MAC_ADMIN))
413 return -EPERM;
414
415 return smk_write_load_list(file, buf, count, ppos, &smack_rule_list,
416 &smack_list_lock);
417}
418
388static const struct file_operations smk_load_ops = { 419static const struct file_operations smk_load_ops = {
389 .open = smk_open_load, 420 .open = smk_open_load,
390 .read = seq_read, 421 .read = seq_read,
@@ -1288,6 +1319,112 @@ static const struct file_operations smk_logging_ops = {
1288 .write = smk_write_logging, 1319 .write = smk_write_logging,
1289 .llseek = default_llseek, 1320 .llseek = default_llseek,
1290}; 1321};
1322
1323/*
1324 * Seq_file read operations for /smack/load-self
1325 */
1326
1327static void *load_self_seq_start(struct seq_file *s, loff_t *pos)
1328{
1329 struct task_smack *tsp = current_security();
1330
1331 if (*pos == SEQ_READ_FINISHED)
1332 return NULL;
1333 if (list_empty(&tsp->smk_rules))
1334 return NULL;
1335 return tsp->smk_rules.next;
1336}
1337
1338static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos)
1339{
1340 struct task_smack *tsp = current_security();
1341 struct list_head *list = v;
1342
1343 if (list_is_last(list, &tsp->smk_rules)) {
1344 *pos = SEQ_READ_FINISHED;
1345 return NULL;
1346 }
1347 return list->next;
1348}
1349
1350static int load_self_seq_show(struct seq_file *s, void *v)
1351{
1352 struct list_head *list = v;
1353 struct smack_rule *srp =
1354 list_entry(list, struct smack_rule, list);
1355
1356 seq_printf(s, "%s %s", (char *)srp->smk_subject,
1357 (char *)srp->smk_object);
1358
1359 seq_putc(s, ' ');
1360
1361 if (srp->smk_access & MAY_READ)
1362 seq_putc(s, 'r');
1363 if (srp->smk_access & MAY_WRITE)
1364 seq_putc(s, 'w');
1365 if (srp->smk_access & MAY_EXEC)
1366 seq_putc(s, 'x');
1367 if (srp->smk_access & MAY_APPEND)
1368 seq_putc(s, 'a');
1369 if (srp->smk_access & MAY_TRANSMUTE)
1370 seq_putc(s, 't');
1371 if (srp->smk_access == 0)
1372 seq_putc(s, '-');
1373
1374 seq_putc(s, '\n');
1375
1376 return 0;
1377}
1378
1379static void load_self_seq_stop(struct seq_file *s, void *v)
1380{
1381 /* No-op */
1382}
1383
1384static const struct seq_operations load_self_seq_ops = {
1385 .start = load_self_seq_start,
1386 .next = load_self_seq_next,
1387 .show = load_self_seq_show,
1388 .stop = load_self_seq_stop,
1389};
1390
1391
1392/**
1393 * smk_open_load_self - open() for /smack/load-self
1394 * @inode: inode structure representing file
1395 * @file: "load" file pointer
1396 *
1397 * For reading, use load_seq_* seq_file reading operations.
1398 */
1399static int smk_open_load_self(struct inode *inode, struct file *file)
1400{
1401 return seq_open(file, &load_self_seq_ops);
1402}
1403
1404/**
1405 * smk_write_load_self - write() for /smack/load-self
1406 * @file: file pointer, not actually used
1407 * @buf: where to get the data from
1408 * @count: bytes sent
1409 * @ppos: where to start - must be 0
1410 *
1411 */
1412static ssize_t smk_write_load_self(struct file *file, const char __user *buf,
1413 size_t count, loff_t *ppos)
1414{
1415 struct task_smack *tsp = current_security();
1416
1417 return smk_write_load_list(file, buf, count, ppos, &tsp->smk_rules,
1418 &tsp->smk_rules_lock);
1419}
1420
1421static const struct file_operations smk_load_self_ops = {
1422 .open = smk_open_load_self,
1423 .read = seq_read,
1424 .llseek = seq_lseek,
1425 .write = smk_write_load_self,
1426 .release = seq_release,
1427};
1291/** 1428/**
1292 * smk_fill_super - fill the /smackfs superblock 1429 * smk_fill_super - fill the /smackfs superblock
1293 * @sb: the empty superblock 1430 * @sb: the empty superblock
@@ -1304,23 +1441,26 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
1304 struct inode *root_inode; 1441 struct inode *root_inode;
1305 1442
1306 static struct tree_descr smack_files[] = { 1443 static struct tree_descr smack_files[] = {
1307 [SMK_LOAD] = 1444 [SMK_LOAD] = {
1308 {"load", &smk_load_ops, S_IRUGO|S_IWUSR}, 1445 "load", &smk_load_ops, S_IRUGO|S_IWUSR},
1309 [SMK_CIPSO] = 1446 [SMK_CIPSO] = {
1310 {"cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR}, 1447 "cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR},
1311 [SMK_DOI] = 1448 [SMK_DOI] = {
1312 {"doi", &smk_doi_ops, S_IRUGO|S_IWUSR}, 1449 "doi", &smk_doi_ops, S_IRUGO|S_IWUSR},
1313 [SMK_DIRECT] = 1450 [SMK_DIRECT] = {
1314 {"direct", &smk_direct_ops, S_IRUGO|S_IWUSR}, 1451 "direct", &smk_direct_ops, S_IRUGO|S_IWUSR},
1315 [SMK_AMBIENT] = 1452 [SMK_AMBIENT] = {
1316 {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR}, 1453 "ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
1317 [SMK_NETLBLADDR] = 1454 [SMK_NETLBLADDR] = {
1318 {"netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR}, 1455 "netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR},
1319 [SMK_ONLYCAP] = 1456 [SMK_ONLYCAP] = {
1320 {"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR}, 1457 "onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
1321 [SMK_LOGGING] = 1458 [SMK_LOGGING] = {
1322 {"logging", &smk_logging_ops, S_IRUGO|S_IWUSR}, 1459 "logging", &smk_logging_ops, S_IRUGO|S_IWUSR},
1323 /* last one */ {""} 1460 [SMK_LOAD_SELF] = {
1461 "load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO},
1462 /* last one */
1463 {""}
1324 }; 1464 };
1325 1465
1326 rc = simple_fill_super(sb, SMACK_MAGIC, smack_files); 1466 rc = simple_fill_super(sb, SMACK_MAGIC, smack_files);