vserver 1.9.3
[linux-2.6.git] / security / selinux / selinuxfs.c
1 /* Updated: Karl MacMillan <kmacmillan@tresys.com>
2  *
3  *      Added conditional policy language extensions
4  *
5  * Copyright (C) 2003 - 2004 Tresys Technology, LLC
6  *      This program is free software; you can redistribute it and/or modify
7  *      it under the terms of the GNU General Public License as published by
8  *      the Free Software Foundation, version 2.
9  */
10
11 #include <linux/config.h>
12 #include <linux/kernel.h>
13 #include <linux/pagemap.h>
14 #include <linux/slab.h>
15 #include <linux/vmalloc.h>
16 #include <linux/fs.h>
17 #include <linux/init.h>
18 #include <linux/string.h>
19 #include <linux/security.h>
20 #include <linux/major.h>
21 #include <asm/uaccess.h>
22 #include <asm/semaphore.h>
23
24 /* selinuxfs pseudo filesystem for exporting the security policy API.
25    Based on the proc code and the fs/nfsd/nfsctl.c code. */
26
27 #include "flask.h"
28 #include "avc.h"
29 #include "avc_ss.h"
30 #include "security.h"
31 #include "objsec.h"
32 #include "conditional.h"
33
34 static DECLARE_MUTEX(sel_sem);
35
36 /* global data for booleans */
37 static struct dentry *bool_dir = NULL;
38 static int bool_num = 0;
39 static int *bool_pending_values = NULL;
40
41 extern void selnl_notify_setenforce(int val);
42
43 /* Check whether a task is allowed to use a security operation. */
44 int task_has_security(struct task_struct *tsk,
45                       u32 perms)
46 {
47         struct task_security_struct *tsec;
48
49         tsec = tsk->security;
50         if (!tsec)
51                 return -EACCES;
52
53         return avc_has_perm(tsec->sid, SECINITSID_SECURITY,
54                             SECCLASS_SECURITY, perms, NULL, NULL);
55 }
56
57 enum sel_inos {
58         SEL_ROOT_INO = 2,
59         SEL_LOAD,       /* load policy */
60         SEL_ENFORCE,    /* get or set enforcing status */
61         SEL_CONTEXT,    /* validate context */
62         SEL_ACCESS,     /* compute access decision */
63         SEL_CREATE,     /* compute create labeling decision */
64         SEL_RELABEL,    /* compute relabeling decision */
65         SEL_USER,       /* compute reachable user contexts */
66         SEL_POLICYVERS, /* return policy version for this kernel */
67         SEL_COMMIT_BOOLS, /* commit new boolean values */
68         SEL_MLS,        /* return if MLS policy is enabled */
69         SEL_DISABLE     /* disable SELinux until next reboot */
70 };
71
72 #define TMPBUFLEN       12
73 static ssize_t sel_read_enforce(struct file *filp, char __user *buf,
74                                 size_t count, loff_t *ppos)
75 {
76         char tmpbuf[TMPBUFLEN];
77         ssize_t length;
78
79         length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_enforcing);
80         return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
81 }
82
83 #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
84 static ssize_t sel_write_enforce(struct file * file, const char __user * buf,
85                                  size_t count, loff_t *ppos)
86
87 {
88         char *page;
89         ssize_t length;
90         int new_value;
91
92         if (count < 0 || count >= PAGE_SIZE)
93                 return -ENOMEM;
94         if (*ppos != 0) {
95                 /* No partial writes. */
96                 return -EINVAL;
97         }
98         page = (char*)get_zeroed_page(GFP_KERNEL);
99         if (!page)
100                 return -ENOMEM;
101         length = -EFAULT;
102         if (copy_from_user(page, buf, count))
103                 goto out;
104
105         length = -EINVAL;
106         if (sscanf(page, "%d", &new_value) != 1)
107                 goto out;
108
109         if (new_value != selinux_enforcing) {
110                 length = task_has_security(current, SECURITY__SETENFORCE);
111                 if (length)
112                         goto out;
113                 selinux_enforcing = new_value;
114                 if (selinux_enforcing)
115                         avc_ss_reset(0);
116                 selnl_notify_setenforce(selinux_enforcing);
117         }
118         length = count;
119 out:
120         free_page((unsigned long) page);
121         return length;
122 }
123 #else
124 #define sel_write_enforce NULL
125 #endif
126
127 static struct file_operations sel_enforce_ops = {
128         .read           = sel_read_enforce,
129         .write          = sel_write_enforce,
130 };
131
132 #ifdef CONFIG_SECURITY_SELINUX_DISABLE
133 static ssize_t sel_write_disable(struct file * file, const char __user * buf,
134                                  size_t count, loff_t *ppos)
135
136 {
137         char *page;
138         ssize_t length;
139         int new_value;
140         extern int selinux_disable(void);
141
142         if (count < 0 || count >= PAGE_SIZE)
143                 return -ENOMEM;
144         if (*ppos != 0) {
145                 /* No partial writes. */
146                 return -EINVAL;
147         }
148         page = (char*)get_zeroed_page(GFP_KERNEL);
149         if (!page)
150                 return -ENOMEM;
151         length = -EFAULT;
152         if (copy_from_user(page, buf, count))
153                 goto out;
154
155         length = -EINVAL;
156         if (sscanf(page, "%d", &new_value) != 1)
157                 goto out;
158
159         if (new_value) {
160                 length = selinux_disable();
161                 if (length < 0)
162                         goto out;
163         }
164
165         length = count;
166 out:
167         free_page((unsigned long) page);
168         return length;
169 }
170 #else
171 #define sel_write_disable NULL
172 #endif
173
174 static struct file_operations sel_disable_ops = {
175         .write          = sel_write_disable,
176 };
177
178 static ssize_t sel_read_policyvers(struct file *filp, char __user *buf,
179                                    size_t count, loff_t *ppos)
180 {
181         char tmpbuf[TMPBUFLEN];
182         ssize_t length;
183
184         length = scnprintf(tmpbuf, TMPBUFLEN, "%u", POLICYDB_VERSION_MAX);
185         return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
186 }
187
188 static struct file_operations sel_policyvers_ops = {
189         .read           = sel_read_policyvers,
190 };
191
192 /* declaration for sel_write_load */
193 static int sel_make_bools(void);
194
195 static ssize_t sel_read_mls(struct file *filp, char __user *buf,
196                                 size_t count, loff_t *ppos)
197 {
198         char tmpbuf[TMPBUFLEN];
199         ssize_t length;
200
201         length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_mls_enabled);
202         return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
203 }
204
205 static struct file_operations sel_mls_ops = {
206         .read           = sel_read_mls,
207 };
208
209 static ssize_t sel_write_load(struct file * file, const char __user * buf,
210                               size_t count, loff_t *ppos)
211
212 {
213         int ret;
214         ssize_t length;
215         void *data = NULL;
216
217         down(&sel_sem);
218
219         length = task_has_security(current, SECURITY__LOAD_POLICY);
220         if (length)
221                 goto out;
222
223         if (*ppos != 0) {
224                 /* No partial writes. */
225                 length = -EINVAL;
226                 goto out;
227         }
228
229         if ((count < 0) || (count > 64 * 1024 * 1024)
230             || (data = vmalloc(count)) == NULL) {
231                 length = -ENOMEM;
232                 goto out;
233         }
234
235         length = -EFAULT;
236         if (copy_from_user(data, buf, count) != 0)
237                 goto out;
238
239         length = security_load_policy(data, count);
240         if (length)
241                 goto out;
242
243         ret = sel_make_bools();
244         if (ret)
245                 length = ret;
246         else
247                 length = count;
248 out:
249         up(&sel_sem);
250         vfree(data);
251         return length;
252 }
253
254 static struct file_operations sel_load_ops = {
255         .write          = sel_write_load,
256 };
257
258
259 static ssize_t sel_write_context(struct file * file, const char __user * buf,
260                                  size_t count, loff_t *ppos)
261
262 {
263         char *page;
264         u32 sid;
265         ssize_t length;
266
267         length = task_has_security(current, SECURITY__CHECK_CONTEXT);
268         if (length)
269                 return length;
270
271         if (count < 0 || count >= PAGE_SIZE)
272                 return -ENOMEM;
273         if (*ppos != 0) {
274                 /* No partial writes. */
275                 return -EINVAL;
276         }
277         page = (char*)get_zeroed_page(GFP_KERNEL);
278         if (!page)
279                 return -ENOMEM;
280         length = -EFAULT;
281         if (copy_from_user(page, buf, count))
282                 goto out;
283
284         length = security_context_to_sid(page, count, &sid);
285         if (length < 0)
286                 goto out;
287
288         length = count;
289 out:
290         free_page((unsigned long) page);
291         return length;
292 }
293
294 static struct file_operations sel_context_ops = {
295         .write          = sel_write_context,
296 };
297
298
299 /*
300  * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
301  */
302 static ssize_t sel_write_access(struct file * file, char *buf, size_t size);
303 static ssize_t sel_write_create(struct file * file, char *buf, size_t size);
304 static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size);
305 static ssize_t sel_write_user(struct file * file, char *buf, size_t size);
306
307 static ssize_t (*write_op[])(struct file *, char *, size_t) = {
308         [SEL_ACCESS] = sel_write_access,
309         [SEL_CREATE] = sel_write_create,
310         [SEL_RELABEL] = sel_write_relabel,
311         [SEL_USER] = sel_write_user,
312 };
313
314 static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
315 {
316         ino_t ino =  file->f_dentry->d_inode->i_ino;
317         char *data;
318         ssize_t rv;
319
320         if (ino >= sizeof(write_op)/sizeof(write_op[0]) || !write_op[ino])
321                 return -EINVAL;
322
323         data = simple_transaction_get(file, buf, size);
324         if (IS_ERR(data))
325                 return PTR_ERR(data);
326
327         rv =  write_op[ino](file, data, size);
328         if (rv>0) {
329                 simple_transaction_set(file, rv);
330                 rv = size;
331         }
332         return rv;
333 }
334
335 static struct file_operations transaction_ops = {
336         .write          = selinux_transaction_write,
337         .read           = simple_transaction_read,
338         .release        = simple_transaction_release,
339 };
340
341 /*
342  * payload - write methods
343  * If the method has a response, the response should be put in buf,
344  * and the length returned.  Otherwise return 0 or and -error.
345  */
346
347 static ssize_t sel_write_access(struct file * file, char *buf, size_t size)
348 {
349         char *scon, *tcon;
350         u32 ssid, tsid;
351         u16 tclass;
352         u32 req;
353         struct av_decision avd;
354         ssize_t length;
355
356         length = task_has_security(current, SECURITY__COMPUTE_AV);
357         if (length)
358                 return length;
359
360         length = -ENOMEM;
361         scon = kmalloc(size+1, GFP_KERNEL);
362         if (!scon)
363                 return length;
364         memset(scon, 0, size+1);
365
366         tcon = kmalloc(size+1, GFP_KERNEL);
367         if (!tcon)
368                 goto out;
369         memset(tcon, 0, size+1);
370
371         length = -EINVAL;
372         if (sscanf(buf, "%s %s %hu %x", scon, tcon, &tclass, &req) != 4)
373                 goto out2;
374
375         length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
376         if (length < 0)
377                 goto out2;
378         length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
379         if (length < 0)
380                 goto out2;
381
382         length = security_compute_av(ssid, tsid, tclass, req, &avd);
383         if (length < 0)
384                 goto out2;
385
386         length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT,
387                           "%x %x %x %x %u",
388                           avd.allowed, avd.decided,
389                           avd.auditallow, avd.auditdeny,
390                           avd.seqno);
391 out2:
392         kfree(tcon);
393 out:
394         kfree(scon);
395         return length;
396 }
397
398 static ssize_t sel_write_create(struct file * file, char *buf, size_t size)
399 {
400         char *scon, *tcon;
401         u32 ssid, tsid, newsid;
402         u16 tclass;
403         ssize_t length;
404         char *newcon;
405         u32 len;
406
407         length = task_has_security(current, SECURITY__COMPUTE_CREATE);
408         if (length)
409                 return length;
410
411         length = -ENOMEM;
412         scon = kmalloc(size+1, GFP_KERNEL);
413         if (!scon)
414                 return length;
415         memset(scon, 0, size+1);
416
417         tcon = kmalloc(size+1, GFP_KERNEL);
418         if (!tcon)
419                 goto out;
420         memset(tcon, 0, size+1);
421
422         length = -EINVAL;
423         if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
424                 goto out2;
425
426         length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
427         if (length < 0)
428                 goto out2;
429         length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
430         if (length < 0)
431                 goto out2;
432
433         length = security_transition_sid(ssid, tsid, tclass, &newsid);
434         if (length < 0)
435                 goto out2;
436
437         length = security_sid_to_context(newsid, &newcon, &len);
438         if (length < 0)
439                 goto out2;
440
441         if (len > SIMPLE_TRANSACTION_LIMIT) {
442                 printk(KERN_ERR "%s:  context size (%u) exceeds payload "
443                        "max\n", __FUNCTION__, len);
444                 length = -ERANGE;
445                 goto out3;
446         }
447
448         memcpy(buf, newcon, len);
449         length = len;
450 out3:
451         kfree(newcon);
452 out2:
453         kfree(tcon);
454 out:
455         kfree(scon);
456         return length;
457 }
458
459 static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size)
460 {
461         char *scon, *tcon;
462         u32 ssid, tsid, newsid;
463         u16 tclass;
464         ssize_t length;
465         char *newcon;
466         u32 len;
467
468         length = task_has_security(current, SECURITY__COMPUTE_RELABEL);
469         if (length)
470                 return length;
471
472         length = -ENOMEM;
473         scon = kmalloc(size+1, GFP_KERNEL);
474         if (!scon)
475                 return length;
476         memset(scon, 0, size+1);
477
478         tcon = kmalloc(size+1, GFP_KERNEL);
479         if (!tcon)
480                 goto out;
481         memset(tcon, 0, size+1);
482
483         length = -EINVAL;
484         if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
485                 goto out2;
486
487         length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
488         if (length < 0)
489                 goto out2;
490         length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
491         if (length < 0)
492                 goto out2;
493
494         length = security_change_sid(ssid, tsid, tclass, &newsid);
495         if (length < 0)
496                 goto out2;
497
498         length = security_sid_to_context(newsid, &newcon, &len);
499         if (length < 0)
500                 goto out2;
501
502         if (len > SIMPLE_TRANSACTION_LIMIT) {
503                 length = -ERANGE;
504                 goto out3;
505         }
506
507         memcpy(buf, newcon, len);
508         length = len;
509 out3:
510         kfree(newcon);
511 out2:
512         kfree(tcon);
513 out:
514         kfree(scon);
515         return length;
516 }
517
518 static ssize_t sel_write_user(struct file * file, char *buf, size_t size)
519 {
520         char *con, *user, *ptr;
521         u32 sid, *sids;
522         ssize_t length;
523         char *newcon;
524         int i, rc;
525         u32 len, nsids;
526
527         length = task_has_security(current, SECURITY__COMPUTE_USER);
528         if (length)
529                 return length;
530
531         length = -ENOMEM;
532         con = kmalloc(size+1, GFP_KERNEL);
533         if (!con)
534                 return length;
535         memset(con, 0, size+1);
536
537         user = kmalloc(size+1, GFP_KERNEL);
538         if (!user)
539                 goto out;
540         memset(user, 0, size+1);
541
542         length = -EINVAL;
543         if (sscanf(buf, "%s %s", con, user) != 2)
544                 goto out2;
545
546         length = security_context_to_sid(con, strlen(con)+1, &sid);
547         if (length < 0)
548                 goto out2;
549
550         length = security_get_user_sids(sid, user, &sids, &nsids);
551         if (length < 0)
552                 goto out2;
553
554         length = sprintf(buf, "%u", nsids) + 1;
555         ptr = buf + length;
556         for (i = 0; i < nsids; i++) {
557                 rc = security_sid_to_context(sids[i], &newcon, &len);
558                 if (rc) {
559                         length = rc;
560                         goto out3;
561                 }
562                 if ((length + len) >= SIMPLE_TRANSACTION_LIMIT) {
563                         kfree(newcon);
564                         length = -ERANGE;
565                         goto out3;
566                 }
567                 memcpy(ptr, newcon, len);
568                 kfree(newcon);
569                 ptr += len;
570                 length += len;
571         }
572 out3:
573         kfree(sids);
574 out2:
575         kfree(user);
576 out:
577         kfree(con);
578         return length;
579 }
580
581 static struct inode *sel_make_inode(struct super_block *sb, int mode)
582 {
583         struct inode *ret = new_inode(sb);
584
585         if (ret) {
586                 ret->i_mode = mode;
587                 ret->i_uid = ret->i_gid = 0;
588                 ret->i_blksize = PAGE_CACHE_SIZE;
589                 ret->i_blocks = 0;
590                 ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
591         }
592         return ret;
593 }
594
595 #define BOOL_INO_OFFSET 30
596
597 static ssize_t sel_read_bool(struct file *filep, char __user *buf,
598                              size_t count, loff_t *ppos)
599 {
600         char *page = NULL;
601         ssize_t length;
602         ssize_t end;
603         ssize_t ret;
604         int cur_enforcing;
605         struct inode *inode;
606
607         down(&sel_sem);
608
609         ret = -EFAULT;
610
611         /* check to see if this file has been deleted */
612         if (!filep->f_op)
613                 goto out;
614
615         if (count < 0 || count > PAGE_SIZE) {
616                 ret = -EINVAL;
617                 goto out;
618         }
619         if (!(page = (char*)get_zeroed_page(GFP_KERNEL))) {
620                 ret = -ENOMEM;
621                 goto out;
622         }
623
624         inode = filep->f_dentry->d_inode;
625         cur_enforcing = security_get_bool_value(inode->i_ino - BOOL_INO_OFFSET);
626         if (cur_enforcing < 0) {
627                 ret = cur_enforcing;
628                 goto out;
629         }
630
631         length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,
632                           bool_pending_values[inode->i_ino - BOOL_INO_OFFSET]);
633         if (length < 0) {
634                 ret = length;
635                 goto out;
636         }
637
638         if (*ppos >= length) {
639                 ret = 0;
640                 goto out;
641         }
642         if (count + *ppos > length)
643                 count = length - *ppos;
644         end = count + *ppos;
645         if (copy_to_user(buf, (char *) page + *ppos, count)) {
646                 ret = -EFAULT;
647                 goto out;
648         }
649         *ppos = end;
650         ret = count;
651 out:
652         up(&sel_sem);
653         if (page)
654                 free_page((unsigned long)page);
655         return ret;
656 }
657
658 static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
659                               size_t count, loff_t *ppos)
660 {
661         char *page = NULL;
662         ssize_t length = -EFAULT;
663         int new_value;
664         struct inode *inode;
665
666         down(&sel_sem);
667
668         length = task_has_security(current, SECURITY__SETBOOL);
669         if (length)
670                 goto out;
671
672         /* check to see if this file has been deleted */
673         if (!filep->f_op)
674                 goto out;
675
676         if (count < 0 || count >= PAGE_SIZE) {
677                 length = -ENOMEM;
678                 goto out;
679         }
680         if (*ppos != 0) {
681                 /* No partial writes. */
682                 goto out;
683         }
684         page = (char*)get_zeroed_page(GFP_KERNEL);
685         if (!page) {
686                 length = -ENOMEM;
687                 goto out;
688         }
689
690         if (copy_from_user(page, buf, count))
691                 goto out;
692
693         length = -EINVAL;
694         if (sscanf(page, "%d", &new_value) != 1)
695                 goto out;
696
697         if (new_value)
698                 new_value = 1;
699
700         inode = filep->f_dentry->d_inode;
701         bool_pending_values[inode->i_ino - BOOL_INO_OFFSET] = new_value;
702         length = count;
703
704 out:
705         up(&sel_sem);
706         if (page)
707                 free_page((unsigned long) page);
708         return length;
709 }
710
711 static struct file_operations sel_bool_ops = {
712         .read           = sel_read_bool,
713         .write          = sel_write_bool,
714 };
715
716 static ssize_t sel_commit_bools_write(struct file *filep,
717                                       const char __user *buf,
718                                       size_t count, loff_t *ppos)
719 {
720         char *page = NULL;
721         ssize_t length = -EFAULT;
722         int new_value;
723
724         down(&sel_sem);
725
726         length = task_has_security(current, SECURITY__SETBOOL);
727         if (length)
728                 goto out;
729
730         /* check to see if this file has been deleted */
731         if (!filep->f_op)
732                 goto out;
733
734         if (count < 0 || count >= PAGE_SIZE) {
735                 length = -ENOMEM;
736                 goto out;
737         }
738         if (*ppos != 0) {
739                 /* No partial writes. */
740                 goto out;
741         }
742         page = (char*)get_zeroed_page(GFP_KERNEL);
743         if (!page) {
744                 length = -ENOMEM;
745                 goto out;
746         }
747
748         if (copy_from_user(page, buf, count))
749                 goto out;
750
751         length = -EINVAL;
752         if (sscanf(page, "%d", &new_value) != 1)
753                 goto out;
754
755         if (new_value) {
756                 security_set_bools(bool_num, bool_pending_values);
757         }
758
759         length = count;
760
761 out:
762         up(&sel_sem);
763         if (page)
764                 free_page((unsigned long) page);
765         return length;
766 }
767
768 static struct file_operations sel_commit_bools_ops = {
769         .write          = sel_commit_bools_write,
770 };
771
772 /* delete booleans - partial revoke() from
773  * fs/proc/generic.c proc_kill_inodes */
774 static void sel_remove_bools(struct dentry *de)
775 {
776         struct list_head *p, *node;
777         struct super_block *sb = de->d_sb;
778
779         spin_lock(&dcache_lock);
780         node = de->d_subdirs.next;
781         while (node != &de->d_subdirs) {
782                 struct dentry *d = list_entry(node, struct dentry, d_child);
783                 list_del_init(node);
784
785                 if (d->d_inode) {
786                         d = dget_locked(d);
787                         spin_unlock(&dcache_lock);
788                         d_delete(d);
789                         simple_unlink(de->d_inode, d);
790                         dput(d);
791                         spin_lock(&dcache_lock);
792                 }
793                 node = de->d_subdirs.next;
794         }
795
796         spin_unlock(&dcache_lock);
797
798         file_list_lock();
799         list_for_each(p, &sb->s_files) {
800                 struct file * filp = list_entry(p, struct file, f_list);
801                 struct dentry * dentry = filp->f_dentry;
802
803                 if (dentry->d_parent != de) {
804                         continue;
805                 }
806                 filp->f_op = NULL;
807         }
808         file_list_unlock();
809 }
810
811 #define BOOL_DIR_NAME "booleans"
812
813 static int sel_make_bools(void)
814 {
815         int i, ret = 0;
816         ssize_t len;
817         struct dentry *dentry = NULL;
818         struct dentry *dir = bool_dir;
819         struct inode *inode = NULL;
820         struct inode_security_struct *isec;
821         struct qstr qname;
822         char **names = NULL, *page;
823         int num;
824         int *values = NULL;
825         u32 sid;
826
827         /* remove any existing files */
828         if (bool_pending_values)
829                 kfree(bool_pending_values);
830
831         sel_remove_bools(dir);
832
833         if (!(page = (char*)get_zeroed_page(GFP_KERNEL)))
834                 return -ENOMEM;
835
836         ret = security_get_bools(&num, &names, &values);
837         if (ret != 0)
838                 goto out;
839
840         for (i = 0; i < num; i++) {
841                 qname.name = names[i];
842                 qname.len = strlen(qname.name);
843                 qname.hash = full_name_hash(qname.name, qname.len);
844                 dentry = d_alloc(dir, &qname);
845                 if (!dentry) {
846                         ret = -ENOMEM;
847                         goto err;
848                 }
849                 inode = sel_make_inode(dir->d_sb, S_IFREG | S_IRUGO | S_IWUSR);
850                 if (!inode) {
851                         ret = -ENOMEM;
852                         goto err;
853                 }
854
855                 len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]);
856                 if (len < 0) {
857                         ret = -EINVAL;
858                         goto err;
859                 } else if (len >= PAGE_SIZE) {
860                         ret = -ENAMETOOLONG;
861                         goto err;
862                 }
863                 isec = (struct inode_security_struct*)inode->i_security;
864                 if ((ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid)))
865                         goto err;
866                 isec->sid = sid;
867                 isec->initialized = 1;
868                 inode->i_fop = &sel_bool_ops;
869                 inode->i_ino = i + BOOL_INO_OFFSET;
870                 d_add(dentry, inode);
871         }
872         bool_num = num;
873         bool_pending_values = values;
874 out:
875         free_page((unsigned long)page);
876         if (names) {
877                 for (i = 0; i < num; i++) {
878                         if (names[i])
879                                 kfree(names[i]);
880                 }
881                 kfree(names);
882         }
883         return ret;
884 err:
885         d_genocide(dir);
886         ret = -ENOMEM;
887         goto out;
888 }
889
890 #define NULL_FILE_NAME "null"
891
892 struct dentry *selinux_null = NULL;
893
894 static int sel_fill_super(struct super_block * sb, void * data, int silent)
895 {
896         int ret;
897         struct dentry *dentry;
898         struct inode *inode;
899         struct qstr qname;
900         struct inode_security_struct *isec;
901
902         static struct tree_descr selinux_files[] = {
903                 [SEL_LOAD] = {"load", &sel_load_ops, S_IRUSR|S_IWUSR},
904                 [SEL_ENFORCE] = {"enforce", &sel_enforce_ops, S_IRUGO|S_IWUSR},
905                 [SEL_CONTEXT] = {"context", &sel_context_ops, S_IRUGO|S_IWUGO},
906                 [SEL_ACCESS] = {"access", &transaction_ops, S_IRUGO|S_IWUGO},
907                 [SEL_CREATE] = {"create", &transaction_ops, S_IRUGO|S_IWUGO},
908                 [SEL_RELABEL] = {"relabel", &transaction_ops, S_IRUGO|S_IWUGO},
909                 [SEL_USER] = {"user", &transaction_ops, S_IRUGO|S_IWUGO},
910                 [SEL_POLICYVERS] = {"policyvers", &sel_policyvers_ops, S_IRUGO},
911                 [SEL_COMMIT_BOOLS] = {"commit_pending_bools", &sel_commit_bools_ops, S_IWUSR},
912                 [SEL_MLS] = {"mls", &sel_mls_ops, S_IRUGO},
913                 [SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR},
914                 /* last one */ {""}
915         };
916         ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
917         if (ret)
918                 return ret;
919
920         qname.name = BOOL_DIR_NAME;
921         qname.len = strlen(qname.name);
922         qname.hash = full_name_hash(qname.name, qname.len);
923         dentry = d_alloc(sb->s_root, &qname);
924         if (!dentry)
925                 return -ENOMEM;
926
927         inode = sel_make_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO);
928         if (!inode)
929                 goto out;
930         inode->i_op = &simple_dir_inode_operations;
931         inode->i_fop = &simple_dir_operations;
932         d_add(dentry, inode);
933         bool_dir = dentry;
934         ret = sel_make_bools();
935         if (ret)
936                 goto out;
937
938         qname.name = NULL_FILE_NAME;
939         qname.len = strlen(qname.name);
940         qname.hash = full_name_hash(qname.name, qname.len);
941         dentry = d_alloc(sb->s_root, &qname);
942         if (!dentry)
943                 return -ENOMEM;
944
945         inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO);
946         if (!inode)
947                 goto out;
948         isec = (struct inode_security_struct*)inode->i_security;
949         isec->sid = SECINITSID_DEVNULL;
950         isec->sclass = SECCLASS_CHR_FILE;
951         isec->initialized = 1;
952
953         init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3));
954         d_add(dentry, inode);
955         selinux_null = dentry;
956
957         return 0;
958 out:
959         dput(dentry);
960         printk(KERN_ERR "%s:  failed while creating inodes\n", __FUNCTION__);
961         return -ENOMEM;
962 }
963
964 static struct super_block *sel_get_sb(struct file_system_type *fs_type,
965                                       int flags, const char *dev_name, void *data)
966 {
967         return get_sb_single(fs_type, flags, data, sel_fill_super);
968 }
969
970 static struct file_system_type sel_fs_type = {
971         .name           = "selinuxfs",
972         .get_sb         = sel_get_sb,
973         .kill_sb        = kill_litter_super,
974 };
975
976 struct vfsmount *selinuxfs_mount;
977
978 static int __init init_sel_fs(void)
979 {
980         int err;
981
982         if (!selinux_enabled)
983                 return 0;
984         err = register_filesystem(&sel_fs_type);
985         if (!err) {
986                 selinuxfs_mount = kern_mount(&sel_fs_type);
987                 if (IS_ERR(selinuxfs_mount)) {
988                         printk(KERN_ERR "selinuxfs:  could not mount!\n");
989                         err = PTR_ERR(selinuxfs_mount);
990                         selinuxfs_mount = NULL;
991                 }
992         }
993         return err;
994 }
995
996 __initcall(init_sel_fs);
997
998 #ifdef CONFIG_SECURITY_SELINUX_DISABLE
999 void exit_sel_fs(void)
1000 {
1001         unregister_filesystem(&sel_fs_type);
1002 }
1003 #endif