diff options
author | Stephen Smalley <sds@tycho.nsa.gov> | 2018-03-20 11:59:11 -0400 |
---|---|---|
committer | Paul Moore <paul@paul-moore.com> | 2018-03-20 16:54:36 -0400 |
commit | 0619f0f5e36f12e100ef294f5980cfe7c93ff23e (patch) | |
tree | 076490596953fdeefdbe2b39e264eb2df08f97fe | |
parent | 274f62e1e5c74e7cbc5c965ec02b7c590da4b2fe (diff) |
selinux: wrap selinuxfs state
Move global selinuxfs state to a per-instance structure (selinux_fs_info),
and include a pointer to the selinux_state in this structure.
Pass this selinux_state to all security server operations, thereby
ensuring that each selinuxfs instance presents a view of and acts
as an interface to a particular selinux_state instance.
This change should have no effect on SELinux behavior or APIs
(userspace or LSM). It merely wraps the selinuxfs global state,
links it to a particular selinux_state (currently always the single
global selinux_state) and uses that state for all operations.
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
Signed-off-by: Paul Moore <paul@paul-moore.com>
-rw-r--r-- | security/selinux/selinuxfs.c | 438 |
1 files changed, 261 insertions, 177 deletions
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index 0dbd5fd6a396..41099cc3d5e2 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/vmalloc.h> | 20 | #include <linux/vmalloc.h> |
21 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
22 | #include <linux/mount.h> | ||
22 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
23 | #include <linux/init.h> | 24 | #include <linux/init.h> |
24 | #include <linux/string.h> | 25 | #include <linux/string.h> |
@@ -41,23 +42,6 @@ | |||
41 | #include "objsec.h" | 42 | #include "objsec.h" |
42 | #include "conditional.h" | 43 | #include "conditional.h" |
43 | 44 | ||
44 | static DEFINE_MUTEX(sel_mutex); | ||
45 | |||
46 | /* global data for booleans */ | ||
47 | static struct dentry *bool_dir; | ||
48 | static int bool_num; | ||
49 | static char **bool_pending_names; | ||
50 | static int *bool_pending_values; | ||
51 | |||
52 | /* global data for classes */ | ||
53 | static struct dentry *class_dir; | ||
54 | static unsigned long last_class_ino; | ||
55 | |||
56 | static char policy_opened; | ||
57 | |||
58 | /* global data for policy capabilities */ | ||
59 | static struct dentry *policycap_dir; | ||
60 | |||
61 | enum sel_inos { | 45 | enum sel_inos { |
62 | SEL_ROOT_INO = 2, | 46 | SEL_ROOT_INO = 2, |
63 | SEL_LOAD, /* load policy */ | 47 | SEL_LOAD, /* load policy */ |
@@ -82,7 +66,51 @@ enum sel_inos { | |||
82 | SEL_INO_NEXT, /* The next inode number to use */ | 66 | SEL_INO_NEXT, /* The next inode number to use */ |
83 | }; | 67 | }; |
84 | 68 | ||
85 | static unsigned long sel_last_ino = SEL_INO_NEXT - 1; | 69 | struct selinux_fs_info { |
70 | struct dentry *bool_dir; | ||
71 | unsigned int bool_num; | ||
72 | char **bool_pending_names; | ||
73 | unsigned int *bool_pending_values; | ||
74 | struct dentry *class_dir; | ||
75 | unsigned long last_class_ino; | ||
76 | bool policy_opened; | ||
77 | struct dentry *policycap_dir; | ||
78 | struct mutex mutex; | ||
79 | unsigned long last_ino; | ||
80 | struct selinux_state *state; | ||
81 | struct super_block *sb; | ||
82 | }; | ||
83 | |||
84 | static int selinux_fs_info_create(struct super_block *sb) | ||
85 | { | ||
86 | struct selinux_fs_info *fsi; | ||
87 | |||
88 | fsi = kzalloc(sizeof(*fsi), GFP_KERNEL); | ||
89 | if (!fsi) | ||
90 | return -ENOMEM; | ||
91 | |||
92 | mutex_init(&fsi->mutex); | ||
93 | fsi->last_ino = SEL_INO_NEXT - 1; | ||
94 | fsi->state = &selinux_state; | ||
95 | fsi->sb = sb; | ||
96 | sb->s_fs_info = fsi; | ||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static void selinux_fs_info_free(struct super_block *sb) | ||
101 | { | ||
102 | struct selinux_fs_info *fsi = sb->s_fs_info; | ||
103 | int i; | ||
104 | |||
105 | if (fsi) { | ||
106 | for (i = 0; i < fsi->bool_num; i++) | ||
107 | kfree(fsi->bool_pending_names[i]); | ||
108 | kfree(fsi->bool_pending_names); | ||
109 | kfree(fsi->bool_pending_values); | ||
110 | } | ||
111 | kfree(sb->s_fs_info); | ||
112 | sb->s_fs_info = NULL; | ||
113 | } | ||
86 | 114 | ||
87 | #define SEL_INITCON_INO_OFFSET 0x01000000 | 115 | #define SEL_INITCON_INO_OFFSET 0x01000000 |
88 | #define SEL_BOOL_INO_OFFSET 0x02000000 | 116 | #define SEL_BOOL_INO_OFFSET 0x02000000 |
@@ -94,11 +122,12 @@ static unsigned long sel_last_ino = SEL_INO_NEXT - 1; | |||
94 | static ssize_t sel_read_enforce(struct file *filp, char __user *buf, | 122 | static ssize_t sel_read_enforce(struct file *filp, char __user *buf, |
95 | size_t count, loff_t *ppos) | 123 | size_t count, loff_t *ppos) |
96 | { | 124 | { |
125 | struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; | ||
97 | char tmpbuf[TMPBUFLEN]; | 126 | char tmpbuf[TMPBUFLEN]; |
98 | ssize_t length; | 127 | ssize_t length; |
99 | 128 | ||
100 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", | 129 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", |
101 | enforcing_enabled(&selinux_state)); | 130 | enforcing_enabled(fsi->state)); |
102 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); | 131 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); |
103 | } | 132 | } |
104 | 133 | ||
@@ -107,6 +136,8 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, | |||
107 | size_t count, loff_t *ppos) | 136 | size_t count, loff_t *ppos) |
108 | 137 | ||
109 | { | 138 | { |
139 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
140 | struct selinux_state *state = fsi->state; | ||
110 | char *page = NULL; | 141 | char *page = NULL; |
111 | ssize_t length; | 142 | ssize_t length; |
112 | int old_value, new_value; | 143 | int old_value, new_value; |
@@ -128,8 +159,7 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, | |||
128 | 159 | ||
129 | new_value = !!new_value; | 160 | new_value = !!new_value; |
130 | 161 | ||
131 | old_value = enforcing_enabled(&selinux_state); | 162 | old_value = enforcing_enabled(state); |
132 | |||
133 | if (new_value != old_value) { | 163 | if (new_value != old_value) { |
134 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 164 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
135 | SECCLASS_SECURITY, SECURITY__SETENFORCE, | 165 | SECCLASS_SECURITY, SECURITY__SETENFORCE, |
@@ -141,12 +171,11 @@ static ssize_t sel_write_enforce(struct file *file, const char __user *buf, | |||
141 | new_value, old_value, | 171 | new_value, old_value, |
142 | from_kuid(&init_user_ns, audit_get_loginuid(current)), | 172 | from_kuid(&init_user_ns, audit_get_loginuid(current)), |
143 | audit_get_sessionid(current)); | 173 | audit_get_sessionid(current)); |
144 | enforcing_set(&selinux_state, new_value); | 174 | enforcing_set(state, new_value); |
145 | if (new_value) | 175 | if (new_value) |
146 | avc_ss_reset(0); | 176 | avc_ss_reset(0); |
147 | selnl_notify_setenforce(new_value); | 177 | selnl_notify_setenforce(new_value); |
148 | selinux_status_update_setenforce(&selinux_state, | 178 | selinux_status_update_setenforce(state, new_value); |
149 | new_value); | ||
150 | if (!new_value) | 179 | if (!new_value) |
151 | call_lsm_notifier(LSM_POLICY_CHANGE, NULL); | 180 | call_lsm_notifier(LSM_POLICY_CHANGE, NULL); |
152 | } | 181 | } |
@@ -168,12 +197,14 @@ static const struct file_operations sel_enforce_ops = { | |||
168 | static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf, | 197 | static ssize_t sel_read_handle_unknown(struct file *filp, char __user *buf, |
169 | size_t count, loff_t *ppos) | 198 | size_t count, loff_t *ppos) |
170 | { | 199 | { |
200 | struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; | ||
201 | struct selinux_state *state = fsi->state; | ||
171 | char tmpbuf[TMPBUFLEN]; | 202 | char tmpbuf[TMPBUFLEN]; |
172 | ssize_t length; | 203 | ssize_t length; |
173 | ino_t ino = file_inode(filp)->i_ino; | 204 | ino_t ino = file_inode(filp)->i_ino; |
174 | int handle_unknown = (ino == SEL_REJECT_UNKNOWN) ? | 205 | int handle_unknown = (ino == SEL_REJECT_UNKNOWN) ? |
175 | security_get_reject_unknown(&selinux_state) : | 206 | security_get_reject_unknown(state) : |
176 | !security_get_allow_unknown(&selinux_state); | 207 | !security_get_allow_unknown(state); |
177 | 208 | ||
178 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", handle_unknown); | 209 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", handle_unknown); |
179 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); | 210 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); |
@@ -186,7 +217,8 @@ static const struct file_operations sel_handle_unknown_ops = { | |||
186 | 217 | ||
187 | static int sel_open_handle_status(struct inode *inode, struct file *filp) | 218 | static int sel_open_handle_status(struct inode *inode, struct file *filp) |
188 | { | 219 | { |
189 | struct page *status = selinux_kernel_status_page(&selinux_state); | 220 | struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; |
221 | struct page *status = selinux_kernel_status_page(fsi->state); | ||
190 | 222 | ||
191 | if (!status) | 223 | if (!status) |
192 | return -ENOMEM; | 224 | return -ENOMEM; |
@@ -242,6 +274,7 @@ static ssize_t sel_write_disable(struct file *file, const char __user *buf, | |||
242 | size_t count, loff_t *ppos) | 274 | size_t count, loff_t *ppos) |
243 | 275 | ||
244 | { | 276 | { |
277 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
245 | char *page; | 278 | char *page; |
246 | ssize_t length; | 279 | ssize_t length; |
247 | int new_value; | 280 | int new_value; |
@@ -262,7 +295,7 @@ static ssize_t sel_write_disable(struct file *file, const char __user *buf, | |||
262 | goto out; | 295 | goto out; |
263 | 296 | ||
264 | if (new_value) { | 297 | if (new_value) { |
265 | length = selinux_disable(&selinux_state); | 298 | length = selinux_disable(fsi->state); |
266 | if (length) | 299 | if (length) |
267 | goto out; | 300 | goto out; |
268 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, | 301 | audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_STATUS, |
@@ -301,9 +334,9 @@ static const struct file_operations sel_policyvers_ops = { | |||
301 | }; | 334 | }; |
302 | 335 | ||
303 | /* declaration for sel_write_load */ | 336 | /* declaration for sel_write_load */ |
304 | static int sel_make_bools(void); | 337 | static int sel_make_bools(struct selinux_fs_info *fsi); |
305 | static int sel_make_classes(void); | 338 | static int sel_make_classes(struct selinux_fs_info *fsi); |
306 | static int sel_make_policycap(void); | 339 | static int sel_make_policycap(struct selinux_fs_info *fsi); |
307 | 340 | ||
308 | /* declaration for sel_make_class_dirs */ | 341 | /* declaration for sel_make_class_dirs */ |
309 | static struct dentry *sel_make_dir(struct dentry *dir, const char *name, | 342 | static struct dentry *sel_make_dir(struct dentry *dir, const char *name, |
@@ -312,11 +345,12 @@ static struct dentry *sel_make_dir(struct dentry *dir, const char *name, | |||
312 | static ssize_t sel_read_mls(struct file *filp, char __user *buf, | 345 | static ssize_t sel_read_mls(struct file *filp, char __user *buf, |
313 | size_t count, loff_t *ppos) | 346 | size_t count, loff_t *ppos) |
314 | { | 347 | { |
348 | struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; | ||
315 | char tmpbuf[TMPBUFLEN]; | 349 | char tmpbuf[TMPBUFLEN]; |
316 | ssize_t length; | 350 | ssize_t length; |
317 | 351 | ||
318 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", | 352 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", |
319 | security_mls_enabled(&selinux_state)); | 353 | security_mls_enabled(fsi->state)); |
320 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); | 354 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); |
321 | } | 355 | } |
322 | 356 | ||
@@ -332,12 +366,14 @@ struct policy_load_memory { | |||
332 | 366 | ||
333 | static int sel_open_policy(struct inode *inode, struct file *filp) | 367 | static int sel_open_policy(struct inode *inode, struct file *filp) |
334 | { | 368 | { |
369 | struct selinux_fs_info *fsi = inode->i_sb->s_fs_info; | ||
370 | struct selinux_state *state = fsi->state; | ||
335 | struct policy_load_memory *plm = NULL; | 371 | struct policy_load_memory *plm = NULL; |
336 | int rc; | 372 | int rc; |
337 | 373 | ||
338 | BUG_ON(filp->private_data); | 374 | BUG_ON(filp->private_data); |
339 | 375 | ||
340 | mutex_lock(&sel_mutex); | 376 | mutex_lock(&fsi->mutex); |
341 | 377 | ||
342 | rc = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 378 | rc = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
343 | SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL); | 379 | SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL); |
@@ -345,7 +381,7 @@ static int sel_open_policy(struct inode *inode, struct file *filp) | |||
345 | goto err; | 381 | goto err; |
346 | 382 | ||
347 | rc = -EBUSY; | 383 | rc = -EBUSY; |
348 | if (policy_opened) | 384 | if (fsi->policy_opened) |
349 | goto err; | 385 | goto err; |
350 | 386 | ||
351 | rc = -ENOMEM; | 387 | rc = -ENOMEM; |
@@ -353,25 +389,25 @@ static int sel_open_policy(struct inode *inode, struct file *filp) | |||
353 | if (!plm) | 389 | if (!plm) |
354 | goto err; | 390 | goto err; |
355 | 391 | ||
356 | if (i_size_read(inode) != security_policydb_len(&selinux_state)) { | 392 | if (i_size_read(inode) != security_policydb_len(state)) { |
357 | inode_lock(inode); | 393 | inode_lock(inode); |
358 | i_size_write(inode, security_policydb_len(&selinux_state)); | 394 | i_size_write(inode, security_policydb_len(state)); |
359 | inode_unlock(inode); | 395 | inode_unlock(inode); |
360 | } | 396 | } |
361 | 397 | ||
362 | rc = security_read_policy(&selinux_state, &plm->data, &plm->len); | 398 | rc = security_read_policy(state, &plm->data, &plm->len); |
363 | if (rc) | 399 | if (rc) |
364 | goto err; | 400 | goto err; |
365 | 401 | ||
366 | policy_opened = 1; | 402 | fsi->policy_opened = 1; |
367 | 403 | ||
368 | filp->private_data = plm; | 404 | filp->private_data = plm; |
369 | 405 | ||
370 | mutex_unlock(&sel_mutex); | 406 | mutex_unlock(&fsi->mutex); |
371 | 407 | ||
372 | return 0; | 408 | return 0; |
373 | err: | 409 | err: |
374 | mutex_unlock(&sel_mutex); | 410 | mutex_unlock(&fsi->mutex); |
375 | 411 | ||
376 | if (plm) | 412 | if (plm) |
377 | vfree(plm->data); | 413 | vfree(plm->data); |
@@ -381,11 +417,12 @@ err: | |||
381 | 417 | ||
382 | static int sel_release_policy(struct inode *inode, struct file *filp) | 418 | static int sel_release_policy(struct inode *inode, struct file *filp) |
383 | { | 419 | { |
420 | struct selinux_fs_info *fsi = inode->i_sb->s_fs_info; | ||
384 | struct policy_load_memory *plm = filp->private_data; | 421 | struct policy_load_memory *plm = filp->private_data; |
385 | 422 | ||
386 | BUG_ON(!plm); | 423 | BUG_ON(!plm); |
387 | 424 | ||
388 | policy_opened = 0; | 425 | fsi->policy_opened = 0; |
389 | 426 | ||
390 | vfree(plm->data); | 427 | vfree(plm->data); |
391 | kfree(plm); | 428 | kfree(plm); |
@@ -396,10 +433,11 @@ static int sel_release_policy(struct inode *inode, struct file *filp) | |||
396 | static ssize_t sel_read_policy(struct file *filp, char __user *buf, | 433 | static ssize_t sel_read_policy(struct file *filp, char __user *buf, |
397 | size_t count, loff_t *ppos) | 434 | size_t count, loff_t *ppos) |
398 | { | 435 | { |
436 | struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; | ||
399 | struct policy_load_memory *plm = filp->private_data; | 437 | struct policy_load_memory *plm = filp->private_data; |
400 | int ret; | 438 | int ret; |
401 | 439 | ||
402 | mutex_lock(&sel_mutex); | 440 | mutex_lock(&fsi->mutex); |
403 | 441 | ||
404 | ret = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 442 | ret = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
405 | SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL); | 443 | SECCLASS_SECURITY, SECURITY__READ_POLICY, NULL); |
@@ -408,7 +446,7 @@ static ssize_t sel_read_policy(struct file *filp, char __user *buf, | |||
408 | 446 | ||
409 | ret = simple_read_from_buffer(buf, count, ppos, plm->data, plm->len); | 447 | ret = simple_read_from_buffer(buf, count, ppos, plm->data, plm->len); |
410 | out: | 448 | out: |
411 | mutex_unlock(&sel_mutex); | 449 | mutex_unlock(&fsi->mutex); |
412 | return ret; | 450 | return ret; |
413 | } | 451 | } |
414 | 452 | ||
@@ -462,14 +500,40 @@ static const struct file_operations sel_policy_ops = { | |||
462 | .llseek = generic_file_llseek, | 500 | .llseek = generic_file_llseek, |
463 | }; | 501 | }; |
464 | 502 | ||
503 | static int sel_make_policy_nodes(struct selinux_fs_info *fsi) | ||
504 | { | ||
505 | int ret; | ||
506 | |||
507 | ret = sel_make_bools(fsi); | ||
508 | if (ret) { | ||
509 | pr_err("SELinux: failed to load policy booleans\n"); | ||
510 | return ret; | ||
511 | } | ||
512 | |||
513 | ret = sel_make_classes(fsi); | ||
514 | if (ret) { | ||
515 | pr_err("SELinux: failed to load policy classes\n"); | ||
516 | return ret; | ||
517 | } | ||
518 | |||
519 | ret = sel_make_policycap(fsi); | ||
520 | if (ret) { | ||
521 | pr_err("SELinux: failed to load policy capabilities\n"); | ||
522 | return ret; | ||
523 | } | ||
524 | |||
525 | return 0; | ||
526 | } | ||
527 | |||
465 | static ssize_t sel_write_load(struct file *file, const char __user *buf, | 528 | static ssize_t sel_write_load(struct file *file, const char __user *buf, |
466 | size_t count, loff_t *ppos) | 529 | size_t count, loff_t *ppos) |
467 | 530 | ||
468 | { | 531 | { |
532 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
469 | ssize_t length; | 533 | ssize_t length; |
470 | void *data = NULL; | 534 | void *data = NULL; |
471 | 535 | ||
472 | mutex_lock(&sel_mutex); | 536 | mutex_lock(&fsi->mutex); |
473 | 537 | ||
474 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 538 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
475 | SECCLASS_SECURITY, SECURITY__LOAD_POLICY, NULL); | 539 | SECCLASS_SECURITY, SECURITY__LOAD_POLICY, NULL); |
@@ -494,29 +558,15 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf, | |||
494 | if (copy_from_user(data, buf, count) != 0) | 558 | if (copy_from_user(data, buf, count) != 0) |
495 | goto out; | 559 | goto out; |
496 | 560 | ||
497 | length = security_load_policy(&selinux_state, data, count); | 561 | length = security_load_policy(fsi->state, data, count); |
498 | if (length) { | 562 | if (length) { |
499 | pr_warn_ratelimited("SELinux: failed to load policy\n"); | 563 | pr_warn_ratelimited("SELinux: failed to load policy\n"); |
500 | goto out; | 564 | goto out; |
501 | } | 565 | } |
502 | 566 | ||
503 | length = sel_make_bools(); | 567 | length = sel_make_policy_nodes(fsi); |
504 | if (length) { | 568 | if (length) |
505 | pr_err("SELinux: failed to load policy booleans\n"); | ||
506 | goto out1; | ||
507 | } | ||
508 | |||
509 | length = sel_make_classes(); | ||
510 | if (length) { | ||
511 | pr_err("SELinux: failed to load policy classes\n"); | ||
512 | goto out1; | ||
513 | } | ||
514 | |||
515 | length = sel_make_policycap(); | ||
516 | if (length) { | ||
517 | pr_err("SELinux: failed to load policy capabilities\n"); | ||
518 | goto out1; | 569 | goto out1; |
519 | } | ||
520 | 570 | ||
521 | length = count; | 571 | length = count; |
522 | 572 | ||
@@ -526,7 +576,7 @@ out1: | |||
526 | from_kuid(&init_user_ns, audit_get_loginuid(current)), | 576 | from_kuid(&init_user_ns, audit_get_loginuid(current)), |
527 | audit_get_sessionid(current)); | 577 | audit_get_sessionid(current)); |
528 | out: | 578 | out: |
529 | mutex_unlock(&sel_mutex); | 579 | mutex_unlock(&fsi->mutex); |
530 | vfree(data); | 580 | vfree(data); |
531 | return length; | 581 | return length; |
532 | } | 582 | } |
@@ -538,6 +588,8 @@ static const struct file_operations sel_load_ops = { | |||
538 | 588 | ||
539 | static ssize_t sel_write_context(struct file *file, char *buf, size_t size) | 589 | static ssize_t sel_write_context(struct file *file, char *buf, size_t size) |
540 | { | 590 | { |
591 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
592 | struct selinux_state *state = fsi->state; | ||
541 | char *canon = NULL; | 593 | char *canon = NULL; |
542 | u32 sid, len; | 594 | u32 sid, len; |
543 | ssize_t length; | 595 | ssize_t length; |
@@ -547,12 +599,11 @@ static ssize_t sel_write_context(struct file *file, char *buf, size_t size) | |||
547 | if (length) | 599 | if (length) |
548 | goto out; | 600 | goto out; |
549 | 601 | ||
550 | length = security_context_to_sid(&selinux_state, buf, size, | 602 | length = security_context_to_sid(state, buf, size, &sid, GFP_KERNEL); |
551 | &sid, GFP_KERNEL); | ||
552 | if (length) | 603 | if (length) |
553 | goto out; | 604 | goto out; |
554 | 605 | ||
555 | length = security_sid_to_context(&selinux_state, sid, &canon, &len); | 606 | length = security_sid_to_context(state, sid, &canon, &len); |
556 | if (length) | 607 | if (length) |
557 | goto out; | 608 | goto out; |
558 | 609 | ||
@@ -573,16 +624,18 @@ out: | |||
573 | static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf, | 624 | static ssize_t sel_read_checkreqprot(struct file *filp, char __user *buf, |
574 | size_t count, loff_t *ppos) | 625 | size_t count, loff_t *ppos) |
575 | { | 626 | { |
627 | struct selinux_fs_info *fsi = file_inode(filp)->i_sb->s_fs_info; | ||
576 | char tmpbuf[TMPBUFLEN]; | 628 | char tmpbuf[TMPBUFLEN]; |
577 | ssize_t length; | 629 | ssize_t length; |
578 | 630 | ||
579 | length = scnprintf(tmpbuf, TMPBUFLEN, "%u", selinux_state.checkreqprot); | 631 | length = scnprintf(tmpbuf, TMPBUFLEN, "%u", fsi->state->checkreqprot); |
580 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); | 632 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); |
581 | } | 633 | } |
582 | 634 | ||
583 | static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf, | 635 | static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf, |
584 | size_t count, loff_t *ppos) | 636 | size_t count, loff_t *ppos) |
585 | { | 637 | { |
638 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
586 | char *page; | 639 | char *page; |
587 | ssize_t length; | 640 | ssize_t length; |
588 | unsigned int new_value; | 641 | unsigned int new_value; |
@@ -608,7 +661,7 @@ static ssize_t sel_write_checkreqprot(struct file *file, const char __user *buf, | |||
608 | if (sscanf(page, "%u", &new_value) != 1) | 661 | if (sscanf(page, "%u", &new_value) != 1) |
609 | goto out; | 662 | goto out; |
610 | 663 | ||
611 | selinux_state.checkreqprot = new_value ? 1 : 0; | 664 | fsi->state->checkreqprot = new_value ? 1 : 0; |
612 | length = count; | 665 | length = count; |
613 | out: | 666 | out: |
614 | kfree(page); | 667 | kfree(page); |
@@ -624,6 +677,8 @@ static ssize_t sel_write_validatetrans(struct file *file, | |||
624 | const char __user *buf, | 677 | const char __user *buf, |
625 | size_t count, loff_t *ppos) | 678 | size_t count, loff_t *ppos) |
626 | { | 679 | { |
680 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
681 | struct selinux_state *state = fsi->state; | ||
627 | char *oldcon = NULL, *newcon = NULL, *taskcon = NULL; | 682 | char *oldcon = NULL, *newcon = NULL, *taskcon = NULL; |
628 | char *req = NULL; | 683 | char *req = NULL; |
629 | u32 osid, nsid, tsid; | 684 | u32 osid, nsid, tsid; |
@@ -668,23 +723,19 @@ static ssize_t sel_write_validatetrans(struct file *file, | |||
668 | if (sscanf(req, "%s %s %hu %s", oldcon, newcon, &tclass, taskcon) != 4) | 723 | if (sscanf(req, "%s %s %hu %s", oldcon, newcon, &tclass, taskcon) != 4) |
669 | goto out; | 724 | goto out; |
670 | 725 | ||
671 | rc = security_context_str_to_sid(&selinux_state, oldcon, &osid, | 726 | rc = security_context_str_to_sid(state, oldcon, &osid, GFP_KERNEL); |
672 | GFP_KERNEL); | ||
673 | if (rc) | 727 | if (rc) |
674 | goto out; | 728 | goto out; |
675 | 729 | ||
676 | rc = security_context_str_to_sid(&selinux_state, newcon, &nsid, | 730 | rc = security_context_str_to_sid(state, newcon, &nsid, GFP_KERNEL); |
677 | GFP_KERNEL); | ||
678 | if (rc) | 731 | if (rc) |
679 | goto out; | 732 | goto out; |
680 | 733 | ||
681 | rc = security_context_str_to_sid(&selinux_state, taskcon, &tsid, | 734 | rc = security_context_str_to_sid(state, taskcon, &tsid, GFP_KERNEL); |
682 | GFP_KERNEL); | ||
683 | if (rc) | 735 | if (rc) |
684 | goto out; | 736 | goto out; |
685 | 737 | ||
686 | rc = security_validate_transition_user(&selinux_state, osid, nsid, | 738 | rc = security_validate_transition_user(state, osid, nsid, tsid, tclass); |
687 | tsid, tclass); | ||
688 | if (!rc) | 739 | if (!rc) |
689 | rc = count; | 740 | rc = count; |
690 | out: | 741 | out: |
@@ -754,6 +805,8 @@ static const struct file_operations transaction_ops = { | |||
754 | 805 | ||
755 | static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | 806 | static ssize_t sel_write_access(struct file *file, char *buf, size_t size) |
756 | { | 807 | { |
808 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
809 | struct selinux_state *state = fsi->state; | ||
757 | char *scon = NULL, *tcon = NULL; | 810 | char *scon = NULL, *tcon = NULL; |
758 | u32 ssid, tsid; | 811 | u32 ssid, tsid; |
759 | u16 tclass; | 812 | u16 tclass; |
@@ -779,17 +832,15 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | |||
779 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 832 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
780 | goto out; | 833 | goto out; |
781 | 834 | ||
782 | length = security_context_str_to_sid(&selinux_state, scon, &ssid, | 835 | length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); |
783 | GFP_KERNEL); | ||
784 | if (length) | 836 | if (length) |
785 | goto out; | 837 | goto out; |
786 | 838 | ||
787 | length = security_context_str_to_sid(&selinux_state, tcon, &tsid, | 839 | length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); |
788 | GFP_KERNEL); | ||
789 | if (length) | 840 | if (length) |
790 | goto out; | 841 | goto out; |
791 | 842 | ||
792 | security_compute_av_user(&selinux_state, ssid, tsid, tclass, &avd); | 843 | security_compute_av_user(state, ssid, tsid, tclass, &avd); |
793 | 844 | ||
794 | length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, | 845 | length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, |
795 | "%x %x %x %x %u %x", | 846 | "%x %x %x %x %u %x", |
@@ -804,6 +855,8 @@ out: | |||
804 | 855 | ||
805 | static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | 856 | static ssize_t sel_write_create(struct file *file, char *buf, size_t size) |
806 | { | 857 | { |
858 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
859 | struct selinux_state *state = fsi->state; | ||
807 | char *scon = NULL, *tcon = NULL; | 860 | char *scon = NULL, *tcon = NULL; |
808 | char *namebuf = NULL, *objname = NULL; | 861 | char *namebuf = NULL, *objname = NULL; |
809 | u32 ssid, tsid, newsid; | 862 | u32 ssid, tsid, newsid; |
@@ -869,23 +922,20 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | |||
869 | objname = namebuf; | 922 | objname = namebuf; |
870 | } | 923 | } |
871 | 924 | ||
872 | length = security_context_str_to_sid(&selinux_state, scon, &ssid, | 925 | length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); |
873 | GFP_KERNEL); | ||
874 | if (length) | 926 | if (length) |
875 | goto out; | 927 | goto out; |
876 | 928 | ||
877 | length = security_context_str_to_sid(&selinux_state, tcon, &tsid, | 929 | length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); |
878 | GFP_KERNEL); | ||
879 | if (length) | 930 | if (length) |
880 | goto out; | 931 | goto out; |
881 | 932 | ||
882 | length = security_transition_sid_user(&selinux_state, ssid, tsid, | 933 | length = security_transition_sid_user(state, ssid, tsid, tclass, |
883 | tclass, objname, &newsid); | 934 | objname, &newsid); |
884 | if (length) | 935 | if (length) |
885 | goto out; | 936 | goto out; |
886 | 937 | ||
887 | length = security_sid_to_context(&selinux_state, newsid, &newcon, | 938 | length = security_sid_to_context(state, newsid, &newcon, &len); |
888 | &len); | ||
889 | if (length) | 939 | if (length) |
890 | goto out; | 940 | goto out; |
891 | 941 | ||
@@ -908,6 +958,8 @@ out: | |||
908 | 958 | ||
909 | static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) | 959 | static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) |
910 | { | 960 | { |
961 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
962 | struct selinux_state *state = fsi->state; | ||
911 | char *scon = NULL, *tcon = NULL; | 963 | char *scon = NULL, *tcon = NULL; |
912 | u32 ssid, tsid, newsid; | 964 | u32 ssid, tsid, newsid; |
913 | u16 tclass; | 965 | u16 tclass; |
@@ -935,23 +987,19 @@ static ssize_t sel_write_relabel(struct file *file, char *buf, size_t size) | |||
935 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 987 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
936 | goto out; | 988 | goto out; |
937 | 989 | ||
938 | length = security_context_str_to_sid(&selinux_state, scon, &ssid, | 990 | length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); |
939 | GFP_KERNEL); | ||
940 | if (length) | 991 | if (length) |
941 | goto out; | 992 | goto out; |
942 | 993 | ||
943 | length = security_context_str_to_sid(&selinux_state, tcon, &tsid, | 994 | length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); |
944 | GFP_KERNEL); | ||
945 | if (length) | 995 | if (length) |
946 | goto out; | 996 | goto out; |
947 | 997 | ||
948 | length = security_change_sid(&selinux_state, ssid, tsid, tclass, | 998 | length = security_change_sid(state, ssid, tsid, tclass, &newsid); |
949 | &newsid); | ||
950 | if (length) | 999 | if (length) |
951 | goto out; | 1000 | goto out; |
952 | 1001 | ||
953 | length = security_sid_to_context(&selinux_state, newsid, &newcon, | 1002 | length = security_sid_to_context(state, newsid, &newcon, &len); |
954 | &len); | ||
955 | if (length) | 1003 | if (length) |
956 | goto out; | 1004 | goto out; |
957 | 1005 | ||
@@ -970,6 +1018,8 @@ out: | |||
970 | 1018 | ||
971 | static ssize_t sel_write_user(struct file *file, char *buf, size_t size) | 1019 | static ssize_t sel_write_user(struct file *file, char *buf, size_t size) |
972 | { | 1020 | { |
1021 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
1022 | struct selinux_state *state = fsi->state; | ||
973 | char *con = NULL, *user = NULL, *ptr; | 1023 | char *con = NULL, *user = NULL, *ptr; |
974 | u32 sid, *sids = NULL; | 1024 | u32 sid, *sids = NULL; |
975 | ssize_t length; | 1025 | ssize_t length; |
@@ -997,21 +1047,18 @@ static ssize_t sel_write_user(struct file *file, char *buf, size_t size) | |||
997 | if (sscanf(buf, "%s %s", con, user) != 2) | 1047 | if (sscanf(buf, "%s %s", con, user) != 2) |
998 | goto out; | 1048 | goto out; |
999 | 1049 | ||
1000 | length = security_context_str_to_sid(&selinux_state, con, &sid, | 1050 | length = security_context_str_to_sid(state, con, &sid, GFP_KERNEL); |
1001 | GFP_KERNEL); | ||
1002 | if (length) | 1051 | if (length) |
1003 | goto out; | 1052 | goto out; |
1004 | 1053 | ||
1005 | length = security_get_user_sids(&selinux_state, sid, user, &sids, | 1054 | length = security_get_user_sids(state, sid, user, &sids, &nsids); |
1006 | &nsids); | ||
1007 | if (length) | 1055 | if (length) |
1008 | goto out; | 1056 | goto out; |
1009 | 1057 | ||
1010 | length = sprintf(buf, "%u", nsids) + 1; | 1058 | length = sprintf(buf, "%u", nsids) + 1; |
1011 | ptr = buf + length; | 1059 | ptr = buf + length; |
1012 | for (i = 0; i < nsids; i++) { | 1060 | for (i = 0; i < nsids; i++) { |
1013 | rc = security_sid_to_context(&selinux_state, sids[i], | 1061 | rc = security_sid_to_context(state, sids[i], &newcon, &len); |
1014 | &newcon, &len); | ||
1015 | if (rc) { | 1062 | if (rc) { |
1016 | length = rc; | 1063 | length = rc; |
1017 | goto out; | 1064 | goto out; |
@@ -1035,6 +1082,8 @@ out: | |||
1035 | 1082 | ||
1036 | static ssize_t sel_write_member(struct file *file, char *buf, size_t size) | 1083 | static ssize_t sel_write_member(struct file *file, char *buf, size_t size) |
1037 | { | 1084 | { |
1085 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
1086 | struct selinux_state *state = fsi->state; | ||
1038 | char *scon = NULL, *tcon = NULL; | 1087 | char *scon = NULL, *tcon = NULL; |
1039 | u32 ssid, tsid, newsid; | 1088 | u32 ssid, tsid, newsid; |
1040 | u16 tclass; | 1089 | u16 tclass; |
@@ -1062,23 +1111,19 @@ static ssize_t sel_write_member(struct file *file, char *buf, size_t size) | |||
1062 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) | 1111 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
1063 | goto out; | 1112 | goto out; |
1064 | 1113 | ||
1065 | length = security_context_str_to_sid(&selinux_state, scon, &ssid, | 1114 | length = security_context_str_to_sid(state, scon, &ssid, GFP_KERNEL); |
1066 | GFP_KERNEL); | ||
1067 | if (length) | 1115 | if (length) |
1068 | goto out; | 1116 | goto out; |
1069 | 1117 | ||
1070 | length = security_context_str_to_sid(&selinux_state, tcon, &tsid, | 1118 | length = security_context_str_to_sid(state, tcon, &tsid, GFP_KERNEL); |
1071 | GFP_KERNEL); | ||
1072 | if (length) | 1119 | if (length) |
1073 | goto out; | 1120 | goto out; |
1074 | 1121 | ||
1075 | length = security_member_sid(&selinux_state, ssid, tsid, tclass, | 1122 | length = security_member_sid(state, ssid, tsid, tclass, &newsid); |
1076 | &newsid); | ||
1077 | if (length) | 1123 | if (length) |
1078 | goto out; | 1124 | goto out; |
1079 | 1125 | ||
1080 | length = security_sid_to_context(&selinux_state, newsid, &newcon, | 1126 | length = security_sid_to_context(state, newsid, &newcon, &len); |
1081 | &len); | ||
1082 | if (length) | 1127 | if (length) |
1083 | goto out; | 1128 | goto out; |
1084 | 1129 | ||
@@ -1112,6 +1157,7 @@ static struct inode *sel_make_inode(struct super_block *sb, int mode) | |||
1112 | static ssize_t sel_read_bool(struct file *filep, char __user *buf, | 1157 | static ssize_t sel_read_bool(struct file *filep, char __user *buf, |
1113 | size_t count, loff_t *ppos) | 1158 | size_t count, loff_t *ppos) |
1114 | { | 1159 | { |
1160 | struct selinux_fs_info *fsi = file_inode(filep)->i_sb->s_fs_info; | ||
1115 | char *page = NULL; | 1161 | char *page = NULL; |
1116 | ssize_t length; | 1162 | ssize_t length; |
1117 | ssize_t ret; | 1163 | ssize_t ret; |
@@ -1119,10 +1165,11 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, | |||
1119 | unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK; | 1165 | unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK; |
1120 | const char *name = filep->f_path.dentry->d_name.name; | 1166 | const char *name = filep->f_path.dentry->d_name.name; |
1121 | 1167 | ||
1122 | mutex_lock(&sel_mutex); | 1168 | mutex_lock(&fsi->mutex); |
1123 | 1169 | ||
1124 | ret = -EINVAL; | 1170 | ret = -EINVAL; |
1125 | if (index >= bool_num || strcmp(name, bool_pending_names[index])) | 1171 | if (index >= fsi->bool_num || strcmp(name, |
1172 | fsi->bool_pending_names[index])) | ||
1126 | goto out; | 1173 | goto out; |
1127 | 1174 | ||
1128 | ret = -ENOMEM; | 1175 | ret = -ENOMEM; |
@@ -1130,16 +1177,16 @@ static ssize_t sel_read_bool(struct file *filep, char __user *buf, | |||
1130 | if (!page) | 1177 | if (!page) |
1131 | goto out; | 1178 | goto out; |
1132 | 1179 | ||
1133 | cur_enforcing = security_get_bool_value(&selinux_state, index); | 1180 | cur_enforcing = security_get_bool_value(fsi->state, index); |
1134 | if (cur_enforcing < 0) { | 1181 | if (cur_enforcing < 0) { |
1135 | ret = cur_enforcing; | 1182 | ret = cur_enforcing; |
1136 | goto out; | 1183 | goto out; |
1137 | } | 1184 | } |
1138 | length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing, | 1185 | length = scnprintf(page, PAGE_SIZE, "%d %d", cur_enforcing, |
1139 | bool_pending_values[index]); | 1186 | fsi->bool_pending_values[index]); |
1140 | ret = simple_read_from_buffer(buf, count, ppos, page, length); | 1187 | ret = simple_read_from_buffer(buf, count, ppos, page, length); |
1141 | out: | 1188 | out: |
1142 | mutex_unlock(&sel_mutex); | 1189 | mutex_unlock(&fsi->mutex); |
1143 | free_page((unsigned long)page); | 1190 | free_page((unsigned long)page); |
1144 | return ret; | 1191 | return ret; |
1145 | } | 1192 | } |
@@ -1147,13 +1194,14 @@ out: | |||
1147 | static ssize_t sel_write_bool(struct file *filep, const char __user *buf, | 1194 | static ssize_t sel_write_bool(struct file *filep, const char __user *buf, |
1148 | size_t count, loff_t *ppos) | 1195 | size_t count, loff_t *ppos) |
1149 | { | 1196 | { |
1197 | struct selinux_fs_info *fsi = file_inode(filep)->i_sb->s_fs_info; | ||
1150 | char *page = NULL; | 1198 | char *page = NULL; |
1151 | ssize_t length; | 1199 | ssize_t length; |
1152 | int new_value; | 1200 | int new_value; |
1153 | unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK; | 1201 | unsigned index = file_inode(filep)->i_ino & SEL_INO_MASK; |
1154 | const char *name = filep->f_path.dentry->d_name.name; | 1202 | const char *name = filep->f_path.dentry->d_name.name; |
1155 | 1203 | ||
1156 | mutex_lock(&sel_mutex); | 1204 | mutex_lock(&fsi->mutex); |
1157 | 1205 | ||
1158 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 1206 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
1159 | SECCLASS_SECURITY, SECURITY__SETBOOL, | 1207 | SECCLASS_SECURITY, SECURITY__SETBOOL, |
@@ -1162,7 +1210,8 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, | |||
1162 | goto out; | 1210 | goto out; |
1163 | 1211 | ||
1164 | length = -EINVAL; | 1212 | length = -EINVAL; |
1165 | if (index >= bool_num || strcmp(name, bool_pending_names[index])) | 1213 | if (index >= fsi->bool_num || strcmp(name, |
1214 | fsi->bool_pending_names[index])) | ||
1166 | goto out; | 1215 | goto out; |
1167 | 1216 | ||
1168 | length = -ENOMEM; | 1217 | length = -ENOMEM; |
@@ -1188,11 +1237,11 @@ static ssize_t sel_write_bool(struct file *filep, const char __user *buf, | |||
1188 | if (new_value) | 1237 | if (new_value) |
1189 | new_value = 1; | 1238 | new_value = 1; |
1190 | 1239 | ||
1191 | bool_pending_values[index] = new_value; | 1240 | fsi->bool_pending_values[index] = new_value; |
1192 | length = count; | 1241 | length = count; |
1193 | 1242 | ||
1194 | out: | 1243 | out: |
1195 | mutex_unlock(&sel_mutex); | 1244 | mutex_unlock(&fsi->mutex); |
1196 | kfree(page); | 1245 | kfree(page); |
1197 | return length; | 1246 | return length; |
1198 | } | 1247 | } |
@@ -1207,11 +1256,12 @@ static ssize_t sel_commit_bools_write(struct file *filep, | |||
1207 | const char __user *buf, | 1256 | const char __user *buf, |
1208 | size_t count, loff_t *ppos) | 1257 | size_t count, loff_t *ppos) |
1209 | { | 1258 | { |
1259 | struct selinux_fs_info *fsi = file_inode(filep)->i_sb->s_fs_info; | ||
1210 | char *page = NULL; | 1260 | char *page = NULL; |
1211 | ssize_t length; | 1261 | ssize_t length; |
1212 | int new_value; | 1262 | int new_value; |
1213 | 1263 | ||
1214 | mutex_lock(&sel_mutex); | 1264 | mutex_lock(&fsi->mutex); |
1215 | 1265 | ||
1216 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, | 1266 | length = avc_has_perm(current_sid(), SECINITSID_SECURITY, |
1217 | SECCLASS_SECURITY, SECURITY__SETBOOL, | 1267 | SECCLASS_SECURITY, SECURITY__SETBOOL, |
@@ -1240,15 +1290,15 @@ static ssize_t sel_commit_bools_write(struct file *filep, | |||
1240 | goto out; | 1290 | goto out; |
1241 | 1291 | ||
1242 | length = 0; | 1292 | length = 0; |
1243 | if (new_value && bool_pending_values) | 1293 | if (new_value && fsi->bool_pending_values) |
1244 | length = security_set_bools(&selinux_state, bool_num, | 1294 | length = security_set_bools(fsi->state, fsi->bool_num, |
1245 | bool_pending_values); | 1295 | fsi->bool_pending_values); |
1246 | 1296 | ||
1247 | if (!length) | 1297 | if (!length) |
1248 | length = count; | 1298 | length = count; |
1249 | 1299 | ||
1250 | out: | 1300 | out: |
1251 | mutex_unlock(&sel_mutex); | 1301 | mutex_unlock(&fsi->mutex); |
1252 | kfree(page); | 1302 | kfree(page); |
1253 | return length; | 1303 | return length; |
1254 | } | 1304 | } |
@@ -1266,12 +1316,12 @@ static void sel_remove_entries(struct dentry *de) | |||
1266 | 1316 | ||
1267 | #define BOOL_DIR_NAME "booleans" | 1317 | #define BOOL_DIR_NAME "booleans" |
1268 | 1318 | ||
1269 | static int sel_make_bools(void) | 1319 | static int sel_make_bools(struct selinux_fs_info *fsi) |
1270 | { | 1320 | { |
1271 | int i, ret; | 1321 | int i, ret; |
1272 | ssize_t len; | 1322 | ssize_t len; |
1273 | struct dentry *dentry = NULL; | 1323 | struct dentry *dentry = NULL; |
1274 | struct dentry *dir = bool_dir; | 1324 | struct dentry *dir = fsi->bool_dir; |
1275 | struct inode *inode = NULL; | 1325 | struct inode *inode = NULL; |
1276 | struct inode_security_struct *isec; | 1326 | struct inode_security_struct *isec; |
1277 | char **names = NULL, *page; | 1327 | char **names = NULL, *page; |
@@ -1280,13 +1330,13 @@ static int sel_make_bools(void) | |||
1280 | u32 sid; | 1330 | u32 sid; |
1281 | 1331 | ||
1282 | /* remove any existing files */ | 1332 | /* remove any existing files */ |
1283 | for (i = 0; i < bool_num; i++) | 1333 | for (i = 0; i < fsi->bool_num; i++) |
1284 | kfree(bool_pending_names[i]); | 1334 | kfree(fsi->bool_pending_names[i]); |
1285 | kfree(bool_pending_names); | 1335 | kfree(fsi->bool_pending_names); |
1286 | kfree(bool_pending_values); | 1336 | kfree(fsi->bool_pending_values); |
1287 | bool_num = 0; | 1337 | fsi->bool_num = 0; |
1288 | bool_pending_names = NULL; | 1338 | fsi->bool_pending_names = NULL; |
1289 | bool_pending_values = NULL; | 1339 | fsi->bool_pending_values = NULL; |
1290 | 1340 | ||
1291 | sel_remove_entries(dir); | 1341 | sel_remove_entries(dir); |
1292 | 1342 | ||
@@ -1295,7 +1345,7 @@ static int sel_make_bools(void) | |||
1295 | if (!page) | 1345 | if (!page) |
1296 | goto out; | 1346 | goto out; |
1297 | 1347 | ||
1298 | ret = security_get_bools(&selinux_state, &num, &names, &values); | 1348 | ret = security_get_bools(fsi->state, &num, &names, &values); |
1299 | if (ret) | 1349 | if (ret) |
1300 | goto out; | 1350 | goto out; |
1301 | 1351 | ||
@@ -1316,7 +1366,7 @@ static int sel_make_bools(void) | |||
1316 | goto out; | 1366 | goto out; |
1317 | 1367 | ||
1318 | isec = (struct inode_security_struct *)inode->i_security; | 1368 | isec = (struct inode_security_struct *)inode->i_security; |
1319 | ret = security_genfs_sid(&selinux_state, "selinuxfs", page, | 1369 | ret = security_genfs_sid(fsi->state, "selinuxfs", page, |
1320 | SECCLASS_FILE, &sid); | 1370 | SECCLASS_FILE, &sid); |
1321 | if (ret) { | 1371 | if (ret) { |
1322 | pr_warn_ratelimited("SELinux: no sid found, defaulting to security isid for %s\n", | 1372 | pr_warn_ratelimited("SELinux: no sid found, defaulting to security isid for %s\n", |
@@ -1330,9 +1380,9 @@ static int sel_make_bools(void) | |||
1330 | inode->i_ino = i|SEL_BOOL_INO_OFFSET; | 1380 | inode->i_ino = i|SEL_BOOL_INO_OFFSET; |
1331 | d_add(dentry, inode); | 1381 | d_add(dentry, inode); |
1332 | } | 1382 | } |
1333 | bool_num = num; | 1383 | fsi->bool_num = num; |
1334 | bool_pending_names = names; | 1384 | fsi->bool_pending_names = names; |
1335 | bool_pending_values = values; | 1385 | fsi->bool_pending_values = values; |
1336 | 1386 | ||
1337 | free_page((unsigned long)page); | 1387 | free_page((unsigned long)page); |
1338 | return 0; | 1388 | return 0; |
@@ -1350,10 +1400,6 @@ out: | |||
1350 | return ret; | 1400 | return ret; |
1351 | } | 1401 | } |
1352 | 1402 | ||
1353 | #define NULL_FILE_NAME "null" | ||
1354 | |||
1355 | struct path selinux_null; | ||
1356 | |||
1357 | static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf, | 1403 | static ssize_t sel_read_avc_cache_threshold(struct file *filp, char __user *buf, |
1358 | size_t count, loff_t *ppos) | 1404 | size_t count, loff_t *ppos) |
1359 | { | 1405 | { |
@@ -1503,6 +1549,8 @@ static const struct file_operations sel_avc_cache_stats_ops = { | |||
1503 | 1549 | ||
1504 | static int sel_make_avc_files(struct dentry *dir) | 1550 | static int sel_make_avc_files(struct dentry *dir) |
1505 | { | 1551 | { |
1552 | struct super_block *sb = dir->d_sb; | ||
1553 | struct selinux_fs_info *fsi = sb->s_fs_info; | ||
1506 | int i; | 1554 | int i; |
1507 | static const struct tree_descr files[] = { | 1555 | static const struct tree_descr files[] = { |
1508 | { "cache_threshold", | 1556 | { "cache_threshold", |
@@ -1526,7 +1574,7 @@ static int sel_make_avc_files(struct dentry *dir) | |||
1526 | return -ENOMEM; | 1574 | return -ENOMEM; |
1527 | 1575 | ||
1528 | inode->i_fop = files[i].ops; | 1576 | inode->i_fop = files[i].ops; |
1529 | inode->i_ino = ++sel_last_ino; | 1577 | inode->i_ino = ++fsi->last_ino; |
1530 | d_add(dentry, inode); | 1578 | d_add(dentry, inode); |
1531 | } | 1579 | } |
1532 | 1580 | ||
@@ -1536,12 +1584,13 @@ static int sel_make_avc_files(struct dentry *dir) | |||
1536 | static ssize_t sel_read_initcon(struct file *file, char __user *buf, | 1584 | static ssize_t sel_read_initcon(struct file *file, char __user *buf, |
1537 | size_t count, loff_t *ppos) | 1585 | size_t count, loff_t *ppos) |
1538 | { | 1586 | { |
1587 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
1539 | char *con; | 1588 | char *con; |
1540 | u32 sid, len; | 1589 | u32 sid, len; |
1541 | ssize_t ret; | 1590 | ssize_t ret; |
1542 | 1591 | ||
1543 | sid = file_inode(file)->i_ino&SEL_INO_MASK; | 1592 | sid = file_inode(file)->i_ino&SEL_INO_MASK; |
1544 | ret = security_sid_to_context(&selinux_state, sid, &con, &len); | 1593 | ret = security_sid_to_context(fsi->state, sid, &con, &len); |
1545 | if (ret) | 1594 | if (ret) |
1546 | return ret; | 1595 | return ret; |
1547 | 1596 | ||
@@ -1629,13 +1678,13 @@ static const struct file_operations sel_perm_ops = { | |||
1629 | static ssize_t sel_read_policycap(struct file *file, char __user *buf, | 1678 | static ssize_t sel_read_policycap(struct file *file, char __user *buf, |
1630 | size_t count, loff_t *ppos) | 1679 | size_t count, loff_t *ppos) |
1631 | { | 1680 | { |
1681 | struct selinux_fs_info *fsi = file_inode(file)->i_sb->s_fs_info; | ||
1632 | int value; | 1682 | int value; |
1633 | char tmpbuf[TMPBUFLEN]; | 1683 | char tmpbuf[TMPBUFLEN]; |
1634 | ssize_t length; | 1684 | ssize_t length; |
1635 | unsigned long i_ino = file_inode(file)->i_ino; | 1685 | unsigned long i_ino = file_inode(file)->i_ino; |
1636 | 1686 | ||
1637 | value = security_policycap_supported(&selinux_state, | 1687 | value = security_policycap_supported(fsi->state, i_ino & SEL_INO_MASK); |
1638 | i_ino & SEL_INO_MASK); | ||
1639 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", value); | 1688 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", value); |
1640 | 1689 | ||
1641 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); | 1690 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); |
@@ -1649,11 +1698,11 @@ static const struct file_operations sel_policycap_ops = { | |||
1649 | static int sel_make_perm_files(char *objclass, int classvalue, | 1698 | static int sel_make_perm_files(char *objclass, int classvalue, |
1650 | struct dentry *dir) | 1699 | struct dentry *dir) |
1651 | { | 1700 | { |
1701 | struct selinux_fs_info *fsi = dir->d_sb->s_fs_info; | ||
1652 | int i, rc, nperms; | 1702 | int i, rc, nperms; |
1653 | char **perms; | 1703 | char **perms; |
1654 | 1704 | ||
1655 | rc = security_get_permissions(&selinux_state, objclass, &perms, | 1705 | rc = security_get_permissions(fsi->state, objclass, &perms, &nperms); |
1656 | &nperms); | ||
1657 | if (rc) | 1706 | if (rc) |
1658 | return rc; | 1707 | return rc; |
1659 | 1708 | ||
@@ -1687,6 +1736,8 @@ out: | |||
1687 | static int sel_make_class_dir_entries(char *classname, int index, | 1736 | static int sel_make_class_dir_entries(char *classname, int index, |
1688 | struct dentry *dir) | 1737 | struct dentry *dir) |
1689 | { | 1738 | { |
1739 | struct super_block *sb = dir->d_sb; | ||
1740 | struct selinux_fs_info *fsi = sb->s_fs_info; | ||
1690 | struct dentry *dentry = NULL; | 1741 | struct dentry *dentry = NULL; |
1691 | struct inode *inode = NULL; | 1742 | struct inode *inode = NULL; |
1692 | int rc; | 1743 | int rc; |
@@ -1703,7 +1754,7 @@ static int sel_make_class_dir_entries(char *classname, int index, | |||
1703 | inode->i_ino = sel_class_to_ino(index); | 1754 | inode->i_ino = sel_class_to_ino(index); |
1704 | d_add(dentry, inode); | 1755 | d_add(dentry, inode); |
1705 | 1756 | ||
1706 | dentry = sel_make_dir(dir, "perms", &last_class_ino); | 1757 | dentry = sel_make_dir(dir, "perms", &fsi->last_class_ino); |
1707 | if (IS_ERR(dentry)) | 1758 | if (IS_ERR(dentry)) |
1708 | return PTR_ERR(dentry); | 1759 | return PTR_ERR(dentry); |
1709 | 1760 | ||
@@ -1712,26 +1763,27 @@ static int sel_make_class_dir_entries(char *classname, int index, | |||
1712 | return rc; | 1763 | return rc; |
1713 | } | 1764 | } |
1714 | 1765 | ||
1715 | static int sel_make_classes(void) | 1766 | static int sel_make_classes(struct selinux_fs_info *fsi) |
1716 | { | 1767 | { |
1768 | |||
1717 | int rc, nclasses, i; | 1769 | int rc, nclasses, i; |
1718 | char **classes; | 1770 | char **classes; |
1719 | 1771 | ||
1720 | /* delete any existing entries */ | 1772 | /* delete any existing entries */ |
1721 | sel_remove_entries(class_dir); | 1773 | sel_remove_entries(fsi->class_dir); |
1722 | 1774 | ||
1723 | rc = security_get_classes(&selinux_state, &classes, &nclasses); | 1775 | rc = security_get_classes(fsi->state, &classes, &nclasses); |
1724 | if (rc) | 1776 | if (rc) |
1725 | return rc; | 1777 | return rc; |
1726 | 1778 | ||
1727 | /* +2 since classes are 1-indexed */ | 1779 | /* +2 since classes are 1-indexed */ |
1728 | last_class_ino = sel_class_to_ino(nclasses + 2); | 1780 | fsi->last_class_ino = sel_class_to_ino(nclasses + 2); |
1729 | 1781 | ||
1730 | for (i = 0; i < nclasses; i++) { | 1782 | for (i = 0; i < nclasses; i++) { |
1731 | struct dentry *class_name_dir; | 1783 | struct dentry *class_name_dir; |
1732 | 1784 | ||
1733 | class_name_dir = sel_make_dir(class_dir, classes[i], | 1785 | class_name_dir = sel_make_dir(fsi->class_dir, classes[i], |
1734 | &last_class_ino); | 1786 | &fsi->last_class_ino); |
1735 | if (IS_ERR(class_name_dir)) { | 1787 | if (IS_ERR(class_name_dir)) { |
1736 | rc = PTR_ERR(class_name_dir); | 1788 | rc = PTR_ERR(class_name_dir); |
1737 | goto out; | 1789 | goto out; |
@@ -1751,25 +1803,25 @@ out: | |||
1751 | return rc; | 1803 | return rc; |
1752 | } | 1804 | } |
1753 | 1805 | ||
1754 | static int sel_make_policycap(void) | 1806 | static int sel_make_policycap(struct selinux_fs_info *fsi) |
1755 | { | 1807 | { |
1756 | unsigned int iter; | 1808 | unsigned int iter; |
1757 | struct dentry *dentry = NULL; | 1809 | struct dentry *dentry = NULL; |
1758 | struct inode *inode = NULL; | 1810 | struct inode *inode = NULL; |
1759 | 1811 | ||
1760 | sel_remove_entries(policycap_dir); | 1812 | sel_remove_entries(fsi->policycap_dir); |
1761 | 1813 | ||
1762 | for (iter = 0; iter <= POLICYDB_CAPABILITY_MAX; iter++) { | 1814 | for (iter = 0; iter <= POLICYDB_CAPABILITY_MAX; iter++) { |
1763 | if (iter < ARRAY_SIZE(selinux_policycap_names)) | 1815 | if (iter < ARRAY_SIZE(selinux_policycap_names)) |
1764 | dentry = d_alloc_name(policycap_dir, | 1816 | dentry = d_alloc_name(fsi->policycap_dir, |
1765 | selinux_policycap_names[iter]); | 1817 | selinux_policycap_names[iter]); |
1766 | else | 1818 | else |
1767 | dentry = d_alloc_name(policycap_dir, "unknown"); | 1819 | dentry = d_alloc_name(fsi->policycap_dir, "unknown"); |
1768 | 1820 | ||
1769 | if (dentry == NULL) | 1821 | if (dentry == NULL) |
1770 | return -ENOMEM; | 1822 | return -ENOMEM; |
1771 | 1823 | ||
1772 | inode = sel_make_inode(policycap_dir->d_sb, S_IFREG | S_IRUGO); | 1824 | inode = sel_make_inode(fsi->sb, S_IFREG | 0444); |
1773 | if (inode == NULL) | 1825 | if (inode == NULL) |
1774 | return -ENOMEM; | 1826 | return -ENOMEM; |
1775 | 1827 | ||
@@ -1808,8 +1860,11 @@ static struct dentry *sel_make_dir(struct dentry *dir, const char *name, | |||
1808 | return dentry; | 1860 | return dentry; |
1809 | } | 1861 | } |
1810 | 1862 | ||
1863 | #define NULL_FILE_NAME "null" | ||
1864 | |||
1811 | static int sel_fill_super(struct super_block *sb, void *data, int silent) | 1865 | static int sel_fill_super(struct super_block *sb, void *data, int silent) |
1812 | { | 1866 | { |
1867 | struct selinux_fs_info *fsi; | ||
1813 | int ret; | 1868 | int ret; |
1814 | struct dentry *dentry; | 1869 | struct dentry *dentry; |
1815 | struct inode *inode; | 1870 | struct inode *inode; |
@@ -1837,14 +1892,20 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1837 | S_IWUGO}, | 1892 | S_IWUGO}, |
1838 | /* last one */ {""} | 1893 | /* last one */ {""} |
1839 | }; | 1894 | }; |
1895 | |||
1896 | ret = selinux_fs_info_create(sb); | ||
1897 | if (ret) | ||
1898 | goto err; | ||
1899 | |||
1840 | ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); | 1900 | ret = simple_fill_super(sb, SELINUX_MAGIC, selinux_files); |
1841 | if (ret) | 1901 | if (ret) |
1842 | goto err; | 1902 | goto err; |
1843 | 1903 | ||
1844 | bool_dir = sel_make_dir(sb->s_root, BOOL_DIR_NAME, &sel_last_ino); | 1904 | fsi = sb->s_fs_info; |
1845 | if (IS_ERR(bool_dir)) { | 1905 | fsi->bool_dir = sel_make_dir(sb->s_root, BOOL_DIR_NAME, &fsi->last_ino); |
1846 | ret = PTR_ERR(bool_dir); | 1906 | if (IS_ERR(fsi->bool_dir)) { |
1847 | bool_dir = NULL; | 1907 | ret = PTR_ERR(fsi->bool_dir); |
1908 | fsi->bool_dir = NULL; | ||
1848 | goto err; | 1909 | goto err; |
1849 | } | 1910 | } |
1850 | 1911 | ||
@@ -1858,7 +1919,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1858 | if (!inode) | 1919 | if (!inode) |
1859 | goto err; | 1920 | goto err; |
1860 | 1921 | ||
1861 | inode->i_ino = ++sel_last_ino; | 1922 | inode->i_ino = ++fsi->last_ino; |
1862 | isec = (struct inode_security_struct *)inode->i_security; | 1923 | isec = (struct inode_security_struct *)inode->i_security; |
1863 | isec->sid = SECINITSID_DEVNULL; | 1924 | isec->sid = SECINITSID_DEVNULL; |
1864 | isec->sclass = SECCLASS_CHR_FILE; | 1925 | isec->sclass = SECCLASS_CHR_FILE; |
@@ -1866,9 +1927,8 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1866 | 1927 | ||
1867 | init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3)); | 1928 | init_special_inode(inode, S_IFCHR | S_IRUGO | S_IWUGO, MKDEV(MEM_MAJOR, 3)); |
1868 | d_add(dentry, inode); | 1929 | d_add(dentry, inode); |
1869 | selinux_null.dentry = dentry; | ||
1870 | 1930 | ||
1871 | dentry = sel_make_dir(sb->s_root, "avc", &sel_last_ino); | 1931 | dentry = sel_make_dir(sb->s_root, "avc", &fsi->last_ino); |
1872 | if (IS_ERR(dentry)) { | 1932 | if (IS_ERR(dentry)) { |
1873 | ret = PTR_ERR(dentry); | 1933 | ret = PTR_ERR(dentry); |
1874 | goto err; | 1934 | goto err; |
@@ -1878,7 +1938,7 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1878 | if (ret) | 1938 | if (ret) |
1879 | goto err; | 1939 | goto err; |
1880 | 1940 | ||
1881 | dentry = sel_make_dir(sb->s_root, "initial_contexts", &sel_last_ino); | 1941 | dentry = sel_make_dir(sb->s_root, "initial_contexts", &fsi->last_ino); |
1882 | if (IS_ERR(dentry)) { | 1942 | if (IS_ERR(dentry)) { |
1883 | ret = PTR_ERR(dentry); | 1943 | ret = PTR_ERR(dentry); |
1884 | goto err; | 1944 | goto err; |
@@ -1888,23 +1948,31 @@ static int sel_fill_super(struct super_block *sb, void *data, int silent) | |||
1888 | if (ret) | 1948 | if (ret) |
1889 | goto err; | 1949 | goto err; |
1890 | 1950 | ||
1891 | class_dir = sel_make_dir(sb->s_root, "class", &sel_last_ino); | 1951 | fsi->class_dir = sel_make_dir(sb->s_root, "class", &fsi->last_ino); |
1892 | if (IS_ERR(class_dir)) { | 1952 | if (IS_ERR(fsi->class_dir)) { |
1893 | ret = PTR_ERR(class_dir); | 1953 | ret = PTR_ERR(fsi->class_dir); |
1894 | class_dir = NULL; | 1954 | fsi->class_dir = NULL; |
1895 | goto err; | 1955 | goto err; |
1896 | } | 1956 | } |
1897 | 1957 | ||
1898 | policycap_dir = sel_make_dir(sb->s_root, "policy_capabilities", &sel_last_ino); | 1958 | fsi->policycap_dir = sel_make_dir(sb->s_root, "policy_capabilities", |
1899 | if (IS_ERR(policycap_dir)) { | 1959 | &fsi->last_ino); |
1900 | ret = PTR_ERR(policycap_dir); | 1960 | if (IS_ERR(fsi->policycap_dir)) { |
1901 | policycap_dir = NULL; | 1961 | ret = PTR_ERR(fsi->policycap_dir); |
1962 | fsi->policycap_dir = NULL; | ||
1902 | goto err; | 1963 | goto err; |
1903 | } | 1964 | } |
1965 | |||
1966 | ret = sel_make_policy_nodes(fsi); | ||
1967 | if (ret) | ||
1968 | goto err; | ||
1904 | return 0; | 1969 | return 0; |
1905 | err: | 1970 | err: |
1906 | printk(KERN_ERR "SELinux: %s: failed while creating inodes\n", | 1971 | printk(KERN_ERR "SELinux: %s: failed while creating inodes\n", |
1907 | __func__); | 1972 | __func__); |
1973 | |||
1974 | selinux_fs_info_free(sb); | ||
1975 | |||
1908 | return ret; | 1976 | return ret; |
1909 | } | 1977 | } |
1910 | 1978 | ||
@@ -1914,16 +1982,25 @@ static struct dentry *sel_mount(struct file_system_type *fs_type, | |||
1914 | return mount_single(fs_type, flags, data, sel_fill_super); | 1982 | return mount_single(fs_type, flags, data, sel_fill_super); |
1915 | } | 1983 | } |
1916 | 1984 | ||
1985 | static void sel_kill_sb(struct super_block *sb) | ||
1986 | { | ||
1987 | selinux_fs_info_free(sb); | ||
1988 | kill_litter_super(sb); | ||
1989 | } | ||
1990 | |||
1917 | static struct file_system_type sel_fs_type = { | 1991 | static struct file_system_type sel_fs_type = { |
1918 | .name = "selinuxfs", | 1992 | .name = "selinuxfs", |
1919 | .mount = sel_mount, | 1993 | .mount = sel_mount, |
1920 | .kill_sb = kill_litter_super, | 1994 | .kill_sb = sel_kill_sb, |
1921 | }; | 1995 | }; |
1922 | 1996 | ||
1923 | struct vfsmount *selinuxfs_mount; | 1997 | struct vfsmount *selinuxfs_mount; |
1998 | struct path selinux_null; | ||
1924 | 1999 | ||
1925 | static int __init init_sel_fs(void) | 2000 | static int __init init_sel_fs(void) |
1926 | { | 2001 | { |
2002 | struct qstr null_name = QSTR_INIT(NULL_FILE_NAME, | ||
2003 | sizeof(NULL_FILE_NAME)-1); | ||
1927 | int err; | 2004 | int err; |
1928 | 2005 | ||
1929 | if (!selinux_enabled) | 2006 | if (!selinux_enabled) |
@@ -1945,6 +2022,13 @@ static int __init init_sel_fs(void) | |||
1945 | err = PTR_ERR(selinuxfs_mount); | 2022 | err = PTR_ERR(selinuxfs_mount); |
1946 | selinuxfs_mount = NULL; | 2023 | selinuxfs_mount = NULL; |
1947 | } | 2024 | } |
2025 | selinux_null.dentry = d_hash_and_lookup(selinux_null.mnt->mnt_root, | ||
2026 | &null_name); | ||
2027 | if (IS_ERR(selinux_null.dentry)) { | ||
2028 | pr_err("selinuxfs: could not lookup null!\n"); | ||
2029 | err = PTR_ERR(selinux_null.dentry); | ||
2030 | selinux_null.dentry = NULL; | ||
2031 | } | ||
1948 | 2032 | ||
1949 | return err; | 2033 | return err; |
1950 | } | 2034 | } |