vserver 1.9.5.x5
[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  * Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
7  *      This program is free software; you can redistribute it and/or modify
8  *      it under the terms of the GNU General Public License as published by
9  *      the Free Software Foundation, version 2.
10  */
11
12 #include <linux/config.h>
13 #include <linux/kernel.h>
14 #include <linux/pagemap.h>
15 #include <linux/slab.h>
16 #include <linux/vmalloc.h>
17 #include <linux/fs.h>
18 #include <linux/init.h>
19 #include <linux/string.h>
20 #include <linux/security.h>
21 #include <linux/major.h>
22 #include <linux/seq_file.h>
23 #include <linux/percpu.h>
24 #include <asm/uaccess.h>
25 #include <asm/semaphore.h>
26
27 /* selinuxfs pseudo filesystem for exporting the security policy API.
28    Based on the proc code and the fs/nfsd/nfsctl.c code. */
29
30 #include "flask.h"
31 #include "avc.h"
32 #include "avc_ss.h"
33 #include "security.h"
34 #include "objsec.h"
35 #include "conditional.h"
36
37 static DECLARE_MUTEX(sel_sem);
38
39 /* global data for booleans */
40 static struct dentry *bool_dir = NULL;
41 static int bool_num = 0;
42 static int *bool_pending_values = NULL;
43
44 extern void selnl_notify_setenforce(int val);
45
46 /* Check whether a task is allowed to use a security operation. */
47 int task_has_security(struct task_struct *tsk,
48                       u32 perms)
49 {
50         struct task_security_struct *tsec;
51
52         tsec = tsk->security;
53         if (!tsec)
54                 return -EACCES;
55
56         return avc_has_perm(tsec->sid, SECINITSID_SECURITY,
57                             SECCLASS_SECURITY, perms, NULL);
58 }
59
60 enum sel_inos {
61         SEL_ROOT_INO = 2,
62         SEL_LOAD,       /* load policy */
63         SEL_ENFORCE,    /* get or set enforcing status */
64         SEL_CONTEXT,    /* validate context */
65         SEL_ACCESS,     /* compute access decision */
66         SEL_CREATE,     /* compute create labeling decision */
67         SEL_RELABEL,    /* compute relabeling decision */
68         SEL_USER,       /* compute reachable user contexts */
69         SEL_POLICYVERS, /* return policy version for this kernel */
70         SEL_COMMIT_BOOLS, /* commit new boolean values */
71         SEL_MLS,        /* return if MLS policy is enabled */
72         SEL_DISABLE,    /* disable SELinux until next reboot */
73         SEL_AVC,        /* AVC management directory */
74         SEL_MEMBER,     /* compute polyinstantiation membership decision */
75 };
76
77 #define TMPBUFLEN       12
78 static ssize_t sel_read_enforce(struct file *filp, char __user *buf,
79                                 size_t count, loff_t *ppos)
80 {
81         char tmpbuf[TMPBUFLEN];
82         ssize_t length;
83
84         length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_enforcing);
85         return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
86 }
87
88 #ifdef CONFIG_SECURITY_SELINUX_DEVELOP
89 static ssize_t sel_write_enforce(struct file * file, const char __user * buf,
90                                  size_t count, loff_t *ppos)
91
92 {
93         char *page;
94         ssize_t length;
95         int new_value;
96
97         if (count < 0 || count >= PAGE_SIZE)
98                 return -ENOMEM;
99         if (*ppos != 0) {
100                 /* No partial writes. */
101                 return -EINVAL;
102         }
103         page = (char*)get_zeroed_page(GFP_KERNEL);
104         if (!page)
105                 return -ENOMEM;
106         length = -EFAULT;
107         if (copy_from_user(page, buf, count))
108                 goto out;
109
110         length = -EINVAL;
111         if (sscanf(page, "%d", &new_value) != 1)
112                 goto out;
113
114         if (new_value != selinux_enforcing) {
115                 length = task_has_security(current, SECURITY__SETENFORCE);
116                 if (length)
117                         goto out;
118                 selinux_enforcing = new_value;
119                 if (selinux_enforcing)
120                         avc_ss_reset(0);
121                 selnl_notify_setenforce(selinux_enforcing);
122         }
123         length = count;
124 out:
125         free_page((unsigned long) page);
126         return length;
127 }
128 #else
129 #define sel_write_enforce NULL
130 #endif
131
132 static struct file_operations sel_enforce_ops = {
133         .read           = sel_read_enforce,
134         .write          = sel_write_enforce,
135 };
136
137 #ifdef CONFIG_SECURITY_SELINUX_DISABLE
138 static ssize_t sel_write_disable(struct file * file, const char __user * buf,
139                                  size_t count, loff_t *ppos)
140
141 {
142         char *page;
143         ssize_t length;
144         int new_value;
145         extern int selinux_disable(void);
146
147         if (count < 0 || count >= PAGE_SIZE)
148                 return -ENOMEM;
149         if (*ppos != 0) {
150                 /* No partial writes. */
151                 return -EINVAL;
152         }
153         page = (char*)get_zeroed_page(GFP_KERNEL);
154         if (!page)
155                 return -ENOMEM;
156         length = -EFAULT;
157         if (copy_from_user(page, buf, count))
158                 goto out;
159
160         length = -EINVAL;
161         if (sscanf(page, "%d", &new_value) != 1)
162                 goto out;
163
164         if (new_value) {
165                 length = selinux_disable();
166                 if (length < 0)
167                         goto out;
168         }
169
170         length = count;
171 out:
172         free_page((unsigned long) page);
173         return length;
174 }
175 #else
176 #define sel_write_disable NULL
177 #endif
178
179 static struct file_operations sel_disable_ops = {
180         .write          = sel_write_disable,
181 };
182
183 static ssize_t sel_read_policyvers(struct file *filp, char __user *buf,
184                                    size_t count, loff_t *ppos)
185 {
186         char tmpbuf[TMPBUFLEN];
187         ssize_t length;
188
189         length = scnprintf(tmpbuf, TMPBUFLEN, "%u", POLICYDB_VERSION_MAX);
190         return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
191 }
192
193 static struct file_operations sel_policyvers_ops = {
194         .read           = sel_read_policyvers,
195 };
196
197 /* declaration for sel_write_load */
198 static int sel_make_bools(void);
199
200 static ssize_t sel_read_mls(struct file *filp, char __user *buf,
201                                 size_t count, loff_t *ppos)
202 {
203         char tmpbuf[TMPBUFLEN];
204         ssize_t length;
205
206         length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_mls_enabled);
207         return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
208 }
209
210 static struct file_operations sel_mls_ops = {
211         .read           = sel_read_mls,
212 };
213
214 static ssize_t sel_write_load(struct file * file, const char __user * buf,
215                               size_t count, loff_t *ppos)
216
217 {
218         int ret;
219         ssize_t length;
220         void *data = NULL;
221
222         down(&sel_sem);
223
224         length = task_has_security(current, SECURITY__LOAD_POLICY);
225         if (length)
226                 goto out;
227
228         if (*ppos != 0) {
229                 /* No partial writes. */
230                 length = -EINVAL;
231                 goto out;
232         }
233
234         if ((count < 0) || (count > 64 * 1024 * 1024)
235             || (data = vmalloc(count)) == NULL) {
236                 length = -ENOMEM;
237                 goto out;
238         }
239
240         length = -EFAULT;
241         if (copy_from_user(data, buf, count) != 0)
242                 goto out;
243
244         length = security_load_policy(data, count);
245         if (length)
246                 goto out;
247
248         ret = sel_make_bools();
249         if (ret)
250                 length = ret;
251         else
252                 length = count;
253 out:
254         up(&sel_sem);
255         vfree(data);
256         return length;
257 }
258
259 static struct file_operations sel_load_ops = {
260         .write          = sel_write_load,
261 };
262
263
264 static ssize_t sel_write_context(struct file * file, const char __user * buf,
265                                  size_t count, loff_t *ppos)
266
267 {
268         char *page;
269         u32 sid;
270         ssize_t length;
271
272         length = task_has_security(current, SECURITY__CHECK_CONTEXT);
273         if (length)
274                 return length;
275
276         if (count < 0 || count >= PAGE_SIZE)
277                 return -ENOMEM;
278         if (*ppos != 0) {
279                 /* No partial writes. */
280                 return -EINVAL;
281         }
282         page = (char*)get_zeroed_page(GFP_KERNEL);
283         if (!page)
284                 return -ENOMEM;
285         length = -EFAULT;
286         if (copy_from_user(page, buf, count))
287                 goto out;
288
289         length = security_context_to_sid(page, count, &sid);
290         if (length < 0)
291                 goto out;
292
293         length = count;
294 out:
295         free_page((unsigned long) page);
296         return length;
297 }
298
299 static struct file_operations sel_context_ops = {
300         .write          = sel_write_context,
301 };
302
303
304 /*
305  * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
306  */
307 static ssize_t sel_write_access(struct file * file, char *buf, size_t size);
308 static ssize_t sel_write_create(struct file * file, char *buf, size_t size);
309 static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size);
310 static ssize_t sel_write_user(struct file * file, char *buf, size_t size);
311 static ssize_t sel_write_member(struct file * file, char *buf, size_t size);
312
313 static ssize_t (*write_op[])(struct file *, char *, size_t) = {
314         [SEL_ACCESS] = sel_write_access,
315         [SEL_CREATE] = sel_write_create,
316         [SEL_RELABEL] = sel_write_relabel,
317         [SEL_USER] = sel_write_user,
318         [SEL_MEMBER] = sel_write_member,
319 };
320
321 static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
322 {
323         ino_t ino =  file->f_dentry->d_inode->i_ino;
324         char *data;
325         ssize_t rv;
326
327         if (ino >= sizeof(write_op)/sizeof(write_op[0]) || !write_op[ino])
328                 return -EINVAL;
329
330         data = simple_transaction_get(file, buf, size);
331         if (IS_ERR(data))
332                 return PTR_ERR(data);
333
334         rv =  write_op[ino](file, data, size);
335         if (rv>0) {
336                 simple_transaction_set(file, rv);
337                 rv = size;
338         }
339         return rv;
340 }
341
342 static struct file_operations transaction_ops = {
343         .write          = selinux_transaction_write,
344         .read           = simple_transaction_read,
345         .release        = simple_transaction_release,
346 };
347
348 /*
349  * payload - write methods
350  * If the method has a response, the response should be put in buf,
351  * and the length returned.  Otherwise return 0 or and -error.
352  */
353
354 static ssize_t sel_write_access(struct file * file, char *buf, size_t size)
355 {
356         char *scon, *tcon;
357         u32 ssid, tsid;
358         u16 tclass;
359         u32 req;
360         struct av_decision avd;
361         ssize_t length;
362
363         length = task_has_security(current, SECURITY__COMPUTE_AV);
364         if (length)
365                 return length;
366
367         length = -ENOMEM;
368         scon = kmalloc(size+1, GFP_KERNEL);
369         if (!scon)
370                 return length;
371         memset(scon, 0, size+1);
372
373         tcon = kmalloc(size+1, GFP_KERNEL);
374         if (!tcon)
375                 goto out;
376         memset(tcon, 0, size+1);
377
378         length = -EINVAL;
379         if (sscanf(buf, "%s %s %hu %x", scon, tcon, &tclass, &req) != 4)
380                 goto out2;
381
382         length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
383         if (length < 0)
384                 goto out2;
385         length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
386         if (length < 0)
387                 goto out2;
388
389         length = security_compute_av(ssid, tsid, tclass, req, &avd);
390         if (length < 0)
391                 goto out2;
392
393         length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT,
394                           "%x %x %x %x %u",
395                           avd.allowed, avd.decided,
396                           avd.auditallow, avd.auditdeny,
397                           avd.seqno);
398 out2:
399         kfree(tcon);
400 out:
401         kfree(scon);
402         return length;
403 }
404
405 static ssize_t sel_write_create(struct file * file, char *buf, size_t size)
406 {
407         char *scon, *tcon;
408         u32 ssid, tsid, newsid;
409         u16 tclass;
410         ssize_t length;
411         char *newcon;
412         u32 len;
413
414         length = task_has_security(current, SECURITY__COMPUTE_CREATE);
415         if (length)
416                 return length;
417
418         length = -ENOMEM;
419         scon = kmalloc(size+1, GFP_KERNEL);
420         if (!scon)
421                 return length;
422         memset(scon, 0, size+1);
423
424         tcon = kmalloc(size+1, GFP_KERNEL);
425         if (!tcon)
426                 goto out;
427         memset(tcon, 0, size+1);
428
429         length = -EINVAL;
430         if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
431                 goto out2;
432
433         length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
434         if (length < 0)
435                 goto out2;
436         length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
437         if (length < 0)
438                 goto out2;
439
440         length = security_transition_sid(ssid, tsid, tclass, &newsid);
441         if (length < 0)
442                 goto out2;
443
444         length = security_sid_to_context(newsid, &newcon, &len);
445         if (length < 0)
446                 goto out2;
447
448         if (len > SIMPLE_TRANSACTION_LIMIT) {
449                 printk(KERN_ERR "%s:  context size (%u) exceeds payload "
450                        "max\n", __FUNCTION__, len);
451                 length = -ERANGE;
452                 goto out3;
453         }
454
455         memcpy(buf, newcon, len);
456         length = len;
457 out3:
458         kfree(newcon);
459 out2:
460         kfree(tcon);
461 out:
462         kfree(scon);
463         return length;
464 }
465
466 static ssize_t sel_write_relabel(struct file * file, char *buf, size_t size)
467 {
468         char *scon, *tcon;
469         u32 ssid, tsid, newsid;
470         u16 tclass;
471         ssize_t length;
472         char *newcon;
473         u32 len;
474
475         length = task_has_security(current, SECURITY__COMPUTE_RELABEL);
476         if (length)
477                 return length;
478
479         length = -ENOMEM;
480         scon = kmalloc(size+1, GFP_KERNEL);
481         if (!scon)
482                 return length;
483         memset(scon, 0, size+1);
484
485         tcon = kmalloc(size+1, GFP_KERNEL);
486         if (!tcon)
487                 goto out;
488         memset(tcon, 0, size+1);
489
490         length = -EINVAL;
491         if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
492                 goto out2;
493
494         length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
495         if (length < 0)
496                 goto out2;
497         length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
498         if (length < 0)
499                 goto out2;
500
501         length = security_change_sid(ssid, tsid, tclass, &newsid);
502         if (length < 0)
503                 goto out2;
504
505         length = security_sid_to_context(newsid, &newcon, &len);
506         if (length < 0)
507                 goto out2;
508
509         if (len > SIMPLE_TRANSACTION_LIMIT) {
510                 length = -ERANGE;
511                 goto out3;
512         }
513
514         memcpy(buf, newcon, len);
515         length = len;
516 out3:
517         kfree(newcon);
518 out2:
519         kfree(tcon);
520 out:
521         kfree(scon);
522         return length;
523 }
524
525 static ssize_t sel_write_user(struct file * file, char *buf, size_t size)
526 {
527         char *con, *user, *ptr;
528         u32 sid, *sids;
529         ssize_t length;
530         char *newcon;
531         int i, rc;
532         u32 len, nsids;
533
534         length = task_has_security(current, SECURITY__COMPUTE_USER);
535         if (length)
536                 return length;
537
538         length = -ENOMEM;
539         con = kmalloc(size+1, GFP_KERNEL);
540         if (!con)
541                 return length;
542         memset(con, 0, size+1);
543
544         user = kmalloc(size+1, GFP_KERNEL);
545         if (!user)
546                 goto out;
547         memset(user, 0, size+1);
548
549         length = -EINVAL;
550         if (sscanf(buf, "%s %s", con, user) != 2)
551                 goto out2;
552
553         length = security_context_to_sid(con, strlen(con)+1, &sid);
554         if (length < 0)
555                 goto out2;
556
557         length = security_get_user_sids(sid, user, &sids, &nsids);
558         if (length < 0)
559                 goto out2;
560
561         length = sprintf(buf, "%u", nsids) + 1;
562         ptr = buf + length;
563         for (i = 0; i < nsids; i++) {
564                 rc = security_sid_to_context(sids[i], &newcon, &len);
565                 if (rc) {
566                         length = rc;
567                         goto out3;
568                 }
569                 if ((length + len) >= SIMPLE_TRANSACTION_LIMIT) {
570                         kfree(newcon);
571                         length = -ERANGE;
572                         goto out3;
573                 }
574                 memcpy(ptr, newcon, len);
575                 kfree(newcon);
576                 ptr += len;
577                 length += len;
578         }
579 out3:
580         kfree(sids);
581 out2:
582         kfree(user);
583 out:
584         kfree(con);
585         return length;
586 }
587
588 static ssize_t sel_write_member(struct file * file, char *buf, size_t size)
589 {
590         char *scon, *tcon;
591         u32 ssid, tsid, newsid;
592         u16 tclass;
593         ssize_t length;
594         char *newcon;
595         u32 len;
596
597         length = task_has_security(current, SECURITY__COMPUTE_MEMBER);
598         if (length)
599                 return length;
600
601         length = -ENOMEM;
602         scon = kmalloc(size+1, GFP_KERNEL);
603         if (!scon)
604                 return length;
605         memset(scon, 0, size+1);
606
607         tcon = kmalloc(size+1, GFP_KERNEL);
608         if (!tcon)
609                 goto out;
610         memset(tcon, 0, size+1);
611
612         length = -EINVAL;
613         if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
614                 goto out2;
615
616         length = security_context_to_sid(scon, strlen(scon)+1, &ssid);
617         if (length < 0)
618                 goto out2;
619         length = security_context_to_sid(tcon, strlen(tcon)+1, &tsid);
620         if (length < 0)
621                 goto out2;
622
623         length = security_member_sid(ssid, tsid, tclass, &newsid);
624         if (length < 0)
625                 goto out2;
626
627         length = security_sid_to_context(newsid, &newcon, &len);
628         if (length < 0)
629                 goto out2;
630
631         if (len > SIMPLE_TRANSACTION_LIMIT) {
632                 printk(KERN_ERR "%s:  context size (%u) exceeds payload "
633                        "max\n", __FUNCTION__, len);
634                 length = -ERANGE;
635                 goto out3;
636         }
637
638         memcpy(buf, newcon, len);
639         length = len;
640 out3:
641         kfree(newcon);
642 out2:
643         kfree(tcon);
644 out:
645         kfree(scon);
646         return length;
647 }
648
649 static struct inode *sel_make_inode(struct super_block *sb, int mode)
650 {
651         struct inode *ret = new_inode(sb);
652
653         if (ret) {
654                 ret->i_mode = mode;
655                 ret->i_uid = ret->i_gid = 0;
656                 ret->i_blksize = PAGE_CACHE_SIZE;
657                 ret->i_blocks = 0;
658                 ret->i_atime = ret->i_mtime = ret->i_ctime = CURRENT_TIME;
659         }
660         return ret;
661 }
662
663 #define BOOL_INO_OFFSET 30
664
665 static ssize_t sel_read_bool(struct file *filep, char __user *buf,
666                              size_t count, loff_t *ppos)
667 {
668         char *page = NULL;
669         ssize_t length;
670         ssize_t end;
671         ssize_t ret;
672         int cur_enforcing;
673         struct inode *inode;
674
675         down(&sel_sem);
676
677         ret = -EFAULT;
678
679         /* check to see if this file has been deleted */
680         if (!filep->f_op)
681                 goto out;
682
683         if (count < 0 || count > PAGE_SIZE) {
684                 ret = -EINVAL;
685                 goto out;
686         }
687         if (!(page = (char*)get_zeroed_page(GFP_KERNEL))) {
688                 ret = -ENOMEM;
689                 goto out;
690         }
691
692         inode = filep->f_dentry->d_inode;
693         cur_enforcing = security_get_bool_value(inode->i_ino - BOOL_INO_OFFSET);
694         if (cur_enforcing < 0) {
695                 ret = cur_enforcing;
696                 goto out;
697         }
698
699         length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,
700                           bool_pending_values[inode->i_ino - BOOL_INO_OFFSET]);
701         if (length < 0) {
702                 ret = length;
703                 goto out;
704         }
705
706         if (*ppos >= length) {
707                 ret = 0;
708                 goto out;
709         }
710         if (count + *ppos > length)
711                 count = length - *ppos;
712         end = count + *ppos;
713         if (copy_to_user(buf, (char *) page + *ppos, count)) {
714                 ret = -EFAULT;
715                 goto out;
716         }
717         *ppos = end;
718         ret = count;
719 out:
720         up(&sel_sem);
721         if (page)
722                 free_page((unsigned long)page);
723         return ret;
724 }
725
726 static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
727                               size_t count, loff_t *ppos)
728 {
729         char *page = NULL;
730         ssize_t length = -EFAULT;
731         int new_value;
732         struct inode *inode;
733
734         down(&sel_sem);
735
736         length = task_has_security(current, SECURITY__SETBOOL);
737         if (length)
738                 goto out;
739
740         /* check to see if this file has been deleted */
741         if (!filep->f_op)
742                 goto out;
743
744         if (count < 0 || count >= PAGE_SIZE) {
745                 length = -ENOMEM;
746                 goto out;
747         }
748         if (*ppos != 0) {
749                 /* No partial writes. */
750                 goto out;
751         }
752         page = (char*)get_zeroed_page(GFP_KERNEL);
753         if (!page) {
754                 length = -ENOMEM;
755                 goto out;
756         }
757
758         if (copy_from_user(page, buf, count))
759                 goto out;
760
761         length = -EINVAL;
762         if (sscanf(page, "%d", &new_value) != 1)
763                 goto out;
764
765         if (new_value)
766                 new_value = 1;
767
768         inode = filep->f_dentry->d_inode;
769         bool_pending_values[inode->i_ino - BOOL_INO_OFFSET] = new_value;
770         length = count;
771
772 out:
773         up(&sel_sem);
774         if (page)
775                 free_page((unsigned long) page);
776         return length;
777 }
778
779 static struct file_operations sel_bool_ops = {
780         .read           = sel_read_bool,
781         .write          = sel_write_bool,
782 };
783
784 static ssize_t sel_commit_bools_write(struct file *filep,
785                                       const char __user *buf,
786                                       size_t count, loff_t *ppos)
787 {
788         char *page = NULL;
789         ssize_t length = -EFAULT;
790         int new_value;
791
792         down(&sel_sem);
793
794         length = task_has_security(current, SECURITY__SETBOOL);
795         if (length)
796                 goto out;
797
798         /* check to see if this file has been deleted */
799         if (!filep->f_op)
800                 goto out;
801
802         if (count < 0 || count >= PAGE_SIZE) {
803                 length = -ENOMEM;
804                 goto out;
805         }
806         if (*ppos != 0) {
807                 /* No partial writes. */
808                 goto out;
809         }
810         page = (char*)get_zeroed_page(GFP_KERNEL);
811         if (!page) {
812                 length = -ENOMEM;
813                 goto out;
814         }
815
816         if (copy_from_user(page, buf, count))
817                 goto out;
818
819         length = -EINVAL;
820         if (sscanf(page, "%d", &new_value) != 1)
821                 goto out;
822
823         if (new_value) {
824                 security_set_bools(bool_num, bool_pending_values);
825         }
826
827         length = count;
828
829 out:
830         up(&sel_sem);
831         if (page)
832                 free_page((unsigned long) page);
833         return length;
834 }
835
836 static struct file_operations sel_commit_bools_ops = {
837         .write          = sel_commit_bools_write,
838 };
839
840 /* delete booleans - partial revoke() from
841  * fs/proc/generic.c proc_kill_inodes */
842 static void sel_remove_bools(struct dentry *de)
843 {
844         struct list_head *p, *node;
845         struct super_block *sb = de->d_sb;
846
847         spin_lock(&dcache_lock);
848         node = de->d_subdirs.next;
849         while (node != &de->d_subdirs) {
850                 struct dentry *d = list_entry(node, struct dentry, d_child);
851                 list_del_init(node);
852
853                 if (d->d_inode) {
854                         d = dget_locked(d);
855                         spin_unlock(&dcache_lock);
856                         d_delete(d);
857                         simple_unlink(de->d_inode, d);
858                         dput(d);
859                         spin_lock(&dcache_lock);
860                 }
861                 node = de->d_subdirs.next;
862         }
863
864         spin_unlock(&dcache_lock);
865
866         file_list_lock();
867         list_for_each(p, &sb->s_files) {
868                 struct file * filp = list_entry(p, struct file, f_list);
869                 struct dentry * dentry = filp->f_dentry;
870
871                 if (dentry->d_parent != de) {
872                         continue;
873                 }
874                 filp->f_op = NULL;
875         }
876         file_list_unlock();
877 }
878
879 #define BOOL_DIR_NAME "booleans"
880
881 static int sel_make_bools(void)
882 {
883         int i, ret = 0;
884         ssize_t len;
885         struct dentry *dentry = NULL;
886         struct dentry *dir = bool_dir;
887         struct inode *inode = NULL;
888         struct inode_security_struct *isec;
889         char **names = NULL, *page;
890         int num;
891         int *values = NULL;
892         u32 sid;
893
894         /* remove any existing files */
895         if (bool_pending_values)
896                 kfree(bool_pending_values);
897
898         sel_remove_bools(dir);
899
900         if (!(page = (char*)get_zeroed_page(GFP_KERNEL)))
901                 return -ENOMEM;
902
903         ret = security_get_bools(&num, &names, &values);
904         if (ret != 0)
905                 goto out;
906
907         for (i = 0; i < num; i++) {
908                 dentry = d_alloc_name(dir, names[i]);
909                 if (!dentry) {
910                         ret = -ENOMEM;
911                         goto err;
912                 }
913                 inode = sel_make_inode(dir->d_sb, S_IFREG | S_IRUGO | S_IWUSR);
914                 if (!inode) {
915                         ret = -ENOMEM;
916                         goto err;
917                 }
918
919                 len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]);
920                 if (len < 0) {
921                         ret = -EINVAL;
922                         goto err;
923                 } else if (len >= PAGE_SIZE) {
924                         ret = -ENAMETOOLONG;
925                         goto err;
926                 }
927                 isec = (struct inode_security_struct*)inode->i_security;
928                 if ((ret = security_genfs_sid("selinuxfs", page, SECCLASS_FILE, &sid)))
929                         goto err;
930                 isec->sid = sid;
931                 isec->initialized = 1;
932                 inode->i_fop = &sel_bool_ops;
933                 inode->i_ino = i + BOOL_INO_OFFSET;
934                 d_add(dentry, inode);
935         }
936         bool_num = num;
937         bool_pending_values = values;
938 out:
939         free_page((unsigned long)page);
940         if (names) {
941                 for (i = 0; i < num; i++) {
942                         if (names[i])
943                                 kfree(names[i]);
944                 }
945                 kfree(names);
946         }
947         return ret;
948 err:
949         d_genocide(dir);
950         ret = -ENOMEM;
951         goto out;
952 }
953
954 #define NULL_FILE_NAME "null"
955
956 struct dentry *selinux_null = NULL;
957
958 static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf,
959                                             size_t count, loff_t *ppos)
960 {
961         char tmpbuf[TMPBUFLEN];
962         ssize_t length;
963
964         length = scnprintf(tmpbuf, TMPBUFLEN, "%u", avc_cache_threshold);
965         return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
966 }
967
968 static ssize_t sel_write_avc_cache_threshold(struct file * file,
969                                              const char __user * buf,
970                                              size_t count, loff_t *ppos)
971
972 {
973         char *page;
974         ssize_t ret;
975         int new_value;
976
977         if (count < 0 || count >= PAGE_SIZE) {
978                 ret = -ENOMEM;
979                 goto out;
980         }
981
982         if (*ppos != 0) {
983                 /* No partial writes. */
984                 ret = -EINVAL;
985                 goto out;
986         }
987
988         page = (char*)get_zeroed_page(GFP_KERNEL);
989         if (!page) {
990                 ret = -ENOMEM;
991                 goto out;
992         }
993
994         if (copy_from_user(page, buf, count)) {
995                 ret = -EFAULT;
996                 goto out_free;
997         }
998
999         if (sscanf(page, "%u", &new_value) != 1) {
1000                 ret = -EINVAL;
1001                 goto out;
1002         }
1003
1004         if (new_value != avc_cache_threshold) {
1005                 ret = task_has_security(current, SECURITY__SETSECPARAM);
1006                 if (ret)
1007                         goto out_free;
1008                 avc_cache_threshold = new_value;
1009         }
1010         ret = count;
1011 out_free:
1012         free_page((unsigned long)page);
1013 out:
1014         return ret;
1015 }
1016
1017 static ssize_t sel_read_avc_hash_stats(struct file *filp, char __user *buf,
1018                                        size_t count, loff_t *ppos)
1019 {
1020         char *page;
1021         ssize_t ret = 0;
1022
1023         page = (char *)__get_free_page(GFP_KERNEL);
1024         if (!page) {
1025                 ret = -ENOMEM;
1026                 goto out;
1027         }
1028         ret = avc_get_hash_stats(page);
1029         if (ret >= 0)
1030                 ret = simple_read_from_buffer(buf, count, ppos, page, ret);
1031         free_page((unsigned long)page);
1032 out:
1033         return ret;
1034 }
1035
1036 static struct file_operations sel_avc_cache_threshold_ops = {
1037         .read           = sel_read_avc_cache_threshold,
1038         .write          = sel_write_avc_cache_threshold,
1039 };
1040
1041 static struct file_operations sel_avc_hash_stats_ops = {
1042         .read           = sel_read_avc_hash_stats,
1043 };
1044
1045 #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS
1046 static struct avc_cache_stats *sel_avc_get_stat_idx(loff_t *idx)
1047 {
1048         int cpu;
1049
1050         for (cpu = *idx; cpu < NR_CPUS; ++cpu) {
1051                 if (!cpu_possible(cpu))
1052                         continue;
1053                 *idx = cpu + 1;
1054                 return &per_cpu(avc_cache_stats, cpu);
1055         }
1056         return NULL;
1057 }
1058
1059 static void *sel_avc_stats_seq_start(struct seq_file *seq, loff_t *pos)
1060 {
1061         loff_t n = *pos - 1;
1062
1063         if (*pos == 0)
1064                 return SEQ_START_TOKEN;
1065
1066         return sel_avc_get_stat_idx(&n);
1067 }
1068
1069 static void *sel_avc_stats_seq_next(struct seq_file *seq, void *v, loff_t *pos)
1070 {
1071         return sel_avc_get_stat_idx(pos);
1072 }
1073
1074 static int sel_avc_stats_seq_show(struct seq_file *seq, void *v)
1075 {
1076         struct avc_cache_stats *st = v;
1077
1078         if (v == SEQ_START_TOKEN)
1079                 seq_printf(seq, "lookups hits misses allocations reclaims "
1080                            "frees\n");
1081         else
1082                 seq_printf(seq, "%u %u %u %u %u %u\n", st->lookups,
1083                            st->hits, st->misses, st->allocations,
1084                            st->reclaims, st->frees);
1085         return 0;
1086 }
1087
1088 static void sel_avc_stats_seq_stop(struct seq_file *seq, void *v)
1089 { }
1090
1091 static struct seq_operations sel_avc_cache_stats_seq_ops = {
1092         .start          = sel_avc_stats_seq_start,
1093         .next           = sel_avc_stats_seq_next,
1094         .show           = sel_avc_stats_seq_show,
1095         .stop           = sel_avc_stats_seq_stop,
1096 };
1097
1098 static int sel_open_avc_cache_stats(struct inode *inode, struct file *file)
1099 {
1100         return seq_open(file, &sel_avc_cache_stats_seq_ops);
1101 }
1102
1103 static struct file_operations sel_avc_cache_stats_ops = {
1104         .open           = sel_open_avc_cache_stats,
1105         .read           = seq_read,
1106         .llseek         = seq_lseek,
1107         .release        = seq_release,
1108 };
1109 #endif
1110
1111 static int sel_make_avc_files(struct dentry *dir)
1112 {
1113         int i, ret = 0;
1114         static struct tree_descr files[] = {
1115                 { "cache_threshold",
1116                   &sel_avc_cache_threshold_ops, S_IRUGO|S_IWUSR },
1117                 { "hash_stats", &sel_avc_hash_stats_ops, S_IRUGO },
1118 #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS
1119                 { "cache_stats", &sel_avc_cache_stats_ops, S_IRUGO },
1120 #endif
1121         };
1122
1123         for (i = 0; i < sizeof (files) / sizeof (files[0]); i++) {
1124                 struct inode *inode;
1125                 struct dentry *dentry;
1126
1127                 dentry = d_alloc_name(dir, files[i].name);
1128                 if (!dentry) {
1129                         ret = -ENOMEM;
1130                         goto err;
1131                 }
1132
1133                 inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode);
1134                 if (!inode) {
1135                         ret = -ENOMEM;
1136                         goto err;
1137                 }
1138                 inode->i_fop = files[i].ops;
1139                 d_add(dentry, inode);
1140         }
1141 out:
1142         return ret;
1143 err:
1144         d_genocide(dir);
1145         goto out;
1146 }
1147
1148 static int sel_make_dir(struct super_block *sb, struct dentry *dentry)
1149 {
1150         int ret = 0;
1151         struct inode *inode;
1152
1153         inode = sel_make_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO);
1154         if (!inode) {
1155                 ret = -ENOMEM;
1156                 goto out;
1157         }
1158         inode->i_op = &simple_dir_inode_operations;
1159         inode->i_fop = &simple_dir_operations;
1160         d_add(dentry, inode);
1161 out:
1162         return ret;
1163 }
1164
1165 static int sel_fill_super(struct super_block * sb, void * data, int silent)
1166 {
1167         int ret;
1168         struct dentry *dentry;
1169         struct inode *inode;
1170         struct inode_security_struct *isec;
1171
1172         static struct tree_descr selinux_files[] = {
1173                 [SEL_LOAD] = {"load", &sel_load_ops, S_IRUSR|S_IWUSR},
1174                 [SEL_ENFORCE] = {"enforce", &sel_enforce_ops, S_IRUGO|S_IWUSR},
1175                 [SEL_CONTEXT] = {"context", &sel_context_ops, S_IRUGO|S_IWUGO},
1176                 [SEL_ACCESS] = {"access", &transaction_ops, S_IRUGO|S_IWUGO},
1177                 [SEL_CREATE] = {"create", &transaction_ops, S_IRUGO|S_IWUGO},
1178                 [SEL_RELABEL] = {"relabel", &transaction_ops, S_IRUGO|S_IWUGO},
1179                 [SEL_USER] = {"user", &transaction_ops, S_IRUGO|S_IWUGO},
1180                 [SEL_POLICYVERS] = {"policyvers", &sel_policyvers_ops, S_IRUGO},
1181                 [SEL_COMMIT_BOOLS] = {"commit_pending_bools", &sel_commit_bools_ops, S_IWUSR},
1182                 [SEL_MLS] = {"mls", &sel_mls_ops, S_IRUGO},
1183                 [SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR},
1184                 [SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO},
1185                 /* last one */ {""}
1186         };
1187         ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
1188         if (ret)
1189                 return ret;
1190
1191         dentry = d_alloc_name(sb->s_root, BOOL_DIR_NAME);
1192         if (!dentry)
1193                 return -ENOMEM;
1194
1195         inode = sel_make_inode(sb, S_IFDIR | S_IRUGO | S_IXUGO);
1196         if (!inode)
1197                 goto out;
1198         inode->i_op = &simple_dir_inode_operations;
1199         inode->i_fop = &simple_dir_operations;
1200         d_add(dentry, inode);
1201         bool_dir = dentry;
1202         ret = sel_make_bools();
1203         if (ret)
1204                 goto out;
1205
1206         dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME);
1207         if (!dentry)
1208                 return -ENOMEM;
1209
1210         inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO);
1211         if (!inode)
1212                 goto out;
1213         isec = (struct inode_security_struct*)inode->i_security;
1214         isec->sid = SECINITSID_DEVNULL;
1215         isec->sclass = SECCLASS_CHR_FILE;
1216         isec->initialized = 1;
1217
1218         init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3));
1219         d_add(dentry, inode);
1220         selinux_null = dentry;
1221
1222         dentry = d_alloc_name(sb->s_root, "avc");
1223         if (!dentry)
1224                 return -ENOMEM;
1225
1226         ret = sel_make_dir(sb, dentry);
1227         if (ret)
1228                 goto out;
1229
1230         ret = sel_make_avc_files(dentry);
1231         if (ret)
1232                 goto out;
1233
1234         return 0;
1235 out:
1236         dput(dentry);
1237         printk(KERN_ERR "%s:  failed while creating inodes\n", __FUNCTION__);
1238         return -ENOMEM;
1239 }
1240
1241 static struct super_block *sel_get_sb(struct file_system_type *fs_type,
1242                                       int flags, const char *dev_name, void *data)
1243 {
1244         return get_sb_single(fs_type, flags, data, sel_fill_super);
1245 }
1246
1247 static struct file_system_type sel_fs_type = {
1248         .name           = "selinuxfs",
1249         .get_sb         = sel_get_sb,
1250         .kill_sb        = kill_litter_super,
1251 };
1252
1253 struct vfsmount *selinuxfs_mount;
1254
1255 static int __init init_sel_fs(void)
1256 {
1257         int err;
1258
1259         if (!selinux_enabled)
1260                 return 0;
1261         err = register_filesystem(&sel_fs_type);
1262         if (!err) {
1263                 selinuxfs_mount = kern_mount(&sel_fs_type);
1264                 if (IS_ERR(selinuxfs_mount)) {
1265                         printk(KERN_ERR "selinuxfs:  could not mount!\n");
1266                         err = PTR_ERR(selinuxfs_mount);
1267                         selinuxfs_mount = NULL;
1268                 }
1269         }
1270         return err;
1271 }
1272
1273 __initcall(init_sel_fs);
1274
1275 #ifdef CONFIG_SECURITY_SELINUX_DISABLE
1276 void exit_sel_fs(void)
1277 {
1278         unregister_filesystem(&sel_fs_type);
1279 }
1280 #endif