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