diff options
Diffstat (limited to 'security/smack/smackfs.c')
-rw-r--r-- | security/smack/smackfs.c | 993 |
1 files changed, 761 insertions, 232 deletions
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 038811cb7e62..1810c9a4ed48 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <net/net_namespace.h> | 24 | #include <net/net_namespace.h> |
25 | #include <net/netlabel.h> | ||
26 | #include <net/cipso_ipv4.h> | 25 | #include <net/cipso_ipv4.h> |
27 | #include <linux/seq_file.h> | 26 | #include <linux/seq_file.h> |
28 | #include <linux/ctype.h> | 27 | #include <linux/ctype.h> |
@@ -45,6 +44,11 @@ enum smk_inos { | |||
45 | SMK_LOGGING = 10, /* logging */ | 44 | SMK_LOGGING = 10, /* logging */ |
46 | SMK_LOAD_SELF = 11, /* task specific rules */ | 45 | SMK_LOAD_SELF = 11, /* task specific rules */ |
47 | SMK_ACCESSES = 12, /* access policy */ | 46 | SMK_ACCESSES = 12, /* access policy */ |
47 | SMK_MAPPED = 13, /* CIPSO level indicating mapped label */ | ||
48 | SMK_LOAD2 = 14, /* load policy with long labels */ | ||
49 | SMK_LOAD_SELF2 = 15, /* load task specific rules with long labels */ | ||
50 | SMK_ACCESS2 = 16, /* make an access check with long labels */ | ||
51 | SMK_CIPSO2 = 17, /* load long label -> CIPSO mapping */ | ||
48 | }; | 52 | }; |
49 | 53 | ||
50 | /* | 54 | /* |
@@ -60,7 +64,7 @@ static DEFINE_MUTEX(smk_netlbladdr_lock); | |||
60 | * If it isn't somehow marked, use this. | 64 | * If it isn't somehow marked, use this. |
61 | * It can be reset via smackfs/ambient | 65 | * It can be reset via smackfs/ambient |
62 | */ | 66 | */ |
63 | char *smack_net_ambient = smack_known_floor.smk_known; | 67 | char *smack_net_ambient; |
64 | 68 | ||
65 | /* | 69 | /* |
66 | * This is the level in a CIPSO header that indicates a | 70 | * This is the level in a CIPSO header that indicates a |
@@ -70,6 +74,13 @@ char *smack_net_ambient = smack_known_floor.smk_known; | |||
70 | int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT; | 74 | int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT; |
71 | 75 | ||
72 | /* | 76 | /* |
77 | * This is the level in a CIPSO header that indicates a | ||
78 | * secid is contained directly in the category set. | ||
79 | * It can be reset via smackfs/mapped | ||
80 | */ | ||
81 | int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT; | ||
82 | |||
83 | /* | ||
73 | * Unless a process is running with this label even | 84 | * Unless a process is running with this label even |
74 | * having CAP_MAC_OVERRIDE isn't enough to grant | 85 | * having CAP_MAC_OVERRIDE isn't enough to grant |
75 | * privilege to violate MAC policy. If no label is | 86 | * privilege to violate MAC policy. If no label is |
@@ -89,7 +100,7 @@ LIST_HEAD(smk_netlbladdr_list); | |||
89 | 100 | ||
90 | /* | 101 | /* |
91 | * Rule lists are maintained for each label. | 102 | * Rule lists are maintained for each label. |
92 | * This master list is just for reading /smack/load. | 103 | * This master list is just for reading /smack/load and /smack/load2. |
93 | */ | 104 | */ |
94 | struct smack_master_list { | 105 | struct smack_master_list { |
95 | struct list_head list; | 106 | struct list_head list; |
@@ -125,6 +136,18 @@ const char *smack_cipso_option = SMACK_CIPSO_OPTION; | |||
125 | #define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN) | 136 | #define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN) |
126 | #define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN) | 137 | #define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN) |
127 | 138 | ||
139 | /* | ||
140 | * Stricly for CIPSO level manipulation. | ||
141 | * Set the category bit number in a smack label sized buffer. | ||
142 | */ | ||
143 | static inline void smack_catset_bit(unsigned int cat, char *catsetp) | ||
144 | { | ||
145 | if (cat == 0 || cat > (SMK_CIPSOLEN * 8)) | ||
146 | return; | ||
147 | |||
148 | catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8); | ||
149 | } | ||
150 | |||
128 | /** | 151 | /** |
129 | * smk_netlabel_audit_set - fill a netlbl_audit struct | 152 | * smk_netlabel_audit_set - fill a netlbl_audit struct |
130 | * @nap: structure to fill | 153 | * @nap: structure to fill |
@@ -137,12 +160,10 @@ static void smk_netlabel_audit_set(struct netlbl_audit *nap) | |||
137 | } | 160 | } |
138 | 161 | ||
139 | /* | 162 | /* |
140 | * Values for parsing single label host rules | 163 | * Value for parsing single label host rules |
141 | * "1.2.3.4 X" | 164 | * "1.2.3.4 X" |
142 | * "192.168.138.129/32 abcdefghijklmnopqrstuvw" | ||
143 | */ | 165 | */ |
144 | #define SMK_NETLBLADDRMIN 9 | 166 | #define SMK_NETLBLADDRMIN 9 |
145 | #define SMK_NETLBLADDRMAX 42 | ||
146 | 167 | ||
147 | /** | 168 | /** |
148 | * smk_set_access - add a rule to the rule list | 169 | * smk_set_access - add a rule to the rule list |
@@ -188,33 +209,47 @@ static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list, | |||
188 | } | 209 | } |
189 | 210 | ||
190 | /** | 211 | /** |
191 | * smk_parse_rule - parse Smack rule from load string | 212 | * smk_fill_rule - Fill Smack rule from strings |
192 | * @data: string to be parsed whose size is SMK_LOADLEN | 213 | * @subject: subject label string |
214 | * @object: object label string | ||
215 | * @access: access string | ||
193 | * @rule: Smack rule | 216 | * @rule: Smack rule |
194 | * @import: if non-zero, import labels | 217 | * @import: if non-zero, import labels |
218 | * | ||
219 | * Returns 0 on success, -1 on failure | ||
195 | */ | 220 | */ |
196 | static int smk_parse_rule(const char *data, struct smack_rule *rule, int import) | 221 | static int smk_fill_rule(const char *subject, const char *object, |
222 | const char *access, struct smack_rule *rule, | ||
223 | int import) | ||
197 | { | 224 | { |
198 | char smack[SMK_LABELLEN]; | 225 | int rc = -1; |
226 | int done; | ||
227 | const char *cp; | ||
199 | struct smack_known *skp; | 228 | struct smack_known *skp; |
200 | 229 | ||
201 | if (import) { | 230 | if (import) { |
202 | rule->smk_subject = smk_import(data, 0); | 231 | rule->smk_subject = smk_import(subject, 0); |
203 | if (rule->smk_subject == NULL) | 232 | if (rule->smk_subject == NULL) |
204 | return -1; | 233 | return -1; |
205 | 234 | ||
206 | rule->smk_object = smk_import(data + SMK_LABELLEN, 0); | 235 | rule->smk_object = smk_import(object, 0); |
207 | if (rule->smk_object == NULL) | 236 | if (rule->smk_object == NULL) |
208 | return -1; | 237 | return -1; |
209 | } else { | 238 | } else { |
210 | smk_parse_smack(data, 0, smack); | 239 | cp = smk_parse_smack(subject, 0); |
211 | skp = smk_find_entry(smack); | 240 | if (cp == NULL) |
241 | return -1; | ||
242 | skp = smk_find_entry(cp); | ||
243 | kfree(cp); | ||
212 | if (skp == NULL) | 244 | if (skp == NULL) |
213 | return -1; | 245 | return -1; |
214 | rule->smk_subject = skp->smk_known; | 246 | rule->smk_subject = skp->smk_known; |
215 | 247 | ||
216 | smk_parse_smack(data + SMK_LABELLEN, 0, smack); | 248 | cp = smk_parse_smack(object, 0); |
217 | skp = smk_find_entry(smack); | 249 | if (cp == NULL) |
250 | return -1; | ||
251 | skp = smk_find_entry(cp); | ||
252 | kfree(cp); | ||
218 | if (skp == NULL) | 253 | if (skp == NULL) |
219 | return -1; | 254 | return -1; |
220 | rule->smk_object = skp->smk_known; | 255 | rule->smk_object = skp->smk_known; |
@@ -222,90 +257,127 @@ static int smk_parse_rule(const char *data, struct smack_rule *rule, int import) | |||
222 | 257 | ||
223 | rule->smk_access = 0; | 258 | rule->smk_access = 0; |
224 | 259 | ||
225 | switch (data[SMK_LABELLEN + SMK_LABELLEN]) { | 260 | for (cp = access, done = 0; *cp && !done; cp++) { |
226 | case '-': | 261 | switch (*cp) { |
227 | break; | 262 | case '-': |
228 | case 'r': | 263 | break; |
229 | case 'R': | 264 | case 'r': |
230 | rule->smk_access |= MAY_READ; | 265 | case 'R': |
231 | break; | 266 | rule->smk_access |= MAY_READ; |
232 | default: | 267 | break; |
233 | return -1; | 268 | case 'w': |
269 | case 'W': | ||
270 | rule->smk_access |= MAY_WRITE; | ||
271 | break; | ||
272 | case 'x': | ||
273 | case 'X': | ||
274 | rule->smk_access |= MAY_EXEC; | ||
275 | break; | ||
276 | case 'a': | ||
277 | case 'A': | ||
278 | rule->smk_access |= MAY_APPEND; | ||
279 | break; | ||
280 | case 't': | ||
281 | case 'T': | ||
282 | rule->smk_access |= MAY_TRANSMUTE; | ||
283 | break; | ||
284 | default: | ||
285 | done = 1; | ||
286 | break; | ||
287 | } | ||
234 | } | 288 | } |
289 | rc = 0; | ||
235 | 290 | ||
236 | switch (data[SMK_LABELLEN + SMK_LABELLEN + 1]) { | 291 | return rc; |
237 | case '-': | 292 | } |
238 | break; | ||
239 | case 'w': | ||
240 | case 'W': | ||
241 | rule->smk_access |= MAY_WRITE; | ||
242 | break; | ||
243 | default: | ||
244 | return -1; | ||
245 | } | ||
246 | 293 | ||
247 | switch (data[SMK_LABELLEN + SMK_LABELLEN + 2]) { | 294 | /** |
248 | case '-': | 295 | * smk_parse_rule - parse Smack rule from load string |
249 | break; | 296 | * @data: string to be parsed whose size is SMK_LOADLEN |
250 | case 'x': | 297 | * @rule: Smack rule |
251 | case 'X': | 298 | * @import: if non-zero, import labels |
252 | rule->smk_access |= MAY_EXEC; | 299 | * |
253 | break; | 300 | * Returns 0 on success, -1 on errors. |
254 | default: | 301 | */ |
255 | return -1; | 302 | static int smk_parse_rule(const char *data, struct smack_rule *rule, int import) |
256 | } | 303 | { |
304 | int rc; | ||
257 | 305 | ||
258 | switch (data[SMK_LABELLEN + SMK_LABELLEN + 3]) { | 306 | rc = smk_fill_rule(data, data + SMK_LABELLEN, |
259 | case '-': | 307 | data + SMK_LABELLEN + SMK_LABELLEN, rule, import); |
260 | break; | 308 | return rc; |
261 | case 'a': | 309 | } |
262 | case 'A': | ||
263 | rule->smk_access |= MAY_APPEND; | ||
264 | break; | ||
265 | default: | ||
266 | return -1; | ||
267 | } | ||
268 | 310 | ||
269 | switch (data[SMK_LABELLEN + SMK_LABELLEN + 4]) { | 311 | /** |
270 | case '-': | 312 | * smk_parse_long_rule - parse Smack rule from rule string |
271 | break; | 313 | * @data: string to be parsed, null terminated |
272 | case 't': | 314 | * @rule: Smack rule |
273 | case 'T': | 315 | * @import: if non-zero, import labels |
274 | rule->smk_access |= MAY_TRANSMUTE; | 316 | * |
275 | break; | 317 | * Returns 0 on success, -1 on failure |
276 | default: | 318 | */ |
277 | return -1; | 319 | static int smk_parse_long_rule(const char *data, struct smack_rule *rule, |
278 | } | 320 | int import) |
321 | { | ||
322 | char *subject; | ||
323 | char *object; | ||
324 | char *access; | ||
325 | int datalen; | ||
326 | int rc = -1; | ||
279 | 327 | ||
280 | return 0; | 328 | /* |
329 | * This is probably inefficient, but safe. | ||
330 | */ | ||
331 | datalen = strlen(data); | ||
332 | subject = kzalloc(datalen, GFP_KERNEL); | ||
333 | if (subject == NULL) | ||
334 | return -1; | ||
335 | object = kzalloc(datalen, GFP_KERNEL); | ||
336 | if (object == NULL) | ||
337 | goto free_out_s; | ||
338 | access = kzalloc(datalen, GFP_KERNEL); | ||
339 | if (access == NULL) | ||
340 | goto free_out_o; | ||
341 | |||
342 | if (sscanf(data, "%s %s %s", subject, object, access) == 3) | ||
343 | rc = smk_fill_rule(subject, object, access, rule, import); | ||
344 | |||
345 | kfree(access); | ||
346 | free_out_o: | ||
347 | kfree(object); | ||
348 | free_out_s: | ||
349 | kfree(subject); | ||
350 | return rc; | ||
281 | } | 351 | } |
282 | 352 | ||
353 | #define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */ | ||
354 | #define SMK_LONG_FMT 1 /* Variable long label format */ | ||
283 | /** | 355 | /** |
284 | * smk_write_load_list - write() for any /smack/load | 356 | * smk_write_rules_list - write() for any /smack rule file |
285 | * @file: file pointer, not actually used | 357 | * @file: file pointer, not actually used |
286 | * @buf: where to get the data from | 358 | * @buf: where to get the data from |
287 | * @count: bytes sent | 359 | * @count: bytes sent |
288 | * @ppos: where to start - must be 0 | 360 | * @ppos: where to start - must be 0 |
289 | * @rule_list: the list of rules to write to | 361 | * @rule_list: the list of rules to write to |
290 | * @rule_lock: lock for the rule list | 362 | * @rule_lock: lock for the rule list |
363 | * @format: /smack/load or /smack/load2 format. | ||
291 | * | 364 | * |
292 | * Get one smack access rule from above. | 365 | * Get one smack access rule from above. |
293 | * The format is exactly: | 366 | * The format for SMK_LONG_FMT is: |
294 | * char subject[SMK_LABELLEN] | 367 | * "subject<whitespace>object<whitespace>access[<whitespace>...]" |
295 | * char object[SMK_LABELLEN] | 368 | * The format for SMK_FIXED24_FMT is exactly: |
296 | * char access[SMK_ACCESSLEN] | 369 | * "subject object rwxat" |
297 | * | ||
298 | * writes must be SMK_LABELLEN+SMK_LABELLEN+SMK_ACCESSLEN bytes. | ||
299 | */ | 370 | */ |
300 | static ssize_t smk_write_load_list(struct file *file, const char __user *buf, | 371 | static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, |
301 | size_t count, loff_t *ppos, | 372 | size_t count, loff_t *ppos, |
302 | struct list_head *rule_list, | 373 | struct list_head *rule_list, |
303 | struct mutex *rule_lock) | 374 | struct mutex *rule_lock, int format) |
304 | { | 375 | { |
305 | struct smack_master_list *smlp; | 376 | struct smack_master_list *smlp; |
306 | struct smack_known *skp; | 377 | struct smack_known *skp; |
307 | struct smack_rule *rule; | 378 | struct smack_rule *rule; |
308 | char *data; | 379 | char *data; |
380 | int datalen; | ||
309 | int rc = -EINVAL; | 381 | int rc = -EINVAL; |
310 | int load = 0; | 382 | int load = 0; |
311 | 383 | ||
@@ -315,13 +387,18 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf, | |||
315 | */ | 387 | */ |
316 | if (*ppos != 0) | 388 | if (*ppos != 0) |
317 | return -EINVAL; | 389 | return -EINVAL; |
318 | /* | ||
319 | * Minor hack for backward compatibility | ||
320 | */ | ||
321 | if (count < (SMK_OLOADLEN) || count > SMK_LOADLEN) | ||
322 | return -EINVAL; | ||
323 | 390 | ||
324 | data = kzalloc(SMK_LOADLEN, GFP_KERNEL); | 391 | if (format == SMK_FIXED24_FMT) { |
392 | /* | ||
393 | * Minor hack for backward compatibility | ||
394 | */ | ||
395 | if (count != SMK_OLOADLEN && count != SMK_LOADLEN) | ||
396 | return -EINVAL; | ||
397 | datalen = SMK_LOADLEN; | ||
398 | } else | ||
399 | datalen = count + 1; | ||
400 | |||
401 | data = kzalloc(datalen, GFP_KERNEL); | ||
325 | if (data == NULL) | 402 | if (data == NULL) |
326 | return -ENOMEM; | 403 | return -ENOMEM; |
327 | 404 | ||
@@ -330,20 +407,29 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf, | |||
330 | goto out; | 407 | goto out; |
331 | } | 408 | } |
332 | 409 | ||
333 | /* | ||
334 | * More on the minor hack for backward compatibility | ||
335 | */ | ||
336 | if (count == (SMK_OLOADLEN)) | ||
337 | data[SMK_OLOADLEN] = '-'; | ||
338 | |||
339 | rule = kzalloc(sizeof(*rule), GFP_KERNEL); | 410 | rule = kzalloc(sizeof(*rule), GFP_KERNEL); |
340 | if (rule == NULL) { | 411 | if (rule == NULL) { |
341 | rc = -ENOMEM; | 412 | rc = -ENOMEM; |
342 | goto out; | 413 | goto out; |
343 | } | 414 | } |
344 | 415 | ||
345 | if (smk_parse_rule(data, rule, 1)) | 416 | if (format == SMK_LONG_FMT) { |
346 | goto out_free_rule; | 417 | /* |
418 | * Be sure the data string is terminated. | ||
419 | */ | ||
420 | data[count] = '\0'; | ||
421 | if (smk_parse_long_rule(data, rule, 1)) | ||
422 | goto out_free_rule; | ||
423 | } else { | ||
424 | /* | ||
425 | * More on the minor hack for backward compatibility | ||
426 | */ | ||
427 | if (count == (SMK_OLOADLEN)) | ||
428 | data[SMK_OLOADLEN] = '-'; | ||
429 | if (smk_parse_rule(data, rule, 1)) | ||
430 | goto out_free_rule; | ||
431 | } | ||
432 | |||
347 | 433 | ||
348 | if (rule_list == NULL) { | 434 | if (rule_list == NULL) { |
349 | load = 1; | 435 | load = 1; |
@@ -354,18 +440,20 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf, | |||
354 | 440 | ||
355 | rc = count; | 441 | rc = count; |
356 | /* | 442 | /* |
357 | * If this is "load" as opposed to "load-self" and a new rule | 443 | * If this is a global as opposed to self and a new rule |
358 | * it needs to get added for reporting. | 444 | * it needs to get added for reporting. |
359 | * smk_set_access returns true if there was already a rule | 445 | * smk_set_access returns true if there was already a rule |
360 | * for the subject/object pair, and false if it was new. | 446 | * for the subject/object pair, and false if it was new. |
361 | */ | 447 | */ |
362 | if (load && !smk_set_access(rule, rule_list, rule_lock)) { | 448 | if (!smk_set_access(rule, rule_list, rule_lock)) { |
363 | smlp = kzalloc(sizeof(*smlp), GFP_KERNEL); | 449 | if (load) { |
364 | if (smlp != NULL) { | 450 | smlp = kzalloc(sizeof(*smlp), GFP_KERNEL); |
365 | smlp->smk_rule = rule; | 451 | if (smlp != NULL) { |
366 | list_add_rcu(&smlp->list, &smack_rule_list); | 452 | smlp->smk_rule = rule; |
367 | } else | 453 | list_add_rcu(&smlp->list, &smack_rule_list); |
368 | rc = -ENOMEM; | 454 | } else |
455 | rc = -ENOMEM; | ||
456 | } | ||
369 | goto out; | 457 | goto out; |
370 | } | 458 | } |
371 | 459 | ||
@@ -421,29 +509,18 @@ static void smk_seq_stop(struct seq_file *s, void *v) | |||
421 | /* No-op */ | 509 | /* No-op */ |
422 | } | 510 | } |
423 | 511 | ||
424 | /* | 512 | static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) |
425 | * Seq_file read operations for /smack/load | ||
426 | */ | ||
427 | |||
428 | static void *load_seq_start(struct seq_file *s, loff_t *pos) | ||
429 | { | ||
430 | return smk_seq_start(s, pos, &smack_rule_list); | ||
431 | } | ||
432 | |||
433 | static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos) | ||
434 | { | 513 | { |
435 | return smk_seq_next(s, v, pos, &smack_rule_list); | 514 | /* |
436 | } | 515 | * Don't show any rules with label names too long for |
437 | 516 | * interface file (/smack/load or /smack/load2) | |
438 | static int load_seq_show(struct seq_file *s, void *v) | 517 | * because you should expect to be able to write |
439 | { | 518 | * anything you read back. |
440 | struct list_head *list = v; | 519 | */ |
441 | struct smack_master_list *smlp = | 520 | if (strlen(srp->smk_subject) >= max || strlen(srp->smk_object) >= max) |
442 | list_entry(list, struct smack_master_list, list); | 521 | return; |
443 | struct smack_rule *srp = smlp->smk_rule; | ||
444 | 522 | ||
445 | seq_printf(s, "%s %s", (char *)srp->smk_subject, | 523 | seq_printf(s, "%s %s", srp->smk_subject, srp->smk_object); |
446 | (char *)srp->smk_object); | ||
447 | 524 | ||
448 | seq_putc(s, ' '); | 525 | seq_putc(s, ' '); |
449 | 526 | ||
@@ -461,13 +538,36 @@ static int load_seq_show(struct seq_file *s, void *v) | |||
461 | seq_putc(s, '-'); | 538 | seq_putc(s, '-'); |
462 | 539 | ||
463 | seq_putc(s, '\n'); | 540 | seq_putc(s, '\n'); |
541 | } | ||
542 | |||
543 | /* | ||
544 | * Seq_file read operations for /smack/load | ||
545 | */ | ||
546 | |||
547 | static void *load2_seq_start(struct seq_file *s, loff_t *pos) | ||
548 | { | ||
549 | return smk_seq_start(s, pos, &smack_rule_list); | ||
550 | } | ||
551 | |||
552 | static void *load2_seq_next(struct seq_file *s, void *v, loff_t *pos) | ||
553 | { | ||
554 | return smk_seq_next(s, v, pos, &smack_rule_list); | ||
555 | } | ||
556 | |||
557 | static int load_seq_show(struct seq_file *s, void *v) | ||
558 | { | ||
559 | struct list_head *list = v; | ||
560 | struct smack_master_list *smlp = | ||
561 | list_entry(list, struct smack_master_list, list); | ||
562 | |||
563 | smk_rule_show(s, smlp->smk_rule, SMK_LABELLEN); | ||
464 | 564 | ||
465 | return 0; | 565 | return 0; |
466 | } | 566 | } |
467 | 567 | ||
468 | static const struct seq_operations load_seq_ops = { | 568 | static const struct seq_operations load_seq_ops = { |
469 | .start = load_seq_start, | 569 | .start = load2_seq_start, |
470 | .next = load_seq_next, | 570 | .next = load2_seq_next, |
471 | .show = load_seq_show, | 571 | .show = load_seq_show, |
472 | .stop = smk_seq_stop, | 572 | .stop = smk_seq_stop, |
473 | }; | 573 | }; |
@@ -504,7 +604,8 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf, | |||
504 | if (!capable(CAP_MAC_ADMIN)) | 604 | if (!capable(CAP_MAC_ADMIN)) |
505 | return -EPERM; | 605 | return -EPERM; |
506 | 606 | ||
507 | return smk_write_load_list(file, buf, count, ppos, NULL, NULL); | 607 | return smk_write_rules_list(file, buf, count, ppos, NULL, NULL, |
608 | SMK_FIXED24_FMT); | ||
508 | } | 609 | } |
509 | 610 | ||
510 | static const struct file_operations smk_load_ops = { | 611 | static const struct file_operations smk_load_ops = { |
@@ -574,6 +675,8 @@ static void smk_unlbl_ambient(char *oldambient) | |||
574 | printk(KERN_WARNING "%s:%d remove rc = %d\n", | 675 | printk(KERN_WARNING "%s:%d remove rc = %d\n", |
575 | __func__, __LINE__, rc); | 676 | __func__, __LINE__, rc); |
576 | } | 677 | } |
678 | if (smack_net_ambient == NULL) | ||
679 | smack_net_ambient = smack_known_floor.smk_known; | ||
577 | 680 | ||
578 | rc = netlbl_cfg_unlbl_map_add(smack_net_ambient, PF_INET, | 681 | rc = netlbl_cfg_unlbl_map_add(smack_net_ambient, PF_INET, |
579 | NULL, NULL, &nai); | 682 | NULL, NULL, &nai); |
@@ -605,27 +708,28 @@ static int cipso_seq_show(struct seq_file *s, void *v) | |||
605 | struct list_head *list = v; | 708 | struct list_head *list = v; |
606 | struct smack_known *skp = | 709 | struct smack_known *skp = |
607 | list_entry(list, struct smack_known, list); | 710 | list_entry(list, struct smack_known, list); |
608 | struct smack_cipso *scp = skp->smk_cipso; | 711 | struct netlbl_lsm_secattr_catmap *cmp = skp->smk_netlabel.attr.mls.cat; |
609 | char *cbp; | ||
610 | char sep = '/'; | 712 | char sep = '/'; |
611 | int cat = 1; | ||
612 | int i; | 713 | int i; |
613 | unsigned char m; | ||
614 | 714 | ||
615 | if (scp == NULL) | 715 | /* |
716 | * Don't show a label that could not have been set using | ||
717 | * /smack/cipso. This is in support of the notion that | ||
718 | * anything read from /smack/cipso ought to be writeable | ||
719 | * to /smack/cipso. | ||
720 | * | ||
721 | * /smack/cipso2 should be used instead. | ||
722 | */ | ||
723 | if (strlen(skp->smk_known) >= SMK_LABELLEN) | ||
616 | return 0; | 724 | return 0; |
617 | 725 | ||
618 | seq_printf(s, "%s %3d", (char *)&skp->smk_known, scp->smk_level); | 726 | seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl); |
619 | 727 | ||
620 | cbp = scp->smk_catset; | 728 | for (i = netlbl_secattr_catmap_walk(cmp, 0); i >= 0; |
621 | for (i = 0; i < SMK_LABELLEN; i++) | 729 | i = netlbl_secattr_catmap_walk(cmp, i + 1)) { |
622 | for (m = 0x80; m != 0; m >>= 1) { | 730 | seq_printf(s, "%c%d", sep, i); |
623 | if (m & cbp[i]) { | 731 | sep = ','; |
624 | seq_printf(s, "%c%d", sep, cat); | 732 | } |
625 | sep = ','; | ||
626 | } | ||
627 | cat++; | ||
628 | } | ||
629 | 733 | ||
630 | seq_putc(s, '\n'); | 734 | seq_putc(s, '\n'); |
631 | 735 | ||
@@ -653,23 +757,24 @@ static int smk_open_cipso(struct inode *inode, struct file *file) | |||
653 | } | 757 | } |
654 | 758 | ||
655 | /** | 759 | /** |
656 | * smk_write_cipso - write() for /smack/cipso | 760 | * smk_set_cipso - do the work for write() for cipso and cipso2 |
657 | * @file: file pointer, not actually used | 761 | * @file: file pointer, not actually used |
658 | * @buf: where to get the data from | 762 | * @buf: where to get the data from |
659 | * @count: bytes sent | 763 | * @count: bytes sent |
660 | * @ppos: where to start | 764 | * @ppos: where to start |
765 | * @format: /smack/cipso or /smack/cipso2 | ||
661 | * | 766 | * |
662 | * Accepts only one cipso rule per write call. | 767 | * Accepts only one cipso rule per write call. |
663 | * Returns number of bytes written or error code, as appropriate | 768 | * Returns number of bytes written or error code, as appropriate |
664 | */ | 769 | */ |
665 | static ssize_t smk_write_cipso(struct file *file, const char __user *buf, | 770 | static ssize_t smk_set_cipso(struct file *file, const char __user *buf, |
666 | size_t count, loff_t *ppos) | 771 | size_t count, loff_t *ppos, int format) |
667 | { | 772 | { |
668 | struct smack_known *skp; | 773 | struct smack_known *skp; |
669 | struct smack_cipso *scp = NULL; | 774 | struct netlbl_lsm_secattr ncats; |
670 | char mapcatset[SMK_LABELLEN]; | 775 | char mapcatset[SMK_CIPSOLEN]; |
671 | int maplevel; | 776 | int maplevel; |
672 | int cat; | 777 | unsigned int cat; |
673 | int catlen; | 778 | int catlen; |
674 | ssize_t rc = -EINVAL; | 779 | ssize_t rc = -EINVAL; |
675 | char *data = NULL; | 780 | char *data = NULL; |
@@ -686,7 +791,8 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf, | |||
686 | return -EPERM; | 791 | return -EPERM; |
687 | if (*ppos != 0) | 792 | if (*ppos != 0) |
688 | return -EINVAL; | 793 | return -EINVAL; |
689 | if (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX) | 794 | if (format == SMK_FIXED24_FMT && |
795 | (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX)) | ||
690 | return -EINVAL; | 796 | return -EINVAL; |
691 | 797 | ||
692 | data = kzalloc(count + 1, GFP_KERNEL); | 798 | data = kzalloc(count + 1, GFP_KERNEL); |
@@ -698,11 +804,6 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf, | |||
698 | goto unlockedout; | 804 | goto unlockedout; |
699 | } | 805 | } |
700 | 806 | ||
701 | /* labels cannot begin with a '-' */ | ||
702 | if (data[0] == '-') { | ||
703 | rc = -EINVAL; | ||
704 | goto unlockedout; | ||
705 | } | ||
706 | data[count] = '\0'; | 807 | data[count] = '\0'; |
707 | rule = data; | 808 | rule = data; |
708 | /* | 809 | /* |
@@ -715,7 +816,11 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf, | |||
715 | if (skp == NULL) | 816 | if (skp == NULL) |
716 | goto out; | 817 | goto out; |
717 | 818 | ||
718 | rule += SMK_LABELLEN; | 819 | if (format == SMK_FIXED24_FMT) |
820 | rule += SMK_LABELLEN; | ||
821 | else | ||
822 | rule += strlen(skp->smk_known); | ||
823 | |||
719 | ret = sscanf(rule, "%d", &maplevel); | 824 | ret = sscanf(rule, "%d", &maplevel); |
720 | if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL) | 825 | if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL) |
721 | goto out; | 826 | goto out; |
@@ -725,41 +830,29 @@ static ssize_t smk_write_cipso(struct file *file, const char __user *buf, | |||
725 | if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM) | 830 | if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM) |
726 | goto out; | 831 | goto out; |
727 | 832 | ||
728 | if (count != (SMK_CIPSOMIN + catlen * SMK_DIGITLEN)) | 833 | if (format == SMK_FIXED24_FMT && |
834 | count != (SMK_CIPSOMIN + catlen * SMK_DIGITLEN)) | ||
729 | goto out; | 835 | goto out; |
730 | 836 | ||
731 | memset(mapcatset, 0, sizeof(mapcatset)); | 837 | memset(mapcatset, 0, sizeof(mapcatset)); |
732 | 838 | ||
733 | for (i = 0; i < catlen; i++) { | 839 | for (i = 0; i < catlen; i++) { |
734 | rule += SMK_DIGITLEN; | 840 | rule += SMK_DIGITLEN; |
735 | ret = sscanf(rule, "%d", &cat); | 841 | ret = sscanf(rule, "%u", &cat); |
736 | if (ret != 1 || cat > SMACK_CIPSO_MAXCATVAL) | 842 | if (ret != 1 || cat > SMACK_CIPSO_MAXCATVAL) |
737 | goto out; | 843 | goto out; |
738 | 844 | ||
739 | smack_catset_bit(cat, mapcatset); | 845 | smack_catset_bit(cat, mapcatset); |
740 | } | 846 | } |
741 | 847 | ||
742 | if (skp->smk_cipso == NULL) { | 848 | rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN); |
743 | scp = kzalloc(sizeof(struct smack_cipso), GFP_KERNEL); | 849 | if (rc >= 0) { |
744 | if (scp == NULL) { | 850 | netlbl_secattr_catmap_free(skp->smk_netlabel.attr.mls.cat); |
745 | rc = -ENOMEM; | 851 | skp->smk_netlabel.attr.mls.cat = ncats.attr.mls.cat; |
746 | goto out; | 852 | skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl; |
747 | } | 853 | rc = count; |
748 | } | 854 | } |
749 | 855 | ||
750 | spin_lock_bh(&skp->smk_cipsolock); | ||
751 | |||
752 | if (scp == NULL) | ||
753 | scp = skp->smk_cipso; | ||
754 | else | ||
755 | skp->smk_cipso = scp; | ||
756 | |||
757 | scp->smk_level = maplevel; | ||
758 | memcpy(scp->smk_catset, mapcatset, sizeof(mapcatset)); | ||
759 | |||
760 | spin_unlock_bh(&skp->smk_cipsolock); | ||
761 | |||
762 | rc = count; | ||
763 | out: | 856 | out: |
764 | mutex_unlock(&smack_cipso_lock); | 857 | mutex_unlock(&smack_cipso_lock); |
765 | unlockedout: | 858 | unlockedout: |
@@ -767,6 +860,22 @@ unlockedout: | |||
767 | return rc; | 860 | return rc; |
768 | } | 861 | } |
769 | 862 | ||
863 | /** | ||
864 | * smk_write_cipso - write() for /smack/cipso | ||
865 | * @file: file pointer, not actually used | ||
866 | * @buf: where to get the data from | ||
867 | * @count: bytes sent | ||
868 | * @ppos: where to start | ||
869 | * | ||
870 | * Accepts only one cipso rule per write call. | ||
871 | * Returns number of bytes written or error code, as appropriate | ||
872 | */ | ||
873 | static ssize_t smk_write_cipso(struct file *file, const char __user *buf, | ||
874 | size_t count, loff_t *ppos) | ||
875 | { | ||
876 | return smk_set_cipso(file, buf, count, ppos, SMK_FIXED24_FMT); | ||
877 | } | ||
878 | |||
770 | static const struct file_operations smk_cipso_ops = { | 879 | static const struct file_operations smk_cipso_ops = { |
771 | .open = smk_open_cipso, | 880 | .open = smk_open_cipso, |
772 | .read = seq_read, | 881 | .read = seq_read, |
@@ -776,6 +885,80 @@ static const struct file_operations smk_cipso_ops = { | |||
776 | }; | 885 | }; |
777 | 886 | ||
778 | /* | 887 | /* |
888 | * Seq_file read operations for /smack/cipso2 | ||
889 | */ | ||
890 | |||
891 | /* | ||
892 | * Print cipso labels in format: | ||
893 | * label level[/cat[,cat]] | ||
894 | */ | ||
895 | static int cipso2_seq_show(struct seq_file *s, void *v) | ||
896 | { | ||
897 | struct list_head *list = v; | ||
898 | struct smack_known *skp = | ||
899 | list_entry(list, struct smack_known, list); | ||
900 | struct netlbl_lsm_secattr_catmap *cmp = skp->smk_netlabel.attr.mls.cat; | ||
901 | char sep = '/'; | ||
902 | int i; | ||
903 | |||
904 | seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl); | ||
905 | |||
906 | for (i = netlbl_secattr_catmap_walk(cmp, 0); i >= 0; | ||
907 | i = netlbl_secattr_catmap_walk(cmp, i + 1)) { | ||
908 | seq_printf(s, "%c%d", sep, i); | ||
909 | sep = ','; | ||
910 | } | ||
911 | |||
912 | seq_putc(s, '\n'); | ||
913 | |||
914 | return 0; | ||
915 | } | ||
916 | |||
917 | static const struct seq_operations cipso2_seq_ops = { | ||
918 | .start = cipso_seq_start, | ||
919 | .next = cipso_seq_next, | ||
920 | .show = cipso2_seq_show, | ||
921 | .stop = smk_seq_stop, | ||
922 | }; | ||
923 | |||
924 | /** | ||
925 | * smk_open_cipso2 - open() for /smack/cipso2 | ||
926 | * @inode: inode structure representing file | ||
927 | * @file: "cipso2" file pointer | ||
928 | * | ||
929 | * Connect our cipso_seq_* operations with /smack/cipso2 | ||
930 | * file_operations | ||
931 | */ | ||
932 | static int smk_open_cipso2(struct inode *inode, struct file *file) | ||
933 | { | ||
934 | return seq_open(file, &cipso2_seq_ops); | ||
935 | } | ||
936 | |||
937 | /** | ||
938 | * smk_write_cipso2 - write() for /smack/cipso2 | ||
939 | * @file: file pointer, not actually used | ||
940 | * @buf: where to get the data from | ||
941 | * @count: bytes sent | ||
942 | * @ppos: where to start | ||
943 | * | ||
944 | * Accepts only one cipso rule per write call. | ||
945 | * Returns number of bytes written or error code, as appropriate | ||
946 | */ | ||
947 | static ssize_t smk_write_cipso2(struct file *file, const char __user *buf, | ||
948 | size_t count, loff_t *ppos) | ||
949 | { | ||
950 | return smk_set_cipso(file, buf, count, ppos, SMK_LONG_FMT); | ||
951 | } | ||
952 | |||
953 | static const struct file_operations smk_cipso2_ops = { | ||
954 | .open = smk_open_cipso2, | ||
955 | .read = seq_read, | ||
956 | .llseek = seq_lseek, | ||
957 | .write = smk_write_cipso2, | ||
958 | .release = seq_release, | ||
959 | }; | ||
960 | |||
961 | /* | ||
779 | * Seq_file read operations for /smack/netlabel | 962 | * Seq_file read operations for /smack/netlabel |
780 | */ | 963 | */ |
781 | 964 | ||
@@ -887,9 +1070,9 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
887 | { | 1070 | { |
888 | struct smk_netlbladdr *skp; | 1071 | struct smk_netlbladdr *skp; |
889 | struct sockaddr_in newname; | 1072 | struct sockaddr_in newname; |
890 | char smack[SMK_LABELLEN]; | 1073 | char *smack; |
891 | char *sp; | 1074 | char *sp; |
892 | char data[SMK_NETLBLADDRMAX + 1]; | 1075 | char *data; |
893 | char *host = (char *)&newname.sin_addr.s_addr; | 1076 | char *host = (char *)&newname.sin_addr.s_addr; |
894 | int rc; | 1077 | int rc; |
895 | struct netlbl_audit audit_info; | 1078 | struct netlbl_audit audit_info; |
@@ -911,10 +1094,23 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
911 | return -EPERM; | 1094 | return -EPERM; |
912 | if (*ppos != 0) | 1095 | if (*ppos != 0) |
913 | return -EINVAL; | 1096 | return -EINVAL; |
914 | if (count < SMK_NETLBLADDRMIN || count > SMK_NETLBLADDRMAX) | 1097 | if (count < SMK_NETLBLADDRMIN) |
915 | return -EINVAL; | 1098 | return -EINVAL; |
916 | if (copy_from_user(data, buf, count) != 0) | 1099 | |
917 | return -EFAULT; | 1100 | data = kzalloc(count + 1, GFP_KERNEL); |
1101 | if (data == NULL) | ||
1102 | return -ENOMEM; | ||
1103 | |||
1104 | if (copy_from_user(data, buf, count) != 0) { | ||
1105 | rc = -EFAULT; | ||
1106 | goto free_data_out; | ||
1107 | } | ||
1108 | |||
1109 | smack = kzalloc(count + 1, GFP_KERNEL); | ||
1110 | if (smack == NULL) { | ||
1111 | rc = -ENOMEM; | ||
1112 | goto free_data_out; | ||
1113 | } | ||
918 | 1114 | ||
919 | data[count] = '\0'; | 1115 | data[count] = '\0'; |
920 | 1116 | ||
@@ -923,24 +1119,34 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
923 | if (rc != 6) { | 1119 | if (rc != 6) { |
924 | rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s", | 1120 | rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s", |
925 | &host[0], &host[1], &host[2], &host[3], smack); | 1121 | &host[0], &host[1], &host[2], &host[3], smack); |
926 | if (rc != 5) | 1122 | if (rc != 5) { |
927 | return -EINVAL; | 1123 | rc = -EINVAL; |
1124 | goto free_out; | ||
1125 | } | ||
928 | m = BEBITS; | 1126 | m = BEBITS; |
929 | } | 1127 | } |
930 | if (m > BEBITS) | 1128 | if (m > BEBITS) { |
931 | return -EINVAL; | 1129 | rc = -EINVAL; |
1130 | goto free_out; | ||
1131 | } | ||
932 | 1132 | ||
933 | /* if smack begins with '-', its an option, don't import it */ | 1133 | /* |
1134 | * If smack begins with '-', it is an option, don't import it | ||
1135 | */ | ||
934 | if (smack[0] != '-') { | 1136 | if (smack[0] != '-') { |
935 | sp = smk_import(smack, 0); | 1137 | sp = smk_import(smack, 0); |
936 | if (sp == NULL) | 1138 | if (sp == NULL) { |
937 | return -EINVAL; | 1139 | rc = -EINVAL; |
1140 | goto free_out; | ||
1141 | } | ||
938 | } else { | 1142 | } else { |
939 | /* check known options */ | 1143 | /* check known options */ |
940 | if (strcmp(smack, smack_cipso_option) == 0) | 1144 | if (strcmp(smack, smack_cipso_option) == 0) |
941 | sp = (char *)smack_cipso_option; | 1145 | sp = (char *)smack_cipso_option; |
942 | else | 1146 | else { |
943 | return -EINVAL; | 1147 | rc = -EINVAL; |
1148 | goto free_out; | ||
1149 | } | ||
944 | } | 1150 | } |
945 | 1151 | ||
946 | for (temp_mask = 0; m > 0; m--) { | 1152 | for (temp_mask = 0; m > 0; m--) { |
@@ -1006,6 +1212,11 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
1006 | 1212 | ||
1007 | mutex_unlock(&smk_netlbladdr_lock); | 1213 | mutex_unlock(&smk_netlbladdr_lock); |
1008 | 1214 | ||
1215 | free_out: | ||
1216 | kfree(smack); | ||
1217 | free_data_out: | ||
1218 | kfree(data); | ||
1219 | |||
1009 | return rc; | 1220 | return rc; |
1010 | } | 1221 | } |
1011 | 1222 | ||
@@ -1119,6 +1330,7 @@ static ssize_t smk_read_direct(struct file *filp, char __user *buf, | |||
1119 | static ssize_t smk_write_direct(struct file *file, const char __user *buf, | 1330 | static ssize_t smk_write_direct(struct file *file, const char __user *buf, |
1120 | size_t count, loff_t *ppos) | 1331 | size_t count, loff_t *ppos) |
1121 | { | 1332 | { |
1333 | struct smack_known *skp; | ||
1122 | char temp[80]; | 1334 | char temp[80]; |
1123 | int i; | 1335 | int i; |
1124 | 1336 | ||
@@ -1136,7 +1348,20 @@ static ssize_t smk_write_direct(struct file *file, const char __user *buf, | |||
1136 | if (sscanf(temp, "%d", &i) != 1) | 1348 | if (sscanf(temp, "%d", &i) != 1) |
1137 | return -EINVAL; | 1349 | return -EINVAL; |
1138 | 1350 | ||
1139 | smack_cipso_direct = i; | 1351 | /* |
1352 | * Don't do anything if the value hasn't actually changed. | ||
1353 | * If it is changing reset the level on entries that were | ||
1354 | * set up to be direct when they were created. | ||
1355 | */ | ||
1356 | if (smack_cipso_direct != i) { | ||
1357 | mutex_lock(&smack_known_lock); | ||
1358 | list_for_each_entry_rcu(skp, &smack_known_list, list) | ||
1359 | if (skp->smk_netlabel.attr.mls.lvl == | ||
1360 | smack_cipso_direct) | ||
1361 | skp->smk_netlabel.attr.mls.lvl = i; | ||
1362 | smack_cipso_direct = i; | ||
1363 | mutex_unlock(&smack_known_lock); | ||
1364 | } | ||
1140 | 1365 | ||
1141 | return count; | 1366 | return count; |
1142 | } | 1367 | } |
@@ -1148,6 +1373,84 @@ static const struct file_operations smk_direct_ops = { | |||
1148 | }; | 1373 | }; |
1149 | 1374 | ||
1150 | /** | 1375 | /** |
1376 | * smk_read_mapped - read() for /smack/mapped | ||
1377 | * @filp: file pointer, not actually used | ||
1378 | * @buf: where to put the result | ||
1379 | * @count: maximum to send along | ||
1380 | * @ppos: where to start | ||
1381 | * | ||
1382 | * Returns number of bytes read or error code, as appropriate | ||
1383 | */ | ||
1384 | static ssize_t smk_read_mapped(struct file *filp, char __user *buf, | ||
1385 | size_t count, loff_t *ppos) | ||
1386 | { | ||
1387 | char temp[80]; | ||
1388 | ssize_t rc; | ||
1389 | |||
1390 | if (*ppos != 0) | ||
1391 | return 0; | ||
1392 | |||
1393 | sprintf(temp, "%d", smack_cipso_mapped); | ||
1394 | rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp)); | ||
1395 | |||
1396 | return rc; | ||
1397 | } | ||
1398 | |||
1399 | /** | ||
1400 | * smk_write_mapped - write() for /smack/mapped | ||
1401 | * @file: file pointer, not actually used | ||
1402 | * @buf: where to get the data from | ||
1403 | * @count: bytes sent | ||
1404 | * @ppos: where to start | ||
1405 | * | ||
1406 | * Returns number of bytes written or error code, as appropriate | ||
1407 | */ | ||
1408 | static ssize_t smk_write_mapped(struct file *file, const char __user *buf, | ||
1409 | size_t count, loff_t *ppos) | ||
1410 | { | ||
1411 | struct smack_known *skp; | ||
1412 | char temp[80]; | ||
1413 | int i; | ||
1414 | |||
1415 | if (!capable(CAP_MAC_ADMIN)) | ||
1416 | return -EPERM; | ||
1417 | |||
1418 | if (count >= sizeof(temp) || count == 0) | ||
1419 | return -EINVAL; | ||
1420 | |||
1421 | if (copy_from_user(temp, buf, count) != 0) | ||
1422 | return -EFAULT; | ||
1423 | |||
1424 | temp[count] = '\0'; | ||
1425 | |||
1426 | if (sscanf(temp, "%d", &i) != 1) | ||
1427 | return -EINVAL; | ||
1428 | |||
1429 | /* | ||
1430 | * Don't do anything if the value hasn't actually changed. | ||
1431 | * If it is changing reset the level on entries that were | ||
1432 | * set up to be mapped when they were created. | ||
1433 | */ | ||
1434 | if (smack_cipso_mapped != i) { | ||
1435 | mutex_lock(&smack_known_lock); | ||
1436 | list_for_each_entry_rcu(skp, &smack_known_list, list) | ||
1437 | if (skp->smk_netlabel.attr.mls.lvl == | ||
1438 | smack_cipso_mapped) | ||
1439 | skp->smk_netlabel.attr.mls.lvl = i; | ||
1440 | smack_cipso_mapped = i; | ||
1441 | mutex_unlock(&smack_known_lock); | ||
1442 | } | ||
1443 | |||
1444 | return count; | ||
1445 | } | ||
1446 | |||
1447 | static const struct file_operations smk_mapped_ops = { | ||
1448 | .read = smk_read_mapped, | ||
1449 | .write = smk_write_mapped, | ||
1450 | .llseek = default_llseek, | ||
1451 | }; | ||
1452 | |||
1453 | /** | ||
1151 | * smk_read_ambient - read() for /smack/ambient | 1454 | * smk_read_ambient - read() for /smack/ambient |
1152 | * @filp: file pointer, not actually used | 1455 | * @filp: file pointer, not actually used |
1153 | * @buf: where to put the result | 1456 | * @buf: where to put the result |
@@ -1195,22 +1498,28 @@ static ssize_t smk_read_ambient(struct file *filp, char __user *buf, | |||
1195 | static ssize_t smk_write_ambient(struct file *file, const char __user *buf, | 1498 | static ssize_t smk_write_ambient(struct file *file, const char __user *buf, |
1196 | size_t count, loff_t *ppos) | 1499 | size_t count, loff_t *ppos) |
1197 | { | 1500 | { |
1198 | char in[SMK_LABELLEN]; | ||
1199 | char *oldambient; | 1501 | char *oldambient; |
1200 | char *smack; | 1502 | char *smack = NULL; |
1503 | char *data; | ||
1504 | int rc = count; | ||
1201 | 1505 | ||
1202 | if (!capable(CAP_MAC_ADMIN)) | 1506 | if (!capable(CAP_MAC_ADMIN)) |
1203 | return -EPERM; | 1507 | return -EPERM; |
1204 | 1508 | ||
1205 | if (count >= SMK_LABELLEN) | 1509 | data = kzalloc(count + 1, GFP_KERNEL); |
1206 | return -EINVAL; | 1510 | if (data == NULL) |
1511 | return -ENOMEM; | ||
1207 | 1512 | ||
1208 | if (copy_from_user(in, buf, count) != 0) | 1513 | if (copy_from_user(data, buf, count) != 0) { |
1209 | return -EFAULT; | 1514 | rc = -EFAULT; |
1515 | goto out; | ||
1516 | } | ||
1210 | 1517 | ||
1211 | smack = smk_import(in, count); | 1518 | smack = smk_import(data, count); |
1212 | if (smack == NULL) | 1519 | if (smack == NULL) { |
1213 | return -EINVAL; | 1520 | rc = -EINVAL; |
1521 | goto out; | ||
1522 | } | ||
1214 | 1523 | ||
1215 | mutex_lock(&smack_ambient_lock); | 1524 | mutex_lock(&smack_ambient_lock); |
1216 | 1525 | ||
@@ -1220,7 +1529,9 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf, | |||
1220 | 1529 | ||
1221 | mutex_unlock(&smack_ambient_lock); | 1530 | mutex_unlock(&smack_ambient_lock); |
1222 | 1531 | ||
1223 | return count; | 1532 | out: |
1533 | kfree(data); | ||
1534 | return rc; | ||
1224 | } | 1535 | } |
1225 | 1536 | ||
1226 | static const struct file_operations smk_ambient_ops = { | 1537 | static const struct file_operations smk_ambient_ops = { |
@@ -1271,8 +1582,9 @@ static ssize_t smk_read_onlycap(struct file *filp, char __user *buf, | |||
1271 | static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, | 1582 | static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, |
1272 | size_t count, loff_t *ppos) | 1583 | size_t count, loff_t *ppos) |
1273 | { | 1584 | { |
1274 | char in[SMK_LABELLEN]; | 1585 | char *data; |
1275 | char *sp = smk_of_task(current->cred->security); | 1586 | char *sp = smk_of_task(current->cred->security); |
1587 | int rc = count; | ||
1276 | 1588 | ||
1277 | if (!capable(CAP_MAC_ADMIN)) | 1589 | if (!capable(CAP_MAC_ADMIN)) |
1278 | return -EPERM; | 1590 | return -EPERM; |
@@ -1285,11 +1597,9 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, | |||
1285 | if (smack_onlycap != NULL && smack_onlycap != sp) | 1597 | if (smack_onlycap != NULL && smack_onlycap != sp) |
1286 | return -EPERM; | 1598 | return -EPERM; |
1287 | 1599 | ||
1288 | if (count >= SMK_LABELLEN) | 1600 | data = kzalloc(count, GFP_KERNEL); |
1289 | return -EINVAL; | 1601 | if (data == NULL) |
1290 | 1602 | return -ENOMEM; | |
1291 | if (copy_from_user(in, buf, count) != 0) | ||
1292 | return -EFAULT; | ||
1293 | 1603 | ||
1294 | /* | 1604 | /* |
1295 | * Should the null string be passed in unset the onlycap value. | 1605 | * Should the null string be passed in unset the onlycap value. |
@@ -1297,10 +1607,17 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, | |||
1297 | * smk_import only expects to return NULL for errors. It | 1607 | * smk_import only expects to return NULL for errors. It |
1298 | * is usually the case that a nullstring or "\n" would be | 1608 | * is usually the case that a nullstring or "\n" would be |
1299 | * bad to pass to smk_import but in fact this is useful here. | 1609 | * bad to pass to smk_import but in fact this is useful here. |
1610 | * | ||
1611 | * smk_import will also reject a label beginning with '-', | ||
1612 | * so "-usecapabilities" will also work. | ||
1300 | */ | 1613 | */ |
1301 | smack_onlycap = smk_import(in, count); | 1614 | if (copy_from_user(data, buf, count) != 0) |
1615 | rc = -EFAULT; | ||
1616 | else | ||
1617 | smack_onlycap = smk_import(data, count); | ||
1302 | 1618 | ||
1303 | return count; | 1619 | kfree(data); |
1620 | return rc; | ||
1304 | } | 1621 | } |
1305 | 1622 | ||
1306 | static const struct file_operations smk_onlycap_ops = { | 1623 | static const struct file_operations smk_onlycap_ops = { |
@@ -1398,25 +1715,7 @@ static int load_self_seq_show(struct seq_file *s, void *v) | |||
1398 | struct smack_rule *srp = | 1715 | struct smack_rule *srp = |
1399 | list_entry(list, struct smack_rule, list); | 1716 | list_entry(list, struct smack_rule, list); |
1400 | 1717 | ||
1401 | seq_printf(s, "%s %s", (char *)srp->smk_subject, | 1718 | smk_rule_show(s, srp, SMK_LABELLEN); |
1402 | (char *)srp->smk_object); | ||
1403 | |||
1404 | seq_putc(s, ' '); | ||
1405 | |||
1406 | if (srp->smk_access & MAY_READ) | ||
1407 | seq_putc(s, 'r'); | ||
1408 | if (srp->smk_access & MAY_WRITE) | ||
1409 | seq_putc(s, 'w'); | ||
1410 | if (srp->smk_access & MAY_EXEC) | ||
1411 | seq_putc(s, 'x'); | ||
1412 | if (srp->smk_access & MAY_APPEND) | ||
1413 | seq_putc(s, 'a'); | ||
1414 | if (srp->smk_access & MAY_TRANSMUTE) | ||
1415 | seq_putc(s, 't'); | ||
1416 | if (srp->smk_access == 0) | ||
1417 | seq_putc(s, '-'); | ||
1418 | |||
1419 | seq_putc(s, '\n'); | ||
1420 | 1719 | ||
1421 | return 0; | 1720 | return 0; |
1422 | } | 1721 | } |
@@ -1430,7 +1729,7 @@ static const struct seq_operations load_self_seq_ops = { | |||
1430 | 1729 | ||
1431 | 1730 | ||
1432 | /** | 1731 | /** |
1433 | * smk_open_load_self - open() for /smack/load-self | 1732 | * smk_open_load_self - open() for /smack/load-self2 |
1434 | * @inode: inode structure representing file | 1733 | * @inode: inode structure representing file |
1435 | * @file: "load" file pointer | 1734 | * @file: "load" file pointer |
1436 | * | 1735 | * |
@@ -1454,8 +1753,8 @@ static ssize_t smk_write_load_self(struct file *file, const char __user *buf, | |||
1454 | { | 1753 | { |
1455 | struct task_smack *tsp = current_security(); | 1754 | struct task_smack *tsp = current_security(); |
1456 | 1755 | ||
1457 | return smk_write_load_list(file, buf, count, ppos, &tsp->smk_rules, | 1756 | return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules, |
1458 | &tsp->smk_rules_lock); | 1757 | &tsp->smk_rules_lock, SMK_FIXED24_FMT); |
1459 | } | 1758 | } |
1460 | 1759 | ||
1461 | static const struct file_operations smk_load_self_ops = { | 1760 | static const struct file_operations smk_load_self_ops = { |
@@ -1467,24 +1766,42 @@ static const struct file_operations smk_load_self_ops = { | |||
1467 | }; | 1766 | }; |
1468 | 1767 | ||
1469 | /** | 1768 | /** |
1470 | * smk_write_access - handle access check transaction | 1769 | * smk_user_access - handle access check transaction |
1471 | * @file: file pointer | 1770 | * @file: file pointer |
1472 | * @buf: data from user space | 1771 | * @buf: data from user space |
1473 | * @count: bytes sent | 1772 | * @count: bytes sent |
1474 | * @ppos: where to start - must be 0 | 1773 | * @ppos: where to start - must be 0 |
1475 | */ | 1774 | */ |
1476 | static ssize_t smk_write_access(struct file *file, const char __user *buf, | 1775 | static ssize_t smk_user_access(struct file *file, const char __user *buf, |
1477 | size_t count, loff_t *ppos) | 1776 | size_t count, loff_t *ppos, int format) |
1478 | { | 1777 | { |
1479 | struct smack_rule rule; | 1778 | struct smack_rule rule; |
1480 | char *data; | 1779 | char *data; |
1780 | char *cod; | ||
1481 | int res; | 1781 | int res; |
1482 | 1782 | ||
1483 | data = simple_transaction_get(file, buf, count); | 1783 | data = simple_transaction_get(file, buf, count); |
1484 | if (IS_ERR(data)) | 1784 | if (IS_ERR(data)) |
1485 | return PTR_ERR(data); | 1785 | return PTR_ERR(data); |
1486 | 1786 | ||
1487 | if (count < SMK_LOADLEN || smk_parse_rule(data, &rule, 0)) | 1787 | if (format == SMK_FIXED24_FMT) { |
1788 | if (count < SMK_LOADLEN) | ||
1789 | return -EINVAL; | ||
1790 | res = smk_parse_rule(data, &rule, 0); | ||
1791 | } else { | ||
1792 | /* | ||
1793 | * Copy the data to make sure the string is terminated. | ||
1794 | */ | ||
1795 | cod = kzalloc(count + 1, GFP_KERNEL); | ||
1796 | if (cod == NULL) | ||
1797 | return -ENOMEM; | ||
1798 | memcpy(cod, data, count); | ||
1799 | cod[count] = '\0'; | ||
1800 | res = smk_parse_long_rule(cod, &rule, 0); | ||
1801 | kfree(cod); | ||
1802 | } | ||
1803 | |||
1804 | if (res) | ||
1488 | return -EINVAL; | 1805 | return -EINVAL; |
1489 | 1806 | ||
1490 | res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access, | 1807 | res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access, |
@@ -1493,7 +1810,23 @@ static ssize_t smk_write_access(struct file *file, const char __user *buf, | |||
1493 | data[1] = '\0'; | 1810 | data[1] = '\0'; |
1494 | 1811 | ||
1495 | simple_transaction_set(file, 2); | 1812 | simple_transaction_set(file, 2); |
1496 | return SMK_LOADLEN; | 1813 | |
1814 | if (format == SMK_FIXED24_FMT) | ||
1815 | return SMK_LOADLEN; | ||
1816 | return count; | ||
1817 | } | ||
1818 | |||
1819 | /** | ||
1820 | * smk_write_access - handle access check transaction | ||
1821 | * @file: file pointer | ||
1822 | * @buf: data from user space | ||
1823 | * @count: bytes sent | ||
1824 | * @ppos: where to start - must be 0 | ||
1825 | */ | ||
1826 | static ssize_t smk_write_access(struct file *file, const char __user *buf, | ||
1827 | size_t count, loff_t *ppos) | ||
1828 | { | ||
1829 | return smk_user_access(file, buf, count, ppos, SMK_FIXED24_FMT); | ||
1497 | } | 1830 | } |
1498 | 1831 | ||
1499 | static const struct file_operations smk_access_ops = { | 1832 | static const struct file_operations smk_access_ops = { |
@@ -1503,6 +1836,163 @@ static const struct file_operations smk_access_ops = { | |||
1503 | .llseek = generic_file_llseek, | 1836 | .llseek = generic_file_llseek, |
1504 | }; | 1837 | }; |
1505 | 1838 | ||
1839 | |||
1840 | /* | ||
1841 | * Seq_file read operations for /smack/load2 | ||
1842 | */ | ||
1843 | |||
1844 | static int load2_seq_show(struct seq_file *s, void *v) | ||
1845 | { | ||
1846 | struct list_head *list = v; | ||
1847 | struct smack_master_list *smlp = | ||
1848 | list_entry(list, struct smack_master_list, list); | ||
1849 | |||
1850 | smk_rule_show(s, smlp->smk_rule, SMK_LONGLABEL); | ||
1851 | |||
1852 | return 0; | ||
1853 | } | ||
1854 | |||
1855 | static const struct seq_operations load2_seq_ops = { | ||
1856 | .start = load2_seq_start, | ||
1857 | .next = load2_seq_next, | ||
1858 | .show = load2_seq_show, | ||
1859 | .stop = smk_seq_stop, | ||
1860 | }; | ||
1861 | |||
1862 | /** | ||
1863 | * smk_open_load2 - open() for /smack/load2 | ||
1864 | * @inode: inode structure representing file | ||
1865 | * @file: "load2" file pointer | ||
1866 | * | ||
1867 | * For reading, use load2_seq_* seq_file reading operations. | ||
1868 | */ | ||
1869 | static int smk_open_load2(struct inode *inode, struct file *file) | ||
1870 | { | ||
1871 | return seq_open(file, &load2_seq_ops); | ||
1872 | } | ||
1873 | |||
1874 | /** | ||
1875 | * smk_write_load2 - write() for /smack/load2 | ||
1876 | * @file: file pointer, not actually used | ||
1877 | * @buf: where to get the data from | ||
1878 | * @count: bytes sent | ||
1879 | * @ppos: where to start - must be 0 | ||
1880 | * | ||
1881 | */ | ||
1882 | static ssize_t smk_write_load2(struct file *file, const char __user *buf, | ||
1883 | size_t count, loff_t *ppos) | ||
1884 | { | ||
1885 | /* | ||
1886 | * Must have privilege. | ||
1887 | */ | ||
1888 | if (!capable(CAP_MAC_ADMIN)) | ||
1889 | return -EPERM; | ||
1890 | |||
1891 | return smk_write_rules_list(file, buf, count, ppos, NULL, NULL, | ||
1892 | SMK_LONG_FMT); | ||
1893 | } | ||
1894 | |||
1895 | static const struct file_operations smk_load2_ops = { | ||
1896 | .open = smk_open_load2, | ||
1897 | .read = seq_read, | ||
1898 | .llseek = seq_lseek, | ||
1899 | .write = smk_write_load2, | ||
1900 | .release = seq_release, | ||
1901 | }; | ||
1902 | |||
1903 | /* | ||
1904 | * Seq_file read operations for /smack/load-self2 | ||
1905 | */ | ||
1906 | |||
1907 | static void *load_self2_seq_start(struct seq_file *s, loff_t *pos) | ||
1908 | { | ||
1909 | struct task_smack *tsp = current_security(); | ||
1910 | |||
1911 | return smk_seq_start(s, pos, &tsp->smk_rules); | ||
1912 | } | ||
1913 | |||
1914 | static void *load_self2_seq_next(struct seq_file *s, void *v, loff_t *pos) | ||
1915 | { | ||
1916 | struct task_smack *tsp = current_security(); | ||
1917 | |||
1918 | return smk_seq_next(s, v, pos, &tsp->smk_rules); | ||
1919 | } | ||
1920 | |||
1921 | static int load_self2_seq_show(struct seq_file *s, void *v) | ||
1922 | { | ||
1923 | struct list_head *list = v; | ||
1924 | struct smack_rule *srp = | ||
1925 | list_entry(list, struct smack_rule, list); | ||
1926 | |||
1927 | smk_rule_show(s, srp, SMK_LONGLABEL); | ||
1928 | |||
1929 | return 0; | ||
1930 | } | ||
1931 | |||
1932 | static const struct seq_operations load_self2_seq_ops = { | ||
1933 | .start = load_self2_seq_start, | ||
1934 | .next = load_self2_seq_next, | ||
1935 | .show = load_self2_seq_show, | ||
1936 | .stop = smk_seq_stop, | ||
1937 | }; | ||
1938 | |||
1939 | /** | ||
1940 | * smk_open_load_self2 - open() for /smack/load-self2 | ||
1941 | * @inode: inode structure representing file | ||
1942 | * @file: "load" file pointer | ||
1943 | * | ||
1944 | * For reading, use load_seq_* seq_file reading operations. | ||
1945 | */ | ||
1946 | static int smk_open_load_self2(struct inode *inode, struct file *file) | ||
1947 | { | ||
1948 | return seq_open(file, &load_self2_seq_ops); | ||
1949 | } | ||
1950 | |||
1951 | /** | ||
1952 | * smk_write_load_self2 - write() for /smack/load-self2 | ||
1953 | * @file: file pointer, not actually used | ||
1954 | * @buf: where to get the data from | ||
1955 | * @count: bytes sent | ||
1956 | * @ppos: where to start - must be 0 | ||
1957 | * | ||
1958 | */ | ||
1959 | static ssize_t smk_write_load_self2(struct file *file, const char __user *buf, | ||
1960 | size_t count, loff_t *ppos) | ||
1961 | { | ||
1962 | struct task_smack *tsp = current_security(); | ||
1963 | |||
1964 | return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules, | ||
1965 | &tsp->smk_rules_lock, SMK_LONG_FMT); | ||
1966 | } | ||
1967 | |||
1968 | static const struct file_operations smk_load_self2_ops = { | ||
1969 | .open = smk_open_load_self2, | ||
1970 | .read = seq_read, | ||
1971 | .llseek = seq_lseek, | ||
1972 | .write = smk_write_load_self2, | ||
1973 | .release = seq_release, | ||
1974 | }; | ||
1975 | |||
1976 | /** | ||
1977 | * smk_write_access2 - handle access check transaction | ||
1978 | * @file: file pointer | ||
1979 | * @buf: data from user space | ||
1980 | * @count: bytes sent | ||
1981 | * @ppos: where to start - must be 0 | ||
1982 | */ | ||
1983 | static ssize_t smk_write_access2(struct file *file, const char __user *buf, | ||
1984 | size_t count, loff_t *ppos) | ||
1985 | { | ||
1986 | return smk_user_access(file, buf, count, ppos, SMK_LONG_FMT); | ||
1987 | } | ||
1988 | |||
1989 | static const struct file_operations smk_access2_ops = { | ||
1990 | .write = smk_write_access2, | ||
1991 | .read = simple_transaction_read, | ||
1992 | .release = simple_transaction_release, | ||
1993 | .llseek = generic_file_llseek, | ||
1994 | }; | ||
1995 | |||
1506 | /** | 1996 | /** |
1507 | * smk_fill_super - fill the /smackfs superblock | 1997 | * smk_fill_super - fill the /smackfs superblock |
1508 | * @sb: the empty superblock | 1998 | * @sb: the empty superblock |
@@ -1539,6 +2029,16 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) | |||
1539 | "load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO}, | 2029 | "load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO}, |
1540 | [SMK_ACCESSES] = { | 2030 | [SMK_ACCESSES] = { |
1541 | "access", &smk_access_ops, S_IRUGO|S_IWUGO}, | 2031 | "access", &smk_access_ops, S_IRUGO|S_IWUGO}, |
2032 | [SMK_MAPPED] = { | ||
2033 | "mapped", &smk_mapped_ops, S_IRUGO|S_IWUSR}, | ||
2034 | [SMK_LOAD2] = { | ||
2035 | "load2", &smk_load2_ops, S_IRUGO|S_IWUSR}, | ||
2036 | [SMK_LOAD_SELF2] = { | ||
2037 | "load-self2", &smk_load_self2_ops, S_IRUGO|S_IWUGO}, | ||
2038 | [SMK_ACCESS2] = { | ||
2039 | "access2", &smk_access2_ops, S_IRUGO|S_IWUGO}, | ||
2040 | [SMK_CIPSO2] = { | ||
2041 | "cipso2", &smk_cipso2_ops, S_IRUGO|S_IWUSR}, | ||
1542 | /* last one */ | 2042 | /* last one */ |
1543 | {""} | 2043 | {""} |
1544 | }; | 2044 | }; |
@@ -1581,6 +2081,15 @@ static struct file_system_type smk_fs_type = { | |||
1581 | 2081 | ||
1582 | static struct vfsmount *smackfs_mount; | 2082 | static struct vfsmount *smackfs_mount; |
1583 | 2083 | ||
2084 | static int __init smk_preset_netlabel(struct smack_known *skp) | ||
2085 | { | ||
2086 | skp->smk_netlabel.domain = skp->smk_known; | ||
2087 | skp->smk_netlabel.flags = | ||
2088 | NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL; | ||
2089 | return smk_netlbl_mls(smack_cipso_direct, skp->smk_known, | ||
2090 | &skp->smk_netlabel, strlen(skp->smk_known)); | ||
2091 | } | ||
2092 | |||
1584 | /** | 2093 | /** |
1585 | * init_smk_fs - get the smackfs superblock | 2094 | * init_smk_fs - get the smackfs superblock |
1586 | * | 2095 | * |
@@ -1597,6 +2106,7 @@ static struct vfsmount *smackfs_mount; | |||
1597 | static int __init init_smk_fs(void) | 2106 | static int __init init_smk_fs(void) |
1598 | { | 2107 | { |
1599 | int err; | 2108 | int err; |
2109 | int rc; | ||
1600 | 2110 | ||
1601 | if (!security_module_enable(&smack_ops)) | 2111 | if (!security_module_enable(&smack_ops)) |
1602 | return 0; | 2112 | return 0; |
@@ -1614,6 +2124,25 @@ static int __init init_smk_fs(void) | |||
1614 | smk_cipso_doi(); | 2124 | smk_cipso_doi(); |
1615 | smk_unlbl_ambient(NULL); | 2125 | smk_unlbl_ambient(NULL); |
1616 | 2126 | ||
2127 | rc = smk_preset_netlabel(&smack_known_floor); | ||
2128 | if (err == 0 && rc < 0) | ||
2129 | err = rc; | ||
2130 | rc = smk_preset_netlabel(&smack_known_hat); | ||
2131 | if (err == 0 && rc < 0) | ||
2132 | err = rc; | ||
2133 | rc = smk_preset_netlabel(&smack_known_huh); | ||
2134 | if (err == 0 && rc < 0) | ||
2135 | err = rc; | ||
2136 | rc = smk_preset_netlabel(&smack_known_invalid); | ||
2137 | if (err == 0 && rc < 0) | ||
2138 | err = rc; | ||
2139 | rc = smk_preset_netlabel(&smack_known_star); | ||
2140 | if (err == 0 && rc < 0) | ||
2141 | err = rc; | ||
2142 | rc = smk_preset_netlabel(&smack_known_web); | ||
2143 | if (err == 0 && rc < 0) | ||
2144 | err = rc; | ||
2145 | |||
1617 | return err; | 2146 | return err; |
1618 | } | 2147 | } |
1619 | 2148 | ||