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