Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/security/smack/smackfs.c
10814 views
1
/*
2
* Copyright (C) 2007 Casey Schaufler <[email protected]>
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 <[email protected]>
10
* Ahmed S. Darwish <[email protected]>
11
*
12
* Special thanks to the authors of selinuxfs.
13
*
14
* Karl MacMillan <[email protected]>
15
* James Morris <[email protected]>
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/netlabel.h>
26
#include <net/cipso_ipv4.h>
27
#include <linux/seq_file.h>
28
#include <linux/ctype.h>
29
#include <linux/audit.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
};
48
49
/*
50
* List locks
51
*/
52
static DEFINE_MUTEX(smack_list_lock);
53
static DEFINE_MUTEX(smack_cipso_lock);
54
static DEFINE_MUTEX(smack_ambient_lock);
55
static DEFINE_MUTEX(smk_netlbladdr_lock);
56
57
/*
58
* This is the "ambient" label for network traffic.
59
* If it isn't somehow marked, use this.
60
* It can be reset via smackfs/ambient
61
*/
62
char *smack_net_ambient = smack_known_floor.smk_known;
63
64
/*
65
* This is the level in a CIPSO header that indicates a
66
* smack label is contained directly in the category set.
67
* It can be reset via smackfs/direct
68
*/
69
int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT;
70
71
/*
72
* Unless a process is running with this label even
73
* having CAP_MAC_OVERRIDE isn't enough to grant
74
* privilege to violate MAC policy. If no label is
75
* designated (the NULL case) capabilities apply to
76
* everyone. It is expected that the hat (^) label
77
* will be used if any label is used.
78
*/
79
char *smack_onlycap;
80
81
/*
82
* Certain IP addresses may be designated as single label hosts.
83
* Packets are sent there unlabeled, but only from tasks that
84
* can write to the specified label.
85
*/
86
87
LIST_HEAD(smk_netlbladdr_list);
88
LIST_HEAD(smack_rule_list);
89
90
static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
91
92
const char *smack_cipso_option = SMACK_CIPSO_OPTION;
93
94
95
#define SEQ_READ_FINISHED 1
96
97
/*
98
* Values for parsing cipso rules
99
* SMK_DIGITLEN: Length of a digit field in a rule.
100
* SMK_CIPSOMIN: Minimum possible cipso rule length.
101
* SMK_CIPSOMAX: Maximum possible cipso rule length.
102
*/
103
#define SMK_DIGITLEN 4
104
#define SMK_CIPSOMIN (SMK_LABELLEN + 2 * SMK_DIGITLEN)
105
#define SMK_CIPSOMAX (SMK_CIPSOMIN + SMACK_CIPSO_MAXCATNUM * SMK_DIGITLEN)
106
107
/*
108
* Values for parsing MAC rules
109
* SMK_ACCESS: Maximum possible combination of access permissions
110
* SMK_ACCESSLEN: Maximum length for a rule access field
111
* SMK_LOADLEN: Smack rule length
112
*/
113
#define SMK_OACCESS "rwxa"
114
#define SMK_ACCESS "rwxat"
115
#define SMK_OACCESSLEN (sizeof(SMK_OACCESS) - 1)
116
#define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1)
117
#define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN)
118
#define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN)
119
120
/**
121
* smk_netlabel_audit_set - fill a netlbl_audit struct
122
* @nap: structure to fill
123
*/
124
static void smk_netlabel_audit_set(struct netlbl_audit *nap)
125
{
126
nap->loginuid = audit_get_loginuid(current);
127
nap->sessionid = audit_get_sessionid(current);
128
nap->secid = smack_to_secid(smk_of_current());
129
}
130
131
/*
132
* Values for parsing single label host rules
133
* "1.2.3.4 X"
134
* "192.168.138.129/32 abcdefghijklmnopqrstuvw"
135
*/
136
#define SMK_NETLBLADDRMIN 9
137
#define SMK_NETLBLADDRMAX 42
138
139
/**
140
* smk_set_access - add a rule to the rule list
141
* @srp: the new rule to add
142
* @rule_list: the list of rules
143
* @rule_lock: the rule list lock
144
*
145
* Looks through the current subject/object/access list for
146
* the subject/object pair and replaces the access that was
147
* there. If the pair isn't found add it with the specified
148
* access.
149
*
150
* Returns 1 if a rule was found to exist already, 0 if it is new
151
* Returns 0 if nothing goes wrong or -ENOMEM if it fails
152
* during the allocation of the new pair to add.
153
*/
154
static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
155
struct mutex *rule_lock)
156
{
157
struct smack_rule *sp;
158
int found = 0;
159
160
mutex_lock(rule_lock);
161
162
list_for_each_entry_rcu(sp, rule_list, list) {
163
if (sp->smk_subject == srp->smk_subject &&
164
sp->smk_object == srp->smk_object) {
165
found = 1;
166
sp->smk_access = srp->smk_access;
167
break;
168
}
169
}
170
if (found == 0)
171
list_add_rcu(&srp->list, rule_list);
172
173
mutex_unlock(rule_lock);
174
175
return found;
176
}
177
178
/**
179
* smk_write_load_list - write() for any /smack/load
180
* @file: file pointer, not actually used
181
* @buf: where to get the data from
182
* @count: bytes sent
183
* @ppos: where to start - must be 0
184
* @rule_list: the list of rules to write to
185
* @rule_lock: lock for the rule list
186
*
187
* Get one smack access rule from above.
188
* The format is exactly:
189
* char subject[SMK_LABELLEN]
190
* char object[SMK_LABELLEN]
191
* char access[SMK_ACCESSLEN]
192
*
193
* writes must be SMK_LABELLEN+SMK_LABELLEN+SMK_ACCESSLEN bytes.
194
*/
195
static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
196
size_t count, loff_t *ppos,
197
struct list_head *rule_list,
198
struct mutex *rule_lock)
199
{
200
struct smack_rule *rule;
201
char *data;
202
int rc = -EINVAL;
203
204
/*
205
* No partial writes.
206
* Enough data must be present.
207
*/
208
if (*ppos != 0)
209
return -EINVAL;
210
/*
211
* Minor hack for backward compatibility
212
*/
213
if (count < (SMK_OLOADLEN) || count > SMK_LOADLEN)
214
return -EINVAL;
215
216
data = kzalloc(SMK_LOADLEN, GFP_KERNEL);
217
if (data == NULL)
218
return -ENOMEM;
219
220
if (copy_from_user(data, buf, count) != 0) {
221
rc = -EFAULT;
222
goto out;
223
}
224
225
/*
226
* More on the minor hack for backward compatibility
227
*/
228
if (count == (SMK_OLOADLEN))
229
data[SMK_OLOADLEN] = '-';
230
231
rule = kzalloc(sizeof(*rule), GFP_KERNEL);
232
if (rule == NULL) {
233
rc = -ENOMEM;
234
goto out;
235
}
236
237
rule->smk_subject = smk_import(data, 0);
238
if (rule->smk_subject == NULL)
239
goto out_free_rule;
240
241
rule->smk_object = smk_import(data + SMK_LABELLEN, 0);
242
if (rule->smk_object == NULL)
243
goto out_free_rule;
244
245
rule->smk_access = 0;
246
247
switch (data[SMK_LABELLEN + SMK_LABELLEN]) {
248
case '-':
249
break;
250
case 'r':
251
case 'R':
252
rule->smk_access |= MAY_READ;
253
break;
254
default:
255
goto out_free_rule;
256
}
257
258
switch (data[SMK_LABELLEN + SMK_LABELLEN + 1]) {
259
case '-':
260
break;
261
case 'w':
262
case 'W':
263
rule->smk_access |= MAY_WRITE;
264
break;
265
default:
266
goto out_free_rule;
267
}
268
269
switch (data[SMK_LABELLEN + SMK_LABELLEN + 2]) {
270
case '-':
271
break;
272
case 'x':
273
case 'X':
274
rule->smk_access |= MAY_EXEC;
275
break;
276
default:
277
goto out_free_rule;
278
}
279
280
switch (data[SMK_LABELLEN + SMK_LABELLEN + 3]) {
281
case '-':
282
break;
283
case 'a':
284
case 'A':
285
rule->smk_access |= MAY_APPEND;
286
break;
287
default:
288
goto out_free_rule;
289
}
290
291
switch (data[SMK_LABELLEN + SMK_LABELLEN + 4]) {
292
case '-':
293
break;
294
case 't':
295
case 'T':
296
rule->smk_access |= MAY_TRANSMUTE;
297
break;
298
default:
299
goto out_free_rule;
300
}
301
302
rc = count;
303
/*
304
* smk_set_access returns true if there was already a rule
305
* for the subject/object pair, and false if it was new.
306
*/
307
if (!smk_set_access(rule, rule_list, rule_lock))
308
goto out;
309
310
out_free_rule:
311
kfree(rule);
312
out:
313
kfree(data);
314
return rc;
315
}
316
317
318
/*
319
* Seq_file read operations for /smack/load
320
*/
321
322
static void *load_seq_start(struct seq_file *s, loff_t *pos)
323
{
324
if (*pos == SEQ_READ_FINISHED)
325
return NULL;
326
if (list_empty(&smack_rule_list))
327
return NULL;
328
return smack_rule_list.next;
329
}
330
331
static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos)
332
{
333
struct list_head *list = v;
334
335
if (list_is_last(list, &smack_rule_list)) {
336
*pos = SEQ_READ_FINISHED;
337
return NULL;
338
}
339
return list->next;
340
}
341
342
static int load_seq_show(struct seq_file *s, void *v)
343
{
344
struct list_head *list = v;
345
struct smack_rule *srp =
346
list_entry(list, struct smack_rule, list);
347
348
seq_printf(s, "%s %s", (char *)srp->smk_subject,
349
(char *)srp->smk_object);
350
351
seq_putc(s, ' ');
352
353
if (srp->smk_access & MAY_READ)
354
seq_putc(s, 'r');
355
if (srp->smk_access & MAY_WRITE)
356
seq_putc(s, 'w');
357
if (srp->smk_access & MAY_EXEC)
358
seq_putc(s, 'x');
359
if (srp->smk_access & MAY_APPEND)
360
seq_putc(s, 'a');
361
if (srp->smk_access & MAY_TRANSMUTE)
362
seq_putc(s, 't');
363
if (srp->smk_access == 0)
364
seq_putc(s, '-');
365
366
seq_putc(s, '\n');
367
368
return 0;
369
}
370
371
static void load_seq_stop(struct seq_file *s, void *v)
372
{
373
/* No-op */
374
}
375
376
static const struct seq_operations load_seq_ops = {
377
.start = load_seq_start,
378
.next = load_seq_next,
379
.show = load_seq_show,
380
.stop = load_seq_stop,
381
};
382
383
/**
384
* smk_open_load - open() for /smack/load
385
* @inode: inode structure representing file
386
* @file: "load" file pointer
387
*
388
* For reading, use load_seq_* seq_file reading operations.
389
*/
390
static int smk_open_load(struct inode *inode, struct file *file)
391
{
392
return seq_open(file, &load_seq_ops);
393
}
394
395
/**
396
* smk_write_load - write() for /smack/load
397
* @file: file pointer, not actually used
398
* @buf: where to get the data from
399
* @count: bytes sent
400
* @ppos: where to start - must be 0
401
*
402
*/
403
static ssize_t smk_write_load(struct file *file, const char __user *buf,
404
size_t count, loff_t *ppos)
405
{
406
407
/*
408
* Must have privilege.
409
* No partial writes.
410
* Enough data must be present.
411
*/
412
if (!capable(CAP_MAC_ADMIN))
413
return -EPERM;
414
415
return smk_write_load_list(file, buf, count, ppos, &smack_rule_list,
416
&smack_list_lock);
417
}
418
419
static const struct file_operations smk_load_ops = {
420
.open = smk_open_load,
421
.read = seq_read,
422
.llseek = seq_lseek,
423
.write = smk_write_load,
424
.release = seq_release,
425
};
426
427
/**
428
* smk_cipso_doi - initialize the CIPSO domain
429
*/
430
static void smk_cipso_doi(void)
431
{
432
int rc;
433
struct cipso_v4_doi *doip;
434
struct netlbl_audit nai;
435
436
smk_netlabel_audit_set(&nai);
437
438
rc = netlbl_cfg_map_del(NULL, PF_INET, NULL, NULL, &nai);
439
if (rc != 0)
440
printk(KERN_WARNING "%s:%d remove rc = %d\n",
441
__func__, __LINE__, rc);
442
443
doip = kmalloc(sizeof(struct cipso_v4_doi), GFP_KERNEL);
444
if (doip == NULL)
445
panic("smack: Failed to initialize cipso DOI.\n");
446
doip->map.std = NULL;
447
doip->doi = smk_cipso_doi_value;
448
doip->type = CIPSO_V4_MAP_PASS;
449
doip->tags[0] = CIPSO_V4_TAG_RBITMAP;
450
for (rc = 1; rc < CIPSO_V4_TAG_MAXCNT; rc++)
451
doip->tags[rc] = CIPSO_V4_TAG_INVALID;
452
453
rc = netlbl_cfg_cipsov4_add(doip, &nai);
454
if (rc != 0) {
455
printk(KERN_WARNING "%s:%d cipso add rc = %d\n",
456
__func__, __LINE__, rc);
457
kfree(doip);
458
return;
459
}
460
rc = netlbl_cfg_cipsov4_map_add(doip->doi, NULL, NULL, NULL, &nai);
461
if (rc != 0) {
462
printk(KERN_WARNING "%s:%d map add rc = %d\n",
463
__func__, __LINE__, rc);
464
kfree(doip);
465
return;
466
}
467
}
468
469
/**
470
* smk_unlbl_ambient - initialize the unlabeled domain
471
* @oldambient: previous domain string
472
*/
473
static void smk_unlbl_ambient(char *oldambient)
474
{
475
int rc;
476
struct netlbl_audit nai;
477
478
smk_netlabel_audit_set(&nai);
479
480
if (oldambient != NULL) {
481
rc = netlbl_cfg_map_del(oldambient, PF_INET, NULL, NULL, &nai);
482
if (rc != 0)
483
printk(KERN_WARNING "%s:%d remove rc = %d\n",
484
__func__, __LINE__, rc);
485
}
486
487
rc = netlbl_cfg_unlbl_map_add(smack_net_ambient, PF_INET,
488
NULL, NULL, &nai);
489
if (rc != 0)
490
printk(KERN_WARNING "%s:%d add rc = %d\n",
491
__func__, __LINE__, rc);
492
}
493
494
/*
495
* Seq_file read operations for /smack/cipso
496
*/
497
498
static void *cipso_seq_start(struct seq_file *s, loff_t *pos)
499
{
500
if (*pos == SEQ_READ_FINISHED)
501
return NULL;
502
if (list_empty(&smack_known_list))
503
return NULL;
504
505
return smack_known_list.next;
506
}
507
508
static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos)
509
{
510
struct list_head *list = v;
511
512
/*
513
* labels with no associated cipso value wont be printed
514
* in cipso_seq_show
515
*/
516
if (list_is_last(list, &smack_known_list)) {
517
*pos = SEQ_READ_FINISHED;
518
return NULL;
519
}
520
521
return list->next;
522
}
523
524
/*
525
* Print cipso labels in format:
526
* label level[/cat[,cat]]
527
*/
528
static int cipso_seq_show(struct seq_file *s, void *v)
529
{
530
struct list_head *list = v;
531
struct smack_known *skp =
532
list_entry(list, struct smack_known, list);
533
struct smack_cipso *scp = skp->smk_cipso;
534
char *cbp;
535
char sep = '/';
536
int cat = 1;
537
int i;
538
unsigned char m;
539
540
if (scp == NULL)
541
return 0;
542
543
seq_printf(s, "%s %3d", (char *)&skp->smk_known, scp->smk_level);
544
545
cbp = scp->smk_catset;
546
for (i = 0; i < SMK_LABELLEN; i++)
547
for (m = 0x80; m != 0; m >>= 1) {
548
if (m & cbp[i]) {
549
seq_printf(s, "%c%d", sep, cat);
550
sep = ',';
551
}
552
cat++;
553
}
554
555
seq_putc(s, '\n');
556
557
return 0;
558
}
559
560
static void cipso_seq_stop(struct seq_file *s, void *v)
561
{
562
/* No-op */
563
}
564
565
static const struct seq_operations cipso_seq_ops = {
566
.start = cipso_seq_start,
567
.stop = cipso_seq_stop,
568
.next = cipso_seq_next,
569
.show = cipso_seq_show,
570
};
571
572
/**
573
* smk_open_cipso - open() for /smack/cipso
574
* @inode: inode structure representing file
575
* @file: "cipso" file pointer
576
*
577
* Connect our cipso_seq_* operations with /smack/cipso
578
* file_operations
579
*/
580
static int smk_open_cipso(struct inode *inode, struct file *file)
581
{
582
return seq_open(file, &cipso_seq_ops);
583
}
584
585
/**
586
* smk_write_cipso - write() for /smack/cipso
587
* @file: file pointer, not actually used
588
* @buf: where to get the data from
589
* @count: bytes sent
590
* @ppos: where to start
591
*
592
* Accepts only one cipso rule per write call.
593
* Returns number of bytes written or error code, as appropriate
594
*/
595
static ssize_t smk_write_cipso(struct file *file, const char __user *buf,
596
size_t count, loff_t *ppos)
597
{
598
struct smack_known *skp;
599
struct smack_cipso *scp = NULL;
600
char mapcatset[SMK_LABELLEN];
601
int maplevel;
602
int cat;
603
int catlen;
604
ssize_t rc = -EINVAL;
605
char *data = NULL;
606
char *rule;
607
int ret;
608
int i;
609
610
/*
611
* Must have privilege.
612
* No partial writes.
613
* Enough data must be present.
614
*/
615
if (!capable(CAP_MAC_ADMIN))
616
return -EPERM;
617
if (*ppos != 0)
618
return -EINVAL;
619
if (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX)
620
return -EINVAL;
621
622
data = kzalloc(count + 1, GFP_KERNEL);
623
if (data == NULL)
624
return -ENOMEM;
625
626
if (copy_from_user(data, buf, count) != 0) {
627
rc = -EFAULT;
628
goto unlockedout;
629
}
630
631
/* labels cannot begin with a '-' */
632
if (data[0] == '-') {
633
rc = -EINVAL;
634
goto unlockedout;
635
}
636
data[count] = '\0';
637
rule = data;
638
/*
639
* Only allow one writer at a time. Writes should be
640
* quite rare and small in any case.
641
*/
642
mutex_lock(&smack_cipso_lock);
643
644
skp = smk_import_entry(rule, 0);
645
if (skp == NULL)
646
goto out;
647
648
rule += SMK_LABELLEN;
649
ret = sscanf(rule, "%d", &maplevel);
650
if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL)
651
goto out;
652
653
rule += SMK_DIGITLEN;
654
ret = sscanf(rule, "%d", &catlen);
655
if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM)
656
goto out;
657
658
if (count != (SMK_CIPSOMIN + catlen * SMK_DIGITLEN))
659
goto out;
660
661
memset(mapcatset, 0, sizeof(mapcatset));
662
663
for (i = 0; i < catlen; i++) {
664
rule += SMK_DIGITLEN;
665
ret = sscanf(rule, "%d", &cat);
666
if (ret != 1 || cat > SMACK_CIPSO_MAXCATVAL)
667
goto out;
668
669
smack_catset_bit(cat, mapcatset);
670
}
671
672
if (skp->smk_cipso == NULL) {
673
scp = kzalloc(sizeof(struct smack_cipso), GFP_KERNEL);
674
if (scp == NULL) {
675
rc = -ENOMEM;
676
goto out;
677
}
678
}
679
680
spin_lock_bh(&skp->smk_cipsolock);
681
682
if (scp == NULL)
683
scp = skp->smk_cipso;
684
else
685
skp->smk_cipso = scp;
686
687
scp->smk_level = maplevel;
688
memcpy(scp->smk_catset, mapcatset, sizeof(mapcatset));
689
690
spin_unlock_bh(&skp->smk_cipsolock);
691
692
rc = count;
693
out:
694
mutex_unlock(&smack_cipso_lock);
695
unlockedout:
696
kfree(data);
697
return rc;
698
}
699
700
static const struct file_operations smk_cipso_ops = {
701
.open = smk_open_cipso,
702
.read = seq_read,
703
.llseek = seq_lseek,
704
.write = smk_write_cipso,
705
.release = seq_release,
706
};
707
708
/*
709
* Seq_file read operations for /smack/netlabel
710
*/
711
712
static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos)
713
{
714
if (*pos == SEQ_READ_FINISHED)
715
return NULL;
716
if (list_empty(&smk_netlbladdr_list))
717
return NULL;
718
return smk_netlbladdr_list.next;
719
}
720
721
static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos)
722
{
723
struct list_head *list = v;
724
725
if (list_is_last(list, &smk_netlbladdr_list)) {
726
*pos = SEQ_READ_FINISHED;
727
return NULL;
728
}
729
730
return list->next;
731
}
732
#define BEBITS (sizeof(__be32) * 8)
733
734
/*
735
* Print host/label pairs
736
*/
737
static int netlbladdr_seq_show(struct seq_file *s, void *v)
738
{
739
struct list_head *list = v;
740
struct smk_netlbladdr *skp =
741
list_entry(list, struct smk_netlbladdr, list);
742
unsigned char *hp = (char *) &skp->smk_host.sin_addr.s_addr;
743
int maskn;
744
u32 temp_mask = be32_to_cpu(skp->smk_mask.s_addr);
745
746
for (maskn = 0; temp_mask; temp_mask <<= 1, maskn++);
747
748
seq_printf(s, "%u.%u.%u.%u/%d %s\n",
749
hp[0], hp[1], hp[2], hp[3], maskn, skp->smk_label);
750
751
return 0;
752
}
753
754
static void netlbladdr_seq_stop(struct seq_file *s, void *v)
755
{
756
/* No-op */
757
}
758
759
static const struct seq_operations netlbladdr_seq_ops = {
760
.start = netlbladdr_seq_start,
761
.stop = netlbladdr_seq_stop,
762
.next = netlbladdr_seq_next,
763
.show = netlbladdr_seq_show,
764
};
765
766
/**
767
* smk_open_netlbladdr - open() for /smack/netlabel
768
* @inode: inode structure representing file
769
* @file: "netlabel" file pointer
770
*
771
* Connect our netlbladdr_seq_* operations with /smack/netlabel
772
* file_operations
773
*/
774
static int smk_open_netlbladdr(struct inode *inode, struct file *file)
775
{
776
return seq_open(file, &netlbladdr_seq_ops);
777
}
778
779
/**
780
* smk_netlbladdr_insert
781
* @new : netlabel to insert
782
*
783
* This helper insert netlabel in the smack_netlbladdrs list
784
* sorted by netmask length (longest to smallest)
785
* locked by &smk_netlbladdr_lock in smk_write_netlbladdr
786
*
787
*/
788
static void smk_netlbladdr_insert(struct smk_netlbladdr *new)
789
{
790
struct smk_netlbladdr *m, *m_next;
791
792
if (list_empty(&smk_netlbladdr_list)) {
793
list_add_rcu(&new->list, &smk_netlbladdr_list);
794
return;
795
}
796
797
m = list_entry_rcu(smk_netlbladdr_list.next,
798
struct smk_netlbladdr, list);
799
800
/* the comparison '>' is a bit hacky, but works */
801
if (new->smk_mask.s_addr > m->smk_mask.s_addr) {
802
list_add_rcu(&new->list, &smk_netlbladdr_list);
803
return;
804
}
805
806
list_for_each_entry_rcu(m, &smk_netlbladdr_list, list) {
807
if (list_is_last(&m->list, &smk_netlbladdr_list)) {
808
list_add_rcu(&new->list, &m->list);
809
return;
810
}
811
m_next = list_entry_rcu(m->list.next,
812
struct smk_netlbladdr, list);
813
if (new->smk_mask.s_addr > m_next->smk_mask.s_addr) {
814
list_add_rcu(&new->list, &m->list);
815
return;
816
}
817
}
818
}
819
820
821
/**
822
* smk_write_netlbladdr - write() for /smack/netlabel
823
* @file: file pointer, not actually used
824
* @buf: where to get the data from
825
* @count: bytes sent
826
* @ppos: where to start
827
*
828
* Accepts only one netlbladdr per write call.
829
* Returns number of bytes written or error code, as appropriate
830
*/
831
static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf,
832
size_t count, loff_t *ppos)
833
{
834
struct smk_netlbladdr *skp;
835
struct sockaddr_in newname;
836
char smack[SMK_LABELLEN];
837
char *sp;
838
char data[SMK_NETLBLADDRMAX + 1];
839
char *host = (char *)&newname.sin_addr.s_addr;
840
int rc;
841
struct netlbl_audit audit_info;
842
struct in_addr mask;
843
unsigned int m;
844
int found;
845
u32 mask_bits = (1<<31);
846
__be32 nsa;
847
u32 temp_mask;
848
849
/*
850
* Must have privilege.
851
* No partial writes.
852
* Enough data must be present.
853
* "<addr/mask, as a.b.c.d/e><space><label>"
854
* "<addr, as a.b.c.d><space><label>"
855
*/
856
if (!capable(CAP_MAC_ADMIN))
857
return -EPERM;
858
if (*ppos != 0)
859
return -EINVAL;
860
if (count < SMK_NETLBLADDRMIN || count > SMK_NETLBLADDRMAX)
861
return -EINVAL;
862
if (copy_from_user(data, buf, count) != 0)
863
return -EFAULT;
864
865
data[count] = '\0';
866
867
rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd/%d %s",
868
&host[0], &host[1], &host[2], &host[3], &m, smack);
869
if (rc != 6) {
870
rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s",
871
&host[0], &host[1], &host[2], &host[3], smack);
872
if (rc != 5)
873
return -EINVAL;
874
m = BEBITS;
875
}
876
if (m > BEBITS)
877
return -EINVAL;
878
879
/* if smack begins with '-', its an option, don't import it */
880
if (smack[0] != '-') {
881
sp = smk_import(smack, 0);
882
if (sp == NULL)
883
return -EINVAL;
884
} else {
885
/* check known options */
886
if (strcmp(smack, smack_cipso_option) == 0)
887
sp = (char *)smack_cipso_option;
888
else
889
return -EINVAL;
890
}
891
892
for (temp_mask = 0; m > 0; m--) {
893
temp_mask |= mask_bits;
894
mask_bits >>= 1;
895
}
896
mask.s_addr = cpu_to_be32(temp_mask);
897
898
newname.sin_addr.s_addr &= mask.s_addr;
899
/*
900
* Only allow one writer at a time. Writes should be
901
* quite rare and small in any case.
902
*/
903
mutex_lock(&smk_netlbladdr_lock);
904
905
nsa = newname.sin_addr.s_addr;
906
/* try to find if the prefix is already in the list */
907
found = 0;
908
list_for_each_entry_rcu(skp, &smk_netlbladdr_list, list) {
909
if (skp->smk_host.sin_addr.s_addr == nsa &&
910
skp->smk_mask.s_addr == mask.s_addr) {
911
found = 1;
912
break;
913
}
914
}
915
smk_netlabel_audit_set(&audit_info);
916
917
if (found == 0) {
918
skp = kzalloc(sizeof(*skp), GFP_KERNEL);
919
if (skp == NULL)
920
rc = -ENOMEM;
921
else {
922
rc = 0;
923
skp->smk_host.sin_addr.s_addr = newname.sin_addr.s_addr;
924
skp->smk_mask.s_addr = mask.s_addr;
925
skp->smk_label = sp;
926
smk_netlbladdr_insert(skp);
927
}
928
} else {
929
/* we delete the unlabeled entry, only if the previous label
930
* wasn't the special CIPSO option */
931
if (skp->smk_label != smack_cipso_option)
932
rc = netlbl_cfg_unlbl_static_del(&init_net, NULL,
933
&skp->smk_host.sin_addr, &skp->smk_mask,
934
PF_INET, &audit_info);
935
else
936
rc = 0;
937
skp->smk_label = sp;
938
}
939
940
/*
941
* Now tell netlabel about the single label nature of
942
* this host so that incoming packets get labeled.
943
* but only if we didn't get the special CIPSO option
944
*/
945
if (rc == 0 && sp != smack_cipso_option)
946
rc = netlbl_cfg_unlbl_static_add(&init_net, NULL,
947
&skp->smk_host.sin_addr, &skp->smk_mask, PF_INET,
948
smack_to_secid(skp->smk_label), &audit_info);
949
950
if (rc == 0)
951
rc = count;
952
953
mutex_unlock(&smk_netlbladdr_lock);
954
955
return rc;
956
}
957
958
static const struct file_operations smk_netlbladdr_ops = {
959
.open = smk_open_netlbladdr,
960
.read = seq_read,
961
.llseek = seq_lseek,
962
.write = smk_write_netlbladdr,
963
.release = seq_release,
964
};
965
966
/**
967
* smk_read_doi - read() for /smack/doi
968
* @filp: file pointer, not actually used
969
* @buf: where to put the result
970
* @count: maximum to send along
971
* @ppos: where to start
972
*
973
* Returns number of bytes read or error code, as appropriate
974
*/
975
static ssize_t smk_read_doi(struct file *filp, char __user *buf,
976
size_t count, loff_t *ppos)
977
{
978
char temp[80];
979
ssize_t rc;
980
981
if (*ppos != 0)
982
return 0;
983
984
sprintf(temp, "%d", smk_cipso_doi_value);
985
rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
986
987
return rc;
988
}
989
990
/**
991
* smk_write_doi - write() for /smack/doi
992
* @file: file pointer, not actually used
993
* @buf: where to get the data from
994
* @count: bytes sent
995
* @ppos: where to start
996
*
997
* Returns number of bytes written or error code, as appropriate
998
*/
999
static ssize_t smk_write_doi(struct file *file, const char __user *buf,
1000
size_t count, loff_t *ppos)
1001
{
1002
char temp[80];
1003
int i;
1004
1005
if (!capable(CAP_MAC_ADMIN))
1006
return -EPERM;
1007
1008
if (count >= sizeof(temp) || count == 0)
1009
return -EINVAL;
1010
1011
if (copy_from_user(temp, buf, count) != 0)
1012
return -EFAULT;
1013
1014
temp[count] = '\0';
1015
1016
if (sscanf(temp, "%d", &i) != 1)
1017
return -EINVAL;
1018
1019
smk_cipso_doi_value = i;
1020
1021
smk_cipso_doi();
1022
1023
return count;
1024
}
1025
1026
static const struct file_operations smk_doi_ops = {
1027
.read = smk_read_doi,
1028
.write = smk_write_doi,
1029
.llseek = default_llseek,
1030
};
1031
1032
/**
1033
* smk_read_direct - read() for /smack/direct
1034
* @filp: file pointer, not actually used
1035
* @buf: where to put the result
1036
* @count: maximum to send along
1037
* @ppos: where to start
1038
*
1039
* Returns number of bytes read or error code, as appropriate
1040
*/
1041
static ssize_t smk_read_direct(struct file *filp, char __user *buf,
1042
size_t count, loff_t *ppos)
1043
{
1044
char temp[80];
1045
ssize_t rc;
1046
1047
if (*ppos != 0)
1048
return 0;
1049
1050
sprintf(temp, "%d", smack_cipso_direct);
1051
rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
1052
1053
return rc;
1054
}
1055
1056
/**
1057
* smk_write_direct - write() for /smack/direct
1058
* @file: file pointer, not actually used
1059
* @buf: where to get the data from
1060
* @count: bytes sent
1061
* @ppos: where to start
1062
*
1063
* Returns number of bytes written or error code, as appropriate
1064
*/
1065
static ssize_t smk_write_direct(struct file *file, const char __user *buf,
1066
size_t count, loff_t *ppos)
1067
{
1068
char temp[80];
1069
int i;
1070
1071
if (!capable(CAP_MAC_ADMIN))
1072
return -EPERM;
1073
1074
if (count >= sizeof(temp) || count == 0)
1075
return -EINVAL;
1076
1077
if (copy_from_user(temp, buf, count) != 0)
1078
return -EFAULT;
1079
1080
temp[count] = '\0';
1081
1082
if (sscanf(temp, "%d", &i) != 1)
1083
return -EINVAL;
1084
1085
smack_cipso_direct = i;
1086
1087
return count;
1088
}
1089
1090
static const struct file_operations smk_direct_ops = {
1091
.read = smk_read_direct,
1092
.write = smk_write_direct,
1093
.llseek = default_llseek,
1094
};
1095
1096
/**
1097
* smk_read_ambient - read() for /smack/ambient
1098
* @filp: file pointer, not actually used
1099
* @buf: where to put the result
1100
* @cn: maximum to send along
1101
* @ppos: where to start
1102
*
1103
* Returns number of bytes read or error code, as appropriate
1104
*/
1105
static ssize_t smk_read_ambient(struct file *filp, char __user *buf,
1106
size_t cn, loff_t *ppos)
1107
{
1108
ssize_t rc;
1109
int asize;
1110
1111
if (*ppos != 0)
1112
return 0;
1113
/*
1114
* Being careful to avoid a problem in the case where
1115
* smack_net_ambient gets changed in midstream.
1116
*/
1117
mutex_lock(&smack_ambient_lock);
1118
1119
asize = strlen(smack_net_ambient) + 1;
1120
1121
if (cn >= asize)
1122
rc = simple_read_from_buffer(buf, cn, ppos,
1123
smack_net_ambient, asize);
1124
else
1125
rc = -EINVAL;
1126
1127
mutex_unlock(&smack_ambient_lock);
1128
1129
return rc;
1130
}
1131
1132
/**
1133
* smk_write_ambient - write() for /smack/ambient
1134
* @file: file pointer, not actually used
1135
* @buf: where to get the data from
1136
* @count: bytes sent
1137
* @ppos: where to start
1138
*
1139
* Returns number of bytes written or error code, as appropriate
1140
*/
1141
static ssize_t smk_write_ambient(struct file *file, const char __user *buf,
1142
size_t count, loff_t *ppos)
1143
{
1144
char in[SMK_LABELLEN];
1145
char *oldambient;
1146
char *smack;
1147
1148
if (!capable(CAP_MAC_ADMIN))
1149
return -EPERM;
1150
1151
if (count >= SMK_LABELLEN)
1152
return -EINVAL;
1153
1154
if (copy_from_user(in, buf, count) != 0)
1155
return -EFAULT;
1156
1157
smack = smk_import(in, count);
1158
if (smack == NULL)
1159
return -EINVAL;
1160
1161
mutex_lock(&smack_ambient_lock);
1162
1163
oldambient = smack_net_ambient;
1164
smack_net_ambient = smack;
1165
smk_unlbl_ambient(oldambient);
1166
1167
mutex_unlock(&smack_ambient_lock);
1168
1169
return count;
1170
}
1171
1172
static const struct file_operations smk_ambient_ops = {
1173
.read = smk_read_ambient,
1174
.write = smk_write_ambient,
1175
.llseek = default_llseek,
1176
};
1177
1178
/**
1179
* smk_read_onlycap - read() for /smack/onlycap
1180
* @filp: file pointer, not actually used
1181
* @buf: where to put the result
1182
* @cn: maximum to send along
1183
* @ppos: where to start
1184
*
1185
* Returns number of bytes read or error code, as appropriate
1186
*/
1187
static ssize_t smk_read_onlycap(struct file *filp, char __user *buf,
1188
size_t cn, loff_t *ppos)
1189
{
1190
char *smack = "";
1191
ssize_t rc = -EINVAL;
1192
int asize;
1193
1194
if (*ppos != 0)
1195
return 0;
1196
1197
if (smack_onlycap != NULL)
1198
smack = smack_onlycap;
1199
1200
asize = strlen(smack) + 1;
1201
1202
if (cn >= asize)
1203
rc = simple_read_from_buffer(buf, cn, ppos, smack, asize);
1204
1205
return rc;
1206
}
1207
1208
/**
1209
* smk_write_onlycap - write() for /smack/onlycap
1210
* @file: file pointer, not actually used
1211
* @buf: where to get the data from
1212
* @count: bytes sent
1213
* @ppos: where to start
1214
*
1215
* Returns number of bytes written or error code, as appropriate
1216
*/
1217
static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
1218
size_t count, loff_t *ppos)
1219
{
1220
char in[SMK_LABELLEN];
1221
char *sp = smk_of_task(current->cred->security);
1222
1223
if (!capable(CAP_MAC_ADMIN))
1224
return -EPERM;
1225
1226
/*
1227
* This can be done using smk_access() but is done
1228
* explicitly for clarity. The smk_access() implementation
1229
* would use smk_access(smack_onlycap, MAY_WRITE)
1230
*/
1231
if (smack_onlycap != NULL && smack_onlycap != sp)
1232
return -EPERM;
1233
1234
if (count >= SMK_LABELLEN)
1235
return -EINVAL;
1236
1237
if (copy_from_user(in, buf, count) != 0)
1238
return -EFAULT;
1239
1240
/*
1241
* Should the null string be passed in unset the onlycap value.
1242
* This seems like something to be careful with as usually
1243
* smk_import only expects to return NULL for errors. It
1244
* is usually the case that a nullstring or "\n" would be
1245
* bad to pass to smk_import but in fact this is useful here.
1246
*/
1247
smack_onlycap = smk_import(in, count);
1248
1249
return count;
1250
}
1251
1252
static const struct file_operations smk_onlycap_ops = {
1253
.read = smk_read_onlycap,
1254
.write = smk_write_onlycap,
1255
.llseek = default_llseek,
1256
};
1257
1258
/**
1259
* smk_read_logging - read() for /smack/logging
1260
* @filp: file pointer, not actually used
1261
* @buf: where to put the result
1262
* @cn: maximum to send along
1263
* @ppos: where to start
1264
*
1265
* Returns number of bytes read or error code, as appropriate
1266
*/
1267
static ssize_t smk_read_logging(struct file *filp, char __user *buf,
1268
size_t count, loff_t *ppos)
1269
{
1270
char temp[32];
1271
ssize_t rc;
1272
1273
if (*ppos != 0)
1274
return 0;
1275
1276
sprintf(temp, "%d\n", log_policy);
1277
rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp));
1278
return rc;
1279
}
1280
1281
/**
1282
* smk_write_logging - write() for /smack/logging
1283
* @file: file pointer, not actually used
1284
* @buf: where to get the data from
1285
* @count: bytes sent
1286
* @ppos: where to start
1287
*
1288
* Returns number of bytes written or error code, as appropriate
1289
*/
1290
static ssize_t smk_write_logging(struct file *file, const char __user *buf,
1291
size_t count, loff_t *ppos)
1292
{
1293
char temp[32];
1294
int i;
1295
1296
if (!capable(CAP_MAC_ADMIN))
1297
return -EPERM;
1298
1299
if (count >= sizeof(temp) || count == 0)
1300
return -EINVAL;
1301
1302
if (copy_from_user(temp, buf, count) != 0)
1303
return -EFAULT;
1304
1305
temp[count] = '\0';
1306
1307
if (sscanf(temp, "%d", &i) != 1)
1308
return -EINVAL;
1309
if (i < 0 || i > 3)
1310
return -EINVAL;
1311
log_policy = i;
1312
return count;
1313
}
1314
1315
1316
1317
static const struct file_operations smk_logging_ops = {
1318
.read = smk_read_logging,
1319
.write = smk_write_logging,
1320
.llseek = default_llseek,
1321
};
1322
1323
/*
1324
* Seq_file read operations for /smack/load-self
1325
*/
1326
1327
static void *load_self_seq_start(struct seq_file *s, loff_t *pos)
1328
{
1329
struct task_smack *tsp = current_security();
1330
1331
if (*pos == SEQ_READ_FINISHED)
1332
return NULL;
1333
if (list_empty(&tsp->smk_rules))
1334
return NULL;
1335
return tsp->smk_rules.next;
1336
}
1337
1338
static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos)
1339
{
1340
struct task_smack *tsp = current_security();
1341
struct list_head *list = v;
1342
1343
if (list_is_last(list, &tsp->smk_rules)) {
1344
*pos = SEQ_READ_FINISHED;
1345
return NULL;
1346
}
1347
return list->next;
1348
}
1349
1350
static int load_self_seq_show(struct seq_file *s, void *v)
1351
{
1352
struct list_head *list = v;
1353
struct smack_rule *srp =
1354
list_entry(list, struct smack_rule, list);
1355
1356
seq_printf(s, "%s %s", (char *)srp->smk_subject,
1357
(char *)srp->smk_object);
1358
1359
seq_putc(s, ' ');
1360
1361
if (srp->smk_access & MAY_READ)
1362
seq_putc(s, 'r');
1363
if (srp->smk_access & MAY_WRITE)
1364
seq_putc(s, 'w');
1365
if (srp->smk_access & MAY_EXEC)
1366
seq_putc(s, 'x');
1367
if (srp->smk_access & MAY_APPEND)
1368
seq_putc(s, 'a');
1369
if (srp->smk_access & MAY_TRANSMUTE)
1370
seq_putc(s, 't');
1371
if (srp->smk_access == 0)
1372
seq_putc(s, '-');
1373
1374
seq_putc(s, '\n');
1375
1376
return 0;
1377
}
1378
1379
static void load_self_seq_stop(struct seq_file *s, void *v)
1380
{
1381
/* No-op */
1382
}
1383
1384
static const struct seq_operations load_self_seq_ops = {
1385
.start = load_self_seq_start,
1386
.next = load_self_seq_next,
1387
.show = load_self_seq_show,
1388
.stop = load_self_seq_stop,
1389
};
1390
1391
1392
/**
1393
* smk_open_load_self - open() for /smack/load-self
1394
* @inode: inode structure representing file
1395
* @file: "load" file pointer
1396
*
1397
* For reading, use load_seq_* seq_file reading operations.
1398
*/
1399
static int smk_open_load_self(struct inode *inode, struct file *file)
1400
{
1401
return seq_open(file, &load_self_seq_ops);
1402
}
1403
1404
/**
1405
* smk_write_load_self - write() for /smack/load-self
1406
* @file: file pointer, not actually used
1407
* @buf: where to get the data from
1408
* @count: bytes sent
1409
* @ppos: where to start - must be 0
1410
*
1411
*/
1412
static ssize_t smk_write_load_self(struct file *file, const char __user *buf,
1413
size_t count, loff_t *ppos)
1414
{
1415
struct task_smack *tsp = current_security();
1416
1417
return smk_write_load_list(file, buf, count, ppos, &tsp->smk_rules,
1418
&tsp->smk_rules_lock);
1419
}
1420
1421
static const struct file_operations smk_load_self_ops = {
1422
.open = smk_open_load_self,
1423
.read = seq_read,
1424
.llseek = seq_lseek,
1425
.write = smk_write_load_self,
1426
.release = seq_release,
1427
};
1428
/**
1429
* smk_fill_super - fill the /smackfs superblock
1430
* @sb: the empty superblock
1431
* @data: unused
1432
* @silent: unused
1433
*
1434
* Fill in the well known entries for /smack
1435
*
1436
* Returns 0 on success, an error code on failure
1437
*/
1438
static int smk_fill_super(struct super_block *sb, void *data, int silent)
1439
{
1440
int rc;
1441
struct inode *root_inode;
1442
1443
static struct tree_descr smack_files[] = {
1444
[SMK_LOAD] = {
1445
"load", &smk_load_ops, S_IRUGO|S_IWUSR},
1446
[SMK_CIPSO] = {
1447
"cipso", &smk_cipso_ops, S_IRUGO|S_IWUSR},
1448
[SMK_DOI] = {
1449
"doi", &smk_doi_ops, S_IRUGO|S_IWUSR},
1450
[SMK_DIRECT] = {
1451
"direct", &smk_direct_ops, S_IRUGO|S_IWUSR},
1452
[SMK_AMBIENT] = {
1453
"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
1454
[SMK_NETLBLADDR] = {
1455
"netlabel", &smk_netlbladdr_ops, S_IRUGO|S_IWUSR},
1456
[SMK_ONLYCAP] = {
1457
"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
1458
[SMK_LOGGING] = {
1459
"logging", &smk_logging_ops, S_IRUGO|S_IWUSR},
1460
[SMK_LOAD_SELF] = {
1461
"load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO},
1462
/* last one */
1463
{""}
1464
};
1465
1466
rc = simple_fill_super(sb, SMACK_MAGIC, smack_files);
1467
if (rc != 0) {
1468
printk(KERN_ERR "%s failed %d while creating inodes\n",
1469
__func__, rc);
1470
return rc;
1471
}
1472
1473
root_inode = sb->s_root->d_inode;
1474
root_inode->i_security = new_inode_smack(smack_known_floor.smk_known);
1475
1476
return 0;
1477
}
1478
1479
/**
1480
* smk_mount - get the smackfs superblock
1481
* @fs_type: passed along without comment
1482
* @flags: passed along without comment
1483
* @dev_name: passed along without comment
1484
* @data: passed along without comment
1485
*
1486
* Just passes everything along.
1487
*
1488
* Returns what the lower level code does.
1489
*/
1490
static struct dentry *smk_mount(struct file_system_type *fs_type,
1491
int flags, const char *dev_name, void *data)
1492
{
1493
return mount_single(fs_type, flags, data, smk_fill_super);
1494
}
1495
1496
static struct file_system_type smk_fs_type = {
1497
.name = "smackfs",
1498
.mount = smk_mount,
1499
.kill_sb = kill_litter_super,
1500
};
1501
1502
static struct vfsmount *smackfs_mount;
1503
1504
/**
1505
* init_smk_fs - get the smackfs superblock
1506
*
1507
* register the smackfs
1508
*
1509
* Do not register smackfs if Smack wasn't enabled
1510
* on boot. We can not put this method normally under the
1511
* smack_init() code path since the security subsystem get
1512
* initialized before the vfs caches.
1513
*
1514
* Returns true if we were not chosen on boot or if
1515
* we were chosen and filesystem registration succeeded.
1516
*/
1517
static int __init init_smk_fs(void)
1518
{
1519
int err;
1520
1521
if (!security_module_enable(&smack_ops))
1522
return 0;
1523
1524
err = register_filesystem(&smk_fs_type);
1525
if (!err) {
1526
smackfs_mount = kern_mount(&smk_fs_type);
1527
if (IS_ERR(smackfs_mount)) {
1528
printk(KERN_ERR "smackfs: could not mount!\n");
1529
err = PTR_ERR(smackfs_mount);
1530
smackfs_mount = NULL;
1531
}
1532
}
1533
1534
smk_cipso_doi();
1535
smk_unlbl_ambient(NULL);
1536
1537
return err;
1538
}
1539
1540
__initcall(init_smk_fs);
1541
1542