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