Branch data Line data Source code
1 : : /*
2 : : * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com>
3 : : *
4 : : * This program is free software; you can redistribute it and/or modify
5 : : * it under the terms of the GNU General Public License as published by
6 : : * the Free Software Foundation, version 2.
7 : : *
8 : : * Authors:
9 : : * Casey Schaufler <casey@schaufler-ca.com>
10 : : * Ahmed S. Darwish <darwish.07@gmail.com>
11 : : *
12 : : * Special thanks to the authors of selinuxfs.
13 : : *
14 : : * Karl MacMillan <kmacmillan@tresys.com>
15 : : * James Morris <jmorris@redhat.com>
16 : : *
17 : : */
18 : :
19 : : #include <linux/kernel.h>
20 : : #include <linux/vmalloc.h>
21 : : #include <linux/security.h>
22 : : #include <linux/mutex.h>
23 : : #include <linux/slab.h>
24 : : #include <net/net_namespace.h>
25 : : #include <net/cipso_ipv4.h>
26 : : #include <linux/seq_file.h>
27 : : #include <linux/ctype.h>
28 : : #include <linux/audit.h>
29 : : #include <linux/magic.h>
30 : : #include "smack.h"
31 : :
32 : : /*
33 : : * smackfs pseudo filesystem.
34 : : */
35 : :
36 : : enum smk_inos {
37 : : SMK_ROOT_INO = 2,
38 : : SMK_LOAD = 3, /* load policy */
39 : : SMK_CIPSO = 4, /* load label -> CIPSO mapping */
40 : : SMK_DOI = 5, /* CIPSO DOI */
41 : : SMK_DIRECT = 6, /* CIPSO level indicating direct label */
42 : : SMK_AMBIENT = 7, /* internet ambient label */
43 : : SMK_NETLBLADDR = 8, /* single label hosts */
44 : : SMK_ONLYCAP = 9, /* the only "capable" label */
45 : : SMK_LOGGING = 10, /* logging */
46 : : SMK_LOAD_SELF = 11, /* task specific rules */
47 : : SMK_ACCESSES = 12, /* access policy */
48 : : SMK_MAPPED = 13, /* CIPSO level indicating mapped label */
49 : : SMK_LOAD2 = 14, /* load policy with long labels */
50 : : SMK_LOAD_SELF2 = 15, /* load task specific rules with long labels */
51 : : SMK_ACCESS2 = 16, /* make an access check with long labels */
52 : : SMK_CIPSO2 = 17, /* load long label -> CIPSO mapping */
53 : : SMK_REVOKE_SUBJ = 18, /* set rules with subject label to '-' */
54 : : SMK_CHANGE_RULE = 19, /* change or add rules (long labels) */
55 : : SMK_SYSLOG = 20, /* change syslog label) */
56 : : };
57 : :
58 : : /*
59 : : * List locks
60 : : */
61 : : static DEFINE_MUTEX(smack_cipso_lock);
62 : : static DEFINE_MUTEX(smack_ambient_lock);
63 : : static DEFINE_MUTEX(smack_syslog_lock);
64 : : static DEFINE_MUTEX(smk_netlbladdr_lock);
65 : :
66 : : /*
67 : : * This is the "ambient" label for network traffic.
68 : : * If it isn't somehow marked, use this.
69 : : * It can be reset via smackfs/ambient
70 : : */
71 : : struct smack_known *smack_net_ambient;
72 : :
73 : : /*
74 : : * This is the level in a CIPSO header that indicates a
75 : : * smack label is contained directly in the category set.
76 : : * It can be reset via smackfs/direct
77 : : */
78 : : int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT;
79 : :
80 : : /*
81 : : * This is the level in a CIPSO header that indicates a
82 : : * secid is contained directly in the category set.
83 : : * It can be reset via smackfs/mapped
84 : : */
85 : : int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT;
86 : :
87 : : /*
88 : : * Unless a process is running with this label even
89 : : * having CAP_MAC_OVERRIDE isn't enough to grant
90 : : * privilege to violate MAC policy. If no label is
91 : : * designated (the NULL case) capabilities apply to
92 : : * everyone. It is expected that the hat (^) label
93 : : * will be used if any label is used.
94 : : */
95 : : struct smack_known *smack_onlycap;
96 : :
97 : : /*
98 : : * If this value is set restrict syslog use to the label specified.
99 : : * It can be reset via smackfs/syslog
100 : : */
101 : : struct smack_known *smack_syslog_label;
102 : :
103 : : /*
104 : : * Certain IP addresses may be designated as single label hosts.
105 : : * Packets are sent there unlabeled, but only from tasks that
106 : : * can write to the specified label.
107 : : */
108 : :
109 : : LIST_HEAD(smk_netlbladdr_list);
110 : :
111 : : /*
112 : : * Rule lists are maintained for each label.
113 : : * This master list is just for reading /smack/load and /smack/load2.
114 : : */
115 : : struct smack_master_list {
116 : : struct list_head list;
117 : : struct smack_rule *smk_rule;
118 : : };
119 : :
120 : : LIST_HEAD(smack_rule_list);
121 : :
122 : : struct smack_parsed_rule {
123 : : struct smack_known *smk_subject;
124 : : char *smk_object;
125 : : int smk_access1;
126 : : int smk_access2;
127 : : };
128 : :
129 : : static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
130 : :
131 : : const char *smack_cipso_option = SMACK_CIPSO_OPTION;
132 : :
133 : : /*
134 : : * Values for parsing cipso rules
135 : : * SMK_DIGITLEN: Length of a digit field in a rule.
136 : : * SMK_CIPSOMIN: Minimum possible cipso rule length.
137 : : * SMK_CIPSOMAX: Maximum possible cipso rule length.
138 : : */
139 : : #define SMK_DIGITLEN 4
140 : : #define SMK_CIPSOMIN (SMK_LABELLEN + 2 * SMK_DIGITLEN)
141 : : #define SMK_CIPSOMAX (SMK_CIPSOMIN + SMACK_CIPSO_MAXCATNUM * SMK_DIGITLEN)
142 : :
143 : : /*
144 : : * Values for parsing MAC rules
145 : : * SMK_ACCESS: Maximum possible combination of access permissions
146 : : * SMK_ACCESSLEN: Maximum length for a rule access field
147 : : * SMK_LOADLEN: Smack rule length
148 : : */
149 : : #define SMK_OACCESS "rwxa"
150 : : #define SMK_ACCESS "rwxatl"
151 : : #define SMK_OACCESSLEN (sizeof(SMK_OACCESS) - 1)
152 : : #define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1)
153 : : #define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN)
154 : : #define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)
155 : :
156 : : /*
157 : : * Stricly for CIPSO level manipulation.
158 : : * Set the category bit number in a smack label sized buffer.
159 : : */
160 : : static inline void smack_catset_bit(unsigned int cat, char *catsetp)
161 : : {
162 [ # # ]: 0 : if (cat == 0 || cat > (SMK_CIPSOLEN * 8))
163 : : return;
164 : :
165 : 0 : catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8);
166 : : }
167 : :
168 : : /**
169 : : * smk_netlabel_audit_set - fill a netlbl_audit struct
170 : : * @nap: structure to fill
171 : : */
172 : : static void smk_netlabel_audit_set(struct netlbl_audit *nap)
173 : : {
174 : : struct smack_known *skp = smk_of_current();
175 : :
176 : 0 : nap->loginuid = audit_get_loginuid(current);
177 : 0 : nap->sessionid = audit_get_sessionid(current);
178 : 0 : nap->secid = skp->smk_secid;
179 : : }
180 : :
181 : : /*
182 : : * Value for parsing single label host rules
183 : : * "1.2.3.4 X"
184 : : */
185 : : #define SMK_NETLBLADDRMIN 9
186 : :
187 : : /**
188 : : * smk_set_access - add a rule to the rule list or replace an old rule
189 : : * @srp: the rule to add or replace
190 : : * @rule_list: the list of rules
191 : : * @rule_lock: the rule list lock
192 : : * @global: if non-zero, indicates a global rule
193 : : *
194 : : * Looks through the current subject/object/access list for
195 : : * the subject/object pair and replaces the access that was
196 : : * there. If the pair isn't found add it with the specified
197 : : * access.
198 : : *
199 : : * Returns 0 if nothing goes wrong or -ENOMEM if it fails
200 : : * during the allocation of the new pair to add.
201 : : */
202 : 0 : static int smk_set_access(struct smack_parsed_rule *srp,
203 : : struct list_head *rule_list,
204 : : struct mutex *rule_lock, int global)
205 : : {
206 : : struct smack_rule *sp;
207 : : struct smack_master_list *smlp;
208 : : int found = 0;
209 : : int rc = 0;
210 : :
211 : 0 : mutex_lock(rule_lock);
212 : :
213 : : /*
214 : : * Because the object label is less likely to match
215 : : * than the subject label check it first
216 : : */
217 [ # # ]: 0 : list_for_each_entry_rcu(sp, rule_list, list) {
218 [ # # ][ # # ]: 0 : if (sp->smk_object == srp->smk_object &&
219 : 0 : sp->smk_subject == srp->smk_subject) {
220 : : found = 1;
221 : 0 : sp->smk_access |= srp->smk_access1;
222 : 0 : sp->smk_access &= ~srp->smk_access2;
223 : 0 : break;
224 : : }
225 : : }
226 : :
227 [ # # ]: 0 : if (found == 0) {
228 : : sp = kzalloc(sizeof(*sp), GFP_KERNEL);
229 [ # # ]: 0 : if (sp == NULL) {
230 : : rc = -ENOMEM;
231 : : goto out;
232 : : }
233 : :
234 : 0 : sp->smk_subject = srp->smk_subject;
235 : 0 : sp->smk_object = srp->smk_object;
236 : 0 : sp->smk_access = srp->smk_access1 & ~srp->smk_access2;
237 : :
238 : 0 : list_add_rcu(&sp->list, rule_list);
239 : : /*
240 : : * If this is a global as opposed to self and a new rule
241 : : * it needs to get added for reporting.
242 : : */
243 [ # # ]: 0 : if (global) {
244 : : smlp = kzalloc(sizeof(*smlp), GFP_KERNEL);
245 [ # # ]: 0 : if (smlp != NULL) {
246 : 0 : smlp->smk_rule = sp;
247 : 0 : list_add_rcu(&smlp->list, &smack_rule_list);
248 : : } else
249 : : rc = -ENOMEM;
250 : : }
251 : : }
252 : :
253 : : out:
254 : 0 : mutex_unlock(rule_lock);
255 : 0 : return rc;
256 : : }
257 : :
258 : : /**
259 : : * smk_perm_from_str - parse smack accesses from a text string
260 : : * @string: a text string that contains a Smack accesses code
261 : : *
262 : : * Returns an integer with respective bits set for specified accesses.
263 : : */
264 : 0 : static int smk_perm_from_str(const char *string)
265 : : {
266 : : int perm = 0;
267 : : const char *cp;
268 : :
269 : 0 : for (cp = string; ; cp++)
270 [ # # # # : 0 : switch (*cp) {
# # # # ]
271 : : case '-':
272 : : break;
273 : : case 'r':
274 : : case 'R':
275 : 0 : perm |= MAY_READ;
276 : 0 : break;
277 : : case 'w':
278 : : case 'W':
279 : 0 : perm |= MAY_WRITE;
280 : 0 : break;
281 : : case 'x':
282 : : case 'X':
283 : 0 : perm |= MAY_EXEC;
284 : 0 : break;
285 : : case 'a':
286 : : case 'A':
287 : 0 : perm |= MAY_APPEND;
288 : 0 : break;
289 : : case 't':
290 : : case 'T':
291 : 0 : perm |= MAY_TRANSMUTE;
292 : 0 : break;
293 : : case 'l':
294 : : case 'L':
295 : 0 : perm |= MAY_LOCK;
296 : 0 : break;
297 : : default:
298 : 0 : return perm;
299 : : }
300 : 0 : }
301 : :
302 : : /**
303 : : * smk_fill_rule - Fill Smack rule from strings
304 : : * @subject: subject label string
305 : : * @object: object label string
306 : : * @access1: access string
307 : : * @access2: string with permissions to be removed
308 : : * @rule: Smack rule
309 : : * @import: if non-zero, import labels
310 : : * @len: label length limit
311 : : *
312 : : * Returns 0 on success, -EINVAL on failure and -ENOENT when either subject
313 : : * or object is missing.
314 : : */
315 : 0 : static int smk_fill_rule(const char *subject, const char *object,
316 : : const char *access1, const char *access2,
317 : : struct smack_parsed_rule *rule, int import,
318 : : int len)
319 : : {
320 : : const char *cp;
321 : : struct smack_known *skp;
322 : :
323 [ # # ]: 0 : if (import) {
324 : 0 : rule->smk_subject = smk_import_entry(subject, len);
325 [ # # ]: 0 : if (rule->smk_subject == NULL)
326 : : return -EINVAL;
327 : :
328 : 0 : rule->smk_object = smk_import(object, len);
329 [ # # ]: 0 : if (rule->smk_object == NULL)
330 : : return -EINVAL;
331 : : } else {
332 : 0 : cp = smk_parse_smack(subject, len);
333 [ # # ]: 0 : if (cp == NULL)
334 : : return -EINVAL;
335 : 0 : skp = smk_find_entry(cp);
336 : 0 : kfree(cp);
337 [ # # ]: 0 : if (skp == NULL)
338 : : return -ENOENT;
339 : 0 : rule->smk_subject = skp;
340 : :
341 : 0 : cp = smk_parse_smack(object, len);
342 [ # # ]: 0 : if (cp == NULL)
343 : : return -EINVAL;
344 : 0 : skp = smk_find_entry(cp);
345 : 0 : kfree(cp);
346 [ # # ]: 0 : if (skp == NULL)
347 : : return -ENOENT;
348 : 0 : rule->smk_object = skp->smk_known;
349 : : }
350 : :
351 : 0 : rule->smk_access1 = smk_perm_from_str(access1);
352 [ # # ]: 0 : if (access2)
353 : 0 : rule->smk_access2 = smk_perm_from_str(access2);
354 : : else
355 : 0 : rule->smk_access2 = ~rule->smk_access1;
356 : :
357 : : return 0;
358 : : }
359 : :
360 : : /**
361 : : * smk_parse_rule - parse Smack rule from load string
362 : : * @data: string to be parsed whose size is SMK_LOADLEN
363 : : * @rule: Smack rule
364 : : * @import: if non-zero, import labels
365 : : *
366 : : * Returns 0 on success, -1 on errors.
367 : : */
368 : 0 : static int smk_parse_rule(const char *data, struct smack_parsed_rule *rule,
369 : : int import)
370 : : {
371 : : int rc;
372 : :
373 : 0 : rc = smk_fill_rule(data, data + SMK_LABELLEN,
374 : : data + SMK_LABELLEN + SMK_LABELLEN, NULL, rule,
375 : : import, SMK_LABELLEN);
376 : 0 : return rc;
377 : : }
378 : :
379 : : /**
380 : : * smk_parse_long_rule - parse Smack rule from rule string
381 : : * @data: string to be parsed, null terminated
382 : : * @rule: Will be filled with Smack parsed rule
383 : : * @import: if non-zero, import labels
384 : : * @tokens: numer of substrings expected in data
385 : : *
386 : : * Returns number of processed bytes on success, -1 on failure.
387 : : */
388 : 0 : static ssize_t smk_parse_long_rule(char *data, struct smack_parsed_rule *rule,
389 : : int import, int tokens)
390 : : {
391 : : ssize_t cnt = 0;
392 : : char *tok[4];
393 : : int rc;
394 : : int i;
395 : :
396 : : /*
397 : : * Parsing the rule in-place, filling all white-spaces with '\0'
398 : : */
399 [ # # ]: 0 : for (i = 0; i < tokens; ++i) {
400 [ # # ]: 0 : while (isspace(data[cnt]))
401 : 0 : data[cnt++] = '\0';
402 : :
403 [ # # ]: 0 : if (data[cnt] == '\0')
404 : : /* Unexpected end of data */
405 : : return -1;
406 : :
407 : 0 : tok[i] = data + cnt;
408 : :
409 [ # # ][ # # ]: 0 : while (data[cnt] && !isspace(data[cnt]))
410 : 0 : ++cnt;
411 : : }
412 [ # # ]: 0 : while (isspace(data[cnt]))
413 : 0 : data[cnt++] = '\0';
414 : :
415 [ # # ]: 0 : while (i < 4)
416 : 0 : tok[i++] = NULL;
417 : :
418 : 0 : rc = smk_fill_rule(tok[0], tok[1], tok[2], tok[3], rule, import, 0);
419 [ # # ]: 0 : return rc == 0 ? cnt : rc;
420 : : }
421 : :
422 : : #define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */
423 : : #define SMK_LONG_FMT 1 /* Variable long label format */
424 : : #define SMK_CHANGE_FMT 2 /* Rule modification format */
425 : : /**
426 : : * smk_write_rules_list - write() for any /smack rule file
427 : : * @file: file pointer, not actually used
428 : : * @buf: where to get the data from
429 : : * @count: bytes sent
430 : : * @ppos: where to start - must be 0
431 : : * @rule_list: the list of rules to write to
432 : : * @rule_lock: lock for the rule list
433 : : * @format: /smack/load or /smack/load2 or /smack/change-rule format.
434 : : *
435 : : * Get one smack access rule from above.
436 : : * The format for SMK_LONG_FMT is:
437 : : * "subject<whitespace>object<whitespace>access[<whitespace>...]"
438 : : * The format for SMK_FIXED24_FMT is exactly:
439 : : * "subject object rwxat"
440 : : * The format for SMK_CHANGE_FMT is:
441 : : * "subject<whitespace>object<whitespace>
442 : : * acc_enable<whitespace>acc_disable[<whitespace>...]"
443 : : */
444 : 0 : static ssize_t smk_write_rules_list(struct file *file, const char __user *buf,
445 : : size_t count, loff_t *ppos,
446 : : struct list_head *rule_list,
447 : : struct mutex *rule_lock, int format)
448 : : {
449 : : struct smack_parsed_rule rule;
450 : : char *data;
451 : : int rc;
452 : : int trunc = 0;
453 : : int tokens;
454 : : ssize_t cnt = 0;
455 : :
456 : : /*
457 : : * No partial writes.
458 : : * Enough data must be present.
459 : : */
460 [ # # ]: 0 : if (*ppos != 0)
461 : : return -EINVAL;
462 : :
463 [ # # ]: 0 : if (format == SMK_FIXED24_FMT) {
464 : : /*
465 : : * Minor hack for backward compatibility
466 : : */
467 [ # # ]: 0 : if (count < SMK_OLOADLEN || count > SMK_LOADLEN)
468 : : return -EINVAL;
469 : : } else {
470 [ # # ]: 0 : if (count >= PAGE_SIZE) {
471 : : count = PAGE_SIZE - 1;
472 : : trunc = 1;
473 : : }
474 : : }
475 : :
476 : 0 : data = kmalloc(count + 1, GFP_KERNEL);
477 [ # # ]: 0 : if (data == NULL)
478 : : return -ENOMEM;
479 : :
480 [ # # ]: 0 : if (copy_from_user(data, buf, count) != 0) {
481 : : rc = -EFAULT;
482 : : goto out;
483 : : }
484 : :
485 : : /*
486 : : * In case of parsing only part of user buf,
487 : : * avoid having partial rule at the data buffer
488 : : */
489 [ # # ]: 0 : if (trunc) {
490 [ # # ][ # # ]: 0 : while (count > 0 && (data[count - 1] != '\n'))
491 : : --count;
492 [ # # ]: 0 : if (count == 0) {
493 : : rc = -EINVAL;
494 : : goto out;
495 : : }
496 : : }
497 : :
498 : 0 : data[count] = '\0';
499 [ # # ]: 0 : tokens = (format == SMK_CHANGE_FMT ? 4 : 3);
500 [ # # ]: 0 : while (cnt < count) {
501 [ # # ]: 0 : if (format == SMK_FIXED24_FMT) {
502 : 0 : rc = smk_parse_rule(data, &rule, 1);
503 [ # # ]: 0 : if (rc != 0) {
504 : : rc = -EINVAL;
505 : : goto out;
506 : : }
507 : 0 : cnt = count;
508 : : } else {
509 : 0 : rc = smk_parse_long_rule(data + cnt, &rule, 1, tokens);
510 [ # # ]: 0 : if (rc <= 0) {
511 : : rc = -EINVAL;
512 : : goto out;
513 : : }
514 : 0 : cnt += rc;
515 : : }
516 : :
517 [ # # ]: 0 : if (rule_list == NULL)
518 : 0 : rc = smk_set_access(&rule, &rule.smk_subject->smk_rules,
519 : : &rule.smk_subject->smk_rules_lock, 1);
520 : : else
521 : 0 : rc = smk_set_access(&rule, rule_list, rule_lock, 0);
522 : :
523 [ # # ]: 0 : if (rc)
524 : : goto out;
525 : : }
526 : :
527 : : rc = cnt;
528 : : out:
529 : 0 : kfree(data);
530 : : return rc;
531 : : }
532 : :
533 : : /*
534 : : * Core logic for smackfs seq list operations.
535 : : */
536 : :
537 : : static void *smk_seq_start(struct seq_file *s, loff_t *pos,
538 : : struct list_head *head)
539 : : {
540 : : struct list_head *list;
541 : :
542 : : /*
543 : : * This is 0 the first time through.
544 : : */
545 [ # # ][ # # ]: 0 : if (s->index == 0)
[ # # ][ # # ]
[ # # ]
546 : 0 : s->private = head;
547 : :
548 [ # # ][ # # ]: 0 : if (s->private == NULL)
[ # # ][ # # ]
[ # # ]
549 : : return NULL;
550 : :
551 : : list = s->private;
552 [ # # ][ # # ]: 0 : if (list_empty(list))
[ # # ][ # # ]
[ # # ]
553 : : return NULL;
554 : :
555 [ # # ][ # # ]: 0 : if (s->index == 0)
[ # # ][ # # ]
[ # # ]
556 : : return list->next;
557 : : return list;
558 : : }
559 : :
560 : : static void *smk_seq_next(struct seq_file *s, void *v, loff_t *pos,
561 : : struct list_head *head)
562 : : {
563 : 0 : struct list_head *list = v;
564 : :
565 [ # # ][ # # ]: 0 : if (list_is_last(list, head)) {
[ # # ][ # # ]
[ # # ]
566 : 0 : s->private = NULL;
567 : : return NULL;
568 : : }
569 : 0 : s->private = list->next;
570 : 0 : return list->next;
571 : : }
572 : :
573 : 0 : static void smk_seq_stop(struct seq_file *s, void *v)
574 : : {
575 : : /* No-op */
576 : 0 : }
577 : :
578 : 0 : static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max)
579 : : {
580 : : /*
581 : : * Don't show any rules with label names too long for
582 : : * interface file (/smack/load or /smack/load2)
583 : : * because you should expect to be able to write
584 : : * anything you read back.
585 : : */
586 [ # # ][ # # ]: 0 : if (strlen(srp->smk_subject->smk_known) >= max ||
587 : 0 : strlen(srp->smk_object) >= max)
588 : : return;
589 : :
590 [ # # ]: 0 : if (srp->smk_access == 0)
591 : : return;
592 : :
593 : 0 : seq_printf(s, "%s %s", srp->smk_subject->smk_known, srp->smk_object);
594 : :
595 : 0 : seq_putc(s, ' ');
596 : :
597 [ # # ]: 0 : if (srp->smk_access & MAY_READ)
598 : 0 : seq_putc(s, 'r');
599 [ # # ]: 0 : if (srp->smk_access & MAY_WRITE)
600 : 0 : seq_putc(s, 'w');
601 [ # # ]: 0 : if (srp->smk_access & MAY_EXEC)
602 : 0 : seq_putc(s, 'x');
603 [ # # ]: 0 : if (srp->smk_access & MAY_APPEND)
604 : 0 : seq_putc(s, 'a');
605 [ # # ]: 0 : if (srp->smk_access & MAY_TRANSMUTE)
606 : 0 : seq_putc(s, 't');
607 [ # # ]: 0 : if (srp->smk_access & MAY_LOCK)
608 : 0 : seq_putc(s, 'l');
609 : :
610 : 0 : seq_putc(s, '\n');
611 : : }
612 : :
613 : : /*
614 : : * Seq_file read operations for /smack/load
615 : : */
616 : :
617 : 0 : static void *load2_seq_start(struct seq_file *s, loff_t *pos)
618 : : {
619 : 0 : return smk_seq_start(s, pos, &smack_rule_list);
620 : : }
621 : :
622 : 0 : static void *load2_seq_next(struct seq_file *s, void *v, loff_t *pos)
623 : : {
624 : 0 : return smk_seq_next(s, v, pos, &smack_rule_list);
625 : : }
626 : :
627 : 0 : static int load_seq_show(struct seq_file *s, void *v)
628 : : {
629 : : struct list_head *list = v;
630 : : struct smack_master_list *smlp =
631 : : list_entry(list, struct smack_master_list, list);
632 : :
633 : 0 : smk_rule_show(s, smlp->smk_rule, SMK_LABELLEN);
634 : :
635 : 0 : return 0;
636 : : }
637 : :
638 : : static const struct seq_operations load_seq_ops = {
639 : : .start = load2_seq_start,
640 : : .next = load2_seq_next,
641 : : .show = load_seq_show,
642 : : .stop = smk_seq_stop,
643 : : };
644 : :
645 : : /**
646 : : * smk_open_load - open() for /smack/load
647 : : * @inode: inode structure representing file
648 : : * @file: "load" file pointer
649 : : *
650 : : * For reading, use load_seq_* seq_file reading operations.
651 : : */
652 : 0 : static int smk_open_load(struct inode *inode, struct file *file)
653 : : {
654 : 0 : return seq_open(file, &load_seq_ops);
655 : : }
656 : :
657 : : /**
658 : : * smk_write_load - write() for /smack/load
659 : : * @file: file pointer, not actually used
660 : : * @buf: where to get the data from
661 : : * @count: bytes sent
662 : : * @ppos: where to start - must be 0
663 : : *
664 : : */
665 : 0 : static ssize_t smk_write_load(struct file *file, const char __user *buf,
666 : 0 : size_t count, loff_t *ppos)
667 : : {
668 : : /*
669 : : * Must have privilege.
670 : : * No partial writes.
671 : : * Enough data must be present.
672 : : */
673 [ # # ]: 0 : if (!smack_privileged(CAP_MAC_ADMIN))
674 : : return -EPERM;
675 : :
676 : 0 : return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
677 : : SMK_FIXED24_FMT);
678 : : }
679 : :
680 : : static const struct file_operations smk_load_ops = {
681 : : .open = smk_open_load,
682 : : .read = seq_read,
683 : : .llseek = seq_lseek,
684 : : .write = smk_write_load,
685 : : .release = seq_release,
686 : : };
687 : :
688 : : /**
689 : : * smk_cipso_doi - initialize the CIPSO domain
690 : : */
691 : 0 : static void smk_cipso_doi(void)
692 : : {
693 : : int rc;
694 : : struct cipso_v4_doi *doip;
695 : : struct netlbl_audit nai;
696 : :
697 : : smk_netlabel_audit_set(&nai);
698 : :
699 : 0 : rc = netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai);
700 [ # # ]: 0 : if (rc != 0)
701 : 0 : printk(KERN_WARNING "%s:%d remove rc = %d\n",
702 : : __func__, __LINE__, rc);
703 : :
704 : : doip = kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL);
705 [ # # ]: 0 : if (doip == NULL)
706 : 0 : panic("smack: Failed to initialize cipso DOI.\n");
707 : 0 : doip->map.std = NULL;
708 : 0 : doip->doi = smk_cipso_doi_value;
709 : 0 : doip->type = CIPSO_V4_MAP_PASS;
710 : 0 : doip->tags[0] = CIPSO_V4_TAG_RBITMAP;
711 [ # # ]: 0 : for (rc = 1; rc < CIPSO_V4_TAG_MAXCNT; rc++)
712 : 0 : doip->tags[rc] = CIPSO_V4_TAG_INVALID;
713 : :
714 : 0 : rc = netlbl_cfg_cipsov4_add(doip, &nai);
715 [ # # ]: 0 : if (rc != 0) {
716 : 0 : printk(KERN_WARNING "%s:%d cipso add rc = %d\n",
717 : : __func__, __LINE__, rc);
718 : 0 : kfree(doip);
719 : 0 : return;
720 : : }
721 : 0 : rc = netlbl_cfg_cipsov4_map_add(doip->doi, NULL, NULL, NULL, &nai);
722 [ # # ]: 0 : if (rc != 0) {
723 : 0 : printk(KERN_WARNING "%s:%d map add rc = %d\n",
724 : : __func__, __LINE__, rc);
725 : 0 : kfree(doip);
726 : 0 : return;
727 : : }
728 : : }
729 : :
730 : : /**
731 : : * smk_unlbl_ambient - initialize the unlabeled domain
732 : : * @oldambient: previous domain string
733 : : */
734 : 0 : static void smk_unlbl_ambient(char *oldambient)
735 : : {
736 : : int rc;
737 : : struct netlbl_audit nai;
738 : :
739 : : smk_netlabel_audit_set(&nai);
740 : :
741 [ # # ]: 0 : if (oldambient != NULL) {
742 : 0 : rc = netlbl_cfg_map_del(oldambient, PF_INET, NULL, NULL, &nai);
743 [ # # ]: 0 : if (rc != 0)
744 : 0 : printk(KERN_WARNING "%s:%d remove rc = %d\n",
745 : : __func__, __LINE__, rc);
746 : : }
747 [ # # ]: 0 : if (smack_net_ambient == NULL)
748 : 0 : smack_net_ambient = &smack_known_floor;
749 : :
750 : 0 : rc = netlbl_cfg_unlbl_map_add(smack_net_ambient->smk_known, PF_INET,
751 : : NULL, NULL, &nai);
752 [ # # ]: 0 : if (rc != 0)
753 : 0 : printk(KERN_WARNING "%s:%d add rc = %d\n",
754 : : __func__, __LINE__, rc);
755 : 0 : }
756 : :
757 : : /*
758 : : * Seq_file read operations for /smack/cipso
759 : : */
760 : :
761 : 0 : static void *cipso_seq_start(struct seq_file *s, loff_t *pos)
762 : : {
763 : 0 : return smk_seq_start(s, pos, &smack_known_list);
764 : : }
765 : :
766 : 0 : static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
767 : : {
768 : 0 : return smk_seq_next(s, v, pos, &smack_known_list);
769 : : }
770 : :
771 : : /*
772 : : * Print cipso labels in format:
773 : : * label level[/cat[,cat]]
774 : : */
775 : 0 : static int cipso_seq_show(struct seq_file *s, void *v)
776 : : {
777 : : struct list_head *list = v;
778 : : struct smack_known *skp =
779 : : list_entry(list, struct smack_known, list);
780 : 0 : struct netlbl_lsm_secattr_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
781 : : char sep = '/';
782 : : int i;
783 : :
784 : : /*
785 : : * Don't show a label that could not have been set using
786 : : * /smack/cipso. This is in support of the notion that
787 : : * anything read from /smack/cipso ought to be writeable
788 : : * to /smack/cipso.
789 : : *
790 : : * /smack/cipso2 should be used instead.
791 : : */
792 [ # # ]: 0 : if (strlen(skp->smk_known) >= SMK_LABELLEN)
793 : : return 0;
794 : :
795 : 0 : seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl);
796 : :
797 [ # # ]: 0 : for (i = netlbl_secattr_catmap_walk(cmp, 0); i >= 0;
798 : 0 : i = netlbl_secattr_catmap_walk(cmp, i + 1)) {
799 : 0 : seq_printf(s, "%c%d", sep, i);
800 : : sep = ',';
801 : : }
802 : :
803 : 0 : seq_putc(s, '\n');
804 : :
805 : 0 : return 0;
806 : : }
807 : :
808 : : static const struct seq_operations cipso_seq_ops = {
809 : : .start = cipso_seq_start,
810 : : .next = cipso_seq_next,
811 : : .show = cipso_seq_show,
812 : : .stop = smk_seq_stop,
813 : : };
814 : :
815 : : /**
816 : : * smk_open_cipso - open() for /smack/cipso
817 : : * @inode: inode structure representing file
818 : : * @file: "cipso" file pointer
819 : : *
820 : : * Connect our cipso_seq_* operations with /smack/cipso
821 : : * file_operations
822 : : */
823 : 0 : static int smk_open_cipso(struct inode *inode, struct file *file)
824 : : {
825 : 0 : return seq_open(file, &cipso_seq_ops);
826 : : }
827 : :
828 : : /**
829 : : * smk_set_cipso - do the work for write() for cipso and cipso2
830 : : * @file: file pointer, not actually used
831 : : * @buf: where to get the data from
832 : : * @count: bytes sent
833 : : * @ppos: where to start
834 : : * @format: /smack/cipso or /smack/cipso2
835 : : *
836 : : * Accepts only one cipso rule per write call.
837 : : * Returns number of bytes written or error code, as appropriate
838 : : */
839 : 0 : static ssize_t smk_set_cipso(struct file *file, const char __user *buf,
840 : : size_t count, loff_t *ppos, int format)
841 : : {
842 : : struct smack_known *skp;
843 : : struct netlbl_lsm_secattr ncats;
844 : : char mapcatset[SMK_CIPSOLEN];
845 : : int maplevel;
846 : : unsigned int cat;
847 : : int catlen;
848 : : ssize_t rc = -EINVAL;
849 : : char *data = NULL;
850 : : char *rule;
851 : : int ret;
852 : : int i;
853 : :
854 : : /*
855 : : * Must have privilege.
856 : : * No partial writes.
857 : : * Enough data must be present.
858 : : */
859 [ # # ]: 0 : if (!smack_privileged(CAP_MAC_ADMIN))
860 : : return -EPERM;
861 [ # # ]: 0 : if (*ppos != 0)
862 : : return -EINVAL;
863 [ # # ][ # # ]: 0 : if (format == SMK_FIXED24_FMT &&
864 : 0 : (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX))
865 : : return -EINVAL;
866 : :
867 : 0 : data = kzalloc(count + 1, GFP_KERNEL);
868 [ # # ]: 0 : if (data == NULL)
869 : : return -ENOMEM;
870 : :
871 [ # # ]: 0 : if (copy_from_user(data, buf, count) != 0) {
872 : : rc = -EFAULT;
873 : : goto unlockedout;
874 : : }
875 : :
876 : 0 : data[count] = '\0';
877 : : rule = data;
878 : : /*
879 : : * Only allow one writer at a time. Writes should be
880 : : * quite rare and small in any case.
881 : : */
882 : 0 : mutex_lock(&smack_cipso_lock);
883 : :
884 : 0 : skp = smk_import_entry(rule, 0);
885 [ # # ]: 0 : if (skp == NULL)
886 : : goto out;
887 : :
888 [ # # ]: 0 : if (format == SMK_FIXED24_FMT)
889 : 0 : rule += SMK_LABELLEN;
890 : : else
891 : 0 : rule += strlen(skp->smk_known) + 1;
892 : :
893 : 0 : ret = sscanf(rule, "%d", &maplevel);
894 [ # # ][ # # ]: 0 : if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL)
895 : : goto out;
896 : :
897 : 0 : rule += SMK_DIGITLEN;
898 : 0 : ret = sscanf(rule, "%d", &catlen);
899 [ # # ][ # # ]: 0 : if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM)
900 : : goto out;
901 : :
902 [ # # ][ # # ]: 0 : if (format == SMK_FIXED24_FMT &&
903 : 0 : count != (SMK_CIPSOMIN + catlen * SMK_DIGITLEN))
904 : : goto out;
905 : :
906 : 0 : memset(mapcatset, 0, sizeof(mapcatset));
907 : :
908 [ # # ]: 0 : for (i = 0; i < catlen; i++) {
909 : 0 : rule += SMK_DIGITLEN;
910 : 0 : ret = sscanf(rule, "%u", &cat);
911 [ # # ][ # # ]: 0 : if (ret != 1 || cat > SMACK_CIPSO_MAXCATNUM)
912 : : goto out;
913 : :
914 : : smack_catset_bit(cat, mapcatset);
915 : : }
916 : :
917 : 0 : rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN);
918 [ # # ]: 0 : if (rc >= 0) {
919 : 0 : netlbl_secattr_catmap_free(skp->smk_netlabel.attr.mls.cat);
920 : 0 : skp->smk_netlabel.attr.mls.cat = ncats.attr.mls.cat;
921 : 0 : skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl;
922 : 0 : rc = count;
923 : : }
924 : :
925 : : out:
926 : 0 : mutex_unlock(&smack_cipso_lock);
927 : : unlockedout:
928 : 0 : kfree(data);
929 : : return rc;
930 : : }
931 : :
932 : : /**
933 : : * smk_write_cipso - write() for /smack/cipso
934 : : * @file: file pointer, not actually used
935 : : * @buf: where to get the data from
936 : : * @count: bytes sent
937 : : * @ppos: where to start
938 : : *
939 : : * Accepts only one cipso rule per write call.
940 : : * Returns number of bytes written or error code, as appropriate
941 : : */
942 : 0 : static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
943 : : size_t count, loff_t *ppos)
944 : : {
945 : 0 : return smk_set_cipso(file, buf, count, ppos, SMK_FIXED24_FMT);
946 : : }
947 : :
948 : : static const struct file_operations smk_cipso_ops = {
949 : : .open = smk_open_cipso,
950 : : .read = seq_read,
951 : : .llseek = seq_lseek,
952 : : .write = smk_write_cipso,
953 : : .release = seq_release,
954 : : };
955 : :
956 : : /*
957 : : * Seq_file read operations for /smack/cipso2
958 : : */
959 : :
960 : : /*
961 : : * Print cipso labels in format:
962 : : * label level[/cat[,cat]]
963 : : */
964 : 0 : static int cipso2_seq_show(struct seq_file *s, void *v)
965 : : {
966 : : struct list_head *list = v;
967 : : struct smack_known *skp =
968 : : list_entry(list, struct smack_known, list);
969 : 0 : struct netlbl_lsm_secattr_catmap *cmp = skp->smk_netlabel.attr.mls.cat;
970 : : char sep = '/';
971 : : int i;
972 : :
973 : 0 : seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl);
974 : :
975 [ # # ]: 0 : for (i = netlbl_secattr_catmap_walk(cmp, 0); i >= 0;
976 : 0 : i = netlbl_secattr_catmap_walk(cmp, i + 1)) {
977 : 0 : seq_printf(s, "%c%d", sep, i);
978 : : sep = ',';
979 : : }
980 : :
981 : 0 : seq_putc(s, '\n');
982 : :
983 : 0 : return 0;
984 : : }
985 : :
986 : : static const struct seq_operations cipso2_seq_ops = {
987 : : .start = cipso_seq_start,
988 : : .next = cipso_seq_next,
989 : : .show = cipso2_seq_show,
990 : : .stop = smk_seq_stop,
991 : : };
992 : :
993 : : /**
994 : : * smk_open_cipso2 - open() for /smack/cipso2
995 : : * @inode: inode structure representing file
996 : : * @file: "cipso2" file pointer
997 : : *
998 : : * Connect our cipso_seq_* operations with /smack/cipso2
999 : : * file_operations
1000 : : */
1001 : 0 : static int smk_open_cipso2(struct inode *inode, struct file *file)
1002 : : {
1003 : 0 : return seq_open(file, &cipso2_seq_ops);
1004 : : }
1005 : :
1006 : : /**
1007 : : * smk_write_cipso2 - write() for /smack/cipso2
1008 : : * @file: file pointer, not actually used
1009 : : * @buf: where to get the data from
1010 : : * @count: bytes sent
1011 : : * @ppos: where to start
1012 : : *
1013 : : * Accepts only one cipso rule per write call.
1014 : : * Returns number of bytes written or error code, as appropriate
1015 : : */
1016 : 0 : static ssize_t smk_write_cipso2(struct file *file, const char __user *buf,
1017 : : size_t count, loff_t *ppos)
1018 : : {
1019 : 0 : return smk_set_cipso(file, buf, count, ppos, SMK_LONG_FMT);
1020 : : }
1021 : :
1022 : : static const struct file_operations smk_cipso2_ops = {
1023 : : .open = smk_open_cipso2,
1024 : : .read = seq_read,
1025 : : .llseek = seq_lseek,
1026 : : .write = smk_write_cipso2,
1027 : : .release = seq_release,
1028 : : };
1029 : :
1030 : : /*
1031 : : * Seq_file read operations for /smack/netlabel
1032 : : */
1033 : :
1034 : 0 : static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos)
1035 : : {
1036 : 0 : return smk_seq_start(s, pos, &smk_netlbladdr_list);
1037 : : }
1038 : :
1039 : 0 : static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
1040 : : {
1041 : 0 : return smk_seq_next(s, v, pos, &smk_netlbladdr_list);
1042 : : }
1043 : : #define BEBITS (sizeof(__be32) * 8)
1044 : :
1045 : : /*
1046 : : * Print host/label pairs
1047 : : */
1048 : 0 : static int netlbladdr_seq_show(struct seq_file *s, void *v)
1049 : : {
1050 : : struct list_head *list = v;
1051 : : struct smk_netlbladdr *skp =
1052 : : list_entry(list, struct smk_netlbladdr, list);
1053 : : unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
1054 : : int maskn;
1055 [ # # ]: 0 : u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr);
1056 : :
1057 [ # # ]: 0 : for (maskn = 0; temp_mask; temp_mask <<= 1, maskn++);
1058 : :
1059 : 0 : seq_printf(s, "%u.%u.%u.%u/%d %s\n",
1060 : 0 : hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label);
1061 : :
1062 : 0 : return 0;
1063 : : }
1064 : :
1065 : : static const struct seq_operations netlbladdr_seq_ops = {
1066 : : .start = netlbladdr_seq_start,
1067 : : .next = netlbladdr_seq_next,
1068 : : .show = netlbladdr_seq_show,
1069 : : .stop = smk_seq_stop,
1070 : : };
1071 : :
1072 : : /**
1073 : : * smk_open_netlbladdr - open() for /smack/netlabel
1074 : : * @inode: inode structure representing file
1075 : : * @file: "netlabel" file pointer
1076 : : *
1077 : : * Connect our netlbladdr_seq_* operations with /smack/netlabel
1078 : : * file_operations
1079 : : */
1080 : 0 : static int smk_open_netlbladdr(struct inode *inode, struct file *file)
1081 : : {
1082 : 0 : return seq_open(file, &netlbladdr_seq_ops);
1083 : : }
1084 : :
1085 : : /**
1086 : : * smk_netlbladdr_insert
1087 : : * @new : netlabel to insert
1088 : : *
1089 : : * This helper insert netlabel in the smack_netlbladdrs list
1090 : : * sorted by netmask length (longest to smallest)
1091 : : * locked by &smk_netlbladdr_lock in smk_write_netlbladdr
1092 : : *
1093 : : */
1094 : 0 : static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
1095 : : {
1096 : : struct smk_netlbladdr *m, *m_next;
1097 : :
1098 [ # # ]: 0 : if (list_empty(&smk_netlbladdr_list)) {
1099 : 0 : list_add_rcu(&new->list, &smk_netlbladdr_list);
1100 : : return;
1101 : : }
1102 : :
1103 : 0 : m = list_entry_rcu(smk_netlbladdr_list.next,
1104 : : struct smk_netlbladdr, list);
1105 : :
1106 : : /* the comparison '>' is a bit hacky, but works */
1107 [ # # ]: 0 : if (new->smk_mask.s_addr > m->smk_mask.s_addr) {
1108 : 0 : list_add_rcu(&new->list, &smk_netlbladdr_list);
1109 : : return;
1110 : : }
1111 : :
1112 [ # # ]: 0 : list_for_each_entry_rcu(m, &smk_netlbladdr_list, list) {
1113 [ # # ]: 0 : if (list_is_last(&m->list, &smk_netlbladdr_list)) {
1114 : 0 : list_add_rcu(&new->list, &m->list);
1115 : : return;
1116 : : }
1117 : 0 : m_next = list_entry_rcu(m->list.next,
1118 : : struct smk_netlbladdr, list);
1119 [ # # ]: 0 : if (new->smk_mask.s_addr > m_next->smk_mask.s_addr) {
1120 : 0 : list_add_rcu(&new->list, &m->list);
1121 : : return;
1122 : : }
1123 : : }
1124 : : }
1125 : :
1126 : :
1127 : : /**
1128 : : * smk_write_netlbladdr - write() for /smack/netlabel
1129 : : * @file: file pointer, not actually used
1130 : : * @buf: where to get the data from
1131 : : * @count: bytes sent
1132 : : * @ppos: where to start
1133 : : *
1134 : : * Accepts only one netlbladdr per write call.
1135 : : * Returns number of bytes written or error code, as appropriate
1136 : : */
1137 : 0 : static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
1138 : : size_t count, loff_t *ppos)
1139 : : {
1140 : : struct smk_netlbladdr *skp;
1141 : : struct sockaddr_in newname;
1142 : : char *smack;
1143 : : char *sp;
1144 : : char *data;
1145 : : char *host = (char *)&newname.sin_addr.s_addr;
1146 : : int rc;
1147 : : struct netlbl_audit audit_info;
1148 : : struct in_addr mask;
1149 : : unsigned int m;
1150 : : int found;
1151 : : u32 mask_bits = (1<<31);
1152 : : __be32 nsa;
1153 : : u32 temp_mask;
1154 : :
1155 : : /*
1156 : : * Must have privilege.
1157 : : * No partial writes.
1158 : : * Enough data must be present.
1159 : : * "<addr/mask, as a.b.c.d/e><space><label>"
1160 : : * "<addr, as a.b.c.d><space><label>"
1161 : : */
1162 [ # # ]: 0 : if (!smack_privileged(CAP_MAC_ADMIN))
1163 : : return -EPERM;
1164 [ # # ]: 0 : if (*ppos != 0)
1165 : : return -EINVAL;
1166 [ # # ]: 0 : if (count < SMK_NETLBLADDRMIN)
1167 : : return -EINVAL;
1168 : :
1169 : 0 : data = kzalloc(count + 1, GFP_KERNEL);
1170 [ # # ]: 0 : if (data == NULL)
1171 : : return -ENOMEM;
1172 : :
1173 [ # # ]: 0 : if (copy_from_user(data, buf, count) != 0) {
1174 : : rc = -EFAULT;
1175 : : goto free_data_out;
1176 : : }
1177 : :
1178 : : smack = kzalloc(count + 1, GFP_KERNEL);
1179 [ # # ]: 0 : if (smack == NULL) {
1180 : : rc = -ENOMEM;
1181 : : goto free_data_out;
1182 : : }
1183 : :
1184 : 0 : data[count] = '\0';
1185 : :
1186 : 0 : rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%d %s",
1187 : : &host[0], &host[1], &host[2], &host[3], &m, smack);
1188 [ # # ]: 0 : if (rc != 6) {
1189 : 0 : rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s",
1190 : : &host[0], &host[1], &host[2], &host[3], smack);
1191 [ # # ]: 0 : if (rc != 5) {
1192 : : rc = -EINVAL;
1193 : : goto free_out;
1194 : : }
1195 : 0 : m = BEBITS;
1196 : : }
1197 [ # # ]: 0 : if (m > BEBITS) {
1198 : : rc = -EINVAL;
1199 : : goto free_out;
1200 : : }
1201 : :
1202 : : /*
1203 : : * If smack begins with '-', it is an option, don't import it
1204 : : */
1205 [ # # ]: 0 : if (smack[0] != '-') {
1206 : 0 : sp = smk_import(smack, 0);
1207 [ # # ]: 0 : if (sp == NULL) {
1208 : : rc = -EINVAL;
1209 : : goto free_out;
1210 : : }
1211 : : } else {
1212 : : /* check known options */
1213 [ # # ]: 0 : if (strcmp(smack, smack_cipso_option) == 0)
1214 : : sp = (char *)smack_cipso_option;
1215 : : else {
1216 : : rc = -EINVAL;
1217 : : goto free_out;
1218 : : }
1219 : : }
1220 : :
1221 [ # # ]: 0 : for (temp_mask = 0; m > 0; m--) {
1222 : 0 : temp_mask |= mask_bits;
1223 : 0 : mask_bits >>= 1;
1224 : : }
1225 [ # # ]: 0 : mask.s_addr = cpu_to_be32(temp_mask);
1226 : :
1227 : 0 : newname.sin_addr.s_addr &= mask.s_addr;
1228 : : /*
1229 : : * Only allow one writer at a time. Writes should be
1230 : : * quite rare and small in any case.
1231 : : */
1232 : 0 : mutex_lock(&smk_netlbladdr_lock);
1233 : :
1234 : 0 : nsa = newname.sin_addr.s_addr;
1235 : : /* try to find if the prefix is already in the list */
1236 : : found = 0;
1237 [ # # ]: 0 : list_for_each_entry_rcu(skp, &smk_netlbladdr_list, list) {
1238 [ # # ][ # # ]: 0 : if (skp->smk_host.sin_addr.s_addr == nsa &&
1239 : 0 : skp->smk_mask.s_addr == mask.s_addr) {
1240 : : found = 1;
1241 : : break;
1242 : : }
1243 : : }
1244 : : smk_netlabel_audit_set(&audit_info);
1245 : :
1246 [ # # ]: 0 : if (found == 0) {
1247 : : skp = kzalloc(sizeof(*skp), GFP_KERNEL);
1248 [ # # ]: 0 : if (skp == NULL)
1249 : : rc = -ENOMEM;
1250 : : else {
1251 : : rc = 0;
1252 : 0 : skp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr;
1253 : 0 : skp->smk_mask.s_addr = mask.s_addr;
1254 : 0 : skp->smk_label = sp;
1255 : 0 : smk_netlbladdr_insert(skp);
1256 : : }
1257 : : } else {
1258 : : /* we delete the unlabeled entry, only if the previous label
1259 : : * wasn't the special CIPSO option */
1260 [ # # ]: 0 : if (skp->smk_label != smack_cipso_option)
1261 : 0 : rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
1262 : 0 : &skp->smk_host.sin_addr, &skp->smk_mask,
1263 : : PF_INET, &audit_info);
1264 : : else
1265 : : rc = 0;
1266 : 0 : skp->smk_label = sp;
1267 : : }
1268 : :
1269 : : /*
1270 : : * Now tell netlabel about the single label nature of
1271 : : * this host so that incoming packets get labeled.
1272 : : * but only if we didn't get the special CIPSO option
1273 : : */
1274 [ # # ][ # # ]: 0 : if (rc == 0 && sp != smack_cipso_option)
1275 : 0 : rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
1276 : 0 : &skp->smk_host.sin_addr, &skp->smk_mask, PF_INET,
1277 : 0 : smack_to_secid(skp->smk_label), &audit_info);
1278 : :
1279 [ # # ]: 0 : if (rc == 0)
1280 : 0 : rc = count;
1281 : :
1282 : 0 : mutex_unlock(&smk_netlbladdr_lock);
1283 : :
1284 : : free_out:
1285 : 0 : kfree(smack);
1286 : : free_data_out:
1287 : 0 : kfree(data);
1288 : :
1289 : 0 : return rc;
1290 : : }
1291 : :
1292 : : static const struct file_operations smk_netlbladdr_ops = {
1293 : : .open = smk_open_netlbladdr,
1294 : : .read = seq_read,
1295 : : .llseek = seq_lseek,
1296 : : .write = smk_write_netlbladdr,
1297 : : .release = seq_release,
1298 : : };
1299 : :
1300 : : /**
1301 : : * smk_read_doi - read() for /smack/doi
1302 : : * @filp: file pointer, not actually used
1303 : : * @buf: where to put the result
1304 : : * @count: maximum to send along
1305 : : * @ppos: where to start
1306 : : *
1307 : : * Returns number of bytes read or error code, as appropriate
1308 : : */
1309 : 0 : static ssize_t smk_read_doi(struct file *filp, char __user *buf,
1310 : : size_t count, loff_t *ppos)
1311 : : {
1312 : : char temp[80];
1313 : : ssize_t rc;
1314 : :
1315 [ # # ]: 0 : if (*ppos != 0)
1316 : : return 0;
1317 : :
1318 : 0 : sprintf(temp, "%d", smk_cipso_doi_value);
1319 : 0 : rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
1320 : :
1321 : 0 : return rc;
1322 : : }
1323 : :
1324 : : /**
1325 : : * smk_write_doi - write() for /smack/doi
1326 : : * @file: file pointer, not actually used
1327 : : * @buf: where to get the data from
1328 : : * @count: bytes sent
1329 : : * @ppos: where to start
1330 : : *
1331 : : * Returns number of bytes written or error code, as appropriate
1332 : : */
1333 : 0 : static ssize_t smk_write_doi(struct file *file, const char __user *buf,
1334 : : size_t count, loff_t *ppos)
1335 : : {
1336 : : char temp[80];
1337 : : int i;
1338 : :
1339 [ # # ]: 0 : if (!smack_privileged(CAP_MAC_ADMIN))
1340 : : return -EPERM;
1341 : :
1342 [ # # ]: 0 : if (count >= sizeof(temp) || count == 0)
1343 : : return -EINVAL;
1344 : :
1345 [ # # ]: 0 : if (copy_from_user(temp, buf, count) != 0)
1346 : : return -EFAULT;
1347 : :
1348 : 0 : temp[count] = '\0';
1349 : :
1350 [ # # ]: 0 : if (sscanf(temp, "%d", &i) != 1)
1351 : : return -EINVAL;
1352 : :
1353 : 0 : smk_cipso_doi_value = i;
1354 : :
1355 : 0 : smk_cipso_doi();
1356 : :
1357 : 0 : return count;
1358 : : }
1359 : :
1360 : : static const struct file_operations smk_doi_ops = {
1361 : : .read = smk_read_doi,
1362 : : .write = smk_write_doi,
1363 : : .llseek = default_llseek,
1364 : : };
1365 : :
1366 : : /**
1367 : : * smk_read_direct - read() for /smack/direct
1368 : : * @filp: file pointer, not actually used
1369 : : * @buf: where to put the result
1370 : : * @count: maximum to send along
1371 : : * @ppos: where to start
1372 : : *
1373 : : * Returns number of bytes read or error code, as appropriate
1374 : : */
1375 : 0 : static ssize_t smk_read_direct(struct file *filp, char __user *buf,
1376 : : size_t count, loff_t *ppos)
1377 : : {
1378 : : char temp[80];
1379 : : ssize_t rc;
1380 : :
1381 [ # # ]: 0 : if (*ppos != 0)
1382 : : return 0;
1383 : :
1384 : 0 : sprintf(temp, "%d", smack_cipso_direct);
1385 : 0 : rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
1386 : :
1387 : 0 : return rc;
1388 : : }
1389 : :
1390 : : /**
1391 : : * smk_write_direct - write() for /smack/direct
1392 : : * @file: file pointer, not actually used
1393 : : * @buf: where to get the data from
1394 : : * @count: bytes sent
1395 : : * @ppos: where to start
1396 : : *
1397 : : * Returns number of bytes written or error code, as appropriate
1398 : : */
1399 : 0 : static ssize_t smk_write_direct(struct file *file, const char __user *buf,
1400 : : size_t count, loff_t *ppos)
1401 : : {
1402 : : struct smack_known *skp;
1403 : : char temp[80];
1404 : : int i;
1405 : :
1406 [ # # ]: 0 : if (!smack_privileged(CAP_MAC_ADMIN))
1407 : : return -EPERM;
1408 : :
1409 [ # # ]: 0 : if (count >= sizeof(temp) || count == 0)
1410 : : return -EINVAL;
1411 : :
1412 [ # # ]: 0 : if (copy_from_user(temp, buf, count) != 0)
1413 : : return -EFAULT;
1414 : :
1415 : 0 : temp[count] = '\0';
1416 : :
1417 [ # # ]: 0 : if (sscanf(temp, "%d", &i) != 1)
1418 : : return -EINVAL;
1419 : :
1420 : : /*
1421 : : * Don't do anything if the value hasn't actually changed.
1422 : : * If it is changing reset the level on entries that were
1423 : : * set up to be direct when they were created.
1424 : : */
1425 [ # # ]: 0 : if (smack_cipso_direct != i) {
1426 : 0 : mutex_lock(&smack_known_lock);
1427 [ # # ]: 0 : list_for_each_entry_rcu(skp, &smack_known_list, list)
1428 [ # # ]: 0 : if (skp->smk_netlabel.attr.mls.lvl ==
1429 : : smack_cipso_direct)
1430 : 0 : skp->smk_netlabel.attr.mls.lvl = i;
1431 : 0 : smack_cipso_direct = i;
1432 : 0 : mutex_unlock(&smack_known_lock);
1433 : : }
1434 : :
1435 : 0 : return count;
1436 : : }
1437 : :
1438 : : static const struct file_operations smk_direct_ops = {
1439 : : .read = smk_read_direct,
1440 : : .write = smk_write_direct,
1441 : : .llseek = default_llseek,
1442 : : };
1443 : :
1444 : : /**
1445 : : * smk_read_mapped - read() for /smack/mapped
1446 : : * @filp: file pointer, not actually used
1447 : : * @buf: where to put the result
1448 : : * @count: maximum to send along
1449 : : * @ppos: where to start
1450 : : *
1451 : : * Returns number of bytes read or error code, as appropriate
1452 : : */
1453 : 0 : static ssize_t smk_read_mapped(struct file *filp, char __user *buf,
1454 : : size_t count, loff_t *ppos)
1455 : : {
1456 : : char temp[80];
1457 : : ssize_t rc;
1458 : :
1459 [ # # ]: 0 : if (*ppos != 0)
1460 : : return 0;
1461 : :
1462 : 0 : sprintf(temp, "%d", smack_cipso_mapped);
1463 : 0 : rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
1464 : :
1465 : 0 : return rc;
1466 : : }
1467 : :
1468 : : /**
1469 : : * smk_write_mapped - write() for /smack/mapped
1470 : : * @file: file pointer, not actually used
1471 : : * @buf: where to get the data from
1472 : : * @count: bytes sent
1473 : : * @ppos: where to start
1474 : : *
1475 : : * Returns number of bytes written or error code, as appropriate
1476 : : */
1477 : 0 : static ssize_t smk_write_mapped(struct file *file, const char __user *buf,
1478 : : size_t count, loff_t *ppos)
1479 : : {
1480 : : struct smack_known *skp;
1481 : : char temp[80];
1482 : : int i;
1483 : :
1484 [ # # ]: 0 : if (!smack_privileged(CAP_MAC_ADMIN))
1485 : : return -EPERM;
1486 : :
1487 [ # # ]: 0 : if (count >= sizeof(temp) || count == 0)
1488 : : return -EINVAL;
1489 : :
1490 [ # # ]: 0 : if (copy_from_user(temp, buf, count) != 0)
1491 : : return -EFAULT;
1492 : :
1493 : 0 : temp[count] = '\0';
1494 : :
1495 [ # # ]: 0 : if (sscanf(temp, "%d", &i) != 1)
1496 : : return -EINVAL;
1497 : :
1498 : : /*
1499 : : * Don't do anything if the value hasn't actually changed.
1500 : : * If it is changing reset the level on entries that were
1501 : : * set up to be mapped when they were created.
1502 : : */
1503 [ # # ]: 0 : if (smack_cipso_mapped != i) {
1504 : 0 : mutex_lock(&smack_known_lock);
1505 [ # # ]: 0 : list_for_each_entry_rcu(skp, &smack_known_list, list)
1506 [ # # ]: 0 : if (skp->smk_netlabel.attr.mls.lvl ==
1507 : : smack_cipso_mapped)
1508 : 0 : skp->smk_netlabel.attr.mls.lvl = i;
1509 : 0 : smack_cipso_mapped = i;
1510 : 0 : mutex_unlock(&smack_known_lock);
1511 : : }
1512 : :
1513 : 0 : return count;
1514 : : }
1515 : :
1516 : : static const struct file_operations smk_mapped_ops = {
1517 : : .read = smk_read_mapped,
1518 : : .write = smk_write_mapped,
1519 : : .llseek = default_llseek,
1520 : : };
1521 : :
1522 : : /**
1523 : : * smk_read_ambient - read() for /smack/ambient
1524 : : * @filp: file pointer, not actually used
1525 : : * @buf: where to put the result
1526 : : * @cn: maximum to send along
1527 : : * @ppos: where to start
1528 : : *
1529 : : * Returns number of bytes read or error code, as appropriate
1530 : : */
1531 : 0 : static ssize_t smk_read_ambient(struct file *filp, char __user *buf,
1532 : : size_t cn, loff_t *ppos)
1533 : : {
1534 : : ssize_t rc;
1535 : : int asize;
1536 : :
1537 [ # # ]: 0 : if (*ppos != 0)
1538 : : return 0;
1539 : : /*
1540 : : * Being careful to avoid a problem in the case where
1541 : : * smack_net_ambient gets changed in midstream.
1542 : : */
1543 : 0 : mutex_lock(&smack_ambient_lock);
1544 : :
1545 : 0 : asize = strlen(smack_net_ambient->smk_known) + 1;
1546 : :
1547 [ # # ]: 0 : if (cn >= asize)
1548 : 0 : rc = simple_read_from_buffer(buf, cn, ppos,
1549 : : smack_net_ambient->smk_known,
1550 : : asize);
1551 : : else
1552 : : rc = -EINVAL;
1553 : :
1554 : 0 : mutex_unlock(&smack_ambient_lock);
1555 : :
1556 : 0 : return rc;
1557 : : }
1558 : :
1559 : : /**
1560 : : * smk_write_ambient - write() for /smack/ambient
1561 : : * @file: file pointer, not actually used
1562 : : * @buf: where to get the data from
1563 : : * @count: bytes sent
1564 : : * @ppos: where to start
1565 : : *
1566 : : * Returns number of bytes written or error code, as appropriate
1567 : : */
1568 : 0 : static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
1569 : : size_t count, loff_t *ppos)
1570 : : {
1571 : : struct smack_known *skp;
1572 : : char *oldambient;
1573 : : char *data;
1574 : 0 : int rc = count;
1575 : :
1576 [ # # ]: 0 : if (!smack_privileged(CAP_MAC_ADMIN))
1577 : : return -EPERM;
1578 : :
1579 : 0 : data = kzalloc(count + 1, GFP_KERNEL);
1580 [ # # ]: 0 : if (data == NULL)
1581 : : return -ENOMEM;
1582 : :
1583 [ # # ]: 0 : if (copy_from_user(data, buf, count) != 0) {
1584 : : rc = -EFAULT;
1585 : : goto out;
1586 : : }
1587 : :
1588 : 0 : skp = smk_import_entry(data, count);
1589 [ # # ]: 0 : if (skp == NULL) {
1590 : : rc = -EINVAL;
1591 : : goto out;
1592 : : }
1593 : :
1594 : 0 : mutex_lock(&smack_ambient_lock);
1595 : :
1596 : 0 : oldambient = smack_net_ambient->smk_known;
1597 : 0 : smack_net_ambient = skp;
1598 : 0 : smk_unlbl_ambient(oldambient);
1599 : :
1600 : 0 : mutex_unlock(&smack_ambient_lock);
1601 : :
1602 : : out:
1603 : 0 : kfree(data);
1604 : 0 : return rc;
1605 : : }
1606 : :
1607 : : static const struct file_operations smk_ambient_ops = {
1608 : : .read = smk_read_ambient,
1609 : : .write = smk_write_ambient,
1610 : : .llseek = default_llseek,
1611 : : };
1612 : :
1613 : : /**
1614 : : * smk_read_onlycap - read() for smackfs/onlycap
1615 : : * @filp: file pointer, not actually used
1616 : : * @buf: where to put the result
1617 : : * @cn: maximum to send along
1618 : : * @ppos: where to start
1619 : : *
1620 : : * Returns number of bytes read or error code, as appropriate
1621 : : */
1622 : 0 : static ssize_t smk_read_onlycap(struct file *filp, char __user *buf,
1623 : : size_t cn, loff_t *ppos)
1624 : : {
1625 : : char *smack = "";
1626 : : ssize_t rc = -EINVAL;
1627 : : int asize;
1628 : :
1629 [ # # ]: 0 : if (*ppos != 0)
1630 : : return 0;
1631 : :
1632 [ # # ]: 0 : if (smack_onlycap != NULL)
1633 : 0 : smack = smack_onlycap->smk_known;
1634 : :
1635 : 0 : asize = strlen(smack) + 1;
1636 : :
1637 [ # # ]: 0 : if (cn >= asize)
1638 : 0 : rc = simple_read_from_buffer(buf, cn, ppos, smack, asize);
1639 : :
1640 : 0 : return rc;
1641 : : }
1642 : :
1643 : : /**
1644 : : * smk_write_onlycap - write() for smackfs/onlycap
1645 : : * @file: file pointer, not actually used
1646 : : * @buf: where to get the data from
1647 : : * @count: bytes sent
1648 : : * @ppos: where to start
1649 : : *
1650 : : * Returns number of bytes written or error code, as appropriate
1651 : : */
1652 : 0 : static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
1653 : : size_t count, loff_t *ppos)
1654 : : {
1655 : : char *data;
1656 : 0 : struct smack_known *skp = smk_of_task(current->cred->security);
1657 : 0 : int rc = count;
1658 : :
1659 [ # # ]: 0 : if (!smack_privileged(CAP_MAC_ADMIN))
1660 : : return -EPERM;
1661 : :
1662 : : /*
1663 : : * This can be done using smk_access() but is done
1664 : : * explicitly for clarity. The smk_access() implementation
1665 : : * would use smk_access(smack_onlycap, MAY_WRITE)
1666 : : */
1667 [ # # ][ # # ]: 0 : if (smack_onlycap != NULL && smack_onlycap != skp)
1668 : : return -EPERM;
1669 : :
1670 : : data = kzalloc(count, GFP_KERNEL);
1671 [ # # ]: 0 : if (data == NULL)
1672 : : return -ENOMEM;
1673 : :
1674 : : /*
1675 : : * Should the null string be passed in unset the onlycap value.
1676 : : * This seems like something to be careful with as usually
1677 : : * smk_import only expects to return NULL for errors. It
1678 : : * is usually the case that a nullstring or "\n" would be
1679 : : * bad to pass to smk_import but in fact this is useful here.
1680 : : *
1681 : : * smk_import will also reject a label beginning with '-',
1682 : : * so "-usecapabilities" will also work.
1683 : : */
1684 [ # # ]: 0 : if (copy_from_user(data, buf, count) != 0)
1685 : : rc = -EFAULT;
1686 : : else
1687 : 0 : smack_onlycap = smk_import_entry(data, count);
1688 : :
1689 : 0 : kfree(data);
1690 : 0 : return rc;
1691 : : }
1692 : :
1693 : : static const struct file_operations smk_onlycap_ops = {
1694 : : .read = smk_read_onlycap,
1695 : : .write = smk_write_onlycap,
1696 : : .llseek = default_llseek,
1697 : : };
1698 : :
1699 : : /**
1700 : : * smk_read_logging - read() for /smack/logging
1701 : : * @filp: file pointer, not actually used
1702 : : * @buf: where to put the result
1703 : : * @cn: maximum to send along
1704 : : * @ppos: where to start
1705 : : *
1706 : : * Returns number of bytes read or error code, as appropriate
1707 : : */
1708 : 0 : static ssize_t smk_read_logging(struct file *filp, char __user *buf,
1709 : : size_t count, loff_t *ppos)
1710 : : {
1711 : : char temp[32];
1712 : : ssize_t rc;
1713 : :
1714 [ # # ]: 0 : if (*ppos != 0)
1715 : : return 0;
1716 : :
1717 : 0 : sprintf(temp, "%d\n", log_policy);
1718 : 0 : rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
1719 : 0 : return rc;
1720 : : }
1721 : :
1722 : : /**
1723 : : * smk_write_logging - write() for /smack/logging
1724 : : * @file: file pointer, not actually used
1725 : : * @buf: where to get the data from
1726 : : * @count: bytes sent
1727 : : * @ppos: where to start
1728 : : *
1729 : : * Returns number of bytes written or error code, as appropriate
1730 : : */
1731 : 0 : static ssize_t smk_write_logging(struct file *file, const char __user *buf,
1732 : : size_t count, loff_t *ppos)
1733 : : {
1734 : : char temp[32];
1735 : : int i;
1736 : :
1737 [ # # ]: 0 : if (!smack_privileged(CAP_MAC_ADMIN))
1738 : : return -EPERM;
1739 : :
1740 [ # # ]: 0 : if (count >= sizeof(temp) || count == 0)
1741 : : return -EINVAL;
1742 : :
1743 [ # # ]: 0 : if (copy_from_user(temp, buf, count) != 0)
1744 : : return -EFAULT;
1745 : :
1746 : 0 : temp[count] = '\0';
1747 : :
1748 [ # # ]: 0 : if (sscanf(temp, "%d", &i) != 1)
1749 : : return -EINVAL;
1750 [ # # ]: 0 : if (i < 0 || i > 3)
1751 : : return -EINVAL;
1752 : 0 : log_policy = i;
1753 : 0 : return count;
1754 : : }
1755 : :
1756 : :
1757 : :
1758 : : static const struct file_operations smk_logging_ops = {
1759 : : .read = smk_read_logging,
1760 : : .write = smk_write_logging,
1761 : : .llseek = default_llseek,
1762 : : };
1763 : :
1764 : : /*
1765 : : * Seq_file read operations for /smack/load-self
1766 : : */
1767 : :
1768 : 0 : static void *load_self_seq_start(struct seq_file *s, loff_t *pos)
1769 : : {
1770 : 0 : struct task_smack *tsp = current_security();
1771 : :
1772 : 0 : return smk_seq_start(s, pos, &tsp->smk_rules);
1773 : : }
1774 : :
1775 : 0 : static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos)
1776 : : {
1777 : 0 : struct task_smack *tsp = current_security();
1778 : :
1779 : 0 : return smk_seq_next(s, v, pos, &tsp->smk_rules);
1780 : : }
1781 : :
1782 : 0 : static int load_self_seq_show(struct seq_file *s, void *v)
1783 : : {
1784 : : struct list_head *list = v;
1785 : : struct smack_rule *srp =
1786 : : list_entry(list, struct smack_rule, list);
1787 : :
1788 : 0 : smk_rule_show(s, srp, SMK_LABELLEN);
1789 : :
1790 : 0 : return 0;
1791 : : }
1792 : :
1793 : : static const struct seq_operations load_self_seq_ops = {
1794 : : .start = load_self_seq_start,
1795 : : .next = load_self_seq_next,
1796 : : .show = load_self_seq_show,
1797 : : .stop = smk_seq_stop,
1798 : : };
1799 : :
1800 : :
1801 : : /**
1802 : : * smk_open_load_self - open() for /smack/load-self2
1803 : : * @inode: inode structure representing file
1804 : : * @file: "load" file pointer
1805 : : *
1806 : : * For reading, use load_seq_* seq_file reading operations.
1807 : : */
1808 : 0 : static int smk_open_load_self(struct inode *inode, struct file *file)
1809 : : {
1810 : 0 : return seq_open(file, &load_self_seq_ops);
1811 : : }
1812 : :
1813 : : /**
1814 : : * smk_write_load_self - write() for /smack/load-self
1815 : : * @file: file pointer, not actually used
1816 : : * @buf: where to get the data from
1817 : : * @count: bytes sent
1818 : : * @ppos: where to start - must be 0
1819 : : *
1820 : : */
1821 : 0 : static ssize_t smk_write_load_self(struct file *file, const char __user *buf,
1822 : 0 : size_t count, loff_t *ppos)
1823 : : {
1824 : 0 : struct task_smack *tsp = current_security();
1825 : :
1826 : 0 : return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules,
1827 : : &tsp->smk_rules_lock, SMK_FIXED24_FMT);
1828 : : }
1829 : :
1830 : : static const struct file_operations smk_load_self_ops = {
1831 : : .open = smk_open_load_self,
1832 : : .read = seq_read,
1833 : : .llseek = seq_lseek,
1834 : : .write = smk_write_load_self,
1835 : : .release = seq_release,
1836 : : };
1837 : :
1838 : : /**
1839 : : * smk_user_access - handle access check transaction
1840 : : * @file: file pointer
1841 : : * @buf: data from user space
1842 : : * @count: bytes sent
1843 : : * @ppos: where to start - must be 0
1844 : : */
1845 : 0 : static ssize_t smk_user_access(struct file *file, const char __user *buf,
1846 : : size_t count, loff_t *ppos, int format)
1847 : : {
1848 : : struct smack_parsed_rule rule;
1849 : : char *data;
1850 : : int res;
1851 : :
1852 : 0 : data = simple_transaction_get(file, buf, count);
1853 [ # # ]: 0 : if (IS_ERR(data))
1854 : : return PTR_ERR(data);
1855 : :
1856 [ # # ]: 0 : if (format == SMK_FIXED24_FMT) {
1857 [ # # ]: 0 : if (count < SMK_LOADLEN)
1858 : : return -EINVAL;
1859 : 0 : res = smk_parse_rule(data, &rule, 0);
1860 : : } else {
1861 : : /*
1862 : : * simple_transaction_get() returns null-terminated data
1863 : : */
1864 : 0 : res = smk_parse_long_rule(data, &rule, 0, 3);
1865 : : }
1866 : :
1867 [ # # ]: 0 : if (res >= 0)
1868 : 0 : res = smk_access(rule.smk_subject, rule.smk_object,
1869 : : rule.smk_access1, NULL);
1870 [ # # ]: 0 : else if (res != -ENOENT)
1871 : : return -EINVAL;
1872 : :
1873 [ # # ]: 0 : data[0] = res == 0 ? '1' : '0';
1874 : 0 : data[1] = '\0';
1875 : :
1876 : 0 : simple_transaction_set(file, 2);
1877 : :
1878 [ # # ]: 0 : if (format == SMK_FIXED24_FMT)
1879 : : return SMK_LOADLEN;
1880 : 0 : return count;
1881 : : }
1882 : :
1883 : : /**
1884 : : * smk_write_access - handle access check transaction
1885 : : * @file: file pointer
1886 : : * @buf: data from user space
1887 : : * @count: bytes sent
1888 : : * @ppos: where to start - must be 0
1889 : : */
1890 : 0 : static ssize_t smk_write_access(struct file *file, const char __user *buf,
1891 : : size_t count, loff_t *ppos)
1892 : : {
1893 : 0 : return smk_user_access(file, buf, count, ppos, SMK_FIXED24_FMT);
1894 : : }
1895 : :
1896 : : static const struct file_operations smk_access_ops = {
1897 : : .write = smk_write_access,
1898 : : .read = simple_transaction_read,
1899 : : .release = simple_transaction_release,
1900 : : .llseek = generic_file_llseek,
1901 : : };
1902 : :
1903 : :
1904 : : /*
1905 : : * Seq_file read operations for /smack/load2
1906 : : */
1907 : :
1908 : 0 : static int load2_seq_show(struct seq_file *s, void *v)
1909 : : {
1910 : : struct list_head *list = v;
1911 : : struct smack_master_list *smlp =
1912 : : list_entry(list, struct smack_master_list, list);
1913 : :
1914 : 0 : smk_rule_show(s, smlp->smk_rule, SMK_LONGLABEL);
1915 : :
1916 : 0 : return 0;
1917 : : }
1918 : :
1919 : : static const struct seq_operations load2_seq_ops = {
1920 : : .start = load2_seq_start,
1921 : : .next = load2_seq_next,
1922 : : .show = load2_seq_show,
1923 : : .stop = smk_seq_stop,
1924 : : };
1925 : :
1926 : : /**
1927 : : * smk_open_load2 - open() for /smack/load2
1928 : : * @inode: inode structure representing file
1929 : : * @file: "load2" file pointer
1930 : : *
1931 : : * For reading, use load2_seq_* seq_file reading operations.
1932 : : */
1933 : 0 : static int smk_open_load2(struct inode *inode, struct file *file)
1934 : : {
1935 : 0 : return seq_open(file, &load2_seq_ops);
1936 : : }
1937 : :
1938 : : /**
1939 : : * smk_write_load2 - write() for /smack/load2
1940 : : * @file: file pointer, not actually used
1941 : : * @buf: where to get the data from
1942 : : * @count: bytes sent
1943 : : * @ppos: where to start - must be 0
1944 : : *
1945 : : */
1946 : 0 : static ssize_t smk_write_load2(struct file *file, const char __user *buf,
1947 : 0 : size_t count, loff_t *ppos)
1948 : : {
1949 : : /*
1950 : : * Must have privilege.
1951 : : */
1952 [ # # ]: 0 : if (!smack_privileged(CAP_MAC_ADMIN))
1953 : : return -EPERM;
1954 : :
1955 : 0 : return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
1956 : : SMK_LONG_FMT);
1957 : : }
1958 : :
1959 : : static const struct file_operations smk_load2_ops = {
1960 : : .open = smk_open_load2,
1961 : : .read = seq_read,
1962 : : .llseek = seq_lseek,
1963 : : .write = smk_write_load2,
1964 : : .release = seq_release,
1965 : : };
1966 : :
1967 : : /*
1968 : : * Seq_file read operations for /smack/load-self2
1969 : : */
1970 : :
1971 : 0 : static void *load_self2_seq_start(struct seq_file *s, loff_t *pos)
1972 : : {
1973 : 0 : struct task_smack *tsp = current_security();
1974 : :
1975 : 0 : return smk_seq_start(s, pos, &tsp->smk_rules);
1976 : : }
1977 : :
1978 : 0 : static void *load_self2_seq_next(struct seq_file *s, void *v, loff_t *pos)
1979 : : {
1980 : 0 : struct task_smack *tsp = current_security();
1981 : :
1982 : 0 : return smk_seq_next(s, v, pos, &tsp->smk_rules);
1983 : : }
1984 : :
1985 : 0 : static int load_self2_seq_show(struct seq_file *s, void *v)
1986 : : {
1987 : : struct list_head *list = v;
1988 : : struct smack_rule *srp =
1989 : : list_entry(list, struct smack_rule, list);
1990 : :
1991 : 0 : smk_rule_show(s, srp, SMK_LONGLABEL);
1992 : :
1993 : 0 : return 0;
1994 : : }
1995 : :
1996 : : static const struct seq_operations load_self2_seq_ops = {
1997 : : .start = load_self2_seq_start,
1998 : : .next = load_self2_seq_next,
1999 : : .show = load_self2_seq_show,
2000 : : .stop = smk_seq_stop,
2001 : : };
2002 : :
2003 : : /**
2004 : : * smk_open_load_self2 - open() for /smack/load-self2
2005 : : * @inode: inode structure representing file
2006 : : * @file: "load" file pointer
2007 : : *
2008 : : * For reading, use load_seq_* seq_file reading operations.
2009 : : */
2010 : 0 : static int smk_open_load_self2(struct inode *inode, struct file *file)
2011 : : {
2012 : 0 : return seq_open(file, &load_self2_seq_ops);
2013 : : }
2014 : :
2015 : : /**
2016 : : * smk_write_load_self2 - write() for /smack/load-self2
2017 : : * @file: file pointer, not actually used
2018 : : * @buf: where to get the data from
2019 : : * @count: bytes sent
2020 : : * @ppos: where to start - must be 0
2021 : : *
2022 : : */
2023 : 0 : static ssize_t smk_write_load_self2(struct file *file, const char __user *buf,
2024 : 0 : size_t count, loff_t *ppos)
2025 : : {
2026 : 0 : struct task_smack *tsp = current_security();
2027 : :
2028 : 0 : return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules,
2029 : : &tsp->smk_rules_lock, SMK_LONG_FMT);
2030 : : }
2031 : :
2032 : : static const struct file_operations smk_load_self2_ops = {
2033 : : .open = smk_open_load_self2,
2034 : : .read = seq_read,
2035 : : .llseek = seq_lseek,
2036 : : .write = smk_write_load_self2,
2037 : : .release = seq_release,
2038 : : };
2039 : :
2040 : : /**
2041 : : * smk_write_access2 - handle access check transaction
2042 : : * @file: file pointer
2043 : : * @buf: data from user space
2044 : : * @count: bytes sent
2045 : : * @ppos: where to start - must be 0
2046 : : */
2047 : 0 : static ssize_t smk_write_access2(struct file *file, const char __user *buf,
2048 : : size_t count, loff_t *ppos)
2049 : : {
2050 : 0 : return smk_user_access(file, buf, count, ppos, SMK_LONG_FMT);
2051 : : }
2052 : :
2053 : : static const struct file_operations smk_access2_ops = {
2054 : : .write = smk_write_access2,
2055 : : .read = simple_transaction_read,
2056 : : .release = simple_transaction_release,
2057 : : .llseek = generic_file_llseek,
2058 : : };
2059 : :
2060 : : /**
2061 : : * smk_write_revoke_subj - write() for /smack/revoke-subject
2062 : : * @file: file pointer
2063 : : * @buf: data from user space
2064 : : * @count: bytes sent
2065 : : * @ppos: where to start - must be 0
2066 : : */
2067 : 0 : static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf,
2068 : : size_t count, loff_t *ppos)
2069 : : {
2070 : : char *data = NULL;
2071 : : const char *cp = NULL;
2072 : : struct smack_known *skp;
2073 : : struct smack_rule *sp;
2074 : : struct list_head *rule_list;
2075 : : struct mutex *rule_lock;
2076 : 0 : int rc = count;
2077 : :
2078 [ # # ]: 0 : if (*ppos != 0)
2079 : : return -EINVAL;
2080 : :
2081 [ # # ]: 0 : if (!smack_privileged(CAP_MAC_ADMIN))
2082 : : return -EPERM;
2083 : :
2084 [ # # ]: 0 : if (count == 0 || count > SMK_LONGLABEL)
2085 : : return -EINVAL;
2086 : :
2087 : : data = kzalloc(count, GFP_KERNEL);
2088 [ # # ]: 0 : if (data == NULL)
2089 : : return -ENOMEM;
2090 : :
2091 [ # # ]: 0 : if (copy_from_user(data, buf, count) != 0) {
2092 : : rc = -EFAULT;
2093 : : goto free_out;
2094 : : }
2095 : :
2096 : 0 : cp = smk_parse_smack(data, count);
2097 [ # # ]: 0 : if (cp == NULL) {
2098 : : rc = -EINVAL;
2099 : : goto free_out;
2100 : : }
2101 : :
2102 : 0 : skp = smk_find_entry(cp);
2103 [ # # ]: 0 : if (skp == NULL)
2104 : : goto free_out;
2105 : :
2106 : 0 : rule_list = &skp->smk_rules;
2107 : 0 : rule_lock = &skp->smk_rules_lock;
2108 : :
2109 : 0 : mutex_lock(rule_lock);
2110 : :
2111 [ # # ]: 0 : list_for_each_entry_rcu(sp, rule_list, list)
2112 : 0 : sp->smk_access = 0;
2113 : :
2114 : 0 : mutex_unlock(rule_lock);
2115 : :
2116 : : free_out:
2117 : 0 : kfree(data);
2118 : 0 : kfree(cp);
2119 : 0 : return rc;
2120 : : }
2121 : :
2122 : : static const struct file_operations smk_revoke_subj_ops = {
2123 : : .write = smk_write_revoke_subj,
2124 : : .read = simple_transaction_read,
2125 : : .release = simple_transaction_release,
2126 : : .llseek = generic_file_llseek,
2127 : : };
2128 : :
2129 : : static struct kset *smackfs_kset;
2130 : : /**
2131 : : * smk_init_sysfs - initialize /sys/fs/smackfs
2132 : : *
2133 : : */
2134 : 0 : static int smk_init_sysfs(void)
2135 : : {
2136 : 0 : smackfs_kset = kset_create_and_add("smackfs", NULL, fs_kobj);
2137 [ # # ]: 0 : if (!smackfs_kset)
2138 : : return -ENOMEM;
2139 : 0 : return 0;
2140 : : }
2141 : :
2142 : : /**
2143 : : * smk_write_change_rule - write() for /smack/change-rule
2144 : : * @file: file pointer
2145 : : * @buf: data from user space
2146 : : * @count: bytes sent
2147 : : * @ppos: where to start - must be 0
2148 : : */
2149 : 0 : static ssize_t smk_write_change_rule(struct file *file, const char __user *buf,
2150 : 0 : size_t count, loff_t *ppos)
2151 : : {
2152 : : /*
2153 : : * Must have privilege.
2154 : : */
2155 [ # # ]: 0 : if (!smack_privileged(CAP_MAC_ADMIN))
2156 : : return -EPERM;
2157 : :
2158 : 0 : return smk_write_rules_list(file, buf, count, ppos, NULL, NULL,
2159 : : SMK_CHANGE_FMT);
2160 : : }
2161 : :
2162 : : static const struct file_operations smk_change_rule_ops = {
2163 : : .write = smk_write_change_rule,
2164 : : .read = simple_transaction_read,
2165 : : .release = simple_transaction_release,
2166 : : .llseek = generic_file_llseek,
2167 : : };
2168 : :
2169 : : /**
2170 : : * smk_read_syslog - read() for smackfs/syslog
2171 : : * @filp: file pointer, not actually used
2172 : : * @buf: where to put the result
2173 : : * @cn: maximum to send along
2174 : : * @ppos: where to start
2175 : : *
2176 : : * Returns number of bytes read or error code, as appropriate
2177 : : */
2178 : 0 : static ssize_t smk_read_syslog(struct file *filp, char __user *buf,
2179 : : size_t cn, loff_t *ppos)
2180 : : {
2181 : : struct smack_known *skp;
2182 : : ssize_t rc = -EINVAL;
2183 : : int asize;
2184 : :
2185 [ # # ]: 0 : if (*ppos != 0)
2186 : : return 0;
2187 : :
2188 [ # # ]: 0 : if (smack_syslog_label == NULL)
2189 : : skp = &smack_known_star;
2190 : : else
2191 : : skp = smack_syslog_label;
2192 : :
2193 : 0 : asize = strlen(skp->smk_known) + 1;
2194 : :
2195 [ # # ]: 0 : if (cn >= asize)
2196 : 0 : rc = simple_read_from_buffer(buf, cn, ppos, skp->smk_known,
2197 : : asize);
2198 : :
2199 : 0 : return rc;
2200 : : }
2201 : :
2202 : : /**
2203 : : * smk_write_syslog - write() for smackfs/syslog
2204 : : * @file: file pointer, not actually used
2205 : : * @buf: where to get the data from
2206 : : * @count: bytes sent
2207 : : * @ppos: where to start
2208 : : *
2209 : : * Returns number of bytes written or error code, as appropriate
2210 : : */
2211 : 0 : static ssize_t smk_write_syslog(struct file *file, const char __user *buf,
2212 : : size_t count, loff_t *ppos)
2213 : : {
2214 : : char *data;
2215 : : struct smack_known *skp;
2216 : 0 : int rc = count;
2217 : :
2218 [ # # ]: 0 : if (!smack_privileged(CAP_MAC_ADMIN))
2219 : : return -EPERM;
2220 : :
2221 : : data = kzalloc(count, GFP_KERNEL);
2222 [ # # ]: 0 : if (data == NULL)
2223 : : return -ENOMEM;
2224 : :
2225 [ # # ]: 0 : if (copy_from_user(data, buf, count) != 0)
2226 : : rc = -EFAULT;
2227 : : else {
2228 : 0 : skp = smk_import_entry(data, count);
2229 [ # # ]: 0 : if (skp == NULL)
2230 : : rc = -EINVAL;
2231 : : else
2232 : 0 : smack_syslog_label = smk_import_entry(data, count);
2233 : : }
2234 : :
2235 : 0 : kfree(data);
2236 : 0 : return rc;
2237 : : }
2238 : :
2239 : : static const struct file_operations smk_syslog_ops = {
2240 : : .read = smk_read_syslog,
2241 : : .write = smk_write_syslog,
2242 : : .llseek = default_llseek,
2243 : : };
2244 : :
2245 : :
2246 : : /**
2247 : : * smk_fill_super - fill the smackfs superblock
2248 : : * @sb: the empty superblock
2249 : : * @data: unused
2250 : : * @silent: unused
2251 : : *
2252 : : * Fill in the well known entries for the smack filesystem
2253 : : *
2254 : : * Returns 0 on success, an error code on failure
2255 : : */
2256 : 0 : static int smk_fill_super(struct super_block *sb, void *data, int silent)
2257 : : {
2258 : : int rc;
2259 : : struct inode *root_inode;
2260 : :
2261 : : static struct tree_descr smack_files[] = {
2262 : : [SMK_LOAD] = {
2263 : : "load", &smk_load_ops, S_IRUGO|S_IWUSR},
2264 : : [SMK_CIPSO] = {
2265 : : "cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR},
2266 : : [SMK_DOI] = {
2267 : : "doi", &smk_doi_ops, S_IRUGO|S_IWUSR},
2268 : : [SMK_DIRECT] = {
2269 : : "direct", &smk_direct_ops, S_IRUGO|S_IWUSR},
2270 : : [SMK_AMBIENT] = {
2271 : : "ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
2272 : : [SMK_NETLBLADDR] = {
2273 : : "netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR},
2274 : : [SMK_ONLYCAP] = {
2275 : : "onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
2276 : : [SMK_LOGGING] = {
2277 : : "logging", &smk_logging_ops, S_IRUGO|S_IWUSR},
2278 : : [SMK_LOAD_SELF] = {
2279 : : "load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO},
2280 : : [SMK_ACCESSES] = {
2281 : : "access", &smk_access_ops, S_IRUGO|S_IWUGO},
2282 : : [SMK_MAPPED] = {
2283 : : "mapped", &smk_mapped_ops, S_IRUGO|S_IWUSR},
2284 : : [SMK_LOAD2] = {
2285 : : "load2", &smk_load2_ops, S_IRUGO|S_IWUSR},
2286 : : [SMK_LOAD_SELF2] = {
2287 : : "load-self2", &smk_load_self2_ops, S_IRUGO|S_IWUGO},
2288 : : [SMK_ACCESS2] = {
2289 : : "access2", &smk_access2_ops, S_IRUGO|S_IWUGO},
2290 : : [SMK_CIPSO2] = {
2291 : : "cipso2", &smk_cipso2_ops, S_IRUGO|S_IWUSR},
2292 : : [SMK_REVOKE_SUBJ] = {
2293 : : "revoke-subject", &smk_revoke_subj_ops,
2294 : : S_IRUGO|S_IWUSR},
2295 : : [SMK_CHANGE_RULE] = {
2296 : : "change-rule", &smk_change_rule_ops, S_IRUGO|S_IWUSR},
2297 : : [SMK_SYSLOG] = {
2298 : : "syslog", &smk_syslog_ops, S_IRUGO|S_IWUSR},
2299 : : /* last one */
2300 : : {""}
2301 : : };
2302 : :
2303 : 0 : rc = simple_fill_super(sb, SMACK_MAGIC, smack_files);
2304 [ # # ]: 0 : if (rc != 0) {
2305 : 0 : printk(KERN_ERR "%s failed %d while creating inodes\n",
2306 : : __func__, rc);
2307 : 0 : return rc;
2308 : : }
2309 : :
2310 : : root_inode = sb->s_root->d_inode;
2311 : :
2312 : : return 0;
2313 : : }
2314 : :
2315 : : /**
2316 : : * smk_mount - get the smackfs superblock
2317 : : * @fs_type: passed along without comment
2318 : : * @flags: passed along without comment
2319 : : * @dev_name: passed along without comment
2320 : : * @data: passed along without comment
2321 : : *
2322 : : * Just passes everything along.
2323 : : *
2324 : : * Returns what the lower level code does.
2325 : : */
2326 : 0 : static struct dentry *smk_mount(struct file_system_type *fs_type,
2327 : : int flags, const char *dev_name, void *data)
2328 : : {
2329 : 0 : return mount_single(fs_type, flags, data, smk_fill_super);
2330 : : }
2331 : :
2332 : : static struct file_system_type smk_fs_type = {
2333 : : .name = "smackfs",
2334 : : .mount = smk_mount,
2335 : : .kill_sb = kill_litter_super,
2336 : : };
2337 : :
2338 : : static struct vfsmount *smackfs_mount;
2339 : :
2340 : 0 : static int __init smk_preset_netlabel(struct smack_known *skp)
2341 : : {
2342 : 0 : skp->smk_netlabel.domain = skp->smk_known;
2343 : 0 : skp->smk_netlabel.flags =
2344 : : NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL;
2345 : 0 : return smk_netlbl_mls(smack_cipso_direct, skp->smk_known,
2346 : 0 : &skp->smk_netlabel, strlen(skp->smk_known));
2347 : : }
2348 : :
2349 : : /**
2350 : : * init_smk_fs - get the smackfs superblock
2351 : : *
2352 : : * register the smackfs
2353 : : *
2354 : : * Do not register smackfs if Smack wasn't enabled
2355 : : * on boot. We can not put this method normally under the
2356 : : * smack_init() code path since the security subsystem get
2357 : : * initialized before the vfs caches.
2358 : : *
2359 : : * Returns true if we were not chosen on boot or if
2360 : : * we were chosen and filesystem registration succeeded.
2361 : : */
2362 : 0 : static int __init init_smk_fs(void)
2363 : : {
2364 : : int err;
2365 : : int rc;
2366 : :
2367 [ # # ]: 0 : if (!security_module_enable(&smack_ops))
2368 : : return 0;
2369 : :
2370 : 0 : err = smk_init_sysfs();
2371 [ # # ]: 0 : if (err)
2372 : 0 : printk(KERN_ERR "smackfs: sysfs mountpoint problem.\n");
2373 : :
2374 : 0 : err = register_filesystem(&smk_fs_type);
2375 [ # # ]: 0 : if (!err) {
2376 : 0 : smackfs_mount = kern_mount(&smk_fs_type);
2377 [ # # ]: 0 : if (IS_ERR(smackfs_mount)) {
2378 : 0 : printk(KERN_ERR "smackfs: could not mount!\n");
2379 : 0 : err = PTR_ERR(smackfs_mount);
2380 : 0 : smackfs_mount = NULL;
2381 : : }
2382 : : }
2383 : :
2384 : 0 : smk_cipso_doi();
2385 : 0 : smk_unlbl_ambient(NULL);
2386 : :
2387 : 0 : rc = smk_preset_netlabel(&smack_known_floor);
2388 [ # # ]: 0 : if (err == 0 && rc < 0)
2389 : : err = rc;
2390 : 0 : rc = smk_preset_netlabel(&smack_known_hat);
2391 [ # # ]: 0 : if (err == 0 && rc < 0)
2392 : : err = rc;
2393 : 0 : rc = smk_preset_netlabel(&smack_known_huh);
2394 [ # # ]: 0 : if (err == 0 && rc < 0)
2395 : : err = rc;
2396 : 0 : rc = smk_preset_netlabel(&smack_known_invalid);
2397 [ # # ]: 0 : if (err == 0 && rc < 0)
2398 : : err = rc;
2399 : 0 : rc = smk_preset_netlabel(&smack_known_star);
2400 [ # # ]: 0 : if (err == 0 && rc < 0)
2401 : : err = rc;
2402 : 0 : rc = smk_preset_netlabel(&smack_known_web);
2403 [ # # ]: 0 : if (err == 0 && rc < 0)
2404 : : err = rc;
2405 : :
2406 : 0 : return err;
2407 : : }
2408 : :
2409 : : __initcall(init_smk_fs);
|