selinux: permit removing security.selinux xattr before policy load
[linux-2.6-block.git] / security / selinux / selinuxfs.c
CommitLineData
a10e763b 1// SPDX-License-Identifier: GPL-2.0-only
1da177e4
LT
2/* Updated: Karl MacMillan <kmacmillan@tresys.com>
3 *
1872981b 4 * Added conditional policy language extensions
1da177e4 5 *
82c21bfa 6 * Updated: Hewlett-Packard <paul@paul-moore.com>
3bb56b25 7 *
1872981b 8 * Added support for the policy capability bitmap
3bb56b25
PM
9 *
10 * Copyright (C) 2007 Hewlett-Packard Development Company, L.P.
1da177e4
LT
11 * Copyright (C) 2003 - 2004 Tresys Technology, LLC
12 * Copyright (C) 2004 Red Hat, Inc., James Morris <jmorris@redhat.com>
1da177e4
LT
13 */
14
1da177e4
LT
15#include <linux/kernel.h>
16#include <linux/pagemap.h>
17#include <linux/slab.h>
18#include <linux/vmalloc.h>
19#include <linux/fs.h>
920f50b2 20#include <linux/fs_context.h>
0619f0f5 21#include <linux/mount.h>
bb003079 22#include <linux/mutex.h>
1da177e4
LT
23#include <linux/init.h>
24#include <linux/string.h>
25#include <linux/security.h>
26#include <linux/major.h>
27#include <linux/seq_file.h>
28#include <linux/percpu.h>
af601e46 29#include <linux/audit.h>
f5269710 30#include <linux/uaccess.h>
7a627e3b 31#include <linux/kobject.h>
0f7e4c33 32#include <linux/ctype.h>
1da177e4
LT
33
34/* selinuxfs pseudo filesystem for exporting the security policy API.
35 Based on the proc code and the fs/nfsd/nfsctl.c code. */
36
37#include "flask.h"
38#include "avc.h"
39#include "avc_ss.h"
40#include "security.h"
41#include "objsec.h"
42#include "conditional.h"
43
1da177e4
LT
44enum sel_inos {
45 SEL_ROOT_INO = 2,
46 SEL_LOAD, /* load policy */
47 SEL_ENFORCE, /* get or set enforcing status */
48 SEL_CONTEXT, /* validate context */
49 SEL_ACCESS, /* compute access decision */
50 SEL_CREATE, /* compute create labeling decision */
51 SEL_RELABEL, /* compute relabeling decision */
52 SEL_USER, /* compute reachable user contexts */
53 SEL_POLICYVERS, /* return policy version for this kernel */
54 SEL_COMMIT_BOOLS, /* commit new boolean values */
55 SEL_MLS, /* return if MLS policy is enabled */
56 SEL_DISABLE, /* disable SELinux until next reboot */
1da177e4
LT
57 SEL_MEMBER, /* compute polyinstantiation membership decision */
58 SEL_CHECKREQPROT, /* check requested protection, not kernel-applied one */
4e5ab4cb 59 SEL_COMPAT_NET, /* whether to use old compat network packet controls */
3f12070e
EP
60 SEL_REJECT_UNKNOWN, /* export unknown reject handling to userspace */
61 SEL_DENY_UNKNOWN, /* export unknown deny handling to userspace */
11904167 62 SEL_STATUS, /* export current status using mmap() */
cee74f47 63 SEL_POLICY, /* allow userspace to read the in kernel policy */
f9df6458 64 SEL_VALIDATE_TRANS, /* compute validatetrans decision */
6174eafc 65 SEL_INO_NEXT, /* The next inode number to use */
1da177e4
LT
66};
67
0619f0f5
SS
68struct selinux_fs_info {
69 struct dentry *bool_dir;
70 unsigned int bool_num;
71 char **bool_pending_names;
72 unsigned int *bool_pending_values;
73 struct dentry *class_dir;
74 unsigned long last_class_ino;
75 bool policy_opened;
76 struct dentry *policycap_dir;
77 struct mutex mutex;
78 unsigned long last_ino;
79 struct selinux_state *state;
80 struct super_block *sb;
81};
82
83static int selinux_fs_info_create(struct super_block *sb)
84{
85 struct selinux_fs_info *fsi;
86
87 fsi = kzalloc(sizeof(*fsi), GFP_KERNEL);
88 if (!fsi)
89 return -ENOMEM;
90
91 mutex_init(&fsi->mutex);
92 fsi->last_ino = SEL_INO_NEXT - 1;
93 fsi->state = &selinux_state;
94 fsi->sb = sb;
95 sb->s_fs_info = fsi;
96 return 0;
97}
98
99static void selinux_fs_info_free(struct super_block *sb)
100{
101 struct selinux_fs_info *fsi = sb->s_fs_info;
102 int i;
103
104 if (fsi) {
105 for (i = 0; i < fsi->bool_num; i++)
106 kfree(fsi->bool_pending_names[i]);
107 kfree(fsi->bool_pending_names);
108 kfree(fsi->bool_pending_values);
109 }
110 kfree(sb->s_fs_info);
111 sb->s_fs_info = NULL;
112}
6174eafc 113
3bb56b25
PM
114#define SEL_INITCON_INO_OFFSET 0x01000000
115#define SEL_BOOL_INO_OFFSET 0x02000000
116#define SEL_CLASS_INO_OFFSET 0x04000000
117#define SEL_POLICYCAP_INO_OFFSET 0x08000000
118#define SEL_INO_MASK 0x00ffffff
f0ee2e46 119
1da177e4
LT
120#define TMPBUFLEN 12
121static ssize_t sel_read_enforce(struct file *filp, char __user *buf,
122 size_t count, loff_t *ppos)
123{
0619f0f5 124 struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
1da177e4
LT
125 char tmpbuf[TMPBUFLEN];
126 ssize_t length;
127
aa8e712c 128 length = scnprintf(tmpbuf, TMPBUFLEN, "%d",
0619f0f5 129 enforcing_enabled(fsi->state));
1da177e4
LT
130 return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
131}
132
133#ifdef CONFIG_SECURITY_SELINUX_DEVELOP
1872981b 134static ssize_t sel_write_enforce(struct file *file, const char __user *buf,
1da177e4
LT
135 size_t count, loff_t *ppos)
136
137{
0619f0f5
SS
138 struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
139 struct selinux_state *state = fsi->state;
b77a493b 140 char *page = NULL;
1da177e4 141 ssize_t length;
aa8e712c 142 int old_value, new_value;
1da177e4 143
bfd51626 144 if (count >= PAGE_SIZE)
8365a719 145 return -ENOMEM;
b77a493b
EP
146
147 /* No partial writes. */
b77a493b 148 if (*ppos != 0)
8365a719 149 return -EINVAL;
b77a493b 150
8365a719
AV
151 page = memdup_user_nul(buf, count);
152 if (IS_ERR(page))
153 return PTR_ERR(page);
1da177e4
LT
154
155 length = -EINVAL;
156 if (sscanf(page, "%d", &new_value) != 1)
157 goto out;
158
ea49d10e
SS
159 new_value = !!new_value;
160
0619f0f5 161 old_value = enforcing_enabled(state);
aa8e712c 162 if (new_value != old_value) {
6b6bc620
SS
163 length = avc_has_perm(&selinux_state,
164 current_sid(), SECINITSID_SECURITY,
be0554c9
SS
165 SECCLASS_SECURITY, SECURITY__SETENFORCE,
166 NULL);
1da177e4
LT
167 if (length)
168 goto out;
cdfb6b34 169 audit_log(audit_context(), GFP_KERNEL, AUDIT_MAC_STATUS,
4195ed42 170 "enforcing=%d old_enforcing=%d auid=%u ses=%u"
6c5a682e 171 " enabled=1 old-enabled=1 lsm=selinux res=1",
aa8e712c 172 new_value, old_value,
581abc09 173 from_kuid(&init_user_ns, audit_get_loginuid(current)),
6c5a682e 174 audit_get_sessionid(current));
0619f0f5 175 enforcing_set(state, new_value);
aa8e712c 176 if (new_value)
6b6bc620 177 avc_ss_reset(state->avc, 0);
aa8e712c 178 selnl_notify_setenforce(new_value);
0619f0f5 179 selinux_status_update_setenforce(state, new_value);
aa8e712c 180 if (!new_value)
42df744c 181 call_blocking_lsm_notifier(LSM_POLICY_CHANGE, NULL);
1da177e4
LT
182 }
183 length = count;
184out:
8365a719 185 kfree(page);
1da177e4
LT
186 return length;
187}
188#else
189#define sel_write_enforce NULL
190#endif
191
9c2e08c5 192static const struct file_operations sel_enforce_ops = {
1da177e4
LT
193 .read = sel_read_enforce,
194 .write = sel_write_enforce,
57a62c23 195 .llseek = generic_file_llseek,
1da177e4
LT
196};
197
3f12070e
EP
198static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf,
199 size_t count, loff_t *ppos)
200{
0619f0f5
SS
201 struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
202 struct selinux_state *state = fsi->state;
3f12070e
EP
203 char tmpbuf[TMPBUFLEN];
204 ssize_t length;
496ad9aa 205 ino_t ino = file_inode(filp)->i_ino;
3f12070e 206 int handle_unknown = (ino == SEL_REJECT_UNKNOWN) ?
0619f0f5
SS
207 security_get_reject_unknown(state) :
208 !security_get_allow_unknown(state);
3f12070e
EP
209
210 length = scnprintf(tmpbuf, TMPBUFLEN, "%d", handle_unknown);
211 return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
212}
213
214static const struct file_operations sel_handle_unknown_ops = {
215 .read = sel_read_handle_unknown,
57a62c23 216 .llseek = generic_file_llseek,
3f12070e
EP
217};
218
11904167
KK
219static int sel_open_handle_status(struct inode *inode, struct file *filp)
220{
0619f0f5
SS
221 struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
222 struct page *status = selinux_kernel_status_page(fsi->state);
11904167
KK
223
224 if (!status)
225 return -ENOMEM;
226
227 filp->private_data = status;
228
229 return 0;
230}
231
232static ssize_t sel_read_handle_status(struct file *filp, char __user *buf,
233 size_t count, loff_t *ppos)
234{
235 struct page *status = filp->private_data;
236
237 BUG_ON(!status);
238
239 return simple_read_from_buffer(buf, count, ppos,
240 page_address(status),
241 sizeof(struct selinux_kernel_status));
242}
243
244static int sel_mmap_handle_status(struct file *filp,
245 struct vm_area_struct *vma)
246{
247 struct page *status = filp->private_data;
248 unsigned long size = vma->vm_end - vma->vm_start;
249
250 BUG_ON(!status);
251
252 /* only allows one page from the head */
253 if (vma->vm_pgoff > 0 || size != PAGE_SIZE)
254 return -EIO;
255 /* disallow writable mapping */
256 if (vma->vm_flags & VM_WRITE)
257 return -EPERM;
258 /* disallow mprotect() turns it into writable */
259 vma->vm_flags &= ~VM_MAYWRITE;
260
261 return remap_pfn_range(vma, vma->vm_start,
262 page_to_pfn(status),
263 size, vma->vm_page_prot);
264}
265
266static const struct file_operations sel_handle_status_ops = {
267 .open = sel_open_handle_status,
268 .read = sel_read_handle_status,
269 .mmap = sel_mmap_handle_status,
270 .llseek = generic_file_llseek,
271};
272
1da177e4 273#ifdef CONFIG_SECURITY_SELINUX_DISABLE
1872981b 274static ssize_t sel_write_disable(struct file *file, const char __user *buf,
1da177e4
LT
275 size_t count, loff_t *ppos)
276
277{
0619f0f5 278 struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
8365a719 279 char *page;
1da177e4
LT
280 ssize_t length;
281 int new_value;
4195ed42 282 int enforcing;
1da177e4 283
89b223bf
PM
284 /* NOTE: we are now officially considering runtime disable as
285 * deprecated, and using it will become increasingly painful
286 * (e.g. sleeping/blocking) as we progress through future
287 * kernel releases until eventually it is removed
288 */
289 pr_err("SELinux: Runtime disable is deprecated, use selinux=0 on the kernel cmdline.\n");
290
bfd51626 291 if (count >= PAGE_SIZE)
8365a719 292 return -ENOMEM;
b77a493b
EP
293
294 /* No partial writes. */
b77a493b 295 if (*ppos != 0)
8365a719 296 return -EINVAL;
b77a493b 297
8365a719
AV
298 page = memdup_user_nul(buf, count);
299 if (IS_ERR(page))
300 return PTR_ERR(page);
1da177e4
LT
301
302 length = -EINVAL;
303 if (sscanf(page, "%d", &new_value) != 1)
304 goto out;
305
306 if (new_value) {
4195ed42 307 enforcing = enforcing_enabled(fsi->state);
0619f0f5 308 length = selinux_disable(fsi->state);
b77a493b 309 if (length)
1da177e4 310 goto out;
cdfb6b34 311 audit_log(audit_context(), GFP_KERNEL, AUDIT_MAC_STATUS,
4195ed42 312 "enforcing=%d old_enforcing=%d auid=%u ses=%u"
6c5a682e 313 " enabled=0 old-enabled=1 lsm=selinux res=1",
4195ed42 314 enforcing, enforcing,
581abc09 315 from_kuid(&init_user_ns, audit_get_loginuid(current)),
6c5a682e 316 audit_get_sessionid(current));
1da177e4
LT
317 }
318
319 length = count;
320out:
8365a719 321 kfree(page);
1da177e4
LT
322 return length;
323}
324#else
325#define sel_write_disable NULL
326#endif
327
9c2e08c5 328static const struct file_operations sel_disable_ops = {
1da177e4 329 .write = sel_write_disable,
57a62c23 330 .llseek = generic_file_llseek,
1da177e4
LT
331};
332
333static ssize_t sel_read_policyvers(struct file *filp, char __user *buf,
1872981b 334 size_t count, loff_t *ppos)
1da177e4
LT
335{
336 char tmpbuf[TMPBUFLEN];
337 ssize_t length;
338
339 length = scnprintf(tmpbuf, TMPBUFLEN, "%u", POLICYDB_VERSION_MAX);
340 return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
341}
342
9c2e08c5 343static const struct file_operations sel_policyvers_ops = {
1da177e4 344 .read = sel_read_policyvers,
57a62c23 345 .llseek = generic_file_llseek,
1da177e4
LT
346};
347
348/* declaration for sel_write_load */
02a52c5c
SS
349static int sel_make_bools(struct selinux_fs_info *fsi,
350 struct selinux_policy *newpolicy);
351static int sel_make_classes(struct selinux_fs_info *fsi,
352 struct selinux_policy *newpolicy);
e47c8fc5
CP
353
354/* declaration for sel_make_class_dirs */
a1c2aa1e 355static struct dentry *sel_make_dir(struct dentry *dir, const char *name,
e47c8fc5 356 unsigned long *ino);
1da177e4
LT
357
358static ssize_t sel_read_mls(struct file *filp, char __user *buf,
359 size_t count, loff_t *ppos)
360{
0619f0f5 361 struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
1da177e4
LT
362 char tmpbuf[TMPBUFLEN];
363 ssize_t length;
364
0719aaf5 365 length = scnprintf(tmpbuf, TMPBUFLEN, "%d",
0619f0f5 366 security_mls_enabled(fsi->state));
1da177e4
LT
367 return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
368}
369
9c2e08c5 370static const struct file_operations sel_mls_ops = {
1da177e4 371 .read = sel_read_mls,
57a62c23 372 .llseek = generic_file_llseek,
1da177e4
LT
373};
374
cee74f47
EP
375struct policy_load_memory {
376 size_t len;
377 void *data;
378};
379
380static int sel_open_policy(struct inode *inode, struct file *filp)
381{
0619f0f5
SS
382 struct selinux_fs_info *fsi = inode->i_sb->s_fs_info;
383 struct selinux_state *state = fsi->state;
cee74f47
EP
384 struct policy_load_memory *plm = NULL;
385 int rc;
386
387 BUG_ON(filp->private_data);
388
0619f0f5 389 mutex_lock(&fsi->mutex);
cee74f47 390
6b6bc620
SS
391 rc = avc_has_perm(&selinux_state,
392 current_sid(), SECINITSID_SECURITY,
be0554c9 393 SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL);
cee74f47
EP
394 if (rc)
395 goto err;
396
397 rc = -EBUSY;
0619f0f5 398 if (fsi->policy_opened)
cee74f47
EP
399 goto err;
400
401 rc = -ENOMEM;
402 plm = kzalloc(sizeof(*plm), GFP_KERNEL);
403 if (!plm)
404 goto err;
405
0619f0f5 406 if (i_size_read(inode) != security_policydb_len(state)) {
5955102c 407 inode_lock(inode);
0619f0f5 408 i_size_write(inode, security_policydb_len(state));
5955102c 409 inode_unlock(inode);
cee74f47
EP
410 }
411
0619f0f5 412 rc = security_read_policy(state, &plm->data, &plm->len);
cee74f47
EP
413 if (rc)
414 goto err;
415
0619f0f5 416 fsi->policy_opened = 1;
cee74f47
EP
417
418 filp->private_data = plm;
419
0619f0f5 420 mutex_unlock(&fsi->mutex);
cee74f47
EP
421
422 return 0;
423err:
0619f0f5 424 mutex_unlock(&fsi->mutex);
cee74f47
EP
425
426 if (plm)
427 vfree(plm->data);
428 kfree(plm);
429 return rc;
430}
431
432static int sel_release_policy(struct inode *inode, struct file *filp)
433{
0619f0f5 434 struct selinux_fs_info *fsi = inode->i_sb->s_fs_info;
cee74f47
EP
435 struct policy_load_memory *plm = filp->private_data;
436
437 BUG_ON(!plm);
438
0619f0f5 439 fsi->policy_opened = 0;
cee74f47
EP
440
441 vfree(plm->data);
442 kfree(plm);
443
444 return 0;
445}
446
447static ssize_t sel_read_policy(struct file *filp, char __user *buf,
448 size_t count, loff_t *ppos)
449{
450 struct policy_load_memory *plm = filp->private_data;
451 int ret;
452
6b6bc620
SS
453 ret = avc_has_perm(&selinux_state,
454 current_sid(), SECINITSID_SECURITY,
be0554c9 455 SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL);
cee74f47 456 if (ret)
0da74120 457 return ret;
cee74f47 458
0da74120 459 return simple_read_from_buffer(buf, count, ppos, plm->data, plm->len);
cee74f47
EP
460}
461
ac9a1f6d 462static vm_fault_t sel_mmap_policy_fault(struct vm_fault *vmf)
845ca30f 463{
11bac800 464 struct policy_load_memory *plm = vmf->vma->vm_file->private_data;
845ca30f
EP
465 unsigned long offset;
466 struct page *page;
467
468 if (vmf->flags & (FAULT_FLAG_MKWRITE | FAULT_FLAG_WRITE))
469 return VM_FAULT_SIGBUS;
470
471 offset = vmf->pgoff << PAGE_SHIFT;
472 if (offset >= roundup(plm->len, PAGE_SIZE))
473 return VM_FAULT_SIGBUS;
474
475 page = vmalloc_to_page(plm->data + offset);
476 get_page(page);
477
478 vmf->page = page;
479
480 return 0;
481}
482
7cbea8dc 483static const struct vm_operations_struct sel_mmap_policy_ops = {
845ca30f
EP
484 .fault = sel_mmap_policy_fault,
485 .page_mkwrite = sel_mmap_policy_fault,
486};
487
ad3fa08c 488static int sel_mmap_policy(struct file *filp, struct vm_area_struct *vma)
845ca30f
EP
489{
490 if (vma->vm_flags & VM_SHARED) {
491 /* do not allow mprotect to make mapping writable */
492 vma->vm_flags &= ~VM_MAYWRITE;
493
494 if (vma->vm_flags & VM_WRITE)
495 return -EACCES;
496 }
497
314e51b9 498 vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
845ca30f
EP
499 vma->vm_ops = &sel_mmap_policy_ops;
500
501 return 0;
502}
503
cee74f47
EP
504static const struct file_operations sel_policy_ops = {
505 .open = sel_open_policy,
506 .read = sel_read_policy,
845ca30f 507 .mmap = sel_mmap_policy,
cee74f47 508 .release = sel_release_policy,
47a93a5b 509 .llseek = generic_file_llseek,
cee74f47
EP
510};
511
02a52c5c
SS
512static int sel_make_policy_nodes(struct selinux_fs_info *fsi,
513 struct selinux_policy *newpolicy)
0619f0f5
SS
514{
515 int ret;
516
02a52c5c 517 ret = sel_make_bools(fsi, newpolicy);
0619f0f5
SS
518 if (ret) {
519 pr_err("SELinux: failed to load policy booleans\n");
520 return ret;
521 }
522
02a52c5c 523 ret = sel_make_classes(fsi, newpolicy);
0619f0f5
SS
524 if (ret) {
525 pr_err("SELinux: failed to load policy classes\n");
526 return ret;
527 }
528
0619f0f5
SS
529 return 0;
530}
531
1872981b 532static ssize_t sel_write_load(struct file *file, const char __user *buf,
1da177e4
LT
533 size_t count, loff_t *ppos)
534
535{
0619f0f5 536 struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
02a52c5c 537 struct selinux_policy *newpolicy;
1da177e4
LT
538 ssize_t length;
539 void *data = NULL;
540
0619f0f5 541 mutex_lock(&fsi->mutex);
1da177e4 542
6b6bc620
SS
543 length = avc_has_perm(&selinux_state,
544 current_sid(), SECINITSID_SECURITY,
be0554c9 545 SECCLASS_SECURITY, SECURITY__LOAD_POLICY, NULL);
1da177e4
LT
546 if (length)
547 goto out;
548
b77a493b
EP
549 /* No partial writes. */
550 length = -EINVAL;
551 if (*ppos != 0)
1da177e4 552 goto out;
1da177e4 553
b77a493b
EP
554 length = -ENOMEM;
555 data = vmalloc(count);
556 if (!data)
1da177e4 557 goto out;
1da177e4
LT
558
559 length = -EFAULT;
560 if (copy_from_user(data, buf, count) != 0)
561 goto out;
562
02a52c5c 563 length = security_load_policy(fsi->state, data, count, &newpolicy);
4262fb51
GT
564 if (length) {
565 pr_warn_ratelimited("SELinux: failed to load policy\n");
1da177e4 566 goto out;
4262fb51 567 }
1da177e4 568
02a52c5c
SS
569 length = sel_make_policy_nodes(fsi, newpolicy);
570 if (length) {
571 selinux_policy_cancel(fsi->state, newpolicy);
b77a493b 572 goto out1;
02a52c5c
SS
573 }
574
575 selinux_policy_commit(fsi->state, newpolicy);
b77a493b
EP
576
577 length = count;
e47c8fc5
CP
578
579out1:
cdfb6b34 580 audit_log(audit_context(), GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
d141136f 581 "auid=%u ses=%u lsm=selinux res=1",
581abc09 582 from_kuid(&init_user_ns, audit_get_loginuid(current)),
4746ec5b 583 audit_get_sessionid(current));
1da177e4 584out:
0619f0f5 585 mutex_unlock(&fsi->mutex);
1da177e4
LT
586 vfree(data);
587 return length;
588}
589
9c2e08c5 590static const struct file_operations sel_load_ops = {
1da177e4 591 .write = sel_write_load,
57a62c23 592 .llseek = generic_file_llseek,
1da177e4
LT
593};
594
1872981b 595static ssize_t sel_write_context(struct file *file, char *buf, size_t size)
1da177e4 596{
0619f0f5
SS
597 struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
598 struct selinux_state *state = fsi->state;
b77a493b 599 char *canon = NULL;
ce9982d0 600 u32 sid, len;
1da177e4
LT
601 ssize_t length;
602
6b6bc620
SS
603 length = avc_has_perm(&selinux_state,
604 current_sid(), SECINITSID_SECURITY,
be0554c9 605 SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT, NULL);
1da177e4 606 if (length)
b77a493b 607 goto out;
1da177e4 608
0619f0f5 609 length = security_context_to_sid(state, buf, size, &sid, GFP_KERNEL);
b77a493b
EP
610 if (length)
611 goto out;
1da177e4 612
0619f0f5 613 length = security_sid_to_context(state, sid, &canon, &len);
b77a493b
EP
614 if (length)
615 goto out;
ce9982d0 616
b77a493b 617 length = -ERANGE;
ce9982d0 618 if (len > SIMPLE_TRANSACTION_LIMIT) {
f8b69a5f 619 pr_err("SELinux: %s: context size (%u) exceeds "
744ba35e 620 "payload max\n", __func__, len);
1da177e4 621 goto out;
ce9982d0 622 }
1da177e4 623
ce9982d0
SS
624 memcpy(buf, canon, len);
625 length = len;
1da177e4 626out:
ce9982d0 627 kfree(canon);
1da177e4
LT
628 return length;
629}
630
1da177e4
LT
631static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf,
632 size_t count, loff_t *ppos)
633{
0619f0f5 634 struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
1da177e4
LT
635 char tmpbuf[TMPBUFLEN];
636 ssize_t length;
637
0619f0f5 638 length = scnprintf(tmpbuf, TMPBUFLEN, "%u", fsi->state->checkreqprot);
1da177e4
LT
639 return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
640}
641
1872981b 642static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf,
1da177e4
LT
643 size_t count, loff_t *ppos)
644{
0619f0f5 645 struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
8365a719 646 char *page;
1da177e4
LT
647 ssize_t length;
648 unsigned int new_value;
649
6b6bc620
SS
650 length = avc_has_perm(&selinux_state,
651 current_sid(), SECINITSID_SECURITY,
be0554c9
SS
652 SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT,
653 NULL);
1da177e4 654 if (length)
8365a719 655 return length;
1da177e4 656
bfd51626 657 if (count >= PAGE_SIZE)
8365a719 658 return -ENOMEM;
b77a493b
EP
659
660 /* No partial writes. */
b77a493b 661 if (*ppos != 0)
8365a719 662 return -EINVAL;
b77a493b 663
8365a719
AV
664 page = memdup_user_nul(buf, count);
665 if (IS_ERR(page))
666 return PTR_ERR(page);
1da177e4
LT
667
668 length = -EINVAL;
669 if (sscanf(page, "%u", &new_value) != 1)
670 goto out;
671
e9c38f9f
SS
672 if (new_value) {
673 char comm[sizeof(current->comm)];
674
675 memcpy(comm, current->comm, sizeof(comm));
676 pr_warn_once("SELinux: %s (%d) set checkreqprot to 1. This is deprecated and will be rejected in a future kernel release.\n",
677 comm, current->pid);
678 }
679
0619f0f5 680 fsi->state->checkreqprot = new_value ? 1 : 0;
1da177e4
LT
681 length = count;
682out:
8365a719 683 kfree(page);
1da177e4
LT
684 return length;
685}
9c2e08c5 686static const struct file_operations sel_checkreqprot_ops = {
1da177e4
LT
687 .read = sel_read_checkreqprot,
688 .write = sel_write_checkreqprot,
57a62c23 689 .llseek = generic_file_llseek,
1da177e4
LT
690};
691
f9df6458
AP
692static ssize_t sel_write_validatetrans(struct file *file,
693 const char __user *buf,
694 size_t count, loff_t *ppos)
695{
0619f0f5
SS
696 struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
697 struct selinux_state *state = fsi->state;
f9df6458
AP
698 char *oldcon = NULL, *newcon = NULL, *taskcon = NULL;
699 char *req = NULL;
700 u32 osid, nsid, tsid;
701 u16 tclass;
702 int rc;
703
6b6bc620
SS
704 rc = avc_has_perm(&selinux_state,
705 current_sid(), SECINITSID_SECURITY,
be0554c9 706 SECCLASS_SECURITY, SECURITY__VALIDATE_TRANS, NULL);
f9df6458
AP
707 if (rc)
708 goto out;
709
710 rc = -ENOMEM;
711 if (count >= PAGE_SIZE)
712 goto out;
713
714 /* No partial writes. */
715 rc = -EINVAL;
716 if (*ppos != 0)
717 goto out;
718
0b884d25
AV
719 req = memdup_user_nul(buf, count);
720 if (IS_ERR(req)) {
721 rc = PTR_ERR(req);
722 req = NULL;
f9df6458 723 goto out;
0b884d25 724 }
f9df6458
AP
725
726 rc = -ENOMEM;
727 oldcon = kzalloc(count + 1, GFP_KERNEL);
728 if (!oldcon)
729 goto out;
730
731 newcon = kzalloc(count + 1, GFP_KERNEL);
732 if (!newcon)
733 goto out;
734
735 taskcon = kzalloc(count + 1, GFP_KERNEL);
736 if (!taskcon)
737 goto out;
738
739 rc = -EINVAL;
740 if (sscanf(req, "%s %s %hu %s", oldcon, newcon, &tclass, taskcon) != 4)
741 goto out;
742
0619f0f5 743 rc = security_context_str_to_sid(state, oldcon, &osid, GFP_KERNEL);
f9df6458
AP
744 if (rc)
745 goto out;
746
0619f0f5 747 rc = security_context_str_to_sid(state, newcon, &nsid, GFP_KERNEL);
f9df6458
AP
748 if (rc)
749 goto out;
750
0619f0f5 751 rc = security_context_str_to_sid(state, taskcon, &tsid, GFP_KERNEL);
f9df6458
AP
752 if (rc)
753 goto out;
754
0619f0f5 755 rc = security_validate_transition_user(state, osid, nsid, tsid, tclass);
f9df6458
AP
756 if (!rc)
757 rc = count;
758out:
759 kfree(req);
760 kfree(oldcon);
761 kfree(newcon);
762 kfree(taskcon);
763 return rc;
764}
765
766static const struct file_operations sel_transition_ops = {
767 .write = sel_write_validatetrans,
768 .llseek = generic_file_llseek,
769};
770
1da177e4
LT
771/*
772 * Remaining nodes use transaction based IO methods like nfsd/nfsctl.c
773 */
1872981b
EP
774static ssize_t sel_write_access(struct file *file, char *buf, size_t size);
775static ssize_t sel_write_create(struct file *file, char *buf, size_t size);
776static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size);
777static ssize_t sel_write_user(struct file *file, char *buf, size_t size);
778static ssize_t sel_write_member(struct file *file, char *buf, size_t size);
1da177e4 779
631d2b49 780static ssize_t (*const write_op[])(struct file *, char *, size_t) = {
1da177e4
LT
781 [SEL_ACCESS] = sel_write_access,
782 [SEL_CREATE] = sel_write_create,
783 [SEL_RELABEL] = sel_write_relabel,
784 [SEL_USER] = sel_write_user,
785 [SEL_MEMBER] = sel_write_member,
ce9982d0 786 [SEL_CONTEXT] = sel_write_context,
1da177e4
LT
787};
788
789static ssize_t selinux_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos)
790{
496ad9aa 791 ino_t ino = file_inode(file)->i_ino;
1da177e4
LT
792 char *data;
793 ssize_t rv;
794
6e20a64a 795 if (ino >= ARRAY_SIZE(write_op) || !write_op[ino])
1da177e4
LT
796 return -EINVAL;
797
798 data = simple_transaction_get(file, buf, size);
799 if (IS_ERR(data))
800 return PTR_ERR(data);
801
1872981b
EP
802 rv = write_op[ino](file, data, size);
803 if (rv > 0) {
1da177e4
LT
804 simple_transaction_set(file, rv);
805 rv = size;
806 }
807 return rv;
808}
809
9c2e08c5 810static const struct file_operations transaction_ops = {
1da177e4
LT
811 .write = selinux_transaction_write,
812 .read = simple_transaction_read,
813 .release = simple_transaction_release,
57a62c23 814 .llseek = generic_file_llseek,
1da177e4
LT
815};
816
817/*
818 * payload - write methods
819 * If the method has a response, the response should be put in buf,
820 * and the length returned. Otherwise return 0 or and -error.
821 */
822
1872981b 823static ssize_t sel_write_access(struct file *file, char *buf, size_t size)
1da177e4 824{
0619f0f5
SS
825 struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
826 struct selinux_state *state = fsi->state;
b77a493b 827 char *scon = NULL, *tcon = NULL;
1da177e4
LT
828 u32 ssid, tsid;
829 u16 tclass;
1da177e4
LT
830 struct av_decision avd;
831 ssize_t length;
832
6b6bc620
SS
833 length = avc_has_perm(&selinux_state,
834 current_sid(), SECINITSID_SECURITY,
be0554c9 835 SECCLASS_SECURITY, SECURITY__COMPUTE_AV, NULL);
1da177e4 836 if (length)
b77a493b 837 goto out;
1da177e4
LT
838
839 length = -ENOMEM;
c1a7368a 840 scon = kzalloc(size + 1, GFP_KERNEL);
1da177e4 841 if (!scon)
b77a493b 842 goto out;
1da177e4 843
b77a493b 844 length = -ENOMEM;
c1a7368a 845 tcon = kzalloc(size + 1, GFP_KERNEL);
1da177e4
LT
846 if (!tcon)
847 goto out;
1da177e4
LT
848
849 length = -EINVAL;
19439d05 850 if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
b77a493b 851 goto out;
1da177e4 852
0619f0f5 853 length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL);
b77a493b
EP
854 if (length)
855 goto out;
856
0619f0f5 857 length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL);
b77a493b
EP
858 if (length)
859 goto out;
1da177e4 860
0619f0f5 861 security_compute_av_user(state, ssid, tsid, tclass, &avd);
1da177e4
LT
862
863 length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT,
8a6f83af 864 "%x %x %x %x %u %x",
f1c6381a 865 avd.allowed, 0xffffffff,
1da177e4 866 avd.auditallow, avd.auditdeny,
8a6f83af 867 avd.seqno, avd.flags);
1da177e4 868out:
b77a493b 869 kfree(tcon);
1da177e4
LT
870 kfree(scon);
871 return length;
872}
873
1872981b 874static ssize_t sel_write_create(struct file *file, char *buf, size_t size)
1da177e4 875{
0619f0f5
SS
876 struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
877 struct selinux_state *state = fsi->state;
b77a493b 878 char *scon = NULL, *tcon = NULL;
f50a3ec9 879 char *namebuf = NULL, *objname = NULL;
1da177e4
LT
880 u32 ssid, tsid, newsid;
881 u16 tclass;
882 ssize_t length;
b77a493b 883 char *newcon = NULL;
1da177e4 884 u32 len;
f50a3ec9 885 int nargs;
1da177e4 886
6b6bc620
SS
887 length = avc_has_perm(&selinux_state,
888 current_sid(), SECINITSID_SECURITY,
be0554c9
SS
889 SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE,
890 NULL);
1da177e4 891 if (length)
b77a493b 892 goto out;
1da177e4
LT
893
894 length = -ENOMEM;
c1a7368a 895 scon = kzalloc(size + 1, GFP_KERNEL);
1da177e4 896 if (!scon)
b77a493b 897 goto out;
1da177e4 898
b77a493b 899 length = -ENOMEM;
c1a7368a 900 tcon = kzalloc(size + 1, GFP_KERNEL);
1da177e4
LT
901 if (!tcon)
902 goto out;
1da177e4 903
f50a3ec9
KK
904 length = -ENOMEM;
905 namebuf = kzalloc(size + 1, GFP_KERNEL);
906 if (!namebuf)
907 goto out;
908
1da177e4 909 length = -EINVAL;
f50a3ec9
KK
910 nargs = sscanf(buf, "%s %s %hu %s", scon, tcon, &tclass, namebuf);
911 if (nargs < 3 || nargs > 4)
b77a493b 912 goto out;
0f7e4c33
KK
913 if (nargs == 4) {
914 /*
915 * If and when the name of new object to be queried contains
916 * either whitespace or multibyte characters, they shall be
917 * encoded based on the percentage-encoding rule.
918 * If not encoded, the sscanf logic picks up only left-half
919 * of the supplied name; splitted by a whitespace unexpectedly.
920 */
921 char *r, *w;
922 int c1, c2;
923
924 r = w = namebuf;
925 do {
926 c1 = *r++;
927 if (c1 == '+')
928 c1 = ' ';
929 else if (c1 == '%') {
af7ff2c2
AS
930 c1 = hex_to_bin(*r++);
931 if (c1 < 0)
0f7e4c33 932 goto out;
af7ff2c2
AS
933 c2 = hex_to_bin(*r++);
934 if (c2 < 0)
0f7e4c33
KK
935 goto out;
936 c1 = (c1 << 4) | c2;
937 }
938 *w++ = c1;
939 } while (c1 != '\0');
940
f50a3ec9 941 objname = namebuf;
0f7e4c33 942 }
1da177e4 943
0619f0f5 944 length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL);
b77a493b
EP
945 if (length)
946 goto out;
947
0619f0f5 948 length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL);
b77a493b
EP
949 if (length)
950 goto out;
1da177e4 951
0619f0f5
SS
952 length = security_transition_sid_user(state, ssid, tsid, tclass,
953 objname, &newsid);
b77a493b
EP
954 if (length)
955 goto out;
1da177e4 956
0619f0f5 957 length = security_sid_to_context(state, newsid, &newcon, &len);
b77a493b
EP
958 if (length)
959 goto out;
1da177e4 960
b77a493b 961 length = -ERANGE;
1da177e4 962 if (len > SIMPLE_TRANSACTION_LIMIT) {
f8b69a5f 963 pr_err("SELinux: %s: context size (%u) exceeds "
744ba35e 964 "payload max\n", __func__, len);
b77a493b 965 goto out;
1da177e4
LT
966 }
967
968 memcpy(buf, newcon, len);
969 length = len;
b77a493b 970out:
1da177e4 971 kfree(newcon);
f50a3ec9 972 kfree(namebuf);
1da177e4 973 kfree(tcon);
1da177e4
LT
974 kfree(scon);
975 return length;
976}
977
1872981b 978static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size)
1da177e4 979{
0619f0f5
SS
980 struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
981 struct selinux_state *state = fsi->state;
b77a493b 982 char *scon = NULL, *tcon = NULL;
1da177e4
LT
983 u32 ssid, tsid, newsid;
984 u16 tclass;
985 ssize_t length;
b77a493b 986 char *newcon = NULL;
1da177e4
LT
987 u32 len;
988
6b6bc620
SS
989 length = avc_has_perm(&selinux_state,
990 current_sid(), SECINITSID_SECURITY,
be0554c9
SS
991 SECCLASS_SECURITY, SECURITY__COMPUTE_RELABEL,
992 NULL);
1da177e4 993 if (length)
b77a493b 994 goto out;
1da177e4
LT
995
996 length = -ENOMEM;
c1a7368a 997 scon = kzalloc(size + 1, GFP_KERNEL);
1da177e4 998 if (!scon)
b77a493b 999 goto out;
1da177e4 1000
b77a493b 1001 length = -ENOMEM;
c1a7368a 1002 tcon = kzalloc(size + 1, GFP_KERNEL);
1da177e4
LT
1003 if (!tcon)
1004 goto out;
1da177e4
LT
1005
1006 length = -EINVAL;
1007 if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
b77a493b 1008 goto out;
1da177e4 1009
0619f0f5 1010 length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL);
b77a493b
EP
1011 if (length)
1012 goto out;
1013
0619f0f5 1014 length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL);
b77a493b
EP
1015 if (length)
1016 goto out;
1da177e4 1017
0619f0f5 1018 length = security_change_sid(state, ssid, tsid, tclass, &newsid);
b77a493b
EP
1019 if (length)
1020 goto out;
1da177e4 1021
0619f0f5 1022 length = security_sid_to_context(state, newsid, &newcon, &len);
b77a493b
EP
1023 if (length)
1024 goto out;
1da177e4 1025
b77a493b
EP
1026 length = -ERANGE;
1027 if (len > SIMPLE_TRANSACTION_LIMIT)
1028 goto out;
1da177e4
LT
1029
1030 memcpy(buf, newcon, len);
1031 length = len;
b77a493b 1032out:
1da177e4 1033 kfree(newcon);
1da177e4 1034 kfree(tcon);
1da177e4
LT
1035 kfree(scon);
1036 return length;
1037}
1038
1872981b 1039static ssize_t sel_write_user(struct file *file, char *buf, size_t size)
1da177e4 1040{
0619f0f5
SS
1041 struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
1042 struct selinux_state *state = fsi->state;
b77a493b
EP
1043 char *con = NULL, *user = NULL, *ptr;
1044 u32 sid, *sids = NULL;
1da177e4
LT
1045 ssize_t length;
1046 char *newcon;
1047 int i, rc;
1048 u32 len, nsids;
1049
6b6bc620
SS
1050 length = avc_has_perm(&selinux_state,
1051 current_sid(), SECINITSID_SECURITY,
be0554c9
SS
1052 SECCLASS_SECURITY, SECURITY__COMPUTE_USER,
1053 NULL);
1da177e4 1054 if (length)
6eab04a8 1055 goto out;
1da177e4
LT
1056
1057 length = -ENOMEM;
c1a7368a 1058 con = kzalloc(size + 1, GFP_KERNEL);
1da177e4 1059 if (!con)
6eab04a8 1060 goto out;
1da177e4 1061
b77a493b 1062 length = -ENOMEM;
c1a7368a 1063 user = kzalloc(size + 1, GFP_KERNEL);
1da177e4
LT
1064 if (!user)
1065 goto out;
1da177e4
LT
1066
1067 length = -EINVAL;
1068 if (sscanf(buf, "%s %s", con, user) != 2)
b77a493b 1069 goto out;
1da177e4 1070
0619f0f5 1071 length = security_context_str_to_sid(state, con, &sid, GFP_KERNEL);
b77a493b
EP
1072 if (length)
1073 goto out;
1da177e4 1074
0619f0f5 1075 length = security_get_user_sids(state, sid, user, &sids, &nsids);
b77a493b
EP
1076 if (length)
1077 goto out;
1da177e4
LT
1078
1079 length = sprintf(buf, "%u", nsids) + 1;
1080 ptr = buf + length;
1081 for (i = 0; i < nsids; i++) {
0619f0f5 1082 rc = security_sid_to_context(state, sids[i], &newcon, &len);
1da177e4
LT
1083 if (rc) {
1084 length = rc;
b77a493b 1085 goto out;
1da177e4
LT
1086 }
1087 if ((length + len) >= SIMPLE_TRANSACTION_LIMIT) {
1088 kfree(newcon);
1089 length = -ERANGE;
b77a493b 1090 goto out;
1da177e4
LT
1091 }
1092 memcpy(ptr, newcon, len);
1093 kfree(newcon);
1094 ptr += len;
1095 length += len;
1096 }
b77a493b 1097out:
1da177e4 1098 kfree(sids);
1da177e4 1099 kfree(user);
1da177e4
LT
1100 kfree(con);
1101 return length;
1102}
1103
1872981b 1104static ssize_t sel_write_member(struct file *file, char *buf, size_t size)
1da177e4 1105{
0619f0f5
SS
1106 struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
1107 struct selinux_state *state = fsi->state;
b77a493b 1108 char *scon = NULL, *tcon = NULL;
1da177e4
LT
1109 u32 ssid, tsid, newsid;
1110 u16 tclass;
1111 ssize_t length;
b77a493b 1112 char *newcon = NULL;
1da177e4
LT
1113 u32 len;
1114
6b6bc620
SS
1115 length = avc_has_perm(&selinux_state,
1116 current_sid(), SECINITSID_SECURITY,
be0554c9
SS
1117 SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER,
1118 NULL);
1da177e4 1119 if (length)
b77a493b 1120 goto out;
1da177e4
LT
1121
1122 length = -ENOMEM;
c1a7368a 1123 scon = kzalloc(size + 1, GFP_KERNEL);
1da177e4 1124 if (!scon)
6eab04a8 1125 goto out;
1da177e4 1126
b77a493b 1127 length = -ENOMEM;
c1a7368a 1128 tcon = kzalloc(size + 1, GFP_KERNEL);
1da177e4
LT
1129 if (!tcon)
1130 goto out;
1da177e4
LT
1131
1132 length = -EINVAL;
1133 if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3)
b77a493b 1134 goto out;
1da177e4 1135
0619f0f5 1136 length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL);
b77a493b
EP
1137 if (length)
1138 goto out;
1139
0619f0f5 1140 length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL);
b77a493b
EP
1141 if (length)
1142 goto out;
1da177e4 1143
0619f0f5 1144 length = security_member_sid(state, ssid, tsid, tclass, &newsid);
b77a493b
EP
1145 if (length)
1146 goto out;
1da177e4 1147
0619f0f5 1148 length = security_sid_to_context(state, newsid, &newcon, &len);
b77a493b
EP
1149 if (length)
1150 goto out;
1da177e4 1151
b77a493b 1152 length = -ERANGE;
1da177e4 1153 if (len > SIMPLE_TRANSACTION_LIMIT) {
f8b69a5f 1154 pr_err("SELinux: %s: context size (%u) exceeds "
744ba35e 1155 "payload max\n", __func__, len);
b77a493b 1156 goto out;
1da177e4
LT
1157 }
1158
1159 memcpy(buf, newcon, len);
1160 length = len;
b77a493b 1161out:
1da177e4 1162 kfree(newcon);
1da177e4 1163 kfree(tcon);
1da177e4
LT
1164 kfree(scon);
1165 return length;
1166}
1167
1168static struct inode *sel_make_inode(struct super_block *sb, int mode)
1169{
1170 struct inode *ret = new_inode(sb);
1171
1172 if (ret) {
1173 ret->i_mode = mode;
078cd827 1174 ret->i_atime = ret->i_mtime = ret->i_ctime = current_time(ret);
1da177e4
LT
1175 }
1176 return ret;
1177}
1178
1da177e4
LT
1179static ssize_t sel_read_bool(struct file *filep, char __user *buf,
1180 size_t count, loff_t *ppos)
1181{
0619f0f5 1182 struct selinux_fs_info *fsi = file_inode(filep)->i_sb->s_fs_info;
1da177e4
LT
1183 char *page = NULL;
1184 ssize_t length;
1da177e4
LT
1185 ssize_t ret;
1186 int cur_enforcing;
496ad9aa 1187 unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK;
d313f948 1188 const char *name = filep->f_path.dentry->d_name.name;
1da177e4 1189
0619f0f5 1190 mutex_lock(&fsi->mutex);
1da177e4 1191
b77a493b 1192 ret = -EINVAL;
0619f0f5
SS
1193 if (index >= fsi->bool_num || strcmp(name,
1194 fsi->bool_pending_names[index]))
0da74120 1195 goto out_unlock;
1da177e4 1196
b77a493b 1197 ret = -ENOMEM;
1872981b 1198 page = (char *)get_zeroed_page(GFP_KERNEL);
b77a493b 1199 if (!page)
0da74120 1200 goto out_unlock;
1da177e4 1201
0619f0f5 1202 cur_enforcing = security_get_bool_value(fsi->state, index);
1da177e4
LT
1203 if (cur_enforcing < 0) {
1204 ret = cur_enforcing;
0da74120 1205 goto out_unlock;
1da177e4 1206 }
1da177e4 1207 length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing,
0619f0f5 1208 fsi->bool_pending_values[index]);
0619f0f5 1209 mutex_unlock(&fsi->mutex);
0da74120
JH
1210 ret = simple_read_from_buffer(buf, count, ppos, page, length);
1211out_free:
b77a493b 1212 free_page((unsigned long)page);
1da177e4 1213 return ret;
0da74120
JH
1214
1215out_unlock:
1216 mutex_unlock(&fsi->mutex);
1217 goto out_free;
1da177e4
LT
1218}
1219
1220static ssize_t sel_write_bool(struct file *filep, const char __user *buf,
1221 size_t count, loff_t *ppos)
1222{
0619f0f5 1223 struct selinux_fs_info *fsi = file_inode(filep)->i_sb->s_fs_info;
1da177e4 1224 char *page = NULL;
d313f948 1225 ssize_t length;
1da177e4 1226 int new_value;
496ad9aa 1227 unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK;
d313f948 1228 const char *name = filep->f_path.dentry->d_name.name;
1da177e4 1229
0da74120
JH
1230 if (count >= PAGE_SIZE)
1231 return -ENOMEM;
1232
1233 /* No partial writes. */
1234 if (*ppos != 0)
1235 return -EINVAL;
1236
1237 page = memdup_user_nul(buf, count);
1238 if (IS_ERR(page))
1239 return PTR_ERR(page);
1240
0619f0f5 1241 mutex_lock(&fsi->mutex);
1da177e4 1242
6b6bc620
SS
1243 length = avc_has_perm(&selinux_state,
1244 current_sid(), SECINITSID_SECURITY,
be0554c9
SS
1245 SECCLASS_SECURITY, SECURITY__SETBOOL,
1246 NULL);
1da177e4
LT
1247 if (length)
1248 goto out;
1249
b77a493b 1250 length = -EINVAL;
0619f0f5
SS
1251 if (index >= fsi->bool_num || strcmp(name,
1252 fsi->bool_pending_names[index]))
d313f948 1253 goto out;
d313f948 1254
1da177e4
LT
1255 length = -EINVAL;
1256 if (sscanf(page, "%d", &new_value) != 1)
1257 goto out;
1258
1259 if (new_value)
1260 new_value = 1;
1261
0619f0f5 1262 fsi->bool_pending_values[index] = new_value;
1da177e4
LT
1263 length = count;
1264
1265out:
0619f0f5 1266 mutex_unlock(&fsi->mutex);
8365a719 1267 kfree(page);
1da177e4
LT
1268 return length;
1269}
1270
9c2e08c5 1271static const struct file_operations sel_bool_ops = {
1872981b
EP
1272 .read = sel_read_bool,
1273 .write = sel_write_bool,
57a62c23 1274 .llseek = generic_file_llseek,
1da177e4
LT
1275};
1276
1277static ssize_t sel_commit_bools_write(struct file *filep,
1278 const char __user *buf,
1279 size_t count, loff_t *ppos)
1280{
0619f0f5 1281 struct selinux_fs_info *fsi = file_inode(filep)->i_sb->s_fs_info;
1da177e4 1282 char *page = NULL;
d313f948 1283 ssize_t length;
1da177e4
LT
1284 int new_value;
1285
0da74120
JH
1286 if (count >= PAGE_SIZE)
1287 return -ENOMEM;
1288
1289 /* No partial writes. */
1290 if (*ppos != 0)
1291 return -EINVAL;
1292
1293 page = memdup_user_nul(buf, count);
1294 if (IS_ERR(page))
1295 return PTR_ERR(page);
1296
0619f0f5 1297 mutex_lock(&fsi->mutex);
1da177e4 1298
6b6bc620
SS
1299 length = avc_has_perm(&selinux_state,
1300 current_sid(), SECINITSID_SECURITY,
be0554c9
SS
1301 SECCLASS_SECURITY, SECURITY__SETBOOL,
1302 NULL);
1da177e4
LT
1303 if (length)
1304 goto out;
1305
1da177e4
LT
1306 length = -EINVAL;
1307 if (sscanf(page, "%d", &new_value) != 1)
1308 goto out;
1309
b77a493b 1310 length = 0;
0619f0f5
SS
1311 if (new_value && fsi->bool_pending_values)
1312 length = security_set_bools(fsi->state, fsi->bool_num,
1313 fsi->bool_pending_values);
1da177e4 1314
b77a493b
EP
1315 if (!length)
1316 length = count;
1da177e4
LT
1317
1318out:
0619f0f5 1319 mutex_unlock(&fsi->mutex);
8365a719 1320 kfree(page);
1da177e4
LT
1321 return length;
1322}
1323
9c2e08c5 1324static const struct file_operations sel_commit_bools_ops = {
1872981b 1325 .write = sel_commit_bools_write,
57a62c23 1326 .llseek = generic_file_llseek,
1da177e4
LT
1327};
1328
0c92d7c7 1329static void sel_remove_entries(struct dentry *de)
1da177e4 1330{
ad52184b
AV
1331 d_genocide(de);
1332 shrink_dcache_parent(de);
1da177e4
LT
1333}
1334
1335#define BOOL_DIR_NAME "booleans"
1336
02a52c5c
SS
1337static int sel_make_bools(struct selinux_fs_info *fsi,
1338 struct selinux_policy *newpolicy)
1da177e4 1339{
60abd318 1340 int ret;
1da177e4
LT
1341 ssize_t len;
1342 struct dentry *dentry = NULL;
0619f0f5 1343 struct dentry *dir = fsi->bool_dir;
1da177e4
LT
1344 struct inode *inode = NULL;
1345 struct inode_security_struct *isec;
1346 char **names = NULL, *page;
60abd318 1347 u32 i, num;
1da177e4
LT
1348 int *values = NULL;
1349 u32 sid;
1350
1351 /* remove any existing files */
0619f0f5
SS
1352 for (i = 0; i < fsi->bool_num; i++)
1353 kfree(fsi->bool_pending_names[i]);
1354 kfree(fsi->bool_pending_names);
1355 kfree(fsi->bool_pending_values);
1356 fsi->bool_num = 0;
1357 fsi->bool_pending_names = NULL;
1358 fsi->bool_pending_values = NULL;
1da177e4 1359
0c92d7c7 1360 sel_remove_entries(dir);
1da177e4 1361
b77a493b 1362 ret = -ENOMEM;
1872981b
EP
1363 page = (char *)get_zeroed_page(GFP_KERNEL);
1364 if (!page)
b77a493b 1365 goto out;
1da177e4 1366
02a52c5c 1367 ret = security_get_bools(newpolicy, &num, &names, &values);
b77a493b 1368 if (ret)
1da177e4
LT
1369 goto out;
1370
1371 for (i = 0; i < num; i++) {
b77a493b 1372 ret = -ENOMEM;
1da177e4 1373 dentry = d_alloc_name(dir, names[i]);
b77a493b
EP
1374 if (!dentry)
1375 goto out;
1376
1377 ret = -ENOMEM;
1da177e4 1378 inode = sel_make_inode(dir->d_sb, S_IFREG | S_IRUGO | S_IWUSR);
7e4237fa 1379 if (!inode) {
1380 dput(dentry);
b77a493b 1381 goto out;
7e4237fa 1382 }
1da177e4 1383
b77a493b 1384 ret = -ENAMETOOLONG;
cc1dad71 1385 len = snprintf(page, PAGE_SIZE, "/%s/%s", BOOL_DIR_NAME, names[i]);
7e4237fa 1386 if (len >= PAGE_SIZE) {
1387 dput(dentry);
1388 iput(inode);
b77a493b 1389 goto out;
7e4237fa 1390 }
b77a493b 1391
80788c22 1392 isec = selinux_inode(inode);
02a52c5c 1393 ret = selinux_policy_genfs_sid(newpolicy, "selinuxfs", page,
aa8e712c 1394 SECCLASS_FILE, &sid);
4262fb51 1395 if (ret) {
900fde06
GT
1396 pr_warn_ratelimited("SELinux: no sid found, defaulting to security isid for %s\n",
1397 page);
1398 sid = SECINITSID_SECURITY;
4262fb51
GT
1399 }
1400
1da177e4 1401 isec->sid = sid;
42059112 1402 isec->initialized = LABEL_INITIALIZED;
1da177e4 1403 inode->i_fop = &sel_bool_ops;
bce34bc0 1404 inode->i_ino = i|SEL_BOOL_INO_OFFSET;
1da177e4
LT
1405 d_add(dentry, inode);
1406 }
0619f0f5
SS
1407 fsi->bool_num = num;
1408 fsi->bool_pending_names = names;
1409 fsi->bool_pending_values = values;
b77a493b
EP
1410
1411 free_page((unsigned long)page);
1412 return 0;
1da177e4
LT
1413out:
1414 free_page((unsigned long)page);
b77a493b 1415
1da177e4 1416 if (names) {
9a5f04bf
JJ
1417 for (i = 0; i < num; i++)
1418 kfree(names[i]);
1da177e4
LT
1419 kfree(names);
1420 }
20c19e41 1421 kfree(values);
0c92d7c7 1422 sel_remove_entries(dir);
b77a493b
EP
1423
1424 return ret;
1da177e4
LT
1425}
1426
1da177e4
LT
1427static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf,
1428 size_t count, loff_t *ppos)
1429{
6b6bc620
SS
1430 struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
1431 struct selinux_state *state = fsi->state;
1da177e4
LT
1432 char tmpbuf[TMPBUFLEN];
1433 ssize_t length;
1434
6b6bc620
SS
1435 length = scnprintf(tmpbuf, TMPBUFLEN, "%u",
1436 avc_get_cache_threshold(state->avc));
1da177e4
LT
1437 return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
1438}
1439
1872981b
EP
1440static ssize_t sel_write_avc_cache_threshold(struct file *file,
1441 const char __user *buf,
1da177e4
LT
1442 size_t count, loff_t *ppos)
1443
1444{
6b6bc620
SS
1445 struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
1446 struct selinux_state *state = fsi->state;
8365a719 1447 char *page;
1da177e4 1448 ssize_t ret;
309c5fad 1449 unsigned int new_value;
1da177e4 1450
6b6bc620
SS
1451 ret = avc_has_perm(&selinux_state,
1452 current_sid(), SECINITSID_SECURITY,
be0554c9
SS
1453 SECCLASS_SECURITY, SECURITY__SETSECPARAM,
1454 NULL);
b77a493b 1455 if (ret)
8365a719 1456 return ret;
1da177e4 1457
b77a493b 1458 if (count >= PAGE_SIZE)
8365a719 1459 return -ENOMEM;
1da177e4 1460
b77a493b 1461 /* No partial writes. */
b77a493b 1462 if (*ppos != 0)
8365a719 1463 return -EINVAL;
1da177e4 1464
8365a719
AV
1465 page = memdup_user_nul(buf, count);
1466 if (IS_ERR(page))
1467 return PTR_ERR(page);
1da177e4 1468
b77a493b
EP
1469 ret = -EINVAL;
1470 if (sscanf(page, "%u", &new_value) != 1)
1da177e4 1471 goto out;
1da177e4 1472
6b6bc620 1473 avc_set_cache_threshold(state->avc, new_value);
b77a493b 1474
1da177e4 1475 ret = count;
1da177e4 1476out:
8365a719 1477 kfree(page);
1da177e4
LT
1478 return ret;
1479}
1480
1481static ssize_t sel_read_avc_hash_stats(struct file *filp, char __user *buf,
1482 size_t count, loff_t *ppos)
1483{
6b6bc620
SS
1484 struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
1485 struct selinux_state *state = fsi->state;
1da177e4 1486 char *page;
b77a493b 1487 ssize_t length;
1da177e4
LT
1488
1489 page = (char *)__get_free_page(GFP_KERNEL);
b77a493b
EP
1490 if (!page)
1491 return -ENOMEM;
1492
6b6bc620 1493 length = avc_get_hash_stats(state->avc, page);
b77a493b
EP
1494 if (length >= 0)
1495 length = simple_read_from_buffer(buf, count, ppos, page, length);
1da177e4 1496 free_page((unsigned long)page);
b77a493b
EP
1497
1498 return length;
1da177e4
LT
1499}
1500
66f8e2f0
JVS
1501static ssize_t sel_read_sidtab_hash_stats(struct file *filp, char __user *buf,
1502 size_t count, loff_t *ppos)
1503{
1504 struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info;
1505 struct selinux_state *state = fsi->state;
1506 char *page;
1507 ssize_t length;
1508
1509 page = (char *)__get_free_page(GFP_KERNEL);
1510 if (!page)
1511 return -ENOMEM;
1512
1513 length = security_sidtab_hash_stats(state, page);
1514 if (length >= 0)
1515 length = simple_read_from_buffer(buf, count, ppos, page,
1516 length);
1517 free_page((unsigned long)page);
1518
1519 return length;
1520}
1521
1522static const struct file_operations sel_sidtab_hash_stats_ops = {
1523 .read = sel_read_sidtab_hash_stats,
1524 .llseek = generic_file_llseek,
1525};
1526
9c2e08c5 1527static const struct file_operations sel_avc_cache_threshold_ops = {
1da177e4
LT
1528 .read = sel_read_avc_cache_threshold,
1529 .write = sel_write_avc_cache_threshold,
57a62c23 1530 .llseek = generic_file_llseek,
1da177e4
LT
1531};
1532
9c2e08c5 1533static const struct file_operations sel_avc_hash_stats_ops = {
1da177e4 1534 .read = sel_read_avc_hash_stats,
57a62c23 1535 .llseek = generic_file_llseek,
1da177e4
LT
1536};
1537
1538#ifdef CONFIG_SECURITY_SELINUX_AVC_STATS
1539static struct avc_cache_stats *sel_avc_get_stat_idx(loff_t *idx)
1540{
1541 int cpu;
1542
4f4b6c1a 1543 for (cpu = *idx; cpu < nr_cpu_ids; ++cpu) {
1da177e4
LT
1544 if (!cpu_possible(cpu))
1545 continue;
1546 *idx = cpu + 1;
1547 return &per_cpu(avc_cache_stats, cpu);
1548 }
8d269a8e 1549 (*idx)++;
1da177e4
LT
1550 return NULL;
1551}
1552
1553static void *sel_avc_stats_seq_start(struct seq_file *seq, loff_t *pos)
1554{
1555 loff_t n = *pos - 1;
1556
1557 if (*pos == 0)
1558 return SEQ_START_TOKEN;
1559
1560 return sel_avc_get_stat_idx(&n);
1561}
1562
1563static void *sel_avc_stats_seq_next(struct seq_file *seq, void *v, loff_t *pos)
1564{
1565 return sel_avc_get_stat_idx(pos);
1566}
1567
1568static int sel_avc_stats_seq_show(struct seq_file *seq, void *v)
1569{
1570 struct avc_cache_stats *st = v;
1571
710a0647
ME
1572 if (v == SEQ_START_TOKEN) {
1573 seq_puts(seq,
1574 "lookups hits misses allocations reclaims frees\n");
1575 } else {
257313b2
LT
1576 unsigned int lookups = st->lookups;
1577 unsigned int misses = st->misses;
1578 unsigned int hits = lookups - misses;
1579 seq_printf(seq, "%u %u %u %u %u %u\n", lookups,
1580 hits, misses, st->allocations,
1da177e4 1581 st->reclaims, st->frees);
257313b2 1582 }
1da177e4
LT
1583 return 0;
1584}
1585
1586static void sel_avc_stats_seq_stop(struct seq_file *seq, void *v)
1587{ }
1588
1996a109 1589static const struct seq_operations sel_avc_cache_stats_seq_ops = {
1da177e4
LT
1590 .start = sel_avc_stats_seq_start,
1591 .next = sel_avc_stats_seq_next,
1592 .show = sel_avc_stats_seq_show,
1593 .stop = sel_avc_stats_seq_stop,
1594};
1595
1596static int sel_open_avc_cache_stats(struct inode *inode, struct file *file)
1597{
1598 return seq_open(file, &sel_avc_cache_stats_seq_ops);
1599}
1600
9c2e08c5 1601static const struct file_operations sel_avc_cache_stats_ops = {
1da177e4
LT
1602 .open = sel_open_avc_cache_stats,
1603 .read = seq_read,
1604 .llseek = seq_lseek,
1605 .release = seq_release,
1606};
1607#endif
1608
1609static int sel_make_avc_files(struct dentry *dir)
1610{
0619f0f5
SS
1611 struct super_block *sb = dir->d_sb;
1612 struct selinux_fs_info *fsi = sb->s_fs_info;
b77a493b 1613 int i;
cda37124 1614 static const struct tree_descr files[] = {
1da177e4
LT
1615 { "cache_threshold",
1616 &sel_avc_cache_threshold_ops, S_IRUGO|S_IWUSR },
1617 { "hash_stats", &sel_avc_hash_stats_ops, S_IRUGO },
1618#ifdef CONFIG_SECURITY_SELINUX_AVC_STATS
1619 { "cache_stats", &sel_avc_cache_stats_ops, S_IRUGO },
1620#endif
1621 };
1622
6e20a64a 1623 for (i = 0; i < ARRAY_SIZE(files); i++) {
1da177e4
LT
1624 struct inode *inode;
1625 struct dentry *dentry;
1626
1627 dentry = d_alloc_name(dir, files[i].name);
b77a493b
EP
1628 if (!dentry)
1629 return -ENOMEM;
1da177e4
LT
1630
1631 inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode);
7e4237fa 1632 if (!inode) {
1633 dput(dentry);
b77a493b 1634 return -ENOMEM;
7e4237fa 1635 }
b77a493b 1636
1da177e4 1637 inode->i_fop = files[i].ops;
0619f0f5 1638 inode->i_ino = ++fsi->last_ino;
1da177e4
LT
1639 d_add(dentry, inode);
1640 }
b77a493b
EP
1641
1642 return 0;
1da177e4
LT
1643}
1644
66f8e2f0
JVS
1645static int sel_make_ss_files(struct dentry *dir)
1646{
1647 struct super_block *sb = dir->d_sb;
1648 struct selinux_fs_info *fsi = sb->s_fs_info;
1649 int i;
1650 static struct tree_descr files[] = {
1651 { "sidtab_hash_stats", &sel_sidtab_hash_stats_ops, S_IRUGO },
1652 };
1653
1654 for (i = 0; i < ARRAY_SIZE(files); i++) {
1655 struct inode *inode;
1656 struct dentry *dentry;
1657
1658 dentry = d_alloc_name(dir, files[i].name);
1659 if (!dentry)
1660 return -ENOMEM;
1661
1662 inode = sel_make_inode(dir->d_sb, S_IFREG|files[i].mode);
1663 if (!inode) {
1664 dput(dentry);
1665 return -ENOMEM;
1666 }
1667
1668 inode->i_fop = files[i].ops;
1669 inode->i_ino = ++fsi->last_ino;
1670 d_add(dentry, inode);
1671 }
1672
1673 return 0;
1674}
1675
1872981b 1676static ssize_t sel_read_initcon(struct file *file, char __user *buf,
f0ee2e46
JC
1677 size_t count, loff_t *ppos)
1678{
0619f0f5 1679 struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
f0ee2e46
JC
1680 char *con;
1681 u32 sid, len;
1682 ssize_t ret;
1683
496ad9aa 1684 sid = file_inode(file)->i_ino&SEL_INO_MASK;
0619f0f5 1685 ret = security_sid_to_context(fsi->state, sid, &con, &len);
b77a493b 1686 if (ret)
f0ee2e46
JC
1687 return ret;
1688
1689 ret = simple_read_from_buffer(buf, count, ppos, con, len);
1690 kfree(con);
1691 return ret;
1692}
1693
1694static const struct file_operations sel_initcon_ops = {
1695 .read = sel_read_initcon,
57a62c23 1696 .llseek = generic_file_llseek,
f0ee2e46
JC
1697};
1698
1699static int sel_make_initcon_files(struct dentry *dir)
1700{
b77a493b 1701 int i;
f0ee2e46
JC
1702
1703 for (i = 1; i <= SECINITSID_NUM; i++) {
1704 struct inode *inode;
1705 struct dentry *dentry;
e3e0b582
SS
1706 const char *s = security_get_initial_sid_context(i);
1707
1708 if (!s)
1709 continue;
1710 dentry = d_alloc_name(dir, s);
b77a493b
EP
1711 if (!dentry)
1712 return -ENOMEM;
f0ee2e46
JC
1713
1714 inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
7e4237fa 1715 if (!inode) {
1716 dput(dentry);
b77a493b 1717 return -ENOMEM;
7e4237fa 1718 }
b77a493b 1719
f0ee2e46
JC
1720 inode->i_fop = &sel_initcon_ops;
1721 inode->i_ino = i|SEL_INITCON_INO_OFFSET;
1722 d_add(dentry, inode);
1723 }
b77a493b
EP
1724
1725 return 0;
f0ee2e46
JC
1726}
1727
e47c8fc5
CP
1728static inline unsigned long sel_class_to_ino(u16 class)
1729{
1730 return (class * (SEL_VEC_MAX + 1)) | SEL_CLASS_INO_OFFSET;
1731}
1732
1733static inline u16 sel_ino_to_class(unsigned long ino)
1734{
92ae9e82 1735 return (ino & SEL_INO_MASK) / (SEL_VEC_MAX + 1);
e47c8fc5
CP
1736}
1737
1738static inline unsigned long sel_perm_to_ino(u16 class, u32 perm)
1739{
1740 return (class * (SEL_VEC_MAX + 1) + perm) | SEL_CLASS_INO_OFFSET;
1741}
1742
1743static inline u32 sel_ino_to_perm(unsigned long ino)
1744{
1745 return (ino & SEL_INO_MASK) % (SEL_VEC_MAX + 1);
1746}
1747
1872981b 1748static ssize_t sel_read_class(struct file *file, char __user *buf,
e47c8fc5
CP
1749 size_t count, loff_t *ppos)
1750{
496ad9aa 1751 unsigned long ino = file_inode(file)->i_ino;
cc1dad71 1752 char res[TMPBUFLEN];
7e78c875 1753 ssize_t len = scnprintf(res, sizeof(res), "%d", sel_ino_to_class(ino));
cc1dad71 1754 return simple_read_from_buffer(buf, count, ppos, res, len);
e47c8fc5
CP
1755}
1756
1757static const struct file_operations sel_class_ops = {
1758 .read = sel_read_class,
57a62c23 1759 .llseek = generic_file_llseek,
e47c8fc5
CP
1760};
1761
1872981b 1762static ssize_t sel_read_perm(struct file *file, char __user *buf,
e47c8fc5
CP
1763 size_t count, loff_t *ppos)
1764{
496ad9aa 1765 unsigned long ino = file_inode(file)->i_ino;
cc1dad71 1766 char res[TMPBUFLEN];
7e78c875 1767 ssize_t len = scnprintf(res, sizeof(res), "%d", sel_ino_to_perm(ino));
cc1dad71 1768 return simple_read_from_buffer(buf, count, ppos, res, len);
e47c8fc5
CP
1769}
1770
1771static const struct file_operations sel_perm_ops = {
1772 .read = sel_read_perm,
57a62c23 1773 .llseek = generic_file_llseek,
e47c8fc5
CP
1774};
1775
3bb56b25
PM
1776static ssize_t sel_read_policycap(struct file *file, char __user *buf,
1777 size_t count, loff_t *ppos)
1778{
0619f0f5 1779 struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info;
3bb56b25
PM
1780 int value;
1781 char tmpbuf[TMPBUFLEN];
1782 ssize_t length;
496ad9aa 1783 unsigned long i_ino = file_inode(file)->i_ino;
3bb56b25 1784
0619f0f5 1785 value = security_policycap_supported(fsi->state, i_ino & SEL_INO_MASK);
3bb56b25
PM
1786 length = scnprintf(tmpbuf, TMPBUFLEN, "%d", value);
1787
1788 return simple_read_from_buffer(buf, count, ppos, tmpbuf, length);
1789}
1790
1791static const struct file_operations sel_policycap_ops = {
1792 .read = sel_read_policycap,
57a62c23 1793 .llseek = generic_file_llseek,
3bb56b25
PM
1794};
1795
02a52c5c
SS
1796static int sel_make_perm_files(struct selinux_policy *newpolicy,
1797 char *objclass, int classvalue,
1798 struct dentry *dir)
e47c8fc5 1799{
b77a493b 1800 int i, rc, nperms;
e47c8fc5
CP
1801 char **perms;
1802
02a52c5c 1803 rc = security_get_permissions(newpolicy, objclass, &perms, &nperms);
e47c8fc5 1804 if (rc)
b77a493b 1805 return rc;
e47c8fc5
CP
1806
1807 for (i = 0; i < nperms; i++) {
1808 struct inode *inode;
1809 struct dentry *dentry;
1810
b77a493b 1811 rc = -ENOMEM;
e47c8fc5 1812 dentry = d_alloc_name(dir, perms[i]);
b77a493b
EP
1813 if (!dentry)
1814 goto out;
e47c8fc5 1815
b77a493b 1816 rc = -ENOMEM;
e47c8fc5 1817 inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
7e4237fa 1818 if (!inode) {
1819 dput(dentry);
b77a493b 1820 goto out;
7e4237fa 1821 }
b77a493b 1822
e47c8fc5
CP
1823 inode->i_fop = &sel_perm_ops;
1824 /* i+1 since perm values are 1-indexed */
c1a7368a 1825 inode->i_ino = sel_perm_to_ino(classvalue, i + 1);
e47c8fc5
CP
1826 d_add(dentry, inode);
1827 }
b77a493b
EP
1828 rc = 0;
1829out:
e47c8fc5
CP
1830 for (i = 0; i < nperms; i++)
1831 kfree(perms[i]);
1832 kfree(perms);
e47c8fc5
CP
1833 return rc;
1834}
1835
02a52c5c
SS
1836static int sel_make_class_dir_entries(struct selinux_policy *newpolicy,
1837 char *classname, int index,
1838 struct dentry *dir)
e47c8fc5 1839{
0619f0f5
SS
1840 struct super_block *sb = dir->d_sb;
1841 struct selinux_fs_info *fsi = sb->s_fs_info;
e47c8fc5
CP
1842 struct dentry *dentry = NULL;
1843 struct inode *inode = NULL;
1844 int rc;
1845
1846 dentry = d_alloc_name(dir, "index");
b77a493b
EP
1847 if (!dentry)
1848 return -ENOMEM;
e47c8fc5
CP
1849
1850 inode = sel_make_inode(dir->d_sb, S_IFREG|S_IRUGO);
7e4237fa 1851 if (!inode) {
1852 dput(dentry);
b77a493b 1853 return -ENOMEM;
7e4237fa 1854 }
e47c8fc5
CP
1855
1856 inode->i_fop = &sel_class_ops;
1857 inode->i_ino = sel_class_to_ino(index);
1858 d_add(dentry, inode);
1859
0619f0f5 1860 dentry = sel_make_dir(dir, "perms", &fsi->last_class_ino);
a1c2aa1e
AV
1861 if (IS_ERR(dentry))
1862 return PTR_ERR(dentry);
e47c8fc5 1863
02a52c5c 1864 rc = sel_make_perm_files(newpolicy, classname, index, dentry);
e47c8fc5 1865
e47c8fc5
CP
1866 return rc;
1867}
1868
02a52c5c
SS
1869static int sel_make_classes(struct selinux_fs_info *fsi,
1870 struct selinux_policy *newpolicy)
e47c8fc5 1871{
0619f0f5 1872
b77a493b 1873 int rc, nclasses, i;
e47c8fc5
CP
1874 char **classes;
1875
1876 /* delete any existing entries */
0619f0f5 1877 sel_remove_entries(fsi->class_dir);
e47c8fc5 1878
02a52c5c 1879 rc = security_get_classes(newpolicy, &classes, &nclasses);
b77a493b
EP
1880 if (rc)
1881 return rc;
e47c8fc5
CP
1882
1883 /* +2 since classes are 1-indexed */
0619f0f5 1884 fsi->last_class_ino = sel_class_to_ino(nclasses + 2);
e47c8fc5
CP
1885
1886 for (i = 0; i < nclasses; i++) {
1887 struct dentry *class_name_dir;
1888
0619f0f5
SS
1889 class_name_dir = sel_make_dir(fsi->class_dir, classes[i],
1890 &fsi->last_class_ino);
a1c2aa1e
AV
1891 if (IS_ERR(class_name_dir)) {
1892 rc = PTR_ERR(class_name_dir);
b77a493b 1893 goto out;
a1c2aa1e 1894 }
e47c8fc5
CP
1895
1896 /* i+1 since class values are 1-indexed */
02a52c5c 1897 rc = sel_make_class_dir_entries(newpolicy, classes[i], i + 1,
e47c8fc5
CP
1898 class_name_dir);
1899 if (rc)
b77a493b 1900 goto out;
e47c8fc5 1901 }
b77a493b
EP
1902 rc = 0;
1903out:
e47c8fc5
CP
1904 for (i = 0; i < nclasses; i++)
1905 kfree(classes[i]);
1906 kfree(classes);
e47c8fc5
CP
1907 return rc;
1908}
1909
0619f0f5 1910static int sel_make_policycap(struct selinux_fs_info *fsi)
3bb56b25
PM
1911{
1912 unsigned int iter;
1913 struct dentry *dentry = NULL;
1914 struct inode *inode = NULL;
1915
3bb56b25 1916 for (iter = 0; iter <= POLICYDB_CAPABILITY_MAX; iter++) {
4dc2fce3 1917 if (iter < ARRAY_SIZE(selinux_policycap_names))
0619f0f5 1918 dentry = d_alloc_name(fsi->policycap_dir,
4dc2fce3 1919 selinux_policycap_names[iter]);
3bb56b25 1920 else
0619f0f5 1921 dentry = d_alloc_name(fsi->policycap_dir, "unknown");
3bb56b25
PM
1922
1923 if (dentry == NULL)
1924 return -ENOMEM;
1925
0619f0f5 1926 inode = sel_make_inode(fsi->sb, S_IFREG | 0444);
7e4237fa 1927 if (inode == NULL) {
1928 dput(dentry);
3bb56b25 1929 return -ENOMEM;
7e4237fa 1930 }
3bb56b25
PM
1931
1932 inode->i_fop = &sel_policycap_ops;
1933 inode->i_ino = iter | SEL_POLICYCAP_INO_OFFSET;
1934 d_add(dentry, inode);
1935 }
1936
1937 return 0;
1938}
1939
a1c2aa1e 1940static struct dentry *sel_make_dir(struct dentry *dir, const char *name,
0dd4ae51 1941 unsigned long *ino)
1da177e4 1942{
a1c2aa1e 1943 struct dentry *dentry = d_alloc_name(dir, name);
1da177e4
LT
1944 struct inode *inode;
1945
a1c2aa1e
AV
1946 if (!dentry)
1947 return ERR_PTR(-ENOMEM);
1948
1949 inode = sel_make_inode(dir->d_sb, S_IFDIR | S_IRUGO | S_IXUGO);
1950 if (!inode) {
1951 dput(dentry);
1952 return ERR_PTR(-ENOMEM);
1953 }
b77a493b 1954
1da177e4
LT
1955 inode->i_op = &simple_dir_inode_operations;
1956 inode->i_fop = &simple_dir_operations;
0dd4ae51 1957 inode->i_ino = ++(*ino);
40e906f8 1958 /* directory inodes start off with i_nlink == 2 (for "." entry) */
d8c76e6f 1959 inc_nlink(inode);
1da177e4 1960 d_add(dentry, inode);
edb20fb5 1961 /* bump link count on parent directory, too */
ce0b16dd 1962 inc_nlink(d_inode(dir));
b77a493b 1963
a1c2aa1e 1964 return dentry;
1da177e4
LT
1965}
1966
0619f0f5
SS
1967#define NULL_FILE_NAME "null"
1968
920f50b2 1969static int sel_fill_super(struct super_block *sb, struct fs_context *fc)
1da177e4 1970{
0619f0f5 1971 struct selinux_fs_info *fsi;
1da177e4
LT
1972 int ret;
1973 struct dentry *dentry;
a1c2aa1e 1974 struct inode *inode;
1da177e4
LT
1975 struct inode_security_struct *isec;
1976
cda37124 1977 static const struct tree_descr selinux_files[] = {
1da177e4
LT
1978 [SEL_LOAD] = {"load", &sel_load_ops, S_IRUSR|S_IWUSR},
1979 [SEL_ENFORCE] = {"enforce", &sel_enforce_ops, S_IRUGO|S_IWUSR},
ce9982d0 1980 [SEL_CONTEXT] = {"context", &transaction_ops, S_IRUGO|S_IWUGO},
1da177e4
LT
1981 [SEL_ACCESS] = {"access", &transaction_ops, S_IRUGO|S_IWUGO},
1982 [SEL_CREATE] = {"create", &transaction_ops, S_IRUGO|S_IWUGO},
1983 [SEL_RELABEL] = {"relabel", &transaction_ops, S_IRUGO|S_IWUGO},
1984 [SEL_USER] = {"user", &transaction_ops, S_IRUGO|S_IWUGO},
1985 [SEL_POLICYVERS] = {"policyvers", &sel_policyvers_ops, S_IRUGO},
1986 [SEL_COMMIT_BOOLS] = {"commit_pending_bools", &sel_commit_bools_ops, S_IWUSR},
1987 [SEL_MLS] = {"mls", &sel_mls_ops, S_IRUGO},
1988 [SEL_DISABLE] = {"disable", &sel_disable_ops, S_IWUSR},
1989 [SEL_MEMBER] = {"member", &transaction_ops, S_IRUGO|S_IWUGO},
1990 [SEL_CHECKREQPROT] = {"checkreqprot", &sel_checkreqprot_ops, S_IRUGO|S_IWUSR},
3f12070e
EP
1991 [SEL_REJECT_UNKNOWN] = {"reject_unknown", &sel_handle_unknown_ops, S_IRUGO},
1992 [SEL_DENY_UNKNOWN] = {"deny_unknown", &sel_handle_unknown_ops, S_IRUGO},
11904167 1993 [SEL_STATUS] = {"status", &sel_handle_status_ops, S_IRUGO},
72e8c859 1994 [SEL_POLICY] = {"policy", &sel_policy_ops, S_IRUGO},
f9df6458
AP
1995 [SEL_VALIDATE_TRANS] = {"validatetrans", &sel_transition_ops,
1996 S_IWUGO},
1da177e4
LT
1997 /* last one */ {""}
1998 };
0619f0f5
SS
1999
2000 ret = selinux_fs_info_create(sb);
2001 if (ret)
2002 goto err;
2003
1da177e4
LT
2004 ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files);
2005 if (ret)
161ce45a 2006 goto err;
1da177e4 2007
0619f0f5
SS
2008 fsi = sb->s_fs_info;
2009 fsi->bool_dir = sel_make_dir(sb->s_root, BOOL_DIR_NAME, &fsi->last_ino);
2010 if (IS_ERR(fsi->bool_dir)) {
2011 ret = PTR_ERR(fsi->bool_dir);
2012 fsi->bool_dir = NULL;
161ce45a 2013 goto err;
a1c2aa1e 2014 }
1da177e4 2015
b77a493b 2016 ret = -ENOMEM;
1da177e4 2017 dentry = d_alloc_name(sb->s_root, NULL_FILE_NAME);
b77a493b 2018 if (!dentry)
161ce45a 2019 goto err;
1da177e4 2020
b77a493b 2021 ret = -ENOMEM;
1da177e4 2022 inode = sel_make_inode(sb, S_IFCHR | S_IRUGO | S_IWUGO);
7e4237fa 2023 if (!inode) {
2024 dput(dentry);
161ce45a 2025 goto err;
7e4237fa 2026 }
b77a493b 2027
0619f0f5 2028 inode->i_ino = ++fsi->last_ino;
80788c22 2029 isec = selinux_inode(inode);
1da177e4
LT
2030 isec->sid = SECINITSID_DEVNULL;
2031 isec->sclass = SECCLASS_CHR_FILE;
42059112 2032 isec->initialized = LABEL_INITIALIZED;
1da177e4
LT
2033
2034 init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3));
2035 d_add(dentry, inode);
1da177e4 2036
0619f0f5 2037 dentry = sel_make_dir(sb->s_root, "avc", &fsi->last_ino);
a1c2aa1e
AV
2038 if (IS_ERR(dentry)) {
2039 ret = PTR_ERR(dentry);
161ce45a 2040 goto err;
a1c2aa1e 2041 }
1da177e4
LT
2042
2043 ret = sel_make_avc_files(dentry);
66f8e2f0
JVS
2044
2045 dentry = sel_make_dir(sb->s_root, "ss", &fsi->last_ino);
2046 if (IS_ERR(dentry)) {
2047 ret = PTR_ERR(dentry);
2048 goto err;
2049 }
2050
2051 ret = sel_make_ss_files(dentry);
1da177e4 2052 if (ret)
161ce45a 2053 goto err;
f0ee2e46 2054
0619f0f5 2055 dentry = sel_make_dir(sb->s_root, "initial_contexts", &fsi->last_ino);
a1c2aa1e
AV
2056 if (IS_ERR(dentry)) {
2057 ret = PTR_ERR(dentry);
f0ee2e46 2058 goto err;
a1c2aa1e 2059 }
f0ee2e46
JC
2060
2061 ret = sel_make_initcon_files(dentry);
2062 if (ret)
2063 goto err;
2064
0619f0f5
SS
2065 fsi->class_dir = sel_make_dir(sb->s_root, "class", &fsi->last_ino);
2066 if (IS_ERR(fsi->class_dir)) {
2067 ret = PTR_ERR(fsi->class_dir);
2068 fsi->class_dir = NULL;
3bb56b25 2069 goto err;
a1c2aa1e 2070 }
3bb56b25 2071
0619f0f5
SS
2072 fsi->policycap_dir = sel_make_dir(sb->s_root, "policy_capabilities",
2073 &fsi->last_ino);
2074 if (IS_ERR(fsi->policycap_dir)) {
2075 ret = PTR_ERR(fsi->policycap_dir);
2076 fsi->policycap_dir = NULL;
3bb56b25 2077 goto err;
a1c2aa1e 2078 }
0619f0f5 2079
02a52c5c
SS
2080 ret = sel_make_policycap(fsi);
2081 if (ret) {
2082 pr_err("SELinux: failed to load policy capabilities\n");
0619f0f5 2083 goto err;
02a52c5c
SS
2084 }
2085
b77a493b 2086 return 0;
161ce45a 2087err:
f8b69a5f 2088 pr_err("SELinux: %s: failed while creating inodes\n",
744ba35e 2089 __func__);
0619f0f5
SS
2090
2091 selinux_fs_info_free(sb);
2092
b77a493b 2093 return ret;
1da177e4
LT
2094}
2095
920f50b2 2096static int sel_get_tree(struct fs_context *fc)
1da177e4 2097{
920f50b2
DH
2098 return get_tree_single(fc, sel_fill_super);
2099}
2100
2101static const struct fs_context_operations sel_context_ops = {
2102 .get_tree = sel_get_tree,
2103};
2104
2105static int sel_init_fs_context(struct fs_context *fc)
2106{
2107 fc->ops = &sel_context_ops;
2108 return 0;
1da177e4
LT
2109}
2110
0619f0f5
SS
2111static void sel_kill_sb(struct super_block *sb)
2112{
2113 selinux_fs_info_free(sb);
2114 kill_litter_super(sb);
2115}
2116
1da177e4
LT
2117static struct file_system_type sel_fs_type = {
2118 .name = "selinuxfs",
920f50b2 2119 .init_fs_context = sel_init_fs_context,
0619f0f5 2120 .kill_sb = sel_kill_sb,
1da177e4
LT
2121};
2122
2123struct vfsmount *selinuxfs_mount;
0619f0f5 2124struct path selinux_null;
1da177e4
LT
2125
2126static int __init init_sel_fs(void)
2127{
0619f0f5
SS
2128 struct qstr null_name = QSTR_INIT(NULL_FILE_NAME,
2129 sizeof(NULL_FILE_NAME)-1);
1da177e4
LT
2130 int err;
2131
6c5a682e 2132 if (!selinux_enabled_boot)
1da177e4 2133 return 0;
7a627e3b 2134
f9bb4882
EB
2135 err = sysfs_create_mount_point(fs_kobj, "selinux");
2136 if (err)
2137 return err;
7a627e3b 2138
1da177e4 2139 err = register_filesystem(&sel_fs_type);
7a627e3b 2140 if (err) {
f9bb4882 2141 sysfs_remove_mount_point(fs_kobj, "selinux");
b77a493b 2142 return err;
7a627e3b 2143 }
b77a493b 2144
765927b2 2145 selinux_null.mnt = selinuxfs_mount = kern_mount(&sel_fs_type);
b77a493b 2146 if (IS_ERR(selinuxfs_mount)) {
f8b69a5f 2147 pr_err("selinuxfs: could not mount!\n");
b77a493b
EP
2148 err = PTR_ERR(selinuxfs_mount);
2149 selinuxfs_mount = NULL;
1da177e4 2150 }
0619f0f5
SS
2151 selinux_null.dentry = d_hash_and_lookup(selinux_null.mnt->mnt_root,
2152 &null_name);
2153 if (IS_ERR(selinux_null.dentry)) {
2154 pr_err("selinuxfs: could not lookup null!\n");
2155 err = PTR_ERR(selinux_null.dentry);
2156 selinux_null.dentry = NULL;
2157 }
b77a493b 2158
1da177e4
LT
2159 return err;
2160}
2161
2162__initcall(init_sel_fs);
2163
2164#ifdef CONFIG_SECURITY_SELINUX_DISABLE
2165void exit_sel_fs(void)
2166{
f9bb4882 2167 sysfs_remove_mount_point(fs_kobj, "selinux");
fd40ffc7 2168 dput(selinux_null.dentry);
423e0ab0 2169 kern_unmount(selinuxfs_mount);
1da177e4
LT
2170 unregister_filesystem(&sel_fs_type);
2171}
2172#endif