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