diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /security | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'security')
73 files changed, 2920 insertions, 3997 deletions
diff --git a/security/Kconfig b/security/Kconfig index fb363cd81cf6..226b9556b25f 100644 --- a/security/Kconfig +++ b/security/Kconfig | |||
@@ -91,28 +91,6 @@ config SECURITY_PATH | |||
91 | implement pathname based access controls. | 91 | implement pathname based access controls. |
92 | If you are unsure how to answer this question, answer N. | 92 | If you are unsure how to answer this question, answer N. |
93 | 93 | ||
94 | config SECURITY_FILE_CAPABILITIES | ||
95 | bool "File POSIX Capabilities" | ||
96 | default n | ||
97 | help | ||
98 | This enables filesystem capabilities, allowing you to give | ||
99 | binaries a subset of root's powers without using setuid 0. | ||
100 | |||
101 | If in doubt, answer N. | ||
102 | |||
103 | config SECURITY_ROOTPLUG | ||
104 | bool "Root Plug Support" | ||
105 | depends on USB=y && SECURITY | ||
106 | help | ||
107 | This is a sample LSM module that should only be used as such. | ||
108 | It prevents any programs running with egid == 0 if a specific | ||
109 | USB device is not present in the system. | ||
110 | |||
111 | See <http://www.linuxjournal.com/article.php?sid=6279> for | ||
112 | more information about this module. | ||
113 | |||
114 | If you are unsure how to answer this question, answer N. | ||
115 | |||
116 | config INTEL_TXT | 94 | config INTEL_TXT |
117 | bool "Enable Intel(R) Trusted Execution Technology (Intel(R) TXT)" | 95 | bool "Enable Intel(R) Trusted Execution Technology (Intel(R) TXT)" |
118 | depends on HAVE_INTEL_TXT | 96 | depends on HAVE_INTEL_TXT |
@@ -165,5 +143,37 @@ source security/tomoyo/Kconfig | |||
165 | 143 | ||
166 | source security/integrity/ima/Kconfig | 144 | source security/integrity/ima/Kconfig |
167 | 145 | ||
146 | choice | ||
147 | prompt "Default security module" | ||
148 | default DEFAULT_SECURITY_SELINUX if SECURITY_SELINUX | ||
149 | default DEFAULT_SECURITY_SMACK if SECURITY_SMACK | ||
150 | default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO | ||
151 | default DEFAULT_SECURITY_DAC | ||
152 | |||
153 | help | ||
154 | Select the security module that will be used by default if the | ||
155 | kernel parameter security= is not specified. | ||
156 | |||
157 | config DEFAULT_SECURITY_SELINUX | ||
158 | bool "SELinux" if SECURITY_SELINUX=y | ||
159 | |||
160 | config DEFAULT_SECURITY_SMACK | ||
161 | bool "Simplified Mandatory Access Control" if SECURITY_SMACK=y | ||
162 | |||
163 | config DEFAULT_SECURITY_TOMOYO | ||
164 | bool "TOMOYO" if SECURITY_TOMOYO=y | ||
165 | |||
166 | config DEFAULT_SECURITY_DAC | ||
167 | bool "Unix Discretionary Access Controls" | ||
168 | |||
169 | endchoice | ||
170 | |||
171 | config DEFAULT_SECURITY | ||
172 | string | ||
173 | default "selinux" if DEFAULT_SECURITY_SELINUX | ||
174 | default "smack" if DEFAULT_SECURITY_SMACK | ||
175 | default "tomoyo" if DEFAULT_SECURITY_TOMOYO | ||
176 | default "" if DEFAULT_SECURITY_DAC | ||
177 | |||
168 | endmenu | 178 | endmenu |
169 | 179 | ||
diff --git a/security/Makefile b/security/Makefile index 95ecc06392d7..da20a193c8dd 100644 --- a/security/Makefile +++ b/security/Makefile | |||
@@ -8,7 +8,8 @@ subdir-$(CONFIG_SECURITY_SMACK) += smack | |||
8 | subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo | 8 | subdir-$(CONFIG_SECURITY_TOMOYO) += tomoyo |
9 | 9 | ||
10 | # always enable default capabilities | 10 | # always enable default capabilities |
11 | obj-y += commoncap.o min_addr.o | 11 | obj-y += commoncap.o |
12 | obj-$(CONFIG_MMU) += min_addr.o | ||
12 | 13 | ||
13 | # Object file lists | 14 | # Object file lists |
14 | obj-$(CONFIG_SECURITY) += security.o capability.o | 15 | obj-$(CONFIG_SECURITY) += security.o capability.o |
@@ -18,7 +19,6 @@ obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o | |||
18 | obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o | 19 | obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o |
19 | obj-$(CONFIG_AUDIT) += lsm_audit.o | 20 | obj-$(CONFIG_AUDIT) += lsm_audit.o |
20 | obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o | 21 | obj-$(CONFIG_SECURITY_TOMOYO) += tomoyo/built-in.o |
21 | obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o | ||
22 | obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o | 22 | obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o |
23 | 23 | ||
24 | # Object integrity file lists | 24 | # Object integrity file lists |
diff --git a/security/capability.c b/security/capability.c index fce07a7bc825..4875142b858d 100644 --- a/security/capability.c +++ b/security/capability.c | |||
@@ -308,6 +308,22 @@ static int cap_path_truncate(struct path *path, loff_t length, | |||
308 | { | 308 | { |
309 | return 0; | 309 | return 0; |
310 | } | 310 | } |
311 | |||
312 | static int cap_path_chmod(struct dentry *dentry, struct vfsmount *mnt, | ||
313 | mode_t mode) | ||
314 | { | ||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static int cap_path_chown(struct path *path, uid_t uid, gid_t gid) | ||
319 | { | ||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | static int cap_path_chroot(struct path *root) | ||
324 | { | ||
325 | return 0; | ||
326 | } | ||
311 | #endif | 327 | #endif |
312 | 328 | ||
313 | static int cap_file_permission(struct file *file, int mask) | 329 | static int cap_file_permission(struct file *file, int mask) |
@@ -405,7 +421,7 @@ static int cap_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
405 | return 0; | 421 | return 0; |
406 | } | 422 | } |
407 | 423 | ||
408 | static int cap_kernel_module_request(void) | 424 | static int cap_kernel_module_request(char *kmod_name) |
409 | { | 425 | { |
410 | return 0; | 426 | return 0; |
411 | } | 427 | } |
@@ -890,10 +906,6 @@ static void cap_audit_rule_free(void *lsmrule) | |||
890 | } | 906 | } |
891 | #endif /* CONFIG_AUDIT */ | 907 | #endif /* CONFIG_AUDIT */ |
892 | 908 | ||
893 | struct security_operations default_security_ops = { | ||
894 | .name = "default", | ||
895 | }; | ||
896 | |||
897 | #define set_to_cap_if_null(ops, function) \ | 909 | #define set_to_cap_if_null(ops, function) \ |
898 | do { \ | 910 | do { \ |
899 | if (!ops->function) { \ | 911 | if (!ops->function) { \ |
@@ -977,6 +989,9 @@ void security_fixup_ops(struct security_operations *ops) | |||
977 | set_to_cap_if_null(ops, path_link); | 989 | set_to_cap_if_null(ops, path_link); |
978 | set_to_cap_if_null(ops, path_rename); | 990 | set_to_cap_if_null(ops, path_rename); |
979 | set_to_cap_if_null(ops, path_truncate); | 991 | set_to_cap_if_null(ops, path_truncate); |
992 | set_to_cap_if_null(ops, path_chmod); | ||
993 | set_to_cap_if_null(ops, path_chown); | ||
994 | set_to_cap_if_null(ops, path_chroot); | ||
980 | #endif | 995 | #endif |
981 | set_to_cap_if_null(ops, file_permission); | 996 | set_to_cap_if_null(ops, file_permission); |
982 | set_to_cap_if_null(ops, file_alloc_security); | 997 | set_to_cap_if_null(ops, file_alloc_security); |
diff --git a/security/commoncap.c b/security/commoncap.c index fe30751a6cd9..61669730da98 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Common capabilities, needed by capability.o and root_plug.o | 1 | /* Common capabilities, needed by capability.o. |
2 | * | 2 | * |
3 | * This program is free software; you can redistribute it and/or modify | 3 | * This program is free software; you can redistribute it and/or modify |
4 | * it under the terms of the GNU General Public License as published by | 4 | * it under the terms of the GNU General Public License as published by |
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
28 | #include <linux/prctl.h> | 28 | #include <linux/prctl.h> |
29 | #include <linux/securebits.h> | 29 | #include <linux/securebits.h> |
30 | #include <linux/syslog.h> | ||
30 | 31 | ||
31 | /* | 32 | /* |
32 | * If a non-root user executes a setuid-root binary in | 33 | * If a non-root user executes a setuid-root binary in |
@@ -173,7 +174,6 @@ int cap_capget(struct task_struct *target, kernel_cap_t *effective, | |||
173 | */ | 174 | */ |
174 | static inline int cap_inh_is_capped(void) | 175 | static inline int cap_inh_is_capped(void) |
175 | { | 176 | { |
176 | #ifdef CONFIG_SECURITY_FILE_CAPABILITIES | ||
177 | 177 | ||
178 | /* they are so limited unless the current task has the CAP_SETPCAP | 178 | /* they are so limited unless the current task has the CAP_SETPCAP |
179 | * capability | 179 | * capability |
@@ -181,7 +181,6 @@ static inline int cap_inh_is_capped(void) | |||
181 | if (cap_capable(current, current_cred(), CAP_SETPCAP, | 181 | if (cap_capable(current, current_cred(), CAP_SETPCAP, |
182 | SECURITY_CAP_AUDIT) == 0) | 182 | SECURITY_CAP_AUDIT) == 0) |
183 | return 0; | 183 | return 0; |
184 | #endif | ||
185 | return 1; | 184 | return 1; |
186 | } | 185 | } |
187 | 186 | ||
@@ -239,8 +238,6 @@ static inline void bprm_clear_caps(struct linux_binprm *bprm) | |||
239 | bprm->cap_effective = false; | 238 | bprm->cap_effective = false; |
240 | } | 239 | } |
241 | 240 | ||
242 | #ifdef CONFIG_SECURITY_FILE_CAPABILITIES | ||
243 | |||
244 | /** | 241 | /** |
245 | * cap_inode_need_killpriv - Determine if inode change affects privileges | 242 | * cap_inode_need_killpriv - Determine if inode change affects privileges |
246 | * @dentry: The inode/dentry in being changed with change marked ATTR_KILL_PRIV | 243 | * @dentry: The inode/dentry in being changed with change marked ATTR_KILL_PRIV |
@@ -421,49 +418,6 @@ out: | |||
421 | return rc; | 418 | return rc; |
422 | } | 419 | } |
423 | 420 | ||
424 | #else | ||
425 | int cap_inode_need_killpriv(struct dentry *dentry) | ||
426 | { | ||
427 | return 0; | ||
428 | } | ||
429 | |||
430 | int cap_inode_killpriv(struct dentry *dentry) | ||
431 | { | ||
432 | return 0; | ||
433 | } | ||
434 | |||
435 | int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps) | ||
436 | { | ||
437 | memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data)); | ||
438 | return -ENODATA; | ||
439 | } | ||
440 | |||
441 | static inline int get_file_caps(struct linux_binprm *bprm, bool *effective) | ||
442 | { | ||
443 | bprm_clear_caps(bprm); | ||
444 | return 0; | ||
445 | } | ||
446 | #endif | ||
447 | |||
448 | /* | ||
449 | * Determine whether a exec'ing process's new permitted capabilities should be | ||
450 | * limited to just what it already has. | ||
451 | * | ||
452 | * This prevents processes that are being ptraced from gaining access to | ||
453 | * CAP_SETPCAP, unless the process they're tracing already has it, and the | ||
454 | * binary they're executing has filecaps that elevate it. | ||
455 | * | ||
456 | * Returns 1 if they should be limited, 0 if they are not. | ||
457 | */ | ||
458 | static inline int cap_limit_ptraced_target(void) | ||
459 | { | ||
460 | #ifndef CONFIG_SECURITY_FILE_CAPABILITIES | ||
461 | if (capable(CAP_SETPCAP)) | ||
462 | return 0; | ||
463 | #endif | ||
464 | return 1; | ||
465 | } | ||
466 | |||
467 | /** | 421 | /** |
468 | * cap_bprm_set_creds - Set up the proposed credentials for execve(). | 422 | * cap_bprm_set_creds - Set up the proposed credentials for execve(). |
469 | * @bprm: The execution parameters, including the proposed creds | 423 | * @bprm: The execution parameters, including the proposed creds |
@@ -523,9 +477,8 @@ skip: | |||
523 | new->euid = new->uid; | 477 | new->euid = new->uid; |
524 | new->egid = new->gid; | 478 | new->egid = new->gid; |
525 | } | 479 | } |
526 | if (cap_limit_ptraced_target()) | 480 | new->cap_permitted = cap_intersect(new->cap_permitted, |
527 | new->cap_permitted = cap_intersect(new->cap_permitted, | 481 | old->cap_permitted); |
528 | old->cap_permitted); | ||
529 | } | 482 | } |
530 | 483 | ||
531 | new->suid = new->fsuid = new->euid; | 484 | new->suid = new->fsuid = new->euid; |
@@ -739,7 +692,6 @@ int cap_task_fix_setuid(struct cred *new, const struct cred *old, int flags) | |||
739 | return 0; | 692 | return 0; |
740 | } | 693 | } |
741 | 694 | ||
742 | #ifdef CONFIG_SECURITY_FILE_CAPABILITIES | ||
743 | /* | 695 | /* |
744 | * Rationale: code calling task_setscheduler, task_setioprio, and | 696 | * Rationale: code calling task_setscheduler, task_setioprio, and |
745 | * task_setnice, assumes that | 697 | * task_setnice, assumes that |
@@ -820,22 +772,6 @@ static long cap_prctl_drop(struct cred *new, unsigned long cap) | |||
820 | return 0; | 772 | return 0; |
821 | } | 773 | } |
822 | 774 | ||
823 | #else | ||
824 | int cap_task_setscheduler (struct task_struct *p, int policy, | ||
825 | struct sched_param *lp) | ||
826 | { | ||
827 | return 0; | ||
828 | } | ||
829 | int cap_task_setioprio (struct task_struct *p, int ioprio) | ||
830 | { | ||
831 | return 0; | ||
832 | } | ||
833 | int cap_task_setnice (struct task_struct *p, int nice) | ||
834 | { | ||
835 | return 0; | ||
836 | } | ||
837 | #endif | ||
838 | |||
839 | /** | 775 | /** |
840 | * cap_task_prctl - Implement process control functions for this security module | 776 | * cap_task_prctl - Implement process control functions for this security module |
841 | * @option: The process control function requested | 777 | * @option: The process control function requested |
@@ -866,7 +802,6 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, | |||
866 | error = !!cap_raised(new->cap_bset, arg2); | 802 | error = !!cap_raised(new->cap_bset, arg2); |
867 | goto no_change; | 803 | goto no_change; |
868 | 804 | ||
869 | #ifdef CONFIG_SECURITY_FILE_CAPABILITIES | ||
870 | case PR_CAPBSET_DROP: | 805 | case PR_CAPBSET_DROP: |
871 | error = cap_prctl_drop(new, arg2); | 806 | error = cap_prctl_drop(new, arg2); |
872 | if (error < 0) | 807 | if (error < 0) |
@@ -917,8 +852,6 @@ int cap_task_prctl(int option, unsigned long arg2, unsigned long arg3, | |||
917 | error = new->securebits; | 852 | error = new->securebits; |
918 | goto no_change; | 853 | goto no_change; |
919 | 854 | ||
920 | #endif /* def CONFIG_SECURITY_FILE_CAPABILITIES */ | ||
921 | |||
922 | case PR_GET_KEEPCAPS: | 855 | case PR_GET_KEEPCAPS: |
923 | if (issecure(SECURE_KEEP_CAPS)) | 856 | if (issecure(SECURE_KEEP_CAPS)) |
924 | error = 1; | 857 | error = 1; |
@@ -956,13 +889,17 @@ error: | |||
956 | /** | 889 | /** |
957 | * cap_syslog - Determine whether syslog function is permitted | 890 | * cap_syslog - Determine whether syslog function is permitted |
958 | * @type: Function requested | 891 | * @type: Function requested |
892 | * @from_file: Whether this request came from an open file (i.e. /proc) | ||
959 | * | 893 | * |
960 | * Determine whether the current process is permitted to use a particular | 894 | * Determine whether the current process is permitted to use a particular |
961 | * syslog function, returning 0 if permission is granted, -ve if not. | 895 | * syslog function, returning 0 if permission is granted, -ve if not. |
962 | */ | 896 | */ |
963 | int cap_syslog(int type) | 897 | int cap_syslog(int type, bool from_file) |
964 | { | 898 | { |
965 | if ((type != 3 && type != 10) && !capable(CAP_SYS_ADMIN)) | 899 | if (type != SYSLOG_ACTION_OPEN && from_file) |
900 | return 0; | ||
901 | if ((type != SYSLOG_ACTION_READ_ALL && | ||
902 | type != SYSLOG_ACTION_SIZE_BUFFER) && !capable(CAP_SYS_ADMIN)) | ||
966 | return -EPERM; | 903 | return -EPERM; |
967 | return 0; | 904 | return 0; |
968 | } | 905 | } |
diff --git a/security/device_cgroup.c b/security/device_cgroup.c index 6cf8fd2b79e8..f77c60423992 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/list.h> | 10 | #include <linux/list.h> |
11 | #include <linux/uaccess.h> | 11 | #include <linux/uaccess.h> |
12 | #include <linux/seq_file.h> | 12 | #include <linux/seq_file.h> |
13 | #include <linux/slab.h> | ||
13 | #include <linux/rcupdate.h> | 14 | #include <linux/rcupdate.h> |
14 | #include <linux/mutex.h> | 15 | #include <linux/mutex.h> |
15 | 16 | ||
diff --git a/security/inode.c b/security/inode.c index f7496c6a022b..1c812e874504 100644 --- a/security/inode.c +++ b/security/inode.c | |||
@@ -156,25 +156,18 @@ static int create_by_name(const char *name, mode_t mode, | |||
156 | * block. A pointer to that is in the struct vfsmount that we | 156 | * block. A pointer to that is in the struct vfsmount that we |
157 | * have around. | 157 | * have around. |
158 | */ | 158 | */ |
159 | if (!parent ) { | 159 | if (!parent) |
160 | if (mount && mount->mnt_sb) { | 160 | parent = mount->mnt_sb->s_root; |
161 | parent = mount->mnt_sb->s_root; | ||
162 | } | ||
163 | } | ||
164 | if (!parent) { | ||
165 | pr_debug("securityfs: Ah! can not find a parent!\n"); | ||
166 | return -EFAULT; | ||
167 | } | ||
168 | 161 | ||
169 | mutex_lock(&parent->d_inode->i_mutex); | 162 | mutex_lock(&parent->d_inode->i_mutex); |
170 | *dentry = lookup_one_len(name, parent, strlen(name)); | 163 | *dentry = lookup_one_len(name, parent, strlen(name)); |
171 | if (!IS_ERR(dentry)) { | 164 | if (!IS_ERR(*dentry)) { |
172 | if ((mode & S_IFMT) == S_IFDIR) | 165 | if ((mode & S_IFMT) == S_IFDIR) |
173 | error = mkdir(parent->d_inode, *dentry, mode); | 166 | error = mkdir(parent->d_inode, *dentry, mode); |
174 | else | 167 | else |
175 | error = create(parent->d_inode, *dentry, mode); | 168 | error = create(parent->d_inode, *dentry, mode); |
176 | } else | 169 | } else |
177 | error = PTR_ERR(dentry); | 170 | error = PTR_ERR(*dentry); |
178 | mutex_unlock(&parent->d_inode->i_mutex); | 171 | mutex_unlock(&parent->d_inode->i_mutex); |
179 | 172 | ||
180 | return error; | 173 | return error; |
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 53d9764e8f09..3d7846de8069 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig | |||
@@ -3,6 +3,7 @@ | |||
3 | config IMA | 3 | config IMA |
4 | bool "Integrity Measurement Architecture(IMA)" | 4 | bool "Integrity Measurement Architecture(IMA)" |
5 | depends on ACPI | 5 | depends on ACPI |
6 | depends on SECURITY | ||
6 | select SECURITYFS | 7 | select SECURITYFS |
7 | select CRYPTO | 8 | select CRYPTO |
8 | select CRYPTO_HMAC | 9 | select CRYPTO_HMAC |
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 165eb5397ea5..47fb65d1fcbd 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
@@ -65,7 +65,6 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode, | |||
65 | const char *cause, int result, int info); | 65 | const char *cause, int result, int info); |
66 | 66 | ||
67 | /* Internal IMA function definitions */ | 67 | /* Internal IMA function definitions */ |
68 | void ima_iintcache_init(void); | ||
69 | int ima_init(void); | 68 | int ima_init(void); |
70 | void ima_cleanup(void); | 69 | void ima_cleanup(void); |
71 | int ima_fs_init(void); | 70 | int ima_fs_init(void); |
@@ -97,7 +96,6 @@ static inline unsigned long ima_hash_key(u8 *digest) | |||
97 | 96 | ||
98 | /* iint cache flags */ | 97 | /* iint cache flags */ |
99 | #define IMA_MEASURED 1 | 98 | #define IMA_MEASURED 1 |
100 | #define IMA_IINT_DUMP_STACK 512 | ||
101 | 99 | ||
102 | /* integrity data associated with an inode */ | 100 | /* integrity data associated with an inode */ |
103 | struct ima_iint_cache { | 101 | struct ima_iint_cache { |
@@ -128,13 +126,11 @@ void ima_template_show(struct seq_file *m, void *e, | |||
128 | */ | 126 | */ |
129 | struct ima_iint_cache *ima_iint_insert(struct inode *inode); | 127 | struct ima_iint_cache *ima_iint_insert(struct inode *inode); |
130 | struct ima_iint_cache *ima_iint_find_get(struct inode *inode); | 128 | struct ima_iint_cache *ima_iint_find_get(struct inode *inode); |
131 | struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode); | ||
132 | void ima_iint_delete(struct inode *inode); | ||
133 | void iint_free(struct kref *kref); | 129 | void iint_free(struct kref *kref); |
134 | void iint_rcu_free(struct rcu_head *rcu); | 130 | void iint_rcu_free(struct rcu_head *rcu); |
135 | 131 | ||
136 | /* IMA policy related functions */ | 132 | /* IMA policy related functions */ |
137 | enum ima_hooks { PATH_CHECK = 1, FILE_MMAP, BPRM_CHECK }; | 133 | enum ima_hooks { FILE_CHECK = 1, FILE_MMAP, BPRM_CHECK }; |
138 | 134 | ||
139 | int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask); | 135 | int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask); |
140 | void ima_init_policy(void); | 136 | void ima_init_policy(void); |
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 3cd58b60afd2..52015d098fdf 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c | |||
@@ -13,6 +13,7 @@ | |||
13 | * and store_template. | 13 | * and store_template. |
14 | */ | 14 | */ |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/slab.h> | ||
16 | 17 | ||
17 | #include "ima.h" | 18 | #include "ima.h" |
18 | static const char *IMA_TEMPLATE_NAME = "ima"; | 19 | static const char *IMA_TEMPLATE_NAME = "ima"; |
@@ -95,12 +96,12 @@ err_out: | |||
95 | * ima_must_measure - measure decision based on policy. | 96 | * ima_must_measure - measure decision based on policy. |
96 | * @inode: pointer to inode to measure | 97 | * @inode: pointer to inode to measure |
97 | * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE) | 98 | * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE) |
98 | * @function: calling function (PATH_CHECK, BPRM_CHECK, FILE_MMAP) | 99 | * @function: calling function (FILE_CHECK, BPRM_CHECK, FILE_MMAP) |
99 | * | 100 | * |
100 | * The policy is defined in terms of keypairs: | 101 | * The policy is defined in terms of keypairs: |
101 | * subj=, obj=, type=, func=, mask=, fsmagic= | 102 | * subj=, obj=, type=, func=, mask=, fsmagic= |
102 | * subj,obj, and type: are LSM specific. | 103 | * subj,obj, and type: are LSM specific. |
103 | * func: PATH_CHECK | BPRM_CHECK | FILE_MMAP | 104 | * func: FILE_CHECK | BPRM_CHECK | FILE_MMAP |
104 | * mask: contains the permission mask | 105 | * mask: contains the permission mask |
105 | * fsmagic: hex value | 106 | * fsmagic: hex value |
106 | * | 107 | * |
diff --git a/security/integrity/ima/ima_audit.c b/security/integrity/ima/ima_audit.c index ff513ff737f5..5af76340470c 100644 --- a/security/integrity/ima/ima_audit.c +++ b/security/integrity/ima/ima_audit.c | |||
@@ -11,6 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
14 | #include <linux/gfp.h> | ||
14 | #include <linux/audit.h> | 15 | #include <linux/audit.h> |
15 | #include "ima.h" | 16 | #include "ima.h" |
16 | 17 | ||
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 46642a19bc78..952e51373f58 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/crypto.h> | 18 | #include <linux/crypto.h> |
19 | #include <linux/scatterlist.h> | 19 | #include <linux/scatterlist.h> |
20 | #include <linux/err.h> | 20 | #include <linux/err.h> |
21 | #include <linux/slab.h> | ||
21 | #include "ima.h" | 22 | #include "ima.h" |
22 | 23 | ||
23 | static int init_desc(struct hash_desc *desc) | 24 | static int init_desc(struct hash_desc *desc) |
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 0c72c9c38956..07cb9c338cc4 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * current measurement list and IMA statistics | 16 | * current measurement list and IMA statistics |
17 | */ | 17 | */ |
18 | #include <linux/fcntl.h> | 18 | #include <linux/fcntl.h> |
19 | #include <linux/slab.h> | ||
19 | #include <linux/module.h> | 20 | #include <linux/module.h> |
20 | #include <linux/seq_file.h> | 21 | #include <linux/seq_file.h> |
21 | #include <linux/rculist.h> | 22 | #include <linux/rculist.h> |
diff --git a/security/integrity/ima/ima_iint.c b/security/integrity/ima/ima_iint.c index a4e2b1dac943..2c744d488014 100644 --- a/security/integrity/ima/ima_iint.c +++ b/security/integrity/ima/ima_iint.c | |||
@@ -14,13 +14,12 @@ | |||
14 | * - cache integrity information associated with an inode | 14 | * - cache integrity information associated with an inode |
15 | * using a radix tree. | 15 | * using a radix tree. |
16 | */ | 16 | */ |
17 | #include <linux/slab.h> | ||
17 | #include <linux/module.h> | 18 | #include <linux/module.h> |
18 | #include <linux/spinlock.h> | 19 | #include <linux/spinlock.h> |
19 | #include <linux/radix-tree.h> | 20 | #include <linux/radix-tree.h> |
20 | #include "ima.h" | 21 | #include "ima.h" |
21 | 22 | ||
22 | #define ima_iint_delete ima_inode_free | ||
23 | |||
24 | RADIX_TREE(ima_iint_store, GFP_ATOMIC); | 23 | RADIX_TREE(ima_iint_store, GFP_ATOMIC); |
25 | DEFINE_SPINLOCK(ima_iint_lock); | 24 | DEFINE_SPINLOCK(ima_iint_lock); |
26 | 25 | ||
@@ -45,22 +44,18 @@ out: | |||
45 | return iint; | 44 | return iint; |
46 | } | 45 | } |
47 | 46 | ||
48 | /* Allocate memory for the iint associated with the inode | 47 | /** |
49 | * from the iint_cache slab, initialize the iint, and | 48 | * ima_inode_alloc - allocate an iint associated with an inode |
50 | * insert it into the radix tree. | 49 | * @inode: pointer to the inode |
51 | * | ||
52 | * On success return a pointer to the iint; on failure return NULL. | ||
53 | */ | 50 | */ |
54 | struct ima_iint_cache *ima_iint_insert(struct inode *inode) | 51 | int ima_inode_alloc(struct inode *inode) |
55 | { | 52 | { |
56 | struct ima_iint_cache *iint = NULL; | 53 | struct ima_iint_cache *iint = NULL; |
57 | int rc = 0; | 54 | int rc = 0; |
58 | 55 | ||
59 | if (!ima_initialized) | ||
60 | return iint; | ||
61 | iint = kmem_cache_alloc(iint_cache, GFP_NOFS); | 56 | iint = kmem_cache_alloc(iint_cache, GFP_NOFS); |
62 | if (!iint) | 57 | if (!iint) |
63 | return iint; | 58 | return -ENOMEM; |
64 | 59 | ||
65 | rc = radix_tree_preload(GFP_NOFS); | 60 | rc = radix_tree_preload(GFP_NOFS); |
66 | if (rc < 0) | 61 | if (rc < 0) |
@@ -69,67 +64,14 @@ struct ima_iint_cache *ima_iint_insert(struct inode *inode) | |||
69 | spin_lock(&ima_iint_lock); | 64 | spin_lock(&ima_iint_lock); |
70 | rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint); | 65 | rc = radix_tree_insert(&ima_iint_store, (unsigned long)inode, iint); |
71 | spin_unlock(&ima_iint_lock); | 66 | spin_unlock(&ima_iint_lock); |
67 | radix_tree_preload_end(); | ||
72 | out: | 68 | out: |
73 | if (rc < 0) { | 69 | if (rc < 0) |
74 | kmem_cache_free(iint_cache, iint); | 70 | kmem_cache_free(iint_cache, iint); |
75 | if (rc == -EEXIST) { | ||
76 | spin_lock(&ima_iint_lock); | ||
77 | iint = radix_tree_lookup(&ima_iint_store, | ||
78 | (unsigned long)inode); | ||
79 | spin_unlock(&ima_iint_lock); | ||
80 | } else | ||
81 | iint = NULL; | ||
82 | } | ||
83 | radix_tree_preload_end(); | ||
84 | return iint; | ||
85 | } | ||
86 | 71 | ||
87 | /** | 72 | return rc; |
88 | * ima_inode_alloc - allocate an iint associated with an inode | ||
89 | * @inode: pointer to the inode | ||
90 | * | ||
91 | * Return 0 on success, 1 on failure. | ||
92 | */ | ||
93 | int ima_inode_alloc(struct inode *inode) | ||
94 | { | ||
95 | struct ima_iint_cache *iint; | ||
96 | |||
97 | if (!ima_initialized) | ||
98 | return 0; | ||
99 | |||
100 | iint = ima_iint_insert(inode); | ||
101 | if (!iint) | ||
102 | return 1; | ||
103 | return 0; | ||
104 | } | 73 | } |
105 | 74 | ||
106 | /* ima_iint_find_insert_get - get the iint associated with an inode | ||
107 | * | ||
108 | * Most insertions are done at inode_alloc, except those allocated | ||
109 | * before late_initcall. When the iint does not exist, allocate it, | ||
110 | * initialize and insert it, and increment the iint refcount. | ||
111 | * | ||
112 | * (Can't initialize at security_initcall before any inodes are | ||
113 | * allocated, got to wait at least until proc_init.) | ||
114 | * | ||
115 | * Return the iint. | ||
116 | */ | ||
117 | struct ima_iint_cache *ima_iint_find_insert_get(struct inode *inode) | ||
118 | { | ||
119 | struct ima_iint_cache *iint = NULL; | ||
120 | |||
121 | iint = ima_iint_find_get(inode); | ||
122 | if (iint) | ||
123 | return iint; | ||
124 | |||
125 | iint = ima_iint_insert(inode); | ||
126 | if (iint) | ||
127 | kref_get(&iint->refcount); | ||
128 | |||
129 | return iint; | ||
130 | } | ||
131 | EXPORT_SYMBOL_GPL(ima_iint_find_insert_get); | ||
132 | |||
133 | /* iint_free - called when the iint refcount goes to zero */ | 75 | /* iint_free - called when the iint refcount goes to zero */ |
134 | void iint_free(struct kref *kref) | 76 | void iint_free(struct kref *kref) |
135 | { | 77 | { |
@@ -164,17 +106,15 @@ void iint_rcu_free(struct rcu_head *rcu_head) | |||
164 | } | 106 | } |
165 | 107 | ||
166 | /** | 108 | /** |
167 | * ima_iint_delete - called on integrity_inode_free | 109 | * ima_inode_free - called on security_inode_free |
168 | * @inode: pointer to the inode | 110 | * @inode: pointer to the inode |
169 | * | 111 | * |
170 | * Free the integrity information(iint) associated with an inode. | 112 | * Free the integrity information(iint) associated with an inode. |
171 | */ | 113 | */ |
172 | void ima_iint_delete(struct inode *inode) | 114 | void ima_inode_free(struct inode *inode) |
173 | { | 115 | { |
174 | struct ima_iint_cache *iint; | 116 | struct ima_iint_cache *iint; |
175 | 117 | ||
176 | if (!ima_initialized) | ||
177 | return; | ||
178 | spin_lock(&ima_iint_lock); | 118 | spin_lock(&ima_iint_lock); |
179 | iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode); | 119 | iint = radix_tree_delete(&ima_iint_store, (unsigned long)inode); |
180 | spin_unlock(&ima_iint_lock); | 120 | spin_unlock(&ima_iint_lock); |
@@ -196,9 +136,11 @@ static void init_once(void *foo) | |||
196 | kref_set(&iint->refcount, 1); | 136 | kref_set(&iint->refcount, 1); |
197 | } | 137 | } |
198 | 138 | ||
199 | void __init ima_iintcache_init(void) | 139 | static int __init ima_iintcache_init(void) |
200 | { | 140 | { |
201 | iint_cache = | 141 | iint_cache = |
202 | kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0, | 142 | kmem_cache_create("iint_cache", sizeof(struct ima_iint_cache), 0, |
203 | SLAB_PANIC, init_once); | 143 | SLAB_PANIC, init_once); |
144 | return 0; | ||
204 | } | 145 | } |
146 | security_initcall(ima_iintcache_init); | ||
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index a40da7ae5900..b1bcb702a27c 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | #include <linux/module.h> | 17 | #include <linux/module.h> |
18 | #include <linux/scatterlist.h> | 18 | #include <linux/scatterlist.h> |
19 | #include <linux/slab.h> | ||
19 | #include <linux/err.h> | 20 | #include <linux/err.h> |
20 | #include "ima.h" | 21 | #include "ima.h" |
21 | 22 | ||
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index b85e61bcf246..b2c89d9de2a4 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -13,14 +13,15 @@ | |||
13 | * License. | 13 | * License. |
14 | * | 14 | * |
15 | * File: ima_main.c | 15 | * File: ima_main.c |
16 | * implements the IMA hooks: ima_bprm_check, ima_file_mmap, | 16 | * implements the IMA hooks: ima_bprm_check, ima_file_mmap, |
17 | * and ima_path_check. | 17 | * and ima_file_check. |
18 | */ | 18 | */ |
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/file.h> | 20 | #include <linux/file.h> |
21 | #include <linux/binfmts.h> | 21 | #include <linux/binfmts.h> |
22 | #include <linux/mount.h> | 22 | #include <linux/mount.h> |
23 | #include <linux/mman.h> | 23 | #include <linux/mman.h> |
24 | #include <linux/slab.h> | ||
24 | 25 | ||
25 | #include "ima.h" | 26 | #include "ima.h" |
26 | 27 | ||
@@ -35,50 +36,53 @@ static int __init hash_setup(char *str) | |||
35 | } | 36 | } |
36 | __setup("ima_hash=", hash_setup); | 37 | __setup("ima_hash=", hash_setup); |
37 | 38 | ||
38 | /** | 39 | struct ima_imbalance { |
39 | * ima_file_free - called on __fput() | 40 | struct hlist_node node; |
40 | * @file: pointer to file structure being freed | 41 | unsigned long fsmagic; |
42 | }; | ||
43 | |||
44 | /* | ||
45 | * ima_limit_imbalance - emit one imbalance message per filesystem type | ||
41 | * | 46 | * |
42 | * Flag files that changed, based on i_version; | 47 | * Maintain list of filesystem types that do not measure files properly. |
43 | * and decrement the iint readcount/writecount. | 48 | * Return false if unknown, true if known. |
44 | */ | 49 | */ |
45 | void ima_file_free(struct file *file) | 50 | static bool ima_limit_imbalance(struct file *file) |
46 | { | 51 | { |
47 | struct inode *inode = file->f_dentry->d_inode; | 52 | static DEFINE_SPINLOCK(ima_imbalance_lock); |
48 | struct ima_iint_cache *iint; | 53 | static HLIST_HEAD(ima_imbalance_list); |
49 | 54 | ||
50 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 55 | struct super_block *sb = file->f_dentry->d_sb; |
51 | return; | 56 | struct ima_imbalance *entry; |
52 | iint = ima_iint_find_get(inode); | 57 | struct hlist_node *node; |
53 | if (!iint) | 58 | bool found = false; |
54 | return; | 59 | |
55 | 60 | rcu_read_lock(); | |
56 | mutex_lock(&iint->mutex); | 61 | hlist_for_each_entry_rcu(entry, node, &ima_imbalance_list, node) { |
57 | if (iint->opencount <= 0) { | 62 | if (entry->fsmagic == sb->s_magic) { |
58 | printk(KERN_INFO | 63 | found = true; |
59 | "%s: %s open/free imbalance (r:%ld w:%ld o:%ld f:%ld)\n", | 64 | break; |
60 | __FUNCTION__, file->f_dentry->d_name.name, | ||
61 | iint->readcount, iint->writecount, | ||
62 | iint->opencount, atomic_long_read(&file->f_count)); | ||
63 | if (!(iint->flags & IMA_IINT_DUMP_STACK)) { | ||
64 | dump_stack(); | ||
65 | iint->flags |= IMA_IINT_DUMP_STACK; | ||
66 | } | 65 | } |
67 | } | 66 | } |
68 | iint->opencount--; | 67 | rcu_read_unlock(); |
69 | 68 | if (found) | |
70 | if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | 69 | goto out; |
71 | iint->readcount--; | ||
72 | 70 | ||
73 | if (file->f_mode & FMODE_WRITE) { | 71 | entry = kmalloc(sizeof(*entry), GFP_NOFS); |
74 | iint->writecount--; | 72 | if (!entry) |
75 | if (iint->writecount == 0) { | 73 | goto out; |
76 | if (iint->version != inode->i_version) | 74 | entry->fsmagic = sb->s_magic; |
77 | iint->flags &= ~IMA_MEASURED; | 75 | spin_lock(&ima_imbalance_lock); |
78 | } | 76 | /* |
79 | } | 77 | * we could have raced and something else might have added this fs |
80 | mutex_unlock(&iint->mutex); | 78 | * to the list, but we don't really care |
81 | kref_put(&iint->refcount, iint_free); | 79 | */ |
80 | hlist_add_head_rcu(&entry->node, &ima_imbalance_list); | ||
81 | spin_unlock(&ima_imbalance_lock); | ||
82 | printk(KERN_INFO "IMA: unmeasured files on fsmagic: %lX\n", | ||
83 | entry->fsmagic); | ||
84 | out: | ||
85 | return found; | ||
82 | } | 86 | } |
83 | 87 | ||
84 | /* ima_read_write_check - reflect possible reading/writing errors in the PCR. | 88 | /* ima_read_write_check - reflect possible reading/writing errors in the PCR. |
@@ -111,196 +115,142 @@ static void ima_read_write_check(enum iint_pcr_error error, | |||
111 | } | 115 | } |
112 | } | 116 | } |
113 | 117 | ||
114 | static int get_path_measurement(struct ima_iint_cache *iint, struct file *file, | 118 | /* |
115 | const unsigned char *filename) | 119 | * Update the counts given an fmode_t |
120 | */ | ||
121 | static void ima_inc_counts(struct ima_iint_cache *iint, fmode_t mode) | ||
116 | { | 122 | { |
117 | int rc = 0; | 123 | BUG_ON(!mutex_is_locked(&iint->mutex)); |
118 | |||
119 | iint->opencount++; | ||
120 | iint->readcount++; | ||
121 | |||
122 | rc = ima_collect_measurement(iint, file); | ||
123 | if (!rc) | ||
124 | ima_store_measurement(iint, file, filename); | ||
125 | return rc; | ||
126 | } | ||
127 | 124 | ||
128 | static void ima_update_counts(struct ima_iint_cache *iint, int mask) | ||
129 | { | ||
130 | iint->opencount++; | 125 | iint->opencount++; |
131 | if ((mask & MAY_WRITE) || (mask == 0)) | 126 | if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) |
132 | iint->writecount++; | ||
133 | else if (mask & (MAY_READ | MAY_EXEC)) | ||
134 | iint->readcount++; | 127 | iint->readcount++; |
128 | if (mode & FMODE_WRITE) | ||
129 | iint->writecount++; | ||
135 | } | 130 | } |
136 | 131 | ||
137 | /** | 132 | /* |
138 | * ima_path_check - based on policy, collect/store measurement. | 133 | * ima_counts_get - increment file counts |
139 | * @path: contains a pointer to the path to be measured | ||
140 | * @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE | ||
141 | * | ||
142 | * Measure the file being open for readonly, based on the | ||
143 | * ima_must_measure() policy decision. | ||
144 | * | 134 | * |
145 | * Keep read/write counters for all files, but only | 135 | * Maintain read/write counters for all files, but only |
146 | * invalidate the PCR for measured files: | 136 | * invalidate the PCR for measured files: |
147 | * - Opening a file for write when already open for read, | 137 | * - Opening a file for write when already open for read, |
148 | * results in a time of measure, time of use (ToMToU) error. | 138 | * results in a time of measure, time of use (ToMToU) error. |
149 | * - Opening a file for read when already open for write, | 139 | * - Opening a file for read when already open for write, |
150 | * could result in a file measurement error. | 140 | * could result in a file measurement error. |
151 | * | 141 | * |
152 | * Always return 0 and audit dentry_open failures. | ||
153 | * (Return code will be based upon measurement appraisal.) | ||
154 | */ | 142 | */ |
155 | int ima_path_check(struct path *path, int mask, int update_counts) | 143 | void ima_counts_get(struct file *file) |
156 | { | 144 | { |
157 | struct inode *inode = path->dentry->d_inode; | 145 | struct dentry *dentry = file->f_path.dentry; |
146 | struct inode *inode = dentry->d_inode; | ||
147 | fmode_t mode = file->f_mode; | ||
158 | struct ima_iint_cache *iint; | 148 | struct ima_iint_cache *iint; |
159 | struct file *file = NULL; | ||
160 | int rc; | 149 | int rc; |
161 | 150 | ||
162 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 151 | if (!ima_initialized || !S_ISREG(inode->i_mode)) |
163 | return 0; | 152 | return; |
164 | iint = ima_iint_find_insert_get(inode); | 153 | iint = ima_iint_find_get(inode); |
165 | if (!iint) | 154 | if (!iint) |
166 | return 0; | 155 | return; |
167 | |||
168 | mutex_lock(&iint->mutex); | 156 | mutex_lock(&iint->mutex); |
169 | if (update_counts) | 157 | rc = ima_must_measure(iint, inode, MAY_READ, FILE_CHECK); |
170 | ima_update_counts(iint, mask); | ||
171 | |||
172 | rc = ima_must_measure(iint, inode, MAY_READ, PATH_CHECK); | ||
173 | if (rc < 0) | 158 | if (rc < 0) |
174 | goto out; | 159 | goto out; |
175 | 160 | ||
176 | if ((mask & MAY_WRITE) || (mask == 0)) | 161 | if (mode & FMODE_WRITE) { |
177 | ima_read_write_check(TOMTOU, iint, inode, | 162 | ima_read_write_check(TOMTOU, iint, inode, dentry->d_name.name); |
178 | path->dentry->d_name.name); | ||
179 | |||
180 | if ((mask & (MAY_WRITE | MAY_READ | MAY_EXEC)) != MAY_READ) | ||
181 | goto out; | 163 | goto out; |
182 | |||
183 | ima_read_write_check(OPEN_WRITERS, iint, inode, | ||
184 | path->dentry->d_name.name); | ||
185 | if (!(iint->flags & IMA_MEASURED)) { | ||
186 | struct dentry *dentry = dget(path->dentry); | ||
187 | struct vfsmount *mnt = mntget(path->mnt); | ||
188 | |||
189 | file = dentry_open(dentry, mnt, O_RDONLY | O_LARGEFILE, | ||
190 | current_cred()); | ||
191 | if (IS_ERR(file)) { | ||
192 | int audit_info = 0; | ||
193 | |||
194 | integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, | ||
195 | dentry->d_name.name, | ||
196 | "add_measurement", | ||
197 | "dentry_open failed", | ||
198 | 1, audit_info); | ||
199 | file = NULL; | ||
200 | goto out; | ||
201 | } | ||
202 | rc = get_path_measurement(iint, file, dentry->d_name.name); | ||
203 | } | 164 | } |
165 | ima_read_write_check(OPEN_WRITERS, iint, inode, dentry->d_name.name); | ||
204 | out: | 166 | out: |
167 | ima_inc_counts(iint, file->f_mode); | ||
205 | mutex_unlock(&iint->mutex); | 168 | mutex_unlock(&iint->mutex); |
206 | if (file) | 169 | |
207 | fput(file); | ||
208 | kref_put(&iint->refcount, iint_free); | 170 | kref_put(&iint->refcount, iint_free); |
209 | return 0; | ||
210 | } | 171 | } |
211 | EXPORT_SYMBOL_GPL(ima_path_check); | ||
212 | 172 | ||
213 | static int process_measurement(struct file *file, const unsigned char *filename, | 173 | /* |
214 | int mask, int function) | 174 | * Decrement ima counts |
175 | */ | ||
176 | static void ima_dec_counts(struct ima_iint_cache *iint, struct inode *inode, | ||
177 | struct file *file) | ||
215 | { | 178 | { |
216 | struct inode *inode = file->f_dentry->d_inode; | 179 | mode_t mode = file->f_mode; |
217 | struct ima_iint_cache *iint; | 180 | BUG_ON(!mutex_is_locked(&iint->mutex)); |
218 | int rc; | ||
219 | 181 | ||
220 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 182 | iint->opencount--; |
221 | return 0; | 183 | if ((mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) |
222 | iint = ima_iint_find_insert_get(inode); | 184 | iint->readcount--; |
223 | if (!iint) | 185 | if (mode & FMODE_WRITE) { |
224 | return -ENOMEM; | 186 | iint->writecount--; |
225 | 187 | if (iint->writecount == 0) { | |
226 | mutex_lock(&iint->mutex); | 188 | if (iint->version != inode->i_version) |
227 | rc = ima_must_measure(iint, inode, mask, function); | 189 | iint->flags &= ~IMA_MEASURED; |
228 | if (rc != 0) | 190 | } |
229 | goto out; | 191 | } |
230 | 192 | ||
231 | rc = ima_collect_measurement(iint, file); | 193 | if (((iint->opencount < 0) || |
232 | if (!rc) | 194 | (iint->readcount < 0) || |
233 | ima_store_measurement(iint, file, filename); | 195 | (iint->writecount < 0)) && |
234 | out: | 196 | !ima_limit_imbalance(file)) { |
235 | mutex_unlock(&iint->mutex); | 197 | printk(KERN_INFO "%s: open/free imbalance (r:%ld w:%ld o:%ld)\n", |
236 | kref_put(&iint->refcount, iint_free); | 198 | __FUNCTION__, iint->readcount, iint->writecount, |
237 | return rc; | 199 | iint->opencount); |
200 | dump_stack(); | ||
201 | } | ||
238 | } | 202 | } |
239 | 203 | ||
240 | /* | 204 | /** |
241 | * ima_counts_put - decrement file counts | 205 | * ima_file_free - called on __fput() |
206 | * @file: pointer to file structure being freed | ||
242 | * | 207 | * |
243 | * File counts are incremented in ima_path_check. On file open | 208 | * Flag files that changed, based on i_version; |
244 | * error, such as ETXTBSY, decrement the counts to prevent | 209 | * and decrement the iint readcount/writecount. |
245 | * unnecessary imbalance messages. | ||
246 | */ | 210 | */ |
247 | void ima_counts_put(struct path *path, int mask) | 211 | void ima_file_free(struct file *file) |
248 | { | 212 | { |
249 | struct inode *inode = path->dentry->d_inode; | 213 | struct inode *inode = file->f_dentry->d_inode; |
250 | struct ima_iint_cache *iint; | 214 | struct ima_iint_cache *iint; |
251 | 215 | ||
252 | /* The inode may already have been freed, freeing the iint | 216 | if (!ima_initialized || !S_ISREG(inode->i_mode)) |
253 | * with it. Verify the inode is not NULL before dereferencing | ||
254 | * it. | ||
255 | */ | ||
256 | if (!ima_initialized || !inode || !S_ISREG(inode->i_mode)) | ||
257 | return; | 217 | return; |
258 | iint = ima_iint_find_insert_get(inode); | 218 | iint = ima_iint_find_get(inode); |
259 | if (!iint) | 219 | if (!iint) |
260 | return; | 220 | return; |
261 | 221 | ||
262 | mutex_lock(&iint->mutex); | 222 | mutex_lock(&iint->mutex); |
263 | iint->opencount--; | 223 | ima_dec_counts(iint, inode, file); |
264 | if ((mask & MAY_WRITE) || (mask == 0)) | ||
265 | iint->writecount--; | ||
266 | else if (mask & (MAY_READ | MAY_EXEC)) | ||
267 | iint->readcount--; | ||
268 | mutex_unlock(&iint->mutex); | 224 | mutex_unlock(&iint->mutex); |
269 | |||
270 | kref_put(&iint->refcount, iint_free); | 225 | kref_put(&iint->refcount, iint_free); |
271 | } | 226 | } |
272 | 227 | ||
273 | /* | 228 | static int process_measurement(struct file *file, const unsigned char *filename, |
274 | * ima_counts_get - increment file counts | 229 | int mask, int function) |
275 | * | ||
276 | * - for IPC shm and shmat file. | ||
277 | * - for nfsd exported files. | ||
278 | * | ||
279 | * Increment the counts for these files to prevent unnecessary | ||
280 | * imbalance messages. | ||
281 | */ | ||
282 | void ima_counts_get(struct file *file) | ||
283 | { | 230 | { |
284 | struct inode *inode = file->f_dentry->d_inode; | 231 | struct inode *inode = file->f_dentry->d_inode; |
285 | struct ima_iint_cache *iint; | 232 | struct ima_iint_cache *iint; |
233 | int rc; | ||
286 | 234 | ||
287 | if (!ima_initialized || !S_ISREG(inode->i_mode)) | 235 | if (!ima_initialized || !S_ISREG(inode->i_mode)) |
288 | return; | 236 | return 0; |
289 | iint = ima_iint_find_insert_get(inode); | 237 | iint = ima_iint_find_get(inode); |
290 | if (!iint) | 238 | if (!iint) |
291 | return; | 239 | return -ENOMEM; |
240 | |||
292 | mutex_lock(&iint->mutex); | 241 | mutex_lock(&iint->mutex); |
293 | iint->opencount++; | 242 | rc = ima_must_measure(iint, inode, mask, function); |
294 | if ((file->f_mode & (FMODE_READ | FMODE_WRITE)) == FMODE_READ) | 243 | if (rc != 0) |
295 | iint->readcount++; | 244 | goto out; |
296 | 245 | ||
297 | if (file->f_mode & FMODE_WRITE) | 246 | rc = ima_collect_measurement(iint, file); |
298 | iint->writecount++; | 247 | if (!rc) |
248 | ima_store_measurement(iint, file, filename); | ||
249 | out: | ||
299 | mutex_unlock(&iint->mutex); | 250 | mutex_unlock(&iint->mutex); |
300 | |||
301 | kref_put(&iint->refcount, iint_free); | 251 | kref_put(&iint->refcount, iint_free); |
252 | return rc; | ||
302 | } | 253 | } |
303 | EXPORT_SYMBOL_GPL(ima_counts_get); | ||
304 | 254 | ||
305 | /** | 255 | /** |
306 | * ima_file_mmap - based on policy, collect/store measurement. | 256 | * ima_file_mmap - based on policy, collect/store measurement. |
@@ -347,11 +297,31 @@ int ima_bprm_check(struct linux_binprm *bprm) | |||
347 | return 0; | 297 | return 0; |
348 | } | 298 | } |
349 | 299 | ||
300 | /** | ||
301 | * ima_path_check - based on policy, collect/store measurement. | ||
302 | * @file: pointer to the file to be measured | ||
303 | * @mask: contains MAY_READ, MAY_WRITE or MAY_EXECUTE | ||
304 | * | ||
305 | * Measure files based on the ima_must_measure() policy decision. | ||
306 | * | ||
307 | * Always return 0 and audit dentry_open failures. | ||
308 | * (Return code will be based upon measurement appraisal.) | ||
309 | */ | ||
310 | int ima_file_check(struct file *file, int mask) | ||
311 | { | ||
312 | int rc; | ||
313 | |||
314 | rc = process_measurement(file, file->f_dentry->d_name.name, | ||
315 | mask & (MAY_READ | MAY_WRITE | MAY_EXEC), | ||
316 | FILE_CHECK); | ||
317 | return 0; | ||
318 | } | ||
319 | EXPORT_SYMBOL_GPL(ima_file_check); | ||
320 | |||
350 | static int __init init_ima(void) | 321 | static int __init init_ima(void) |
351 | { | 322 | { |
352 | int error; | 323 | int error; |
353 | 324 | ||
354 | ima_iintcache_init(); | ||
355 | error = ima_init(); | 325 | error = ima_init(); |
356 | ima_initialized = 1; | 326 | ima_initialized = 1; |
357 | return error; | 327 | return error; |
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index e1278399b345..8643a93c5963 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/security.h> | 15 | #include <linux/security.h> |
16 | #include <linux/magic.h> | 16 | #include <linux/magic.h> |
17 | #include <linux/parser.h> | 17 | #include <linux/parser.h> |
18 | #include <linux/slab.h> | ||
18 | 19 | ||
19 | #include "ima.h" | 20 | #include "ima.h" |
20 | 21 | ||
@@ -67,7 +68,7 @@ static struct ima_measure_rule_entry default_rules[] = { | |||
67 | .flags = IMA_FUNC | IMA_MASK}, | 68 | .flags = IMA_FUNC | IMA_MASK}, |
68 | {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC, | 69 | {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC, |
69 | .flags = IMA_FUNC | IMA_MASK}, | 70 | .flags = IMA_FUNC | IMA_MASK}, |
70 | {.action = MEASURE,.func = PATH_CHECK,.mask = MAY_READ,.uid = 0, | 71 | {.action = MEASURE,.func = FILE_CHECK,.mask = MAY_READ,.uid = 0, |
71 | .flags = IMA_FUNC | IMA_MASK | IMA_UID}, | 72 | .flags = IMA_FUNC | IMA_MASK | IMA_UID}, |
72 | }; | 73 | }; |
73 | 74 | ||
@@ -282,8 +283,11 @@ static int ima_parse_rule(char *rule, struct ima_measure_rule_entry *entry) | |||
282 | break; | 283 | break; |
283 | case Opt_func: | 284 | case Opt_func: |
284 | audit_log_format(ab, "func=%s ", args[0].from); | 285 | audit_log_format(ab, "func=%s ", args[0].from); |
285 | if (strcmp(args[0].from, "PATH_CHECK") == 0) | 286 | if (strcmp(args[0].from, "FILE_CHECK") == 0) |
286 | entry->func = PATH_CHECK; | 287 | entry->func = FILE_CHECK; |
288 | /* PATH_CHECK is for backwards compat */ | ||
289 | else if (strcmp(args[0].from, "PATH_CHECK") == 0) | ||
290 | entry->func = FILE_CHECK; | ||
287 | else if (strcmp(args[0].from, "FILE_MMAP") == 0) | 291 | else if (strcmp(args[0].from, "FILE_MMAP") == 0) |
288 | entry->func = FILE_MMAP; | 292 | entry->func = FILE_MMAP; |
289 | else if (strcmp(args[0].from, "BPRM_CHECK") == 0) | 293 | else if (strcmp(args[0].from, "BPRM_CHECK") == 0) |
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index a0880e9c8e05..46ba62b1adf5 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c | |||
@@ -20,6 +20,7 @@ | |||
20 | */ | 20 | */ |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/rculist.h> | 22 | #include <linux/rculist.h> |
23 | #include <linux/slab.h> | ||
23 | #include "ima.h" | 24 | #include "ima.h" |
24 | 25 | ||
25 | LIST_HEAD(ima_measurements); /* list of all measurements */ | 26 | LIST_HEAD(ima_measurements); /* list of all measurements */ |
diff --git a/security/keys/gc.c b/security/keys/gc.c index 4770be375ffe..a46e825cbf02 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c | |||
@@ -77,9 +77,10 @@ static bool key_gc_keyring(struct key *keyring, time_t limit) | |||
77 | goto dont_gc; | 77 | goto dont_gc; |
78 | 78 | ||
79 | /* scan the keyring looking for dead keys */ | 79 | /* scan the keyring looking for dead keys */ |
80 | rcu_read_lock(); | ||
80 | klist = rcu_dereference(keyring->payload.subscriptions); | 81 | klist = rcu_dereference(keyring->payload.subscriptions); |
81 | if (!klist) | 82 | if (!klist) |
82 | goto dont_gc; | 83 | goto unlock_dont_gc; |
83 | 84 | ||
84 | for (loop = klist->nkeys - 1; loop >= 0; loop--) { | 85 | for (loop = klist->nkeys - 1; loop >= 0; loop--) { |
85 | key = klist->keys[loop]; | 86 | key = klist->keys[loop]; |
@@ -88,11 +89,14 @@ static bool key_gc_keyring(struct key *keyring, time_t limit) | |||
88 | goto do_gc; | 89 | goto do_gc; |
89 | } | 90 | } |
90 | 91 | ||
92 | unlock_dont_gc: | ||
93 | rcu_read_unlock(); | ||
91 | dont_gc: | 94 | dont_gc: |
92 | kleave(" = false"); | 95 | kleave(" = false"); |
93 | return false; | 96 | return false; |
94 | 97 | ||
95 | do_gc: | 98 | do_gc: |
99 | rcu_read_unlock(); | ||
96 | key_gc_cursor = keyring->serial; | 100 | key_gc_cursor = keyring->serial; |
97 | key_get(keyring); | 101 | key_get(keyring); |
98 | spin_unlock(&key_serial_lock); | 102 | spin_unlock(&key_serial_lock); |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 06ec722897be..e9c2e7c584d9 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -1194,7 +1194,7 @@ long keyctl_get_security(key_serial_t keyid, | |||
1194 | * have the authorisation token handy */ | 1194 | * have the authorisation token handy */ |
1195 | instkey = key_get_instantiation_authkey(keyid); | 1195 | instkey = key_get_instantiation_authkey(keyid); |
1196 | if (IS_ERR(instkey)) | 1196 | if (IS_ERR(instkey)) |
1197 | return PTR_ERR(key_ref); | 1197 | return PTR_ERR(instkey); |
1198 | key_put(instkey); | 1198 | key_put(instkey); |
1199 | 1199 | ||
1200 | key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, 0); | 1200 | key_ref = lookup_user_key(keyid, KEY_LOOKUP_PARTIAL, 0); |
@@ -1236,6 +1236,7 @@ long keyctl_get_security(key_serial_t keyid, | |||
1236 | */ | 1236 | */ |
1237 | long keyctl_session_to_parent(void) | 1237 | long keyctl_session_to_parent(void) |
1238 | { | 1238 | { |
1239 | #ifdef TIF_NOTIFY_RESUME | ||
1239 | struct task_struct *me, *parent; | 1240 | struct task_struct *me, *parent; |
1240 | const struct cred *mycred, *pcred; | 1241 | const struct cred *mycred, *pcred; |
1241 | struct cred *cred, *oldcred; | 1242 | struct cred *cred, *oldcred; |
@@ -1326,6 +1327,15 @@ not_permitted: | |||
1326 | error_keyring: | 1327 | error_keyring: |
1327 | key_ref_put(keyring_r); | 1328 | key_ref_put(keyring_r); |
1328 | return ret; | 1329 | return ret; |
1330 | |||
1331 | #else /* !TIF_NOTIFY_RESUME */ | ||
1332 | /* | ||
1333 | * To be removed when TIF_NOTIFY_RESUME has been implemented on | ||
1334 | * m68k/xtensa | ||
1335 | */ | ||
1336 | #warning TIF_NOTIFY_RESUME not implemented | ||
1337 | return -EOPNOTSUPP; | ||
1338 | #endif /* !TIF_NOTIFY_RESUME */ | ||
1329 | } | 1339 | } |
1330 | 1340 | ||
1331 | /*****************************************************************************/ | 1341 | /*****************************************************************************/ |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 8ec02746ca99..1e4b0037935c 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -20,6 +20,11 @@ | |||
20 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
21 | #include "internal.h" | 21 | #include "internal.h" |
22 | 22 | ||
23 | #define rcu_dereference_locked_keyring(keyring) \ | ||
24 | (rcu_dereference_protected( \ | ||
25 | (keyring)->payload.subscriptions, \ | ||
26 | rwsem_is_locked((struct rw_semaphore *)&(keyring)->sem))) | ||
27 | |||
23 | /* | 28 | /* |
24 | * when plumbing the depths of the key tree, this sets a hard limit set on how | 29 | * when plumbing the depths of the key tree, this sets a hard limit set on how |
25 | * deep we're willing to go | 30 | * deep we're willing to go |
@@ -151,7 +156,9 @@ static void keyring_destroy(struct key *keyring) | |||
151 | write_unlock(&keyring_name_lock); | 156 | write_unlock(&keyring_name_lock); |
152 | } | 157 | } |
153 | 158 | ||
154 | klist = rcu_dereference(keyring->payload.subscriptions); | 159 | klist = rcu_dereference_check(keyring->payload.subscriptions, |
160 | rcu_read_lock_held() || | ||
161 | atomic_read(&keyring->usage) == 0); | ||
155 | if (klist) { | 162 | if (klist) { |
156 | for (loop = klist->nkeys - 1; loop >= 0; loop--) | 163 | for (loop = klist->nkeys - 1; loop >= 0; loop--) |
157 | key_put(klist->keys[loop]); | 164 | key_put(klist->keys[loop]); |
@@ -199,8 +206,7 @@ static long keyring_read(const struct key *keyring, | |||
199 | int loop, ret; | 206 | int loop, ret; |
200 | 207 | ||
201 | ret = 0; | 208 | ret = 0; |
202 | klist = rcu_dereference(keyring->payload.subscriptions); | 209 | klist = rcu_dereference_locked_keyring(keyring); |
203 | |||
204 | if (klist) { | 210 | if (klist) { |
205 | /* calculate how much data we could return */ | 211 | /* calculate how much data we could return */ |
206 | qty = klist->nkeys * sizeof(key_serial_t); | 212 | qty = klist->nkeys * sizeof(key_serial_t); |
@@ -524,9 +530,8 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check) | |||
524 | struct key *keyring; | 530 | struct key *keyring; |
525 | int bucket; | 531 | int bucket; |
526 | 532 | ||
527 | keyring = ERR_PTR(-EINVAL); | ||
528 | if (!name) | 533 | if (!name) |
529 | goto error; | 534 | return ERR_PTR(-EINVAL); |
530 | 535 | ||
531 | bucket = keyring_hash(name); | 536 | bucket = keyring_hash(name); |
532 | 537 | ||
@@ -553,17 +558,18 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check) | |||
553 | KEY_SEARCH) < 0) | 558 | KEY_SEARCH) < 0) |
554 | continue; | 559 | continue; |
555 | 560 | ||
556 | /* we've got a match */ | 561 | /* we've got a match but we might end up racing with |
557 | atomic_inc(&keyring->usage); | 562 | * key_cleanup() if the keyring is currently 'dead' |
558 | read_unlock(&keyring_name_lock); | 563 | * (ie. it has a zero usage count) */ |
559 | goto error; | 564 | if (!atomic_inc_not_zero(&keyring->usage)) |
565 | continue; | ||
566 | goto out; | ||
560 | } | 567 | } |
561 | } | 568 | } |
562 | 569 | ||
563 | read_unlock(&keyring_name_lock); | ||
564 | keyring = ERR_PTR(-ENOKEY); | 570 | keyring = ERR_PTR(-ENOKEY); |
565 | 571 | out: | |
566 | error: | 572 | read_unlock(&keyring_name_lock); |
567 | return keyring; | 573 | return keyring; |
568 | 574 | ||
569 | } /* end find_keyring_by_name() */ | 575 | } /* end find_keyring_by_name() */ |
@@ -718,8 +724,7 @@ int __key_link(struct key *keyring, struct key *key) | |||
718 | } | 724 | } |
719 | 725 | ||
720 | /* see if there's a matching key we can displace */ | 726 | /* see if there's a matching key we can displace */ |
721 | klist = keyring->payload.subscriptions; | 727 | klist = rcu_dereference_locked_keyring(keyring); |
722 | |||
723 | if (klist && klist->nkeys > 0) { | 728 | if (klist && klist->nkeys > 0) { |
724 | struct key_type *type = key->type; | 729 | struct key_type *type = key->type; |
725 | 730 | ||
@@ -763,8 +768,6 @@ int __key_link(struct key *keyring, struct key *key) | |||
763 | if (ret < 0) | 768 | if (ret < 0) |
764 | goto error2; | 769 | goto error2; |
765 | 770 | ||
766 | klist = keyring->payload.subscriptions; | ||
767 | |||
768 | if (klist && klist->nkeys < klist->maxkeys) { | 771 | if (klist && klist->nkeys < klist->maxkeys) { |
769 | /* there's sufficient slack space to add directly */ | 772 | /* there's sufficient slack space to add directly */ |
770 | atomic_inc(&key->usage); | 773 | atomic_inc(&key->usage); |
@@ -866,7 +869,7 @@ int key_unlink(struct key *keyring, struct key *key) | |||
866 | 869 | ||
867 | down_write(&keyring->sem); | 870 | down_write(&keyring->sem); |
868 | 871 | ||
869 | klist = keyring->payload.subscriptions; | 872 | klist = rcu_dereference_locked_keyring(keyring); |
870 | if (klist) { | 873 | if (klist) { |
871 | /* search the keyring for the key */ | 874 | /* search the keyring for the key */ |
872 | for (loop = 0; loop < klist->nkeys; loop++) | 875 | for (loop = 0; loop < klist->nkeys; loop++) |
@@ -957,7 +960,7 @@ int keyring_clear(struct key *keyring) | |||
957 | /* detach the pointer block with the locks held */ | 960 | /* detach the pointer block with the locks held */ |
958 | down_write(&keyring->sem); | 961 | down_write(&keyring->sem); |
959 | 962 | ||
960 | klist = keyring->payload.subscriptions; | 963 | klist = rcu_dereference_locked_keyring(keyring); |
961 | if (klist) { | 964 | if (klist) { |
962 | /* adjust the quota */ | 965 | /* adjust the quota */ |
963 | key_payload_reserve(keyring, | 966 | key_payload_reserve(keyring, |
@@ -989,7 +992,9 @@ EXPORT_SYMBOL(keyring_clear); | |||
989 | */ | 992 | */ |
990 | static void keyring_revoke(struct key *keyring) | 993 | static void keyring_revoke(struct key *keyring) |
991 | { | 994 | { |
992 | struct keyring_list *klist = keyring->payload.subscriptions; | 995 | struct keyring_list *klist; |
996 | |||
997 | klist = rcu_dereference_locked_keyring(keyring); | ||
993 | 998 | ||
994 | /* adjust the quota */ | 999 | /* adjust the quota */ |
995 | key_payload_reserve(keyring, 0); | 1000 | key_payload_reserve(keyring, 0); |
@@ -1023,7 +1028,7 @@ void keyring_gc(struct key *keyring, time_t limit) | |||
1023 | 1028 | ||
1024 | down_write(&keyring->sem); | 1029 | down_write(&keyring->sem); |
1025 | 1030 | ||
1026 | klist = keyring->payload.subscriptions; | 1031 | klist = rcu_dereference_locked_keyring(keyring); |
1027 | if (!klist) | 1032 | if (!klist) |
1028 | goto no_klist; | 1033 | goto no_klist; |
1029 | 1034 | ||
diff --git a/security/keys/proc.c b/security/keys/proc.c index 9d01021ca0c8..706d63f4f185 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
15 | #include <linux/slab.h> | ||
16 | #include <linux/fs.h> | 15 | #include <linux/fs.h> |
17 | #include <linux/proc_fs.h> | 16 | #include <linux/proc_fs.h> |
18 | #include <linux/seq_file.h> | 17 | #include <linux/seq_file.h> |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 5c23afb31ece..06c2ccf26ed3 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -12,7 +12,6 @@ | |||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/sched.h> | 14 | #include <linux/sched.h> |
15 | #include <linux/slab.h> | ||
16 | #include <linux/keyctl.h> | 15 | #include <linux/keyctl.h> |
17 | #include <linux/fs.h> | 16 | #include <linux/fs.h> |
18 | #include <linux/err.h> | 17 | #include <linux/err.h> |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 03fe63ed55bd..d8c1a6a0fb08 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -68,7 +68,8 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
68 | { | 68 | { |
69 | const struct cred *cred = current_cred(); | 69 | const struct cred *cred = current_cred(); |
70 | key_serial_t prkey, sskey; | 70 | key_serial_t prkey, sskey; |
71 | struct key *key = cons->key, *authkey = cons->authkey, *keyring; | 71 | struct key *key = cons->key, *authkey = cons->authkey, *keyring, |
72 | *session; | ||
72 | char *argv[9], *envp[3], uid_str[12], gid_str[12]; | 73 | char *argv[9], *envp[3], uid_str[12], gid_str[12]; |
73 | char key_str[12], keyring_str[3][12]; | 74 | char key_str[12], keyring_str[3][12]; |
74 | char desc[20]; | 75 | char desc[20]; |
@@ -93,7 +94,7 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
93 | } | 94 | } |
94 | 95 | ||
95 | /* attach the auth key to the session keyring */ | 96 | /* attach the auth key to the session keyring */ |
96 | ret = __key_link(keyring, authkey); | 97 | ret = key_link(keyring, authkey); |
97 | if (ret < 0) | 98 | if (ret < 0) |
98 | goto error_link; | 99 | goto error_link; |
99 | 100 | ||
@@ -112,10 +113,12 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
112 | if (cred->tgcred->process_keyring) | 113 | if (cred->tgcred->process_keyring) |
113 | prkey = cred->tgcred->process_keyring->serial; | 114 | prkey = cred->tgcred->process_keyring->serial; |
114 | 115 | ||
115 | if (cred->tgcred->session_keyring) | 116 | rcu_read_lock(); |
116 | sskey = rcu_dereference(cred->tgcred->session_keyring)->serial; | 117 | session = rcu_dereference(cred->tgcred->session_keyring); |
117 | else | 118 | if (!session) |
118 | sskey = cred->user->session_keyring->serial; | 119 | session = cred->user->session_keyring; |
120 | sskey = session->serial; | ||
121 | rcu_read_unlock(); | ||
119 | 122 | ||
120 | sprintf(keyring_str[2], "%d", sskey); | 123 | sprintf(keyring_str[2], "%d", sskey); |
121 | 124 | ||
@@ -336,8 +339,10 @@ static int construct_alloc_key(struct key_type *type, | |||
336 | 339 | ||
337 | key_already_present: | 340 | key_already_present: |
338 | mutex_unlock(&key_construction_mutex); | 341 | mutex_unlock(&key_construction_mutex); |
339 | if (dest_keyring) | 342 | if (dest_keyring) { |
343 | __key_link(dest_keyring, key_ref_to_ptr(key_ref)); | ||
340 | up_write(&dest_keyring->sem); | 344 | up_write(&dest_keyring->sem); |
345 | } | ||
341 | mutex_unlock(&user->cons_lock); | 346 | mutex_unlock(&user->cons_lock); |
342 | key_put(key); | 347 | key_put(key); |
343 | *_key = key = key_ref_to_ptr(key_ref); | 348 | *_key = key = key_ref_to_ptr(key_ref); |
@@ -428,6 +433,11 @@ struct key *request_key_and_link(struct key_type *type, | |||
428 | 433 | ||
429 | if (!IS_ERR(key_ref)) { | 434 | if (!IS_ERR(key_ref)) { |
430 | key = key_ref_to_ptr(key_ref); | 435 | key = key_ref_to_ptr(key_ref); |
436 | if (dest_keyring) { | ||
437 | construct_get_dest_keyring(&dest_keyring); | ||
438 | key_link(dest_keyring, key); | ||
439 | key_put(dest_keyring); | ||
440 | } | ||
431 | } else if (PTR_ERR(key_ref) != -EAGAIN) { | 441 | } else if (PTR_ERR(key_ref) != -EAGAIN) { |
432 | key = ERR_CAST(key_ref); | 442 | key = ERR_CAST(key_ref); |
433 | } else { | 443 | } else { |
diff --git a/security/keys/sysctl.c b/security/keys/sysctl.c index 5e05dc09e2db..ee32d181764a 100644 --- a/security/keys/sysctl.c +++ b/security/keys/sysctl.c | |||
@@ -17,54 +17,49 @@ static const int zero, one = 1, max = INT_MAX; | |||
17 | 17 | ||
18 | ctl_table key_sysctls[] = { | 18 | ctl_table key_sysctls[] = { |
19 | { | 19 | { |
20 | .ctl_name = CTL_UNNUMBERED, | ||
21 | .procname = "maxkeys", | 20 | .procname = "maxkeys", |
22 | .data = &key_quota_maxkeys, | 21 | .data = &key_quota_maxkeys, |
23 | .maxlen = sizeof(unsigned), | 22 | .maxlen = sizeof(unsigned), |
24 | .mode = 0644, | 23 | .mode = 0644, |
25 | .proc_handler = &proc_dointvec_minmax, | 24 | .proc_handler = proc_dointvec_minmax, |
26 | .extra1 = (void *) &one, | 25 | .extra1 = (void *) &one, |
27 | .extra2 = (void *) &max, | 26 | .extra2 = (void *) &max, |
28 | }, | 27 | }, |
29 | { | 28 | { |
30 | .ctl_name = CTL_UNNUMBERED, | ||
31 | .procname = "maxbytes", | 29 | .procname = "maxbytes", |
32 | .data = &key_quota_maxbytes, | 30 | .data = &key_quota_maxbytes, |
33 | .maxlen = sizeof(unsigned), | 31 | .maxlen = sizeof(unsigned), |
34 | .mode = 0644, | 32 | .mode = 0644, |
35 | .proc_handler = &proc_dointvec_minmax, | 33 | .proc_handler = proc_dointvec_minmax, |
36 | .extra1 = (void *) &one, | 34 | .extra1 = (void *) &one, |
37 | .extra2 = (void *) &max, | 35 | .extra2 = (void *) &max, |
38 | }, | 36 | }, |
39 | { | 37 | { |
40 | .ctl_name = CTL_UNNUMBERED, | ||
41 | .procname = "root_maxkeys", | 38 | .procname = "root_maxkeys", |
42 | .data = &key_quota_root_maxkeys, | 39 | .data = &key_quota_root_maxkeys, |
43 | .maxlen = sizeof(unsigned), | 40 | .maxlen = sizeof(unsigned), |
44 | .mode = 0644, | 41 | .mode = 0644, |
45 | .proc_handler = &proc_dointvec_minmax, | 42 | .proc_handler = proc_dointvec_minmax, |
46 | .extra1 = (void *) &one, | 43 | .extra1 = (void *) &one, |
47 | .extra2 = (void *) &max, | 44 | .extra2 = (void *) &max, |
48 | }, | 45 | }, |
49 | { | 46 | { |
50 | .ctl_name = CTL_UNNUMBERED, | ||
51 | .procname = "root_maxbytes", | 47 | .procname = "root_maxbytes", |
52 | .data = &key_quota_root_maxbytes, | 48 | .data = &key_quota_root_maxbytes, |
53 | .maxlen = sizeof(unsigned), | 49 | .maxlen = sizeof(unsigned), |
54 | .mode = 0644, | 50 | .mode = 0644, |
55 | .proc_handler = &proc_dointvec_minmax, | 51 | .proc_handler = proc_dointvec_minmax, |
56 | .extra1 = (void *) &one, | 52 | .extra1 = (void *) &one, |
57 | .extra2 = (void *) &max, | 53 | .extra2 = (void *) &max, |
58 | }, | 54 | }, |
59 | { | 55 | { |
60 | .ctl_name = CTL_UNNUMBERED, | ||
61 | .procname = "gc_delay", | 56 | .procname = "gc_delay", |
62 | .data = &key_gc_delay, | 57 | .data = &key_gc_delay, |
63 | .maxlen = sizeof(unsigned), | 58 | .maxlen = sizeof(unsigned), |
64 | .mode = 0644, | 59 | .mode = 0644, |
65 | .proc_handler = &proc_dointvec_minmax, | 60 | .proc_handler = proc_dointvec_minmax, |
66 | .extra1 = (void *) &zero, | 61 | .extra1 = (void *) &zero, |
67 | .extra2 = (void *) &max, | 62 | .extra2 = (void *) &max, |
68 | }, | 63 | }, |
69 | { .ctl_name = 0 } | 64 | { } |
70 | }; | 65 | }; |
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index 7c687d568221..e9aa07929656 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c | |||
@@ -199,7 +199,8 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen) | |||
199 | struct user_key_payload *upayload; | 199 | struct user_key_payload *upayload; |
200 | long ret; | 200 | long ret; |
201 | 201 | ||
202 | upayload = rcu_dereference(key->payload.data); | 202 | upayload = rcu_dereference_protected( |
203 | key->payload.data, rwsem_is_locked(&((struct key *)key)->sem)); | ||
203 | ret = upayload->datalen; | 204 | ret = upayload->datalen; |
204 | 205 | ||
205 | /* we can return the data as is */ | 206 | /* we can return the data as is */ |
diff --git a/security/lsm_audit.c b/security/lsm_audit.c index 3bb90b6f1dd3..893365b79a29 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <linux/stddef.h> | 15 | #include <linux/stddef.h> |
16 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
17 | #include <linux/gfp.h> | ||
17 | #include <linux/fs.h> | 18 | #include <linux/fs.h> |
18 | #include <linux/init.h> | 19 | #include <linux/init.h> |
19 | #include <net/sock.h> | 20 | #include <net/sock.h> |
@@ -273,11 +274,11 @@ static void dump_common_audit_data(struct audit_buffer *ab, | |||
273 | case AF_INET: { | 274 | case AF_INET: { |
274 | struct inet_sock *inet = inet_sk(sk); | 275 | struct inet_sock *inet = inet_sk(sk); |
275 | 276 | ||
276 | print_ipv4_addr(ab, inet->rcv_saddr, | 277 | print_ipv4_addr(ab, inet->inet_rcv_saddr, |
277 | inet->sport, | 278 | inet->inet_sport, |
278 | "laddr", "lport"); | 279 | "laddr", "lport"); |
279 | print_ipv4_addr(ab, inet->daddr, | 280 | print_ipv4_addr(ab, inet->inet_daddr, |
280 | inet->dport, | 281 | inet->inet_dport, |
281 | "faddr", "fport"); | 282 | "faddr", "fport"); |
282 | break; | 283 | break; |
283 | } | 284 | } |
@@ -286,10 +287,10 @@ static void dump_common_audit_data(struct audit_buffer *ab, | |||
286 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | 287 | struct ipv6_pinfo *inet6 = inet6_sk(sk); |
287 | 288 | ||
288 | print_ipv6_addr(ab, &inet6->rcv_saddr, | 289 | print_ipv6_addr(ab, &inet6->rcv_saddr, |
289 | inet->sport, | 290 | inet->inet_sport, |
290 | "laddr", "lport"); | 291 | "laddr", "lport"); |
291 | print_ipv6_addr(ab, &inet6->daddr, | 292 | print_ipv6_addr(ab, &inet6->daddr, |
292 | inet->dport, | 293 | inet->inet_dport, |
293 | "faddr", "fport"); | 294 | "faddr", "fport"); |
294 | break; | 295 | break; |
295 | } | 296 | } |
@@ -354,6 +355,10 @@ static void dump_common_audit_data(struct audit_buffer *ab, | |||
354 | } | 355 | } |
355 | break; | 356 | break; |
356 | #endif | 357 | #endif |
358 | case LSM_AUDIT_DATA_KMOD: | ||
359 | audit_log_format(ab, " kmod="); | ||
360 | audit_log_untrustedstring(ab, a->u.kmod_name); | ||
361 | break; | ||
357 | } /* switch (a->type) */ | 362 | } /* switch (a->type) */ |
358 | } | 363 | } |
359 | 364 | ||
diff --git a/security/min_addr.c b/security/min_addr.c index c844eed7915d..f728728f193b 100644 --- a/security/min_addr.c +++ b/security/min_addr.c | |||
@@ -33,6 +33,9 @@ int mmap_min_addr_handler(struct ctl_table *table, int write, | |||
33 | { | 33 | { |
34 | int ret; | 34 | int ret; |
35 | 35 | ||
36 | if (write && !capable(CAP_SYS_RAWIO)) | ||
37 | return -EPERM; | ||
38 | |||
36 | ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos); | 39 | ret = proc_doulongvec_minmax(table, write, buffer, lenp, ppos); |
37 | 40 | ||
38 | update_mmap_min_addr(); | 41 | update_mmap_min_addr(); |
@@ -40,7 +43,7 @@ int mmap_min_addr_handler(struct ctl_table *table, int write, | |||
40 | return ret; | 43 | return ret; |
41 | } | 44 | } |
42 | 45 | ||
43 | int __init init_mmap_min_addr(void) | 46 | static int __init init_mmap_min_addr(void) |
44 | { | 47 | { |
45 | update_mmap_min_addr(); | 48 | update_mmap_min_addr(); |
46 | 49 | ||
diff --git a/security/root_plug.c b/security/root_plug.c deleted file mode 100644 index 2f7ffa67c4d2..000000000000 --- a/security/root_plug.c +++ /dev/null | |||
@@ -1,90 +0,0 @@ | |||
1 | /* | ||
2 | * Root Plug sample LSM module | ||
3 | * | ||
4 | * Originally written for a Linux Journal. | ||
5 | * | ||
6 | * Copyright (C) 2002 Greg Kroah-Hartman <greg@kroah.com> | ||
7 | * | ||
8 | * Prevents any programs running with egid == 0 if a specific USB device | ||
9 | * is not present in the system. Yes, it can be gotten around, but is a | ||
10 | * nice starting point for people to play with, and learn the LSM | ||
11 | * interface. | ||
12 | * | ||
13 | * If you want to turn this into something with a semblance of security, | ||
14 | * you need to hook the task_* functions also. | ||
15 | * | ||
16 | * See http://www.linuxjournal.com/article.php?sid=6279 for more information | ||
17 | * about this code. | ||
18 | * | ||
19 | * This program is free software; you can redistribute it and/or | ||
20 | * modify it under the terms of the GNU General Public License as | ||
21 | * published by the Free Software Foundation, version 2 of the | ||
22 | * License. | ||
23 | */ | ||
24 | |||
25 | #include <linux/kernel.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/security.h> | ||
28 | #include <linux/usb.h> | ||
29 | #include <linux/moduleparam.h> | ||
30 | |||
31 | /* default is a generic type of usb to serial converter */ | ||
32 | static int vendor_id = 0x0557; | ||
33 | static int product_id = 0x2008; | ||
34 | |||
35 | module_param(vendor_id, uint, 0400); | ||
36 | module_param(product_id, uint, 0400); | ||
37 | |||
38 | /* should we print out debug messages */ | ||
39 | static int debug = 0; | ||
40 | |||
41 | module_param(debug, bool, 0600); | ||
42 | |||
43 | #define MY_NAME "root_plug" | ||
44 | |||
45 | #define root_dbg(fmt, arg...) \ | ||
46 | do { \ | ||
47 | if (debug) \ | ||
48 | printk(KERN_DEBUG "%s: %s: " fmt , \ | ||
49 | MY_NAME , __func__ , \ | ||
50 | ## arg); \ | ||
51 | } while (0) | ||
52 | |||
53 | static int rootplug_bprm_check_security (struct linux_binprm *bprm) | ||
54 | { | ||
55 | struct usb_device *dev; | ||
56 | |||
57 | root_dbg("file %s, e_uid = %d, e_gid = %d\n", | ||
58 | bprm->filename, bprm->cred->euid, bprm->cred->egid); | ||
59 | |||
60 | if (bprm->cred->egid == 0) { | ||
61 | dev = usb_find_device(vendor_id, product_id); | ||
62 | if (!dev) { | ||
63 | root_dbg("e_gid = 0, and device not found, " | ||
64 | "task not allowed to run...\n"); | ||
65 | return -EPERM; | ||
66 | } | ||
67 | usb_put_dev(dev); | ||
68 | } | ||
69 | |||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static struct security_operations rootplug_security_ops = { | ||
74 | .bprm_check_security = rootplug_bprm_check_security, | ||
75 | }; | ||
76 | |||
77 | static int __init rootplug_init (void) | ||
78 | { | ||
79 | /* register ourselves with the security framework */ | ||
80 | if (register_security (&rootplug_security_ops)) { | ||
81 | printk (KERN_INFO | ||
82 | "Failure registering Root Plug module with the kernel\n"); | ||
83 | return -EINVAL; | ||
84 | } | ||
85 | printk (KERN_INFO "Root Plug module initialized, " | ||
86 | "vendor_id = %4.4x, product id = %4.4x\n", vendor_id, product_id); | ||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | security_initcall (rootplug_init); | ||
diff --git a/security/security.c b/security/security.c index c4c673240c1c..687c6fd14bb6 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -16,15 +16,19 @@ | |||
16 | #include <linux/init.h> | 16 | #include <linux/init.h> |
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/security.h> | 18 | #include <linux/security.h> |
19 | #include <linux/ima.h> | ||
19 | 20 | ||
20 | /* Boot-time LSM user choice */ | 21 | /* Boot-time LSM user choice */ |
21 | static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1]; | 22 | static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1] = |
23 | CONFIG_DEFAULT_SECURITY; | ||
22 | 24 | ||
23 | /* things that live in capability.c */ | 25 | /* things that live in capability.c */ |
24 | extern struct security_operations default_security_ops; | ||
25 | extern void security_fixup_ops(struct security_operations *ops); | 26 | extern void security_fixup_ops(struct security_operations *ops); |
26 | 27 | ||
27 | struct security_operations *security_ops; /* Initialized to NULL */ | 28 | static struct security_operations *security_ops; |
29 | static struct security_operations default_security_ops = { | ||
30 | .name = "default", | ||
31 | }; | ||
28 | 32 | ||
29 | static inline int verify(struct security_operations *ops) | 33 | static inline int verify(struct security_operations *ops) |
30 | { | 34 | { |
@@ -61,6 +65,11 @@ int __init security_init(void) | |||
61 | return 0; | 65 | return 0; |
62 | } | 66 | } |
63 | 67 | ||
68 | void reset_security_ops(void) | ||
69 | { | ||
70 | security_ops = &default_security_ops; | ||
71 | } | ||
72 | |||
64 | /* Save user chosen LSM */ | 73 | /* Save user chosen LSM */ |
65 | static int __init choose_lsm(char *str) | 74 | static int __init choose_lsm(char *str) |
66 | { | 75 | { |
@@ -79,8 +88,10 @@ __setup("security=", choose_lsm); | |||
79 | * | 88 | * |
80 | * Return true if: | 89 | * Return true if: |
81 | * -The passed LSM is the one chosen by user at boot time, | 90 | * -The passed LSM is the one chosen by user at boot time, |
82 | * -or user didn't specify a specific LSM and we're the first to ask | 91 | * -or the passed LSM is configured as the default and the user did not |
83 | * for registration permission, | 92 | * choose an alternate LSM at boot time, |
93 | * -or there is no default LSM set and the user didn't specify a | ||
94 | * specific LSM and we're the first to ask for registration permission, | ||
84 | * -or the passed LSM is currently loaded. | 95 | * -or the passed LSM is currently loaded. |
85 | * Otherwise, return false. | 96 | * Otherwise, return false. |
86 | */ | 97 | */ |
@@ -199,9 +210,9 @@ int security_quota_on(struct dentry *dentry) | |||
199 | return security_ops->quota_on(dentry); | 210 | return security_ops->quota_on(dentry); |
200 | } | 211 | } |
201 | 212 | ||
202 | int security_syslog(int type) | 213 | int security_syslog(int type, bool from_file) |
203 | { | 214 | { |
204 | return security_ops->syslog(type); | 215 | return security_ops->syslog(type, from_file); |
205 | } | 216 | } |
206 | 217 | ||
207 | int security_settime(struct timespec *ts, struct timezone *tz) | 218 | int security_settime(struct timespec *ts, struct timezone *tz) |
@@ -235,7 +246,12 @@ int security_bprm_set_creds(struct linux_binprm *bprm) | |||
235 | 246 | ||
236 | int security_bprm_check(struct linux_binprm *bprm) | 247 | int security_bprm_check(struct linux_binprm *bprm) |
237 | { | 248 | { |
238 | return security_ops->bprm_check_security(bprm); | 249 | int ret; |
250 | |||
251 | ret = security_ops->bprm_check_security(bprm); | ||
252 | if (ret) | ||
253 | return ret; | ||
254 | return ima_bprm_check(bprm); | ||
239 | } | 255 | } |
240 | 256 | ||
241 | void security_bprm_committing_creds(struct linux_binprm *bprm) | 257 | void security_bprm_committing_creds(struct linux_binprm *bprm) |
@@ -352,12 +368,21 @@ EXPORT_SYMBOL(security_sb_parse_opts_str); | |||
352 | 368 | ||
353 | int security_inode_alloc(struct inode *inode) | 369 | int security_inode_alloc(struct inode *inode) |
354 | { | 370 | { |
371 | int ret; | ||
372 | |||
355 | inode->i_security = NULL; | 373 | inode->i_security = NULL; |
356 | return security_ops->inode_alloc_security(inode); | 374 | ret = security_ops->inode_alloc_security(inode); |
375 | if (ret) | ||
376 | return ret; | ||
377 | ret = ima_inode_alloc(inode); | ||
378 | if (ret) | ||
379 | security_inode_free(inode); | ||
380 | return ret; | ||
357 | } | 381 | } |
358 | 382 | ||
359 | void security_inode_free(struct inode *inode) | 383 | void security_inode_free(struct inode *inode) |
360 | { | 384 | { |
385 | ima_inode_free(inode); | ||
361 | security_ops->inode_free_security(inode); | 386 | security_ops->inode_free_security(inode); |
362 | } | 387 | } |
363 | 388 | ||
@@ -371,42 +396,42 @@ int security_inode_init_security(struct inode *inode, struct inode *dir, | |||
371 | EXPORT_SYMBOL(security_inode_init_security); | 396 | EXPORT_SYMBOL(security_inode_init_security); |
372 | 397 | ||
373 | #ifdef CONFIG_SECURITY_PATH | 398 | #ifdef CONFIG_SECURITY_PATH |
374 | int security_path_mknod(struct path *path, struct dentry *dentry, int mode, | 399 | int security_path_mknod(struct path *dir, struct dentry *dentry, int mode, |
375 | unsigned int dev) | 400 | unsigned int dev) |
376 | { | 401 | { |
377 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | 402 | if (unlikely(IS_PRIVATE(dir->dentry->d_inode))) |
378 | return 0; | 403 | return 0; |
379 | return security_ops->path_mknod(path, dentry, mode, dev); | 404 | return security_ops->path_mknod(dir, dentry, mode, dev); |
380 | } | 405 | } |
381 | EXPORT_SYMBOL(security_path_mknod); | 406 | EXPORT_SYMBOL(security_path_mknod); |
382 | 407 | ||
383 | int security_path_mkdir(struct path *path, struct dentry *dentry, int mode) | 408 | int security_path_mkdir(struct path *dir, struct dentry *dentry, int mode) |
384 | { | 409 | { |
385 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | 410 | if (unlikely(IS_PRIVATE(dir->dentry->d_inode))) |
386 | return 0; | 411 | return 0; |
387 | return security_ops->path_mkdir(path, dentry, mode); | 412 | return security_ops->path_mkdir(dir, dentry, mode); |
388 | } | 413 | } |
389 | 414 | ||
390 | int security_path_rmdir(struct path *path, struct dentry *dentry) | 415 | int security_path_rmdir(struct path *dir, struct dentry *dentry) |
391 | { | 416 | { |
392 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | 417 | if (unlikely(IS_PRIVATE(dir->dentry->d_inode))) |
393 | return 0; | 418 | return 0; |
394 | return security_ops->path_rmdir(path, dentry); | 419 | return security_ops->path_rmdir(dir, dentry); |
395 | } | 420 | } |
396 | 421 | ||
397 | int security_path_unlink(struct path *path, struct dentry *dentry) | 422 | int security_path_unlink(struct path *dir, struct dentry *dentry) |
398 | { | 423 | { |
399 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | 424 | if (unlikely(IS_PRIVATE(dir->dentry->d_inode))) |
400 | return 0; | 425 | return 0; |
401 | return security_ops->path_unlink(path, dentry); | 426 | return security_ops->path_unlink(dir, dentry); |
402 | } | 427 | } |
403 | 428 | ||
404 | int security_path_symlink(struct path *path, struct dentry *dentry, | 429 | int security_path_symlink(struct path *dir, struct dentry *dentry, |
405 | const char *old_name) | 430 | const char *old_name) |
406 | { | 431 | { |
407 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | 432 | if (unlikely(IS_PRIVATE(dir->dentry->d_inode))) |
408 | return 0; | 433 | return 0; |
409 | return security_ops->path_symlink(path, dentry, old_name); | 434 | return security_ops->path_symlink(dir, dentry, old_name); |
410 | } | 435 | } |
411 | 436 | ||
412 | int security_path_link(struct dentry *old_dentry, struct path *new_dir, | 437 | int security_path_link(struct dentry *old_dentry, struct path *new_dir, |
@@ -434,6 +459,26 @@ int security_path_truncate(struct path *path, loff_t length, | |||
434 | return 0; | 459 | return 0; |
435 | return security_ops->path_truncate(path, length, time_attrs); | 460 | return security_ops->path_truncate(path, length, time_attrs); |
436 | } | 461 | } |
462 | |||
463 | int security_path_chmod(struct dentry *dentry, struct vfsmount *mnt, | ||
464 | mode_t mode) | ||
465 | { | ||
466 | if (unlikely(IS_PRIVATE(dentry->d_inode))) | ||
467 | return 0; | ||
468 | return security_ops->path_chmod(dentry, mnt, mode); | ||
469 | } | ||
470 | |||
471 | int security_path_chown(struct path *path, uid_t uid, gid_t gid) | ||
472 | { | ||
473 | if (unlikely(IS_PRIVATE(path->dentry->d_inode))) | ||
474 | return 0; | ||
475 | return security_ops->path_chown(path, uid, gid); | ||
476 | } | ||
477 | |||
478 | int security_path_chroot(struct path *path) | ||
479 | { | ||
480 | return security_ops->path_chroot(path); | ||
481 | } | ||
437 | #endif | 482 | #endif |
438 | 483 | ||
439 | int security_inode_create(struct inode *dir, struct dentry *dentry, int mode) | 484 | int security_inode_create(struct inode *dir, struct dentry *dentry, int mode) |
@@ -592,14 +637,14 @@ int security_inode_killpriv(struct dentry *dentry) | |||
592 | int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc) | 637 | int security_inode_getsecurity(const struct inode *inode, const char *name, void **buffer, bool alloc) |
593 | { | 638 | { |
594 | if (unlikely(IS_PRIVATE(inode))) | 639 | if (unlikely(IS_PRIVATE(inode))) |
595 | return 0; | 640 | return -EOPNOTSUPP; |
596 | return security_ops->inode_getsecurity(inode, name, buffer, alloc); | 641 | return security_ops->inode_getsecurity(inode, name, buffer, alloc); |
597 | } | 642 | } |
598 | 643 | ||
599 | int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) | 644 | int security_inode_setsecurity(struct inode *inode, const char *name, const void *value, size_t size, int flags) |
600 | { | 645 | { |
601 | if (unlikely(IS_PRIVATE(inode))) | 646 | if (unlikely(IS_PRIVATE(inode))) |
602 | return 0; | 647 | return -EOPNOTSUPP; |
603 | return security_ops->inode_setsecurity(inode, name, value, size, flags); | 648 | return security_ops->inode_setsecurity(inode, name, value, size, flags); |
604 | } | 649 | } |
605 | 650 | ||
@@ -639,7 +684,12 @@ int security_file_mmap(struct file *file, unsigned long reqprot, | |||
639 | unsigned long prot, unsigned long flags, | 684 | unsigned long prot, unsigned long flags, |
640 | unsigned long addr, unsigned long addr_only) | 685 | unsigned long addr, unsigned long addr_only) |
641 | { | 686 | { |
642 | return security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only); | 687 | int ret; |
688 | |||
689 | ret = security_ops->file_mmap(file, reqprot, prot, flags, addr, addr_only); | ||
690 | if (ret) | ||
691 | return ret; | ||
692 | return ima_file_mmap(file, prot); | ||
643 | } | 693 | } |
644 | 694 | ||
645 | int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, | 695 | int security_file_mprotect(struct vm_area_struct *vma, unsigned long reqprot, |
@@ -719,9 +769,9 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
719 | return security_ops->kernel_create_files_as(new, inode); | 769 | return security_ops->kernel_create_files_as(new, inode); |
720 | } | 770 | } |
721 | 771 | ||
722 | int security_kernel_module_request(void) | 772 | int security_kernel_module_request(char *kmod_name) |
723 | { | 773 | { |
724 | return security_ops->kernel_module_request(); | 774 | return security_ops->kernel_module_request(kmod_name); |
725 | } | 775 | } |
726 | 776 | ||
727 | int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) | 777 | int security_task_setuid(uid_t id0, uid_t id1, uid_t id2, int flags) |
diff --git a/security/selinux/.gitignore b/security/selinux/.gitignore new file mode 100644 index 000000000000..2e5040a3d48b --- /dev/null +++ b/security/selinux/.gitignore | |||
@@ -0,0 +1,2 @@ | |||
1 | av_permissions.h | ||
2 | flask.h | ||
diff --git a/security/selinux/Makefile b/security/selinux/Makefile index d47fc5e545e0..f013982df417 100644 --- a/security/selinux/Makefile +++ b/security/selinux/Makefile | |||
@@ -18,5 +18,13 @@ selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o | |||
18 | 18 | ||
19 | selinux-$(CONFIG_NETLABEL) += netlabel.o | 19 | selinux-$(CONFIG_NETLABEL) += netlabel.o |
20 | 20 | ||
21 | EXTRA_CFLAGS += -Isecurity/selinux/include | 21 | EXTRA_CFLAGS += -Isecurity/selinux -Isecurity/selinux/include |
22 | 22 | ||
23 | $(obj)/avc.o: $(obj)/flask.h | ||
24 | |||
25 | quiet_cmd_flask = GEN $(obj)/flask.h $(obj)/av_permissions.h | ||
26 | cmd_flask = scripts/selinux/genheaders/genheaders $(obj)/flask.h $(obj)/av_permissions.h | ||
27 | |||
28 | targets += flask.h | ||
29 | $(obj)/flask.h: $(src)/include/classmap.h FORCE | ||
30 | $(call if_changed,flask) | ||
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index b4b5da1c0a42..989fef82563a 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -31,43 +31,7 @@ | |||
31 | #include <net/ipv6.h> | 31 | #include <net/ipv6.h> |
32 | #include "avc.h" | 32 | #include "avc.h" |
33 | #include "avc_ss.h" | 33 | #include "avc_ss.h" |
34 | 34 | #include "classmap.h" | |
35 | static const struct av_perm_to_string av_perm_to_string[] = { | ||
36 | #define S_(c, v, s) { c, v, s }, | ||
37 | #include "av_perm_to_string.h" | ||
38 | #undef S_ | ||
39 | }; | ||
40 | |||
41 | static const char *class_to_string[] = { | ||
42 | #define S_(s) s, | ||
43 | #include "class_to_string.h" | ||
44 | #undef S_ | ||
45 | }; | ||
46 | |||
47 | #define TB_(s) static const char *s[] = { | ||
48 | #define TE_(s) }; | ||
49 | #define S_(s) s, | ||
50 | #include "common_perm_to_string.h" | ||
51 | #undef TB_ | ||
52 | #undef TE_ | ||
53 | #undef S_ | ||
54 | |||
55 | static const struct av_inherit av_inherit[] = { | ||
56 | #define S_(c, i, b) { .tclass = c,\ | ||
57 | .common_pts = common_##i##_perm_to_string,\ | ||
58 | .common_base = b }, | ||
59 | #include "av_inherit.h" | ||
60 | #undef S_ | ||
61 | }; | ||
62 | |||
63 | const struct selinux_class_perm selinux_class_perm = { | ||
64 | .av_perm_to_string = av_perm_to_string, | ||
65 | .av_pts_len = ARRAY_SIZE(av_perm_to_string), | ||
66 | .class_to_string = class_to_string, | ||
67 | .cts_len = ARRAY_SIZE(class_to_string), | ||
68 | .av_inherit = av_inherit, | ||
69 | .av_inherit_len = ARRAY_SIZE(av_inherit) | ||
70 | }; | ||
71 | 35 | ||
72 | #define AVC_CACHE_SLOTS 512 | 36 | #define AVC_CACHE_SLOTS 512 |
73 | #define AVC_DEF_CACHE_THRESHOLD 512 | 37 | #define AVC_DEF_CACHE_THRESHOLD 512 |
@@ -139,52 +103,28 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass) | |||
139 | */ | 103 | */ |
140 | static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) | 104 | static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) |
141 | { | 105 | { |
142 | const char **common_pts = NULL; | 106 | const char **perms; |
143 | u32 common_base = 0; | 107 | int i, perm; |
144 | int i, i2, perm; | ||
145 | 108 | ||
146 | if (av == 0) { | 109 | if (av == 0) { |
147 | audit_log_format(ab, " null"); | 110 | audit_log_format(ab, " null"); |
148 | return; | 111 | return; |
149 | } | 112 | } |
150 | 113 | ||
151 | for (i = 0; i < ARRAY_SIZE(av_inherit); i++) { | 114 | perms = secclass_map[tclass-1].perms; |
152 | if (av_inherit[i].tclass == tclass) { | ||
153 | common_pts = av_inherit[i].common_pts; | ||
154 | common_base = av_inherit[i].common_base; | ||
155 | break; | ||
156 | } | ||
157 | } | ||
158 | 115 | ||
159 | audit_log_format(ab, " {"); | 116 | audit_log_format(ab, " {"); |
160 | i = 0; | 117 | i = 0; |
161 | perm = 1; | 118 | perm = 1; |
162 | while (perm < common_base) { | 119 | while (i < (sizeof(av) * 8)) { |
163 | if (perm & av) { | 120 | if ((perm & av) && perms[i]) { |
164 | audit_log_format(ab, " %s", common_pts[i]); | 121 | audit_log_format(ab, " %s", perms[i]); |
165 | av &= ~perm; | 122 | av &= ~perm; |
166 | } | 123 | } |
167 | i++; | 124 | i++; |
168 | perm <<= 1; | 125 | perm <<= 1; |
169 | } | 126 | } |
170 | 127 | ||
171 | while (i < sizeof(av) * 8) { | ||
172 | if (perm & av) { | ||
173 | for (i2 = 0; i2 < ARRAY_SIZE(av_perm_to_string); i2++) { | ||
174 | if ((av_perm_to_string[i2].tclass == tclass) && | ||
175 | (av_perm_to_string[i2].value == perm)) | ||
176 | break; | ||
177 | } | ||
178 | if (i2 < ARRAY_SIZE(av_perm_to_string)) { | ||
179 | audit_log_format(ab, " %s", | ||
180 | av_perm_to_string[i2].name); | ||
181 | av &= ~perm; | ||
182 | } | ||
183 | } | ||
184 | i++; | ||
185 | perm <<= 1; | ||
186 | } | ||
187 | |||
188 | if (av) | 128 | if (av) |
189 | audit_log_format(ab, " 0x%x", av); | 129 | audit_log_format(ab, " 0x%x", av); |
190 | 130 | ||
@@ -219,8 +159,8 @@ static void avc_dump_query(struct audit_buffer *ab, u32 ssid, u32 tsid, u16 tcla | |||
219 | kfree(scontext); | 159 | kfree(scontext); |
220 | } | 160 | } |
221 | 161 | ||
222 | BUG_ON(tclass >= ARRAY_SIZE(class_to_string) || !class_to_string[tclass]); | 162 | BUG_ON(tclass >= ARRAY_SIZE(secclass_map)); |
223 | audit_log_format(ab, " tclass=%s", class_to_string[tclass]); | 163 | audit_log_format(ab, " tclass=%s", secclass_map[tclass-1].name); |
224 | } | 164 | } |
225 | 165 | ||
226 | /** | 166 | /** |
@@ -397,7 +337,7 @@ static inline struct avc_node *avc_search_node(u32 ssid, u32 tsid, u16 tclass) | |||
397 | * Look up an AVC entry that is valid for the | 337 | * Look up an AVC entry that is valid for the |
398 | * (@ssid, @tsid), interpreting the permissions | 338 | * (@ssid, @tsid), interpreting the permissions |
399 | * based on @tclass. If a valid AVC entry exists, | 339 | * based on @tclass. If a valid AVC entry exists, |
400 | * then this function return the avc_node. | 340 | * then this function returns the avc_node. |
401 | * Otherwise, this function returns NULL. | 341 | * Otherwise, this function returns NULL. |
402 | */ | 342 | */ |
403 | static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass) | 343 | static struct avc_node *avc_lookup(u32 ssid, u32 tsid, u16 tclass) |
@@ -549,17 +489,14 @@ void avc_audit(u32 ssid, u32 tsid, | |||
549 | struct common_audit_data stack_data; | 489 | struct common_audit_data stack_data; |
550 | u32 denied, audited; | 490 | u32 denied, audited; |
551 | denied = requested & ~avd->allowed; | 491 | denied = requested & ~avd->allowed; |
552 | if (denied) { | 492 | if (denied) |
553 | audited = denied; | 493 | audited = denied & avd->auditdeny; |
554 | if (!(audited & avd->auditdeny)) | 494 | else if (result) |
555 | return; | ||
556 | } else if (result) { | ||
557 | audited = denied = requested; | 495 | audited = denied = requested; |
558 | } else { | 496 | else |
559 | audited = requested; | 497 | audited = requested & avd->auditallow; |
560 | if (!(audited & avd->auditallow)) | 498 | if (!audited) |
561 | return; | 499 | return; |
562 | } | ||
563 | if (!a) { | 500 | if (!a) { |
564 | a = &stack_data; | 501 | a = &stack_data; |
565 | memset(a, 0, sizeof(*a)); | 502 | memset(a, 0, sizeof(*a)); |
@@ -586,7 +523,7 @@ void avc_audit(u32 ssid, u32 tsid, | |||
586 | * @perms: permissions | 523 | * @perms: permissions |
587 | * | 524 | * |
588 | * Register a callback function for events in the set @events | 525 | * Register a callback function for events in the set @events |
589 | * related to the SID pair (@ssid, @tsid) and | 526 | * related to the SID pair (@ssid, @tsid) |
590 | * and the permissions @perms, interpreting | 527 | * and the permissions @perms, interpreting |
591 | * @perms based on @tclass. Returns %0 on success or | 528 | * @perms based on @tclass. Returns %0 on success or |
592 | * -%ENOMEM if insufficient memory exists to add the callback. | 529 | * -%ENOMEM if insufficient memory exists to add the callback. |
@@ -631,7 +568,7 @@ static inline int avc_sidcmp(u32 x, u32 y) | |||
631 | * | 568 | * |
632 | * if a valid AVC entry doesn't exist,this function returns -ENOENT. | 569 | * if a valid AVC entry doesn't exist,this function returns -ENOENT. |
633 | * if kmalloc() called internal returns NULL, this function returns -ENOMEM. | 570 | * if kmalloc() called internal returns NULL, this function returns -ENOMEM. |
634 | * otherwise, this function update the AVC entry. The original AVC-entry object | 571 | * otherwise, this function updates the AVC entry. The original AVC-entry object |
635 | * will release later by RCU. | 572 | * will release later by RCU. |
636 | */ | 573 | */ |
637 | static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass, | 574 | static int avc_update_node(u32 event, u32 perms, u32 ssid, u32 tsid, u16 tclass, |
@@ -806,9 +743,7 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
806 | else | 743 | else |
807 | avd = &avd_entry; | 744 | avd = &avd_entry; |
808 | 745 | ||
809 | rc = security_compute_av(ssid, tsid, tclass, requested, avd); | 746 | security_compute_av(ssid, tsid, tclass, avd); |
810 | if (rc) | ||
811 | goto out; | ||
812 | rcu_read_lock(); | 747 | rcu_read_lock(); |
813 | node = avc_insert(ssid, tsid, tclass, avd); | 748 | node = avc_insert(ssid, tsid, tclass, avd); |
814 | } else { | 749 | } else { |
@@ -830,7 +765,6 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
830 | } | 765 | } |
831 | 766 | ||
832 | rcu_read_unlock(); | 767 | rcu_read_unlock(); |
833 | out: | ||
834 | return rc; | 768 | return rc; |
835 | } | 769 | } |
836 | 770 | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index bb230d5d7085..5feecb41009d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -76,6 +76,7 @@ | |||
76 | #include <linux/selinux.h> | 76 | #include <linux/selinux.h> |
77 | #include <linux/mutex.h> | 77 | #include <linux/mutex.h> |
78 | #include <linux/posix-timers.h> | 78 | #include <linux/posix-timers.h> |
79 | #include <linux/syslog.h> | ||
79 | 80 | ||
80 | #include "avc.h" | 81 | #include "avc.h" |
81 | #include "objsec.h" | 82 | #include "objsec.h" |
@@ -91,7 +92,6 @@ | |||
91 | 92 | ||
92 | #define NUM_SEL_MNT_OPTS 5 | 93 | #define NUM_SEL_MNT_OPTS 5 |
93 | 94 | ||
94 | extern unsigned int policydb_loaded_version; | ||
95 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); | 95 | extern int selinux_nlmsg_lookup(u16 sclass, u16 nlmsg_type, u32 *perm); |
96 | extern struct security_operations *security_ops; | 96 | extern struct security_operations *security_ops; |
97 | 97 | ||
@@ -126,13 +126,6 @@ __setup("selinux=", selinux_enabled_setup); | |||
126 | int selinux_enabled = 1; | 126 | int selinux_enabled = 1; |
127 | #endif | 127 | #endif |
128 | 128 | ||
129 | |||
130 | /* | ||
131 | * Minimal support for a secondary security module, | ||
132 | * just to allow the use of the capability module. | ||
133 | */ | ||
134 | static struct security_operations *secondary_ops; | ||
135 | |||
136 | /* Lists of inode and superblock security structures initialized | 129 | /* Lists of inode and superblock security structures initialized |
137 | before the policy was loaded. */ | 130 | before the policy was loaded. */ |
138 | static LIST_HEAD(superblock_security_head); | 131 | static LIST_HEAD(superblock_security_head); |
@@ -2050,29 +2043,30 @@ static int selinux_quota_on(struct dentry *dentry) | |||
2050 | return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON); | 2043 | return dentry_has_perm(cred, NULL, dentry, FILE__QUOTAON); |
2051 | } | 2044 | } |
2052 | 2045 | ||
2053 | static int selinux_syslog(int type) | 2046 | static int selinux_syslog(int type, bool from_file) |
2054 | { | 2047 | { |
2055 | int rc; | 2048 | int rc; |
2056 | 2049 | ||
2057 | rc = cap_syslog(type); | 2050 | rc = cap_syslog(type, from_file); |
2058 | if (rc) | 2051 | if (rc) |
2059 | return rc; | 2052 | return rc; |
2060 | 2053 | ||
2061 | switch (type) { | 2054 | switch (type) { |
2062 | case 3: /* Read last kernel messages */ | 2055 | case SYSLOG_ACTION_READ_ALL: /* Read last kernel messages */ |
2063 | case 10: /* Return size of the log buffer */ | 2056 | case SYSLOG_ACTION_SIZE_BUFFER: /* Return size of the log buffer */ |
2064 | rc = task_has_system(current, SYSTEM__SYSLOG_READ); | 2057 | rc = task_has_system(current, SYSTEM__SYSLOG_READ); |
2065 | break; | 2058 | break; |
2066 | case 6: /* Disable logging to console */ | 2059 | case SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging to console */ |
2067 | case 7: /* Enable logging to console */ | 2060 | case SYSLOG_ACTION_CONSOLE_ON: /* Enable logging to console */ |
2068 | case 8: /* Set level of messages printed to console */ | 2061 | /* Set level of messages printed to console */ |
2062 | case SYSLOG_ACTION_CONSOLE_LEVEL: | ||
2069 | rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE); | 2063 | rc = task_has_system(current, SYSTEM__SYSLOG_CONSOLE); |
2070 | break; | 2064 | break; |
2071 | case 0: /* Close log */ | 2065 | case SYSLOG_ACTION_CLOSE: /* Close log */ |
2072 | case 1: /* Open log */ | 2066 | case SYSLOG_ACTION_OPEN: /* Open log */ |
2073 | case 2: /* Read from log */ | 2067 | case SYSLOG_ACTION_READ: /* Read from log */ |
2074 | case 4: /* Read/clear last kernel messages */ | 2068 | case SYSLOG_ACTION_READ_CLEAR: /* Read/clear last kernel messages */ |
2075 | case 5: /* Clear ring buffer */ | 2069 | case SYSLOG_ACTION_CLEAR: /* Clear ring buffer */ |
2076 | default: | 2070 | default: |
2077 | rc = task_has_system(current, SYSTEM__SYSLOG_MOD); | 2071 | rc = task_has_system(current, SYSTEM__SYSLOG_MOD); |
2078 | break; | 2072 | break; |
@@ -2366,7 +2360,7 @@ static void selinux_bprm_committing_creds(struct linux_binprm *bprm) | |||
2366 | initrlim = init_task.signal->rlim + i; | 2360 | initrlim = init_task.signal->rlim + i; |
2367 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); | 2361 | rlim->rlim_cur = min(rlim->rlim_max, initrlim->rlim_cur); |
2368 | } | 2362 | } |
2369 | update_rlimit_cpu(rlim->rlim_cur); | 2363 | update_rlimit_cpu(current->signal->rlim[RLIMIT_CPU].rlim_cur); |
2370 | } | 2364 | } |
2371 | } | 2365 | } |
2372 | 2366 | ||
@@ -3335,12 +3329,21 @@ static int selinux_kernel_create_files_as(struct cred *new, struct inode *inode) | |||
3335 | 3329 | ||
3336 | if (ret == 0) | 3330 | if (ret == 0) |
3337 | tsec->create_sid = isec->sid; | 3331 | tsec->create_sid = isec->sid; |
3338 | return 0; | 3332 | return ret; |
3339 | } | 3333 | } |
3340 | 3334 | ||
3341 | static int selinux_kernel_module_request(void) | 3335 | static int selinux_kernel_module_request(char *kmod_name) |
3342 | { | 3336 | { |
3343 | return task_has_system(current, SYSTEM__MODULE_REQUEST); | 3337 | u32 sid; |
3338 | struct common_audit_data ad; | ||
3339 | |||
3340 | sid = task_sid(current); | ||
3341 | |||
3342 | COMMON_AUDIT_DATA_INIT(&ad, KMOD); | ||
3343 | ad.u.kmod_name = kmod_name; | ||
3344 | |||
3345 | return avc_has_perm(sid, SECINITSID_KERNEL, SECCLASS_SYSTEM, | ||
3346 | SYSTEM__MODULE_REQUEST, &ad); | ||
3344 | } | 3347 | } |
3345 | 3348 | ||
3346 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) | 3349 | static int selinux_task_setpgid(struct task_struct *p, pid_t pgid) |
@@ -4085,7 +4088,7 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb, | |||
4085 | char *addrp; | 4088 | char *addrp; |
4086 | 4089 | ||
4087 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4090 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4088 | ad.u.net.netif = skb->iif; | 4091 | ad.u.net.netif = skb->skb_iif; |
4089 | ad.u.net.family = family; | 4092 | ad.u.net.family = family; |
4090 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); | 4093 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); |
4091 | if (err) | 4094 | if (err) |
@@ -4147,7 +4150,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4147 | return 0; | 4150 | return 0; |
4148 | 4151 | ||
4149 | COMMON_AUDIT_DATA_INIT(&ad, NET); | 4152 | COMMON_AUDIT_DATA_INIT(&ad, NET); |
4150 | ad.u.net.netif = skb->iif; | 4153 | ad.u.net.netif = skb->skb_iif; |
4151 | ad.u.net.family = family; | 4154 | ad.u.net.family = family; |
4152 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); | 4155 | err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL); |
4153 | if (err) | 4156 | if (err) |
@@ -4159,7 +4162,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4159 | err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); | 4162 | err = selinux_skb_peerlbl_sid(skb, family, &peer_sid); |
4160 | if (err) | 4163 | if (err) |
4161 | return err; | 4164 | return err; |
4162 | err = selinux_inet_sys_rcv_skb(skb->iif, addrp, family, | 4165 | err = selinux_inet_sys_rcv_skb(skb->skb_iif, addrp, family, |
4163 | peer_sid, &ad); | 4166 | peer_sid, &ad); |
4164 | if (err) { | 4167 | if (err) { |
4165 | selinux_netlbl_err(skb, err, 0); | 4168 | selinux_netlbl_err(skb, err, 0); |
@@ -4714,10 +4717,7 @@ static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb) | |||
4714 | if (err) | 4717 | if (err) |
4715 | return err; | 4718 | return err; |
4716 | 4719 | ||
4717 | if (policydb_loaded_version >= POLICYDB_VERSION_NLCLASS) | 4720 | return selinux_nlmsg_perm(sk, skb); |
4718 | err = selinux_nlmsg_perm(sk, skb); | ||
4719 | |||
4720 | return err; | ||
4721 | } | 4721 | } |
4722 | 4722 | ||
4723 | static int selinux_netlink_recv(struct sk_buff *skb, int capability) | 4723 | static int selinux_netlink_recv(struct sk_buff *skb, int capability) |
@@ -5667,9 +5667,6 @@ static __init int selinux_init(void) | |||
5667 | 0, SLAB_PANIC, NULL); | 5667 | 0, SLAB_PANIC, NULL); |
5668 | avc_init(); | 5668 | avc_init(); |
5669 | 5669 | ||
5670 | secondary_ops = security_ops; | ||
5671 | if (!secondary_ops) | ||
5672 | panic("SELinux: No initial security operations\n"); | ||
5673 | if (register_security(&selinux_ops)) | 5670 | if (register_security(&selinux_ops)) |
5674 | panic("SELinux: Unable to register with kernel.\n"); | 5671 | panic("SELinux: Unable to register with kernel.\n"); |
5675 | 5672 | ||
@@ -5830,12 +5827,11 @@ int selinux_disable(void) | |||
5830 | selinux_disabled = 1; | 5827 | selinux_disabled = 1; |
5831 | selinux_enabled = 0; | 5828 | selinux_enabled = 0; |
5832 | 5829 | ||
5830 | reset_security_ops(); | ||
5831 | |||
5833 | /* Try to destroy the avc node cache */ | 5832 | /* Try to destroy the avc node cache */ |
5834 | avc_disable(); | 5833 | avc_disable(); |
5835 | 5834 | ||
5836 | /* Reset security_ops to the secondary module, dummy or capability. */ | ||
5837 | security_ops = secondary_ops; | ||
5838 | |||
5839 | /* Unregister netfilter hooks. */ | 5835 | /* Unregister netfilter hooks. */ |
5840 | selinux_nf_ip_exit(); | 5836 | selinux_nf_ip_exit(); |
5841 | 5837 | ||
diff --git a/security/selinux/include/av_inherit.h b/security/selinux/include/av_inherit.h deleted file mode 100644 index abedcd704dae..000000000000 --- a/security/selinux/include/av_inherit.h +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | /* This file is automatically generated. Do not edit. */ | ||
2 | S_(SECCLASS_DIR, file, 0x00020000UL) | ||
3 | S_(SECCLASS_FILE, file, 0x00020000UL) | ||
4 | S_(SECCLASS_LNK_FILE, file, 0x00020000UL) | ||
5 | S_(SECCLASS_CHR_FILE, file, 0x00020000UL) | ||
6 | S_(SECCLASS_BLK_FILE, file, 0x00020000UL) | ||
7 | S_(SECCLASS_SOCK_FILE, file, 0x00020000UL) | ||
8 | S_(SECCLASS_FIFO_FILE, file, 0x00020000UL) | ||
9 | S_(SECCLASS_SOCKET, socket, 0x00400000UL) | ||
10 | S_(SECCLASS_TCP_SOCKET, socket, 0x00400000UL) | ||
11 | S_(SECCLASS_UDP_SOCKET, socket, 0x00400000UL) | ||
12 | S_(SECCLASS_RAWIP_SOCKET, socket, 0x00400000UL) | ||
13 | S_(SECCLASS_NETLINK_SOCKET, socket, 0x00400000UL) | ||
14 | S_(SECCLASS_PACKET_SOCKET, socket, 0x00400000UL) | ||
15 | S_(SECCLASS_KEY_SOCKET, socket, 0x00400000UL) | ||
16 | S_(SECCLASS_UNIX_STREAM_SOCKET, socket, 0x00400000UL) | ||
17 | S_(SECCLASS_UNIX_DGRAM_SOCKET, socket, 0x00400000UL) | ||
18 | S_(SECCLASS_TUN_SOCKET, socket, 0x00400000UL) | ||
19 | S_(SECCLASS_IPC, ipc, 0x00000200UL) | ||
20 | S_(SECCLASS_SEM, ipc, 0x00000200UL) | ||
21 | S_(SECCLASS_MSGQ, ipc, 0x00000200UL) | ||
22 | S_(SECCLASS_SHM, ipc, 0x00000200UL) | ||
23 | S_(SECCLASS_NETLINK_ROUTE_SOCKET, socket, 0x00400000UL) | ||
24 | S_(SECCLASS_NETLINK_FIREWALL_SOCKET, socket, 0x00400000UL) | ||
25 | S_(SECCLASS_NETLINK_TCPDIAG_SOCKET, socket, 0x00400000UL) | ||
26 | S_(SECCLASS_NETLINK_NFLOG_SOCKET, socket, 0x00400000UL) | ||
27 | S_(SECCLASS_NETLINK_XFRM_SOCKET, socket, 0x00400000UL) | ||
28 | S_(SECCLASS_NETLINK_SELINUX_SOCKET, socket, 0x00400000UL) | ||
29 | S_(SECCLASS_NETLINK_AUDIT_SOCKET, socket, 0x00400000UL) | ||
30 | S_(SECCLASS_NETLINK_IP6FW_SOCKET, socket, 0x00400000UL) | ||
31 | S_(SECCLASS_NETLINK_DNRT_SOCKET, socket, 0x00400000UL) | ||
32 | S_(SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET, socket, 0x00400000UL) | ||
33 | S_(SECCLASS_APPLETALK_SOCKET, socket, 0x00400000UL) | ||
34 | S_(SECCLASS_DCCP_SOCKET, socket, 0x00400000UL) | ||
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h deleted file mode 100644 index 2b683ad83d21..000000000000 --- a/security/selinux/include/av_perm_to_string.h +++ /dev/null | |||
@@ -1,183 +0,0 @@ | |||
1 | /* This file is automatically generated. Do not edit. */ | ||
2 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__MOUNT, "mount") | ||
3 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__REMOUNT, "remount") | ||
4 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__UNMOUNT, "unmount") | ||
5 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__GETATTR, "getattr") | ||
6 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__RELABELFROM, "relabelfrom") | ||
7 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__RELABELTO, "relabelto") | ||
8 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__TRANSITION, "transition") | ||
9 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__ASSOCIATE, "associate") | ||
10 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__QUOTAMOD, "quotamod") | ||
11 | S_(SECCLASS_FILESYSTEM, FILESYSTEM__QUOTAGET, "quotaget") | ||
12 | S_(SECCLASS_DIR, DIR__ADD_NAME, "add_name") | ||
13 | S_(SECCLASS_DIR, DIR__REMOVE_NAME, "remove_name") | ||
14 | S_(SECCLASS_DIR, DIR__REPARENT, "reparent") | ||
15 | S_(SECCLASS_DIR, DIR__SEARCH, "search") | ||
16 | S_(SECCLASS_DIR, DIR__RMDIR, "rmdir") | ||
17 | S_(SECCLASS_DIR, DIR__OPEN, "open") | ||
18 | S_(SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, "execute_no_trans") | ||
19 | S_(SECCLASS_FILE, FILE__ENTRYPOINT, "entrypoint") | ||
20 | S_(SECCLASS_FILE, FILE__EXECMOD, "execmod") | ||
21 | S_(SECCLASS_FILE, FILE__OPEN, "open") | ||
22 | S_(SECCLASS_CHR_FILE, CHR_FILE__EXECUTE_NO_TRANS, "execute_no_trans") | ||
23 | S_(SECCLASS_CHR_FILE, CHR_FILE__ENTRYPOINT, "entrypoint") | ||
24 | S_(SECCLASS_CHR_FILE, CHR_FILE__EXECMOD, "execmod") | ||
25 | S_(SECCLASS_CHR_FILE, CHR_FILE__OPEN, "open") | ||
26 | S_(SECCLASS_BLK_FILE, BLK_FILE__OPEN, "open") | ||
27 | S_(SECCLASS_SOCK_FILE, SOCK_FILE__OPEN, "open") | ||
28 | S_(SECCLASS_FIFO_FILE, FIFO_FILE__OPEN, "open") | ||
29 | S_(SECCLASS_FD, FD__USE, "use") | ||
30 | S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__CONNECTTO, "connectto") | ||
31 | S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NEWCONN, "newconn") | ||
32 | S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__ACCEPTFROM, "acceptfrom") | ||
33 | S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NODE_BIND, "node_bind") | ||
34 | S_(SECCLASS_TCP_SOCKET, TCP_SOCKET__NAME_CONNECT, "name_connect") | ||
35 | S_(SECCLASS_UDP_SOCKET, UDP_SOCKET__NODE_BIND, "node_bind") | ||
36 | S_(SECCLASS_RAWIP_SOCKET, RAWIP_SOCKET__NODE_BIND, "node_bind") | ||
37 | S_(SECCLASS_NODE, NODE__TCP_RECV, "tcp_recv") | ||
38 | S_(SECCLASS_NODE, NODE__TCP_SEND, "tcp_send") | ||
39 | S_(SECCLASS_NODE, NODE__UDP_RECV, "udp_recv") | ||
40 | S_(SECCLASS_NODE, NODE__UDP_SEND, "udp_send") | ||
41 | S_(SECCLASS_NODE, NODE__RAWIP_RECV, "rawip_recv") | ||
42 | S_(SECCLASS_NODE, NODE__RAWIP_SEND, "rawip_send") | ||
43 | S_(SECCLASS_NODE, NODE__ENFORCE_DEST, "enforce_dest") | ||
44 | S_(SECCLASS_NODE, NODE__DCCP_RECV, "dccp_recv") | ||
45 | S_(SECCLASS_NODE, NODE__DCCP_SEND, "dccp_send") | ||
46 | S_(SECCLASS_NODE, NODE__RECVFROM, "recvfrom") | ||
47 | S_(SECCLASS_NODE, NODE__SENDTO, "sendto") | ||
48 | S_(SECCLASS_NETIF, NETIF__TCP_RECV, "tcp_recv") | ||
49 | S_(SECCLASS_NETIF, NETIF__TCP_SEND, "tcp_send") | ||
50 | S_(SECCLASS_NETIF, NETIF__UDP_RECV, "udp_recv") | ||
51 | S_(SECCLASS_NETIF, NETIF__UDP_SEND, "udp_send") | ||
52 | S_(SECCLASS_NETIF, NETIF__RAWIP_RECV, "rawip_recv") | ||
53 | S_(SECCLASS_NETIF, NETIF__RAWIP_SEND, "rawip_send") | ||
54 | S_(SECCLASS_NETIF, NETIF__DCCP_RECV, "dccp_recv") | ||
55 | S_(SECCLASS_NETIF, NETIF__DCCP_SEND, "dccp_send") | ||
56 | S_(SECCLASS_NETIF, NETIF__INGRESS, "ingress") | ||
57 | S_(SECCLASS_NETIF, NETIF__EGRESS, "egress") | ||
58 | S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__CONNECTTO, "connectto") | ||
59 | S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__NEWCONN, "newconn") | ||
60 | S_(SECCLASS_UNIX_STREAM_SOCKET, UNIX_STREAM_SOCKET__ACCEPTFROM, "acceptfrom") | ||
61 | S_(SECCLASS_PROCESS, PROCESS__FORK, "fork") | ||
62 | S_(SECCLASS_PROCESS, PROCESS__TRANSITION, "transition") | ||
63 | S_(SECCLASS_PROCESS, PROCESS__SIGCHLD, "sigchld") | ||
64 | S_(SECCLASS_PROCESS, PROCESS__SIGKILL, "sigkill") | ||
65 | S_(SECCLASS_PROCESS, PROCESS__SIGSTOP, "sigstop") | ||
66 | S_(SECCLASS_PROCESS, PROCESS__SIGNULL, "signull") | ||
67 | S_(SECCLASS_PROCESS, PROCESS__SIGNAL, "signal") | ||
68 | S_(SECCLASS_PROCESS, PROCESS__PTRACE, "ptrace") | ||
69 | S_(SECCLASS_PROCESS, PROCESS__GETSCHED, "getsched") | ||
70 | S_(SECCLASS_PROCESS, PROCESS__SETSCHED, "setsched") | ||
71 | S_(SECCLASS_PROCESS, PROCESS__GETSESSION, "getsession") | ||
72 | S_(SECCLASS_PROCESS, PROCESS__GETPGID, "getpgid") | ||
73 | S_(SECCLASS_PROCESS, PROCESS__SETPGID, "setpgid") | ||
74 | S_(SECCLASS_PROCESS, PROCESS__GETCAP, "getcap") | ||
75 | S_(SECCLASS_PROCESS, PROCESS__SETCAP, "setcap") | ||
76 | S_(SECCLASS_PROCESS, PROCESS__SHARE, "share") | ||
77 | S_(SECCLASS_PROCESS, PROCESS__GETATTR, "getattr") | ||
78 | S_(SECCLASS_PROCESS, PROCESS__SETEXEC, "setexec") | ||
79 | S_(SECCLASS_PROCESS, PROCESS__SETFSCREATE, "setfscreate") | ||
80 | S_(SECCLASS_PROCESS, PROCESS__NOATSECURE, "noatsecure") | ||
81 | S_(SECCLASS_PROCESS, PROCESS__SIGINH, "siginh") | ||
82 | S_(SECCLASS_PROCESS, PROCESS__SETRLIMIT, "setrlimit") | ||
83 | S_(SECCLASS_PROCESS, PROCESS__RLIMITINH, "rlimitinh") | ||
84 | S_(SECCLASS_PROCESS, PROCESS__DYNTRANSITION, "dyntransition") | ||
85 | S_(SECCLASS_PROCESS, PROCESS__SETCURRENT, "setcurrent") | ||
86 | S_(SECCLASS_PROCESS, PROCESS__EXECMEM, "execmem") | ||
87 | S_(SECCLASS_PROCESS, PROCESS__EXECSTACK, "execstack") | ||
88 | S_(SECCLASS_PROCESS, PROCESS__EXECHEAP, "execheap") | ||
89 | S_(SECCLASS_PROCESS, PROCESS__SETKEYCREATE, "setkeycreate") | ||
90 | S_(SECCLASS_PROCESS, PROCESS__SETSOCKCREATE, "setsockcreate") | ||
91 | S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue") | ||
92 | S_(SECCLASS_MSG, MSG__SEND, "send") | ||
93 | S_(SECCLASS_MSG, MSG__RECEIVE, "receive") | ||
94 | S_(SECCLASS_SHM, SHM__LOCK, "lock") | ||
95 | S_(SECCLASS_SECURITY, SECURITY__COMPUTE_AV, "compute_av") | ||
96 | S_(SECCLASS_SECURITY, SECURITY__COMPUTE_CREATE, "compute_create") | ||
97 | S_(SECCLASS_SECURITY, SECURITY__COMPUTE_MEMBER, "compute_member") | ||
98 | S_(SECCLASS_SECURITY, SECURITY__CHECK_CONTEXT, "check_context") | ||
99 | S_(SECCLASS_SECURITY, SECURITY__LOAD_POLICY, "load_policy") | ||
100 | S_(SECCLASS_SECURITY, SECURITY__COMPUTE_RELABEL, "compute_relabel") | ||
101 | S_(SECCLASS_SECURITY, SECURITY__COMPUTE_USER, "compute_user") | ||
102 | S_(SECCLASS_SECURITY, SECURITY__SETENFORCE, "setenforce") | ||
103 | S_(SECCLASS_SECURITY, SECURITY__SETBOOL, "setbool") | ||
104 | S_(SECCLASS_SECURITY, SECURITY__SETSECPARAM, "setsecparam") | ||
105 | S_(SECCLASS_SECURITY, SECURITY__SETCHECKREQPROT, "setcheckreqprot") | ||
106 | S_(SECCLASS_SYSTEM, SYSTEM__IPC_INFO, "ipc_info") | ||
107 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_READ, "syslog_read") | ||
108 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_MOD, "syslog_mod") | ||
109 | S_(SECCLASS_SYSTEM, SYSTEM__SYSLOG_CONSOLE, "syslog_console") | ||
110 | S_(SECCLASS_SYSTEM, SYSTEM__MODULE_REQUEST, "module_request") | ||
111 | S_(SECCLASS_CAPABILITY, CAPABILITY__CHOWN, "chown") | ||
112 | S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_OVERRIDE, "dac_override") | ||
113 | S_(SECCLASS_CAPABILITY, CAPABILITY__DAC_READ_SEARCH, "dac_read_search") | ||
114 | S_(SECCLASS_CAPABILITY, CAPABILITY__FOWNER, "fowner") | ||
115 | S_(SECCLASS_CAPABILITY, CAPABILITY__FSETID, "fsetid") | ||
116 | S_(SECCLASS_CAPABILITY, CAPABILITY__KILL, "kill") | ||
117 | S_(SECCLASS_CAPABILITY, CAPABILITY__SETGID, "setgid") | ||
118 | S_(SECCLASS_CAPABILITY, CAPABILITY__SETUID, "setuid") | ||
119 | S_(SECCLASS_CAPABILITY, CAPABILITY__SETPCAP, "setpcap") | ||
120 | S_(SECCLASS_CAPABILITY, CAPABILITY__LINUX_IMMUTABLE, "linux_immutable") | ||
121 | S_(SECCLASS_CAPABILITY, CAPABILITY__NET_BIND_SERVICE, "net_bind_service") | ||
122 | S_(SECCLASS_CAPABILITY, CAPABILITY__NET_BROADCAST, "net_broadcast") | ||
123 | S_(SECCLASS_CAPABILITY, CAPABILITY__NET_ADMIN, "net_admin") | ||
124 | S_(SECCLASS_CAPABILITY, CAPABILITY__NET_RAW, "net_raw") | ||
125 | S_(SECCLASS_CAPABILITY, CAPABILITY__IPC_LOCK, "ipc_lock") | ||
126 | S_(SECCLASS_CAPABILITY, CAPABILITY__IPC_OWNER, "ipc_owner") | ||
127 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_MODULE, "sys_module") | ||
128 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_RAWIO, "sys_rawio") | ||
129 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_CHROOT, "sys_chroot") | ||
130 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_PTRACE, "sys_ptrace") | ||
131 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_PACCT, "sys_pacct") | ||
132 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_ADMIN, "sys_admin") | ||
133 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_BOOT, "sys_boot") | ||
134 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_NICE, "sys_nice") | ||
135 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_RESOURCE, "sys_resource") | ||
136 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_TIME, "sys_time") | ||
137 | S_(SECCLASS_CAPABILITY, CAPABILITY__SYS_TTY_CONFIG, "sys_tty_config") | ||
138 | S_(SECCLASS_CAPABILITY, CAPABILITY__MKNOD, "mknod") | ||
139 | S_(SECCLASS_CAPABILITY, CAPABILITY__LEASE, "lease") | ||
140 | S_(SECCLASS_CAPABILITY, CAPABILITY__AUDIT_WRITE, "audit_write") | ||
141 | S_(SECCLASS_CAPABILITY, CAPABILITY__AUDIT_CONTROL, "audit_control") | ||
142 | S_(SECCLASS_CAPABILITY, CAPABILITY__SETFCAP, "setfcap") | ||
143 | S_(SECCLASS_CAPABILITY2, CAPABILITY2__MAC_OVERRIDE, "mac_override") | ||
144 | S_(SECCLASS_CAPABILITY2, CAPABILITY2__MAC_ADMIN, "mac_admin") | ||
145 | S_(SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_READ, "nlmsg_read") | ||
146 | S_(SECCLASS_NETLINK_ROUTE_SOCKET, NETLINK_ROUTE_SOCKET__NLMSG_WRITE, "nlmsg_write") | ||
147 | S_(SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_READ, "nlmsg_read") | ||
148 | S_(SECCLASS_NETLINK_FIREWALL_SOCKET, NETLINK_FIREWALL_SOCKET__NLMSG_WRITE, "nlmsg_write") | ||
149 | S_(SECCLASS_NETLINK_TCPDIAG_SOCKET, NETLINK_TCPDIAG_SOCKET__NLMSG_READ, "nlmsg_read") | ||
150 | S_(SECCLASS_NETLINK_TCPDIAG_SOCKET, NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE, "nlmsg_write") | ||
151 | S_(SECCLASS_NETLINK_XFRM_SOCKET, NETLINK_XFRM_SOCKET__NLMSG_READ, "nlmsg_read") | ||
152 | S_(SECCLASS_NETLINK_XFRM_SOCKET, NETLINK_XFRM_SOCKET__NLMSG_WRITE, "nlmsg_write") | ||
153 | S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READ, "nlmsg_read") | ||
154 | S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_WRITE, "nlmsg_write") | ||
155 | S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_RELAY, "nlmsg_relay") | ||
156 | S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_READPRIV, "nlmsg_readpriv") | ||
157 | S_(SECCLASS_NETLINK_AUDIT_SOCKET, NETLINK_AUDIT_SOCKET__NLMSG_TTY_AUDIT, "nlmsg_tty_audit") | ||
158 | S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_READ, "nlmsg_read") | ||
159 | S_(SECCLASS_NETLINK_IP6FW_SOCKET, NETLINK_IP6FW_SOCKET__NLMSG_WRITE, "nlmsg_write") | ||
160 | S_(SECCLASS_ASSOCIATION, ASSOCIATION__SENDTO, "sendto") | ||
161 | S_(SECCLASS_ASSOCIATION, ASSOCIATION__RECVFROM, "recvfrom") | ||
162 | S_(SECCLASS_ASSOCIATION, ASSOCIATION__SETCONTEXT, "setcontext") | ||
163 | S_(SECCLASS_ASSOCIATION, ASSOCIATION__POLMATCH, "polmatch") | ||
164 | S_(SECCLASS_PACKET, PACKET__SEND, "send") | ||
165 | S_(SECCLASS_PACKET, PACKET__RECV, "recv") | ||
166 | S_(SECCLASS_PACKET, PACKET__RELABELTO, "relabelto") | ||
167 | S_(SECCLASS_PACKET, PACKET__FLOW_IN, "flow_in") | ||
168 | S_(SECCLASS_PACKET, PACKET__FLOW_OUT, "flow_out") | ||
169 | S_(SECCLASS_PACKET, PACKET__FORWARD_IN, "forward_in") | ||
170 | S_(SECCLASS_PACKET, PACKET__FORWARD_OUT, "forward_out") | ||
171 | S_(SECCLASS_KEY, KEY__VIEW, "view") | ||
172 | S_(SECCLASS_KEY, KEY__READ, "read") | ||
173 | S_(SECCLASS_KEY, KEY__WRITE, "write") | ||
174 | S_(SECCLASS_KEY, KEY__SEARCH, "search") | ||
175 | S_(SECCLASS_KEY, KEY__LINK, "link") | ||
176 | S_(SECCLASS_KEY, KEY__SETATTR, "setattr") | ||
177 | S_(SECCLASS_KEY, KEY__CREATE, "create") | ||
178 | S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NODE_BIND, "node_bind") | ||
179 | S_(SECCLASS_DCCP_SOCKET, DCCP_SOCKET__NAME_CONNECT, "name_connect") | ||
180 | S_(SECCLASS_MEMPROTECT, MEMPROTECT__MMAP_ZERO, "mmap_zero") | ||
181 | S_(SECCLASS_PEER, PEER__RECV, "recv") | ||
182 | S_(SECCLASS_KERNEL_SERVICE, KERNEL_SERVICE__USE_AS_OVERRIDE, "use_as_override") | ||
183 | S_(SECCLASS_KERNEL_SERVICE, KERNEL_SERVICE__CREATE_FILES_AS, "create_files_as") | ||
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h deleted file mode 100644 index 0546d616ccac..000000000000 --- a/security/selinux/include/av_permissions.h +++ /dev/null | |||
@@ -1,870 +0,0 @@ | |||
1 | /* This file is automatically generated. Do not edit. */ | ||
2 | #define COMMON_FILE__IOCTL 0x00000001UL | ||
3 | #define COMMON_FILE__READ 0x00000002UL | ||
4 | #define COMMON_FILE__WRITE 0x00000004UL | ||
5 | #define COMMON_FILE__CREATE 0x00000008UL | ||
6 | #define COMMON_FILE__GETATTR 0x00000010UL | ||
7 | #define COMMON_FILE__SETATTR 0x00000020UL | ||
8 | #define COMMON_FILE__LOCK 0x00000040UL | ||
9 | #define COMMON_FILE__RELABELFROM 0x00000080UL | ||
10 | #define COMMON_FILE__RELABELTO 0x00000100UL | ||
11 | #define COMMON_FILE__APPEND 0x00000200UL | ||
12 | #define COMMON_FILE__UNLINK 0x00000400UL | ||
13 | #define COMMON_FILE__LINK 0x00000800UL | ||
14 | #define COMMON_FILE__RENAME 0x00001000UL | ||
15 | #define COMMON_FILE__EXECUTE 0x00002000UL | ||
16 | #define COMMON_FILE__SWAPON 0x00004000UL | ||
17 | #define COMMON_FILE__QUOTAON 0x00008000UL | ||
18 | #define COMMON_FILE__MOUNTON 0x00010000UL | ||
19 | #define COMMON_SOCKET__IOCTL 0x00000001UL | ||
20 | #define COMMON_SOCKET__READ 0x00000002UL | ||
21 | #define COMMON_SOCKET__WRITE 0x00000004UL | ||
22 | #define COMMON_SOCKET__CREATE 0x00000008UL | ||
23 | #define COMMON_SOCKET__GETATTR 0x00000010UL | ||
24 | #define COMMON_SOCKET__SETATTR 0x00000020UL | ||
25 | #define COMMON_SOCKET__LOCK 0x00000040UL | ||
26 | #define COMMON_SOCKET__RELABELFROM 0x00000080UL | ||
27 | #define COMMON_SOCKET__RELABELTO 0x00000100UL | ||
28 | #define COMMON_SOCKET__APPEND 0x00000200UL | ||
29 | #define COMMON_SOCKET__BIND 0x00000400UL | ||
30 | #define COMMON_SOCKET__CONNECT 0x00000800UL | ||
31 | #define COMMON_SOCKET__LISTEN 0x00001000UL | ||
32 | #define COMMON_SOCKET__ACCEPT 0x00002000UL | ||
33 | #define COMMON_SOCKET__GETOPT 0x00004000UL | ||
34 | #define COMMON_SOCKET__SETOPT 0x00008000UL | ||
35 | #define COMMON_SOCKET__SHUTDOWN 0x00010000UL | ||
36 | #define COMMON_SOCKET__RECVFROM 0x00020000UL | ||
37 | #define COMMON_SOCKET__SENDTO 0x00040000UL | ||
38 | #define COMMON_SOCKET__RECV_MSG 0x00080000UL | ||
39 | #define COMMON_SOCKET__SEND_MSG 0x00100000UL | ||
40 | #define COMMON_SOCKET__NAME_BIND 0x00200000UL | ||
41 | #define COMMON_IPC__CREATE 0x00000001UL | ||
42 | #define COMMON_IPC__DESTROY 0x00000002UL | ||
43 | #define COMMON_IPC__GETATTR 0x00000004UL | ||
44 | #define COMMON_IPC__SETATTR 0x00000008UL | ||
45 | #define COMMON_IPC__READ 0x00000010UL | ||
46 | #define COMMON_IPC__WRITE 0x00000020UL | ||
47 | #define COMMON_IPC__ASSOCIATE 0x00000040UL | ||
48 | #define COMMON_IPC__UNIX_READ 0x00000080UL | ||
49 | #define COMMON_IPC__UNIX_WRITE 0x00000100UL | ||
50 | #define FILESYSTEM__MOUNT 0x00000001UL | ||
51 | #define FILESYSTEM__REMOUNT 0x00000002UL | ||
52 | #define FILESYSTEM__UNMOUNT 0x00000004UL | ||
53 | #define FILESYSTEM__GETATTR 0x00000008UL | ||
54 | #define FILESYSTEM__RELABELFROM 0x00000010UL | ||
55 | #define FILESYSTEM__RELABELTO 0x00000020UL | ||
56 | #define FILESYSTEM__TRANSITION 0x00000040UL | ||
57 | #define FILESYSTEM__ASSOCIATE 0x00000080UL | ||
58 | #define FILESYSTEM__QUOTAMOD 0x00000100UL | ||
59 | #define FILESYSTEM__QUOTAGET 0x00000200UL | ||
60 | #define DIR__IOCTL 0x00000001UL | ||
61 | #define DIR__READ 0x00000002UL | ||
62 | #define DIR__WRITE 0x00000004UL | ||
63 | #define DIR__CREATE 0x00000008UL | ||
64 | #define DIR__GETATTR 0x00000010UL | ||
65 | #define DIR__SETATTR 0x00000020UL | ||
66 | #define DIR__LOCK 0x00000040UL | ||
67 | #define DIR__RELABELFROM 0x00000080UL | ||
68 | #define DIR__RELABELTO 0x00000100UL | ||
69 | #define DIR__APPEND 0x00000200UL | ||
70 | #define DIR__UNLINK 0x00000400UL | ||
71 | #define DIR__LINK 0x00000800UL | ||
72 | #define DIR__RENAME 0x00001000UL | ||
73 | #define DIR__EXECUTE 0x00002000UL | ||
74 | #define DIR__SWAPON 0x00004000UL | ||
75 | #define DIR__QUOTAON 0x00008000UL | ||
76 | #define DIR__MOUNTON 0x00010000UL | ||
77 | #define DIR__ADD_NAME 0x00020000UL | ||
78 | #define DIR__REMOVE_NAME 0x00040000UL | ||
79 | #define DIR__REPARENT 0x00080000UL | ||
80 | #define DIR__SEARCH 0x00100000UL | ||
81 | #define DIR__RMDIR 0x00200000UL | ||
82 | #define DIR__OPEN 0x00400000UL | ||
83 | #define FILE__IOCTL 0x00000001UL | ||
84 | #define FILE__READ 0x00000002UL | ||
85 | #define FILE__WRITE 0x00000004UL | ||
86 | #define FILE__CREATE 0x00000008UL | ||
87 | #define FILE__GETATTR 0x00000010UL | ||
88 | #define FILE__SETATTR 0x00000020UL | ||
89 | #define FILE__LOCK 0x00000040UL | ||
90 | #define FILE__RELABELFROM 0x00000080UL | ||
91 | #define FILE__RELABELTO 0x00000100UL | ||
92 | #define FILE__APPEND 0x00000200UL | ||
93 | #define FILE__UNLINK 0x00000400UL | ||
94 | #define FILE__LINK 0x00000800UL | ||
95 | #define FILE__RENAME 0x00001000UL | ||
96 | #define FILE__EXECUTE 0x00002000UL | ||
97 | #define FILE__SWAPON 0x00004000UL | ||
98 | #define FILE__QUOTAON 0x00008000UL | ||
99 | #define FILE__MOUNTON 0x00010000UL | ||
100 | #define FILE__EXECUTE_NO_TRANS 0x00020000UL | ||
101 | #define FILE__ENTRYPOINT 0x00040000UL | ||
102 | #define FILE__EXECMOD 0x00080000UL | ||
103 | #define FILE__OPEN 0x00100000UL | ||
104 | #define LNK_FILE__IOCTL 0x00000001UL | ||
105 | #define LNK_FILE__READ 0x00000002UL | ||
106 | #define LNK_FILE__WRITE 0x00000004UL | ||
107 | #define LNK_FILE__CREATE 0x00000008UL | ||
108 | #define LNK_FILE__GETATTR 0x00000010UL | ||
109 | #define LNK_FILE__SETATTR 0x00000020UL | ||
110 | #define LNK_FILE__LOCK 0x00000040UL | ||
111 | #define LNK_FILE__RELABELFROM 0x00000080UL | ||
112 | #define LNK_FILE__RELABELTO 0x00000100UL | ||
113 | #define LNK_FILE__APPEND 0x00000200UL | ||
114 | #define LNK_FILE__UNLINK 0x00000400UL | ||
115 | #define LNK_FILE__LINK 0x00000800UL | ||
116 | #define LNK_FILE__RENAME 0x00001000UL | ||
117 | #define LNK_FILE__EXECUTE 0x00002000UL | ||
118 | #define LNK_FILE__SWAPON 0x00004000UL | ||
119 | #define LNK_FILE__QUOTAON 0x00008000UL | ||
120 | #define LNK_FILE__MOUNTON 0x00010000UL | ||
121 | #define CHR_FILE__IOCTL 0x00000001UL | ||
122 | #define CHR_FILE__READ 0x00000002UL | ||
123 | #define CHR_FILE__WRITE 0x00000004UL | ||
124 | #define CHR_FILE__CREATE 0x00000008UL | ||
125 | #define CHR_FILE__GETATTR 0x00000010UL | ||
126 | #define CHR_FILE__SETATTR 0x00000020UL | ||
127 | #define CHR_FILE__LOCK 0x00000040UL | ||
128 | #define CHR_FILE__RELABELFROM 0x00000080UL | ||
129 | #define CHR_FILE__RELABELTO 0x00000100UL | ||
130 | #define CHR_FILE__APPEND 0x00000200UL | ||
131 | #define CHR_FILE__UNLINK 0x00000400UL | ||
132 | #define CHR_FILE__LINK 0x00000800UL | ||
133 | #define CHR_FILE__RENAME 0x00001000UL | ||
134 | #define CHR_FILE__EXECUTE 0x00002000UL | ||
135 | #define CHR_FILE__SWAPON 0x00004000UL | ||
136 | #define CHR_FILE__QUOTAON 0x00008000UL | ||
137 | #define CHR_FILE__MOUNTON 0x00010000UL | ||
138 | #define CHR_FILE__EXECUTE_NO_TRANS 0x00020000UL | ||
139 | #define CHR_FILE__ENTRYPOINT 0x00040000UL | ||
140 | #define CHR_FILE__EXECMOD 0x00080000UL | ||
141 | #define CHR_FILE__OPEN 0x00100000UL | ||
142 | #define BLK_FILE__IOCTL 0x00000001UL | ||
143 | #define BLK_FILE__READ 0x00000002UL | ||
144 | #define BLK_FILE__WRITE 0x00000004UL | ||
145 | #define BLK_FILE__CREATE 0x00000008UL | ||
146 | #define BLK_FILE__GETATTR 0x00000010UL | ||
147 | #define BLK_FILE__SETATTR 0x00000020UL | ||
148 | #define BLK_FILE__LOCK 0x00000040UL | ||
149 | #define BLK_FILE__RELABELFROM 0x00000080UL | ||
150 | #define BLK_FILE__RELABELTO 0x00000100UL | ||
151 | #define BLK_FILE__APPEND 0x00000200UL | ||
152 | #define BLK_FILE__UNLINK 0x00000400UL | ||
153 | #define BLK_FILE__LINK 0x00000800UL | ||
154 | #define BLK_FILE__RENAME 0x00001000UL | ||
155 | #define BLK_FILE__EXECUTE 0x00002000UL | ||
156 | #define BLK_FILE__SWAPON 0x00004000UL | ||
157 | #define BLK_FILE__QUOTAON 0x00008000UL | ||
158 | #define BLK_FILE__MOUNTON 0x00010000UL | ||
159 | #define BLK_FILE__OPEN 0x00020000UL | ||
160 | #define SOCK_FILE__IOCTL 0x00000001UL | ||
161 | #define SOCK_FILE__READ 0x00000002UL | ||
162 | #define SOCK_FILE__WRITE 0x00000004UL | ||
163 | #define SOCK_FILE__CREATE 0x00000008UL | ||
164 | #define SOCK_FILE__GETATTR 0x00000010UL | ||
165 | #define SOCK_FILE__SETATTR 0x00000020UL | ||
166 | #define SOCK_FILE__LOCK 0x00000040UL | ||
167 | #define SOCK_FILE__RELABELFROM 0x00000080UL | ||
168 | #define SOCK_FILE__RELABELTO 0x00000100UL | ||
169 | #define SOCK_FILE__APPEND 0x00000200UL | ||
170 | #define SOCK_FILE__UNLINK 0x00000400UL | ||
171 | #define SOCK_FILE__LINK 0x00000800UL | ||
172 | #define SOCK_FILE__RENAME 0x00001000UL | ||
173 | #define SOCK_FILE__EXECUTE 0x00002000UL | ||
174 | #define SOCK_FILE__SWAPON 0x00004000UL | ||
175 | #define SOCK_FILE__QUOTAON 0x00008000UL | ||
176 | #define SOCK_FILE__MOUNTON 0x00010000UL | ||
177 | #define SOCK_FILE__OPEN 0x00020000UL | ||
178 | #define FIFO_FILE__IOCTL 0x00000001UL | ||
179 | #define FIFO_FILE__READ 0x00000002UL | ||
180 | #define FIFO_FILE__WRITE 0x00000004UL | ||
181 | #define FIFO_FILE__CREATE 0x00000008UL | ||
182 | #define FIFO_FILE__GETATTR 0x00000010UL | ||
183 | #define FIFO_FILE__SETATTR 0x00000020UL | ||
184 | #define FIFO_FILE__LOCK 0x00000040UL | ||
185 | #define FIFO_FILE__RELABELFROM 0x00000080UL | ||
186 | #define FIFO_FILE__RELABELTO 0x00000100UL | ||
187 | #define FIFO_FILE__APPEND 0x00000200UL | ||
188 | #define FIFO_FILE__UNLINK 0x00000400UL | ||
189 | #define FIFO_FILE__LINK 0x00000800UL | ||
190 | #define FIFO_FILE__RENAME 0x00001000UL | ||
191 | #define FIFO_FILE__EXECUTE 0x00002000UL | ||
192 | #define FIFO_FILE__SWAPON 0x00004000UL | ||
193 | #define FIFO_FILE__QUOTAON 0x00008000UL | ||
194 | #define FIFO_FILE__MOUNTON 0x00010000UL | ||
195 | #define FIFO_FILE__OPEN 0x00020000UL | ||
196 | #define FD__USE 0x00000001UL | ||
197 | #define SOCKET__IOCTL 0x00000001UL | ||
198 | #define SOCKET__READ 0x00000002UL | ||
199 | #define SOCKET__WRITE 0x00000004UL | ||
200 | #define SOCKET__CREATE 0x00000008UL | ||
201 | #define SOCKET__GETATTR 0x00000010UL | ||
202 | #define SOCKET__SETATTR 0x00000020UL | ||
203 | #define SOCKET__LOCK 0x00000040UL | ||
204 | #define SOCKET__RELABELFROM 0x00000080UL | ||
205 | #define SOCKET__RELABELTO 0x00000100UL | ||
206 | #define SOCKET__APPEND 0x00000200UL | ||
207 | #define SOCKET__BIND 0x00000400UL | ||
208 | #define SOCKET__CONNECT 0x00000800UL | ||
209 | #define SOCKET__LISTEN 0x00001000UL | ||
210 | #define SOCKET__ACCEPT 0x00002000UL | ||
211 | #define SOCKET__GETOPT 0x00004000UL | ||
212 | #define SOCKET__SETOPT 0x00008000UL | ||
213 | #define SOCKET__SHUTDOWN 0x00010000UL | ||
214 | #define SOCKET__RECVFROM 0x00020000UL | ||
215 | #define SOCKET__SENDTO 0x00040000UL | ||
216 | #define SOCKET__RECV_MSG 0x00080000UL | ||
217 | #define SOCKET__SEND_MSG 0x00100000UL | ||
218 | #define SOCKET__NAME_BIND 0x00200000UL | ||
219 | #define TCP_SOCKET__IOCTL 0x00000001UL | ||
220 | #define TCP_SOCKET__READ 0x00000002UL | ||
221 | #define TCP_SOCKET__WRITE 0x00000004UL | ||
222 | #define TCP_SOCKET__CREATE 0x00000008UL | ||
223 | #define TCP_SOCKET__GETATTR 0x00000010UL | ||
224 | #define TCP_SOCKET__SETATTR 0x00000020UL | ||
225 | #define TCP_SOCKET__LOCK 0x00000040UL | ||
226 | #define TCP_SOCKET__RELABELFROM 0x00000080UL | ||
227 | #define TCP_SOCKET__RELABELTO 0x00000100UL | ||
228 | #define TCP_SOCKET__APPEND 0x00000200UL | ||
229 | #define TCP_SOCKET__BIND 0x00000400UL | ||
230 | #define TCP_SOCKET__CONNECT 0x00000800UL | ||
231 | #define TCP_SOCKET__LISTEN 0x00001000UL | ||
232 | #define TCP_SOCKET__ACCEPT 0x00002000UL | ||
233 | #define TCP_SOCKET__GETOPT 0x00004000UL | ||
234 | #define TCP_SOCKET__SETOPT 0x00008000UL | ||
235 | #define TCP_SOCKET__SHUTDOWN 0x00010000UL | ||
236 | #define TCP_SOCKET__RECVFROM 0x00020000UL | ||
237 | #define TCP_SOCKET__SENDTO 0x00040000UL | ||
238 | #define TCP_SOCKET__RECV_MSG 0x00080000UL | ||
239 | #define TCP_SOCKET__SEND_MSG 0x00100000UL | ||
240 | #define TCP_SOCKET__NAME_BIND 0x00200000UL | ||
241 | #define TCP_SOCKET__CONNECTTO 0x00400000UL | ||
242 | #define TCP_SOCKET__NEWCONN 0x00800000UL | ||
243 | #define TCP_SOCKET__ACCEPTFROM 0x01000000UL | ||
244 | #define TCP_SOCKET__NODE_BIND 0x02000000UL | ||
245 | #define TCP_SOCKET__NAME_CONNECT 0x04000000UL | ||
246 | #define UDP_SOCKET__IOCTL 0x00000001UL | ||
247 | #define UDP_SOCKET__READ 0x00000002UL | ||
248 | #define UDP_SOCKET__WRITE 0x00000004UL | ||
249 | #define UDP_SOCKET__CREATE 0x00000008UL | ||
250 | #define UDP_SOCKET__GETATTR 0x00000010UL | ||
251 | #define UDP_SOCKET__SETATTR 0x00000020UL | ||
252 | #define UDP_SOCKET__LOCK 0x00000040UL | ||
253 | #define UDP_SOCKET__RELABELFROM 0x00000080UL | ||
254 | #define UDP_SOCKET__RELABELTO 0x00000100UL | ||
255 | #define UDP_SOCKET__APPEND 0x00000200UL | ||
256 | #define UDP_SOCKET__BIND 0x00000400UL | ||
257 | #define UDP_SOCKET__CONNECT 0x00000800UL | ||
258 | #define UDP_SOCKET__LISTEN 0x00001000UL | ||
259 | #define UDP_SOCKET__ACCEPT 0x00002000UL | ||
260 | #define UDP_SOCKET__GETOPT 0x00004000UL | ||
261 | #define UDP_SOCKET__SETOPT 0x00008000UL | ||
262 | #define UDP_SOCKET__SHUTDOWN 0x00010000UL | ||
263 | #define UDP_SOCKET__RECVFROM 0x00020000UL | ||
264 | #define UDP_SOCKET__SENDTO 0x00040000UL | ||
265 | #define UDP_SOCKET__RECV_MSG 0x00080000UL | ||
266 | #define UDP_SOCKET__SEND_MSG 0x00100000UL | ||
267 | #define UDP_SOCKET__NAME_BIND 0x00200000UL | ||
268 | #define UDP_SOCKET__NODE_BIND 0x00400000UL | ||
269 | #define RAWIP_SOCKET__IOCTL 0x00000001UL | ||
270 | #define RAWIP_SOCKET__READ 0x00000002UL | ||
271 | #define RAWIP_SOCKET__WRITE 0x00000004UL | ||
272 | #define RAWIP_SOCKET__CREATE 0x00000008UL | ||
273 | #define RAWIP_SOCKET__GETATTR 0x00000010UL | ||
274 | #define RAWIP_SOCKET__SETATTR 0x00000020UL | ||
275 | #define RAWIP_SOCKET__LOCK 0x00000040UL | ||
276 | #define RAWIP_SOCKET__RELABELFROM 0x00000080UL | ||
277 | #define RAWIP_SOCKET__RELABELTO 0x00000100UL | ||
278 | #define RAWIP_SOCKET__APPEND 0x00000200UL | ||
279 | #define RAWIP_SOCKET__BIND 0x00000400UL | ||
280 | #define RAWIP_SOCKET__CONNECT 0x00000800UL | ||
281 | #define RAWIP_SOCKET__LISTEN 0x00001000UL | ||
282 | #define RAWIP_SOCKET__ACCEPT 0x00002000UL | ||
283 | #define RAWIP_SOCKET__GETOPT 0x00004000UL | ||
284 | #define RAWIP_SOCKET__SETOPT 0x00008000UL | ||
285 | #define RAWIP_SOCKET__SHUTDOWN 0x00010000UL | ||
286 | #define RAWIP_SOCKET__RECVFROM 0x00020000UL | ||
287 | #define RAWIP_SOCKET__SENDTO 0x00040000UL | ||
288 | #define RAWIP_SOCKET__RECV_MSG 0x00080000UL | ||
289 | #define RAWIP_SOCKET__SEND_MSG 0x00100000UL | ||
290 | #define RAWIP_SOCKET__NAME_BIND 0x00200000UL | ||
291 | #define RAWIP_SOCKET__NODE_BIND 0x00400000UL | ||
292 | #define NODE__TCP_RECV 0x00000001UL | ||
293 | #define NODE__TCP_SEND 0x00000002UL | ||
294 | #define NODE__UDP_RECV 0x00000004UL | ||
295 | #define NODE__UDP_SEND 0x00000008UL | ||
296 | #define NODE__RAWIP_RECV 0x00000010UL | ||
297 | #define NODE__RAWIP_SEND 0x00000020UL | ||
298 | #define NODE__ENFORCE_DEST 0x00000040UL | ||
299 | #define NODE__DCCP_RECV 0x00000080UL | ||
300 | #define NODE__DCCP_SEND 0x00000100UL | ||
301 | #define NODE__RECVFROM 0x00000200UL | ||
302 | #define NODE__SENDTO 0x00000400UL | ||
303 | #define NETIF__TCP_RECV 0x00000001UL | ||
304 | #define NETIF__TCP_SEND 0x00000002UL | ||
305 | #define NETIF__UDP_RECV 0x00000004UL | ||
306 | #define NETIF__UDP_SEND 0x00000008UL | ||
307 | #define NETIF__RAWIP_RECV 0x00000010UL | ||
308 | #define NETIF__RAWIP_SEND 0x00000020UL | ||
309 | #define NETIF__DCCP_RECV 0x00000040UL | ||
310 | #define NETIF__DCCP_SEND 0x00000080UL | ||
311 | #define NETIF__INGRESS 0x00000100UL | ||
312 | #define NETIF__EGRESS 0x00000200UL | ||
313 | #define NETLINK_SOCKET__IOCTL 0x00000001UL | ||
314 | #define NETLINK_SOCKET__READ 0x00000002UL | ||
315 | #define NETLINK_SOCKET__WRITE 0x00000004UL | ||
316 | #define NETLINK_SOCKET__CREATE 0x00000008UL | ||
317 | #define NETLINK_SOCKET__GETATTR 0x00000010UL | ||
318 | #define NETLINK_SOCKET__SETATTR 0x00000020UL | ||
319 | #define NETLINK_SOCKET__LOCK 0x00000040UL | ||
320 | #define NETLINK_SOCKET__RELABELFROM 0x00000080UL | ||
321 | #define NETLINK_SOCKET__RELABELTO 0x00000100UL | ||
322 | #define NETLINK_SOCKET__APPEND 0x00000200UL | ||
323 | #define NETLINK_SOCKET__BIND 0x00000400UL | ||
324 | #define NETLINK_SOCKET__CONNECT 0x00000800UL | ||
325 | #define NETLINK_SOCKET__LISTEN 0x00001000UL | ||
326 | #define NETLINK_SOCKET__ACCEPT 0x00002000UL | ||
327 | #define NETLINK_SOCKET__GETOPT 0x00004000UL | ||
328 | #define NETLINK_SOCKET__SETOPT 0x00008000UL | ||
329 | #define NETLINK_SOCKET__SHUTDOWN 0x00010000UL | ||
330 | #define NETLINK_SOCKET__RECVFROM 0x00020000UL | ||
331 | #define NETLINK_SOCKET__SENDTO 0x00040000UL | ||
332 | #define NETLINK_SOCKET__RECV_MSG 0x00080000UL | ||
333 | #define NETLINK_SOCKET__SEND_MSG 0x00100000UL | ||
334 | #define NETLINK_SOCKET__NAME_BIND 0x00200000UL | ||
335 | #define PACKET_SOCKET__IOCTL 0x00000001UL | ||
336 | #define PACKET_SOCKET__READ 0x00000002UL | ||
337 | #define PACKET_SOCKET__WRITE 0x00000004UL | ||
338 | #define PACKET_SOCKET__CREATE 0x00000008UL | ||
339 | #define PACKET_SOCKET__GETATTR 0x00000010UL | ||
340 | #define PACKET_SOCKET__SETATTR 0x00000020UL | ||
341 | #define PACKET_SOCKET__LOCK 0x00000040UL | ||
342 | #define PACKET_SOCKET__RELABELFROM 0x00000080UL | ||
343 | #define PACKET_SOCKET__RELABELTO 0x00000100UL | ||
344 | #define PACKET_SOCKET__APPEND 0x00000200UL | ||
345 | #define PACKET_SOCKET__BIND 0x00000400UL | ||
346 | #define PACKET_SOCKET__CONNECT 0x00000800UL | ||
347 | #define PACKET_SOCKET__LISTEN 0x00001000UL | ||
348 | #define PACKET_SOCKET__ACCEPT 0x00002000UL | ||
349 | #define PACKET_SOCKET__GETOPT 0x00004000UL | ||
350 | #define PACKET_SOCKET__SETOPT 0x00008000UL | ||
351 | #define PACKET_SOCKET__SHUTDOWN 0x00010000UL | ||
352 | #define PACKET_SOCKET__RECVFROM 0x00020000UL | ||
353 | #define PACKET_SOCKET__SENDTO 0x00040000UL | ||
354 | #define PACKET_SOCKET__RECV_MSG 0x00080000UL | ||
355 | #define PACKET_SOCKET__SEND_MSG 0x00100000UL | ||
356 | #define PACKET_SOCKET__NAME_BIND 0x00200000UL | ||
357 | #define KEY_SOCKET__IOCTL 0x00000001UL | ||
358 | #define KEY_SOCKET__READ 0x00000002UL | ||
359 | #define KEY_SOCKET__WRITE 0x00000004UL | ||
360 | #define KEY_SOCKET__CREATE 0x00000008UL | ||
361 | #define KEY_SOCKET__GETATTR 0x00000010UL | ||
362 | #define KEY_SOCKET__SETATTR 0x00000020UL | ||
363 | #define KEY_SOCKET__LOCK 0x00000040UL | ||
364 | #define KEY_SOCKET__RELABELFROM 0x00000080UL | ||
365 | #define KEY_SOCKET__RELABELTO 0x00000100UL | ||
366 | #define KEY_SOCKET__APPEND 0x00000200UL | ||
367 | #define KEY_SOCKET__BIND 0x00000400UL | ||
368 | #define KEY_SOCKET__CONNECT 0x00000800UL | ||
369 | #define KEY_SOCKET__LISTEN 0x00001000UL | ||
370 | #define KEY_SOCKET__ACCEPT 0x00002000UL | ||
371 | #define KEY_SOCKET__GETOPT 0x00004000UL | ||
372 | #define KEY_SOCKET__SETOPT 0x00008000UL | ||
373 | #define KEY_SOCKET__SHUTDOWN 0x00010000UL | ||
374 | #define KEY_SOCKET__RECVFROM 0x00020000UL | ||
375 | #define KEY_SOCKET__SENDTO 0x00040000UL | ||
376 | #define KEY_SOCKET__RECV_MSG 0x00080000UL | ||
377 | #define KEY_SOCKET__SEND_MSG 0x00100000UL | ||
378 | #define KEY_SOCKET__NAME_BIND 0x00200000UL | ||
379 | #define UNIX_STREAM_SOCKET__IOCTL 0x00000001UL | ||
380 | #define UNIX_STREAM_SOCKET__READ 0x00000002UL | ||
381 | #define UNIX_STREAM_SOCKET__WRITE 0x00000004UL | ||
382 | #define UNIX_STREAM_SOCKET__CREATE 0x00000008UL | ||
383 | #define UNIX_STREAM_SOCKET__GETATTR 0x00000010UL | ||
384 | #define UNIX_STREAM_SOCKET__SETATTR 0x00000020UL | ||
385 | #define UNIX_STREAM_SOCKET__LOCK 0x00000040UL | ||
386 | #define UNIX_STREAM_SOCKET__RELABELFROM 0x00000080UL | ||
387 | #define UNIX_STREAM_SOCKET__RELABELTO 0x00000100UL | ||
388 | #define UNIX_STREAM_SOCKET__APPEND 0x00000200UL | ||
389 | #define UNIX_STREAM_SOCKET__BIND 0x00000400UL | ||
390 | #define UNIX_STREAM_SOCKET__CONNECT 0x00000800UL | ||
391 | #define UNIX_STREAM_SOCKET__LISTEN 0x00001000UL | ||
392 | #define UNIX_STREAM_SOCKET__ACCEPT 0x00002000UL | ||
393 | #define UNIX_STREAM_SOCKET__GETOPT 0x00004000UL | ||
394 | #define UNIX_STREAM_SOCKET__SETOPT 0x00008000UL | ||
395 | #define UNIX_STREAM_SOCKET__SHUTDOWN 0x00010000UL | ||
396 | #define UNIX_STREAM_SOCKET__RECVFROM 0x00020000UL | ||
397 | #define UNIX_STREAM_SOCKET__SENDTO 0x00040000UL | ||
398 | #define UNIX_STREAM_SOCKET__RECV_MSG 0x00080000UL | ||
399 | #define UNIX_STREAM_SOCKET__SEND_MSG 0x00100000UL | ||
400 | #define UNIX_STREAM_SOCKET__NAME_BIND 0x00200000UL | ||
401 | #define UNIX_STREAM_SOCKET__CONNECTTO 0x00400000UL | ||
402 | #define UNIX_STREAM_SOCKET__NEWCONN 0x00800000UL | ||
403 | #define UNIX_STREAM_SOCKET__ACCEPTFROM 0x01000000UL | ||
404 | #define UNIX_DGRAM_SOCKET__IOCTL 0x00000001UL | ||
405 | #define UNIX_DGRAM_SOCKET__READ 0x00000002UL | ||
406 | #define UNIX_DGRAM_SOCKET__WRITE 0x00000004UL | ||
407 | #define UNIX_DGRAM_SOCKET__CREATE 0x00000008UL | ||
408 | #define UNIX_DGRAM_SOCKET__GETATTR 0x00000010UL | ||
409 | #define UNIX_DGRAM_SOCKET__SETATTR 0x00000020UL | ||
410 | #define UNIX_DGRAM_SOCKET__LOCK 0x00000040UL | ||
411 | #define UNIX_DGRAM_SOCKET__RELABELFROM 0x00000080UL | ||
412 | #define UNIX_DGRAM_SOCKET__RELABELTO 0x00000100UL | ||
413 | #define UNIX_DGRAM_SOCKET__APPEND 0x00000200UL | ||
414 | #define UNIX_DGRAM_SOCKET__BIND 0x00000400UL | ||
415 | #define UNIX_DGRAM_SOCKET__CONNECT 0x00000800UL | ||
416 | #define UNIX_DGRAM_SOCKET__LISTEN 0x00001000UL | ||
417 | #define UNIX_DGRAM_SOCKET__ACCEPT 0x00002000UL | ||
418 | #define UNIX_DGRAM_SOCKET__GETOPT 0x00004000UL | ||
419 | #define UNIX_DGRAM_SOCKET__SETOPT 0x00008000UL | ||
420 | #define UNIX_DGRAM_SOCKET__SHUTDOWN 0x00010000UL | ||
421 | #define UNIX_DGRAM_SOCKET__RECVFROM 0x00020000UL | ||
422 | #define UNIX_DGRAM_SOCKET__SENDTO 0x00040000UL | ||
423 | #define UNIX_DGRAM_SOCKET__RECV_MSG 0x00080000UL | ||
424 | #define UNIX_DGRAM_SOCKET__SEND_MSG 0x00100000UL | ||
425 | #define UNIX_DGRAM_SOCKET__NAME_BIND 0x00200000UL | ||
426 | #define TUN_SOCKET__IOCTL 0x00000001UL | ||
427 | #define TUN_SOCKET__READ 0x00000002UL | ||
428 | #define TUN_SOCKET__WRITE 0x00000004UL | ||
429 | #define TUN_SOCKET__CREATE 0x00000008UL | ||
430 | #define TUN_SOCKET__GETATTR 0x00000010UL | ||
431 | #define TUN_SOCKET__SETATTR 0x00000020UL | ||
432 | #define TUN_SOCKET__LOCK 0x00000040UL | ||
433 | #define TUN_SOCKET__RELABELFROM 0x00000080UL | ||
434 | #define TUN_SOCKET__RELABELTO 0x00000100UL | ||
435 | #define TUN_SOCKET__APPEND 0x00000200UL | ||
436 | #define TUN_SOCKET__BIND 0x00000400UL | ||
437 | #define TUN_SOCKET__CONNECT 0x00000800UL | ||
438 | #define TUN_SOCKET__LISTEN 0x00001000UL | ||
439 | #define TUN_SOCKET__ACCEPT 0x00002000UL | ||
440 | #define TUN_SOCKET__GETOPT 0x00004000UL | ||
441 | #define TUN_SOCKET__SETOPT 0x00008000UL | ||
442 | #define TUN_SOCKET__SHUTDOWN 0x00010000UL | ||
443 | #define TUN_SOCKET__RECVFROM 0x00020000UL | ||
444 | #define TUN_SOCKET__SENDTO 0x00040000UL | ||
445 | #define TUN_SOCKET__RECV_MSG 0x00080000UL | ||
446 | #define TUN_SOCKET__SEND_MSG 0x00100000UL | ||
447 | #define TUN_SOCKET__NAME_BIND 0x00200000UL | ||
448 | #define PROCESS__FORK 0x00000001UL | ||
449 | #define PROCESS__TRANSITION 0x00000002UL | ||
450 | #define PROCESS__SIGCHLD 0x00000004UL | ||
451 | #define PROCESS__SIGKILL 0x00000008UL | ||
452 | #define PROCESS__SIGSTOP 0x00000010UL | ||
453 | #define PROCESS__SIGNULL 0x00000020UL | ||
454 | #define PROCESS__SIGNAL 0x00000040UL | ||
455 | #define PROCESS__PTRACE 0x00000080UL | ||
456 | #define PROCESS__GETSCHED 0x00000100UL | ||
457 | #define PROCESS__SETSCHED 0x00000200UL | ||
458 | #define PROCESS__GETSESSION 0x00000400UL | ||
459 | #define PROCESS__GETPGID 0x00000800UL | ||
460 | #define PROCESS__SETPGID 0x00001000UL | ||
461 | #define PROCESS__GETCAP 0x00002000UL | ||
462 | #define PROCESS__SETCAP 0x00004000UL | ||
463 | #define PROCESS__SHARE 0x00008000UL | ||
464 | #define PROCESS__GETATTR 0x00010000UL | ||
465 | #define PROCESS__SETEXEC 0x00020000UL | ||
466 | #define PROCESS__SETFSCREATE 0x00040000UL | ||
467 | #define PROCESS__NOATSECURE 0x00080000UL | ||
468 | #define PROCESS__SIGINH 0x00100000UL | ||
469 | #define PROCESS__SETRLIMIT 0x00200000UL | ||
470 | #define PROCESS__RLIMITINH 0x00400000UL | ||
471 | #define PROCESS__DYNTRANSITION 0x00800000UL | ||
472 | #define PROCESS__SETCURRENT 0x01000000UL | ||
473 | #define PROCESS__EXECMEM 0x02000000UL | ||
474 | #define PROCESS__EXECSTACK 0x04000000UL | ||
475 | #define PROCESS__EXECHEAP 0x08000000UL | ||
476 | #define PROCESS__SETKEYCREATE 0x10000000UL | ||
477 | #define PROCESS__SETSOCKCREATE 0x20000000UL | ||
478 | #define IPC__CREATE 0x00000001UL | ||
479 | #define IPC__DESTROY 0x00000002UL | ||
480 | #define IPC__GETATTR 0x00000004UL | ||
481 | #define IPC__SETATTR 0x00000008UL | ||
482 | #define IPC__READ 0x00000010UL | ||
483 | #define IPC__WRITE 0x00000020UL | ||
484 | #define IPC__ASSOCIATE 0x00000040UL | ||
485 | #define IPC__UNIX_READ 0x00000080UL | ||
486 | #define IPC__UNIX_WRITE 0x00000100UL | ||
487 | #define SEM__CREATE 0x00000001UL | ||
488 | #define SEM__DESTROY 0x00000002UL | ||
489 | #define SEM__GETATTR 0x00000004UL | ||
490 | #define SEM__SETATTR 0x00000008UL | ||
491 | #define SEM__READ 0x00000010UL | ||
492 | #define SEM__WRITE 0x00000020UL | ||
493 | #define SEM__ASSOCIATE 0x00000040UL | ||
494 | #define SEM__UNIX_READ 0x00000080UL | ||
495 | #define SEM__UNIX_WRITE 0x00000100UL | ||
496 | #define MSGQ__CREATE 0x00000001UL | ||
497 | #define MSGQ__DESTROY 0x00000002UL | ||
498 | #define MSGQ__GETATTR 0x00000004UL | ||
499 | #define MSGQ__SETATTR 0x00000008UL | ||
500 | #define MSGQ__READ 0x00000010UL | ||
501 | #define MSGQ__WRITE 0x00000020UL | ||
502 | #define MSGQ__ASSOCIATE 0x00000040UL | ||
503 | #define MSGQ__UNIX_READ 0x00000080UL | ||
504 | #define MSGQ__UNIX_WRITE 0x00000100UL | ||
505 | #define MSGQ__ENQUEUE 0x00000200UL | ||
506 | #define MSG__SEND 0x00000001UL | ||
507 | #define MSG__RECEIVE 0x00000002UL | ||
508 | #define SHM__CREATE 0x00000001UL | ||
509 | #define SHM__DESTROY 0x00000002UL | ||
510 | #define SHM__GETATTR 0x00000004UL | ||
511 | #define SHM__SETATTR 0x00000008UL | ||
512 | #define SHM__READ 0x00000010UL | ||
513 | #define SHM__WRITE 0x00000020UL | ||
514 | #define SHM__ASSOCIATE 0x00000040UL | ||
515 | #define SHM__UNIX_READ 0x00000080UL | ||
516 | #define SHM__UNIX_WRITE 0x00000100UL | ||
517 | #define SHM__LOCK 0x00000200UL | ||
518 | #define SECURITY__COMPUTE_AV 0x00000001UL | ||
519 | #define SECURITY__COMPUTE_CREATE 0x00000002UL | ||
520 | #define SECURITY__COMPUTE_MEMBER 0x00000004UL | ||
521 | #define SECURITY__CHECK_CONTEXT 0x00000008UL | ||
522 | #define SECURITY__LOAD_POLICY 0x00000010UL | ||
523 | #define SECURITY__COMPUTE_RELABEL 0x00000020UL | ||
524 | #define SECURITY__COMPUTE_USER 0x00000040UL | ||
525 | #define SECURITY__SETENFORCE 0x00000080UL | ||
526 | #define SECURITY__SETBOOL 0x00000100UL | ||
527 | #define SECURITY__SETSECPARAM 0x00000200UL | ||
528 | #define SECURITY__SETCHECKREQPROT 0x00000400UL | ||
529 | #define SYSTEM__IPC_INFO 0x00000001UL | ||
530 | #define SYSTEM__SYSLOG_READ 0x00000002UL | ||
531 | #define SYSTEM__SYSLOG_MOD 0x00000004UL | ||
532 | #define SYSTEM__SYSLOG_CONSOLE 0x00000008UL | ||
533 | #define SYSTEM__MODULE_REQUEST 0x00000010UL | ||
534 | #define CAPABILITY__CHOWN 0x00000001UL | ||
535 | #define CAPABILITY__DAC_OVERRIDE 0x00000002UL | ||
536 | #define CAPABILITY__DAC_READ_SEARCH 0x00000004UL | ||
537 | #define CAPABILITY__FOWNER 0x00000008UL | ||
538 | #define CAPABILITY__FSETID 0x00000010UL | ||
539 | #define CAPABILITY__KILL 0x00000020UL | ||
540 | #define CAPABILITY__SETGID 0x00000040UL | ||
541 | #define CAPABILITY__SETUID 0x00000080UL | ||
542 | #define CAPABILITY__SETPCAP 0x00000100UL | ||
543 | #define CAPABILITY__LINUX_IMMUTABLE 0x00000200UL | ||
544 | #define CAPABILITY__NET_BIND_SERVICE 0x00000400UL | ||
545 | #define CAPABILITY__NET_BROADCAST 0x00000800UL | ||
546 | #define CAPABILITY__NET_ADMIN 0x00001000UL | ||
547 | #define CAPABILITY__NET_RAW 0x00002000UL | ||
548 | #define CAPABILITY__IPC_LOCK 0x00004000UL | ||
549 | #define CAPABILITY__IPC_OWNER 0x00008000UL | ||
550 | #define CAPABILITY__SYS_MODULE 0x00010000UL | ||
551 | #define CAPABILITY__SYS_RAWIO 0x00020000UL | ||
552 | #define CAPABILITY__SYS_CHROOT 0x00040000UL | ||
553 | #define CAPABILITY__SYS_PTRACE 0x00080000UL | ||
554 | #define CAPABILITY__SYS_PACCT 0x00100000UL | ||
555 | #define CAPABILITY__SYS_ADMIN 0x00200000UL | ||
556 | #define CAPABILITY__SYS_BOOT 0x00400000UL | ||
557 | #define CAPABILITY__SYS_NICE 0x00800000UL | ||
558 | #define CAPABILITY__SYS_RESOURCE 0x01000000UL | ||
559 | #define CAPABILITY__SYS_TIME 0x02000000UL | ||
560 | #define CAPABILITY__SYS_TTY_CONFIG 0x04000000UL | ||
561 | #define CAPABILITY__MKNOD 0x08000000UL | ||
562 | #define CAPABILITY__LEASE 0x10000000UL | ||
563 | #define CAPABILITY__AUDIT_WRITE 0x20000000UL | ||
564 | #define CAPABILITY__AUDIT_CONTROL 0x40000000UL | ||
565 | #define CAPABILITY__SETFCAP 0x80000000UL | ||
566 | #define CAPABILITY2__MAC_OVERRIDE 0x00000001UL | ||
567 | #define CAPABILITY2__MAC_ADMIN 0x00000002UL | ||
568 | #define NETLINK_ROUTE_SOCKET__IOCTL 0x00000001UL | ||
569 | #define NETLINK_ROUTE_SOCKET__READ 0x00000002UL | ||
570 | #define NETLINK_ROUTE_SOCKET__WRITE 0x00000004UL | ||
571 | #define NETLINK_ROUTE_SOCKET__CREATE 0x00000008UL | ||
572 | #define NETLINK_ROUTE_SOCKET__GETATTR 0x00000010UL | ||
573 | #define NETLINK_ROUTE_SOCKET__SETATTR 0x00000020UL | ||
574 | #define NETLINK_ROUTE_SOCKET__LOCK 0x00000040UL | ||
575 | #define NETLINK_ROUTE_SOCKET__RELABELFROM 0x00000080UL | ||
576 | #define NETLINK_ROUTE_SOCKET__RELABELTO 0x00000100UL | ||
577 | #define NETLINK_ROUTE_SOCKET__APPEND 0x00000200UL | ||
578 | #define NETLINK_ROUTE_SOCKET__BIND 0x00000400UL | ||
579 | #define NETLINK_ROUTE_SOCKET__CONNECT 0x00000800UL | ||
580 | #define NETLINK_ROUTE_SOCKET__LISTEN 0x00001000UL | ||
581 | #define NETLINK_ROUTE_SOCKET__ACCEPT 0x00002000UL | ||
582 | #define NETLINK_ROUTE_SOCKET__GETOPT 0x00004000UL | ||
583 | #define NETLINK_ROUTE_SOCKET__SETOPT 0x00008000UL | ||
584 | #define NETLINK_ROUTE_SOCKET__SHUTDOWN 0x00010000UL | ||
585 | #define NETLINK_ROUTE_SOCKET__RECVFROM 0x00020000UL | ||
586 | #define NETLINK_ROUTE_SOCKET__SENDTO 0x00040000UL | ||
587 | #define NETLINK_ROUTE_SOCKET__RECV_MSG 0x00080000UL | ||
588 | #define NETLINK_ROUTE_SOCKET__SEND_MSG 0x00100000UL | ||
589 | #define NETLINK_ROUTE_SOCKET__NAME_BIND 0x00200000UL | ||
590 | #define NETLINK_ROUTE_SOCKET__NLMSG_READ 0x00400000UL | ||
591 | #define NETLINK_ROUTE_SOCKET__NLMSG_WRITE 0x00800000UL | ||
592 | #define NETLINK_FIREWALL_SOCKET__IOCTL 0x00000001UL | ||
593 | #define NETLINK_FIREWALL_SOCKET__READ 0x00000002UL | ||
594 | #define NETLINK_FIREWALL_SOCKET__WRITE 0x00000004UL | ||
595 | #define NETLINK_FIREWALL_SOCKET__CREATE 0x00000008UL | ||
596 | #define NETLINK_FIREWALL_SOCKET__GETATTR 0x00000010UL | ||
597 | #define NETLINK_FIREWALL_SOCKET__SETATTR 0x00000020UL | ||
598 | #define NETLINK_FIREWALL_SOCKET__LOCK 0x00000040UL | ||
599 | #define NETLINK_FIREWALL_SOCKET__RELABELFROM 0x00000080UL | ||
600 | #define NETLINK_FIREWALL_SOCKET__RELABELTO 0x00000100UL | ||
601 | #define NETLINK_FIREWALL_SOCKET__APPEND 0x00000200UL | ||
602 | #define NETLINK_FIREWALL_SOCKET__BIND 0x00000400UL | ||
603 | #define NETLINK_FIREWALL_SOCKET__CONNECT 0x00000800UL | ||
604 | #define NETLINK_FIREWALL_SOCKET__LISTEN 0x00001000UL | ||
605 | #define NETLINK_FIREWALL_SOCKET__ACCEPT 0x00002000UL | ||
606 | #define NETLINK_FIREWALL_SOCKET__GETOPT 0x00004000UL | ||
607 | #define NETLINK_FIREWALL_SOCKET__SETOPT 0x00008000UL | ||
608 | #define NETLINK_FIREWALL_SOCKET__SHUTDOWN 0x00010000UL | ||
609 | #define NETLINK_FIREWALL_SOCKET__RECVFROM 0x00020000UL | ||
610 | #define NETLINK_FIREWALL_SOCKET__SENDTO 0x00040000UL | ||
611 | #define NETLINK_FIREWALL_SOCKET__RECV_MSG 0x00080000UL | ||
612 | #define NETLINK_FIREWALL_SOCKET__SEND_MSG 0x00100000UL | ||
613 | #define NETLINK_FIREWALL_SOCKET__NAME_BIND 0x00200000UL | ||
614 | #define NETLINK_FIREWALL_SOCKET__NLMSG_READ 0x00400000UL | ||
615 | #define NETLINK_FIREWALL_SOCKET__NLMSG_WRITE 0x00800000UL | ||
616 | #define NETLINK_TCPDIAG_SOCKET__IOCTL 0x00000001UL | ||
617 | #define NETLINK_TCPDIAG_SOCKET__READ 0x00000002UL | ||
618 | #define NETLINK_TCPDIAG_SOCKET__WRITE 0x00000004UL | ||
619 | #define NETLINK_TCPDIAG_SOCKET__CREATE 0x00000008UL | ||
620 | #define NETLINK_TCPDIAG_SOCKET__GETATTR 0x00000010UL | ||
621 | #define NETLINK_TCPDIAG_SOCKET__SETATTR 0x00000020UL | ||
622 | #define NETLINK_TCPDIAG_SOCKET__LOCK 0x00000040UL | ||
623 | #define NETLINK_TCPDIAG_SOCKET__RELABELFROM 0x00000080UL | ||
624 | #define NETLINK_TCPDIAG_SOCKET__RELABELTO 0x00000100UL | ||
625 | #define NETLINK_TCPDIAG_SOCKET__APPEND 0x00000200UL | ||
626 | #define NETLINK_TCPDIAG_SOCKET__BIND 0x00000400UL | ||
627 | #define NETLINK_TCPDIAG_SOCKET__CONNECT 0x00000800UL | ||
628 | #define NETLINK_TCPDIAG_SOCKET__LISTEN 0x00001000UL | ||
629 | #define NETLINK_TCPDIAG_SOCKET__ACCEPT 0x00002000UL | ||
630 | #define NETLINK_TCPDIAG_SOCKET__GETOPT 0x00004000UL | ||
631 | #define NETLINK_TCPDIAG_SOCKET__SETOPT 0x00008000UL | ||
632 | #define NETLINK_TCPDIAG_SOCKET__SHUTDOWN 0x00010000UL | ||
633 | #define NETLINK_TCPDIAG_SOCKET__RECVFROM 0x00020000UL | ||
634 | #define NETLINK_TCPDIAG_SOCKET__SENDTO 0x00040000UL | ||
635 | #define NETLINK_TCPDIAG_SOCKET__RECV_MSG 0x00080000UL | ||
636 | #define NETLINK_TCPDIAG_SOCKET__SEND_MSG 0x00100000UL | ||
637 | #define NETLINK_TCPDIAG_SOCKET__NAME_BIND 0x00200000UL | ||
638 | #define NETLINK_TCPDIAG_SOCKET__NLMSG_READ 0x00400000UL | ||
639 | #define NETLINK_TCPDIAG_SOCKET__NLMSG_WRITE 0x00800000UL | ||
640 | #define NETLINK_NFLOG_SOCKET__IOCTL 0x00000001UL | ||
641 | #define NETLINK_NFLOG_SOCKET__READ 0x00000002UL | ||
642 | #define NETLINK_NFLOG_SOCKET__WRITE 0x00000004UL | ||
643 | #define NETLINK_NFLOG_SOCKET__CREATE 0x00000008UL | ||
644 | #define NETLINK_NFLOG_SOCKET__GETATTR 0x00000010UL | ||
645 | #define NETLINK_NFLOG_SOCKET__SETATTR 0x00000020UL | ||
646 | #define NETLINK_NFLOG_SOCKET__LOCK 0x00000040UL | ||
647 | #define NETLINK_NFLOG_SOCKET__RELABELFROM 0x00000080UL | ||
648 | #define NETLINK_NFLOG_SOCKET__RELABELTO 0x00000100UL | ||
649 | #define NETLINK_NFLOG_SOCKET__APPEND 0x00000200UL | ||
650 | #define NETLINK_NFLOG_SOCKET__BIND 0x00000400UL | ||
651 | #define NETLINK_NFLOG_SOCKET__CONNECT 0x00000800UL | ||
652 | #define NETLINK_NFLOG_SOCKET__LISTEN 0x00001000UL | ||
653 | #define NETLINK_NFLOG_SOCKET__ACCEPT 0x00002000UL | ||
654 | #define NETLINK_NFLOG_SOCKET__GETOPT 0x00004000UL | ||
655 | #define NETLINK_NFLOG_SOCKET__SETOPT 0x00008000UL | ||
656 | #define NETLINK_NFLOG_SOCKET__SHUTDOWN 0x00010000UL | ||
657 | #define NETLINK_NFLOG_SOCKET__RECVFROM 0x00020000UL | ||
658 | #define NETLINK_NFLOG_SOCKET__SENDTO 0x00040000UL | ||
659 | #define NETLINK_NFLOG_SOCKET__RECV_MSG 0x00080000UL | ||
660 | #define NETLINK_NFLOG_SOCKET__SEND_MSG 0x00100000UL | ||
661 | #define NETLINK_NFLOG_SOCKET__NAME_BIND 0x00200000UL | ||
662 | #define NETLINK_XFRM_SOCKET__IOCTL 0x00000001UL | ||
663 | #define NETLINK_XFRM_SOCKET__READ 0x00000002UL | ||
664 | #define NETLINK_XFRM_SOCKET__WRITE 0x00000004UL | ||
665 | #define NETLINK_XFRM_SOCKET__CREATE 0x00000008UL | ||
666 | #define NETLINK_XFRM_SOCKET__GETATTR 0x00000010UL | ||
667 | #define NETLINK_XFRM_SOCKET__SETATTR 0x00000020UL | ||
668 | #define NETLINK_XFRM_SOCKET__LOCK 0x00000040UL | ||
669 | #define NETLINK_XFRM_SOCKET__RELABELFROM 0x00000080UL | ||
670 | #define NETLINK_XFRM_SOCKET__RELABELTO 0x00000100UL | ||
671 | #define NETLINK_XFRM_SOCKET__APPEND 0x00000200UL | ||
672 | #define NETLINK_XFRM_SOCKET__BIND 0x00000400UL | ||
673 | #define NETLINK_XFRM_SOCKET__CONNECT 0x00000800UL | ||
674 | #define NETLINK_XFRM_SOCKET__LISTEN 0x00001000UL | ||
675 | #define NETLINK_XFRM_SOCKET__ACCEPT 0x00002000UL | ||
676 | #define NETLINK_XFRM_SOCKET__GETOPT 0x00004000UL | ||
677 | #define NETLINK_XFRM_SOCKET__SETOPT 0x00008000UL | ||
678 | #define NETLINK_XFRM_SOCKET__SHUTDOWN 0x00010000UL | ||
679 | #define NETLINK_XFRM_SOCKET__RECVFROM 0x00020000UL | ||
680 | #define NETLINK_XFRM_SOCKET__SENDTO 0x00040000UL | ||
681 | #define NETLINK_XFRM_SOCKET__RECV_MSG 0x00080000UL | ||
682 | #define NETLINK_XFRM_SOCKET__SEND_MSG 0x00100000UL | ||
683 | #define NETLINK_XFRM_SOCKET__NAME_BIND 0x00200000UL | ||
684 | #define NETLINK_XFRM_SOCKET__NLMSG_READ 0x00400000UL | ||
685 | #define NETLINK_XFRM_SOCKET__NLMSG_WRITE 0x00800000UL | ||
686 | #define NETLINK_SELINUX_SOCKET__IOCTL 0x00000001UL | ||
687 | #define NETLINK_SELINUX_SOCKET__READ 0x00000002UL | ||
688 | #define NETLINK_SELINUX_SOCKET__WRITE 0x00000004UL | ||
689 | #define NETLINK_SELINUX_SOCKET__CREATE 0x00000008UL | ||
690 | #define NETLINK_SELINUX_SOCKET__GETATTR 0x00000010UL | ||
691 | #define NETLINK_SELINUX_SOCKET__SETATTR 0x00000020UL | ||
692 | #define NETLINK_SELINUX_SOCKET__LOCK 0x00000040UL | ||
693 | #define NETLINK_SELINUX_SOCKET__RELABELFROM 0x00000080UL | ||
694 | #define NETLINK_SELINUX_SOCKET__RELABELTO 0x00000100UL | ||
695 | #define NETLINK_SELINUX_SOCKET__APPEND 0x00000200UL | ||
696 | #define NETLINK_SELINUX_SOCKET__BIND 0x00000400UL | ||
697 | #define NETLINK_SELINUX_SOCKET__CONNECT 0x00000800UL | ||
698 | #define NETLINK_SELINUX_SOCKET__LISTEN 0x00001000UL | ||
699 | #define NETLINK_SELINUX_SOCKET__ACCEPT 0x00002000UL | ||
700 | #define NETLINK_SELINUX_SOCKET__GETOPT 0x00004000UL | ||
701 | #define NETLINK_SELINUX_SOCKET__SETOPT 0x00008000UL | ||
702 | #define NETLINK_SELINUX_SOCKET__SHUTDOWN 0x00010000UL | ||
703 | #define NETLINK_SELINUX_SOCKET__RECVFROM 0x00020000UL | ||
704 | #define NETLINK_SELINUX_SOCKET__SENDTO 0x00040000UL | ||
705 | #define NETLINK_SELINUX_SOCKET__RECV_MSG 0x00080000UL | ||
706 | #define NETLINK_SELINUX_SOCKET__SEND_MSG 0x00100000UL | ||
707 | #define NETLINK_SELINUX_SOCKET__NAME_BIND 0x00200000UL | ||
708 | #define NETLINK_AUDIT_SOCKET__IOCTL 0x00000001UL | ||
709 | #define NETLINK_AUDIT_SOCKET__READ 0x00000002UL | ||
710 | #define NETLINK_AUDIT_SOCKET__WRITE 0x00000004UL | ||
711 | #define NETLINK_AUDIT_SOCKET__CREATE 0x00000008UL | ||
712 | #define NETLINK_AUDIT_SOCKET__GETATTR 0x00000010UL | ||
713 | #define NETLINK_AUDIT_SOCKET__SETATTR 0x00000020UL | ||
714 | #define NETLINK_AUDIT_SOCKET__LOCK 0x00000040UL | ||
715 | #define NETLINK_AUDIT_SOCKET__RELABELFROM 0x00000080UL | ||
716 | #define NETLINK_AUDIT_SOCKET__RELABELTO 0x00000100UL | ||
717 | #define NETLINK_AUDIT_SOCKET__APPEND 0x00000200UL | ||
718 | #define NETLINK_AUDIT_SOCKET__BIND 0x00000400UL | ||
719 | #define NETLINK_AUDIT_SOCKET__CONNECT 0x00000800UL | ||
720 | #define NETLINK_AUDIT_SOCKET__LISTEN 0x00001000UL | ||
721 | #define NETLINK_AUDIT_SOCKET__ACCEPT 0x00002000UL | ||
722 | #define NETLINK_AUDIT_SOCKET__GETOPT 0x00004000UL | ||
723 | #define NETLINK_AUDIT_SOCKET__SETOPT 0x00008000UL | ||
724 | #define NETLINK_AUDIT_SOCKET__SHUTDOWN 0x00010000UL | ||
725 | #define NETLINK_AUDIT_SOCKET__RECVFROM 0x00020000UL | ||
726 | #define NETLINK_AUDIT_SOCKET__SENDTO 0x00040000UL | ||
727 | #define NETLINK_AUDIT_SOCKET__RECV_MSG 0x00080000UL | ||
728 | #define NETLINK_AUDIT_SOCKET__SEND_MSG 0x00100000UL | ||
729 | #define NETLINK_AUDIT_SOCKET__NAME_BIND 0x00200000UL | ||
730 | #define NETLINK_AUDIT_SOCKET__NLMSG_READ 0x00400000UL | ||
731 | #define NETLINK_AUDIT_SOCKET__NLMSG_WRITE 0x00800000UL | ||
732 | #define NETLINK_AUDIT_SOCKET__NLMSG_RELAY 0x01000000UL | ||
733 | #define NETLINK_AUDIT_SOCKET__NLMSG_READPRIV 0x02000000UL | ||
734 | #define NETLINK_AUDIT_SOCKET__NLMSG_TTY_AUDIT 0x04000000UL | ||
735 | #define NETLINK_IP6FW_SOCKET__IOCTL 0x00000001UL | ||
736 | #define NETLINK_IP6FW_SOCKET__READ 0x00000002UL | ||
737 | #define NETLINK_IP6FW_SOCKET__WRITE 0x00000004UL | ||
738 | #define NETLINK_IP6FW_SOCKET__CREATE 0x00000008UL | ||
739 | #define NETLINK_IP6FW_SOCKET__GETATTR 0x00000010UL | ||
740 | #define NETLINK_IP6FW_SOCKET__SETATTR 0x00000020UL | ||
741 | #define NETLINK_IP6FW_SOCKET__LOCK 0x00000040UL | ||
742 | #define NETLINK_IP6FW_SOCKET__RELABELFROM 0x00000080UL | ||
743 | #define NETLINK_IP6FW_SOCKET__RELABELTO 0x00000100UL | ||
744 | #define NETLINK_IP6FW_SOCKET__APPEND 0x00000200UL | ||
745 | #define NETLINK_IP6FW_SOCKET__BIND 0x00000400UL | ||
746 | #define NETLINK_IP6FW_SOCKET__CONNECT 0x00000800UL | ||
747 | #define NETLINK_IP6FW_SOCKET__LISTEN 0x00001000UL | ||
748 | #define NETLINK_IP6FW_SOCKET__ACCEPT 0x00002000UL | ||
749 | #define NETLINK_IP6FW_SOCKET__GETOPT 0x00004000UL | ||
750 | #define NETLINK_IP6FW_SOCKET__SETOPT 0x00008000UL | ||
751 | #define NETLINK_IP6FW_SOCKET__SHUTDOWN 0x00010000UL | ||
752 | #define NETLINK_IP6FW_SOCKET__RECVFROM 0x00020000UL | ||
753 | #define NETLINK_IP6FW_SOCKET__SENDTO 0x00040000UL | ||
754 | #define NETLINK_IP6FW_SOCKET__RECV_MSG 0x00080000UL | ||
755 | #define NETLINK_IP6FW_SOCKET__SEND_MSG 0x00100000UL | ||
756 | #define NETLINK_IP6FW_SOCKET__NAME_BIND 0x00200000UL | ||
757 | #define NETLINK_IP6FW_SOCKET__NLMSG_READ 0x00400000UL | ||
758 | #define NETLINK_IP6FW_SOCKET__NLMSG_WRITE 0x00800000UL | ||
759 | #define NETLINK_DNRT_SOCKET__IOCTL 0x00000001UL | ||
760 | #define NETLINK_DNRT_SOCKET__READ 0x00000002UL | ||
761 | #define NETLINK_DNRT_SOCKET__WRITE 0x00000004UL | ||
762 | #define NETLINK_DNRT_SOCKET__CREATE 0x00000008UL | ||
763 | #define NETLINK_DNRT_SOCKET__GETATTR 0x00000010UL | ||
764 | #define NETLINK_DNRT_SOCKET__SETATTR 0x00000020UL | ||
765 | #define NETLINK_DNRT_SOCKET__LOCK 0x00000040UL | ||
766 | #define NETLINK_DNRT_SOCKET__RELABELFROM 0x00000080UL | ||
767 | #define NETLINK_DNRT_SOCKET__RELABELTO 0x00000100UL | ||
768 | #define NETLINK_DNRT_SOCKET__APPEND 0x00000200UL | ||
769 | #define NETLINK_DNRT_SOCKET__BIND 0x00000400UL | ||
770 | #define NETLINK_DNRT_SOCKET__CONNECT 0x00000800UL | ||
771 | #define NETLINK_DNRT_SOCKET__LISTEN 0x00001000UL | ||
772 | #define NETLINK_DNRT_SOCKET__ACCEPT 0x00002000UL | ||
773 | #define NETLINK_DNRT_SOCKET__GETOPT 0x00004000UL | ||
774 | #define NETLINK_DNRT_SOCKET__SETOPT 0x00008000UL | ||
775 | #define NETLINK_DNRT_SOCKET__SHUTDOWN 0x00010000UL | ||
776 | #define NETLINK_DNRT_SOCKET__RECVFROM 0x00020000UL | ||
777 | #define NETLINK_DNRT_SOCKET__SENDTO 0x00040000UL | ||
778 | #define NETLINK_DNRT_SOCKET__RECV_MSG 0x00080000UL | ||
779 | #define NETLINK_DNRT_SOCKET__SEND_MSG 0x00100000UL | ||
780 | #define NETLINK_DNRT_SOCKET__NAME_BIND 0x00200000UL | ||
781 | #define ASSOCIATION__SENDTO 0x00000001UL | ||
782 | #define ASSOCIATION__RECVFROM 0x00000002UL | ||
783 | #define ASSOCIATION__SETCONTEXT 0x00000004UL | ||
784 | #define ASSOCIATION__POLMATCH 0x00000008UL | ||
785 | #define NETLINK_KOBJECT_UEVENT_SOCKET__IOCTL 0x00000001UL | ||
786 | #define NETLINK_KOBJECT_UEVENT_SOCKET__READ 0x00000002UL | ||
787 | #define NETLINK_KOBJECT_UEVENT_SOCKET__WRITE 0x00000004UL | ||
788 | #define NETLINK_KOBJECT_UEVENT_SOCKET__CREATE 0x00000008UL | ||
789 | #define NETLINK_KOBJECT_UEVENT_SOCKET__GETATTR 0x00000010UL | ||
790 | #define NETLINK_KOBJECT_UEVENT_SOCKET__SETATTR 0x00000020UL | ||
791 | #define NETLINK_KOBJECT_UEVENT_SOCKET__LOCK 0x00000040UL | ||
792 | #define NETLINK_KOBJECT_UEVENT_SOCKET__RELABELFROM 0x00000080UL | ||
793 | #define NETLINK_KOBJECT_UEVENT_SOCKET__RELABELTO 0x00000100UL | ||
794 | #define NETLINK_KOBJECT_UEVENT_SOCKET__APPEND 0x00000200UL | ||
795 | #define NETLINK_KOBJECT_UEVENT_SOCKET__BIND 0x00000400UL | ||
796 | #define NETLINK_KOBJECT_UEVENT_SOCKET__CONNECT 0x00000800UL | ||
797 | #define NETLINK_KOBJECT_UEVENT_SOCKET__LISTEN 0x00001000UL | ||
798 | #define NETLINK_KOBJECT_UEVENT_SOCKET__ACCEPT 0x00002000UL | ||
799 | #define NETLINK_KOBJECT_UEVENT_SOCKET__GETOPT 0x00004000UL | ||
800 | #define NETLINK_KOBJECT_UEVENT_SOCKET__SETOPT 0x00008000UL | ||
801 | #define NETLINK_KOBJECT_UEVENT_SOCKET__SHUTDOWN 0x00010000UL | ||
802 | #define NETLINK_KOBJECT_UEVENT_SOCKET__RECVFROM 0x00020000UL | ||
803 | #define NETLINK_KOBJECT_UEVENT_SOCKET__SENDTO 0x00040000UL | ||
804 | #define NETLINK_KOBJECT_UEVENT_SOCKET__RECV_MSG 0x00080000UL | ||
805 | #define NETLINK_KOBJECT_UEVENT_SOCKET__SEND_MSG 0x00100000UL | ||
806 | #define NETLINK_KOBJECT_UEVENT_SOCKET__NAME_BIND 0x00200000UL | ||
807 | #define APPLETALK_SOCKET__IOCTL 0x00000001UL | ||
808 | #define APPLETALK_SOCKET__READ 0x00000002UL | ||
809 | #define APPLETALK_SOCKET__WRITE 0x00000004UL | ||
810 | #define APPLETALK_SOCKET__CREATE 0x00000008UL | ||
811 | #define APPLETALK_SOCKET__GETATTR 0x00000010UL | ||
812 | #define APPLETALK_SOCKET__SETATTR 0x00000020UL | ||
813 | #define APPLETALK_SOCKET__LOCK 0x00000040UL | ||
814 | #define APPLETALK_SOCKET__RELABELFROM 0x00000080UL | ||
815 | #define APPLETALK_SOCKET__RELABELTO 0x00000100UL | ||
816 | #define APPLETALK_SOCKET__APPEND 0x00000200UL | ||
817 | #define APPLETALK_SOCKET__BIND 0x00000400UL | ||
818 | #define APPLETALK_SOCKET__CONNECT 0x00000800UL | ||
819 | #define APPLETALK_SOCKET__LISTEN 0x00001000UL | ||
820 | #define APPLETALK_SOCKET__ACCEPT 0x00002000UL | ||
821 | #define APPLETALK_SOCKET__GETOPT 0x00004000UL | ||
822 | #define APPLETALK_SOCKET__SETOPT 0x00008000UL | ||
823 | #define APPLETALK_SOCKET__SHUTDOWN 0x00010000UL | ||
824 | #define APPLETALK_SOCKET__RECVFROM 0x00020000UL | ||
825 | #define APPLETALK_SOCKET__SENDTO 0x00040000UL | ||
826 | #define APPLETALK_SOCKET__RECV_MSG 0x00080000UL | ||
827 | #define APPLETALK_SOCKET__SEND_MSG 0x00100000UL | ||
828 | #define APPLETALK_SOCKET__NAME_BIND 0x00200000UL | ||
829 | #define PACKET__SEND 0x00000001UL | ||
830 | #define PACKET__RECV 0x00000002UL | ||
831 | #define PACKET__RELABELTO 0x00000004UL | ||
832 | #define PACKET__FLOW_IN 0x00000008UL | ||
833 | #define PACKET__FLOW_OUT 0x00000010UL | ||
834 | #define PACKET__FORWARD_IN 0x00000020UL | ||
835 | #define PACKET__FORWARD_OUT 0x00000040UL | ||
836 | #define KEY__VIEW 0x00000001UL | ||
837 | #define KEY__READ 0x00000002UL | ||
838 | #define KEY__WRITE 0x00000004UL | ||
839 | #define KEY__SEARCH 0x00000008UL | ||
840 | #define KEY__LINK 0x00000010UL | ||
841 | #define KEY__SETATTR 0x00000020UL | ||
842 | #define KEY__CREATE 0x00000040UL | ||
843 | #define DCCP_SOCKET__IOCTL 0x00000001UL | ||
844 | #define DCCP_SOCKET__READ 0x00000002UL | ||
845 | #define DCCP_SOCKET__WRITE 0x00000004UL | ||
846 | #define DCCP_SOCKET__CREATE 0x00000008UL | ||
847 | #define DCCP_SOCKET__GETATTR 0x00000010UL | ||
848 | #define DCCP_SOCKET__SETATTR 0x00000020UL | ||
849 | #define DCCP_SOCKET__LOCK 0x00000040UL | ||
850 | #define DCCP_SOCKET__RELABELFROM 0x00000080UL | ||
851 | #define DCCP_SOCKET__RELABELTO 0x00000100UL | ||
852 | #define DCCP_SOCKET__APPEND 0x00000200UL | ||
853 | #define DCCP_SOCKET__BIND 0x00000400UL | ||
854 | #define DCCP_SOCKET__CONNECT 0x00000800UL | ||
855 | #define DCCP_SOCKET__LISTEN 0x00001000UL | ||
856 | #define DCCP_SOCKET__ACCEPT 0x00002000UL | ||
857 | #define DCCP_SOCKET__GETOPT 0x00004000UL | ||
858 | #define DCCP_SOCKET__SETOPT 0x00008000UL | ||
859 | #define DCCP_SOCKET__SHUTDOWN 0x00010000UL | ||
860 | #define DCCP_SOCKET__RECVFROM 0x00020000UL | ||
861 | #define DCCP_SOCKET__SENDTO 0x00040000UL | ||
862 | #define DCCP_SOCKET__RECV_MSG 0x00080000UL | ||
863 | #define DCCP_SOCKET__SEND_MSG 0x00100000UL | ||
864 | #define DCCP_SOCKET__NAME_BIND 0x00200000UL | ||
865 | #define DCCP_SOCKET__NODE_BIND 0x00400000UL | ||
866 | #define DCCP_SOCKET__NAME_CONNECT 0x00800000UL | ||
867 | #define MEMPROTECT__MMAP_ZERO 0x00000001UL | ||
868 | #define PEER__RECV 0x00000001UL | ||
869 | #define KERNEL_SERVICE__USE_AS_OVERRIDE 0x00000001UL | ||
870 | #define KERNEL_SERVICE__CREATE_FILES_AS 0x00000002UL | ||
diff --git a/security/selinux/include/avc_ss.h b/security/selinux/include/avc_ss.h index bb1ec801bdfe..4677aa519b04 100644 --- a/security/selinux/include/avc_ss.h +++ b/security/selinux/include/avc_ss.h | |||
@@ -10,26 +10,13 @@ | |||
10 | 10 | ||
11 | int avc_ss_reset(u32 seqno); | 11 | int avc_ss_reset(u32 seqno); |
12 | 12 | ||
13 | struct av_perm_to_string { | 13 | /* Class/perm mapping support */ |
14 | u16 tclass; | 14 | struct security_class_mapping { |
15 | u32 value; | ||
16 | const char *name; | 15 | const char *name; |
16 | const char *perms[sizeof(u32) * 8 + 1]; | ||
17 | }; | 17 | }; |
18 | 18 | ||
19 | struct av_inherit { | 19 | extern struct security_class_mapping secclass_map[]; |
20 | const char **common_pts; | ||
21 | u32 common_base; | ||
22 | u16 tclass; | ||
23 | }; | ||
24 | |||
25 | struct selinux_class_perm { | ||
26 | const struct av_perm_to_string *av_perm_to_string; | ||
27 | u32 av_pts_len; | ||
28 | u32 cts_len; | ||
29 | const char **class_to_string; | ||
30 | const struct av_inherit *av_inherit; | ||
31 | u32 av_inherit_len; | ||
32 | }; | ||
33 | 20 | ||
34 | #endif /* _SELINUX_AVC_SS_H_ */ | 21 | #endif /* _SELINUX_AVC_SS_H_ */ |
35 | 22 | ||
diff --git a/security/selinux/include/class_to_string.h b/security/selinux/include/class_to_string.h deleted file mode 100644 index 7ab9299bfb6b..000000000000 --- a/security/selinux/include/class_to_string.h +++ /dev/null | |||
@@ -1,80 +0,0 @@ | |||
1 | /* This file is automatically generated. Do not edit. */ | ||
2 | /* | ||
3 | * Security object class definitions | ||
4 | */ | ||
5 | S_(NULL) | ||
6 | S_("security") | ||
7 | S_("process") | ||
8 | S_("system") | ||
9 | S_("capability") | ||
10 | S_("filesystem") | ||
11 | S_("file") | ||
12 | S_("dir") | ||
13 | S_("fd") | ||
14 | S_("lnk_file") | ||
15 | S_("chr_file") | ||
16 | S_("blk_file") | ||
17 | S_("sock_file") | ||
18 | S_("fifo_file") | ||
19 | S_("socket") | ||
20 | S_("tcp_socket") | ||
21 | S_("udp_socket") | ||
22 | S_("rawip_socket") | ||
23 | S_("node") | ||
24 | S_("netif") | ||
25 | S_("netlink_socket") | ||
26 | S_("packet_socket") | ||
27 | S_("key_socket") | ||
28 | S_("unix_stream_socket") | ||
29 | S_("unix_dgram_socket") | ||
30 | S_("sem") | ||
31 | S_("msg") | ||
32 | S_("msgq") | ||
33 | S_("shm") | ||
34 | S_("ipc") | ||
35 | S_(NULL) | ||
36 | S_(NULL) | ||
37 | S_(NULL) | ||
38 | S_(NULL) | ||
39 | S_(NULL) | ||
40 | S_(NULL) | ||
41 | S_(NULL) | ||
42 | S_(NULL) | ||
43 | S_(NULL) | ||
44 | S_(NULL) | ||
45 | S_(NULL) | ||
46 | S_(NULL) | ||
47 | S_(NULL) | ||
48 | S_("netlink_route_socket") | ||
49 | S_("netlink_firewall_socket") | ||
50 | S_("netlink_tcpdiag_socket") | ||
51 | S_("netlink_nflog_socket") | ||
52 | S_("netlink_xfrm_socket") | ||
53 | S_("netlink_selinux_socket") | ||
54 | S_("netlink_audit_socket") | ||
55 | S_("netlink_ip6fw_socket") | ||
56 | S_("netlink_dnrt_socket") | ||
57 | S_(NULL) | ||
58 | S_(NULL) | ||
59 | S_("association") | ||
60 | S_("netlink_kobject_uevent_socket") | ||
61 | S_("appletalk_socket") | ||
62 | S_("packet") | ||
63 | S_("key") | ||
64 | S_(NULL) | ||
65 | S_("dccp_socket") | ||
66 | S_("memprotect") | ||
67 | S_(NULL) | ||
68 | S_(NULL) | ||
69 | S_(NULL) | ||
70 | S_(NULL) | ||
71 | S_(NULL) | ||
72 | S_(NULL) | ||
73 | S_("peer") | ||
74 | S_("capability2") | ||
75 | S_(NULL) | ||
76 | S_(NULL) | ||
77 | S_(NULL) | ||
78 | S_(NULL) | ||
79 | S_("kernel_service") | ||
80 | S_("tun_socket") | ||
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h new file mode 100644 index 000000000000..8b32e959bb2e --- /dev/null +++ b/security/selinux/include/classmap.h | |||
@@ -0,0 +1,150 @@ | |||
1 | #define COMMON_FILE_SOCK_PERMS "ioctl", "read", "write", "create", \ | ||
2 | "getattr", "setattr", "lock", "relabelfrom", "relabelto", "append" | ||
3 | |||
4 | #define COMMON_FILE_PERMS COMMON_FILE_SOCK_PERMS, "unlink", "link", \ | ||
5 | "rename", "execute", "swapon", "quotaon", "mounton" | ||
6 | |||
7 | #define COMMON_SOCK_PERMS COMMON_FILE_SOCK_PERMS, "bind", "connect", \ | ||
8 | "listen", "accept", "getopt", "setopt", "shutdown", "recvfrom", \ | ||
9 | "sendto", "recv_msg", "send_msg", "name_bind" | ||
10 | |||
11 | #define COMMON_IPC_PERMS "create", "destroy", "getattr", "setattr", "read", \ | ||
12 | "write", "associate", "unix_read", "unix_write" | ||
13 | |||
14 | struct security_class_mapping secclass_map[] = { | ||
15 | { "security", | ||
16 | { "compute_av", "compute_create", "compute_member", | ||
17 | "check_context", "load_policy", "compute_relabel", | ||
18 | "compute_user", "setenforce", "setbool", "setsecparam", | ||
19 | "setcheckreqprot", NULL } }, | ||
20 | { "process", | ||
21 | { "fork", "transition", "sigchld", "sigkill", | ||
22 | "sigstop", "signull", "signal", "ptrace", "getsched", "setsched", | ||
23 | "getsession", "getpgid", "setpgid", "getcap", "setcap", "share", | ||
24 | "getattr", "setexec", "setfscreate", "noatsecure", "siginh", | ||
25 | "setrlimit", "rlimitinh", "dyntransition", "setcurrent", | ||
26 | "execmem", "execstack", "execheap", "setkeycreate", | ||
27 | "setsockcreate", NULL } }, | ||
28 | { "system", | ||
29 | { "ipc_info", "syslog_read", "syslog_mod", | ||
30 | "syslog_console", "module_request", NULL } }, | ||
31 | { "capability", | ||
32 | { "chown", "dac_override", "dac_read_search", | ||
33 | "fowner", "fsetid", "kill", "setgid", "setuid", "setpcap", | ||
34 | "linux_immutable", "net_bind_service", "net_broadcast", | ||
35 | "net_admin", "net_raw", "ipc_lock", "ipc_owner", "sys_module", | ||
36 | "sys_rawio", "sys_chroot", "sys_ptrace", "sys_pacct", "sys_admin", | ||
37 | "sys_boot", "sys_nice", "sys_resource", "sys_time", | ||
38 | "sys_tty_config", "mknod", "lease", "audit_write", | ||
39 | "audit_control", "setfcap", NULL } }, | ||
40 | { "filesystem", | ||
41 | { "mount", "remount", "unmount", "getattr", | ||
42 | "relabelfrom", "relabelto", "transition", "associate", "quotamod", | ||
43 | "quotaget", NULL } }, | ||
44 | { "file", | ||
45 | { COMMON_FILE_PERMS, | ||
46 | "execute_no_trans", "entrypoint", "execmod", "open", NULL } }, | ||
47 | { "dir", | ||
48 | { COMMON_FILE_PERMS, "add_name", "remove_name", | ||
49 | "reparent", "search", "rmdir", "open", NULL } }, | ||
50 | { "fd", { "use", NULL } }, | ||
51 | { "lnk_file", | ||
52 | { COMMON_FILE_PERMS, NULL } }, | ||
53 | { "chr_file", | ||
54 | { COMMON_FILE_PERMS, | ||
55 | "execute_no_trans", "entrypoint", "execmod", "open", NULL } }, | ||
56 | { "blk_file", | ||
57 | { COMMON_FILE_PERMS, "open", NULL } }, | ||
58 | { "sock_file", | ||
59 | { COMMON_FILE_PERMS, "open", NULL } }, | ||
60 | { "fifo_file", | ||
61 | { COMMON_FILE_PERMS, "open", NULL } }, | ||
62 | { "socket", | ||
63 | { COMMON_SOCK_PERMS, NULL } }, | ||
64 | { "tcp_socket", | ||
65 | { COMMON_SOCK_PERMS, | ||
66 | "connectto", "newconn", "acceptfrom", "node_bind", "name_connect", | ||
67 | NULL } }, | ||
68 | { "udp_socket", | ||
69 | { COMMON_SOCK_PERMS, | ||
70 | "node_bind", NULL } }, | ||
71 | { "rawip_socket", | ||
72 | { COMMON_SOCK_PERMS, | ||
73 | "node_bind", NULL } }, | ||
74 | { "node", | ||
75 | { "tcp_recv", "tcp_send", "udp_recv", "udp_send", | ||
76 | "rawip_recv", "rawip_send", "enforce_dest", | ||
77 | "dccp_recv", "dccp_send", "recvfrom", "sendto", NULL } }, | ||
78 | { "netif", | ||
79 | { "tcp_recv", "tcp_send", "udp_recv", "udp_send", | ||
80 | "rawip_recv", "rawip_send", "dccp_recv", "dccp_send", | ||
81 | "ingress", "egress", NULL } }, | ||
82 | { "netlink_socket", | ||
83 | { COMMON_SOCK_PERMS, NULL } }, | ||
84 | { "packet_socket", | ||
85 | { COMMON_SOCK_PERMS, NULL } }, | ||
86 | { "key_socket", | ||
87 | { COMMON_SOCK_PERMS, NULL } }, | ||
88 | { "unix_stream_socket", | ||
89 | { COMMON_SOCK_PERMS, "connectto", "newconn", "acceptfrom", NULL | ||
90 | } }, | ||
91 | { "unix_dgram_socket", | ||
92 | { COMMON_SOCK_PERMS, NULL | ||
93 | } }, | ||
94 | { "sem", | ||
95 | { COMMON_IPC_PERMS, NULL } }, | ||
96 | { "msg", { "send", "receive", NULL } }, | ||
97 | { "msgq", | ||
98 | { COMMON_IPC_PERMS, "enqueue", NULL } }, | ||
99 | { "shm", | ||
100 | { COMMON_IPC_PERMS, "lock", NULL } }, | ||
101 | { "ipc", | ||
102 | { COMMON_IPC_PERMS, NULL } }, | ||
103 | { "netlink_route_socket", | ||
104 | { COMMON_SOCK_PERMS, | ||
105 | "nlmsg_read", "nlmsg_write", NULL } }, | ||
106 | { "netlink_firewall_socket", | ||
107 | { COMMON_SOCK_PERMS, | ||
108 | "nlmsg_read", "nlmsg_write", NULL } }, | ||
109 | { "netlink_tcpdiag_socket", | ||
110 | { COMMON_SOCK_PERMS, | ||
111 | "nlmsg_read", "nlmsg_write", NULL } }, | ||
112 | { "netlink_nflog_socket", | ||
113 | { COMMON_SOCK_PERMS, NULL } }, | ||
114 | { "netlink_xfrm_socket", | ||
115 | { COMMON_SOCK_PERMS, | ||
116 | "nlmsg_read", "nlmsg_write", NULL } }, | ||
117 | { "netlink_selinux_socket", | ||
118 | { COMMON_SOCK_PERMS, NULL } }, | ||
119 | { "netlink_audit_socket", | ||
120 | { COMMON_SOCK_PERMS, | ||
121 | "nlmsg_read", "nlmsg_write", "nlmsg_relay", "nlmsg_readpriv", | ||
122 | "nlmsg_tty_audit", NULL } }, | ||
123 | { "netlink_ip6fw_socket", | ||
124 | { COMMON_SOCK_PERMS, | ||
125 | "nlmsg_read", "nlmsg_write", NULL } }, | ||
126 | { "netlink_dnrt_socket", | ||
127 | { COMMON_SOCK_PERMS, NULL } }, | ||
128 | { "association", | ||
129 | { "sendto", "recvfrom", "setcontext", "polmatch", NULL } }, | ||
130 | { "netlink_kobject_uevent_socket", | ||
131 | { COMMON_SOCK_PERMS, NULL } }, | ||
132 | { "appletalk_socket", | ||
133 | { COMMON_SOCK_PERMS, NULL } }, | ||
134 | { "packet", | ||
135 | { "send", "recv", "relabelto", "flow_in", "flow_out", | ||
136 | "forward_in", "forward_out", NULL } }, | ||
137 | { "key", | ||
138 | { "view", "read", "write", "search", "link", "setattr", "create", | ||
139 | NULL } }, | ||
140 | { "dccp_socket", | ||
141 | { COMMON_SOCK_PERMS, | ||
142 | "node_bind", "name_connect", NULL } }, | ||
143 | { "memprotect", { "mmap_zero", NULL } }, | ||
144 | { "peer", { "recv", NULL } }, | ||
145 | { "capability2", { "mac_override", "mac_admin", NULL } }, | ||
146 | { "kernel_service", { "use_as_override", "create_files_as", NULL } }, | ||
147 | { "tun_socket", | ||
148 | { COMMON_SOCK_PERMS, NULL } }, | ||
149 | { NULL } | ||
150 | }; | ||
diff --git a/security/selinux/include/common_perm_to_string.h b/security/selinux/include/common_perm_to_string.h deleted file mode 100644 index ce5b6e2fe9dd..000000000000 --- a/security/selinux/include/common_perm_to_string.h +++ /dev/null | |||
@@ -1,58 +0,0 @@ | |||
1 | /* This file is automatically generated. Do not edit. */ | ||
2 | TB_(common_file_perm_to_string) | ||
3 | S_("ioctl") | ||
4 | S_("read") | ||
5 | S_("write") | ||
6 | S_("create") | ||
7 | S_("getattr") | ||
8 | S_("setattr") | ||
9 | S_("lock") | ||
10 | S_("relabelfrom") | ||
11 | S_("relabelto") | ||
12 | S_("append") | ||
13 | S_("unlink") | ||
14 | S_("link") | ||
15 | S_("rename") | ||
16 | S_("execute") | ||
17 | S_("swapon") | ||
18 | S_("quotaon") | ||
19 | S_("mounton") | ||
20 | TE_(common_file_perm_to_string) | ||
21 | |||
22 | TB_(common_socket_perm_to_string) | ||
23 | S_("ioctl") | ||
24 | S_("read") | ||
25 | S_("write") | ||
26 | S_("create") | ||
27 | S_("getattr") | ||
28 | S_("setattr") | ||
29 | S_("lock") | ||
30 | S_("relabelfrom") | ||
31 | S_("relabelto") | ||
32 | S_("append") | ||
33 | S_("bind") | ||
34 | S_("connect") | ||
35 | S_("listen") | ||
36 | S_("accept") | ||
37 | S_("getopt") | ||
38 | S_("setopt") | ||
39 | S_("shutdown") | ||
40 | S_("recvfrom") | ||
41 | S_("sendto") | ||
42 | S_("recv_msg") | ||
43 | S_("send_msg") | ||
44 | S_("name_bind") | ||
45 | TE_(common_socket_perm_to_string) | ||
46 | |||
47 | TB_(common_ipc_perm_to_string) | ||
48 | S_("create") | ||
49 | S_("destroy") | ||
50 | S_("getattr") | ||
51 | S_("setattr") | ||
52 | S_("read") | ||
53 | S_("write") | ||
54 | S_("associate") | ||
55 | S_("unix_read") | ||
56 | S_("unix_write") | ||
57 | TE_(common_ipc_perm_to_string) | ||
58 | |||
diff --git a/security/selinux/include/flask.h b/security/selinux/include/flask.h deleted file mode 100644 index f248500a1e3c..000000000000 --- a/security/selinux/include/flask.h +++ /dev/null | |||
@@ -1,91 +0,0 @@ | |||
1 | /* This file is automatically generated. Do not edit. */ | ||
2 | #ifndef _SELINUX_FLASK_H_ | ||
3 | #define _SELINUX_FLASK_H_ | ||
4 | |||
5 | /* | ||
6 | * Security object class definitions | ||
7 | */ | ||
8 | #define SECCLASS_SECURITY 1 | ||
9 | #define SECCLASS_PROCESS 2 | ||
10 | #define SECCLASS_SYSTEM 3 | ||
11 | #define SECCLASS_CAPABILITY 4 | ||
12 | #define SECCLASS_FILESYSTEM 5 | ||
13 | #define SECCLASS_FILE 6 | ||
14 | #define SECCLASS_DIR 7 | ||
15 | #define SECCLASS_FD 8 | ||
16 | #define SECCLASS_LNK_FILE 9 | ||
17 | #define SECCLASS_CHR_FILE 10 | ||
18 | #define SECCLASS_BLK_FILE 11 | ||
19 | #define SECCLASS_SOCK_FILE 12 | ||
20 | #define SECCLASS_FIFO_FILE 13 | ||
21 | #define SECCLASS_SOCKET 14 | ||
22 | #define SECCLASS_TCP_SOCKET 15 | ||
23 | #define SECCLASS_UDP_SOCKET 16 | ||
24 | #define SECCLASS_RAWIP_SOCKET 17 | ||
25 | #define SECCLASS_NODE 18 | ||
26 | #define SECCLASS_NETIF 19 | ||
27 | #define SECCLASS_NETLINK_SOCKET 20 | ||
28 | #define SECCLASS_PACKET_SOCKET 21 | ||
29 | #define SECCLASS_KEY_SOCKET 22 | ||
30 | #define SECCLASS_UNIX_STREAM_SOCKET 23 | ||
31 | #define SECCLASS_UNIX_DGRAM_SOCKET 24 | ||
32 | #define SECCLASS_SEM 25 | ||
33 | #define SECCLASS_MSG 26 | ||
34 | #define SECCLASS_MSGQ 27 | ||
35 | #define SECCLASS_SHM 28 | ||
36 | #define SECCLASS_IPC 29 | ||
37 | #define SECCLASS_NETLINK_ROUTE_SOCKET 43 | ||
38 | #define SECCLASS_NETLINK_FIREWALL_SOCKET 44 | ||
39 | #define SECCLASS_NETLINK_TCPDIAG_SOCKET 45 | ||
40 | #define SECCLASS_NETLINK_NFLOG_SOCKET 46 | ||
41 | #define SECCLASS_NETLINK_XFRM_SOCKET 47 | ||
42 | #define SECCLASS_NETLINK_SELINUX_SOCKET 48 | ||
43 | #define SECCLASS_NETLINK_AUDIT_SOCKET 49 | ||
44 | #define SECCLASS_NETLINK_IP6FW_SOCKET 50 | ||
45 | #define SECCLASS_NETLINK_DNRT_SOCKET 51 | ||
46 | #define SECCLASS_ASSOCIATION 54 | ||
47 | #define SECCLASS_NETLINK_KOBJECT_UEVENT_SOCKET 55 | ||
48 | #define SECCLASS_APPLETALK_SOCKET 56 | ||
49 | #define SECCLASS_PACKET 57 | ||
50 | #define SECCLASS_KEY 58 | ||
51 | #define SECCLASS_DCCP_SOCKET 60 | ||
52 | #define SECCLASS_MEMPROTECT 61 | ||
53 | #define SECCLASS_PEER 68 | ||
54 | #define SECCLASS_CAPABILITY2 69 | ||
55 | #define SECCLASS_KERNEL_SERVICE 74 | ||
56 | #define SECCLASS_TUN_SOCKET 75 | ||
57 | |||
58 | /* | ||
59 | * Security identifier indices for initial entities | ||
60 | */ | ||
61 | #define SECINITSID_KERNEL 1 | ||
62 | #define SECINITSID_SECURITY 2 | ||
63 | #define SECINITSID_UNLABELED 3 | ||
64 | #define SECINITSID_FS 4 | ||
65 | #define SECINITSID_FILE 5 | ||
66 | #define SECINITSID_FILE_LABELS 6 | ||
67 | #define SECINITSID_INIT 7 | ||
68 | #define SECINITSID_ANY_SOCKET 8 | ||
69 | #define SECINITSID_PORT 9 | ||
70 | #define SECINITSID_NETIF 10 | ||
71 | #define SECINITSID_NETMSG 11 | ||
72 | #define SECINITSID_NODE 12 | ||
73 | #define SECINITSID_IGMP_PACKET 13 | ||
74 | #define SECINITSID_ICMP_SOCKET 14 | ||
75 | #define SECINITSID_TCP_SOCKET 15 | ||
76 | #define SECINITSID_SYSCTL_MODPROBE 16 | ||
77 | #define SECINITSID_SYSCTL 17 | ||
78 | #define SECINITSID_SYSCTL_FS 18 | ||
79 | #define SECINITSID_SYSCTL_KERNEL 19 | ||
80 | #define SECINITSID_SYSCTL_NET 20 | ||
81 | #define SECINITSID_SYSCTL_NET_UNIX 21 | ||
82 | #define SECINITSID_SYSCTL_VM 22 | ||
83 | #define SECINITSID_SYSCTL_DEV 23 | ||
84 | #define SECINITSID_KMOD 24 | ||
85 | #define SECINITSID_POLICY 25 | ||
86 | #define SECINITSID_SCMP_PACKET 26 | ||
87 | #define SECINITSID_DEVNULL 27 | ||
88 | |||
89 | #define SECINITSID_NUM 27 | ||
90 | |||
91 | #endif | ||
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h index ca835795a8b3..1f7c2491d3dc 100644 --- a/security/selinux/include/security.h +++ b/security/selinux/include/security.h | |||
@@ -57,7 +57,6 @@ | |||
57 | struct netlbl_lsm_secattr; | 57 | struct netlbl_lsm_secattr; |
58 | 58 | ||
59 | extern int selinux_enabled; | 59 | extern int selinux_enabled; |
60 | extern int selinux_mls_enabled; | ||
61 | 60 | ||
62 | /* Policy capabilities */ | 61 | /* Policy capabilities */ |
63 | enum { | 62 | enum { |
@@ -80,6 +79,8 @@ extern int selinux_policycap_openperm; | |||
80 | /* limitation of boundary depth */ | 79 | /* limitation of boundary depth */ |
81 | #define POLICYDB_BOUNDS_MAXDEPTH 4 | 80 | #define POLICYDB_BOUNDS_MAXDEPTH 4 |
82 | 81 | ||
82 | int security_mls_enabled(void); | ||
83 | |||
83 | int security_load_policy(void *data, size_t len); | 84 | int security_load_policy(void *data, size_t len); |
84 | 85 | ||
85 | int security_policycap_supported(unsigned int req_cap); | 86 | int security_policycap_supported(unsigned int req_cap); |
@@ -96,12 +97,17 @@ struct av_decision { | |||
96 | /* definitions of av_decision.flags */ | 97 | /* definitions of av_decision.flags */ |
97 | #define AVD_FLAGS_PERMISSIVE 0x0001 | 98 | #define AVD_FLAGS_PERMISSIVE 0x0001 |
98 | 99 | ||
99 | int security_compute_av(u32 ssid, u32 tsid, | 100 | void security_compute_av(u32 ssid, u32 tsid, |
100 | u16 tclass, u32 requested, | 101 | u16 tclass, struct av_decision *avd); |
101 | struct av_decision *avd); | 102 | |
103 | void security_compute_av_user(u32 ssid, u32 tsid, | ||
104 | u16 tclass, struct av_decision *avd); | ||
102 | 105 | ||
103 | int security_transition_sid(u32 ssid, u32 tsid, | 106 | int security_transition_sid(u32 ssid, u32 tsid, |
104 | u16 tclass, u32 *out_sid); | 107 | u16 tclass, u32 *out_sid); |
108 | |||
109 | int security_transition_sid_user(u32 ssid, u32 tsid, | ||
110 | u16 tclass, u32 *out_sid); | ||
105 | 111 | ||
106 | int security_member_sid(u32 ssid, u32 tsid, | 112 | int security_member_sid(u32 ssid, u32 tsid, |
107 | u16 tclass, u32 *out_sid); | 113 | u16 tclass, u32 *out_sid); |
diff --git a/security/selinux/netif.c b/security/selinux/netif.c index b4e14bc0bf32..d6095d63d831 100644 --- a/security/selinux/netif.c +++ b/security/selinux/netif.c | |||
@@ -16,6 +16,7 @@ | |||
16 | */ | 16 | */ |
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <linux/slab.h> | ||
19 | #include <linux/stddef.h> | 20 | #include <linux/stddef.h> |
20 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
21 | #include <linux/list.h> | 22 | #include <linux/list.h> |
diff --git a/security/selinux/netlabel.c b/security/selinux/netlabel.c index e68823741ad5..628da72ee763 100644 --- a/security/selinux/netlabel.c +++ b/security/selinux/netlabel.c | |||
@@ -29,6 +29,7 @@ | |||
29 | 29 | ||
30 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
31 | #include <linux/rcupdate.h> | 31 | #include <linux/rcupdate.h> |
32 | #include <linux/gfp.h> | ||
32 | #include <linux/ip.h> | 33 | #include <linux/ip.h> |
33 | #include <linux/ipv6.h> | 34 | #include <linux/ipv6.h> |
34 | #include <net/sock.h> | 35 | #include <net/sock.h> |
@@ -204,7 +205,7 @@ int selinux_netlbl_skbuff_getsid(struct sk_buff *skb, | |||
204 | * | 205 | * |
205 | * Description | 206 | * Description |
206 | * Call the NetLabel mechanism to set the label of a packet using @sid. | 207 | * Call the NetLabel mechanism to set the label of a packet using @sid. |
207 | * Returns zero on auccess, negative values on failure. | 208 | * Returns zero on success, negative values on failure. |
208 | * | 209 | * |
209 | */ | 210 | */ |
210 | int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, | 211 | int selinux_netlbl_skbuff_setsid(struct sk_buff *skb, |
diff --git a/security/selinux/netlink.c b/security/selinux/netlink.c index 1ae556446e65..0e147b6914ad 100644 --- a/security/selinux/netlink.c +++ b/security/selinux/netlink.c | |||
@@ -11,6 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | #include <linux/slab.h> | ||
14 | #include <linux/stddef.h> | 15 | #include <linux/stddef.h> |
15 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
16 | #include <linux/list.h> | 17 | #include <linux/list.h> |
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c index 7100072bb1b0..dc92792271f1 100644 --- a/security/selinux/netnode.c +++ b/security/selinux/netnode.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <linux/types.h> | 31 | #include <linux/types.h> |
32 | #include <linux/rcupdate.h> | 32 | #include <linux/rcupdate.h> |
33 | #include <linux/list.h> | 33 | #include <linux/list.h> |
34 | #include <linux/slab.h> | ||
34 | #include <linux/spinlock.h> | 35 | #include <linux/spinlock.h> |
35 | #include <linux/in.h> | 36 | #include <linux/in.h> |
36 | #include <linux/in6.h> | 37 | #include <linux/in6.h> |
diff --git a/security/selinux/netport.c b/security/selinux/netport.c index fe7fba67f19f..cfe2d72d3fb7 100644 --- a/security/selinux/netport.c +++ b/security/selinux/netport.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
31 | #include <linux/rcupdate.h> | 31 | #include <linux/rcupdate.h> |
32 | #include <linux/list.h> | 32 | #include <linux/list.h> |
33 | #include <linux/slab.h> | ||
33 | #include <linux/spinlock.h> | 34 | #include <linux/spinlock.h> |
34 | #include <linux/in.h> | 35 | #include <linux/in.h> |
35 | #include <linux/in6.h> | 36 | #include <linux/in6.h> |
diff --git a/security/selinux/selinuxfs.c b/security/selinux/selinuxfs.c index b4fc506e7a87..cd191bbec03c 100644 --- a/security/selinux/selinuxfs.c +++ b/security/selinux/selinuxfs.c | |||
@@ -282,7 +282,8 @@ static ssize_t sel_read_mls(struct file *filp, char __user *buf, | |||
282 | char tmpbuf[TMPBUFLEN]; | 282 | char tmpbuf[TMPBUFLEN]; |
283 | ssize_t length; | 283 | ssize_t length; |
284 | 284 | ||
285 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", selinux_mls_enabled); | 285 | length = scnprintf(tmpbuf, TMPBUFLEN, "%d", |
286 | security_mls_enabled()); | ||
286 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); | 287 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, length); |
287 | } | 288 | } |
288 | 289 | ||
@@ -494,7 +495,6 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | |||
494 | char *scon, *tcon; | 495 | char *scon, *tcon; |
495 | u32 ssid, tsid; | 496 | u32 ssid, tsid; |
496 | u16 tclass; | 497 | u16 tclass; |
497 | u32 req; | ||
498 | struct av_decision avd; | 498 | struct av_decision avd; |
499 | ssize_t length; | 499 | ssize_t length; |
500 | 500 | ||
@@ -512,7 +512,7 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | |||
512 | goto out; | 512 | goto out; |
513 | 513 | ||
514 | length = -EINVAL; | 514 | length = -EINVAL; |
515 | if (sscanf(buf, "%s %s %hu %x", scon, tcon, &tclass, &req) != 4) | 515 | if (sscanf(buf, "%s %s %hu", scon, tcon, &tclass) != 3) |
516 | goto out2; | 516 | goto out2; |
517 | 517 | ||
518 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); | 518 | length = security_context_to_sid(scon, strlen(scon)+1, &ssid); |
@@ -522,9 +522,7 @@ static ssize_t sel_write_access(struct file *file, char *buf, size_t size) | |||
522 | if (length < 0) | 522 | if (length < 0) |
523 | goto out2; | 523 | goto out2; |
524 | 524 | ||
525 | length = security_compute_av(ssid, tsid, tclass, req, &avd); | 525 | security_compute_av_user(ssid, tsid, tclass, &avd); |
526 | if (length < 0) | ||
527 | goto out2; | ||
528 | 526 | ||
529 | length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, | 527 | length = scnprintf(buf, SIMPLE_TRANSACTION_LIMIT, |
530 | "%x %x %x %x %u %x", | 528 | "%x %x %x %x %u %x", |
@@ -571,7 +569,7 @@ static ssize_t sel_write_create(struct file *file, char *buf, size_t size) | |||
571 | if (length < 0) | 569 | if (length < 0) |
572 | goto out2; | 570 | goto out2; |
573 | 571 | ||
574 | length = security_transition_sid(ssid, tsid, tclass, &newsid); | 572 | length = security_transition_sid_user(ssid, tsid, tclass, &newsid); |
575 | if (length < 0) | 573 | if (length < 0) |
576 | goto out2; | 574 | goto out2; |
577 | 575 | ||
@@ -979,6 +977,8 @@ static int sel_make_bools(void) | |||
979 | u32 sid; | 977 | u32 sid; |
980 | 978 | ||
981 | /* remove any existing files */ | 979 | /* remove any existing files */ |
980 | for (i = 0; i < bool_num; i++) | ||
981 | kfree(bool_pending_names[i]); | ||
982 | kfree(bool_pending_names); | 982 | kfree(bool_pending_names); |
983 | kfree(bool_pending_values); | 983 | kfree(bool_pending_values); |
984 | bool_pending_names = NULL; | 984 | bool_pending_names = NULL; |
diff --git a/security/selinux/ss/Makefile b/security/selinux/ss/Makefile index bad78779b9b0..15d4e62917de 100644 --- a/security/selinux/ss/Makefile +++ b/security/selinux/ss/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for building the SELinux security server as part of the kernel tree. | 2 | # Makefile for building the SELinux security server as part of the kernel tree. |
3 | # | 3 | # |
4 | 4 | ||
5 | EXTRA_CFLAGS += -Isecurity/selinux/include | 5 | EXTRA_CFLAGS += -Isecurity/selinux -Isecurity/selinux/include |
6 | obj-y := ss.o | 6 | obj-y := ss.o |
7 | 7 | ||
8 | ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o mls.o | 8 | ss-y := ebitmap.o hashtab.o symtab.o sidtab.o avtab.o policydb.o services.o conditional.o mls.o |
diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 8da6a8428086..cd4f734e2749 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h | |||
@@ -82,7 +82,7 @@ struct avtab_node *avtab_search_node_next(struct avtab_node *node, int specified | |||
82 | void avtab_cache_init(void); | 82 | void avtab_cache_init(void); |
83 | void avtab_cache_destroy(void); | 83 | void avtab_cache_destroy(void); |
84 | 84 | ||
85 | #define MAX_AVTAB_HASH_BITS 13 | 85 | #define MAX_AVTAB_HASH_BITS 11 |
86 | #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) | 86 | #define MAX_AVTAB_HASH_BUCKETS (1 << MAX_AVTAB_HASH_BITS) |
87 | #define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1) | 87 | #define MAX_AVTAB_HASH_MASK (MAX_AVTAB_HASH_BUCKETS-1) |
88 | #define MAX_AVTAB_SIZE MAX_AVTAB_HASH_BUCKETS | 88 | #define MAX_AVTAB_SIZE MAX_AVTAB_HASH_BUCKETS |
diff --git a/security/selinux/ss/context.h b/security/selinux/ss/context.h index d9dd7a2f6a8a..45e8fb0515f8 100644 --- a/security/selinux/ss/context.h +++ b/security/selinux/ss/context.h | |||
@@ -41,9 +41,6 @@ static inline int mls_context_cpy(struct context *dst, struct context *src) | |||
41 | { | 41 | { |
42 | int rc; | 42 | int rc; |
43 | 43 | ||
44 | if (!selinux_mls_enabled) | ||
45 | return 0; | ||
46 | |||
47 | dst->range.level[0].sens = src->range.level[0].sens; | 44 | dst->range.level[0].sens = src->range.level[0].sens; |
48 | rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); | 45 | rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); |
49 | if (rc) | 46 | if (rc) |
@@ -64,9 +61,6 @@ static inline int mls_context_cpy_low(struct context *dst, struct context *src) | |||
64 | { | 61 | { |
65 | int rc; | 62 | int rc; |
66 | 63 | ||
67 | if (!selinux_mls_enabled) | ||
68 | return 0; | ||
69 | |||
70 | dst->range.level[0].sens = src->range.level[0].sens; | 64 | dst->range.level[0].sens = src->range.level[0].sens; |
71 | rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); | 65 | rc = ebitmap_cpy(&dst->range.level[0].cat, &src->range.level[0].cat); |
72 | if (rc) | 66 | if (rc) |
@@ -82,9 +76,6 @@ out: | |||
82 | 76 | ||
83 | static inline int mls_context_cmp(struct context *c1, struct context *c2) | 77 | static inline int mls_context_cmp(struct context *c1, struct context *c2) |
84 | { | 78 | { |
85 | if (!selinux_mls_enabled) | ||
86 | return 1; | ||
87 | |||
88 | return ((c1->range.level[0].sens == c2->range.level[0].sens) && | 79 | return ((c1->range.level[0].sens == c2->range.level[0].sens) && |
89 | ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) && | 80 | ebitmap_cmp(&c1->range.level[0].cat, &c2->range.level[0].cat) && |
90 | (c1->range.level[1].sens == c2->range.level[1].sens) && | 81 | (c1->range.level[1].sens == c2->range.level[1].sens) && |
@@ -93,9 +84,6 @@ static inline int mls_context_cmp(struct context *c1, struct context *c2) | |||
93 | 84 | ||
94 | static inline void mls_context_destroy(struct context *c) | 85 | static inline void mls_context_destroy(struct context *c) |
95 | { | 86 | { |
96 | if (!selinux_mls_enabled) | ||
97 | return; | ||
98 | |||
99 | ebitmap_destroy(&c->range.level[0].cat); | 87 | ebitmap_destroy(&c->range.level[0].cat); |
100 | ebitmap_destroy(&c->range.level[1].cat); | 88 | ebitmap_destroy(&c->range.level[1].cat); |
101 | mls_context_init(c); | 89 | mls_context_init(c); |
diff --git a/security/selinux/ss/ebitmap.c b/security/selinux/ss/ebitmap.c index 68c7348d1acc..04b6145d767f 100644 --- a/security/selinux/ss/ebitmap.c +++ b/security/selinux/ss/ebitmap.c | |||
@@ -128,7 +128,7 @@ int ebitmap_netlbl_export(struct ebitmap *ebmap, | |||
128 | cmap_idx = delta / NETLBL_CATMAP_MAPSIZE; | 128 | cmap_idx = delta / NETLBL_CATMAP_MAPSIZE; |
129 | cmap_sft = delta % NETLBL_CATMAP_MAPSIZE; | 129 | cmap_sft = delta % NETLBL_CATMAP_MAPSIZE; |
130 | c_iter->bitmap[cmap_idx] | 130 | c_iter->bitmap[cmap_idx] |
131 | |= e_iter->maps[cmap_idx] << cmap_sft; | 131 | |= e_iter->maps[i] << cmap_sft; |
132 | } | 132 | } |
133 | e_iter = e_iter->next; | 133 | e_iter = e_iter->next; |
134 | } | 134 | } |
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c index b5407f16c2a4..372b773f8210 100644 --- a/security/selinux/ss/mls.c +++ b/security/selinux/ss/mls.c | |||
@@ -39,7 +39,7 @@ int mls_compute_context_len(struct context *context) | |||
39 | struct ebitmap *e; | 39 | struct ebitmap *e; |
40 | struct ebitmap_node *node; | 40 | struct ebitmap_node *node; |
41 | 41 | ||
42 | if (!selinux_mls_enabled) | 42 | if (!policydb.mls_enabled) |
43 | return 0; | 43 | return 0; |
44 | 44 | ||
45 | len = 1; /* for the beginning ":" */ | 45 | len = 1; /* for the beginning ":" */ |
@@ -93,7 +93,7 @@ void mls_sid_to_context(struct context *context, | |||
93 | struct ebitmap *e; | 93 | struct ebitmap *e; |
94 | struct ebitmap_node *node; | 94 | struct ebitmap_node *node; |
95 | 95 | ||
96 | if (!selinux_mls_enabled) | 96 | if (!policydb.mls_enabled) |
97 | return; | 97 | return; |
98 | 98 | ||
99 | scontextp = *scontext; | 99 | scontextp = *scontext; |
@@ -200,7 +200,7 @@ int mls_context_isvalid(struct policydb *p, struct context *c) | |||
200 | { | 200 | { |
201 | struct user_datum *usrdatum; | 201 | struct user_datum *usrdatum; |
202 | 202 | ||
203 | if (!selinux_mls_enabled) | 203 | if (!p->mls_enabled) |
204 | return 1; | 204 | return 1; |
205 | 205 | ||
206 | if (!mls_range_isvalid(p, &c->range)) | 206 | if (!mls_range_isvalid(p, &c->range)) |
@@ -253,7 +253,7 @@ int mls_context_to_sid(struct policydb *pol, | |||
253 | struct cat_datum *catdatum, *rngdatum; | 253 | struct cat_datum *catdatum, *rngdatum; |
254 | int l, rc = -EINVAL; | 254 | int l, rc = -EINVAL; |
255 | 255 | ||
256 | if (!selinux_mls_enabled) { | 256 | if (!pol->mls_enabled) { |
257 | if (def_sid != SECSID_NULL && oldc) | 257 | if (def_sid != SECSID_NULL && oldc) |
258 | *scontext += strlen(*scontext)+1; | 258 | *scontext += strlen(*scontext)+1; |
259 | return 0; | 259 | return 0; |
@@ -387,7 +387,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask) | |||
387 | char *tmpstr, *freestr; | 387 | char *tmpstr, *freestr; |
388 | int rc; | 388 | int rc; |
389 | 389 | ||
390 | if (!selinux_mls_enabled) | 390 | if (!policydb.mls_enabled) |
391 | return -EINVAL; | 391 | return -EINVAL; |
392 | 392 | ||
393 | /* we need freestr because mls_context_to_sid will change | 393 | /* we need freestr because mls_context_to_sid will change |
@@ -407,7 +407,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask) | |||
407 | /* | 407 | /* |
408 | * Copies the MLS range `range' into `context'. | 408 | * Copies the MLS range `range' into `context'. |
409 | */ | 409 | */ |
410 | static inline int mls_range_set(struct context *context, | 410 | int mls_range_set(struct context *context, |
411 | struct mls_range *range) | 411 | struct mls_range *range) |
412 | { | 412 | { |
413 | int l, rc = 0; | 413 | int l, rc = 0; |
@@ -427,7 +427,7 @@ static inline int mls_range_set(struct context *context, | |||
427 | int mls_setup_user_range(struct context *fromcon, struct user_datum *user, | 427 | int mls_setup_user_range(struct context *fromcon, struct user_datum *user, |
428 | struct context *usercon) | 428 | struct context *usercon) |
429 | { | 429 | { |
430 | if (selinux_mls_enabled) { | 430 | if (policydb.mls_enabled) { |
431 | struct mls_level *fromcon_sen = &(fromcon->range.level[0]); | 431 | struct mls_level *fromcon_sen = &(fromcon->range.level[0]); |
432 | struct mls_level *fromcon_clr = &(fromcon->range.level[1]); | 432 | struct mls_level *fromcon_clr = &(fromcon->range.level[1]); |
433 | struct mls_level *user_low = &(user->range.level[0]); | 433 | struct mls_level *user_low = &(user->range.level[0]); |
@@ -477,7 +477,7 @@ int mls_convert_context(struct policydb *oldp, | |||
477 | struct ebitmap_node *node; | 477 | struct ebitmap_node *node; |
478 | int l, i; | 478 | int l, i; |
479 | 479 | ||
480 | if (!selinux_mls_enabled) | 480 | if (!policydb.mls_enabled) |
481 | return 0; | 481 | return 0; |
482 | 482 | ||
483 | for (l = 0; l < 2; l++) { | 483 | for (l = 0; l < 2; l++) { |
@@ -513,26 +513,24 @@ int mls_compute_sid(struct context *scontext, | |||
513 | u32 specified, | 513 | u32 specified, |
514 | struct context *newcontext) | 514 | struct context *newcontext) |
515 | { | 515 | { |
516 | struct range_trans *rtr; | 516 | struct range_trans rtr; |
517 | struct mls_range *r; | ||
517 | 518 | ||
518 | if (!selinux_mls_enabled) | 519 | if (!policydb.mls_enabled) |
519 | return 0; | 520 | return 0; |
520 | 521 | ||
521 | switch (specified) { | 522 | switch (specified) { |
522 | case AVTAB_TRANSITION: | 523 | case AVTAB_TRANSITION: |
523 | /* Look for a range transition rule. */ | 524 | /* Look for a range transition rule. */ |
524 | for (rtr = policydb.range_tr; rtr; rtr = rtr->next) { | 525 | rtr.source_type = scontext->type; |
525 | if (rtr->source_type == scontext->type && | 526 | rtr.target_type = tcontext->type; |
526 | rtr->target_type == tcontext->type && | 527 | rtr.target_class = tclass; |
527 | rtr->target_class == tclass) { | 528 | r = hashtab_search(policydb.range_tr, &rtr); |
528 | /* Set the range from the rule */ | 529 | if (r) |
529 | return mls_range_set(newcontext, | 530 | return mls_range_set(newcontext, r); |
530 | &rtr->target_range); | ||
531 | } | ||
532 | } | ||
533 | /* Fallthrough */ | 531 | /* Fallthrough */ |
534 | case AVTAB_CHANGE: | 532 | case AVTAB_CHANGE: |
535 | if (tclass == SECCLASS_PROCESS) | 533 | if (tclass == policydb.process_class) |
536 | /* Use the process MLS attributes. */ | 534 | /* Use the process MLS attributes. */ |
537 | return mls_context_cpy(newcontext, scontext); | 535 | return mls_context_cpy(newcontext, scontext); |
538 | else | 536 | else |
@@ -541,8 +539,8 @@ int mls_compute_sid(struct context *scontext, | |||
541 | case AVTAB_MEMBER: | 539 | case AVTAB_MEMBER: |
542 | /* Use the process effective MLS attributes. */ | 540 | /* Use the process effective MLS attributes. */ |
543 | return mls_context_cpy_low(newcontext, scontext); | 541 | return mls_context_cpy_low(newcontext, scontext); |
544 | default: | 542 | |
545 | return -EINVAL; | 543 | /* fall through */ |
546 | } | 544 | } |
547 | return -EINVAL; | 545 | return -EINVAL; |
548 | } | 546 | } |
@@ -561,7 +559,7 @@ int mls_compute_sid(struct context *scontext, | |||
561 | void mls_export_netlbl_lvl(struct context *context, | 559 | void mls_export_netlbl_lvl(struct context *context, |
562 | struct netlbl_lsm_secattr *secattr) | 560 | struct netlbl_lsm_secattr *secattr) |
563 | { | 561 | { |
564 | if (!selinux_mls_enabled) | 562 | if (!policydb.mls_enabled) |
565 | return; | 563 | return; |
566 | 564 | ||
567 | secattr->attr.mls.lvl = context->range.level[0].sens - 1; | 565 | secattr->attr.mls.lvl = context->range.level[0].sens - 1; |
@@ -581,7 +579,7 @@ void mls_export_netlbl_lvl(struct context *context, | |||
581 | void mls_import_netlbl_lvl(struct context *context, | 579 | void mls_import_netlbl_lvl(struct context *context, |
582 | struct netlbl_lsm_secattr *secattr) | 580 | struct netlbl_lsm_secattr *secattr) |
583 | { | 581 | { |
584 | if (!selinux_mls_enabled) | 582 | if (!policydb.mls_enabled) |
585 | return; | 583 | return; |
586 | 584 | ||
587 | context->range.level[0].sens = secattr->attr.mls.lvl + 1; | 585 | context->range.level[0].sens = secattr->attr.mls.lvl + 1; |
@@ -603,7 +601,7 @@ int mls_export_netlbl_cat(struct context *context, | |||
603 | { | 601 | { |
604 | int rc; | 602 | int rc; |
605 | 603 | ||
606 | if (!selinux_mls_enabled) | 604 | if (!policydb.mls_enabled) |
607 | return 0; | 605 | return 0; |
608 | 606 | ||
609 | rc = ebitmap_netlbl_export(&context->range.level[0].cat, | 607 | rc = ebitmap_netlbl_export(&context->range.level[0].cat, |
@@ -631,7 +629,7 @@ int mls_import_netlbl_cat(struct context *context, | |||
631 | { | 629 | { |
632 | int rc; | 630 | int rc; |
633 | 631 | ||
634 | if (!selinux_mls_enabled) | 632 | if (!policydb.mls_enabled) |
635 | return 0; | 633 | return 0; |
636 | 634 | ||
637 | rc = ebitmap_netlbl_import(&context->range.level[0].cat, | 635 | rc = ebitmap_netlbl_import(&context->range.level[0].cat, |
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h index 1276715aaa8b..cd9152632e54 100644 --- a/security/selinux/ss/mls.h +++ b/security/selinux/ss/mls.h | |||
@@ -39,6 +39,8 @@ int mls_context_to_sid(struct policydb *p, | |||
39 | 39 | ||
40 | int mls_from_string(char *str, struct context *context, gfp_t gfp_mask); | 40 | int mls_from_string(char *str, struct context *context, gfp_t gfp_mask); |
41 | 41 | ||
42 | int mls_range_set(struct context *context, struct mls_range *range); | ||
43 | |||
42 | int mls_convert_context(struct policydb *oldp, | 44 | int mls_convert_context(struct policydb *oldp, |
43 | struct policydb *newp, | 45 | struct policydb *newp, |
44 | struct context *context); | 46 | struct context *context); |
diff --git a/security/selinux/ss/mls_types.h b/security/selinux/ss/mls_types.h index b6e943a21061..03bed52a8052 100644 --- a/security/selinux/ss/mls_types.h +++ b/security/selinux/ss/mls_types.h | |||
@@ -15,6 +15,7 @@ | |||
15 | #define _SS_MLS_TYPES_H_ | 15 | #define _SS_MLS_TYPES_H_ |
16 | 16 | ||
17 | #include "security.h" | 17 | #include "security.h" |
18 | #include "ebitmap.h" | ||
18 | 19 | ||
19 | struct mls_level { | 20 | struct mls_level { |
20 | u32 sens; /* sensitivity */ | 21 | u32 sens; /* sensitivity */ |
@@ -27,18 +28,12 @@ struct mls_range { | |||
27 | 28 | ||
28 | static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2) | 29 | static inline int mls_level_eq(struct mls_level *l1, struct mls_level *l2) |
29 | { | 30 | { |
30 | if (!selinux_mls_enabled) | ||
31 | return 1; | ||
32 | |||
33 | return ((l1->sens == l2->sens) && | 31 | return ((l1->sens == l2->sens) && |
34 | ebitmap_cmp(&l1->cat, &l2->cat)); | 32 | ebitmap_cmp(&l1->cat, &l2->cat)); |
35 | } | 33 | } |
36 | 34 | ||
37 | static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2) | 35 | static inline int mls_level_dom(struct mls_level *l1, struct mls_level *l2) |
38 | { | 36 | { |
39 | if (!selinux_mls_enabled) | ||
40 | return 1; | ||
41 | |||
42 | return ((l1->sens >= l2->sens) && | 37 | return ((l1->sens >= l2->sens) && |
43 | ebitmap_contains(&l1->cat, &l2->cat)); | 38 | ebitmap_contains(&l1->cat, &l2->cat)); |
44 | } | 39 | } |
diff --git a/security/selinux/ss/policydb.c b/security/selinux/ss/policydb.c index 72e4a54973aa..23c6e53c102c 100644 --- a/security/selinux/ss/policydb.c +++ b/security/selinux/ss/policydb.c | |||
@@ -52,8 +52,6 @@ static char *symtab_name[SYM_NUM] = { | |||
52 | }; | 52 | }; |
53 | #endif | 53 | #endif |
54 | 54 | ||
55 | int selinux_mls_enabled; | ||
56 | |||
57 | static unsigned int symtab_sizes[SYM_NUM] = { | 55 | static unsigned int symtab_sizes[SYM_NUM] = { |
58 | 2, | 56 | 2, |
59 | 32, | 57 | 32, |
@@ -177,6 +175,21 @@ out_free_role: | |||
177 | goto out; | 175 | goto out; |
178 | } | 176 | } |
179 | 177 | ||
178 | static u32 rangetr_hash(struct hashtab *h, const void *k) | ||
179 | { | ||
180 | const struct range_trans *key = k; | ||
181 | return (key->source_type + (key->target_type << 3) + | ||
182 | (key->target_class << 5)) & (h->size - 1); | ||
183 | } | ||
184 | |||
185 | static int rangetr_cmp(struct hashtab *h, const void *k1, const void *k2) | ||
186 | { | ||
187 | const struct range_trans *key1 = k1, *key2 = k2; | ||
188 | return (key1->source_type != key2->source_type || | ||
189 | key1->target_type != key2->target_type || | ||
190 | key1->target_class != key2->target_class); | ||
191 | } | ||
192 | |||
180 | /* | 193 | /* |
181 | * Initialize a policy database structure. | 194 | * Initialize a policy database structure. |
182 | */ | 195 | */ |
@@ -204,6 +217,10 @@ static int policydb_init(struct policydb *p) | |||
204 | if (rc) | 217 | if (rc) |
205 | goto out_free_symtab; | 218 | goto out_free_symtab; |
206 | 219 | ||
220 | p->range_tr = hashtab_create(rangetr_hash, rangetr_cmp, 256); | ||
221 | if (!p->range_tr) | ||
222 | goto out_free_symtab; | ||
223 | |||
207 | ebitmap_init(&p->policycaps); | 224 | ebitmap_init(&p->policycaps); |
208 | ebitmap_init(&p->permissive_map); | 225 | ebitmap_init(&p->permissive_map); |
209 | 226 | ||
@@ -408,6 +425,20 @@ static void symtab_hash_eval(struct symtab *s) | |||
408 | info.slots_used, h->size, info.max_chain_len); | 425 | info.slots_used, h->size, info.max_chain_len); |
409 | } | 426 | } |
410 | } | 427 | } |
428 | |||
429 | static void rangetr_hash_eval(struct hashtab *h) | ||
430 | { | ||
431 | struct hashtab_info info; | ||
432 | |||
433 | hashtab_stat(h, &info); | ||
434 | printk(KERN_DEBUG "SELinux: rangetr: %d entries and %d/%d buckets used, " | ||
435 | "longest chain length %d\n", h->nel, | ||
436 | info.slots_used, h->size, info.max_chain_len); | ||
437 | } | ||
438 | #else | ||
439 | static inline void rangetr_hash_eval(struct hashtab *h) | ||
440 | { | ||
441 | } | ||
411 | #endif | 442 | #endif |
412 | 443 | ||
413 | /* | 444 | /* |
@@ -422,7 +453,7 @@ static int policydb_index_others(struct policydb *p) | |||
422 | 453 | ||
423 | printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools", | 454 | printk(KERN_DEBUG "SELinux: %d users, %d roles, %d types, %d bools", |
424 | p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim); | 455 | p->p_users.nprim, p->p_roles.nprim, p->p_types.nprim, p->p_bools.nprim); |
425 | if (selinux_mls_enabled) | 456 | if (p->mls_enabled) |
426 | printk(", %d sens, %d cats", p->p_levels.nprim, | 457 | printk(", %d sens, %d cats", p->p_levels.nprim, |
427 | p->p_cats.nprim); | 458 | p->p_cats.nprim); |
428 | printk("\n"); | 459 | printk("\n"); |
@@ -612,6 +643,17 @@ static int (*destroy_f[SYM_NUM]) (void *key, void *datum, void *datap) = | |||
612 | cat_destroy, | 643 | cat_destroy, |
613 | }; | 644 | }; |
614 | 645 | ||
646 | static int range_tr_destroy(void *key, void *datum, void *p) | ||
647 | { | ||
648 | struct mls_range *rt = datum; | ||
649 | kfree(key); | ||
650 | ebitmap_destroy(&rt->level[0].cat); | ||
651 | ebitmap_destroy(&rt->level[1].cat); | ||
652 | kfree(datum); | ||
653 | cond_resched(); | ||
654 | return 0; | ||
655 | } | ||
656 | |||
615 | static void ocontext_destroy(struct ocontext *c, int i) | 657 | static void ocontext_destroy(struct ocontext *c, int i) |
616 | { | 658 | { |
617 | context_destroy(&c->context[0]); | 659 | context_destroy(&c->context[0]); |
@@ -632,7 +674,6 @@ void policydb_destroy(struct policydb *p) | |||
632 | int i; | 674 | int i; |
633 | struct role_allow *ra, *lra = NULL; | 675 | struct role_allow *ra, *lra = NULL; |
634 | struct role_trans *tr, *ltr = NULL; | 676 | struct role_trans *tr, *ltr = NULL; |
635 | struct range_trans *rt, *lrt = NULL; | ||
636 | 677 | ||
637 | for (i = 0; i < SYM_NUM; i++) { | 678 | for (i = 0; i < SYM_NUM; i++) { |
638 | cond_resched(); | 679 | cond_resched(); |
@@ -693,27 +734,14 @@ void policydb_destroy(struct policydb *p) | |||
693 | } | 734 | } |
694 | kfree(lra); | 735 | kfree(lra); |
695 | 736 | ||
696 | for (rt = p->range_tr; rt; rt = rt->next) { | 737 | hashtab_map(p->range_tr, range_tr_destroy, NULL); |
697 | cond_resched(); | 738 | hashtab_destroy(p->range_tr); |
698 | if (lrt) { | ||
699 | ebitmap_destroy(&lrt->target_range.level[0].cat); | ||
700 | ebitmap_destroy(&lrt->target_range.level[1].cat); | ||
701 | kfree(lrt); | ||
702 | } | ||
703 | lrt = rt; | ||
704 | } | ||
705 | if (lrt) { | ||
706 | ebitmap_destroy(&lrt->target_range.level[0].cat); | ||
707 | ebitmap_destroy(&lrt->target_range.level[1].cat); | ||
708 | kfree(lrt); | ||
709 | } | ||
710 | 739 | ||
711 | if (p->type_attr_map) { | 740 | if (p->type_attr_map) { |
712 | for (i = 0; i < p->p_types.nprim; i++) | 741 | for (i = 0; i < p->p_types.nprim; i++) |
713 | ebitmap_destroy(&p->type_attr_map[i]); | 742 | ebitmap_destroy(&p->type_attr_map[i]); |
714 | } | 743 | } |
715 | kfree(p->type_attr_map); | 744 | kfree(p->type_attr_map); |
716 | kfree(p->undefined_perms); | ||
717 | ebitmap_destroy(&p->policycaps); | 745 | ebitmap_destroy(&p->policycaps); |
718 | ebitmap_destroy(&p->permissive_map); | 746 | ebitmap_destroy(&p->permissive_map); |
719 | 747 | ||
@@ -1640,6 +1668,40 @@ static int policydb_bounds_sanity_check(struct policydb *p) | |||
1640 | 1668 | ||
1641 | extern int ss_initialized; | 1669 | extern int ss_initialized; |
1642 | 1670 | ||
1671 | u16 string_to_security_class(struct policydb *p, const char *name) | ||
1672 | { | ||
1673 | struct class_datum *cladatum; | ||
1674 | |||
1675 | cladatum = hashtab_search(p->p_classes.table, name); | ||
1676 | if (!cladatum) | ||
1677 | return 0; | ||
1678 | |||
1679 | return cladatum->value; | ||
1680 | } | ||
1681 | |||
1682 | u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name) | ||
1683 | { | ||
1684 | struct class_datum *cladatum; | ||
1685 | struct perm_datum *perdatum = NULL; | ||
1686 | struct common_datum *comdatum; | ||
1687 | |||
1688 | if (!tclass || tclass > p->p_classes.nprim) | ||
1689 | return 0; | ||
1690 | |||
1691 | cladatum = p->class_val_to_struct[tclass-1]; | ||
1692 | comdatum = cladatum->comdatum; | ||
1693 | if (comdatum) | ||
1694 | perdatum = hashtab_search(comdatum->permissions.table, | ||
1695 | name); | ||
1696 | if (!perdatum) | ||
1697 | perdatum = hashtab_search(cladatum->permissions.table, | ||
1698 | name); | ||
1699 | if (!perdatum) | ||
1700 | return 0; | ||
1701 | |||
1702 | return 1U << (perdatum->value-1); | ||
1703 | } | ||
1704 | |||
1643 | /* | 1705 | /* |
1644 | * Read the configuration data from a policy database binary | 1706 | * Read the configuration data from a policy database binary |
1645 | * representation file into a policy database structure. | 1707 | * representation file into a policy database structure. |
@@ -1653,12 +1715,11 @@ int policydb_read(struct policydb *p, void *fp) | |||
1653 | int i, j, rc; | 1715 | int i, j, rc; |
1654 | __le32 buf[4]; | 1716 | __le32 buf[4]; |
1655 | u32 nodebuf[8]; | 1717 | u32 nodebuf[8]; |
1656 | u32 len, len2, config, nprim, nel, nel2; | 1718 | u32 len, len2, nprim, nel, nel2; |
1657 | char *policydb_str; | 1719 | char *policydb_str; |
1658 | struct policydb_compat_info *info; | 1720 | struct policydb_compat_info *info; |
1659 | struct range_trans *rt, *lrt; | 1721 | struct range_trans *rt; |
1660 | 1722 | struct mls_range *r; | |
1661 | config = 0; | ||
1662 | 1723 | ||
1663 | rc = policydb_init(p); | 1724 | rc = policydb_init(p); |
1664 | if (rc) | 1725 | if (rc) |
@@ -1707,7 +1768,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
1707 | kfree(policydb_str); | 1768 | kfree(policydb_str); |
1708 | policydb_str = NULL; | 1769 | policydb_str = NULL; |
1709 | 1770 | ||
1710 | /* Read the version, config, and table sizes. */ | 1771 | /* Read the version and table sizes. */ |
1711 | rc = next_entry(buf, fp, sizeof(u32)*4); | 1772 | rc = next_entry(buf, fp, sizeof(u32)*4); |
1712 | if (rc < 0) | 1773 | if (rc < 0) |
1713 | goto bad; | 1774 | goto bad; |
@@ -1722,13 +1783,7 @@ int policydb_read(struct policydb *p, void *fp) | |||
1722 | } | 1783 | } |
1723 | 1784 | ||
1724 | if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) { | 1785 | if ((le32_to_cpu(buf[1]) & POLICYDB_CONFIG_MLS)) { |
1725 | if (ss_initialized && !selinux_mls_enabled) { | 1786 | p->mls_enabled = 1; |
1726 | printk(KERN_ERR "SELinux: Cannot switch between non-MLS" | ||
1727 | " and MLS policies\n"); | ||
1728 | goto bad; | ||
1729 | } | ||
1730 | selinux_mls_enabled = 1; | ||
1731 | config |= POLICYDB_CONFIG_MLS; | ||
1732 | 1787 | ||
1733 | if (p->policyvers < POLICYDB_VERSION_MLS) { | 1788 | if (p->policyvers < POLICYDB_VERSION_MLS) { |
1734 | printk(KERN_ERR "SELinux: security policydb version %d " | 1789 | printk(KERN_ERR "SELinux: security policydb version %d " |
@@ -1736,12 +1791,6 @@ int policydb_read(struct policydb *p, void *fp) | |||
1736 | p->policyvers); | 1791 | p->policyvers); |
1737 | goto bad; | 1792 | goto bad; |
1738 | } | 1793 | } |
1739 | } else { | ||
1740 | if (ss_initialized && selinux_mls_enabled) { | ||
1741 | printk(KERN_ERR "SELinux: Cannot switch between MLS and" | ||
1742 | " non-MLS policies\n"); | ||
1743 | goto bad; | ||
1744 | } | ||
1745 | } | 1794 | } |
1746 | p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN); | 1795 | p->reject_unknown = !!(le32_to_cpu(buf[1]) & REJECT_UNKNOWN); |
1747 | p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN); | 1796 | p->allow_unknown = !!(le32_to_cpu(buf[1]) & ALLOW_UNKNOWN); |
@@ -1861,6 +1910,16 @@ int policydb_read(struct policydb *p, void *fp) | |||
1861 | if (rc) | 1910 | if (rc) |
1862 | goto bad; | 1911 | goto bad; |
1863 | 1912 | ||
1913 | p->process_class = string_to_security_class(p, "process"); | ||
1914 | if (!p->process_class) | ||
1915 | goto bad; | ||
1916 | p->process_trans_perms = string_to_av_perm(p, p->process_class, | ||
1917 | "transition"); | ||
1918 | p->process_trans_perms |= string_to_av_perm(p, p->process_class, | ||
1919 | "dyntransition"); | ||
1920 | if (!p->process_trans_perms) | ||
1921 | goto bad; | ||
1922 | |||
1864 | for (i = 0; i < info->ocon_num; i++) { | 1923 | for (i = 0; i < info->ocon_num; i++) { |
1865 | rc = next_entry(buf, fp, sizeof(u32)); | 1924 | rc = next_entry(buf, fp, sizeof(u32)); |
1866 | if (rc < 0) | 1925 | if (rc < 0) |
@@ -2079,44 +2138,61 @@ int policydb_read(struct policydb *p, void *fp) | |||
2079 | if (rc < 0) | 2138 | if (rc < 0) |
2080 | goto bad; | 2139 | goto bad; |
2081 | nel = le32_to_cpu(buf[0]); | 2140 | nel = le32_to_cpu(buf[0]); |
2082 | lrt = NULL; | ||
2083 | for (i = 0; i < nel; i++) { | 2141 | for (i = 0; i < nel; i++) { |
2084 | rt = kzalloc(sizeof(*rt), GFP_KERNEL); | 2142 | rt = kzalloc(sizeof(*rt), GFP_KERNEL); |
2085 | if (!rt) { | 2143 | if (!rt) { |
2086 | rc = -ENOMEM; | 2144 | rc = -ENOMEM; |
2087 | goto bad; | 2145 | goto bad; |
2088 | } | 2146 | } |
2089 | if (lrt) | ||
2090 | lrt->next = rt; | ||
2091 | else | ||
2092 | p->range_tr = rt; | ||
2093 | rc = next_entry(buf, fp, (sizeof(u32) * 2)); | 2147 | rc = next_entry(buf, fp, (sizeof(u32) * 2)); |
2094 | if (rc < 0) | 2148 | if (rc < 0) { |
2149 | kfree(rt); | ||
2095 | goto bad; | 2150 | goto bad; |
2151 | } | ||
2096 | rt->source_type = le32_to_cpu(buf[0]); | 2152 | rt->source_type = le32_to_cpu(buf[0]); |
2097 | rt->target_type = le32_to_cpu(buf[1]); | 2153 | rt->target_type = le32_to_cpu(buf[1]); |
2098 | if (new_rangetr) { | 2154 | if (new_rangetr) { |
2099 | rc = next_entry(buf, fp, sizeof(u32)); | 2155 | rc = next_entry(buf, fp, sizeof(u32)); |
2100 | if (rc < 0) | 2156 | if (rc < 0) { |
2157 | kfree(rt); | ||
2101 | goto bad; | 2158 | goto bad; |
2159 | } | ||
2102 | rt->target_class = le32_to_cpu(buf[0]); | 2160 | rt->target_class = le32_to_cpu(buf[0]); |
2103 | } else | 2161 | } else |
2104 | rt->target_class = SECCLASS_PROCESS; | 2162 | rt->target_class = p->process_class; |
2105 | if (!policydb_type_isvalid(p, rt->source_type) || | 2163 | if (!policydb_type_isvalid(p, rt->source_type) || |
2106 | !policydb_type_isvalid(p, rt->target_type) || | 2164 | !policydb_type_isvalid(p, rt->target_type) || |
2107 | !policydb_class_isvalid(p, rt->target_class)) { | 2165 | !policydb_class_isvalid(p, rt->target_class)) { |
2166 | kfree(rt); | ||
2108 | rc = -EINVAL; | 2167 | rc = -EINVAL; |
2109 | goto bad; | 2168 | goto bad; |
2110 | } | 2169 | } |
2111 | rc = mls_read_range_helper(&rt->target_range, fp); | 2170 | r = kzalloc(sizeof(*r), GFP_KERNEL); |
2112 | if (rc) | 2171 | if (!r) { |
2172 | kfree(rt); | ||
2173 | rc = -ENOMEM; | ||
2174 | goto bad; | ||
2175 | } | ||
2176 | rc = mls_read_range_helper(r, fp); | ||
2177 | if (rc) { | ||
2178 | kfree(rt); | ||
2179 | kfree(r); | ||
2113 | goto bad; | 2180 | goto bad; |
2114 | if (!mls_range_isvalid(p, &rt->target_range)) { | 2181 | } |
2182 | if (!mls_range_isvalid(p, r)) { | ||
2115 | printk(KERN_WARNING "SELinux: rangetrans: invalid range\n"); | 2183 | printk(KERN_WARNING "SELinux: rangetrans: invalid range\n"); |
2184 | kfree(rt); | ||
2185 | kfree(r); | ||
2186 | goto bad; | ||
2187 | } | ||
2188 | rc = hashtab_insert(p->range_tr, rt, r); | ||
2189 | if (rc) { | ||
2190 | kfree(rt); | ||
2191 | kfree(r); | ||
2116 | goto bad; | 2192 | goto bad; |
2117 | } | 2193 | } |
2118 | lrt = rt; | ||
2119 | } | 2194 | } |
2195 | rangetr_hash_eval(p->range_tr); | ||
2120 | } | 2196 | } |
2121 | 2197 | ||
2122 | p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL); | 2198 | p->type_attr_map = kmalloc(p->p_types.nprim*sizeof(struct ebitmap), GFP_KERNEL); |
diff --git a/security/selinux/ss/policydb.h b/security/selinux/ss/policydb.h index 55152d498b53..26d9adf8542b 100644 --- a/security/selinux/ss/policydb.h +++ b/security/selinux/ss/policydb.h | |||
@@ -27,6 +27,8 @@ | |||
27 | #include "symtab.h" | 27 | #include "symtab.h" |
28 | #include "avtab.h" | 28 | #include "avtab.h" |
29 | #include "sidtab.h" | 29 | #include "sidtab.h" |
30 | #include "ebitmap.h" | ||
31 | #include "mls_types.h" | ||
30 | #include "context.h" | 32 | #include "context.h" |
31 | #include "constraint.h" | 33 | #include "constraint.h" |
32 | 34 | ||
@@ -113,8 +115,6 @@ struct range_trans { | |||
113 | u32 source_type; | 115 | u32 source_type; |
114 | u32 target_type; | 116 | u32 target_type; |
115 | u32 target_class; | 117 | u32 target_class; |
116 | struct mls_range target_range; | ||
117 | struct range_trans *next; | ||
118 | }; | 118 | }; |
119 | 119 | ||
120 | /* Boolean data type */ | 120 | /* Boolean data type */ |
@@ -187,6 +187,8 @@ struct genfs { | |||
187 | 187 | ||
188 | /* The policy database */ | 188 | /* The policy database */ |
189 | struct policydb { | 189 | struct policydb { |
190 | int mls_enabled; | ||
191 | |||
190 | /* symbol tables */ | 192 | /* symbol tables */ |
191 | struct symtab symtab[SYM_NUM]; | 193 | struct symtab symtab[SYM_NUM]; |
192 | #define p_commons symtab[SYM_COMMONS] | 194 | #define p_commons symtab[SYM_COMMONS] |
@@ -240,8 +242,8 @@ struct policydb { | |||
240 | fixed labeling behavior. */ | 242 | fixed labeling behavior. */ |
241 | struct genfs *genfs; | 243 | struct genfs *genfs; |
242 | 244 | ||
243 | /* range transitions */ | 245 | /* range transitions table (range_trans_key -> mls_range) */ |
244 | struct range_trans *range_tr; | 246 | struct hashtab *range_tr; |
245 | 247 | ||
246 | /* type -> attribute reverse mapping */ | 248 | /* type -> attribute reverse mapping */ |
247 | struct ebitmap *type_attr_map; | 249 | struct ebitmap *type_attr_map; |
@@ -254,7 +256,9 @@ struct policydb { | |||
254 | 256 | ||
255 | unsigned int reject_unknown : 1; | 257 | unsigned int reject_unknown : 1; |
256 | unsigned int allow_unknown : 1; | 258 | unsigned int allow_unknown : 1; |
257 | u32 *undefined_perms; | 259 | |
260 | u16 process_class; | ||
261 | u32 process_trans_perms; | ||
258 | }; | 262 | }; |
259 | 263 | ||
260 | extern void policydb_destroy(struct policydb *p); | 264 | extern void policydb_destroy(struct policydb *p); |
@@ -295,5 +299,8 @@ static inline int next_entry(void *buf, struct policy_file *fp, size_t bytes) | |||
295 | return 0; | 299 | return 0; |
296 | } | 300 | } |
297 | 301 | ||
302 | extern u16 string_to_security_class(struct policydb *p, const char *name); | ||
303 | extern u32 string_to_av_perm(struct policydb *p, u16 tclass, const char *name); | ||
304 | |||
298 | #endif /* _SS_POLICYDB_H_ */ | 305 | #endif /* _SS_POLICYDB_H_ */ |
299 | 306 | ||
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index ff17820d35ec..cf27b3ee1a95 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -26,6 +26,10 @@ | |||
26 | * | 26 | * |
27 | * Added support for bounds domain and audit messaged on masked permissions | 27 | * Added support for bounds domain and audit messaged on masked permissions |
28 | * | 28 | * |
29 | * Updated: Guido Trentalancia <guido@trentalancia.com> | ||
30 | * | ||
31 | * Added support for runtime switching of the policy type | ||
32 | * | ||
29 | * Copyright (C) 2008, 2009 NEC Corporation | 33 | * Copyright (C) 2008, 2009 NEC Corporation |
30 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. | 34 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. |
31 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. | 35 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. |
@@ -65,16 +69,10 @@ | |||
65 | #include "audit.h" | 69 | #include "audit.h" |
66 | 70 | ||
67 | extern void selnl_notify_policyload(u32 seqno); | 71 | extern void selnl_notify_policyload(u32 seqno); |
68 | unsigned int policydb_loaded_version; | ||
69 | 72 | ||
70 | int selinux_policycap_netpeer; | 73 | int selinux_policycap_netpeer; |
71 | int selinux_policycap_openperm; | 74 | int selinux_policycap_openperm; |
72 | 75 | ||
73 | /* | ||
74 | * This is declared in avc.c | ||
75 | */ | ||
76 | extern const struct selinux_class_perm selinux_class_perm; | ||
77 | |||
78 | static DEFINE_RWLOCK(policy_rwlock); | 76 | static DEFINE_RWLOCK(policy_rwlock); |
79 | 77 | ||
80 | static struct sidtab sidtab; | 78 | static struct sidtab sidtab; |
@@ -93,11 +91,156 @@ static u32 latest_granting; | |||
93 | static int context_struct_to_string(struct context *context, char **scontext, | 91 | static int context_struct_to_string(struct context *context, char **scontext, |
94 | u32 *scontext_len); | 92 | u32 *scontext_len); |
95 | 93 | ||
96 | static int context_struct_compute_av(struct context *scontext, | 94 | static void context_struct_compute_av(struct context *scontext, |
97 | struct context *tcontext, | 95 | struct context *tcontext, |
98 | u16 tclass, | 96 | u16 tclass, |
99 | u32 requested, | 97 | struct av_decision *avd); |
100 | struct av_decision *avd); | 98 | |
99 | struct selinux_mapping { | ||
100 | u16 value; /* policy value */ | ||
101 | unsigned num_perms; | ||
102 | u32 perms[sizeof(u32) * 8]; | ||
103 | }; | ||
104 | |||
105 | static struct selinux_mapping *current_mapping; | ||
106 | static u16 current_mapping_size; | ||
107 | |||
108 | static int selinux_set_mapping(struct policydb *pol, | ||
109 | struct security_class_mapping *map, | ||
110 | struct selinux_mapping **out_map_p, | ||
111 | u16 *out_map_size) | ||
112 | { | ||
113 | struct selinux_mapping *out_map = NULL; | ||
114 | size_t size = sizeof(struct selinux_mapping); | ||
115 | u16 i, j; | ||
116 | unsigned k; | ||
117 | bool print_unknown_handle = false; | ||
118 | |||
119 | /* Find number of classes in the input mapping */ | ||
120 | if (!map) | ||
121 | return -EINVAL; | ||
122 | i = 0; | ||
123 | while (map[i].name) | ||
124 | i++; | ||
125 | |||
126 | /* Allocate space for the class records, plus one for class zero */ | ||
127 | out_map = kcalloc(++i, size, GFP_ATOMIC); | ||
128 | if (!out_map) | ||
129 | return -ENOMEM; | ||
130 | |||
131 | /* Store the raw class and permission values */ | ||
132 | j = 0; | ||
133 | while (map[j].name) { | ||
134 | struct security_class_mapping *p_in = map + (j++); | ||
135 | struct selinux_mapping *p_out = out_map + j; | ||
136 | |||
137 | /* An empty class string skips ahead */ | ||
138 | if (!strcmp(p_in->name, "")) { | ||
139 | p_out->num_perms = 0; | ||
140 | continue; | ||
141 | } | ||
142 | |||
143 | p_out->value = string_to_security_class(pol, p_in->name); | ||
144 | if (!p_out->value) { | ||
145 | printk(KERN_INFO | ||
146 | "SELinux: Class %s not defined in policy.\n", | ||
147 | p_in->name); | ||
148 | if (pol->reject_unknown) | ||
149 | goto err; | ||
150 | p_out->num_perms = 0; | ||
151 | print_unknown_handle = true; | ||
152 | continue; | ||
153 | } | ||
154 | |||
155 | k = 0; | ||
156 | while (p_in->perms && p_in->perms[k]) { | ||
157 | /* An empty permission string skips ahead */ | ||
158 | if (!*p_in->perms[k]) { | ||
159 | k++; | ||
160 | continue; | ||
161 | } | ||
162 | p_out->perms[k] = string_to_av_perm(pol, p_out->value, | ||
163 | p_in->perms[k]); | ||
164 | if (!p_out->perms[k]) { | ||
165 | printk(KERN_INFO | ||
166 | "SELinux: Permission %s in class %s not defined in policy.\n", | ||
167 | p_in->perms[k], p_in->name); | ||
168 | if (pol->reject_unknown) | ||
169 | goto err; | ||
170 | print_unknown_handle = true; | ||
171 | } | ||
172 | |||
173 | k++; | ||
174 | } | ||
175 | p_out->num_perms = k; | ||
176 | } | ||
177 | |||
178 | if (print_unknown_handle) | ||
179 | printk(KERN_INFO "SELinux: the above unknown classes and permissions will be %s\n", | ||
180 | pol->allow_unknown ? "allowed" : "denied"); | ||
181 | |||
182 | *out_map_p = out_map; | ||
183 | *out_map_size = i; | ||
184 | return 0; | ||
185 | err: | ||
186 | kfree(out_map); | ||
187 | return -EINVAL; | ||
188 | } | ||
189 | |||
190 | /* | ||
191 | * Get real, policy values from mapped values | ||
192 | */ | ||
193 | |||
194 | static u16 unmap_class(u16 tclass) | ||
195 | { | ||
196 | if (tclass < current_mapping_size) | ||
197 | return current_mapping[tclass].value; | ||
198 | |||
199 | return tclass; | ||
200 | } | ||
201 | |||
202 | static void map_decision(u16 tclass, struct av_decision *avd, | ||
203 | int allow_unknown) | ||
204 | { | ||
205 | if (tclass < current_mapping_size) { | ||
206 | unsigned i, n = current_mapping[tclass].num_perms; | ||
207 | u32 result; | ||
208 | |||
209 | for (i = 0, result = 0; i < n; i++) { | ||
210 | if (avd->allowed & current_mapping[tclass].perms[i]) | ||
211 | result |= 1<<i; | ||
212 | if (allow_unknown && !current_mapping[tclass].perms[i]) | ||
213 | result |= 1<<i; | ||
214 | } | ||
215 | avd->allowed = result; | ||
216 | |||
217 | for (i = 0, result = 0; i < n; i++) | ||
218 | if (avd->auditallow & current_mapping[tclass].perms[i]) | ||
219 | result |= 1<<i; | ||
220 | avd->auditallow = result; | ||
221 | |||
222 | for (i = 0, result = 0; i < n; i++) { | ||
223 | if (avd->auditdeny & current_mapping[tclass].perms[i]) | ||
224 | result |= 1<<i; | ||
225 | if (!allow_unknown && !current_mapping[tclass].perms[i]) | ||
226 | result |= 1<<i; | ||
227 | } | ||
228 | /* | ||
229 | * In case the kernel has a bug and requests a permission | ||
230 | * between num_perms and the maximum permission number, we | ||
231 | * should audit that denial | ||
232 | */ | ||
233 | for (; i < (sizeof(u32)*8); i++) | ||
234 | result |= 1<<i; | ||
235 | avd->auditdeny = result; | ||
236 | } | ||
237 | } | ||
238 | |||
239 | int security_mls_enabled(void) | ||
240 | { | ||
241 | return policydb.mls_enabled; | ||
242 | } | ||
243 | |||
101 | /* | 244 | /* |
102 | * Return the boolean value of a constraint expression | 245 | * Return the boolean value of a constraint expression |
103 | * when it is applied to the specified source and target | 246 | * when it is applied to the specified source and target |
@@ -312,7 +455,8 @@ static void security_dump_masked_av(struct context *scontext, | |||
312 | char *scontext_name = NULL; | 455 | char *scontext_name = NULL; |
313 | char *tcontext_name = NULL; | 456 | char *tcontext_name = NULL; |
314 | char *permission_names[32]; | 457 | char *permission_names[32]; |
315 | int index, length; | 458 | int index; |
459 | u32 length; | ||
316 | bool need_comma = false; | 460 | bool need_comma = false; |
317 | 461 | ||
318 | if (!permissions) | 462 | if (!permissions) |
@@ -379,7 +523,6 @@ out: | |||
379 | static void type_attribute_bounds_av(struct context *scontext, | 523 | static void type_attribute_bounds_av(struct context *scontext, |
380 | struct context *tcontext, | 524 | struct context *tcontext, |
381 | u16 tclass, | 525 | u16 tclass, |
382 | u32 requested, | ||
383 | struct av_decision *avd) | 526 | struct av_decision *avd) |
384 | { | 527 | { |
385 | struct context lo_scontext; | 528 | struct context lo_scontext; |
@@ -400,7 +543,6 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
400 | context_struct_compute_av(&lo_scontext, | 543 | context_struct_compute_av(&lo_scontext, |
401 | tcontext, | 544 | tcontext, |
402 | tclass, | 545 | tclass, |
403 | requested, | ||
404 | &lo_avd); | 546 | &lo_avd); |
405 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) | 547 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) |
406 | return; /* no masked permission */ | 548 | return; /* no masked permission */ |
@@ -416,7 +558,6 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
416 | context_struct_compute_av(scontext, | 558 | context_struct_compute_av(scontext, |
417 | &lo_tcontext, | 559 | &lo_tcontext, |
418 | tclass, | 560 | tclass, |
419 | requested, | ||
420 | &lo_avd); | 561 | &lo_avd); |
421 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) | 562 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) |
422 | return; /* no masked permission */ | 563 | return; /* no masked permission */ |
@@ -433,7 +574,6 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
433 | context_struct_compute_av(&lo_scontext, | 574 | context_struct_compute_av(&lo_scontext, |
434 | &lo_tcontext, | 575 | &lo_tcontext, |
435 | tclass, | 576 | tclass, |
436 | requested, | ||
437 | &lo_avd); | 577 | &lo_avd); |
438 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) | 578 | if ((lo_avd.allowed & avd->allowed) == avd->allowed) |
439 | return; /* no masked permission */ | 579 | return; /* no masked permission */ |
@@ -454,11 +594,10 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
454 | * Compute access vectors based on a context structure pair for | 594 | * Compute access vectors based on a context structure pair for |
455 | * the permissions in a particular class. | 595 | * the permissions in a particular class. |
456 | */ | 596 | */ |
457 | static int context_struct_compute_av(struct context *scontext, | 597 | static void context_struct_compute_av(struct context *scontext, |
458 | struct context *tcontext, | 598 | struct context *tcontext, |
459 | u16 tclass, | 599 | u16 tclass, |
460 | u32 requested, | 600 | struct av_decision *avd) |
461 | struct av_decision *avd) | ||
462 | { | 601 | { |
463 | struct constraint_node *constraint; | 602 | struct constraint_node *constraint; |
464 | struct role_allow *ra; | 603 | struct role_allow *ra; |
@@ -467,56 +606,17 @@ static int context_struct_compute_av(struct context *scontext, | |||
467 | struct class_datum *tclass_datum; | 606 | struct class_datum *tclass_datum; |
468 | struct ebitmap *sattr, *tattr; | 607 | struct ebitmap *sattr, *tattr; |
469 | struct ebitmap_node *snode, *tnode; | 608 | struct ebitmap_node *snode, *tnode; |
470 | const struct selinux_class_perm *kdefs = &selinux_class_perm; | ||
471 | unsigned int i, j; | 609 | unsigned int i, j; |
472 | 610 | ||
473 | /* | ||
474 | * Remap extended Netlink classes for old policy versions. | ||
475 | * Do this here rather than socket_type_to_security_class() | ||
476 | * in case a newer policy version is loaded, allowing sockets | ||
477 | * to remain in the correct class. | ||
478 | */ | ||
479 | if (policydb_loaded_version < POLICYDB_VERSION_NLCLASS) | ||
480 | if (tclass >= SECCLASS_NETLINK_ROUTE_SOCKET && | ||
481 | tclass <= SECCLASS_NETLINK_DNRT_SOCKET) | ||
482 | tclass = SECCLASS_NETLINK_SOCKET; | ||
483 | |||
484 | /* | ||
485 | * Initialize the access vectors to the default values. | ||
486 | */ | ||
487 | avd->allowed = 0; | 611 | avd->allowed = 0; |
488 | avd->auditallow = 0; | 612 | avd->auditallow = 0; |
489 | avd->auditdeny = 0xffffffff; | 613 | avd->auditdeny = 0xffffffff; |
490 | avd->seqno = latest_granting; | ||
491 | avd->flags = 0; | ||
492 | 614 | ||
493 | /* | 615 | if (unlikely(!tclass || tclass > policydb.p_classes.nprim)) { |
494 | * Check for all the invalid cases. | 616 | if (printk_ratelimit()) |
495 | * - tclass 0 | 617 | printk(KERN_WARNING "SELinux: Invalid class %hu\n", tclass); |
496 | * - tclass > policy and > kernel | 618 | return; |
497 | * - tclass > policy but is a userspace class | 619 | } |
498 | * - tclass > policy but we do not allow unknowns | ||
499 | */ | ||
500 | if (unlikely(!tclass)) | ||
501 | goto inval_class; | ||
502 | if (unlikely(tclass > policydb.p_classes.nprim)) | ||
503 | if (tclass > kdefs->cts_len || | ||
504 | !kdefs->class_to_string[tclass] || | ||
505 | !policydb.allow_unknown) | ||
506 | goto inval_class; | ||
507 | |||
508 | /* | ||
509 | * Kernel class and we allow unknown so pad the allow decision | ||
510 | * the pad will be all 1 for unknown classes. | ||
511 | */ | ||
512 | if (tclass <= kdefs->cts_len && policydb.allow_unknown) | ||
513 | avd->allowed = policydb.undefined_perms[tclass - 1]; | ||
514 | |||
515 | /* | ||
516 | * Not in policy. Since decision is completed (all 1 or all 0) return. | ||
517 | */ | ||
518 | if (unlikely(tclass > policydb.p_classes.nprim)) | ||
519 | return 0; | ||
520 | 620 | ||
521 | tclass_datum = policydb.class_val_to_struct[tclass - 1]; | 621 | tclass_datum = policydb.class_val_to_struct[tclass - 1]; |
522 | 622 | ||
@@ -568,8 +668,8 @@ static int context_struct_compute_av(struct context *scontext, | |||
568 | * role is changing, then check the (current_role, new_role) | 668 | * role is changing, then check the (current_role, new_role) |
569 | * pair. | 669 | * pair. |
570 | */ | 670 | */ |
571 | if (tclass == SECCLASS_PROCESS && | 671 | if (tclass == policydb.process_class && |
572 | (avd->allowed & (PROCESS__TRANSITION | PROCESS__DYNTRANSITION)) && | 672 | (avd->allowed & policydb.process_trans_perms) && |
573 | scontext->role != tcontext->role) { | 673 | scontext->role != tcontext->role) { |
574 | for (ra = policydb.role_allow; ra; ra = ra->next) { | 674 | for (ra = policydb.role_allow; ra; ra = ra->next) { |
575 | if (scontext->role == ra->role && | 675 | if (scontext->role == ra->role && |
@@ -577,8 +677,7 @@ static int context_struct_compute_av(struct context *scontext, | |||
577 | break; | 677 | break; |
578 | } | 678 | } |
579 | if (!ra) | 679 | if (!ra) |
580 | avd->allowed &= ~(PROCESS__TRANSITION | | 680 | avd->allowed &= ~policydb.process_trans_perms; |
581 | PROCESS__DYNTRANSITION); | ||
582 | } | 681 | } |
583 | 682 | ||
584 | /* | 683 | /* |
@@ -587,24 +686,7 @@ static int context_struct_compute_av(struct context *scontext, | |||
587 | * permission and notice it to userspace via audit. | 686 | * permission and notice it to userspace via audit. |
588 | */ | 687 | */ |
589 | type_attribute_bounds_av(scontext, tcontext, | 688 | type_attribute_bounds_av(scontext, tcontext, |
590 | tclass, requested, avd); | 689 | tclass, avd); |
591 | |||
592 | return 0; | ||
593 | |||
594 | inval_class: | ||
595 | if (!tclass || tclass > kdefs->cts_len || | ||
596 | !kdefs->class_to_string[tclass]) { | ||
597 | if (printk_ratelimit()) | ||
598 | printk(KERN_ERR "SELinux: %s: unrecognized class %d\n", | ||
599 | __func__, tclass); | ||
600 | return -EINVAL; | ||
601 | } | ||
602 | |||
603 | /* | ||
604 | * Known to the kernel, but not to the policy. | ||
605 | * Handle as a denial (allowed is 0). | ||
606 | */ | ||
607 | return 0; | ||
608 | } | 690 | } |
609 | 691 | ||
610 | static int security_validtrans_handle_fail(struct context *ocontext, | 692 | static int security_validtrans_handle_fail(struct context *ocontext, |
@@ -636,13 +718,14 @@ out: | |||
636 | } | 718 | } |
637 | 719 | ||
638 | int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, | 720 | int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, |
639 | u16 tclass) | 721 | u16 orig_tclass) |
640 | { | 722 | { |
641 | struct context *ocontext; | 723 | struct context *ocontext; |
642 | struct context *ncontext; | 724 | struct context *ncontext; |
643 | struct context *tcontext; | 725 | struct context *tcontext; |
644 | struct class_datum *tclass_datum; | 726 | struct class_datum *tclass_datum; |
645 | struct constraint_node *constraint; | 727 | struct constraint_node *constraint; |
728 | u16 tclass; | ||
646 | int rc = 0; | 729 | int rc = 0; |
647 | 730 | ||
648 | if (!ss_initialized) | 731 | if (!ss_initialized) |
@@ -650,16 +733,7 @@ int security_validate_transition(u32 oldsid, u32 newsid, u32 tasksid, | |||
650 | 733 | ||
651 | read_lock(&policy_rwlock); | 734 | read_lock(&policy_rwlock); |
652 | 735 | ||
653 | /* | 736 | tclass = unmap_class(orig_tclass); |
654 | * Remap extended Netlink classes for old policy versions. | ||
655 | * Do this here rather than socket_type_to_security_class() | ||
656 | * in case a newer policy version is loaded, allowing sockets | ||
657 | * to remain in the correct class. | ||
658 | */ | ||
659 | if (policydb_loaded_version < POLICYDB_VERSION_NLCLASS) | ||
660 | if (tclass >= SECCLASS_NETLINK_ROUTE_SOCKET && | ||
661 | tclass <= SECCLASS_NETLINK_DNRT_SOCKET) | ||
662 | tclass = SECCLASS_NETLINK_SOCKET; | ||
663 | 737 | ||
664 | if (!tclass || tclass > policydb.p_classes.nprim) { | 738 | if (!tclass || tclass > policydb.p_classes.nprim) { |
665 | printk(KERN_ERR "SELinux: %s: unrecognized class %d\n", | 739 | printk(KERN_ERR "SELinux: %s: unrecognized class %d\n", |
@@ -741,7 +815,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
741 | goto out; | 815 | goto out; |
742 | } | 816 | } |
743 | 817 | ||
744 | /* type/domain unchaned */ | 818 | /* type/domain unchanged */ |
745 | if (old_context->type == new_context->type) { | 819 | if (old_context->type == new_context->type) { |
746 | rc = 0; | 820 | rc = 0; |
747 | goto out; | 821 | goto out; |
@@ -769,7 +843,7 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
769 | if (rc) { | 843 | if (rc) { |
770 | char *old_name = NULL; | 844 | char *old_name = NULL; |
771 | char *new_name = NULL; | 845 | char *new_name = NULL; |
772 | int length; | 846 | u32 length; |
773 | 847 | ||
774 | if (!context_struct_to_string(old_context, | 848 | if (!context_struct_to_string(old_context, |
775 | &old_name, &length) && | 849 | &old_name, &length) && |
@@ -791,63 +865,116 @@ out: | |||
791 | return rc; | 865 | return rc; |
792 | } | 866 | } |
793 | 867 | ||
868 | static void avd_init(struct av_decision *avd) | ||
869 | { | ||
870 | avd->allowed = 0; | ||
871 | avd->auditallow = 0; | ||
872 | avd->auditdeny = 0xffffffff; | ||
873 | avd->seqno = latest_granting; | ||
874 | avd->flags = 0; | ||
875 | } | ||
876 | |||
794 | 877 | ||
795 | /** | 878 | /** |
796 | * security_compute_av - Compute access vector decisions. | 879 | * security_compute_av - Compute access vector decisions. |
797 | * @ssid: source security identifier | 880 | * @ssid: source security identifier |
798 | * @tsid: target security identifier | 881 | * @tsid: target security identifier |
799 | * @tclass: target security class | 882 | * @tclass: target security class |
800 | * @requested: requested permissions | ||
801 | * @avd: access vector decisions | 883 | * @avd: access vector decisions |
802 | * | 884 | * |
803 | * Compute a set of access vector decisions based on the | 885 | * Compute a set of access vector decisions based on the |
804 | * SID pair (@ssid, @tsid) for the permissions in @tclass. | 886 | * SID pair (@ssid, @tsid) for the permissions in @tclass. |
805 | * Return -%EINVAL if any of the parameters are invalid or %0 | ||
806 | * if the access vector decisions were computed successfully. | ||
807 | */ | 887 | */ |
808 | int security_compute_av(u32 ssid, | 888 | void security_compute_av(u32 ssid, |
809 | u32 tsid, | 889 | u32 tsid, |
810 | u16 tclass, | 890 | u16 orig_tclass, |
811 | u32 requested, | 891 | struct av_decision *avd) |
812 | struct av_decision *avd) | ||
813 | { | 892 | { |
893 | u16 tclass; | ||
814 | struct context *scontext = NULL, *tcontext = NULL; | 894 | struct context *scontext = NULL, *tcontext = NULL; |
815 | int rc = 0; | ||
816 | |||
817 | if (!ss_initialized) { | ||
818 | avd->allowed = 0xffffffff; | ||
819 | avd->auditallow = 0; | ||
820 | avd->auditdeny = 0xffffffff; | ||
821 | avd->seqno = latest_granting; | ||
822 | return 0; | ||
823 | } | ||
824 | 895 | ||
825 | read_lock(&policy_rwlock); | 896 | read_lock(&policy_rwlock); |
897 | avd_init(avd); | ||
898 | if (!ss_initialized) | ||
899 | goto allow; | ||
826 | 900 | ||
827 | scontext = sidtab_search(&sidtab, ssid); | 901 | scontext = sidtab_search(&sidtab, ssid); |
828 | if (!scontext) { | 902 | if (!scontext) { |
829 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 903 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
830 | __func__, ssid); | 904 | __func__, ssid); |
831 | rc = -EINVAL; | ||
832 | goto out; | 905 | goto out; |
833 | } | 906 | } |
907 | |||
908 | /* permissive domain? */ | ||
909 | if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) | ||
910 | avd->flags |= AVD_FLAGS_PERMISSIVE; | ||
911 | |||
834 | tcontext = sidtab_search(&sidtab, tsid); | 912 | tcontext = sidtab_search(&sidtab, tsid); |
835 | if (!tcontext) { | 913 | if (!tcontext) { |
836 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 914 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
837 | __func__, tsid); | 915 | __func__, tsid); |
838 | rc = -EINVAL; | ||
839 | goto out; | 916 | goto out; |
840 | } | 917 | } |
841 | 918 | ||
842 | rc = context_struct_compute_av(scontext, tcontext, tclass, | 919 | tclass = unmap_class(orig_tclass); |
843 | requested, avd); | 920 | if (unlikely(orig_tclass && !tclass)) { |
921 | if (policydb.allow_unknown) | ||
922 | goto allow; | ||
923 | goto out; | ||
924 | } | ||
925 | context_struct_compute_av(scontext, tcontext, tclass, avd); | ||
926 | map_decision(orig_tclass, avd, policydb.allow_unknown); | ||
927 | out: | ||
928 | read_unlock(&policy_rwlock); | ||
929 | return; | ||
930 | allow: | ||
931 | avd->allowed = 0xffffffff; | ||
932 | goto out; | ||
933 | } | ||
934 | |||
935 | void security_compute_av_user(u32 ssid, | ||
936 | u32 tsid, | ||
937 | u16 tclass, | ||
938 | struct av_decision *avd) | ||
939 | { | ||
940 | struct context *scontext = NULL, *tcontext = NULL; | ||
941 | |||
942 | read_lock(&policy_rwlock); | ||
943 | avd_init(avd); | ||
944 | if (!ss_initialized) | ||
945 | goto allow; | ||
946 | |||
947 | scontext = sidtab_search(&sidtab, ssid); | ||
948 | if (!scontext) { | ||
949 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
950 | __func__, ssid); | ||
951 | goto out; | ||
952 | } | ||
844 | 953 | ||
845 | /* permissive domain? */ | 954 | /* permissive domain? */ |
846 | if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) | 955 | if (ebitmap_get_bit(&policydb.permissive_map, scontext->type)) |
847 | avd->flags |= AVD_FLAGS_PERMISSIVE; | 956 | avd->flags |= AVD_FLAGS_PERMISSIVE; |
848 | out: | 957 | |
958 | tcontext = sidtab_search(&sidtab, tsid); | ||
959 | if (!tcontext) { | ||
960 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | ||
961 | __func__, tsid); | ||
962 | goto out; | ||
963 | } | ||
964 | |||
965 | if (unlikely(!tclass)) { | ||
966 | if (policydb.allow_unknown) | ||
967 | goto allow; | ||
968 | goto out; | ||
969 | } | ||
970 | |||
971 | context_struct_compute_av(scontext, tcontext, tclass, avd); | ||
972 | out: | ||
849 | read_unlock(&policy_rwlock); | 973 | read_unlock(&policy_rwlock); |
850 | return rc; | 974 | return; |
975 | allow: | ||
976 | avd->allowed = 0xffffffff; | ||
977 | goto out; | ||
851 | } | 978 | } |
852 | 979 | ||
853 | /* | 980 | /* |
@@ -1204,20 +1331,22 @@ out: | |||
1204 | 1331 | ||
1205 | static int security_compute_sid(u32 ssid, | 1332 | static int security_compute_sid(u32 ssid, |
1206 | u32 tsid, | 1333 | u32 tsid, |
1207 | u16 tclass, | 1334 | u16 orig_tclass, |
1208 | u32 specified, | 1335 | u32 specified, |
1209 | u32 *out_sid) | 1336 | u32 *out_sid, |
1337 | bool kern) | ||
1210 | { | 1338 | { |
1211 | struct context *scontext = NULL, *tcontext = NULL, newcontext; | 1339 | struct context *scontext = NULL, *tcontext = NULL, newcontext; |
1212 | struct role_trans *roletr = NULL; | 1340 | struct role_trans *roletr = NULL; |
1213 | struct avtab_key avkey; | 1341 | struct avtab_key avkey; |
1214 | struct avtab_datum *avdatum; | 1342 | struct avtab_datum *avdatum; |
1215 | struct avtab_node *node; | 1343 | struct avtab_node *node; |
1344 | u16 tclass; | ||
1216 | int rc = 0; | 1345 | int rc = 0; |
1217 | 1346 | ||
1218 | if (!ss_initialized) { | 1347 | if (!ss_initialized) { |
1219 | switch (tclass) { | 1348 | switch (orig_tclass) { |
1220 | case SECCLASS_PROCESS: | 1349 | case SECCLASS_PROCESS: /* kernel value */ |
1221 | *out_sid = ssid; | 1350 | *out_sid = ssid; |
1222 | break; | 1351 | break; |
1223 | default: | 1352 | default: |
@@ -1231,6 +1360,11 @@ static int security_compute_sid(u32 ssid, | |||
1231 | 1360 | ||
1232 | read_lock(&policy_rwlock); | 1361 | read_lock(&policy_rwlock); |
1233 | 1362 | ||
1363 | if (kern) | ||
1364 | tclass = unmap_class(orig_tclass); | ||
1365 | else | ||
1366 | tclass = orig_tclass; | ||
1367 | |||
1234 | scontext = sidtab_search(&sidtab, ssid); | 1368 | scontext = sidtab_search(&sidtab, ssid); |
1235 | if (!scontext) { | 1369 | if (!scontext) { |
1236 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", | 1370 | printk(KERN_ERR "SELinux: %s: unrecognized SID %d\n", |
@@ -1260,13 +1394,11 @@ static int security_compute_sid(u32 ssid, | |||
1260 | } | 1394 | } |
1261 | 1395 | ||
1262 | /* Set the role and type to default values. */ | 1396 | /* Set the role and type to default values. */ |
1263 | switch (tclass) { | 1397 | if (tclass == policydb.process_class) { |
1264 | case SECCLASS_PROCESS: | ||
1265 | /* Use the current role and type of process. */ | 1398 | /* Use the current role and type of process. */ |
1266 | newcontext.role = scontext->role; | 1399 | newcontext.role = scontext->role; |
1267 | newcontext.type = scontext->type; | 1400 | newcontext.type = scontext->type; |
1268 | break; | 1401 | } else { |
1269 | default: | ||
1270 | /* Use the well-defined object role. */ | 1402 | /* Use the well-defined object role. */ |
1271 | newcontext.role = OBJECT_R_VAL; | 1403 | newcontext.role = OBJECT_R_VAL; |
1272 | /* Use the type of the related object. */ | 1404 | /* Use the type of the related object. */ |
@@ -1297,8 +1429,7 @@ static int security_compute_sid(u32 ssid, | |||
1297 | } | 1429 | } |
1298 | 1430 | ||
1299 | /* Check for class-specific changes. */ | 1431 | /* Check for class-specific changes. */ |
1300 | switch (tclass) { | 1432 | if (tclass == policydb.process_class) { |
1301 | case SECCLASS_PROCESS: | ||
1302 | if (specified & AVTAB_TRANSITION) { | 1433 | if (specified & AVTAB_TRANSITION) { |
1303 | /* Look for a role transition rule. */ | 1434 | /* Look for a role transition rule. */ |
1304 | for (roletr = policydb.role_tr; roletr; | 1435 | for (roletr = policydb.role_tr; roletr; |
@@ -1311,9 +1442,6 @@ static int security_compute_sid(u32 ssid, | |||
1311 | } | 1442 | } |
1312 | } | 1443 | } |
1313 | } | 1444 | } |
1314 | break; | ||
1315 | default: | ||
1316 | break; | ||
1317 | } | 1445 | } |
1318 | 1446 | ||
1319 | /* Set the MLS attributes. | 1447 | /* Set the MLS attributes. |
@@ -1358,7 +1486,17 @@ int security_transition_sid(u32 ssid, | |||
1358 | u16 tclass, | 1486 | u16 tclass, |
1359 | u32 *out_sid) | 1487 | u32 *out_sid) |
1360 | { | 1488 | { |
1361 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, out_sid); | 1489 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, |
1490 | out_sid, true); | ||
1491 | } | ||
1492 | |||
1493 | int security_transition_sid_user(u32 ssid, | ||
1494 | u32 tsid, | ||
1495 | u16 tclass, | ||
1496 | u32 *out_sid) | ||
1497 | { | ||
1498 | return security_compute_sid(ssid, tsid, tclass, AVTAB_TRANSITION, | ||
1499 | out_sid, false); | ||
1362 | } | 1500 | } |
1363 | 1501 | ||
1364 | /** | 1502 | /** |
@@ -1379,7 +1517,8 @@ int security_member_sid(u32 ssid, | |||
1379 | u16 tclass, | 1517 | u16 tclass, |
1380 | u32 *out_sid) | 1518 | u32 *out_sid) |
1381 | { | 1519 | { |
1382 | return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid); | 1520 | return security_compute_sid(ssid, tsid, tclass, AVTAB_MEMBER, out_sid, |
1521 | false); | ||
1383 | } | 1522 | } |
1384 | 1523 | ||
1385 | /** | 1524 | /** |
@@ -1400,144 +1539,8 @@ int security_change_sid(u32 ssid, | |||
1400 | u16 tclass, | 1539 | u16 tclass, |
1401 | u32 *out_sid) | 1540 | u32 *out_sid) |
1402 | { | 1541 | { |
1403 | return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid); | 1542 | return security_compute_sid(ssid, tsid, tclass, AVTAB_CHANGE, out_sid, |
1404 | } | 1543 | false); |
1405 | |||
1406 | /* | ||
1407 | * Verify that each kernel class that is defined in the | ||
1408 | * policy is correct | ||
1409 | */ | ||
1410 | static int validate_classes(struct policydb *p) | ||
1411 | { | ||
1412 | int i, j; | ||
1413 | struct class_datum *cladatum; | ||
1414 | struct perm_datum *perdatum; | ||
1415 | u32 nprim, tmp, common_pts_len, perm_val, pol_val; | ||
1416 | u16 class_val; | ||
1417 | const struct selinux_class_perm *kdefs = &selinux_class_perm; | ||
1418 | const char *def_class, *def_perm, *pol_class; | ||
1419 | struct symtab *perms; | ||
1420 | bool print_unknown_handle = 0; | ||
1421 | |||
1422 | if (p->allow_unknown) { | ||
1423 | u32 num_classes = kdefs->cts_len; | ||
1424 | p->undefined_perms = kcalloc(num_classes, sizeof(u32), GFP_KERNEL); | ||
1425 | if (!p->undefined_perms) | ||
1426 | return -ENOMEM; | ||
1427 | } | ||
1428 | |||
1429 | for (i = 1; i < kdefs->cts_len; i++) { | ||
1430 | def_class = kdefs->class_to_string[i]; | ||
1431 | if (!def_class) | ||
1432 | continue; | ||
1433 | if (i > p->p_classes.nprim) { | ||
1434 | printk(KERN_INFO | ||
1435 | "SELinux: class %s not defined in policy\n", | ||
1436 | def_class); | ||
1437 | if (p->reject_unknown) | ||
1438 | return -EINVAL; | ||
1439 | if (p->allow_unknown) | ||
1440 | p->undefined_perms[i-1] = ~0U; | ||
1441 | print_unknown_handle = 1; | ||
1442 | continue; | ||
1443 | } | ||
1444 | pol_class = p->p_class_val_to_name[i-1]; | ||
1445 | if (strcmp(pol_class, def_class)) { | ||
1446 | printk(KERN_ERR | ||
1447 | "SELinux: class %d is incorrect, found %s but should be %s\n", | ||
1448 | i, pol_class, def_class); | ||
1449 | return -EINVAL; | ||
1450 | } | ||
1451 | } | ||
1452 | for (i = 0; i < kdefs->av_pts_len; i++) { | ||
1453 | class_val = kdefs->av_perm_to_string[i].tclass; | ||
1454 | perm_val = kdefs->av_perm_to_string[i].value; | ||
1455 | def_perm = kdefs->av_perm_to_string[i].name; | ||
1456 | if (class_val > p->p_classes.nprim) | ||
1457 | continue; | ||
1458 | pol_class = p->p_class_val_to_name[class_val-1]; | ||
1459 | cladatum = hashtab_search(p->p_classes.table, pol_class); | ||
1460 | BUG_ON(!cladatum); | ||
1461 | perms = &cladatum->permissions; | ||
1462 | nprim = 1 << (perms->nprim - 1); | ||
1463 | if (perm_val > nprim) { | ||
1464 | printk(KERN_INFO | ||
1465 | "SELinux: permission %s in class %s not defined in policy\n", | ||
1466 | def_perm, pol_class); | ||
1467 | if (p->reject_unknown) | ||
1468 | return -EINVAL; | ||
1469 | if (p->allow_unknown) | ||
1470 | p->undefined_perms[class_val-1] |= perm_val; | ||
1471 | print_unknown_handle = 1; | ||
1472 | continue; | ||
1473 | } | ||
1474 | perdatum = hashtab_search(perms->table, def_perm); | ||
1475 | if (perdatum == NULL) { | ||
1476 | printk(KERN_ERR | ||
1477 | "SELinux: permission %s in class %s not found in policy, bad policy\n", | ||
1478 | def_perm, pol_class); | ||
1479 | return -EINVAL; | ||
1480 | } | ||
1481 | pol_val = 1 << (perdatum->value - 1); | ||
1482 | if (pol_val != perm_val) { | ||
1483 | printk(KERN_ERR | ||
1484 | "SELinux: permission %s in class %s has incorrect value\n", | ||
1485 | def_perm, pol_class); | ||
1486 | return -EINVAL; | ||
1487 | } | ||
1488 | } | ||
1489 | for (i = 0; i < kdefs->av_inherit_len; i++) { | ||
1490 | class_val = kdefs->av_inherit[i].tclass; | ||
1491 | if (class_val > p->p_classes.nprim) | ||
1492 | continue; | ||
1493 | pol_class = p->p_class_val_to_name[class_val-1]; | ||
1494 | cladatum = hashtab_search(p->p_classes.table, pol_class); | ||
1495 | BUG_ON(!cladatum); | ||
1496 | if (!cladatum->comdatum) { | ||
1497 | printk(KERN_ERR | ||
1498 | "SELinux: class %s should have an inherits clause but does not\n", | ||
1499 | pol_class); | ||
1500 | return -EINVAL; | ||
1501 | } | ||
1502 | tmp = kdefs->av_inherit[i].common_base; | ||
1503 | common_pts_len = 0; | ||
1504 | while (!(tmp & 0x01)) { | ||
1505 | common_pts_len++; | ||
1506 | tmp >>= 1; | ||
1507 | } | ||
1508 | perms = &cladatum->comdatum->permissions; | ||
1509 | for (j = 0; j < common_pts_len; j++) { | ||
1510 | def_perm = kdefs->av_inherit[i].common_pts[j]; | ||
1511 | if (j >= perms->nprim) { | ||
1512 | printk(KERN_INFO | ||
1513 | "SELinux: permission %s in class %s not defined in policy\n", | ||
1514 | def_perm, pol_class); | ||
1515 | if (p->reject_unknown) | ||
1516 | return -EINVAL; | ||
1517 | if (p->allow_unknown) | ||
1518 | p->undefined_perms[class_val-1] |= (1 << j); | ||
1519 | print_unknown_handle = 1; | ||
1520 | continue; | ||
1521 | } | ||
1522 | perdatum = hashtab_search(perms->table, def_perm); | ||
1523 | if (perdatum == NULL) { | ||
1524 | printk(KERN_ERR | ||
1525 | "SELinux: permission %s in class %s not found in policy, bad policy\n", | ||
1526 | def_perm, pol_class); | ||
1527 | return -EINVAL; | ||
1528 | } | ||
1529 | if (perdatum->value != j + 1) { | ||
1530 | printk(KERN_ERR | ||
1531 | "SELinux: permission %s in class %s has incorrect value\n", | ||
1532 | def_perm, pol_class); | ||
1533 | return -EINVAL; | ||
1534 | } | ||
1535 | } | ||
1536 | } | ||
1537 | if (print_unknown_handle) | ||
1538 | printk(KERN_INFO "SELinux: the above unknown classes and permissions will be %s\n", | ||
1539 | (security_get_allow_unknown() ? "allowed" : "denied")); | ||
1540 | return 0; | ||
1541 | } | 1544 | } |
1542 | 1545 | ||
1543 | /* Clone the SID into the new SID table. */ | 1546 | /* Clone the SID into the new SID table. */ |
@@ -1547,7 +1550,10 @@ static int clone_sid(u32 sid, | |||
1547 | { | 1550 | { |
1548 | struct sidtab *s = arg; | 1551 | struct sidtab *s = arg; |
1549 | 1552 | ||
1550 | return sidtab_insert(s, sid, context); | 1553 | if (sid > SECINITSID_NUM) |
1554 | return sidtab_insert(s, sid, context); | ||
1555 | else | ||
1556 | return 0; | ||
1551 | } | 1557 | } |
1552 | 1558 | ||
1553 | static inline int convert_context_handle_invalid_context(struct context *context) | 1559 | static inline int convert_context_handle_invalid_context(struct context *context) |
@@ -1588,12 +1594,17 @@ static int convert_context(u32 key, | |||
1588 | { | 1594 | { |
1589 | struct convert_context_args *args; | 1595 | struct convert_context_args *args; |
1590 | struct context oldc; | 1596 | struct context oldc; |
1597 | struct ocontext *oc; | ||
1598 | struct mls_range *range; | ||
1591 | struct role_datum *role; | 1599 | struct role_datum *role; |
1592 | struct type_datum *typdatum; | 1600 | struct type_datum *typdatum; |
1593 | struct user_datum *usrdatum; | 1601 | struct user_datum *usrdatum; |
1594 | char *s; | 1602 | char *s; |
1595 | u32 len; | 1603 | u32 len; |
1596 | int rc; | 1604 | int rc = 0; |
1605 | |||
1606 | if (key <= SECINITSID_NUM) | ||
1607 | goto out; | ||
1597 | 1608 | ||
1598 | args = p; | 1609 | args = p; |
1599 | 1610 | ||
@@ -1655,9 +1666,39 @@ static int convert_context(u32 key, | |||
1655 | goto bad; | 1666 | goto bad; |
1656 | c->type = typdatum->value; | 1667 | c->type = typdatum->value; |
1657 | 1668 | ||
1658 | rc = mls_convert_context(args->oldp, args->newp, c); | 1669 | /* Convert the MLS fields if dealing with MLS policies */ |
1659 | if (rc) | 1670 | if (args->oldp->mls_enabled && args->newp->mls_enabled) { |
1660 | goto bad; | 1671 | rc = mls_convert_context(args->oldp, args->newp, c); |
1672 | if (rc) | ||
1673 | goto bad; | ||
1674 | } else if (args->oldp->mls_enabled && !args->newp->mls_enabled) { | ||
1675 | /* | ||
1676 | * Switching between MLS and non-MLS policy: | ||
1677 | * free any storage used by the MLS fields in the | ||
1678 | * context for all existing entries in the sidtab. | ||
1679 | */ | ||
1680 | mls_context_destroy(c); | ||
1681 | } else if (!args->oldp->mls_enabled && args->newp->mls_enabled) { | ||
1682 | /* | ||
1683 | * Switching between non-MLS and MLS policy: | ||
1684 | * ensure that the MLS fields of the context for all | ||
1685 | * existing entries in the sidtab are filled in with a | ||
1686 | * suitable default value, likely taken from one of the | ||
1687 | * initial SIDs. | ||
1688 | */ | ||
1689 | oc = args->newp->ocontexts[OCON_ISID]; | ||
1690 | while (oc && oc->sid[0] != SECINITSID_UNLABELED) | ||
1691 | oc = oc->next; | ||
1692 | if (!oc) { | ||
1693 | printk(KERN_ERR "SELinux: unable to look up" | ||
1694 | " the initial SIDs list\n"); | ||
1695 | goto bad; | ||
1696 | } | ||
1697 | range = &oc->context[0].range; | ||
1698 | rc = mls_range_set(c, range); | ||
1699 | if (rc) | ||
1700 | goto bad; | ||
1701 | } | ||
1661 | 1702 | ||
1662 | /* Check the validity of the new context. */ | 1703 | /* Check the validity of the new context. */ |
1663 | if (!policydb_context_isvalid(args->newp, c)) { | 1704 | if (!policydb_context_isvalid(args->newp, c)) { |
@@ -1710,8 +1751,10 @@ int security_load_policy(void *data, size_t len) | |||
1710 | { | 1751 | { |
1711 | struct policydb oldpolicydb, newpolicydb; | 1752 | struct policydb oldpolicydb, newpolicydb; |
1712 | struct sidtab oldsidtab, newsidtab; | 1753 | struct sidtab oldsidtab, newsidtab; |
1754 | struct selinux_mapping *oldmap, *map = NULL; | ||
1713 | struct convert_context_args args; | 1755 | struct convert_context_args args; |
1714 | u32 seqno; | 1756 | u32 seqno; |
1757 | u16 map_size; | ||
1715 | int rc = 0; | 1758 | int rc = 0; |
1716 | struct policy_file file = { data, len }, *fp = &file; | 1759 | struct policy_file file = { data, len }, *fp = &file; |
1717 | 1760 | ||
@@ -1721,22 +1764,19 @@ int security_load_policy(void *data, size_t len) | |||
1721 | avtab_cache_destroy(); | 1764 | avtab_cache_destroy(); |
1722 | return -EINVAL; | 1765 | return -EINVAL; |
1723 | } | 1766 | } |
1724 | if (policydb_load_isids(&policydb, &sidtab)) { | 1767 | if (selinux_set_mapping(&policydb, secclass_map, |
1768 | ¤t_mapping, | ||
1769 | ¤t_mapping_size)) { | ||
1725 | policydb_destroy(&policydb); | 1770 | policydb_destroy(&policydb); |
1726 | avtab_cache_destroy(); | 1771 | avtab_cache_destroy(); |
1727 | return -EINVAL; | 1772 | return -EINVAL; |
1728 | } | 1773 | } |
1729 | /* Verify that the kernel defined classes are correct. */ | 1774 | if (policydb_load_isids(&policydb, &sidtab)) { |
1730 | if (validate_classes(&policydb)) { | ||
1731 | printk(KERN_ERR | ||
1732 | "SELinux: the definition of a class is incorrect\n"); | ||
1733 | sidtab_destroy(&sidtab); | ||
1734 | policydb_destroy(&policydb); | 1775 | policydb_destroy(&policydb); |
1735 | avtab_cache_destroy(); | 1776 | avtab_cache_destroy(); |
1736 | return -EINVAL; | 1777 | return -EINVAL; |
1737 | } | 1778 | } |
1738 | security_load_policycaps(); | 1779 | security_load_policycaps(); |
1739 | policydb_loaded_version = policydb.policyvers; | ||
1740 | ss_initialized = 1; | 1780 | ss_initialized = 1; |
1741 | seqno = ++latest_granting; | 1781 | seqno = ++latest_granting; |
1742 | selinux_complete_init(); | 1782 | selinux_complete_init(); |
@@ -1754,18 +1794,22 @@ int security_load_policy(void *data, size_t len) | |||
1754 | if (policydb_read(&newpolicydb, fp)) | 1794 | if (policydb_read(&newpolicydb, fp)) |
1755 | return -EINVAL; | 1795 | return -EINVAL; |
1756 | 1796 | ||
1757 | if (sidtab_init(&newsidtab)) { | 1797 | /* If switching between different policy types, log MLS status */ |
1798 | if (policydb.mls_enabled && !newpolicydb.mls_enabled) | ||
1799 | printk(KERN_INFO "SELinux: Disabling MLS support...\n"); | ||
1800 | else if (!policydb.mls_enabled && newpolicydb.mls_enabled) | ||
1801 | printk(KERN_INFO "SELinux: Enabling MLS support...\n"); | ||
1802 | |||
1803 | rc = policydb_load_isids(&newpolicydb, &newsidtab); | ||
1804 | if (rc) { | ||
1805 | printk(KERN_ERR "SELinux: unable to load the initial SIDs\n"); | ||
1758 | policydb_destroy(&newpolicydb); | 1806 | policydb_destroy(&newpolicydb); |
1759 | return -ENOMEM; | 1807 | return rc; |
1760 | } | 1808 | } |
1761 | 1809 | ||
1762 | /* Verify that the kernel defined classes are correct. */ | 1810 | if (selinux_set_mapping(&newpolicydb, secclass_map, |
1763 | if (validate_classes(&newpolicydb)) { | 1811 | &map, &map_size)) |
1764 | printk(KERN_ERR | ||
1765 | "SELinux: the definition of a class is incorrect\n"); | ||
1766 | rc = -EINVAL; | ||
1767 | goto err; | 1812 | goto err; |
1768 | } | ||
1769 | 1813 | ||
1770 | rc = security_preserve_bools(&newpolicydb); | 1814 | rc = security_preserve_bools(&newpolicydb); |
1771 | if (rc) { | 1815 | if (rc) { |
@@ -1787,8 +1831,12 @@ int security_load_policy(void *data, size_t len) | |||
1787 | args.oldp = &policydb; | 1831 | args.oldp = &policydb; |
1788 | args.newp = &newpolicydb; | 1832 | args.newp = &newpolicydb; |
1789 | rc = sidtab_map(&newsidtab, convert_context, &args); | 1833 | rc = sidtab_map(&newsidtab, convert_context, &args); |
1790 | if (rc) | 1834 | if (rc) { |
1835 | printk(KERN_ERR "SELinux: unable to convert the internal" | ||
1836 | " representation of contexts in the new SID" | ||
1837 | " table\n"); | ||
1791 | goto err; | 1838 | goto err; |
1839 | } | ||
1792 | 1840 | ||
1793 | /* Save the old policydb and SID table to free later. */ | 1841 | /* Save the old policydb and SID table to free later. */ |
1794 | memcpy(&oldpolicydb, &policydb, sizeof policydb); | 1842 | memcpy(&oldpolicydb, &policydb, sizeof policydb); |
@@ -1799,13 +1847,16 @@ int security_load_policy(void *data, size_t len) | |||
1799 | memcpy(&policydb, &newpolicydb, sizeof policydb); | 1847 | memcpy(&policydb, &newpolicydb, sizeof policydb); |
1800 | sidtab_set(&sidtab, &newsidtab); | 1848 | sidtab_set(&sidtab, &newsidtab); |
1801 | security_load_policycaps(); | 1849 | security_load_policycaps(); |
1850 | oldmap = current_mapping; | ||
1851 | current_mapping = map; | ||
1852 | current_mapping_size = map_size; | ||
1802 | seqno = ++latest_granting; | 1853 | seqno = ++latest_granting; |
1803 | policydb_loaded_version = policydb.policyvers; | ||
1804 | write_unlock_irq(&policy_rwlock); | 1854 | write_unlock_irq(&policy_rwlock); |
1805 | 1855 | ||
1806 | /* Free the old policydb and SID table. */ | 1856 | /* Free the old policydb and SID table. */ |
1807 | policydb_destroy(&oldpolicydb); | 1857 | policydb_destroy(&oldpolicydb); |
1808 | sidtab_destroy(&oldsidtab); | 1858 | sidtab_destroy(&oldsidtab); |
1859 | kfree(oldmap); | ||
1809 | 1860 | ||
1810 | avc_ss_reset(seqno); | 1861 | avc_ss_reset(seqno); |
1811 | selnl_notify_policyload(seqno); | 1862 | selnl_notify_policyload(seqno); |
@@ -1815,6 +1866,7 @@ int security_load_policy(void *data, size_t len) | |||
1815 | return 0; | 1866 | return 0; |
1816 | 1867 | ||
1817 | err: | 1868 | err: |
1869 | kfree(map); | ||
1818 | sidtab_destroy(&newsidtab); | 1870 | sidtab_destroy(&newsidtab); |
1819 | policydb_destroy(&newpolicydb); | 1871 | policydb_destroy(&newpolicydb); |
1820 | return rc; | 1872 | return rc; |
@@ -2091,7 +2143,7 @@ out_unlock: | |||
2091 | } | 2143 | } |
2092 | for (i = 0, j = 0; i < mynel; i++) { | 2144 | for (i = 0, j = 0; i < mynel; i++) { |
2093 | rc = avc_has_perm_noaudit(fromsid, mysids[i], | 2145 | rc = avc_has_perm_noaudit(fromsid, mysids[i], |
2094 | SECCLASS_PROCESS, | 2146 | SECCLASS_PROCESS, /* kernel value */ |
2095 | PROCESS__TRANSITION, AVC_STRICT, | 2147 | PROCESS__TRANSITION, AVC_STRICT, |
2096 | NULL); | 2148 | NULL); |
2097 | if (!rc) | 2149 | if (!rc) |
@@ -2119,10 +2171,11 @@ out: | |||
2119 | */ | 2171 | */ |
2120 | int security_genfs_sid(const char *fstype, | 2172 | int security_genfs_sid(const char *fstype, |
2121 | char *path, | 2173 | char *path, |
2122 | u16 sclass, | 2174 | u16 orig_sclass, |
2123 | u32 *sid) | 2175 | u32 *sid) |
2124 | { | 2176 | { |
2125 | int len; | 2177 | int len; |
2178 | u16 sclass; | ||
2126 | struct genfs *genfs; | 2179 | struct genfs *genfs; |
2127 | struct ocontext *c; | 2180 | struct ocontext *c; |
2128 | int rc = 0, cmp = 0; | 2181 | int rc = 0, cmp = 0; |
@@ -2132,6 +2185,8 @@ int security_genfs_sid(const char *fstype, | |||
2132 | 2185 | ||
2133 | read_lock(&policy_rwlock); | 2186 | read_lock(&policy_rwlock); |
2134 | 2187 | ||
2188 | sclass = unmap_class(orig_sclass); | ||
2189 | |||
2135 | for (genfs = policydb.genfs; genfs; genfs = genfs->next) { | 2190 | for (genfs = policydb.genfs; genfs; genfs = genfs->next) { |
2136 | cmp = strcmp(fstype, genfs->fstype); | 2191 | cmp = strcmp(fstype, genfs->fstype); |
2137 | if (cmp <= 0) | 2192 | if (cmp <= 0) |
@@ -2377,7 +2432,7 @@ int security_sid_mls_copy(u32 sid, u32 mls_sid, u32 *new_sid) | |||
2377 | u32 len; | 2432 | u32 len; |
2378 | int rc = 0; | 2433 | int rc = 0; |
2379 | 2434 | ||
2380 | if (!ss_initialized || !selinux_mls_enabled) { | 2435 | if (!ss_initialized || !policydb.mls_enabled) { |
2381 | *new_sid = sid; | 2436 | *new_sid = sid; |
2382 | goto out; | 2437 | goto out; |
2383 | } | 2438 | } |
@@ -2478,7 +2533,7 @@ int security_net_peersid_resolve(u32 nlbl_sid, u32 nlbl_type, | |||
2478 | /* we don't need to check ss_initialized here since the only way both | 2533 | /* we don't need to check ss_initialized here since the only way both |
2479 | * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the | 2534 | * nlbl_sid and xfrm_sid are not equal to SECSID_NULL would be if the |
2480 | * security server was initialized and ss_initialized was true */ | 2535 | * security server was initialized and ss_initialized was true */ |
2481 | if (!selinux_mls_enabled) { | 2536 | if (!policydb.mls_enabled) { |
2482 | *peer_sid = SECSID_NULL; | 2537 | *peer_sid = SECSID_NULL; |
2483 | return 0; | 2538 | return 0; |
2484 | } | 2539 | } |
@@ -2535,7 +2590,7 @@ int security_get_classes(char ***classes, int *nclasses) | |||
2535 | read_lock(&policy_rwlock); | 2590 | read_lock(&policy_rwlock); |
2536 | 2591 | ||
2537 | *nclasses = policydb.p_classes.nprim; | 2592 | *nclasses = policydb.p_classes.nprim; |
2538 | *classes = kcalloc(*nclasses, sizeof(*classes), GFP_ATOMIC); | 2593 | *classes = kcalloc(*nclasses, sizeof(**classes), GFP_ATOMIC); |
2539 | if (!*classes) | 2594 | if (!*classes) |
2540 | goto out; | 2595 | goto out; |
2541 | 2596 | ||
@@ -2582,7 +2637,7 @@ int security_get_permissions(char *class, char ***perms, int *nperms) | |||
2582 | } | 2637 | } |
2583 | 2638 | ||
2584 | *nperms = match->permissions.nprim; | 2639 | *nperms = match->permissions.nprim; |
2585 | *perms = kcalloc(*nperms, sizeof(*perms), GFP_ATOMIC); | 2640 | *perms = kcalloc(*nperms, sizeof(**perms), GFP_ATOMIC); |
2586 | if (!*perms) | 2641 | if (!*perms) |
2587 | goto out; | 2642 | goto out; |
2588 | 2643 | ||
diff --git a/security/selinux/ss/symtab.c b/security/selinux/ss/symtab.c index 837658a98a54..bcf9f620426e 100644 --- a/security/selinux/ss/symtab.c +++ b/security/selinux/ss/symtab.c | |||
@@ -4,7 +4,6 @@ | |||
4 | * Author : Stephen Smalley, <sds@epoch.ncsc.mil> | 4 | * Author : Stephen Smalley, <sds@epoch.ncsc.mil> |
5 | */ | 5 | */ |
6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
7 | #include <linux/slab.h> | ||
8 | #include <linux/string.h> | 7 | #include <linux/string.h> |
9 | #include <linux/errno.h> | 8 | #include <linux/errno.h> |
10 | #include "symtab.h" | 9 | #include "symtab.h" |
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index f3cb9ed731a9..fff78d3b51a2 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/netfilter.h> | 38 | #include <linux/netfilter.h> |
39 | #include <linux/netfilter_ipv4.h> | 39 | #include <linux/netfilter_ipv4.h> |
40 | #include <linux/netfilter_ipv6.h> | 40 | #include <linux/netfilter_ipv6.h> |
41 | #include <linux/slab.h> | ||
41 | #include <linux/ip.h> | 42 | #include <linux/ip.h> |
42 | #include <linux/tcp.h> | 43 | #include <linux/tcp.h> |
43 | #include <linux/skbuff.h> | 44 | #include <linux/skbuff.h> |
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 0f9ac8146900..f4fac64c4da8 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
@@ -11,6 +11,7 @@ | |||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include <linux/types.h> | 13 | #include <linux/types.h> |
14 | #include <linux/slab.h> | ||
14 | #include <linux/fs.h> | 15 | #include <linux/fs.h> |
15 | #include <linux/sched.h> | 16 | #include <linux/sched.h> |
16 | #include "smack.h" | 17 | #include "smack.h" |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index c33b6bb9b6dd..fdfeaa2f28ec 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/ip.h> | 25 | #include <linux/ip.h> |
26 | #include <linux/tcp.h> | 26 | #include <linux/tcp.h> |
27 | #include <linux/udp.h> | 27 | #include <linux/udp.h> |
28 | #include <linux/slab.h> | ||
28 | #include <linux/mutex.h> | 29 | #include <linux/mutex.h> |
29 | #include <linux/pipe_fs_i.h> | 30 | #include <linux/pipe_fs_i.h> |
30 | #include <net/netlabel.h> | 31 | #include <net/netlabel.h> |
@@ -157,12 +158,12 @@ static int smack_ptrace_traceme(struct task_struct *ptp) | |||
157 | * | 158 | * |
158 | * Returns 0 on success, error code otherwise. | 159 | * Returns 0 on success, error code otherwise. |
159 | */ | 160 | */ |
160 | static int smack_syslog(int type) | 161 | static int smack_syslog(int type, bool from_file) |
161 | { | 162 | { |
162 | int rc; | 163 | int rc; |
163 | char *sp = current_security(); | 164 | char *sp = current_security(); |
164 | 165 | ||
165 | rc = cap_syslog(type); | 166 | rc = cap_syslog(type, from_file); |
166 | if (rc != 0) | 167 | if (rc != 0) |
167 | return rc; | 168 | return rc; |
168 | 169 | ||
@@ -387,7 +388,7 @@ static int smack_sb_umount(struct vfsmount *mnt, int flags) | |||
387 | struct smk_audit_info ad; | 388 | struct smk_audit_info ad; |
388 | 389 | ||
389 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); | 390 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_FS); |
390 | smk_ad_setfield_u_fs_path_dentry(&ad, mnt->mnt_mountpoint); | 391 | smk_ad_setfield_u_fs_path_dentry(&ad, mnt->mnt_root); |
391 | smk_ad_setfield_u_fs_path_mnt(&ad, mnt); | 392 | smk_ad_setfield_u_fs_path_mnt(&ad, mnt); |
392 | 393 | ||
393 | sbp = mnt->mnt_sb->s_security; | 394 | sbp = mnt->mnt_sb->s_security; |
@@ -2602,7 +2603,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
2602 | #ifdef CONFIG_AUDIT | 2603 | #ifdef CONFIG_AUDIT |
2603 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); | 2604 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); |
2604 | ad.a.u.net.family = sk->sk_family; | 2605 | ad.a.u.net.family = sk->sk_family; |
2605 | ad.a.u.net.netif = skb->iif; | 2606 | ad.a.u.net.netif = skb->skb_iif; |
2606 | ipv4_skb_to_auditdata(skb, &ad.a, NULL); | 2607 | ipv4_skb_to_auditdata(skb, &ad.a, NULL); |
2607 | #endif | 2608 | #endif |
2608 | /* | 2609 | /* |
@@ -2757,7 +2758,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
2757 | #ifdef CONFIG_AUDIT | 2758 | #ifdef CONFIG_AUDIT |
2758 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); | 2759 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); |
2759 | ad.a.u.net.family = family; | 2760 | ad.a.u.net.family = family; |
2760 | ad.a.u.net.netif = skb->iif; | 2761 | ad.a.u.net.netif = skb->skb_iif; |
2761 | ipv4_skb_to_auditdata(skb, &ad.a, NULL); | 2762 | ipv4_skb_to_auditdata(skb, &ad.a, NULL); |
2762 | #endif | 2763 | #endif |
2763 | /* | 2764 | /* |
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index aeead7585093..a2b72d77f926 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/vmalloc.h> | 20 | #include <linux/vmalloc.h> |
21 | #include <linux/security.h> | 21 | #include <linux/security.h> |
22 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
23 | #include <linux/slab.h> | ||
23 | #include <net/net_namespace.h> | 24 | #include <net/net_namespace.h> |
24 | #include <net/netlabel.h> | 25 | #include <net/netlabel.h> |
25 | #include <net/cipso_ipv4.h> | 26 | #include <net/cipso_ipv4.h> |
diff --git a/security/tomoyo/Makefile b/security/tomoyo/Makefile index 10ccd686b290..60a9e2002da1 100644 --- a/security/tomoyo/Makefile +++ b/security/tomoyo/Makefile | |||
@@ -1 +1 @@ | |||
obj-y = common.o realpath.o tomoyo.o domain.o file.o | obj-y = common.o realpath.o tomoyo.o domain.o file.o gc.o | ||
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 3c8bd8ee0b95..975c45d88baa 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -10,11 +10,13 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include <linux/uaccess.h> | 12 | #include <linux/uaccess.h> |
13 | #include <linux/slab.h> | ||
13 | #include <linux/security.h> | 14 | #include <linux/security.h> |
14 | #include <linux/hardirq.h> | 15 | #include <linux/hardirq.h> |
15 | #include "realpath.h" | ||
16 | #include "common.h" | 16 | #include "common.h" |
17 | #include "tomoyo.h" | 17 | |
18 | /* Lock for protecting policy. */ | ||
19 | DEFINE_MUTEX(tomoyo_policy_lock); | ||
18 | 20 | ||
19 | /* Has loading policy done? */ | 21 | /* Has loading policy done? */ |
20 | bool tomoyo_policy_loaded; | 22 | bool tomoyo_policy_loaded; |
@@ -178,20 +180,19 @@ static void tomoyo_normalize_line(unsigned char *buffer) | |||
178 | * 1 = must / -1 = must not / 0 = don't care | 180 | * 1 = must / -1 = must not / 0 = don't care |
179 | * @end_type: Should the pathname end with '/'? | 181 | * @end_type: Should the pathname end with '/'? |
180 | * 1 = must / -1 = must not / 0 = don't care | 182 | * 1 = must / -1 = must not / 0 = don't care |
181 | * @function: The name of function calling me. | ||
182 | * | 183 | * |
183 | * Check whether the given filename follows the naming rules. | 184 | * Check whether the given filename follows the naming rules. |
184 | * Returns true if @filename follows the naming rules, false otherwise. | 185 | * Returns true if @filename follows the naming rules, false otherwise. |
185 | */ | 186 | */ |
186 | bool tomoyo_is_correct_path(const char *filename, const s8 start_type, | 187 | bool tomoyo_is_correct_path(const char *filename, const s8 start_type, |
187 | const s8 pattern_type, const s8 end_type, | 188 | const s8 pattern_type, const s8 end_type) |
188 | const char *function) | ||
189 | { | 189 | { |
190 | const char *const start = filename; | ||
191 | bool in_repetition = false; | ||
190 | bool contains_pattern = false; | 192 | bool contains_pattern = false; |
191 | unsigned char c; | 193 | unsigned char c; |
192 | unsigned char d; | 194 | unsigned char d; |
193 | unsigned char e; | 195 | unsigned char e; |
194 | const char *original_filename = filename; | ||
195 | 196 | ||
196 | if (!filename) | 197 | if (!filename) |
197 | goto out; | 198 | goto out; |
@@ -212,9 +213,13 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, | |||
212 | if (c == '/') | 213 | if (c == '/') |
213 | goto out; | 214 | goto out; |
214 | } | 215 | } |
215 | while ((c = *filename++) != '\0') { | 216 | while (1) { |
217 | c = *filename++; | ||
218 | if (!c) | ||
219 | break; | ||
216 | if (c == '\\') { | 220 | if (c == '\\') { |
217 | switch ((c = *filename++)) { | 221 | c = *filename++; |
222 | switch (c) { | ||
218 | case '\\': /* "\\" */ | 223 | case '\\': /* "\\" */ |
219 | continue; | 224 | continue; |
220 | case '$': /* "\$" */ | 225 | case '$': /* "\$" */ |
@@ -231,6 +236,22 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, | |||
231 | break; /* Must not contain pattern */ | 236 | break; /* Must not contain pattern */ |
232 | contains_pattern = true; | 237 | contains_pattern = true; |
233 | continue; | 238 | continue; |
239 | case '{': /* "/\{" */ | ||
240 | if (filename - 3 < start || | ||
241 | *(filename - 3) != '/') | ||
242 | break; | ||
243 | if (pattern_type == -1) | ||
244 | break; /* Must not contain pattern */ | ||
245 | contains_pattern = true; | ||
246 | in_repetition = true; | ||
247 | continue; | ||
248 | case '}': /* "\}/" */ | ||
249 | if (*filename != '/') | ||
250 | break; | ||
251 | if (!in_repetition) | ||
252 | break; | ||
253 | in_repetition = false; | ||
254 | continue; | ||
234 | case '0': /* "\ooo" */ | 255 | case '0': /* "\ooo" */ |
235 | case '1': | 256 | case '1': |
236 | case '2': | 257 | case '2': |
@@ -246,6 +267,8 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, | |||
246 | continue; /* pattern is not \000 */ | 267 | continue; /* pattern is not \000 */ |
247 | } | 268 | } |
248 | goto out; | 269 | goto out; |
270 | } else if (in_repetition && c == '/') { | ||
271 | goto out; | ||
249 | } else if (tomoyo_is_invalid(c)) { | 272 | } else if (tomoyo_is_invalid(c)) { |
250 | goto out; | 273 | goto out; |
251 | } | 274 | } |
@@ -254,27 +277,24 @@ bool tomoyo_is_correct_path(const char *filename, const s8 start_type, | |||
254 | if (!contains_pattern) | 277 | if (!contains_pattern) |
255 | goto out; | 278 | goto out; |
256 | } | 279 | } |
280 | if (in_repetition) | ||
281 | goto out; | ||
257 | return true; | 282 | return true; |
258 | out: | 283 | out: |
259 | printk(KERN_DEBUG "%s: Invalid pathname '%s'\n", function, | ||
260 | original_filename); | ||
261 | return false; | 284 | return false; |
262 | } | 285 | } |
263 | 286 | ||
264 | /** | 287 | /** |
265 | * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules. | 288 | * tomoyo_is_correct_domain - Check whether the given domainname follows the naming rules. |
266 | * @domainname: The domainname to check. | 289 | * @domainname: The domainname to check. |
267 | * @function: The name of function calling me. | ||
268 | * | 290 | * |
269 | * Returns true if @domainname follows the naming rules, false otherwise. | 291 | * Returns true if @domainname follows the naming rules, false otherwise. |
270 | */ | 292 | */ |
271 | bool tomoyo_is_correct_domain(const unsigned char *domainname, | 293 | bool tomoyo_is_correct_domain(const unsigned char *domainname) |
272 | const char *function) | ||
273 | { | 294 | { |
274 | unsigned char c; | 295 | unsigned char c; |
275 | unsigned char d; | 296 | unsigned char d; |
276 | unsigned char e; | 297 | unsigned char e; |
277 | const char *org_domainname = domainname; | ||
278 | 298 | ||
279 | if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME, | 299 | if (!domainname || strncmp(domainname, TOMOYO_ROOT_NAME, |
280 | TOMOYO_ROOT_NAME_LEN)) | 300 | TOMOYO_ROOT_NAME_LEN)) |
@@ -317,8 +337,6 @@ bool tomoyo_is_correct_domain(const unsigned char *domainname, | |||
317 | } while (*domainname); | 337 | } while (*domainname); |
318 | return true; | 338 | return true; |
319 | out: | 339 | out: |
320 | printk(KERN_DEBUG "%s: Invalid domainname '%s'\n", function, | ||
321 | org_domainname); | ||
322 | return false; | 340 | return false; |
323 | } | 341 | } |
324 | 342 | ||
@@ -339,10 +357,9 @@ bool tomoyo_is_domain_def(const unsigned char *buffer) | |||
339 | * | 357 | * |
340 | * @domainname: The domainname to find. | 358 | * @domainname: The domainname to find. |
341 | * | 359 | * |
342 | * Caller must call down_read(&tomoyo_domain_list_lock); or | ||
343 | * down_write(&tomoyo_domain_list_lock); . | ||
344 | * | ||
345 | * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise. | 360 | * Returns pointer to "struct tomoyo_domain_info" if found, NULL otherwise. |
361 | * | ||
362 | * Caller holds tomoyo_read_lock(). | ||
346 | */ | 363 | */ |
347 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname) | 364 | struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname) |
348 | { | 365 | { |
@@ -351,7 +368,7 @@ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname) | |||
351 | 368 | ||
352 | name.name = domainname; | 369 | name.name = domainname; |
353 | tomoyo_fill_path_info(&name); | 370 | tomoyo_fill_path_info(&name); |
354 | list_for_each_entry(domain, &tomoyo_domain_list, list) { | 371 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { |
355 | if (!domain->is_deleted && | 372 | if (!domain->is_deleted && |
356 | !tomoyo_pathcmp(&name, domain->domainname)) | 373 | !tomoyo_pathcmp(&name, domain->domainname)) |
357 | return domain; | 374 | return domain; |
@@ -360,33 +377,6 @@ struct tomoyo_domain_info *tomoyo_find_domain(const char *domainname) | |||
360 | } | 377 | } |
361 | 378 | ||
362 | /** | 379 | /** |
363 | * tomoyo_path_depth - Evaluate the number of '/' in a string. | ||
364 | * | ||
365 | * @pathname: The string to evaluate. | ||
366 | * | ||
367 | * Returns path depth of the string. | ||
368 | * | ||
369 | * I score 2 for each of the '/' in the @pathname | ||
370 | * and score 1 if the @pathname ends with '/'. | ||
371 | */ | ||
372 | static int tomoyo_path_depth(const char *pathname) | ||
373 | { | ||
374 | int i = 0; | ||
375 | |||
376 | if (pathname) { | ||
377 | const char *ep = pathname + strlen(pathname); | ||
378 | if (pathname < ep--) { | ||
379 | if (*ep != '/') | ||
380 | i++; | ||
381 | while (pathname <= ep) | ||
382 | if (*ep-- == '/') | ||
383 | i += 2; | ||
384 | } | ||
385 | } | ||
386 | return i; | ||
387 | } | ||
388 | |||
389 | /** | ||
390 | * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token. | 380 | * tomoyo_const_part_length - Evaluate the initial length without a pattern in a token. |
391 | * | 381 | * |
392 | * @filename: The string to evaluate. | 382 | * @filename: The string to evaluate. |
@@ -444,11 +434,10 @@ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr) | |||
444 | ptr->is_dir = len && (name[len - 1] == '/'); | 434 | ptr->is_dir = len && (name[len - 1] == '/'); |
445 | ptr->is_patterned = (ptr->const_len < len); | 435 | ptr->is_patterned = (ptr->const_len < len); |
446 | ptr->hash = full_name_hash(name, len); | 436 | ptr->hash = full_name_hash(name, len); |
447 | ptr->depth = tomoyo_path_depth(name); | ||
448 | } | 437 | } |
449 | 438 | ||
450 | /** | 439 | /** |
451 | * tomoyo_file_matches_to_pattern2 - Pattern matching without '/' character | 440 | * tomoyo_file_matches_pattern2 - Pattern matching without '/' character |
452 | * and "\-" pattern. | 441 | * and "\-" pattern. |
453 | * | 442 | * |
454 | * @filename: The start of string to check. | 443 | * @filename: The start of string to check. |
@@ -458,10 +447,10 @@ void tomoyo_fill_path_info(struct tomoyo_path_info *ptr) | |||
458 | * | 447 | * |
459 | * Returns true if @filename matches @pattern, false otherwise. | 448 | * Returns true if @filename matches @pattern, false otherwise. |
460 | */ | 449 | */ |
461 | static bool tomoyo_file_matches_to_pattern2(const char *filename, | 450 | static bool tomoyo_file_matches_pattern2(const char *filename, |
462 | const char *filename_end, | 451 | const char *filename_end, |
463 | const char *pattern, | 452 | const char *pattern, |
464 | const char *pattern_end) | 453 | const char *pattern_end) |
465 | { | 454 | { |
466 | while (filename < filename_end && pattern < pattern_end) { | 455 | while (filename < filename_end && pattern < pattern_end) { |
467 | char c; | 456 | char c; |
@@ -519,7 +508,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename, | |||
519 | case '*': | 508 | case '*': |
520 | case '@': | 509 | case '@': |
521 | for (i = 0; i <= filename_end - filename; i++) { | 510 | for (i = 0; i <= filename_end - filename; i++) { |
522 | if (tomoyo_file_matches_to_pattern2( | 511 | if (tomoyo_file_matches_pattern2( |
523 | filename + i, filename_end, | 512 | filename + i, filename_end, |
524 | pattern + 1, pattern_end)) | 513 | pattern + 1, pattern_end)) |
525 | return true; | 514 | return true; |
@@ -550,7 +539,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename, | |||
550 | j++; | 539 | j++; |
551 | } | 540 | } |
552 | for (i = 1; i <= j; i++) { | 541 | for (i = 1; i <= j; i++) { |
553 | if (tomoyo_file_matches_to_pattern2( | 542 | if (tomoyo_file_matches_pattern2( |
554 | filename + i, filename_end, | 543 | filename + i, filename_end, |
555 | pattern + 1, pattern_end)) | 544 | pattern + 1, pattern_end)) |
556 | return true; | 545 | return true; |
@@ -567,7 +556,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename, | |||
567 | } | 556 | } |
568 | 557 | ||
569 | /** | 558 | /** |
570 | * tomoyo_file_matches_to_pattern - Pattern matching without without '/' character. | 559 | * tomoyo_file_matches_pattern - Pattern matching without without '/' character. |
571 | * | 560 | * |
572 | * @filename: The start of string to check. | 561 | * @filename: The start of string to check. |
573 | * @filename_end: The end of string to check. | 562 | * @filename_end: The end of string to check. |
@@ -576,7 +565,7 @@ static bool tomoyo_file_matches_to_pattern2(const char *filename, | |||
576 | * | 565 | * |
577 | * Returns true if @filename matches @pattern, false otherwise. | 566 | * Returns true if @filename matches @pattern, false otherwise. |
578 | */ | 567 | */ |
579 | static bool tomoyo_file_matches_to_pattern(const char *filename, | 568 | static bool tomoyo_file_matches_pattern(const char *filename, |
580 | const char *filename_end, | 569 | const char *filename_end, |
581 | const char *pattern, | 570 | const char *pattern, |
582 | const char *pattern_end) | 571 | const char *pattern_end) |
@@ -589,10 +578,10 @@ static bool tomoyo_file_matches_to_pattern(const char *filename, | |||
589 | /* Split at "\-" pattern. */ | 578 | /* Split at "\-" pattern. */ |
590 | if (*pattern++ != '\\' || *pattern++ != '-') | 579 | if (*pattern++ != '\\' || *pattern++ != '-') |
591 | continue; | 580 | continue; |
592 | result = tomoyo_file_matches_to_pattern2(filename, | 581 | result = tomoyo_file_matches_pattern2(filename, |
593 | filename_end, | 582 | filename_end, |
594 | pattern_start, | 583 | pattern_start, |
595 | pattern - 2); | 584 | pattern - 2); |
596 | if (first) | 585 | if (first) |
597 | result = !result; | 586 | result = !result; |
598 | if (result) | 587 | if (result) |
@@ -600,13 +589,79 @@ static bool tomoyo_file_matches_to_pattern(const char *filename, | |||
600 | first = false; | 589 | first = false; |
601 | pattern_start = pattern; | 590 | pattern_start = pattern; |
602 | } | 591 | } |
603 | result = tomoyo_file_matches_to_pattern2(filename, filename_end, | 592 | result = tomoyo_file_matches_pattern2(filename, filename_end, |
604 | pattern_start, pattern_end); | 593 | pattern_start, pattern_end); |
605 | return first ? result : !result; | 594 | return first ? result : !result; |
606 | } | 595 | } |
607 | 596 | ||
608 | /** | 597 | /** |
598 | * tomoyo_path_matches_pattern2 - Do pathname pattern matching. | ||
599 | * | ||
600 | * @f: The start of string to check. | ||
601 | * @p: The start of pattern to compare. | ||
602 | * | ||
603 | * Returns true if @f matches @p, false otherwise. | ||
604 | */ | ||
605 | static bool tomoyo_path_matches_pattern2(const char *f, const char *p) | ||
606 | { | ||
607 | const char *f_delimiter; | ||
608 | const char *p_delimiter; | ||
609 | |||
610 | while (*f && *p) { | ||
611 | f_delimiter = strchr(f, '/'); | ||
612 | if (!f_delimiter) | ||
613 | f_delimiter = f + strlen(f); | ||
614 | p_delimiter = strchr(p, '/'); | ||
615 | if (!p_delimiter) | ||
616 | p_delimiter = p + strlen(p); | ||
617 | if (*p == '\\' && *(p + 1) == '{') | ||
618 | goto recursive; | ||
619 | if (!tomoyo_file_matches_pattern(f, f_delimiter, p, | ||
620 | p_delimiter)) | ||
621 | return false; | ||
622 | f = f_delimiter; | ||
623 | if (*f) | ||
624 | f++; | ||
625 | p = p_delimiter; | ||
626 | if (*p) | ||
627 | p++; | ||
628 | } | ||
629 | /* Ignore trailing "\*" and "\@" in @pattern. */ | ||
630 | while (*p == '\\' && | ||
631 | (*(p + 1) == '*' || *(p + 1) == '@')) | ||
632 | p += 2; | ||
633 | return !*f && !*p; | ||
634 | recursive: | ||
635 | /* | ||
636 | * The "\{" pattern is permitted only after '/' character. | ||
637 | * This guarantees that below "*(p - 1)" is safe. | ||
638 | * Also, the "\}" pattern is permitted only before '/' character | ||
639 | * so that "\{" + "\}" pair will not break the "\-" operator. | ||
640 | */ | ||
641 | if (*(p - 1) != '/' || p_delimiter <= p + 3 || *p_delimiter != '/' || | ||
642 | *(p_delimiter - 1) != '}' || *(p_delimiter - 2) != '\\') | ||
643 | return false; /* Bad pattern. */ | ||
644 | do { | ||
645 | /* Compare current component with pattern. */ | ||
646 | if (!tomoyo_file_matches_pattern(f, f_delimiter, p + 2, | ||
647 | p_delimiter - 2)) | ||
648 | break; | ||
649 | /* Proceed to next component. */ | ||
650 | f = f_delimiter; | ||
651 | if (!*f) | ||
652 | break; | ||
653 | f++; | ||
654 | /* Continue comparison. */ | ||
655 | if (tomoyo_path_matches_pattern2(f, p_delimiter + 1)) | ||
656 | return true; | ||
657 | f_delimiter = strchr(f, '/'); | ||
658 | } while (f_delimiter); | ||
659 | return false; /* Not matched. */ | ||
660 | } | ||
661 | |||
662 | /** | ||
609 | * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern. | 663 | * tomoyo_path_matches_pattern - Check whether the given filename matches the given pattern. |
664 | * | ||
610 | * @filename: The filename to check. | 665 | * @filename: The filename to check. |
611 | * @pattern: The pattern to compare. | 666 | * @pattern: The pattern to compare. |
612 | * | 667 | * |
@@ -615,24 +670,24 @@ static bool tomoyo_file_matches_to_pattern(const char *filename, | |||
615 | * The following patterns are available. | 670 | * The following patterns are available. |
616 | * \\ \ itself. | 671 | * \\ \ itself. |
617 | * \ooo Octal representation of a byte. | 672 | * \ooo Octal representation of a byte. |
618 | * \* More than or equals to 0 character other than '/'. | 673 | * \* Zero or more repetitions of characters other than '/'. |
619 | * \@ More than or equals to 0 character other than '/' or '.'. | 674 | * \@ Zero or more repetitions of characters other than '/' or '.'. |
620 | * \? 1 byte character other than '/'. | 675 | * \? 1 byte character other than '/'. |
621 | * \$ More than or equals to 1 decimal digit. | 676 | * \$ One or more repetitions of decimal digits. |
622 | * \+ 1 decimal digit. | 677 | * \+ 1 decimal digit. |
623 | * \X More than or equals to 1 hexadecimal digit. | 678 | * \X One or more repetitions of hexadecimal digits. |
624 | * \x 1 hexadecimal digit. | 679 | * \x 1 hexadecimal digit. |
625 | * \A More than or equals to 1 alphabet character. | 680 | * \A One or more repetitions of alphabet characters. |
626 | * \a 1 alphabet character. | 681 | * \a 1 alphabet character. |
682 | * | ||
627 | * \- Subtraction operator. | 683 | * \- Subtraction operator. |
684 | * | ||
685 | * /\{dir\}/ '/' + 'One or more repetitions of dir/' (e.g. /dir/ /dir/dir/ | ||
686 | * /dir/dir/dir/ ). | ||
628 | */ | 687 | */ |
629 | bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, | 688 | bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, |
630 | const struct tomoyo_path_info *pattern) | 689 | const struct tomoyo_path_info *pattern) |
631 | { | 690 | { |
632 | /* | ||
633 | if (!filename || !pattern) | ||
634 | return false; | ||
635 | */ | ||
636 | const char *f = filename->name; | 691 | const char *f = filename->name; |
637 | const char *p = pattern->name; | 692 | const char *p = pattern->name; |
638 | const int len = pattern->const_len; | 693 | const int len = pattern->const_len; |
@@ -640,37 +695,15 @@ bool tomoyo_path_matches_pattern(const struct tomoyo_path_info *filename, | |||
640 | /* If @pattern doesn't contain pattern, I can use strcmp(). */ | 695 | /* If @pattern doesn't contain pattern, I can use strcmp(). */ |
641 | if (!pattern->is_patterned) | 696 | if (!pattern->is_patterned) |
642 | return !tomoyo_pathcmp(filename, pattern); | 697 | return !tomoyo_pathcmp(filename, pattern); |
643 | /* Dont compare if the number of '/' differs. */ | 698 | /* Don't compare directory and non-directory. */ |
644 | if (filename->depth != pattern->depth) | 699 | if (filename->is_dir != pattern->is_dir) |
645 | return false; | 700 | return false; |
646 | /* Compare the initial length without patterns. */ | 701 | /* Compare the initial length without patterns. */ |
647 | if (strncmp(f, p, len)) | 702 | if (strncmp(f, p, len)) |
648 | return false; | 703 | return false; |
649 | f += len; | 704 | f += len; |
650 | p += len; | 705 | p += len; |
651 | /* Main loop. Compare each directory component. */ | 706 | return tomoyo_path_matches_pattern2(f, p); |
652 | while (*f && *p) { | ||
653 | const char *f_delimiter = strchr(f, '/'); | ||
654 | const char *p_delimiter = strchr(p, '/'); | ||
655 | if (!f_delimiter) | ||
656 | f_delimiter = f + strlen(f); | ||
657 | if (!p_delimiter) | ||
658 | p_delimiter = p + strlen(p); | ||
659 | if (!tomoyo_file_matches_to_pattern(f, f_delimiter, | ||
660 | p, p_delimiter)) | ||
661 | return false; | ||
662 | f = f_delimiter; | ||
663 | if (*f) | ||
664 | f++; | ||
665 | p = p_delimiter; | ||
666 | if (*p) | ||
667 | p++; | ||
668 | } | ||
669 | /* Ignore trailing "\*" and "\@" in @pattern. */ | ||
670 | while (*p == '\\' && | ||
671 | (*(p + 1) == '*' || *(p + 1) == '@')) | ||
672 | p += 2; | ||
673 | return !*f && !*p; | ||
674 | } | 707 | } |
675 | 708 | ||
676 | /** | 709 | /** |
@@ -706,7 +739,7 @@ bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) | |||
706 | * | 739 | * |
707 | * Returns the tomoyo_realpath() of current process on success, NULL otherwise. | 740 | * Returns the tomoyo_realpath() of current process on success, NULL otherwise. |
708 | * | 741 | * |
709 | * This function uses tomoyo_alloc(), so the caller must call tomoyo_free() | 742 | * This function uses kzalloc(), so the caller must call kfree() |
710 | * if this function didn't return NULL. | 743 | * if this function didn't return NULL. |
711 | */ | 744 | */ |
712 | static const char *tomoyo_get_exe(void) | 745 | static const char *tomoyo_get_exe(void) |
@@ -787,6 +820,8 @@ bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain) | |||
787 | * @domain: Pointer to "struct tomoyo_domain_info". | 820 | * @domain: Pointer to "struct tomoyo_domain_info". |
788 | * | 821 | * |
789 | * Returns true if the domain is not exceeded quota, false otherwise. | 822 | * Returns true if the domain is not exceeded quota, false otherwise. |
823 | * | ||
824 | * Caller holds tomoyo_read_lock(). | ||
790 | */ | 825 | */ |
791 | bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) | 826 | bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) |
792 | { | 827 | { |
@@ -795,61 +830,29 @@ bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain) | |||
795 | 830 | ||
796 | if (!domain) | 831 | if (!domain) |
797 | return true; | 832 | return true; |
798 | down_read(&tomoyo_domain_acl_info_list_lock); | 833 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
799 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | 834 | switch (ptr->type) { |
800 | if (ptr->type & TOMOYO_ACL_DELETED) | 835 | struct tomoyo_path_acl *acl; |
801 | continue; | 836 | u32 perm; |
802 | switch (tomoyo_acl_type2(ptr)) { | 837 | u8 i; |
803 | struct tomoyo_single_path_acl_record *acl1; | 838 | case TOMOYO_TYPE_PATH_ACL: |
804 | struct tomoyo_double_path_acl_record *acl2; | 839 | acl = container_of(ptr, struct tomoyo_path_acl, head); |
805 | u16 perm; | 840 | perm = acl->perm | (((u32) acl->perm_high) << 16); |
806 | case TOMOYO_TYPE_SINGLE_PATH_ACL: | 841 | for (i = 0; i < TOMOYO_MAX_PATH_OPERATION; i++) |
807 | acl1 = container_of(ptr, | 842 | if (perm & (1 << i)) |
808 | struct tomoyo_single_path_acl_record, | 843 | count++; |
809 | head); | 844 | if (perm & (1 << TOMOYO_TYPE_READ_WRITE)) |
810 | perm = acl1->perm; | 845 | count -= 2; |
811 | if (perm & (1 << TOMOYO_TYPE_EXECUTE_ACL)) | ||
812 | count++; | ||
813 | if (perm & | ||
814 | ((1 << TOMOYO_TYPE_READ_ACL) | | ||
815 | (1 << TOMOYO_TYPE_WRITE_ACL))) | ||
816 | count++; | ||
817 | if (perm & (1 << TOMOYO_TYPE_CREATE_ACL)) | ||
818 | count++; | ||
819 | if (perm & (1 << TOMOYO_TYPE_UNLINK_ACL)) | ||
820 | count++; | ||
821 | if (perm & (1 << TOMOYO_TYPE_MKDIR_ACL)) | ||
822 | count++; | ||
823 | if (perm & (1 << TOMOYO_TYPE_RMDIR_ACL)) | ||
824 | count++; | ||
825 | if (perm & (1 << TOMOYO_TYPE_MKFIFO_ACL)) | ||
826 | count++; | ||
827 | if (perm & (1 << TOMOYO_TYPE_MKSOCK_ACL)) | ||
828 | count++; | ||
829 | if (perm & (1 << TOMOYO_TYPE_MKBLOCK_ACL)) | ||
830 | count++; | ||
831 | if (perm & (1 << TOMOYO_TYPE_MKCHAR_ACL)) | ||
832 | count++; | ||
833 | if (perm & (1 << TOMOYO_TYPE_TRUNCATE_ACL)) | ||
834 | count++; | ||
835 | if (perm & (1 << TOMOYO_TYPE_SYMLINK_ACL)) | ||
836 | count++; | ||
837 | if (perm & (1 << TOMOYO_TYPE_REWRITE_ACL)) | ||
838 | count++; | ||
839 | break; | 846 | break; |
840 | case TOMOYO_TYPE_DOUBLE_PATH_ACL: | 847 | case TOMOYO_TYPE_PATH2_ACL: |
841 | acl2 = container_of(ptr, | 848 | perm = container_of(ptr, struct tomoyo_path2_acl, head) |
842 | struct tomoyo_double_path_acl_record, | 849 | ->perm; |
843 | head); | 850 | for (i = 0; i < TOMOYO_MAX_PATH2_OPERATION; i++) |
844 | perm = acl2->perm; | 851 | if (perm & (1 << i)) |
845 | if (perm & (1 << TOMOYO_TYPE_LINK_ACL)) | 852 | count++; |
846 | count++; | ||
847 | if (perm & (1 << TOMOYO_TYPE_RENAME_ACL)) | ||
848 | count++; | ||
849 | break; | 853 | break; |
850 | } | 854 | } |
851 | } | 855 | } |
852 | up_read(&tomoyo_domain_acl_info_list_lock); | ||
853 | if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY)) | 856 | if (count < tomoyo_check_flags(domain, TOMOYO_MAX_ACCEPT_ENTRY)) |
854 | return true; | 857 | return true; |
855 | if (!domain->quota_warned) { | 858 | if (!domain->quota_warned) { |
@@ -881,9 +884,12 @@ static struct tomoyo_profile *tomoyo_find_or_assign_new_profile(const unsigned | |||
881 | ptr = tomoyo_profile_ptr[profile]; | 884 | ptr = tomoyo_profile_ptr[profile]; |
882 | if (ptr) | 885 | if (ptr) |
883 | goto ok; | 886 | goto ok; |
884 | ptr = tomoyo_alloc_element(sizeof(*ptr)); | 887 | ptr = kmalloc(sizeof(*ptr), GFP_KERNEL); |
885 | if (!ptr) | 888 | if (!tomoyo_memory_ok(ptr)) { |
889 | kfree(ptr); | ||
890 | ptr = NULL; | ||
886 | goto ok; | 891 | goto ok; |
892 | } | ||
887 | for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) | 893 | for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) |
888 | ptr->value[i] = tomoyo_control_array[i].current_value; | 894 | ptr->value[i] = tomoyo_control_array[i].current_value; |
889 | mb(); /* Avoid out-of-order execution. */ | 895 | mb(); /* Avoid out-of-order execution. */ |
@@ -924,7 +930,9 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head) | |||
924 | return -EINVAL; | 930 | return -EINVAL; |
925 | *cp = '\0'; | 931 | *cp = '\0'; |
926 | if (!strcmp(data, "COMMENT")) { | 932 | if (!strcmp(data, "COMMENT")) { |
927 | profile->comment = tomoyo_save_name(cp + 1); | 933 | const struct tomoyo_path_info *old_comment = profile->comment; |
934 | profile->comment = tomoyo_get_name(cp + 1); | ||
935 | tomoyo_put_name(old_comment); | ||
928 | return 0; | 936 | return 0; |
929 | } | 937 | } |
930 | for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) { | 938 | for (i = 0; i < TOMOYO_MAX_CONTROL_INDEX; i++) { |
@@ -1019,27 +1027,6 @@ static int tomoyo_read_profile(struct tomoyo_io_buffer *head) | |||
1019 | } | 1027 | } |
1020 | 1028 | ||
1021 | /* | 1029 | /* |
1022 | * tomoyo_policy_manager_entry is a structure which is used for holding list of | ||
1023 | * domainnames or programs which are permitted to modify configuration via | ||
1024 | * /sys/kernel/security/tomoyo/ interface. | ||
1025 | * It has following fields. | ||
1026 | * | ||
1027 | * (1) "list" which is linked to tomoyo_policy_manager_list . | ||
1028 | * (2) "manager" is a domainname or a program's pathname. | ||
1029 | * (3) "is_domain" is a bool which is true if "manager" is a domainname, false | ||
1030 | * otherwise. | ||
1031 | * (4) "is_deleted" is a bool which is true if marked as deleted, false | ||
1032 | * otherwise. | ||
1033 | */ | ||
1034 | struct tomoyo_policy_manager_entry { | ||
1035 | struct list_head list; | ||
1036 | /* A path to program or a domainname. */ | ||
1037 | const struct tomoyo_path_info *manager; | ||
1038 | bool is_domain; /* True if manager is a domainname. */ | ||
1039 | bool is_deleted; /* True if this entry is deleted. */ | ||
1040 | }; | ||
1041 | |||
1042 | /* | ||
1043 | * tomoyo_policy_manager_list is used for holding list of domainnames or | 1030 | * tomoyo_policy_manager_list is used for holding list of domainnames or |
1044 | * programs which are permitted to modify configuration via | 1031 | * programs which are permitted to modify configuration via |
1045 | * /sys/kernel/security/tomoyo/ interface. | 1032 | * /sys/kernel/security/tomoyo/ interface. |
@@ -1069,8 +1056,7 @@ struct tomoyo_policy_manager_entry { | |||
1069 | * | 1056 | * |
1070 | * # cat /sys/kernel/security/tomoyo/manager | 1057 | * # cat /sys/kernel/security/tomoyo/manager |
1071 | */ | 1058 | */ |
1072 | static LIST_HEAD(tomoyo_policy_manager_list); | 1059 | LIST_HEAD(tomoyo_policy_manager_list); |
1073 | static DECLARE_RWSEM(tomoyo_policy_manager_list_lock); | ||
1074 | 1060 | ||
1075 | /** | 1061 | /** |
1076 | * tomoyo_update_manager_entry - Add a manager entry. | 1062 | * tomoyo_update_manager_entry - Add a manager entry. |
@@ -1079,48 +1065,50 @@ static DECLARE_RWSEM(tomoyo_policy_manager_list_lock); | |||
1079 | * @is_delete: True if it is a delete request. | 1065 | * @is_delete: True if it is a delete request. |
1080 | * | 1066 | * |
1081 | * Returns 0 on success, negative value otherwise. | 1067 | * Returns 0 on success, negative value otherwise. |
1068 | * | ||
1069 | * Caller holds tomoyo_read_lock(). | ||
1082 | */ | 1070 | */ |
1083 | static int tomoyo_update_manager_entry(const char *manager, | 1071 | static int tomoyo_update_manager_entry(const char *manager, |
1084 | const bool is_delete) | 1072 | const bool is_delete) |
1085 | { | 1073 | { |
1086 | struct tomoyo_policy_manager_entry *new_entry; | 1074 | struct tomoyo_policy_manager_entry *entry = NULL; |
1087 | struct tomoyo_policy_manager_entry *ptr; | 1075 | struct tomoyo_policy_manager_entry *ptr; |
1088 | const struct tomoyo_path_info *saved_manager; | 1076 | const struct tomoyo_path_info *saved_manager; |
1089 | int error = -ENOMEM; | 1077 | int error = is_delete ? -ENOENT : -ENOMEM; |
1090 | bool is_domain = false; | 1078 | bool is_domain = false; |
1091 | 1079 | ||
1092 | if (tomoyo_is_domain_def(manager)) { | 1080 | if (tomoyo_is_domain_def(manager)) { |
1093 | if (!tomoyo_is_correct_domain(manager, __func__)) | 1081 | if (!tomoyo_is_correct_domain(manager)) |
1094 | return -EINVAL; | 1082 | return -EINVAL; |
1095 | is_domain = true; | 1083 | is_domain = true; |
1096 | } else { | 1084 | } else { |
1097 | if (!tomoyo_is_correct_path(manager, 1, -1, -1, __func__)) | 1085 | if (!tomoyo_is_correct_path(manager, 1, -1, -1)) |
1098 | return -EINVAL; | 1086 | return -EINVAL; |
1099 | } | 1087 | } |
1100 | saved_manager = tomoyo_save_name(manager); | 1088 | saved_manager = tomoyo_get_name(manager); |
1101 | if (!saved_manager) | 1089 | if (!saved_manager) |
1102 | return -ENOMEM; | 1090 | return -ENOMEM; |
1103 | down_write(&tomoyo_policy_manager_list_lock); | 1091 | if (!is_delete) |
1104 | list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) { | 1092 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
1093 | mutex_lock(&tomoyo_policy_lock); | ||
1094 | list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { | ||
1105 | if (ptr->manager != saved_manager) | 1095 | if (ptr->manager != saved_manager) |
1106 | continue; | 1096 | continue; |
1107 | ptr->is_deleted = is_delete; | 1097 | ptr->is_deleted = is_delete; |
1108 | error = 0; | 1098 | error = 0; |
1109 | goto out; | 1099 | break; |
1110 | } | 1100 | } |
1111 | if (is_delete) { | 1101 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
1112 | error = -ENOENT; | 1102 | entry->manager = saved_manager; |
1113 | goto out; | 1103 | saved_manager = NULL; |
1104 | entry->is_domain = is_domain; | ||
1105 | list_add_tail_rcu(&entry->list, &tomoyo_policy_manager_list); | ||
1106 | entry = NULL; | ||
1107 | error = 0; | ||
1114 | } | 1108 | } |
1115 | new_entry = tomoyo_alloc_element(sizeof(*new_entry)); | 1109 | mutex_unlock(&tomoyo_policy_lock); |
1116 | if (!new_entry) | 1110 | tomoyo_put_name(saved_manager); |
1117 | goto out; | 1111 | kfree(entry); |
1118 | new_entry->manager = saved_manager; | ||
1119 | new_entry->is_domain = is_domain; | ||
1120 | list_add_tail(&new_entry->list, &tomoyo_policy_manager_list); | ||
1121 | error = 0; | ||
1122 | out: | ||
1123 | up_write(&tomoyo_policy_manager_list_lock); | ||
1124 | return error; | 1112 | return error; |
1125 | } | 1113 | } |
1126 | 1114 | ||
@@ -1130,6 +1118,8 @@ static int tomoyo_update_manager_entry(const char *manager, | |||
1130 | * @head: Pointer to "struct tomoyo_io_buffer". | 1118 | * @head: Pointer to "struct tomoyo_io_buffer". |
1131 | * | 1119 | * |
1132 | * Returns 0 on success, negative value otherwise. | 1120 | * Returns 0 on success, negative value otherwise. |
1121 | * | ||
1122 | * Caller holds tomoyo_read_lock(). | ||
1133 | */ | 1123 | */ |
1134 | static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head) | 1124 | static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head) |
1135 | { | 1125 | { |
@@ -1149,6 +1139,8 @@ static int tomoyo_write_manager_policy(struct tomoyo_io_buffer *head) | |||
1149 | * @head: Pointer to "struct tomoyo_io_buffer". | 1139 | * @head: Pointer to "struct tomoyo_io_buffer". |
1150 | * | 1140 | * |
1151 | * Returns 0. | 1141 | * Returns 0. |
1142 | * | ||
1143 | * Caller holds tomoyo_read_lock(). | ||
1152 | */ | 1144 | */ |
1153 | static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) | 1145 | static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) |
1154 | { | 1146 | { |
@@ -1157,7 +1149,6 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) | |||
1157 | 1149 | ||
1158 | if (head->read_eof) | 1150 | if (head->read_eof) |
1159 | return 0; | 1151 | return 0; |
1160 | down_read(&tomoyo_policy_manager_list_lock); | ||
1161 | list_for_each_cookie(pos, head->read_var2, | 1152 | list_for_each_cookie(pos, head->read_var2, |
1162 | &tomoyo_policy_manager_list) { | 1153 | &tomoyo_policy_manager_list) { |
1163 | struct tomoyo_policy_manager_entry *ptr; | 1154 | struct tomoyo_policy_manager_entry *ptr; |
@@ -1169,7 +1160,6 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) | |||
1169 | if (!done) | 1160 | if (!done) |
1170 | break; | 1161 | break; |
1171 | } | 1162 | } |
1172 | up_read(&tomoyo_policy_manager_list_lock); | ||
1173 | head->read_eof = done; | 1163 | head->read_eof = done; |
1174 | return 0; | 1164 | return 0; |
1175 | } | 1165 | } |
@@ -1179,6 +1169,8 @@ static int tomoyo_read_manager_policy(struct tomoyo_io_buffer *head) | |||
1179 | * | 1169 | * |
1180 | * Returns true if the current process is permitted to modify policy | 1170 | * Returns true if the current process is permitted to modify policy |
1181 | * via /sys/kernel/security/tomoyo/ interface. | 1171 | * via /sys/kernel/security/tomoyo/ interface. |
1172 | * | ||
1173 | * Caller holds tomoyo_read_lock(). | ||
1182 | */ | 1174 | */ |
1183 | static bool tomoyo_is_policy_manager(void) | 1175 | static bool tomoyo_is_policy_manager(void) |
1184 | { | 1176 | { |
@@ -1192,29 +1184,25 @@ static bool tomoyo_is_policy_manager(void) | |||
1192 | return true; | 1184 | return true; |
1193 | if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid)) | 1185 | if (!tomoyo_manage_by_non_root && (task->cred->uid || task->cred->euid)) |
1194 | return false; | 1186 | return false; |
1195 | down_read(&tomoyo_policy_manager_list_lock); | 1187 | list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { |
1196 | list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) { | ||
1197 | if (!ptr->is_deleted && ptr->is_domain | 1188 | if (!ptr->is_deleted && ptr->is_domain |
1198 | && !tomoyo_pathcmp(domainname, ptr->manager)) { | 1189 | && !tomoyo_pathcmp(domainname, ptr->manager)) { |
1199 | found = true; | 1190 | found = true; |
1200 | break; | 1191 | break; |
1201 | } | 1192 | } |
1202 | } | 1193 | } |
1203 | up_read(&tomoyo_policy_manager_list_lock); | ||
1204 | if (found) | 1194 | if (found) |
1205 | return true; | 1195 | return true; |
1206 | exe = tomoyo_get_exe(); | 1196 | exe = tomoyo_get_exe(); |
1207 | if (!exe) | 1197 | if (!exe) |
1208 | return false; | 1198 | return false; |
1209 | down_read(&tomoyo_policy_manager_list_lock); | 1199 | list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, list) { |
1210 | list_for_each_entry(ptr, &tomoyo_policy_manager_list, list) { | ||
1211 | if (!ptr->is_deleted && !ptr->is_domain | 1200 | if (!ptr->is_deleted && !ptr->is_domain |
1212 | && !strcmp(exe, ptr->manager->name)) { | 1201 | && !strcmp(exe, ptr->manager->name)) { |
1213 | found = true; | 1202 | found = true; |
1214 | break; | 1203 | break; |
1215 | } | 1204 | } |
1216 | } | 1205 | } |
1217 | up_read(&tomoyo_policy_manager_list_lock); | ||
1218 | if (!found) { /* Reduce error messages. */ | 1206 | if (!found) { /* Reduce error messages. */ |
1219 | static pid_t last_pid; | 1207 | static pid_t last_pid; |
1220 | const pid_t pid = current->pid; | 1208 | const pid_t pid = current->pid; |
@@ -1224,7 +1212,7 @@ static bool tomoyo_is_policy_manager(void) | |||
1224 | last_pid = pid; | 1212 | last_pid = pid; |
1225 | } | 1213 | } |
1226 | } | 1214 | } |
1227 | tomoyo_free(exe); | 1215 | kfree(exe); |
1228 | return found; | 1216 | return found; |
1229 | } | 1217 | } |
1230 | 1218 | ||
@@ -1235,6 +1223,8 @@ static bool tomoyo_is_policy_manager(void) | |||
1235 | * @data: String to parse. | 1223 | * @data: String to parse. |
1236 | * | 1224 | * |
1237 | * Returns true on success, false otherwise. | 1225 | * Returns true on success, false otherwise. |
1226 | * | ||
1227 | * Caller holds tomoyo_read_lock(). | ||
1238 | */ | 1228 | */ |
1239 | static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, | 1229 | static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, |
1240 | const char *data) | 1230 | const char *data) |
@@ -1244,17 +1234,16 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, | |||
1244 | 1234 | ||
1245 | if (sscanf(data, "pid=%u", &pid) == 1) { | 1235 | if (sscanf(data, "pid=%u", &pid) == 1) { |
1246 | struct task_struct *p; | 1236 | struct task_struct *p; |
1237 | rcu_read_lock(); | ||
1247 | read_lock(&tasklist_lock); | 1238 | read_lock(&tasklist_lock); |
1248 | p = find_task_by_vpid(pid); | 1239 | p = find_task_by_vpid(pid); |
1249 | if (p) | 1240 | if (p) |
1250 | domain = tomoyo_real_domain(p); | 1241 | domain = tomoyo_real_domain(p); |
1251 | read_unlock(&tasklist_lock); | 1242 | read_unlock(&tasklist_lock); |
1243 | rcu_read_unlock(); | ||
1252 | } else if (!strncmp(data, "domain=", 7)) { | 1244 | } else if (!strncmp(data, "domain=", 7)) { |
1253 | if (tomoyo_is_domain_def(data + 7)) { | 1245 | if (tomoyo_is_domain_def(data + 7)) |
1254 | down_read(&tomoyo_domain_list_lock); | ||
1255 | domain = tomoyo_find_domain(data + 7); | 1246 | domain = tomoyo_find_domain(data + 7); |
1256 | up_read(&tomoyo_domain_list_lock); | ||
1257 | } | ||
1258 | } else | 1247 | } else |
1259 | return false; | 1248 | return false; |
1260 | head->write_var1 = domain; | 1249 | head->write_var1 = domain; |
@@ -1268,13 +1257,11 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, | |||
1268 | if (domain) { | 1257 | if (domain) { |
1269 | struct tomoyo_domain_info *d; | 1258 | struct tomoyo_domain_info *d; |
1270 | head->read_var1 = NULL; | 1259 | head->read_var1 = NULL; |
1271 | down_read(&tomoyo_domain_list_lock); | 1260 | list_for_each_entry_rcu(d, &tomoyo_domain_list, list) { |
1272 | list_for_each_entry(d, &tomoyo_domain_list, list) { | ||
1273 | if (d == domain) | 1261 | if (d == domain) |
1274 | break; | 1262 | break; |
1275 | head->read_var1 = &d->list; | 1263 | head->read_var1 = &d->list; |
1276 | } | 1264 | } |
1277 | up_read(&tomoyo_domain_list_lock); | ||
1278 | head->read_var2 = NULL; | 1265 | head->read_var2 = NULL; |
1279 | head->read_bit = 0; | 1266 | head->read_bit = 0; |
1280 | head->read_step = 0; | 1267 | head->read_step = 0; |
@@ -1290,6 +1277,8 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, | |||
1290 | * @domainname: The name of domain. | 1277 | * @domainname: The name of domain. |
1291 | * | 1278 | * |
1292 | * Returns 0. | 1279 | * Returns 0. |
1280 | * | ||
1281 | * Caller holds tomoyo_read_lock(). | ||
1293 | */ | 1282 | */ |
1294 | static int tomoyo_delete_domain(char *domainname) | 1283 | static int tomoyo_delete_domain(char *domainname) |
1295 | { | 1284 | { |
@@ -1298,9 +1287,9 @@ static int tomoyo_delete_domain(char *domainname) | |||
1298 | 1287 | ||
1299 | name.name = domainname; | 1288 | name.name = domainname; |
1300 | tomoyo_fill_path_info(&name); | 1289 | tomoyo_fill_path_info(&name); |
1301 | down_write(&tomoyo_domain_list_lock); | 1290 | mutex_lock(&tomoyo_policy_lock); |
1302 | /* Is there an active domain? */ | 1291 | /* Is there an active domain? */ |
1303 | list_for_each_entry(domain, &tomoyo_domain_list, list) { | 1292 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { |
1304 | /* Never delete tomoyo_kernel_domain */ | 1293 | /* Never delete tomoyo_kernel_domain */ |
1305 | if (domain == &tomoyo_kernel_domain) | 1294 | if (domain == &tomoyo_kernel_domain) |
1306 | continue; | 1295 | continue; |
@@ -1310,7 +1299,7 @@ static int tomoyo_delete_domain(char *domainname) | |||
1310 | domain->is_deleted = true; | 1299 | domain->is_deleted = true; |
1311 | break; | 1300 | break; |
1312 | } | 1301 | } |
1313 | up_write(&tomoyo_domain_list_lock); | 1302 | mutex_unlock(&tomoyo_policy_lock); |
1314 | return 0; | 1303 | return 0; |
1315 | } | 1304 | } |
1316 | 1305 | ||
@@ -1320,6 +1309,8 @@ static int tomoyo_delete_domain(char *domainname) | |||
1320 | * @head: Pointer to "struct tomoyo_io_buffer". | 1309 | * @head: Pointer to "struct tomoyo_io_buffer". |
1321 | * | 1310 | * |
1322 | * Returns 0 on success, negative value otherwise. | 1311 | * Returns 0 on success, negative value otherwise. |
1312 | * | ||
1313 | * Caller holds tomoyo_read_lock(). | ||
1323 | */ | 1314 | */ |
1324 | static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) | 1315 | static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) |
1325 | { | 1316 | { |
@@ -1342,11 +1333,9 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) | |||
1342 | domain = NULL; | 1333 | domain = NULL; |
1343 | if (is_delete) | 1334 | if (is_delete) |
1344 | tomoyo_delete_domain(data); | 1335 | tomoyo_delete_domain(data); |
1345 | else if (is_select) { | 1336 | else if (is_select) |
1346 | down_read(&tomoyo_domain_list_lock); | ||
1347 | domain = tomoyo_find_domain(data); | 1337 | domain = tomoyo_find_domain(data); |
1348 | up_read(&tomoyo_domain_list_lock); | 1338 | else |
1349 | } else | ||
1350 | domain = tomoyo_find_or_assign_new_domain(data, 0); | 1339 | domain = tomoyo_find_or_assign_new_domain(data, 0); |
1351 | head->write_var1 = domain; | 1340 | head->write_var1 = domain; |
1352 | return 0; | 1341 | return 0; |
@@ -1361,43 +1350,39 @@ static int tomoyo_write_domain_policy(struct tomoyo_io_buffer *head) | |||
1361 | return 0; | 1350 | return 0; |
1362 | } | 1351 | } |
1363 | if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) { | 1352 | if (!strcmp(data, TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ)) { |
1364 | tomoyo_set_domain_flag(domain, is_delete, | 1353 | domain->ignore_global_allow_read = !is_delete; |
1365 | TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ); | ||
1366 | return 0; | 1354 | return 0; |
1367 | } | 1355 | } |
1368 | return tomoyo_write_file_policy(data, domain, is_delete); | 1356 | return tomoyo_write_file_policy(data, domain, is_delete); |
1369 | } | 1357 | } |
1370 | 1358 | ||
1371 | /** | 1359 | /** |
1372 | * tomoyo_print_single_path_acl - Print a single path ACL entry. | 1360 | * tomoyo_print_path_acl - Print a single path ACL entry. |
1373 | * | 1361 | * |
1374 | * @head: Pointer to "struct tomoyo_io_buffer". | 1362 | * @head: Pointer to "struct tomoyo_io_buffer". |
1375 | * @ptr: Pointer to "struct tomoyo_single_path_acl_record". | 1363 | * @ptr: Pointer to "struct tomoyo_path_acl". |
1376 | * | 1364 | * |
1377 | * Returns true on success, false otherwise. | 1365 | * Returns true on success, false otherwise. |
1378 | */ | 1366 | */ |
1379 | static bool tomoyo_print_single_path_acl(struct tomoyo_io_buffer *head, | 1367 | static bool tomoyo_print_path_acl(struct tomoyo_io_buffer *head, |
1380 | struct tomoyo_single_path_acl_record * | 1368 | struct tomoyo_path_acl *ptr) |
1381 | ptr) | ||
1382 | { | 1369 | { |
1383 | int pos; | 1370 | int pos; |
1384 | u8 bit; | 1371 | u8 bit; |
1385 | const char *atmark = ""; | 1372 | const char *atmark = ""; |
1386 | const char *filename; | 1373 | const char *filename; |
1387 | const u16 perm = ptr->perm; | 1374 | const u32 perm = ptr->perm | (((u32) ptr->perm_high) << 16); |
1388 | 1375 | ||
1389 | filename = ptr->filename->name; | 1376 | filename = ptr->filename->name; |
1390 | for (bit = head->read_bit; bit < TOMOYO_MAX_SINGLE_PATH_OPERATION; | 1377 | for (bit = head->read_bit; bit < TOMOYO_MAX_PATH_OPERATION; bit++) { |
1391 | bit++) { | ||
1392 | const char *msg; | 1378 | const char *msg; |
1393 | if (!(perm & (1 << bit))) | 1379 | if (!(perm & (1 << bit))) |
1394 | continue; | 1380 | continue; |
1395 | /* Print "read/write" instead of "read" and "write". */ | 1381 | /* Print "read/write" instead of "read" and "write". */ |
1396 | if ((bit == TOMOYO_TYPE_READ_ACL || | 1382 | if ((bit == TOMOYO_TYPE_READ || bit == TOMOYO_TYPE_WRITE) |
1397 | bit == TOMOYO_TYPE_WRITE_ACL) | 1383 | && (perm & (1 << TOMOYO_TYPE_READ_WRITE))) |
1398 | && (perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))) | ||
1399 | continue; | 1384 | continue; |
1400 | msg = tomoyo_sp2keyword(bit); | 1385 | msg = tomoyo_path2keyword(bit); |
1401 | pos = head->read_avail; | 1386 | pos = head->read_avail; |
1402 | if (!tomoyo_io_printf(head, "allow_%s %s%s\n", msg, | 1387 | if (!tomoyo_io_printf(head, "allow_%s %s%s\n", msg, |
1403 | atmark, filename)) | 1388 | atmark, filename)) |
@@ -1412,16 +1397,15 @@ static bool tomoyo_print_single_path_acl(struct tomoyo_io_buffer *head, | |||
1412 | } | 1397 | } |
1413 | 1398 | ||
1414 | /** | 1399 | /** |
1415 | * tomoyo_print_double_path_acl - Print a double path ACL entry. | 1400 | * tomoyo_print_path2_acl - Print a double path ACL entry. |
1416 | * | 1401 | * |
1417 | * @head: Pointer to "struct tomoyo_io_buffer". | 1402 | * @head: Pointer to "struct tomoyo_io_buffer". |
1418 | * @ptr: Pointer to "struct tomoyo_double_path_acl_record". | 1403 | * @ptr: Pointer to "struct tomoyo_path2_acl". |
1419 | * | 1404 | * |
1420 | * Returns true on success, false otherwise. | 1405 | * Returns true on success, false otherwise. |
1421 | */ | 1406 | */ |
1422 | static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head, | 1407 | static bool tomoyo_print_path2_acl(struct tomoyo_io_buffer *head, |
1423 | struct tomoyo_double_path_acl_record * | 1408 | struct tomoyo_path2_acl *ptr) |
1424 | ptr) | ||
1425 | { | 1409 | { |
1426 | int pos; | 1410 | int pos; |
1427 | const char *atmark1 = ""; | 1411 | const char *atmark1 = ""; |
@@ -1433,12 +1417,11 @@ static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head, | |||
1433 | 1417 | ||
1434 | filename1 = ptr->filename1->name; | 1418 | filename1 = ptr->filename1->name; |
1435 | filename2 = ptr->filename2->name; | 1419 | filename2 = ptr->filename2->name; |
1436 | for (bit = head->read_bit; bit < TOMOYO_MAX_DOUBLE_PATH_OPERATION; | 1420 | for (bit = head->read_bit; bit < TOMOYO_MAX_PATH2_OPERATION; bit++) { |
1437 | bit++) { | ||
1438 | const char *msg; | 1421 | const char *msg; |
1439 | if (!(perm & (1 << bit))) | 1422 | if (!(perm & (1 << bit))) |
1440 | continue; | 1423 | continue; |
1441 | msg = tomoyo_dp2keyword(bit); | 1424 | msg = tomoyo_path22keyword(bit); |
1442 | pos = head->read_avail; | 1425 | pos = head->read_avail; |
1443 | if (!tomoyo_io_printf(head, "allow_%s %s%s %s%s\n", msg, | 1426 | if (!tomoyo_io_printf(head, "allow_%s %s%s %s%s\n", msg, |
1444 | atmark1, filename1, atmark2, filename2)) | 1427 | atmark1, filename1, atmark2, filename2)) |
@@ -1463,23 +1446,17 @@ static bool tomoyo_print_double_path_acl(struct tomoyo_io_buffer *head, | |||
1463 | static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, | 1446 | static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, |
1464 | struct tomoyo_acl_info *ptr) | 1447 | struct tomoyo_acl_info *ptr) |
1465 | { | 1448 | { |
1466 | const u8 acl_type = tomoyo_acl_type2(ptr); | 1449 | const u8 acl_type = ptr->type; |
1467 | 1450 | ||
1468 | if (acl_type & TOMOYO_ACL_DELETED) | 1451 | if (acl_type == TOMOYO_TYPE_PATH_ACL) { |
1469 | return true; | 1452 | struct tomoyo_path_acl *acl |
1470 | if (acl_type == TOMOYO_TYPE_SINGLE_PATH_ACL) { | 1453 | = container_of(ptr, struct tomoyo_path_acl, head); |
1471 | struct tomoyo_single_path_acl_record *acl | 1454 | return tomoyo_print_path_acl(head, acl); |
1472 | = container_of(ptr, | ||
1473 | struct tomoyo_single_path_acl_record, | ||
1474 | head); | ||
1475 | return tomoyo_print_single_path_acl(head, acl); | ||
1476 | } | 1455 | } |
1477 | if (acl_type == TOMOYO_TYPE_DOUBLE_PATH_ACL) { | 1456 | if (acl_type == TOMOYO_TYPE_PATH2_ACL) { |
1478 | struct tomoyo_double_path_acl_record *acl | 1457 | struct tomoyo_path2_acl *acl |
1479 | = container_of(ptr, | 1458 | = container_of(ptr, struct tomoyo_path2_acl, head); |
1480 | struct tomoyo_double_path_acl_record, | 1459 | return tomoyo_print_path2_acl(head, acl); |
1481 | head); | ||
1482 | return tomoyo_print_double_path_acl(head, acl); | ||
1483 | } | 1460 | } |
1484 | BUG(); /* This must not happen. */ | 1461 | BUG(); /* This must not happen. */ |
1485 | return false; | 1462 | return false; |
@@ -1491,6 +1468,8 @@ static bool tomoyo_print_entry(struct tomoyo_io_buffer *head, | |||
1491 | * @head: Pointer to "struct tomoyo_io_buffer". | 1468 | * @head: Pointer to "struct tomoyo_io_buffer". |
1492 | * | 1469 | * |
1493 | * Returns 0. | 1470 | * Returns 0. |
1471 | * | ||
1472 | * Caller holds tomoyo_read_lock(). | ||
1494 | */ | 1473 | */ |
1495 | static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head) | 1474 | static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head) |
1496 | { | 1475 | { |
@@ -1502,7 +1481,6 @@ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head) | |||
1502 | return 0; | 1481 | return 0; |
1503 | if (head->read_step == 0) | 1482 | if (head->read_step == 0) |
1504 | head->read_step = 1; | 1483 | head->read_step = 1; |
1505 | down_read(&tomoyo_domain_list_lock); | ||
1506 | list_for_each_cookie(dpos, head->read_var1, &tomoyo_domain_list) { | 1484 | list_for_each_cookie(dpos, head->read_var1, &tomoyo_domain_list) { |
1507 | struct tomoyo_domain_info *domain; | 1485 | struct tomoyo_domain_info *domain; |
1508 | const char *quota_exceeded = ""; | 1486 | const char *quota_exceeded = ""; |
@@ -1516,10 +1494,9 @@ static int tomoyo_read_domain_policy(struct tomoyo_io_buffer *head) | |||
1516 | /* Print domainname and flags. */ | 1494 | /* Print domainname and flags. */ |
1517 | if (domain->quota_warned) | 1495 | if (domain->quota_warned) |
1518 | quota_exceeded = "quota_exceeded\n"; | 1496 | quota_exceeded = "quota_exceeded\n"; |
1519 | if (domain->flags & TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED) | 1497 | if (domain->transition_failed) |
1520 | transition_failed = "transition_failed\n"; | 1498 | transition_failed = "transition_failed\n"; |
1521 | if (domain->flags & | 1499 | if (domain->ignore_global_allow_read) |
1522 | TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) | ||
1523 | ignore_global_allow_read | 1500 | ignore_global_allow_read |
1524 | = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n"; | 1501 | = TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "\n"; |
1525 | done = tomoyo_io_printf(head, "%s\n" TOMOYO_KEYWORD_USE_PROFILE | 1502 | done = tomoyo_io_printf(head, "%s\n" TOMOYO_KEYWORD_USE_PROFILE |
@@ -1535,7 +1512,6 @@ acl_loop: | |||
1535 | if (head->read_step == 3) | 1512 | if (head->read_step == 3) |
1536 | goto tail_mark; | 1513 | goto tail_mark; |
1537 | /* Print ACL entries in the domain. */ | 1514 | /* Print ACL entries in the domain. */ |
1538 | down_read(&tomoyo_domain_acl_info_list_lock); | ||
1539 | list_for_each_cookie(apos, head->read_var2, | 1515 | list_for_each_cookie(apos, head->read_var2, |
1540 | &domain->acl_info_list) { | 1516 | &domain->acl_info_list) { |
1541 | struct tomoyo_acl_info *ptr | 1517 | struct tomoyo_acl_info *ptr |
@@ -1545,7 +1521,6 @@ acl_loop: | |||
1545 | if (!done) | 1521 | if (!done) |
1546 | break; | 1522 | break; |
1547 | } | 1523 | } |
1548 | up_read(&tomoyo_domain_acl_info_list_lock); | ||
1549 | if (!done) | 1524 | if (!done) |
1550 | break; | 1525 | break; |
1551 | head->read_step = 3; | 1526 | head->read_step = 3; |
@@ -1557,7 +1532,6 @@ tail_mark: | |||
1557 | if (head->read_single_domain) | 1532 | if (head->read_single_domain) |
1558 | break; | 1533 | break; |
1559 | } | 1534 | } |
1560 | up_read(&tomoyo_domain_list_lock); | ||
1561 | head->read_eof = done; | 1535 | head->read_eof = done; |
1562 | return 0; | 1536 | return 0; |
1563 | } | 1537 | } |
@@ -1573,6 +1547,8 @@ tail_mark: | |||
1573 | * | 1547 | * |
1574 | * ( echo "select " $domainname; echo "use_profile " $profile ) | | 1548 | * ( echo "select " $domainname; echo "use_profile " $profile ) | |
1575 | * /usr/lib/ccs/loadpolicy -d | 1549 | * /usr/lib/ccs/loadpolicy -d |
1550 | * | ||
1551 | * Caller holds tomoyo_read_lock(). | ||
1576 | */ | 1552 | */ |
1577 | static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head) | 1553 | static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head) |
1578 | { | 1554 | { |
@@ -1584,9 +1560,7 @@ static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head) | |||
1584 | if (!cp) | 1560 | if (!cp) |
1585 | return -EINVAL; | 1561 | return -EINVAL; |
1586 | *cp = '\0'; | 1562 | *cp = '\0'; |
1587 | down_read(&tomoyo_domain_list_lock); | ||
1588 | domain = tomoyo_find_domain(cp + 1); | 1563 | domain = tomoyo_find_domain(cp + 1); |
1589 | up_read(&tomoyo_domain_list_lock); | ||
1590 | if (strict_strtoul(data, 10, &profile)) | 1564 | if (strict_strtoul(data, 10, &profile)) |
1591 | return -EINVAL; | 1565 | return -EINVAL; |
1592 | if (domain && profile < TOMOYO_MAX_PROFILES | 1566 | if (domain && profile < TOMOYO_MAX_PROFILES |
@@ -1608,6 +1582,8 @@ static int tomoyo_write_domain_profile(struct tomoyo_io_buffer *head) | |||
1608 | * awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" ) | 1582 | * awk ' { if ( domainname == "" ) { if ( $1 == "<kernel>" ) |
1609 | * domainname = $0; } else if ( $1 == "use_profile" ) { | 1583 | * domainname = $0; } else if ( $1 == "use_profile" ) { |
1610 | * print $2 " " domainname; domainname = ""; } } ; ' | 1584 | * print $2 " " domainname; domainname = ""; } } ; ' |
1585 | * | ||
1586 | * Caller holds tomoyo_read_lock(). | ||
1611 | */ | 1587 | */ |
1612 | static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head) | 1588 | static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head) |
1613 | { | 1589 | { |
@@ -1616,7 +1592,6 @@ static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head) | |||
1616 | 1592 | ||
1617 | if (head->read_eof) | 1593 | if (head->read_eof) |
1618 | return 0; | 1594 | return 0; |
1619 | down_read(&tomoyo_domain_list_lock); | ||
1620 | list_for_each_cookie(pos, head->read_var1, &tomoyo_domain_list) { | 1595 | list_for_each_cookie(pos, head->read_var1, &tomoyo_domain_list) { |
1621 | struct tomoyo_domain_info *domain; | 1596 | struct tomoyo_domain_info *domain; |
1622 | domain = list_entry(pos, struct tomoyo_domain_info, list); | 1597 | domain = list_entry(pos, struct tomoyo_domain_info, list); |
@@ -1627,7 +1602,6 @@ static int tomoyo_read_domain_profile(struct tomoyo_io_buffer *head) | |||
1627 | if (!done) | 1602 | if (!done) |
1628 | break; | 1603 | break; |
1629 | } | 1604 | } |
1630 | up_read(&tomoyo_domain_list_lock); | ||
1631 | head->read_eof = done; | 1605 | head->read_eof = done; |
1632 | return 0; | 1606 | return 0; |
1633 | } | 1607 | } |
@@ -1665,11 +1639,13 @@ static int tomoyo_read_pid(struct tomoyo_io_buffer *head) | |||
1665 | const int pid = head->read_step; | 1639 | const int pid = head->read_step; |
1666 | struct task_struct *p; | 1640 | struct task_struct *p; |
1667 | struct tomoyo_domain_info *domain = NULL; | 1641 | struct tomoyo_domain_info *domain = NULL; |
1642 | rcu_read_lock(); | ||
1668 | read_lock(&tasklist_lock); | 1643 | read_lock(&tasklist_lock); |
1669 | p = find_task_by_vpid(pid); | 1644 | p = find_task_by_vpid(pid); |
1670 | if (p) | 1645 | if (p) |
1671 | domain = tomoyo_real_domain(p); | 1646 | domain = tomoyo_real_domain(p); |
1672 | read_unlock(&tasklist_lock); | 1647 | read_unlock(&tasklist_lock); |
1648 | rcu_read_unlock(); | ||
1673 | if (domain) | 1649 | if (domain) |
1674 | tomoyo_io_printf(head, "%d %u %s", pid, domain->profile, | 1650 | tomoyo_io_printf(head, "%d %u %s", pid, domain->profile, |
1675 | domain->domainname->name); | 1651 | domain->domainname->name); |
@@ -1684,6 +1660,8 @@ static int tomoyo_read_pid(struct tomoyo_io_buffer *head) | |||
1684 | * @head: Pointer to "struct tomoyo_io_buffer". | 1660 | * @head: Pointer to "struct tomoyo_io_buffer". |
1685 | * | 1661 | * |
1686 | * Returns 0 on success, negative value otherwise. | 1662 | * Returns 0 on success, negative value otherwise. |
1663 | * | ||
1664 | * Caller holds tomoyo_read_lock(). | ||
1687 | */ | 1665 | */ |
1688 | static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) | 1666 | static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) |
1689 | { | 1667 | { |
@@ -1718,6 +1696,8 @@ static int tomoyo_write_exception_policy(struct tomoyo_io_buffer *head) | |||
1718 | * @head: Pointer to "struct tomoyo_io_buffer". | 1696 | * @head: Pointer to "struct tomoyo_io_buffer". |
1719 | * | 1697 | * |
1720 | * Returns 0 on success, -EINVAL otherwise. | 1698 | * Returns 0 on success, -EINVAL otherwise. |
1699 | * | ||
1700 | * Caller holds tomoyo_read_lock(). | ||
1721 | */ | 1701 | */ |
1722 | static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head) | 1702 | static int tomoyo_read_exception_policy(struct tomoyo_io_buffer *head) |
1723 | { | 1703 | { |
@@ -1847,15 +1827,13 @@ void tomoyo_load_policy(const char *filename) | |||
1847 | tomoyo_policy_loaded = true; | 1827 | tomoyo_policy_loaded = true; |
1848 | { /* Check all profiles currently assigned to domains are defined. */ | 1828 | { /* Check all profiles currently assigned to domains are defined. */ |
1849 | struct tomoyo_domain_info *domain; | 1829 | struct tomoyo_domain_info *domain; |
1850 | down_read(&tomoyo_domain_list_lock); | 1830 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { |
1851 | list_for_each_entry(domain, &tomoyo_domain_list, list) { | ||
1852 | const u8 profile = domain->profile; | 1831 | const u8 profile = domain->profile; |
1853 | if (tomoyo_profile_ptr[profile]) | 1832 | if (tomoyo_profile_ptr[profile]) |
1854 | continue; | 1833 | continue; |
1855 | panic("Profile %u (used by '%s') not defined.\n", | 1834 | panic("Profile %u (used by '%s') not defined.\n", |
1856 | profile, domain->domainname->name); | 1835 | profile, domain->domainname->name); |
1857 | } | 1836 | } |
1858 | up_read(&tomoyo_domain_list_lock); | ||
1859 | } | 1837 | } |
1860 | } | 1838 | } |
1861 | 1839 | ||
@@ -1903,10 +1881,12 @@ static int tomoyo_read_self_domain(struct tomoyo_io_buffer *head) | |||
1903 | * @file: Pointer to "struct file". | 1881 | * @file: Pointer to "struct file". |
1904 | * | 1882 | * |
1905 | * Associates policy handler and returns 0 on success, -ENOMEM otherwise. | 1883 | * Associates policy handler and returns 0 on success, -ENOMEM otherwise. |
1884 | * | ||
1885 | * Caller acquires tomoyo_read_lock(). | ||
1906 | */ | 1886 | */ |
1907 | static int tomoyo_open_control(const u8 type, struct file *file) | 1887 | static int tomoyo_open_control(const u8 type, struct file *file) |
1908 | { | 1888 | { |
1909 | struct tomoyo_io_buffer *head = tomoyo_alloc(sizeof(*head)); | 1889 | struct tomoyo_io_buffer *head = kzalloc(sizeof(*head), GFP_KERNEL); |
1910 | 1890 | ||
1911 | if (!head) | 1891 | if (!head) |
1912 | return -ENOMEM; | 1892 | return -ENOMEM; |
@@ -1967,9 +1947,9 @@ static int tomoyo_open_control(const u8 type, struct file *file) | |||
1967 | } else { | 1947 | } else { |
1968 | if (!head->readbuf_size) | 1948 | if (!head->readbuf_size) |
1969 | head->readbuf_size = 4096 * 2; | 1949 | head->readbuf_size = 4096 * 2; |
1970 | head->read_buf = tomoyo_alloc(head->readbuf_size); | 1950 | head->read_buf = kzalloc(head->readbuf_size, GFP_KERNEL); |
1971 | if (!head->read_buf) { | 1951 | if (!head->read_buf) { |
1972 | tomoyo_free(head); | 1952 | kfree(head); |
1973 | return -ENOMEM; | 1953 | return -ENOMEM; |
1974 | } | 1954 | } |
1975 | } | 1955 | } |
@@ -1981,13 +1961,14 @@ static int tomoyo_open_control(const u8 type, struct file *file) | |||
1981 | head->write = NULL; | 1961 | head->write = NULL; |
1982 | } else if (head->write) { | 1962 | } else if (head->write) { |
1983 | head->writebuf_size = 4096 * 2; | 1963 | head->writebuf_size = 4096 * 2; |
1984 | head->write_buf = tomoyo_alloc(head->writebuf_size); | 1964 | head->write_buf = kzalloc(head->writebuf_size, GFP_KERNEL); |
1985 | if (!head->write_buf) { | 1965 | if (!head->write_buf) { |
1986 | tomoyo_free(head->read_buf); | 1966 | kfree(head->read_buf); |
1987 | tomoyo_free(head); | 1967 | kfree(head); |
1988 | return -ENOMEM; | 1968 | return -ENOMEM; |
1989 | } | 1969 | } |
1990 | } | 1970 | } |
1971 | head->reader_idx = tomoyo_read_lock(); | ||
1991 | file->private_data = head; | 1972 | file->private_data = head; |
1992 | /* | 1973 | /* |
1993 | * Call the handler now if the file is | 1974 | * Call the handler now if the file is |
@@ -2009,6 +1990,8 @@ static int tomoyo_open_control(const u8 type, struct file *file) | |||
2009 | * @buffer_len: Size of @buffer. | 1990 | * @buffer_len: Size of @buffer. |
2010 | * | 1991 | * |
2011 | * Returns bytes read on success, negative value otherwise. | 1992 | * Returns bytes read on success, negative value otherwise. |
1993 | * | ||
1994 | * Caller holds tomoyo_read_lock(). | ||
2012 | */ | 1995 | */ |
2013 | static int tomoyo_read_control(struct file *file, char __user *buffer, | 1996 | static int tomoyo_read_control(struct file *file, char __user *buffer, |
2014 | const int buffer_len) | 1997 | const int buffer_len) |
@@ -2052,6 +2035,8 @@ static int tomoyo_read_control(struct file *file, char __user *buffer, | |||
2052 | * @buffer_len: Size of @buffer. | 2035 | * @buffer_len: Size of @buffer. |
2053 | * | 2036 | * |
2054 | * Returns @buffer_len on success, negative value otherwise. | 2037 | * Returns @buffer_len on success, negative value otherwise. |
2038 | * | ||
2039 | * Caller holds tomoyo_read_lock(). | ||
2055 | */ | 2040 | */ |
2056 | static int tomoyo_write_control(struct file *file, const char __user *buffer, | 2041 | static int tomoyo_write_control(struct file *file, const char __user *buffer, |
2057 | const int buffer_len) | 2042 | const int buffer_len) |
@@ -2102,52 +2087,29 @@ static int tomoyo_write_control(struct file *file, const char __user *buffer, | |||
2102 | * @file: Pointer to "struct file". | 2087 | * @file: Pointer to "struct file". |
2103 | * | 2088 | * |
2104 | * Releases memory and returns 0. | 2089 | * Releases memory and returns 0. |
2090 | * | ||
2091 | * Caller looses tomoyo_read_lock(). | ||
2105 | */ | 2092 | */ |
2106 | static int tomoyo_close_control(struct file *file) | 2093 | static int tomoyo_close_control(struct file *file) |
2107 | { | 2094 | { |
2108 | struct tomoyo_io_buffer *head = file->private_data; | 2095 | struct tomoyo_io_buffer *head = file->private_data; |
2096 | const bool is_write = !!head->write_buf; | ||
2109 | 2097 | ||
2098 | tomoyo_read_unlock(head->reader_idx); | ||
2110 | /* Release memory used for policy I/O. */ | 2099 | /* Release memory used for policy I/O. */ |
2111 | tomoyo_free(head->read_buf); | 2100 | kfree(head->read_buf); |
2112 | head->read_buf = NULL; | 2101 | head->read_buf = NULL; |
2113 | tomoyo_free(head->write_buf); | 2102 | kfree(head->write_buf); |
2114 | head->write_buf = NULL; | 2103 | head->write_buf = NULL; |
2115 | tomoyo_free(head); | 2104 | kfree(head); |
2116 | head = NULL; | 2105 | head = NULL; |
2117 | file->private_data = NULL; | 2106 | file->private_data = NULL; |
2107 | if (is_write) | ||
2108 | tomoyo_run_gc(); | ||
2118 | return 0; | 2109 | return 0; |
2119 | } | 2110 | } |
2120 | 2111 | ||
2121 | /** | 2112 | /** |
2122 | * tomoyo_alloc_acl_element - Allocate permanent memory for ACL entry. | ||
2123 | * | ||
2124 | * @acl_type: Type of ACL entry. | ||
2125 | * | ||
2126 | * Returns pointer to the ACL entry on success, NULL otherwise. | ||
2127 | */ | ||
2128 | void *tomoyo_alloc_acl_element(const u8 acl_type) | ||
2129 | { | ||
2130 | int len; | ||
2131 | struct tomoyo_acl_info *ptr; | ||
2132 | |||
2133 | switch (acl_type) { | ||
2134 | case TOMOYO_TYPE_SINGLE_PATH_ACL: | ||
2135 | len = sizeof(struct tomoyo_single_path_acl_record); | ||
2136 | break; | ||
2137 | case TOMOYO_TYPE_DOUBLE_PATH_ACL: | ||
2138 | len = sizeof(struct tomoyo_double_path_acl_record); | ||
2139 | break; | ||
2140 | default: | ||
2141 | return NULL; | ||
2142 | } | ||
2143 | ptr = tomoyo_alloc_element(len); | ||
2144 | if (!ptr) | ||
2145 | return NULL; | ||
2146 | ptr->type = acl_type; | ||
2147 | return ptr; | ||
2148 | } | ||
2149 | |||
2150 | /** | ||
2151 | * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface. | 2113 | * tomoyo_open - open() for /sys/kernel/security/tomoyo/ interface. |
2152 | * | 2114 | * |
2153 | * @inode: Pointer to "struct inode". | 2115 | * @inode: Pointer to "struct inode". |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 31df541911f7..67bd22dd3e68 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -1,12 +1,9 @@ | |||
1 | /* | 1 | /* |
2 | * security/tomoyo/common.h | 2 | * security/tomoyo/common.h |
3 | * | 3 | * |
4 | * Common functions for TOMOYO. | 4 | * Header file for TOMOYO. |
5 | * | ||
6 | * Copyright (C) 2005-2009 NTT DATA CORPORATION | ||
7 | * | ||
8 | * Version: 2.2.0 2009/04/01 | ||
9 | * | 5 | * |
6 | * Copyright (C) 2005-2010 NTT DATA CORPORATION | ||
10 | */ | 7 | */ |
11 | 8 | ||
12 | #ifndef _SECURITY_TOMOYO_COMMON_H | 9 | #ifndef _SECURITY_TOMOYO_COMMON_H |
@@ -22,9 +19,119 @@ | |||
22 | #include <linux/namei.h> | 19 | #include <linux/namei.h> |
23 | #include <linux/mount.h> | 20 | #include <linux/mount.h> |
24 | #include <linux/list.h> | 21 | #include <linux/list.h> |
22 | #include <linux/cred.h> | ||
23 | struct linux_binprm; | ||
24 | |||
25 | /********** Constants definitions. **********/ | ||
26 | |||
27 | /* | ||
28 | * TOMOYO uses this hash only when appending a string into the string | ||
29 | * table. Frequency of appending strings is very low. So we don't need | ||
30 | * large (e.g. 64k) hash size. 256 will be sufficient. | ||
31 | */ | ||
32 | #define TOMOYO_HASH_BITS 8 | ||
33 | #define TOMOYO_MAX_HASH (1u<<TOMOYO_HASH_BITS) | ||
34 | |||
35 | /* | ||
36 | * This is the max length of a token. | ||
37 | * | ||
38 | * A token consists of only ASCII printable characters. | ||
39 | * Non printable characters in a token is represented in \ooo style | ||
40 | * octal string. Thus, \ itself is represented as \\. | ||
41 | */ | ||
42 | #define TOMOYO_MAX_PATHNAME_LEN 4000 | ||
43 | |||
44 | /* Profile number is an integer between 0 and 255. */ | ||
45 | #define TOMOYO_MAX_PROFILES 256 | ||
46 | |||
47 | /* Keywords for ACLs. */ | ||
48 | #define TOMOYO_KEYWORD_ALIAS "alias " | ||
49 | #define TOMOYO_KEYWORD_ALLOW_READ "allow_read " | ||
50 | #define TOMOYO_KEYWORD_DELETE "delete " | ||
51 | #define TOMOYO_KEYWORD_DENY_REWRITE "deny_rewrite " | ||
52 | #define TOMOYO_KEYWORD_FILE_PATTERN "file_pattern " | ||
53 | #define TOMOYO_KEYWORD_INITIALIZE_DOMAIN "initialize_domain " | ||
54 | #define TOMOYO_KEYWORD_KEEP_DOMAIN "keep_domain " | ||
55 | #define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain " | ||
56 | #define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain " | ||
57 | #define TOMOYO_KEYWORD_SELECT "select " | ||
58 | #define TOMOYO_KEYWORD_USE_PROFILE "use_profile " | ||
59 | #define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read" | ||
60 | /* A domain definition starts with <kernel>. */ | ||
61 | #define TOMOYO_ROOT_NAME "<kernel>" | ||
62 | #define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1) | ||
63 | |||
64 | /* Index numbers for Access Controls. */ | ||
65 | enum tomoyo_mac_index { | ||
66 | TOMOYO_MAC_FOR_FILE, /* domain_policy.conf */ | ||
67 | TOMOYO_MAX_ACCEPT_ENTRY, | ||
68 | TOMOYO_VERBOSE, | ||
69 | TOMOYO_MAX_CONTROL_INDEX | ||
70 | }; | ||
71 | |||
72 | /* Index numbers for Access Controls. */ | ||
73 | enum tomoyo_acl_entry_type_index { | ||
74 | TOMOYO_TYPE_PATH_ACL, | ||
75 | TOMOYO_TYPE_PATH2_ACL, | ||
76 | }; | ||
77 | |||
78 | /* Index numbers for File Controls. */ | ||
79 | |||
80 | /* | ||
81 | * TYPE_READ_WRITE_ACL is special. TYPE_READ_WRITE_ACL is automatically set | ||
82 | * if both TYPE_READ_ACL and TYPE_WRITE_ACL are set. Both TYPE_READ_ACL and | ||
83 | * TYPE_WRITE_ACL are automatically set if TYPE_READ_WRITE_ACL is set. | ||
84 | * TYPE_READ_WRITE_ACL is automatically cleared if either TYPE_READ_ACL or | ||
85 | * TYPE_WRITE_ACL is cleared. Both TYPE_READ_ACL and TYPE_WRITE_ACL are | ||
86 | * automatically cleared if TYPE_READ_WRITE_ACL is cleared. | ||
87 | */ | ||
88 | |||
89 | enum tomoyo_path_acl_index { | ||
90 | TOMOYO_TYPE_READ_WRITE, | ||
91 | TOMOYO_TYPE_EXECUTE, | ||
92 | TOMOYO_TYPE_READ, | ||
93 | TOMOYO_TYPE_WRITE, | ||
94 | TOMOYO_TYPE_CREATE, | ||
95 | TOMOYO_TYPE_UNLINK, | ||
96 | TOMOYO_TYPE_MKDIR, | ||
97 | TOMOYO_TYPE_RMDIR, | ||
98 | TOMOYO_TYPE_MKFIFO, | ||
99 | TOMOYO_TYPE_MKSOCK, | ||
100 | TOMOYO_TYPE_MKBLOCK, | ||
101 | TOMOYO_TYPE_MKCHAR, | ||
102 | TOMOYO_TYPE_TRUNCATE, | ||
103 | TOMOYO_TYPE_SYMLINK, | ||
104 | TOMOYO_TYPE_REWRITE, | ||
105 | TOMOYO_TYPE_IOCTL, | ||
106 | TOMOYO_TYPE_CHMOD, | ||
107 | TOMOYO_TYPE_CHOWN, | ||
108 | TOMOYO_TYPE_CHGRP, | ||
109 | TOMOYO_TYPE_CHROOT, | ||
110 | TOMOYO_TYPE_MOUNT, | ||
111 | TOMOYO_TYPE_UMOUNT, | ||
112 | TOMOYO_MAX_PATH_OPERATION | ||
113 | }; | ||
25 | 114 | ||
26 | struct dentry; | 115 | enum tomoyo_path2_acl_index { |
27 | struct vfsmount; | 116 | TOMOYO_TYPE_LINK, |
117 | TOMOYO_TYPE_RENAME, | ||
118 | TOMOYO_TYPE_PIVOT_ROOT, | ||
119 | TOMOYO_MAX_PATH2_OPERATION | ||
120 | }; | ||
121 | |||
122 | enum tomoyo_securityfs_interface_index { | ||
123 | TOMOYO_DOMAINPOLICY, | ||
124 | TOMOYO_EXCEPTIONPOLICY, | ||
125 | TOMOYO_DOMAIN_STATUS, | ||
126 | TOMOYO_PROCESS_STATUS, | ||
127 | TOMOYO_MEMINFO, | ||
128 | TOMOYO_SELFDOMAIN, | ||
129 | TOMOYO_VERSION, | ||
130 | TOMOYO_PROFILE, | ||
131 | TOMOYO_MANAGER | ||
132 | }; | ||
133 | |||
134 | /********** Structure definitions. **********/ | ||
28 | 135 | ||
29 | /* | 136 | /* |
30 | * tomoyo_page_buffer is a structure which is used for holding a pathname | 137 | * tomoyo_page_buffer is a structure which is used for holding a pathname |
@@ -56,9 +163,6 @@ struct tomoyo_page_buffer { | |||
56 | * (5) "is_patterned" is a bool which is true if "name" contains wildcard | 163 | * (5) "is_patterned" is a bool which is true if "name" contains wildcard |
57 | * characters, false otherwise. This allows TOMOYO to use "hash" and | 164 | * characters, false otherwise. This allows TOMOYO to use "hash" and |
58 | * strcmp() for string comparison if "is_patterned" is false. | 165 | * strcmp() for string comparison if "is_patterned" is false. |
59 | * (6) "depth" is calculated using the number of "/" characters in "name". | ||
60 | * This allows TOMOYO to avoid comparing two pathnames which never match | ||
61 | * (e.g. whether "/var/www/html/index.html" matches "/tmp/sh-thd-\$"). | ||
62 | */ | 166 | */ |
63 | struct tomoyo_path_info { | 167 | struct tomoyo_path_info { |
64 | const char *name; | 168 | const char *name; |
@@ -66,17 +170,17 @@ struct tomoyo_path_info { | |||
66 | u16 const_len; /* = tomoyo_const_part_length(name) */ | 170 | u16 const_len; /* = tomoyo_const_part_length(name) */ |
67 | bool is_dir; /* = tomoyo_strendswith(name, "/") */ | 171 | bool is_dir; /* = tomoyo_strendswith(name, "/") */ |
68 | bool is_patterned; /* = tomoyo_path_contains_pattern(name) */ | 172 | bool is_patterned; /* = tomoyo_path_contains_pattern(name) */ |
69 | u16 depth; /* = tomoyo_path_depth(name) */ | ||
70 | }; | 173 | }; |
71 | 174 | ||
72 | /* | 175 | /* |
73 | * This is the max length of a token. | 176 | * tomoyo_name_entry is a structure which is used for linking |
74 | * | 177 | * "struct tomoyo_path_info" into tomoyo_name_list . |
75 | * A token consists of only ASCII printable characters. | ||
76 | * Non printable characters in a token is represented in \ooo style | ||
77 | * octal string. Thus, \ itself is represented as \\. | ||
78 | */ | 178 | */ |
79 | #define TOMOYO_MAX_PATHNAME_LEN 4000 | 179 | struct tomoyo_name_entry { |
180 | struct list_head list; | ||
181 | atomic_t users; | ||
182 | struct tomoyo_path_info entry; | ||
183 | }; | ||
80 | 184 | ||
81 | /* | 185 | /* |
82 | * tomoyo_path_info_with_data is a structure which is used for holding a | 186 | * tomoyo_path_info_with_data is a structure which is used for holding a |
@@ -93,7 +197,7 @@ struct tomoyo_path_info { | |||
93 | * "struct tomoyo_path_info_with_data". | 197 | * "struct tomoyo_path_info_with_data". |
94 | */ | 198 | */ |
95 | struct tomoyo_path_info_with_data { | 199 | struct tomoyo_path_info_with_data { |
96 | /* Keep "head" first, for this pointer is passed to tomoyo_free(). */ | 200 | /* Keep "head" first, for this pointer is passed to kfree(). */ |
97 | struct tomoyo_path_info head; | 201 | struct tomoyo_path_info head; |
98 | char barrier1[16]; /* Safeguard for overrun. */ | 202 | char barrier1[16]; /* Safeguard for overrun. */ |
99 | char body[TOMOYO_MAX_PATHNAME_LEN]; | 203 | char body[TOMOYO_MAX_PATHNAME_LEN]; |
@@ -105,30 +209,19 @@ struct tomoyo_path_info_with_data { | |||
105 | * | 209 | * |
106 | * (1) "list" which is linked to the ->acl_info_list of | 210 | * (1) "list" which is linked to the ->acl_info_list of |
107 | * "struct tomoyo_domain_info" | 211 | * "struct tomoyo_domain_info" |
108 | * (2) "type" which tells | 212 | * (2) "type" which tells type of the entry (either |
109 | * (a) type & 0x7F : type of the entry (either | 213 | * "struct tomoyo_path_acl" or "struct tomoyo_path2_acl"). |
110 | * "struct tomoyo_single_path_acl_record" or | ||
111 | * "struct tomoyo_double_path_acl_record") | ||
112 | * (b) type & 0x80 : whether the entry is marked as "deleted". | ||
113 | * | 214 | * |
114 | * Packing "struct tomoyo_acl_info" allows | 215 | * Packing "struct tomoyo_acl_info" allows |
115 | * "struct tomoyo_single_path_acl_record" to embed "u16" and | 216 | * "struct tomoyo_path_acl" to embed "u8" + "u16" and |
116 | * "struct tomoyo_double_path_acl_record" to embed "u8" | 217 | * "struct tomoyo_path2_acl" to embed "u8" |
117 | * without enlarging their structure size. | 218 | * without enlarging their structure size. |
118 | */ | 219 | */ |
119 | struct tomoyo_acl_info { | 220 | struct tomoyo_acl_info { |
120 | struct list_head list; | 221 | struct list_head list; |
121 | /* | ||
122 | * Type of this ACL entry. | ||
123 | * | ||
124 | * MSB is is_deleted flag. | ||
125 | */ | ||
126 | u8 type; | 222 | u8 type; |
127 | } __packed; | 223 | } __packed; |
128 | 224 | ||
129 | /* This ACL entry is deleted. */ | ||
130 | #define TOMOYO_ACL_DELETED 0x80 | ||
131 | |||
132 | /* | 225 | /* |
133 | * tomoyo_domain_info is a structure which is used for holding permissions | 226 | * tomoyo_domain_info is a structure which is used for holding permissions |
134 | * (e.g. "allow_read /lib/libc-2.5.so") given to each domain. | 227 | * (e.g. "allow_read /lib/libc-2.5.so") given to each domain. |
@@ -142,7 +235,17 @@ struct tomoyo_acl_info { | |||
142 | * "deleted", false otherwise. | 235 | * "deleted", false otherwise. |
143 | * (6) "quota_warned" is a bool which is used for suppressing warning message | 236 | * (6) "quota_warned" is a bool which is used for suppressing warning message |
144 | * when learning mode learned too much entries. | 237 | * when learning mode learned too much entries. |
145 | * (7) "flags" which remembers this domain's attributes. | 238 | * (7) "ignore_global_allow_read" is a bool which is true if this domain |
239 | * should ignore "allow_read" directive in exception policy. | ||
240 | * (8) "transition_failed" is a bool which is set to true when this domain was | ||
241 | * unable to create a new domain at tomoyo_find_next_domain() because the | ||
242 | * name of the domain to be created was too long or it could not allocate | ||
243 | * memory. If set to true, more than one process continued execve() | ||
244 | * without domain transition. | ||
245 | * (9) "users" is an atomic_t that holds how many "struct cred"->security | ||
246 | * are referring this "struct tomoyo_domain_info". If is_deleted == true | ||
247 | * and users == 0, this struct will be kfree()d upon next garbage | ||
248 | * collection. | ||
146 | * | 249 | * |
147 | * A domain's lifecycle is an analogy of files on / directory. | 250 | * A domain's lifecycle is an analogy of files on / directory. |
148 | * Multiple domains with the same domainname cannot be created (as with | 251 | * Multiple domains with the same domainname cannot be created (as with |
@@ -159,25 +262,13 @@ struct tomoyo_domain_info { | |||
159 | u8 profile; /* Profile number to use. */ | 262 | u8 profile; /* Profile number to use. */ |
160 | bool is_deleted; /* Delete flag. */ | 263 | bool is_deleted; /* Delete flag. */ |
161 | bool quota_warned; /* Quota warnning flag. */ | 264 | bool quota_warned; /* Quota warnning flag. */ |
162 | /* DOMAIN_FLAGS_*. Use tomoyo_set_domain_flag() to modify. */ | 265 | bool ignore_global_allow_read; /* Ignore "allow_read" flag. */ |
163 | u8 flags; | 266 | bool transition_failed; /* Domain transition failed flag. */ |
267 | atomic_t users; /* Number of referring credentials. */ | ||
164 | }; | 268 | }; |
165 | 269 | ||
166 | /* Profile number is an integer between 0 and 255. */ | ||
167 | #define TOMOYO_MAX_PROFILES 256 | ||
168 | |||
169 | /* Ignore "allow_read" directive in exception policy. */ | ||
170 | #define TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ 1 | ||
171 | /* | ||
172 | * This domain was unable to create a new domain at tomoyo_find_next_domain() | ||
173 | * because the name of the domain to be created was too long or | ||
174 | * it could not allocate memory. | ||
175 | * More than one process continued execve() without domain transition. | ||
176 | */ | ||
177 | #define TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED 2 | ||
178 | |||
179 | /* | 270 | /* |
180 | * tomoyo_single_path_acl_record is a structure which is used for holding an | 271 | * tomoyo_path_acl is a structure which is used for holding an |
181 | * entry with one pathname operation (e.g. open(), mkdir()). | 272 | * entry with one pathname operation (e.g. open(), mkdir()). |
182 | * It has following fields. | 273 | * It has following fields. |
183 | * | 274 | * |
@@ -188,18 +279,21 @@ struct tomoyo_domain_info { | |||
188 | * Directives held by this structure are "allow_read/write", "allow_execute", | 279 | * Directives held by this structure are "allow_read/write", "allow_execute", |
189 | * "allow_read", "allow_write", "allow_create", "allow_unlink", "allow_mkdir", | 280 | * "allow_read", "allow_write", "allow_create", "allow_unlink", "allow_mkdir", |
190 | * "allow_rmdir", "allow_mkfifo", "allow_mksock", "allow_mkblock", | 281 | * "allow_rmdir", "allow_mkfifo", "allow_mksock", "allow_mkblock", |
191 | * "allow_mkchar", "allow_truncate", "allow_symlink" and "allow_rewrite". | 282 | * "allow_mkchar", "allow_truncate", "allow_symlink", "allow_rewrite", |
283 | * "allow_chmod", "allow_chown", "allow_chgrp", "allow_chroot", "allow_mount" | ||
284 | * and "allow_unmount". | ||
192 | */ | 285 | */ |
193 | struct tomoyo_single_path_acl_record { | 286 | struct tomoyo_path_acl { |
194 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_SINGLE_PATH_ACL */ | 287 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH_ACL */ |
288 | u8 perm_high; | ||
195 | u16 perm; | 289 | u16 perm; |
196 | /* Pointer to single pathname. */ | 290 | /* Pointer to single pathname. */ |
197 | const struct tomoyo_path_info *filename; | 291 | const struct tomoyo_path_info *filename; |
198 | }; | 292 | }; |
199 | 293 | ||
200 | /* | 294 | /* |
201 | * tomoyo_double_path_acl_record is a structure which is used for holding an | 295 | * tomoyo_path2_acl is a structure which is used for holding an |
202 | * entry with two pathnames operation (i.e. link() and rename()). | 296 | * entry with two pathnames operation (i.e. link(), rename() and pivot_root()). |
203 | * It has following fields. | 297 | * It has following fields. |
204 | * | 298 | * |
205 | * (1) "head" which is a "struct tomoyo_acl_info". | 299 | * (1) "head" which is a "struct tomoyo_acl_info". |
@@ -207,10 +301,11 @@ struct tomoyo_single_path_acl_record { | |||
207 | * (3) "filename1" is the source/old pathname. | 301 | * (3) "filename1" is the source/old pathname. |
208 | * (4) "filename2" is the destination/new pathname. | 302 | * (4) "filename2" is the destination/new pathname. |
209 | * | 303 | * |
210 | * Directives held by this structure are "allow_rename" and "allow_link". | 304 | * Directives held by this structure are "allow_rename", "allow_link" and |
305 | * "allow_pivot_root". | ||
211 | */ | 306 | */ |
212 | struct tomoyo_double_path_acl_record { | 307 | struct tomoyo_path2_acl { |
213 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_DOUBLE_PATH_ACL */ | 308 | struct tomoyo_acl_info head; /* type = TOMOYO_TYPE_PATH2_ACL */ |
214 | u8 perm; | 309 | u8 perm; |
215 | /* Pointer to single pathname. */ | 310 | /* Pointer to single pathname. */ |
216 | const struct tomoyo_path_info *filename1; | 311 | const struct tomoyo_path_info *filename1; |
@@ -218,29 +313,6 @@ struct tomoyo_double_path_acl_record { | |||
218 | const struct tomoyo_path_info *filename2; | 313 | const struct tomoyo_path_info *filename2; |
219 | }; | 314 | }; |
220 | 315 | ||
221 | /* Keywords for ACLs. */ | ||
222 | #define TOMOYO_KEYWORD_ALIAS "alias " | ||
223 | #define TOMOYO_KEYWORD_ALLOW_READ "allow_read " | ||
224 | #define TOMOYO_KEYWORD_DELETE "delete " | ||
225 | #define TOMOYO_KEYWORD_DENY_REWRITE "deny_rewrite " | ||
226 | #define TOMOYO_KEYWORD_FILE_PATTERN "file_pattern " | ||
227 | #define TOMOYO_KEYWORD_INITIALIZE_DOMAIN "initialize_domain " | ||
228 | #define TOMOYO_KEYWORD_KEEP_DOMAIN "keep_domain " | ||
229 | #define TOMOYO_KEYWORD_NO_INITIALIZE_DOMAIN "no_initialize_domain " | ||
230 | #define TOMOYO_KEYWORD_NO_KEEP_DOMAIN "no_keep_domain " | ||
231 | #define TOMOYO_KEYWORD_SELECT "select " | ||
232 | #define TOMOYO_KEYWORD_USE_PROFILE "use_profile " | ||
233 | #define TOMOYO_KEYWORD_IGNORE_GLOBAL_ALLOW_READ "ignore_global_allow_read" | ||
234 | /* A domain definition starts with <kernel>. */ | ||
235 | #define TOMOYO_ROOT_NAME "<kernel>" | ||
236 | #define TOMOYO_ROOT_NAME_LEN (sizeof(TOMOYO_ROOT_NAME) - 1) | ||
237 | |||
238 | /* Index numbers for Access Controls. */ | ||
239 | #define TOMOYO_MAC_FOR_FILE 0 /* domain_policy.conf */ | ||
240 | #define TOMOYO_MAX_ACCEPT_ENTRY 1 | ||
241 | #define TOMOYO_VERBOSE 2 | ||
242 | #define TOMOYO_MAX_CONTROL_INDEX 3 | ||
243 | |||
244 | /* | 316 | /* |
245 | * tomoyo_io_buffer is a structure which is used for reading and modifying | 317 | * tomoyo_io_buffer is a structure which is used for reading and modifying |
246 | * configuration via /sys/kernel/security/tomoyo/ interface. | 318 | * configuration via /sys/kernel/security/tomoyo/ interface. |
@@ -269,6 +341,8 @@ struct tomoyo_io_buffer { | |||
269 | int (*write) (struct tomoyo_io_buffer *); | 341 | int (*write) (struct tomoyo_io_buffer *); |
270 | /* Exclusive lock for this structure. */ | 342 | /* Exclusive lock for this structure. */ |
271 | struct mutex io_sem; | 343 | struct mutex io_sem; |
344 | /* Index returned by tomoyo_read_lock(). */ | ||
345 | int reader_idx; | ||
272 | /* The position currently reading from. */ | 346 | /* The position currently reading from. */ |
273 | struct list_head *read_var1; | 347 | struct list_head *read_var1; |
274 | /* Extra variables for reading. */ | 348 | /* Extra variables for reading. */ |
@@ -297,18 +371,159 @@ struct tomoyo_io_buffer { | |||
297 | int writebuf_size; | 371 | int writebuf_size; |
298 | }; | 372 | }; |
299 | 373 | ||
374 | /* | ||
375 | * tomoyo_globally_readable_file_entry is a structure which is used for holding | ||
376 | * "allow_read" entries. | ||
377 | * It has following fields. | ||
378 | * | ||
379 | * (1) "list" which is linked to tomoyo_globally_readable_list . | ||
380 | * (2) "filename" is a pathname which is allowed to open(O_RDONLY). | ||
381 | * (3) "is_deleted" is a bool which is true if marked as deleted, false | ||
382 | * otherwise. | ||
383 | */ | ||
384 | struct tomoyo_globally_readable_file_entry { | ||
385 | struct list_head list; | ||
386 | const struct tomoyo_path_info *filename; | ||
387 | bool is_deleted; | ||
388 | }; | ||
389 | |||
390 | /* | ||
391 | * tomoyo_pattern_entry is a structure which is used for holding | ||
392 | * "tomoyo_pattern_list" entries. | ||
393 | * It has following fields. | ||
394 | * | ||
395 | * (1) "list" which is linked to tomoyo_pattern_list . | ||
396 | * (2) "pattern" is a pathname pattern which is used for converting pathnames | ||
397 | * to pathname patterns during learning mode. | ||
398 | * (3) "is_deleted" is a bool which is true if marked as deleted, false | ||
399 | * otherwise. | ||
400 | */ | ||
401 | struct tomoyo_pattern_entry { | ||
402 | struct list_head list; | ||
403 | const struct tomoyo_path_info *pattern; | ||
404 | bool is_deleted; | ||
405 | }; | ||
406 | |||
407 | /* | ||
408 | * tomoyo_no_rewrite_entry is a structure which is used for holding | ||
409 | * "deny_rewrite" entries. | ||
410 | * It has following fields. | ||
411 | * | ||
412 | * (1) "list" which is linked to tomoyo_no_rewrite_list . | ||
413 | * (2) "pattern" is a pathname which is by default not permitted to modify | ||
414 | * already existing content. | ||
415 | * (3) "is_deleted" is a bool which is true if marked as deleted, false | ||
416 | * otherwise. | ||
417 | */ | ||
418 | struct tomoyo_no_rewrite_entry { | ||
419 | struct list_head list; | ||
420 | const struct tomoyo_path_info *pattern; | ||
421 | bool is_deleted; | ||
422 | }; | ||
423 | |||
424 | /* | ||
425 | * tomoyo_domain_initializer_entry is a structure which is used for holding | ||
426 | * "initialize_domain" and "no_initialize_domain" entries. | ||
427 | * It has following fields. | ||
428 | * | ||
429 | * (1) "list" which is linked to tomoyo_domain_initializer_list . | ||
430 | * (2) "domainname" which is "a domainname" or "the last component of a | ||
431 | * domainname". This field is NULL if "from" clause is not specified. | ||
432 | * (3) "program" which is a program's pathname. | ||
433 | * (4) "is_deleted" is a bool which is true if marked as deleted, false | ||
434 | * otherwise. | ||
435 | * (5) "is_not" is a bool which is true if "no_initialize_domain", false | ||
436 | * otherwise. | ||
437 | * (6) "is_last_name" is a bool which is true if "domainname" is "the last | ||
438 | * component of a domainname", false otherwise. | ||
439 | */ | ||
440 | struct tomoyo_domain_initializer_entry { | ||
441 | struct list_head list; | ||
442 | const struct tomoyo_path_info *domainname; /* This may be NULL */ | ||
443 | const struct tomoyo_path_info *program; | ||
444 | bool is_deleted; | ||
445 | bool is_not; /* True if this entry is "no_initialize_domain". */ | ||
446 | /* True if the domainname is tomoyo_get_last_name(). */ | ||
447 | bool is_last_name; | ||
448 | }; | ||
449 | |||
450 | /* | ||
451 | * tomoyo_domain_keeper_entry is a structure which is used for holding | ||
452 | * "keep_domain" and "no_keep_domain" entries. | ||
453 | * It has following fields. | ||
454 | * | ||
455 | * (1) "list" which is linked to tomoyo_domain_keeper_list . | ||
456 | * (2) "domainname" which is "a domainname" or "the last component of a | ||
457 | * domainname". | ||
458 | * (3) "program" which is a program's pathname. | ||
459 | * This field is NULL if "from" clause is not specified. | ||
460 | * (4) "is_deleted" is a bool which is true if marked as deleted, false | ||
461 | * otherwise. | ||
462 | * (5) "is_not" is a bool which is true if "no_initialize_domain", false | ||
463 | * otherwise. | ||
464 | * (6) "is_last_name" is a bool which is true if "domainname" is "the last | ||
465 | * component of a domainname", false otherwise. | ||
466 | */ | ||
467 | struct tomoyo_domain_keeper_entry { | ||
468 | struct list_head list; | ||
469 | const struct tomoyo_path_info *domainname; | ||
470 | const struct tomoyo_path_info *program; /* This may be NULL */ | ||
471 | bool is_deleted; | ||
472 | bool is_not; /* True if this entry is "no_keep_domain". */ | ||
473 | /* True if the domainname is tomoyo_get_last_name(). */ | ||
474 | bool is_last_name; | ||
475 | }; | ||
476 | |||
477 | /* | ||
478 | * tomoyo_alias_entry is a structure which is used for holding "alias" entries. | ||
479 | * It has following fields. | ||
480 | * | ||
481 | * (1) "list" which is linked to tomoyo_alias_list . | ||
482 | * (2) "original_name" which is a dereferenced pathname. | ||
483 | * (3) "aliased_name" which is a symlink's pathname. | ||
484 | * (4) "is_deleted" is a bool which is true if marked as deleted, false | ||
485 | * otherwise. | ||
486 | */ | ||
487 | struct tomoyo_alias_entry { | ||
488 | struct list_head list; | ||
489 | const struct tomoyo_path_info *original_name; | ||
490 | const struct tomoyo_path_info *aliased_name; | ||
491 | bool is_deleted; | ||
492 | }; | ||
493 | |||
494 | /* | ||
495 | * tomoyo_policy_manager_entry is a structure which is used for holding list of | ||
496 | * domainnames or programs which are permitted to modify configuration via | ||
497 | * /sys/kernel/security/tomoyo/ interface. | ||
498 | * It has following fields. | ||
499 | * | ||
500 | * (1) "list" which is linked to tomoyo_policy_manager_list . | ||
501 | * (2) "manager" is a domainname or a program's pathname. | ||
502 | * (3) "is_domain" is a bool which is true if "manager" is a domainname, false | ||
503 | * otherwise. | ||
504 | * (4) "is_deleted" is a bool which is true if marked as deleted, false | ||
505 | * otherwise. | ||
506 | */ | ||
507 | struct tomoyo_policy_manager_entry { | ||
508 | struct list_head list; | ||
509 | /* A path to program or a domainname. */ | ||
510 | const struct tomoyo_path_info *manager; | ||
511 | bool is_domain; /* True if manager is a domainname. */ | ||
512 | bool is_deleted; /* True if this entry is deleted. */ | ||
513 | }; | ||
514 | |||
515 | /********** Function prototypes. **********/ | ||
516 | |||
300 | /* Check whether the domain has too many ACL entries to hold. */ | 517 | /* Check whether the domain has too many ACL entries to hold. */ |
301 | bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain); | 518 | bool tomoyo_domain_quota_is_ok(struct tomoyo_domain_info * const domain); |
302 | /* Transactional sprintf() for policy dump. */ | 519 | /* Transactional sprintf() for policy dump. */ |
303 | bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) | 520 | bool tomoyo_io_printf(struct tomoyo_io_buffer *head, const char *fmt, ...) |
304 | __attribute__ ((format(printf, 2, 3))); | 521 | __attribute__ ((format(printf, 2, 3))); |
305 | /* Check whether the domainname is correct. */ | 522 | /* Check whether the domainname is correct. */ |
306 | bool tomoyo_is_correct_domain(const unsigned char *domainname, | 523 | bool tomoyo_is_correct_domain(const unsigned char *domainname); |
307 | const char *function); | ||
308 | /* Check whether the token is correct. */ | 524 | /* Check whether the token is correct. */ |
309 | bool tomoyo_is_correct_path(const char *filename, const s8 start_type, | 525 | bool tomoyo_is_correct_path(const char *filename, const s8 start_type, |
310 | const s8 pattern_type, const s8 end_type, | 526 | const s8 pattern_type, const s8 end_type); |
311 | const char *function); | ||
312 | /* Check whether the token can be a domainname. */ | 527 | /* Check whether the token can be a domainname. */ |
313 | bool tomoyo_is_domain_def(const unsigned char *buffer); | 528 | bool tomoyo_is_domain_def(const unsigned char *buffer); |
314 | /* Check whether the given filename matches the given pattern. */ | 529 | /* Check whether the given filename matches the given pattern. */ |
@@ -332,13 +547,13 @@ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head); | |||
332 | /* Write domain policy violation warning message to console? */ | 547 | /* Write domain policy violation warning message to console? */ |
333 | bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); | 548 | bool tomoyo_verbose_mode(const struct tomoyo_domain_info *domain); |
334 | /* Convert double path operation to operation name. */ | 549 | /* Convert double path operation to operation name. */ |
335 | const char *tomoyo_dp2keyword(const u8 operation); | 550 | const char *tomoyo_path22keyword(const u8 operation); |
336 | /* Get the last component of the given domainname. */ | 551 | /* Get the last component of the given domainname. */ |
337 | const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain); | 552 | const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain); |
338 | /* Get warning message. */ | 553 | /* Get warning message. */ |
339 | const char *tomoyo_get_msg(const bool is_enforce); | 554 | const char *tomoyo_get_msg(const bool is_enforce); |
340 | /* Convert single path operation to operation name. */ | 555 | /* Convert single path operation to operation name. */ |
341 | const char *tomoyo_sp2keyword(const u8 operation); | 556 | const char *tomoyo_path2keyword(const u8 operation); |
342 | /* Create "alias" entry in exception policy. */ | 557 | /* Create "alias" entry in exception policy. */ |
343 | int tomoyo_write_alias_policy(char *data, const bool is_delete); | 558 | int tomoyo_write_alias_policy(char *data, const bool is_delete); |
344 | /* | 559 | /* |
@@ -374,33 +589,107 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
374 | /* Check mode for specified functionality. */ | 589 | /* Check mode for specified functionality. */ |
375 | unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, | 590 | unsigned int tomoyo_check_flags(const struct tomoyo_domain_info *domain, |
376 | const u8 index); | 591 | const u8 index); |
377 | /* Allocate memory for structures. */ | ||
378 | void *tomoyo_alloc_acl_element(const u8 acl_type); | ||
379 | /* Fill in "struct tomoyo_path_info" members. */ | 592 | /* Fill in "struct tomoyo_path_info" members. */ |
380 | void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); | 593 | void tomoyo_fill_path_info(struct tomoyo_path_info *ptr); |
381 | /* Run policy loader when /sbin/init starts. */ | 594 | /* Run policy loader when /sbin/init starts. */ |
382 | void tomoyo_load_policy(const char *filename); | 595 | void tomoyo_load_policy(const char *filename); |
383 | /* Change "struct tomoyo_domain_info"->flags. */ | ||
384 | void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain, | ||
385 | const bool is_delete, const u8 flags); | ||
386 | 596 | ||
387 | /* strcmp() for "struct tomoyo_path_info" structure. */ | 597 | /* Convert binary string to ascii string. */ |
388 | static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, | 598 | int tomoyo_encode(char *buffer, int buflen, const char *str); |
389 | const struct tomoyo_path_info *b) | 599 | |
600 | /* Returns realpath(3) of the given pathname but ignores chroot'ed root. */ | ||
601 | int tomoyo_realpath_from_path2(struct path *path, char *newname, | ||
602 | int newname_len); | ||
603 | |||
604 | /* | ||
605 | * Returns realpath(3) of the given pathname but ignores chroot'ed root. | ||
606 | * These functions use kzalloc(), so the caller must call kfree() | ||
607 | * if these functions didn't return NULL. | ||
608 | */ | ||
609 | char *tomoyo_realpath(const char *pathname); | ||
610 | /* | ||
611 | * Same with tomoyo_realpath() except that it doesn't follow the final symlink. | ||
612 | */ | ||
613 | char *tomoyo_realpath_nofollow(const char *pathname); | ||
614 | /* Same with tomoyo_realpath() except that the pathname is already solved. */ | ||
615 | char *tomoyo_realpath_from_path(struct path *path); | ||
616 | |||
617 | /* Check memory quota. */ | ||
618 | bool tomoyo_memory_ok(void *ptr); | ||
619 | |||
620 | /* | ||
621 | * Keep the given name on the RAM. | ||
622 | * The RAM is shared, so NEVER try to modify or kfree() the returned name. | ||
623 | */ | ||
624 | const struct tomoyo_path_info *tomoyo_get_name(const char *name); | ||
625 | |||
626 | /* Check for memory usage. */ | ||
627 | int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head); | ||
628 | |||
629 | /* Set memory quota. */ | ||
630 | int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head); | ||
631 | |||
632 | /* Initialize realpath related code. */ | ||
633 | void __init tomoyo_realpath_init(void); | ||
634 | int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, | ||
635 | const struct tomoyo_path_info *filename); | ||
636 | int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | ||
637 | struct path *path, const int flag); | ||
638 | int tomoyo_path_perm(const u8 operation, struct path *path); | ||
639 | int tomoyo_path2_perm(const u8 operation, struct path *path1, | ||
640 | struct path *path2); | ||
641 | int tomoyo_check_rewrite_permission(struct file *filp); | ||
642 | int tomoyo_find_next_domain(struct linux_binprm *bprm); | ||
643 | |||
644 | /* Run garbage collector. */ | ||
645 | void tomoyo_run_gc(void); | ||
646 | |||
647 | void tomoyo_memory_free(void *ptr); | ||
648 | |||
649 | /********** External variable definitions. **********/ | ||
650 | |||
651 | /* Lock for GC. */ | ||
652 | extern struct srcu_struct tomoyo_ss; | ||
653 | |||
654 | /* The list for "struct tomoyo_domain_info". */ | ||
655 | extern struct list_head tomoyo_domain_list; | ||
656 | |||
657 | extern struct list_head tomoyo_domain_initializer_list; | ||
658 | extern struct list_head tomoyo_domain_keeper_list; | ||
659 | extern struct list_head tomoyo_alias_list; | ||
660 | extern struct list_head tomoyo_globally_readable_list; | ||
661 | extern struct list_head tomoyo_pattern_list; | ||
662 | extern struct list_head tomoyo_no_rewrite_list; | ||
663 | extern struct list_head tomoyo_policy_manager_list; | ||
664 | extern struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; | ||
665 | extern struct mutex tomoyo_name_list_lock; | ||
666 | |||
667 | /* Lock for protecting policy. */ | ||
668 | extern struct mutex tomoyo_policy_lock; | ||
669 | |||
670 | /* Has /sbin/init started? */ | ||
671 | extern bool tomoyo_policy_loaded; | ||
672 | |||
673 | /* The kernel's domain. */ | ||
674 | extern struct tomoyo_domain_info tomoyo_kernel_domain; | ||
675 | |||
676 | /********** Inlined functions. **********/ | ||
677 | |||
678 | static inline int tomoyo_read_lock(void) | ||
390 | { | 679 | { |
391 | return a->hash != b->hash || strcmp(a->name, b->name); | 680 | return srcu_read_lock(&tomoyo_ss); |
392 | } | 681 | } |
393 | 682 | ||
394 | /* Get type of an ACL entry. */ | 683 | static inline void tomoyo_read_unlock(int idx) |
395 | static inline u8 tomoyo_acl_type1(struct tomoyo_acl_info *ptr) | ||
396 | { | 684 | { |
397 | return ptr->type & ~TOMOYO_ACL_DELETED; | 685 | srcu_read_unlock(&tomoyo_ss, idx); |
398 | } | 686 | } |
399 | 687 | ||
400 | /* Get type of an ACL entry. */ | 688 | /* strcmp() for "struct tomoyo_path_info" structure. */ |
401 | static inline u8 tomoyo_acl_type2(struct tomoyo_acl_info *ptr) | 689 | static inline bool tomoyo_pathcmp(const struct tomoyo_path_info *a, |
690 | const struct tomoyo_path_info *b) | ||
402 | { | 691 | { |
403 | return ptr->type; | 692 | return a->hash != b->hash || strcmp(a->name, b->name); |
404 | } | 693 | } |
405 | 694 | ||
406 | /** | 695 | /** |
@@ -427,18 +716,25 @@ static inline bool tomoyo_is_invalid(const unsigned char c) | |||
427 | return c && (c <= ' ' || c >= 127); | 716 | return c && (c <= ' ' || c >= 127); |
428 | } | 717 | } |
429 | 718 | ||
430 | /* The list for "struct tomoyo_domain_info". */ | 719 | static inline void tomoyo_put_name(const struct tomoyo_path_info *name) |
431 | extern struct list_head tomoyo_domain_list; | 720 | { |
432 | extern struct rw_semaphore tomoyo_domain_list_lock; | 721 | if (name) { |
433 | 722 | struct tomoyo_name_entry *ptr = | |
434 | /* Lock for domain->acl_info_list. */ | 723 | container_of(name, struct tomoyo_name_entry, entry); |
435 | extern struct rw_semaphore tomoyo_domain_acl_info_list_lock; | 724 | atomic_dec(&ptr->users); |
725 | } | ||
726 | } | ||
436 | 727 | ||
437 | /* Has /sbin/init started? */ | 728 | static inline struct tomoyo_domain_info *tomoyo_domain(void) |
438 | extern bool tomoyo_policy_loaded; | 729 | { |
730 | return current_cred()->security; | ||
731 | } | ||
439 | 732 | ||
440 | /* The kernel's domain. */ | 733 | static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct |
441 | extern struct tomoyo_domain_info tomoyo_kernel_domain; | 734 | *task) |
735 | { | ||
736 | return task_cred_xxx(task, security); | ||
737 | } | ||
442 | 738 | ||
443 | /** | 739 | /** |
444 | * list_for_each_cookie - iterate over a list with cookie. | 740 | * list_for_each_cookie - iterate over a list with cookie. |
@@ -446,16 +742,16 @@ extern struct tomoyo_domain_info tomoyo_kernel_domain; | |||
446 | * @cookie: the &struct list_head to use as a cookie. | 742 | * @cookie: the &struct list_head to use as a cookie. |
447 | * @head: the head for your list. | 743 | * @head: the head for your list. |
448 | * | 744 | * |
449 | * Same with list_for_each() except that this primitive uses @cookie | 745 | * Same with list_for_each_rcu() except that this primitive uses @cookie |
450 | * so that we can continue iteration. | 746 | * so that we can continue iteration. |
451 | * @cookie must be NULL when iteration starts, and @cookie will become | 747 | * @cookie must be NULL when iteration starts, and @cookie will become |
452 | * NULL when iteration finishes. | 748 | * NULL when iteration finishes. |
453 | */ | 749 | */ |
454 | #define list_for_each_cookie(pos, cookie, head) \ | 750 | #define list_for_each_cookie(pos, cookie, head) \ |
455 | for (({ if (!cookie) \ | 751 | for (({ if (!cookie) \ |
456 | cookie = head; }), \ | 752 | cookie = head; }), \ |
457 | pos = (cookie)->next; \ | 753 | pos = rcu_dereference((cookie)->next); \ |
458 | prefetch(pos->next), pos != (head) || ((cookie) = NULL); \ | 754 | prefetch(pos->next), pos != (head) || ((cookie) = NULL); \ |
459 | (cookie) = pos, pos = pos->next) | 755 | (cookie) = pos, pos = rcu_dereference(pos->next)) |
460 | 756 | ||
461 | #endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */ | 757 | #endif /* !defined(_SECURITY_TOMOYO_COMMON_H) */ |
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index fcf52accce2b..acb8c397d5cf 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -10,9 +10,8 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include "common.h" | 12 | #include "common.h" |
13 | #include "tomoyo.h" | ||
14 | #include "realpath.h" | ||
15 | #include <linux/binfmts.h> | 13 | #include <linux/binfmts.h> |
14 | #include <linux/slab.h> | ||
16 | 15 | ||
17 | /* Variables definitions.*/ | 16 | /* Variables definitions.*/ |
18 | 17 | ||
@@ -58,99 +57,6 @@ struct tomoyo_domain_info tomoyo_kernel_domain; | |||
58 | * exceptions. | 57 | * exceptions. |
59 | */ | 58 | */ |
60 | LIST_HEAD(tomoyo_domain_list); | 59 | LIST_HEAD(tomoyo_domain_list); |
61 | DECLARE_RWSEM(tomoyo_domain_list_lock); | ||
62 | |||
63 | /* | ||
64 | * tomoyo_domain_initializer_entry is a structure which is used for holding | ||
65 | * "initialize_domain" and "no_initialize_domain" entries. | ||
66 | * It has following fields. | ||
67 | * | ||
68 | * (1) "list" which is linked to tomoyo_domain_initializer_list . | ||
69 | * (2) "domainname" which is "a domainname" or "the last component of a | ||
70 | * domainname". This field is NULL if "from" clause is not specified. | ||
71 | * (3) "program" which is a program's pathname. | ||
72 | * (4) "is_deleted" is a bool which is true if marked as deleted, false | ||
73 | * otherwise. | ||
74 | * (5) "is_not" is a bool which is true if "no_initialize_domain", false | ||
75 | * otherwise. | ||
76 | * (6) "is_last_name" is a bool which is true if "domainname" is "the last | ||
77 | * component of a domainname", false otherwise. | ||
78 | */ | ||
79 | struct tomoyo_domain_initializer_entry { | ||
80 | struct list_head list; | ||
81 | const struct tomoyo_path_info *domainname; /* This may be NULL */ | ||
82 | const struct tomoyo_path_info *program; | ||
83 | bool is_deleted; | ||
84 | bool is_not; /* True if this entry is "no_initialize_domain". */ | ||
85 | /* True if the domainname is tomoyo_get_last_name(). */ | ||
86 | bool is_last_name; | ||
87 | }; | ||
88 | |||
89 | /* | ||
90 | * tomoyo_domain_keeper_entry is a structure which is used for holding | ||
91 | * "keep_domain" and "no_keep_domain" entries. | ||
92 | * It has following fields. | ||
93 | * | ||
94 | * (1) "list" which is linked to tomoyo_domain_keeper_list . | ||
95 | * (2) "domainname" which is "a domainname" or "the last component of a | ||
96 | * domainname". | ||
97 | * (3) "program" which is a program's pathname. | ||
98 | * This field is NULL if "from" clause is not specified. | ||
99 | * (4) "is_deleted" is a bool which is true if marked as deleted, false | ||
100 | * otherwise. | ||
101 | * (5) "is_not" is a bool which is true if "no_initialize_domain", false | ||
102 | * otherwise. | ||
103 | * (6) "is_last_name" is a bool which is true if "domainname" is "the last | ||
104 | * component of a domainname", false otherwise. | ||
105 | */ | ||
106 | struct tomoyo_domain_keeper_entry { | ||
107 | struct list_head list; | ||
108 | const struct tomoyo_path_info *domainname; | ||
109 | const struct tomoyo_path_info *program; /* This may be NULL */ | ||
110 | bool is_deleted; | ||
111 | bool is_not; /* True if this entry is "no_keep_domain". */ | ||
112 | /* True if the domainname is tomoyo_get_last_name(). */ | ||
113 | bool is_last_name; | ||
114 | }; | ||
115 | |||
116 | /* | ||
117 | * tomoyo_alias_entry is a structure which is used for holding "alias" entries. | ||
118 | * It has following fields. | ||
119 | * | ||
120 | * (1) "list" which is linked to tomoyo_alias_list . | ||
121 | * (2) "original_name" which is a dereferenced pathname. | ||
122 | * (3) "aliased_name" which is a symlink's pathname. | ||
123 | * (4) "is_deleted" is a bool which is true if marked as deleted, false | ||
124 | * otherwise. | ||
125 | */ | ||
126 | struct tomoyo_alias_entry { | ||
127 | struct list_head list; | ||
128 | const struct tomoyo_path_info *original_name; | ||
129 | const struct tomoyo_path_info *aliased_name; | ||
130 | bool is_deleted; | ||
131 | }; | ||
132 | |||
133 | /** | ||
134 | * tomoyo_set_domain_flag - Set or clear domain's attribute flags. | ||
135 | * | ||
136 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
137 | * @is_delete: True if it is a delete request. | ||
138 | * @flags: Flags to set or clear. | ||
139 | * | ||
140 | * Returns nothing. | ||
141 | */ | ||
142 | void tomoyo_set_domain_flag(struct tomoyo_domain_info *domain, | ||
143 | const bool is_delete, const u8 flags) | ||
144 | { | ||
145 | /* We need to serialize because this is bitfield operation. */ | ||
146 | static DEFINE_SPINLOCK(lock); | ||
147 | spin_lock(&lock); | ||
148 | if (!is_delete) | ||
149 | domain->flags |= flags; | ||
150 | else | ||
151 | domain->flags &= ~flags; | ||
152 | spin_unlock(&lock); | ||
153 | } | ||
154 | 60 | ||
155 | /** | 61 | /** |
156 | * tomoyo_get_last_name - Get last component of a domainname. | 62 | * tomoyo_get_last_name - Get last component of a domainname. |
@@ -205,8 +111,7 @@ const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain) | |||
205 | * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain | 111 | * will cause "/usr/sbin/httpd" to belong to "<kernel> /usr/sbin/httpd" domain |
206 | * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain. | 112 | * unless executed from "<kernel> /etc/rc.d/init.d/httpd" domain. |
207 | */ | 113 | */ |
208 | static LIST_HEAD(tomoyo_domain_initializer_list); | 114 | LIST_HEAD(tomoyo_domain_initializer_list); |
209 | static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock); | ||
210 | 115 | ||
211 | /** | 116 | /** |
212 | * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list. | 117 | * tomoyo_update_domain_initializer_entry - Update "struct tomoyo_domain_initializer_entry" list. |
@@ -217,59 +122,65 @@ static DECLARE_RWSEM(tomoyo_domain_initializer_list_lock); | |||
217 | * @is_delete: True if it is a delete request. | 122 | * @is_delete: True if it is a delete request. |
218 | * | 123 | * |
219 | * Returns 0 on success, negative value otherwise. | 124 | * Returns 0 on success, negative value otherwise. |
125 | * | ||
126 | * Caller holds tomoyo_read_lock(). | ||
220 | */ | 127 | */ |
221 | static int tomoyo_update_domain_initializer_entry(const char *domainname, | 128 | static int tomoyo_update_domain_initializer_entry(const char *domainname, |
222 | const char *program, | 129 | const char *program, |
223 | const bool is_not, | 130 | const bool is_not, |
224 | const bool is_delete) | 131 | const bool is_delete) |
225 | { | 132 | { |
226 | struct tomoyo_domain_initializer_entry *new_entry; | 133 | struct tomoyo_domain_initializer_entry *entry = NULL; |
227 | struct tomoyo_domain_initializer_entry *ptr; | 134 | struct tomoyo_domain_initializer_entry *ptr; |
228 | const struct tomoyo_path_info *saved_program; | 135 | const struct tomoyo_path_info *saved_program = NULL; |
229 | const struct tomoyo_path_info *saved_domainname = NULL; | 136 | const struct tomoyo_path_info *saved_domainname = NULL; |
230 | int error = -ENOMEM; | 137 | int error = is_delete ? -ENOENT : -ENOMEM; |
231 | bool is_last_name = false; | 138 | bool is_last_name = false; |
232 | 139 | ||
233 | if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) | 140 | if (!tomoyo_is_correct_path(program, 1, -1, -1)) |
234 | return -EINVAL; /* No patterns allowed. */ | 141 | return -EINVAL; /* No patterns allowed. */ |
235 | if (domainname) { | 142 | if (domainname) { |
236 | if (!tomoyo_is_domain_def(domainname) && | 143 | if (!tomoyo_is_domain_def(domainname) && |
237 | tomoyo_is_correct_path(domainname, 1, -1, -1, __func__)) | 144 | tomoyo_is_correct_path(domainname, 1, -1, -1)) |
238 | is_last_name = true; | 145 | is_last_name = true; |
239 | else if (!tomoyo_is_correct_domain(domainname, __func__)) | 146 | else if (!tomoyo_is_correct_domain(domainname)) |
240 | return -EINVAL; | 147 | return -EINVAL; |
241 | saved_domainname = tomoyo_save_name(domainname); | 148 | saved_domainname = tomoyo_get_name(domainname); |
242 | if (!saved_domainname) | 149 | if (!saved_domainname) |
243 | return -ENOMEM; | 150 | goto out; |
244 | } | 151 | } |
245 | saved_program = tomoyo_save_name(program); | 152 | saved_program = tomoyo_get_name(program); |
246 | if (!saved_program) | 153 | if (!saved_program) |
247 | return -ENOMEM; | 154 | goto out; |
248 | down_write(&tomoyo_domain_initializer_list_lock); | 155 | if (!is_delete) |
249 | list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) { | 156 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
157 | mutex_lock(&tomoyo_policy_lock); | ||
158 | list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { | ||
250 | if (ptr->is_not != is_not || | 159 | if (ptr->is_not != is_not || |
251 | ptr->domainname != saved_domainname || | 160 | ptr->domainname != saved_domainname || |
252 | ptr->program != saved_program) | 161 | ptr->program != saved_program) |
253 | continue; | 162 | continue; |
254 | ptr->is_deleted = is_delete; | 163 | ptr->is_deleted = is_delete; |
255 | error = 0; | 164 | error = 0; |
256 | goto out; | 165 | break; |
257 | } | 166 | } |
258 | if (is_delete) { | 167 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
259 | error = -ENOENT; | 168 | entry->domainname = saved_domainname; |
260 | goto out; | 169 | saved_domainname = NULL; |
170 | entry->program = saved_program; | ||
171 | saved_program = NULL; | ||
172 | entry->is_not = is_not; | ||
173 | entry->is_last_name = is_last_name; | ||
174 | list_add_tail_rcu(&entry->list, | ||
175 | &tomoyo_domain_initializer_list); | ||
176 | entry = NULL; | ||
177 | error = 0; | ||
261 | } | 178 | } |
262 | new_entry = tomoyo_alloc_element(sizeof(*new_entry)); | 179 | mutex_unlock(&tomoyo_policy_lock); |
263 | if (!new_entry) | ||
264 | goto out; | ||
265 | new_entry->domainname = saved_domainname; | ||
266 | new_entry->program = saved_program; | ||
267 | new_entry->is_not = is_not; | ||
268 | new_entry->is_last_name = is_last_name; | ||
269 | list_add_tail(&new_entry->list, &tomoyo_domain_initializer_list); | ||
270 | error = 0; | ||
271 | out: | 180 | out: |
272 | up_write(&tomoyo_domain_initializer_list_lock); | 181 | tomoyo_put_name(saved_domainname); |
182 | tomoyo_put_name(saved_program); | ||
183 | kfree(entry); | ||
273 | return error; | 184 | return error; |
274 | } | 185 | } |
275 | 186 | ||
@@ -279,13 +190,14 @@ static int tomoyo_update_domain_initializer_entry(const char *domainname, | |||
279 | * @head: Pointer to "struct tomoyo_io_buffer". | 190 | * @head: Pointer to "struct tomoyo_io_buffer". |
280 | * | 191 | * |
281 | * Returns true on success, false otherwise. | 192 | * Returns true on success, false otherwise. |
193 | * | ||
194 | * Caller holds tomoyo_read_lock(). | ||
282 | */ | 195 | */ |
283 | bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) | 196 | bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) |
284 | { | 197 | { |
285 | struct list_head *pos; | 198 | struct list_head *pos; |
286 | bool done = true; | 199 | bool done = true; |
287 | 200 | ||
288 | down_read(&tomoyo_domain_initializer_list_lock); | ||
289 | list_for_each_cookie(pos, head->read_var2, | 201 | list_for_each_cookie(pos, head->read_var2, |
290 | &tomoyo_domain_initializer_list) { | 202 | &tomoyo_domain_initializer_list) { |
291 | const char *no; | 203 | const char *no; |
@@ -308,7 +220,6 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) | |||
308 | if (!done) | 220 | if (!done) |
309 | break; | 221 | break; |
310 | } | 222 | } |
311 | up_read(&tomoyo_domain_initializer_list_lock); | ||
312 | return done; | 223 | return done; |
313 | } | 224 | } |
314 | 225 | ||
@@ -320,6 +231,8 @@ bool tomoyo_read_domain_initializer_policy(struct tomoyo_io_buffer *head) | |||
320 | * @is_delete: True if it is a delete request. | 231 | * @is_delete: True if it is a delete request. |
321 | * | 232 | * |
322 | * Returns 0 on success, negative value otherwise. | 233 | * Returns 0 on success, negative value otherwise. |
234 | * | ||
235 | * Caller holds tomoyo_read_lock(). | ||
323 | */ | 236 | */ |
324 | int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, | 237 | int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, |
325 | const bool is_delete) | 238 | const bool is_delete) |
@@ -345,6 +258,8 @@ int tomoyo_write_domain_initializer_policy(char *data, const bool is_not, | |||
345 | * | 258 | * |
346 | * Returns true if executing @program reinitializes domain transition, | 259 | * Returns true if executing @program reinitializes domain transition, |
347 | * false otherwise. | 260 | * false otherwise. |
261 | * | ||
262 | * Caller holds tomoyo_read_lock(). | ||
348 | */ | 263 | */ |
349 | static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * | 264 | static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * |
350 | domainname, | 265 | domainname, |
@@ -355,8 +270,7 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * | |||
355 | struct tomoyo_domain_initializer_entry *ptr; | 270 | struct tomoyo_domain_initializer_entry *ptr; |
356 | bool flag = false; | 271 | bool flag = false; |
357 | 272 | ||
358 | down_read(&tomoyo_domain_initializer_list_lock); | 273 | list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, list) { |
359 | list_for_each_entry(ptr, &tomoyo_domain_initializer_list, list) { | ||
360 | if (ptr->is_deleted) | 274 | if (ptr->is_deleted) |
361 | continue; | 275 | continue; |
362 | if (ptr->domainname) { | 276 | if (ptr->domainname) { |
@@ -376,7 +290,6 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * | |||
376 | } | 290 | } |
377 | flag = true; | 291 | flag = true; |
378 | } | 292 | } |
379 | up_read(&tomoyo_domain_initializer_list_lock); | ||
380 | return flag; | 293 | return flag; |
381 | } | 294 | } |
382 | 295 | ||
@@ -418,8 +331,7 @@ static bool tomoyo_is_domain_initializer(const struct tomoyo_path_info * | |||
418 | * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless | 331 | * "<kernel> /usr/sbin/sshd /bin/bash /usr/bin/passwd" domain, unless |
419 | * explicitly specified by "initialize_domain". | 332 | * explicitly specified by "initialize_domain". |
420 | */ | 333 | */ |
421 | static LIST_HEAD(tomoyo_domain_keeper_list); | 334 | LIST_HEAD(tomoyo_domain_keeper_list); |
422 | static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock); | ||
423 | 335 | ||
424 | /** | 336 | /** |
425 | * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list. | 337 | * tomoyo_update_domain_keeper_entry - Update "struct tomoyo_domain_keeper_entry" list. |
@@ -430,59 +342,64 @@ static DECLARE_RWSEM(tomoyo_domain_keeper_list_lock); | |||
430 | * @is_delete: True if it is a delete request. | 342 | * @is_delete: True if it is a delete request. |
431 | * | 343 | * |
432 | * Returns 0 on success, negative value otherwise. | 344 | * Returns 0 on success, negative value otherwise. |
345 | * | ||
346 | * Caller holds tomoyo_read_lock(). | ||
433 | */ | 347 | */ |
434 | static int tomoyo_update_domain_keeper_entry(const char *domainname, | 348 | static int tomoyo_update_domain_keeper_entry(const char *domainname, |
435 | const char *program, | 349 | const char *program, |
436 | const bool is_not, | 350 | const bool is_not, |
437 | const bool is_delete) | 351 | const bool is_delete) |
438 | { | 352 | { |
439 | struct tomoyo_domain_keeper_entry *new_entry; | 353 | struct tomoyo_domain_keeper_entry *entry = NULL; |
440 | struct tomoyo_domain_keeper_entry *ptr; | 354 | struct tomoyo_domain_keeper_entry *ptr; |
441 | const struct tomoyo_path_info *saved_domainname; | 355 | const struct tomoyo_path_info *saved_domainname = NULL; |
442 | const struct tomoyo_path_info *saved_program = NULL; | 356 | const struct tomoyo_path_info *saved_program = NULL; |
443 | int error = -ENOMEM; | 357 | int error = is_delete ? -ENOENT : -ENOMEM; |
444 | bool is_last_name = false; | 358 | bool is_last_name = false; |
445 | 359 | ||
446 | if (!tomoyo_is_domain_def(domainname) && | 360 | if (!tomoyo_is_domain_def(domainname) && |
447 | tomoyo_is_correct_path(domainname, 1, -1, -1, __func__)) | 361 | tomoyo_is_correct_path(domainname, 1, -1, -1)) |
448 | is_last_name = true; | 362 | is_last_name = true; |
449 | else if (!tomoyo_is_correct_domain(domainname, __func__)) | 363 | else if (!tomoyo_is_correct_domain(domainname)) |
450 | return -EINVAL; | 364 | return -EINVAL; |
451 | if (program) { | 365 | if (program) { |
452 | if (!tomoyo_is_correct_path(program, 1, -1, -1, __func__)) | 366 | if (!tomoyo_is_correct_path(program, 1, -1, -1)) |
453 | return -EINVAL; | 367 | return -EINVAL; |
454 | saved_program = tomoyo_save_name(program); | 368 | saved_program = tomoyo_get_name(program); |
455 | if (!saved_program) | 369 | if (!saved_program) |
456 | return -ENOMEM; | 370 | goto out; |
457 | } | 371 | } |
458 | saved_domainname = tomoyo_save_name(domainname); | 372 | saved_domainname = tomoyo_get_name(domainname); |
459 | if (!saved_domainname) | 373 | if (!saved_domainname) |
460 | return -ENOMEM; | 374 | goto out; |
461 | down_write(&tomoyo_domain_keeper_list_lock); | 375 | if (!is_delete) |
462 | list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) { | 376 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
377 | mutex_lock(&tomoyo_policy_lock); | ||
378 | list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { | ||
463 | if (ptr->is_not != is_not || | 379 | if (ptr->is_not != is_not || |
464 | ptr->domainname != saved_domainname || | 380 | ptr->domainname != saved_domainname || |
465 | ptr->program != saved_program) | 381 | ptr->program != saved_program) |
466 | continue; | 382 | continue; |
467 | ptr->is_deleted = is_delete; | 383 | ptr->is_deleted = is_delete; |
468 | error = 0; | 384 | error = 0; |
469 | goto out; | 385 | break; |
470 | } | 386 | } |
471 | if (is_delete) { | 387 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
472 | error = -ENOENT; | 388 | entry->domainname = saved_domainname; |
473 | goto out; | 389 | saved_domainname = NULL; |
390 | entry->program = saved_program; | ||
391 | saved_program = NULL; | ||
392 | entry->is_not = is_not; | ||
393 | entry->is_last_name = is_last_name; | ||
394 | list_add_tail_rcu(&entry->list, &tomoyo_domain_keeper_list); | ||
395 | entry = NULL; | ||
396 | error = 0; | ||
474 | } | 397 | } |
475 | new_entry = tomoyo_alloc_element(sizeof(*new_entry)); | 398 | mutex_unlock(&tomoyo_policy_lock); |
476 | if (!new_entry) | ||
477 | goto out; | ||
478 | new_entry->domainname = saved_domainname; | ||
479 | new_entry->program = saved_program; | ||
480 | new_entry->is_not = is_not; | ||
481 | new_entry->is_last_name = is_last_name; | ||
482 | list_add_tail(&new_entry->list, &tomoyo_domain_keeper_list); | ||
483 | error = 0; | ||
484 | out: | 399 | out: |
485 | up_write(&tomoyo_domain_keeper_list_lock); | 400 | tomoyo_put_name(saved_domainname); |
401 | tomoyo_put_name(saved_program); | ||
402 | kfree(entry); | ||
486 | return error; | 403 | return error; |
487 | } | 404 | } |
488 | 405 | ||
@@ -493,6 +410,7 @@ static int tomoyo_update_domain_keeper_entry(const char *domainname, | |||
493 | * @is_not: True if it is "no_keep_domain" entry. | 410 | * @is_not: True if it is "no_keep_domain" entry. |
494 | * @is_delete: True if it is a delete request. | 411 | * @is_delete: True if it is a delete request. |
495 | * | 412 | * |
413 | * Caller holds tomoyo_read_lock(). | ||
496 | */ | 414 | */ |
497 | int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, | 415 | int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, |
498 | const bool is_delete) | 416 | const bool is_delete) |
@@ -513,13 +431,14 @@ int tomoyo_write_domain_keeper_policy(char *data, const bool is_not, | |||
513 | * @head: Pointer to "struct tomoyo_io_buffer". | 431 | * @head: Pointer to "struct tomoyo_io_buffer". |
514 | * | 432 | * |
515 | * Returns true on success, false otherwise. | 433 | * Returns true on success, false otherwise. |
434 | * | ||
435 | * Caller holds tomoyo_read_lock(). | ||
516 | */ | 436 | */ |
517 | bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) | 437 | bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) |
518 | { | 438 | { |
519 | struct list_head *pos; | 439 | struct list_head *pos; |
520 | bool done = true; | 440 | bool done = true; |
521 | 441 | ||
522 | down_read(&tomoyo_domain_keeper_list_lock); | ||
523 | list_for_each_cookie(pos, head->read_var2, | 442 | list_for_each_cookie(pos, head->read_var2, |
524 | &tomoyo_domain_keeper_list) { | 443 | &tomoyo_domain_keeper_list) { |
525 | struct tomoyo_domain_keeper_entry *ptr; | 444 | struct tomoyo_domain_keeper_entry *ptr; |
@@ -542,7 +461,6 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) | |||
542 | if (!done) | 461 | if (!done) |
543 | break; | 462 | break; |
544 | } | 463 | } |
545 | up_read(&tomoyo_domain_keeper_list_lock); | ||
546 | return done; | 464 | return done; |
547 | } | 465 | } |
548 | 466 | ||
@@ -555,6 +473,8 @@ bool tomoyo_read_domain_keeper_policy(struct tomoyo_io_buffer *head) | |||
555 | * | 473 | * |
556 | * Returns true if executing @program supresses domain transition, | 474 | * Returns true if executing @program supresses domain transition, |
557 | * false otherwise. | 475 | * false otherwise. |
476 | * | ||
477 | * Caller holds tomoyo_read_lock(). | ||
558 | */ | 478 | */ |
559 | static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, | 479 | static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, |
560 | const struct tomoyo_path_info *program, | 480 | const struct tomoyo_path_info *program, |
@@ -563,8 +483,7 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, | |||
563 | struct tomoyo_domain_keeper_entry *ptr; | 483 | struct tomoyo_domain_keeper_entry *ptr; |
564 | bool flag = false; | 484 | bool flag = false; |
565 | 485 | ||
566 | down_read(&tomoyo_domain_keeper_list_lock); | 486 | list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { |
567 | list_for_each_entry(ptr, &tomoyo_domain_keeper_list, list) { | ||
568 | if (ptr->is_deleted) | 487 | if (ptr->is_deleted) |
569 | continue; | 488 | continue; |
570 | if (!ptr->is_last_name) { | 489 | if (!ptr->is_last_name) { |
@@ -582,7 +501,6 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, | |||
582 | } | 501 | } |
583 | flag = true; | 502 | flag = true; |
584 | } | 503 | } |
585 | up_read(&tomoyo_domain_keeper_list_lock); | ||
586 | return flag; | 504 | return flag; |
587 | } | 505 | } |
588 | 506 | ||
@@ -616,8 +534,7 @@ static bool tomoyo_is_domain_keeper(const struct tomoyo_path_info *domainname, | |||
616 | * /bin/busybox and domainname which the current process will belong to after | 534 | * /bin/busybox and domainname which the current process will belong to after |
617 | * execve() succeeds is calculated using /bin/cat rather than /bin/busybox . | 535 | * execve() succeeds is calculated using /bin/cat rather than /bin/busybox . |
618 | */ | 536 | */ |
619 | static LIST_HEAD(tomoyo_alias_list); | 537 | LIST_HEAD(tomoyo_alias_list); |
620 | static DECLARE_RWSEM(tomoyo_alias_list_lock); | ||
621 | 538 | ||
622 | /** | 539 | /** |
623 | * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list. | 540 | * tomoyo_update_alias_entry - Update "struct tomoyo_alias_entry" list. |
@@ -627,46 +544,51 @@ static DECLARE_RWSEM(tomoyo_alias_list_lock); | |||
627 | * @is_delete: True if it is a delete request. | 544 | * @is_delete: True if it is a delete request. |
628 | * | 545 | * |
629 | * Returns 0 on success, negative value otherwise. | 546 | * Returns 0 on success, negative value otherwise. |
547 | * | ||
548 | * Caller holds tomoyo_read_lock(). | ||
630 | */ | 549 | */ |
631 | static int tomoyo_update_alias_entry(const char *original_name, | 550 | static int tomoyo_update_alias_entry(const char *original_name, |
632 | const char *aliased_name, | 551 | const char *aliased_name, |
633 | const bool is_delete) | 552 | const bool is_delete) |
634 | { | 553 | { |
635 | struct tomoyo_alias_entry *new_entry; | 554 | struct tomoyo_alias_entry *entry = NULL; |
636 | struct tomoyo_alias_entry *ptr; | 555 | struct tomoyo_alias_entry *ptr; |
637 | const struct tomoyo_path_info *saved_original_name; | 556 | const struct tomoyo_path_info *saved_original_name; |
638 | const struct tomoyo_path_info *saved_aliased_name; | 557 | const struct tomoyo_path_info *saved_aliased_name; |
639 | int error = -ENOMEM; | 558 | int error = is_delete ? -ENOENT : -ENOMEM; |
640 | 559 | ||
641 | if (!tomoyo_is_correct_path(original_name, 1, -1, -1, __func__) || | 560 | if (!tomoyo_is_correct_path(original_name, 1, -1, -1) || |
642 | !tomoyo_is_correct_path(aliased_name, 1, -1, -1, __func__)) | 561 | !tomoyo_is_correct_path(aliased_name, 1, -1, -1)) |
643 | return -EINVAL; /* No patterns allowed. */ | 562 | return -EINVAL; /* No patterns allowed. */ |
644 | saved_original_name = tomoyo_save_name(original_name); | 563 | saved_original_name = tomoyo_get_name(original_name); |
645 | saved_aliased_name = tomoyo_save_name(aliased_name); | 564 | saved_aliased_name = tomoyo_get_name(aliased_name); |
646 | if (!saved_original_name || !saved_aliased_name) | 565 | if (!saved_original_name || !saved_aliased_name) |
647 | return -ENOMEM; | 566 | goto out; |
648 | down_write(&tomoyo_alias_list_lock); | 567 | if (!is_delete) |
649 | list_for_each_entry(ptr, &tomoyo_alias_list, list) { | 568 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
569 | mutex_lock(&tomoyo_policy_lock); | ||
570 | list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { | ||
650 | if (ptr->original_name != saved_original_name || | 571 | if (ptr->original_name != saved_original_name || |
651 | ptr->aliased_name != saved_aliased_name) | 572 | ptr->aliased_name != saved_aliased_name) |
652 | continue; | 573 | continue; |
653 | ptr->is_deleted = is_delete; | 574 | ptr->is_deleted = is_delete; |
654 | error = 0; | 575 | error = 0; |
655 | goto out; | 576 | break; |
656 | } | 577 | } |
657 | if (is_delete) { | 578 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
658 | error = -ENOENT; | 579 | entry->original_name = saved_original_name; |
659 | goto out; | 580 | saved_original_name = NULL; |
581 | entry->aliased_name = saved_aliased_name; | ||
582 | saved_aliased_name = NULL; | ||
583 | list_add_tail_rcu(&entry->list, &tomoyo_alias_list); | ||
584 | entry = NULL; | ||
585 | error = 0; | ||
660 | } | 586 | } |
661 | new_entry = tomoyo_alloc_element(sizeof(*new_entry)); | 587 | mutex_unlock(&tomoyo_policy_lock); |
662 | if (!new_entry) | ||
663 | goto out; | ||
664 | new_entry->original_name = saved_original_name; | ||
665 | new_entry->aliased_name = saved_aliased_name; | ||
666 | list_add_tail(&new_entry->list, &tomoyo_alias_list); | ||
667 | error = 0; | ||
668 | out: | 588 | out: |
669 | up_write(&tomoyo_alias_list_lock); | 589 | tomoyo_put_name(saved_original_name); |
590 | tomoyo_put_name(saved_aliased_name); | ||
591 | kfree(entry); | ||
670 | return error; | 592 | return error; |
671 | } | 593 | } |
672 | 594 | ||
@@ -676,13 +598,14 @@ static int tomoyo_update_alias_entry(const char *original_name, | |||
676 | * @head: Pointer to "struct tomoyo_io_buffer". | 598 | * @head: Pointer to "struct tomoyo_io_buffer". |
677 | * | 599 | * |
678 | * Returns true on success, false otherwise. | 600 | * Returns true on success, false otherwise. |
601 | * | ||
602 | * Caller holds tomoyo_read_lock(). | ||
679 | */ | 603 | */ |
680 | bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) | 604 | bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) |
681 | { | 605 | { |
682 | struct list_head *pos; | 606 | struct list_head *pos; |
683 | bool done = true; | 607 | bool done = true; |
684 | 608 | ||
685 | down_read(&tomoyo_alias_list_lock); | ||
686 | list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) { | 609 | list_for_each_cookie(pos, head->read_var2, &tomoyo_alias_list) { |
687 | struct tomoyo_alias_entry *ptr; | 610 | struct tomoyo_alias_entry *ptr; |
688 | 611 | ||
@@ -695,7 +618,6 @@ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) | |||
695 | if (!done) | 618 | if (!done) |
696 | break; | 619 | break; |
697 | } | 620 | } |
698 | up_read(&tomoyo_alias_list_lock); | ||
699 | return done; | 621 | return done; |
700 | } | 622 | } |
701 | 623 | ||
@@ -706,6 +628,8 @@ bool tomoyo_read_alias_policy(struct tomoyo_io_buffer *head) | |||
706 | * @is_delete: True if it is a delete request. | 628 | * @is_delete: True if it is a delete request. |
707 | * | 629 | * |
708 | * Returns 0 on success, negative value otherwise. | 630 | * Returns 0 on success, negative value otherwise. |
631 | * | ||
632 | * Caller holds tomoyo_read_lock(). | ||
709 | */ | 633 | */ |
710 | int tomoyo_write_alias_policy(char *data, const bool is_delete) | 634 | int tomoyo_write_alias_policy(char *data, const bool is_delete) |
711 | { | 635 | { |
@@ -724,63 +648,46 @@ int tomoyo_write_alias_policy(char *data, const bool is_delete) | |||
724 | * @profile: Profile number to assign if the domain was newly created. | 648 | * @profile: Profile number to assign if the domain was newly created. |
725 | * | 649 | * |
726 | * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. | 650 | * Returns pointer to "struct tomoyo_domain_info" on success, NULL otherwise. |
651 | * | ||
652 | * Caller holds tomoyo_read_lock(). | ||
727 | */ | 653 | */ |
728 | struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | 654 | struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * |
729 | domainname, | 655 | domainname, |
730 | const u8 profile) | 656 | const u8 profile) |
731 | { | 657 | { |
732 | struct tomoyo_domain_info *domain = NULL; | 658 | struct tomoyo_domain_info *entry; |
659 | struct tomoyo_domain_info *domain; | ||
733 | const struct tomoyo_path_info *saved_domainname; | 660 | const struct tomoyo_path_info *saved_domainname; |
661 | bool found = false; | ||
734 | 662 | ||
735 | down_write(&tomoyo_domain_list_lock); | 663 | if (!tomoyo_is_correct_domain(domainname)) |
736 | domain = tomoyo_find_domain(domainname); | 664 | return NULL; |
737 | if (domain) | 665 | saved_domainname = tomoyo_get_name(domainname); |
738 | goto out; | ||
739 | if (!tomoyo_is_correct_domain(domainname, __func__)) | ||
740 | goto out; | ||
741 | saved_domainname = tomoyo_save_name(domainname); | ||
742 | if (!saved_domainname) | 666 | if (!saved_domainname) |
743 | goto out; | 667 | return NULL; |
744 | /* Can I reuse memory of deleted domain? */ | 668 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
745 | list_for_each_entry(domain, &tomoyo_domain_list, list) { | 669 | mutex_lock(&tomoyo_policy_lock); |
746 | struct task_struct *p; | 670 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { |
747 | struct tomoyo_acl_info *ptr; | 671 | if (domain->is_deleted || |
748 | bool flag; | 672 | tomoyo_pathcmp(saved_domainname, domain->domainname)) |
749 | if (!domain->is_deleted || | ||
750 | domain->domainname != saved_domainname) | ||
751 | continue; | 673 | continue; |
752 | flag = false; | 674 | found = true; |
753 | read_lock(&tasklist_lock); | 675 | break; |
754 | for_each_process(p) { | ||
755 | if (tomoyo_real_domain(p) != domain) | ||
756 | continue; | ||
757 | flag = true; | ||
758 | break; | ||
759 | } | ||
760 | read_unlock(&tasklist_lock); | ||
761 | if (flag) | ||
762 | continue; | ||
763 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | ||
764 | ptr->type |= TOMOYO_ACL_DELETED; | ||
765 | } | ||
766 | tomoyo_set_domain_flag(domain, true, domain->flags); | ||
767 | domain->profile = profile; | ||
768 | domain->quota_warned = false; | ||
769 | mb(); /* Avoid out-of-order execution. */ | ||
770 | domain->is_deleted = false; | ||
771 | goto out; | ||
772 | } | 676 | } |
773 | /* No memory reusable. Create using new memory. */ | 677 | if (!found && tomoyo_memory_ok(entry)) { |
774 | domain = tomoyo_alloc_element(sizeof(*domain)); | 678 | INIT_LIST_HEAD(&entry->acl_info_list); |
775 | if (domain) { | 679 | entry->domainname = saved_domainname; |
776 | INIT_LIST_HEAD(&domain->acl_info_list); | 680 | saved_domainname = NULL; |
777 | domain->domainname = saved_domainname; | 681 | entry->profile = profile; |
778 | domain->profile = profile; | 682 | list_add_tail_rcu(&entry->list, &tomoyo_domain_list); |
779 | list_add_tail(&domain->list, &tomoyo_domain_list); | 683 | domain = entry; |
684 | entry = NULL; | ||
685 | found = true; | ||
780 | } | 686 | } |
781 | out: | 687 | mutex_unlock(&tomoyo_policy_lock); |
782 | up_write(&tomoyo_domain_list_lock); | 688 | tomoyo_put_name(saved_domainname); |
783 | return domain; | 689 | kfree(entry); |
690 | return found ? domain : NULL; | ||
784 | } | 691 | } |
785 | 692 | ||
786 | /** | 693 | /** |
@@ -789,6 +696,8 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
789 | * @bprm: Pointer to "struct linux_binprm". | 696 | * @bprm: Pointer to "struct linux_binprm". |
790 | * | 697 | * |
791 | * Returns 0 on success, negative value otherwise. | 698 | * Returns 0 on success, negative value otherwise. |
699 | * | ||
700 | * Caller holds tomoyo_read_lock(). | ||
792 | */ | 701 | */ |
793 | int tomoyo_find_next_domain(struct linux_binprm *bprm) | 702 | int tomoyo_find_next_domain(struct linux_binprm *bprm) |
794 | { | 703 | { |
@@ -796,7 +705,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
796 | * This function assumes that the size of buffer returned by | 705 | * This function assumes that the size of buffer returned by |
797 | * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN. | 706 | * tomoyo_realpath() = TOMOYO_MAX_PATHNAME_LEN. |
798 | */ | 707 | */ |
799 | struct tomoyo_page_buffer *tmp = tomoyo_alloc(sizeof(*tmp)); | 708 | struct tomoyo_page_buffer *tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); |
800 | struct tomoyo_domain_info *old_domain = tomoyo_domain(); | 709 | struct tomoyo_domain_info *old_domain = tomoyo_domain(); |
801 | struct tomoyo_domain_info *domain = NULL; | 710 | struct tomoyo_domain_info *domain = NULL; |
802 | const char *old_domain_name = old_domain->domainname->name; | 711 | const char *old_domain_name = old_domain->domainname->name; |
@@ -849,8 +758,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
849 | if (tomoyo_pathcmp(&r, &s)) { | 758 | if (tomoyo_pathcmp(&r, &s)) { |
850 | struct tomoyo_alias_entry *ptr; | 759 | struct tomoyo_alias_entry *ptr; |
851 | /* Is this program allowed to be called via symbolic links? */ | 760 | /* Is this program allowed to be called via symbolic links? */ |
852 | down_read(&tomoyo_alias_list_lock); | 761 | list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { |
853 | list_for_each_entry(ptr, &tomoyo_alias_list, list) { | ||
854 | if (ptr->is_deleted || | 762 | if (ptr->is_deleted || |
855 | tomoyo_pathcmp(&r, ptr->original_name) || | 763 | tomoyo_pathcmp(&r, ptr->original_name) || |
856 | tomoyo_pathcmp(&s, ptr->aliased_name)) | 764 | tomoyo_pathcmp(&s, ptr->aliased_name)) |
@@ -861,7 +769,6 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
861 | tomoyo_fill_path_info(&r); | 769 | tomoyo_fill_path_info(&r); |
862 | break; | 770 | break; |
863 | } | 771 | } |
864 | up_read(&tomoyo_alias_list_lock); | ||
865 | } | 772 | } |
866 | 773 | ||
867 | /* Check execute permission. */ | 774 | /* Check execute permission. */ |
@@ -892,9 +799,7 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
892 | } | 799 | } |
893 | if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN) | 800 | if (domain || strlen(new_domain_name) >= TOMOYO_MAX_PATHNAME_LEN) |
894 | goto done; | 801 | goto done; |
895 | down_read(&tomoyo_domain_list_lock); | ||
896 | domain = tomoyo_find_domain(new_domain_name); | 802 | domain = tomoyo_find_domain(new_domain_name); |
897 | up_read(&tomoyo_domain_list_lock); | ||
898 | if (domain) | 803 | if (domain) |
899 | goto done; | 804 | goto done; |
900 | if (is_enforce) | 805 | if (is_enforce) |
@@ -909,14 +814,15 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm) | |||
909 | if (is_enforce) | 814 | if (is_enforce) |
910 | retval = -EPERM; | 815 | retval = -EPERM; |
911 | else | 816 | else |
912 | tomoyo_set_domain_flag(old_domain, false, | 817 | old_domain->transition_failed = true; |
913 | TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED); | ||
914 | out: | 818 | out: |
915 | if (!domain) | 819 | if (!domain) |
916 | domain = old_domain; | 820 | domain = old_domain; |
821 | /* Update reference count on "struct tomoyo_domain_info". */ | ||
822 | atomic_inc(&domain->users); | ||
917 | bprm->cred->security = domain; | 823 | bprm->cred->security = domain; |
918 | tomoyo_free(real_program_name); | 824 | kfree(real_program_name); |
919 | tomoyo_free(symlink_program_name); | 825 | kfree(symlink_program_name); |
920 | tomoyo_free(tmp); | 826 | kfree(tmp); |
921 | return retval; | 827 | return retval; |
922 | } | 828 | } |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index 5ae3a571559f..6f3fe76a1fde 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -10,109 +10,65 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | #include "common.h" | 12 | #include "common.h" |
13 | #include "tomoyo.h" | 13 | #include <linux/slab.h> |
14 | #include "realpath.h" | ||
15 | #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE]) | ||
16 | |||
17 | /* | ||
18 | * tomoyo_globally_readable_file_entry is a structure which is used for holding | ||
19 | * "allow_read" entries. | ||
20 | * It has following fields. | ||
21 | * | ||
22 | * (1) "list" which is linked to tomoyo_globally_readable_list . | ||
23 | * (2) "filename" is a pathname which is allowed to open(O_RDONLY). | ||
24 | * (3) "is_deleted" is a bool which is true if marked as deleted, false | ||
25 | * otherwise. | ||
26 | */ | ||
27 | struct tomoyo_globally_readable_file_entry { | ||
28 | struct list_head list; | ||
29 | const struct tomoyo_path_info *filename; | ||
30 | bool is_deleted; | ||
31 | }; | ||
32 | |||
33 | /* | ||
34 | * tomoyo_pattern_entry is a structure which is used for holding | ||
35 | * "tomoyo_pattern_list" entries. | ||
36 | * It has following fields. | ||
37 | * | ||
38 | * (1) "list" which is linked to tomoyo_pattern_list . | ||
39 | * (2) "pattern" is a pathname pattern which is used for converting pathnames | ||
40 | * to pathname patterns during learning mode. | ||
41 | * (3) "is_deleted" is a bool which is true if marked as deleted, false | ||
42 | * otherwise. | ||
43 | */ | ||
44 | struct tomoyo_pattern_entry { | ||
45 | struct list_head list; | ||
46 | const struct tomoyo_path_info *pattern; | ||
47 | bool is_deleted; | ||
48 | }; | ||
49 | |||
50 | /* | ||
51 | * tomoyo_no_rewrite_entry is a structure which is used for holding | ||
52 | * "deny_rewrite" entries. | ||
53 | * It has following fields. | ||
54 | * | ||
55 | * (1) "list" which is linked to tomoyo_no_rewrite_list . | ||
56 | * (2) "pattern" is a pathname which is by default not permitted to modify | ||
57 | * already existing content. | ||
58 | * (3) "is_deleted" is a bool which is true if marked as deleted, false | ||
59 | * otherwise. | ||
60 | */ | ||
61 | struct tomoyo_no_rewrite_entry { | ||
62 | struct list_head list; | ||
63 | const struct tomoyo_path_info *pattern; | ||
64 | bool is_deleted; | ||
65 | }; | ||
66 | 14 | ||
67 | /* Keyword array for single path operations. */ | 15 | /* Keyword array for single path operations. */ |
68 | static const char *tomoyo_sp_keyword[TOMOYO_MAX_SINGLE_PATH_OPERATION] = { | 16 | static const char *tomoyo_path_keyword[TOMOYO_MAX_PATH_OPERATION] = { |
69 | [TOMOYO_TYPE_READ_WRITE_ACL] = "read/write", | 17 | [TOMOYO_TYPE_READ_WRITE] = "read/write", |
70 | [TOMOYO_TYPE_EXECUTE_ACL] = "execute", | 18 | [TOMOYO_TYPE_EXECUTE] = "execute", |
71 | [TOMOYO_TYPE_READ_ACL] = "read", | 19 | [TOMOYO_TYPE_READ] = "read", |
72 | [TOMOYO_TYPE_WRITE_ACL] = "write", | 20 | [TOMOYO_TYPE_WRITE] = "write", |
73 | [TOMOYO_TYPE_CREATE_ACL] = "create", | 21 | [TOMOYO_TYPE_CREATE] = "create", |
74 | [TOMOYO_TYPE_UNLINK_ACL] = "unlink", | 22 | [TOMOYO_TYPE_UNLINK] = "unlink", |
75 | [TOMOYO_TYPE_MKDIR_ACL] = "mkdir", | 23 | [TOMOYO_TYPE_MKDIR] = "mkdir", |
76 | [TOMOYO_TYPE_RMDIR_ACL] = "rmdir", | 24 | [TOMOYO_TYPE_RMDIR] = "rmdir", |
77 | [TOMOYO_TYPE_MKFIFO_ACL] = "mkfifo", | 25 | [TOMOYO_TYPE_MKFIFO] = "mkfifo", |
78 | [TOMOYO_TYPE_MKSOCK_ACL] = "mksock", | 26 | [TOMOYO_TYPE_MKSOCK] = "mksock", |
79 | [TOMOYO_TYPE_MKBLOCK_ACL] = "mkblock", | 27 | [TOMOYO_TYPE_MKBLOCK] = "mkblock", |
80 | [TOMOYO_TYPE_MKCHAR_ACL] = "mkchar", | 28 | [TOMOYO_TYPE_MKCHAR] = "mkchar", |
81 | [TOMOYO_TYPE_TRUNCATE_ACL] = "truncate", | 29 | [TOMOYO_TYPE_TRUNCATE] = "truncate", |
82 | [TOMOYO_TYPE_SYMLINK_ACL] = "symlink", | 30 | [TOMOYO_TYPE_SYMLINK] = "symlink", |
83 | [TOMOYO_TYPE_REWRITE_ACL] = "rewrite", | 31 | [TOMOYO_TYPE_REWRITE] = "rewrite", |
32 | [TOMOYO_TYPE_IOCTL] = "ioctl", | ||
33 | [TOMOYO_TYPE_CHMOD] = "chmod", | ||
34 | [TOMOYO_TYPE_CHOWN] = "chown", | ||
35 | [TOMOYO_TYPE_CHGRP] = "chgrp", | ||
36 | [TOMOYO_TYPE_CHROOT] = "chroot", | ||
37 | [TOMOYO_TYPE_MOUNT] = "mount", | ||
38 | [TOMOYO_TYPE_UMOUNT] = "unmount", | ||
84 | }; | 39 | }; |
85 | 40 | ||
86 | /* Keyword array for double path operations. */ | 41 | /* Keyword array for double path operations. */ |
87 | static const char *tomoyo_dp_keyword[TOMOYO_MAX_DOUBLE_PATH_OPERATION] = { | 42 | static const char *tomoyo_path2_keyword[TOMOYO_MAX_PATH2_OPERATION] = { |
88 | [TOMOYO_TYPE_LINK_ACL] = "link", | 43 | [TOMOYO_TYPE_LINK] = "link", |
89 | [TOMOYO_TYPE_RENAME_ACL] = "rename", | 44 | [TOMOYO_TYPE_RENAME] = "rename", |
45 | [TOMOYO_TYPE_PIVOT_ROOT] = "pivot_root", | ||
90 | }; | 46 | }; |
91 | 47 | ||
92 | /** | 48 | /** |
93 | * tomoyo_sp2keyword - Get the name of single path operation. | 49 | * tomoyo_path2keyword - Get the name of single path operation. |
94 | * | 50 | * |
95 | * @operation: Type of operation. | 51 | * @operation: Type of operation. |
96 | * | 52 | * |
97 | * Returns the name of single path operation. | 53 | * Returns the name of single path operation. |
98 | */ | 54 | */ |
99 | const char *tomoyo_sp2keyword(const u8 operation) | 55 | const char *tomoyo_path2keyword(const u8 operation) |
100 | { | 56 | { |
101 | return (operation < TOMOYO_MAX_SINGLE_PATH_OPERATION) | 57 | return (operation < TOMOYO_MAX_PATH_OPERATION) |
102 | ? tomoyo_sp_keyword[operation] : NULL; | 58 | ? tomoyo_path_keyword[operation] : NULL; |
103 | } | 59 | } |
104 | 60 | ||
105 | /** | 61 | /** |
106 | * tomoyo_dp2keyword - Get the name of double path operation. | 62 | * tomoyo_path22keyword - Get the name of double path operation. |
107 | * | 63 | * |
108 | * @operation: Type of operation. | 64 | * @operation: Type of operation. |
109 | * | 65 | * |
110 | * Returns the name of double path operation. | 66 | * Returns the name of double path operation. |
111 | */ | 67 | */ |
112 | const char *tomoyo_dp2keyword(const u8 operation) | 68 | const char *tomoyo_path22keyword(const u8 operation) |
113 | { | 69 | { |
114 | return (operation < TOMOYO_MAX_DOUBLE_PATH_OPERATION) | 70 | return (operation < TOMOYO_MAX_PATH2_OPERATION) |
115 | ? tomoyo_dp_keyword[operation] : NULL; | 71 | ? tomoyo_path2_keyword[operation] : NULL; |
116 | } | 72 | } |
117 | 73 | ||
118 | /** | 74 | /** |
@@ -143,7 +99,8 @@ static bool tomoyo_strendswith(const char *name, const char *tail) | |||
143 | static struct tomoyo_path_info *tomoyo_get_path(struct path *path) | 99 | static struct tomoyo_path_info *tomoyo_get_path(struct path *path) |
144 | { | 100 | { |
145 | int error; | 101 | int error; |
146 | struct tomoyo_path_info_with_data *buf = tomoyo_alloc(sizeof(*buf)); | 102 | struct tomoyo_path_info_with_data *buf = kzalloc(sizeof(*buf), |
103 | GFP_KERNEL); | ||
147 | 104 | ||
148 | if (!buf) | 105 | if (!buf) |
149 | return NULL; | 106 | return NULL; |
@@ -155,20 +112,17 @@ static struct tomoyo_path_info *tomoyo_get_path(struct path *path) | |||
155 | tomoyo_fill_path_info(&buf->head); | 112 | tomoyo_fill_path_info(&buf->head); |
156 | return &buf->head; | 113 | return &buf->head; |
157 | } | 114 | } |
158 | tomoyo_free(buf); | 115 | kfree(buf); |
159 | return NULL; | 116 | return NULL; |
160 | } | 117 | } |
161 | 118 | ||
162 | /* Lock for domain->acl_info_list. */ | 119 | static int tomoyo_update_path2_acl(const u8 type, const char *filename1, |
163 | DECLARE_RWSEM(tomoyo_domain_acl_info_list_lock); | 120 | const char *filename2, |
164 | 121 | struct tomoyo_domain_info *const domain, | |
165 | static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, | 122 | const bool is_delete); |
166 | const char *filename2, | 123 | static int tomoyo_update_path_acl(const u8 type, const char *filename, |
167 | struct tomoyo_domain_info * | 124 | struct tomoyo_domain_info *const domain, |
168 | const domain, const bool is_delete); | 125 | const bool is_delete); |
169 | static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | ||
170 | struct tomoyo_domain_info * | ||
171 | const domain, const bool is_delete); | ||
172 | 126 | ||
173 | /* | 127 | /* |
174 | * tomoyo_globally_readable_list is used for holding list of pathnames which | 128 | * tomoyo_globally_readable_list is used for holding list of pathnames which |
@@ -195,8 +149,7 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | |||
195 | * given "allow_read /lib/libc-2.5.so" to the domain which current process | 149 | * given "allow_read /lib/libc-2.5.so" to the domain which current process |
196 | * belongs to. | 150 | * belongs to. |
197 | */ | 151 | */ |
198 | static LIST_HEAD(tomoyo_globally_readable_list); | 152 | LIST_HEAD(tomoyo_globally_readable_list); |
199 | static DECLARE_RWSEM(tomoyo_globally_readable_list_lock); | ||
200 | 153 | ||
201 | /** | 154 | /** |
202 | * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list. | 155 | * tomoyo_update_globally_readable_entry - Update "struct tomoyo_globally_readable_file_entry" list. |
@@ -205,40 +158,42 @@ static DECLARE_RWSEM(tomoyo_globally_readable_list_lock); | |||
205 | * @is_delete: True if it is a delete request. | 158 | * @is_delete: True if it is a delete request. |
206 | * | 159 | * |
207 | * Returns 0 on success, negative value otherwise. | 160 | * Returns 0 on success, negative value otherwise. |
161 | * | ||
162 | * Caller holds tomoyo_read_lock(). | ||
208 | */ | 163 | */ |
209 | static int tomoyo_update_globally_readable_entry(const char *filename, | 164 | static int tomoyo_update_globally_readable_entry(const char *filename, |
210 | const bool is_delete) | 165 | const bool is_delete) |
211 | { | 166 | { |
212 | struct tomoyo_globally_readable_file_entry *new_entry; | 167 | struct tomoyo_globally_readable_file_entry *entry = NULL; |
213 | struct tomoyo_globally_readable_file_entry *ptr; | 168 | struct tomoyo_globally_readable_file_entry *ptr; |
214 | const struct tomoyo_path_info *saved_filename; | 169 | const struct tomoyo_path_info *saved_filename; |
215 | int error = -ENOMEM; | 170 | int error = is_delete ? -ENOENT : -ENOMEM; |
216 | 171 | ||
217 | if (!tomoyo_is_correct_path(filename, 1, 0, -1, __func__)) | 172 | if (!tomoyo_is_correct_path(filename, 1, 0, -1)) |
218 | return -EINVAL; | 173 | return -EINVAL; |
219 | saved_filename = tomoyo_save_name(filename); | 174 | saved_filename = tomoyo_get_name(filename); |
220 | if (!saved_filename) | 175 | if (!saved_filename) |
221 | return -ENOMEM; | 176 | return -ENOMEM; |
222 | down_write(&tomoyo_globally_readable_list_lock); | 177 | if (!is_delete) |
223 | list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) { | 178 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
179 | mutex_lock(&tomoyo_policy_lock); | ||
180 | list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { | ||
224 | if (ptr->filename != saved_filename) | 181 | if (ptr->filename != saved_filename) |
225 | continue; | 182 | continue; |
226 | ptr->is_deleted = is_delete; | 183 | ptr->is_deleted = is_delete; |
227 | error = 0; | 184 | error = 0; |
228 | goto out; | 185 | break; |
229 | } | 186 | } |
230 | if (is_delete) { | 187 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
231 | error = -ENOENT; | 188 | entry->filename = saved_filename; |
232 | goto out; | 189 | saved_filename = NULL; |
190 | list_add_tail_rcu(&entry->list, &tomoyo_globally_readable_list); | ||
191 | entry = NULL; | ||
192 | error = 0; | ||
233 | } | 193 | } |
234 | new_entry = tomoyo_alloc_element(sizeof(*new_entry)); | 194 | mutex_unlock(&tomoyo_policy_lock); |
235 | if (!new_entry) | 195 | tomoyo_put_name(saved_filename); |
236 | goto out; | 196 | kfree(entry); |
237 | new_entry->filename = saved_filename; | ||
238 | list_add_tail(&new_entry->list, &tomoyo_globally_readable_list); | ||
239 | error = 0; | ||
240 | out: | ||
241 | up_write(&tomoyo_globally_readable_list_lock); | ||
242 | return error; | 197 | return error; |
243 | } | 198 | } |
244 | 199 | ||
@@ -248,21 +203,22 @@ static int tomoyo_update_globally_readable_entry(const char *filename, | |||
248 | * @filename: The filename to check. | 203 | * @filename: The filename to check. |
249 | * | 204 | * |
250 | * Returns true if any domain can open @filename for reading, false otherwise. | 205 | * Returns true if any domain can open @filename for reading, false otherwise. |
206 | * | ||
207 | * Caller holds tomoyo_read_lock(). | ||
251 | */ | 208 | */ |
252 | static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info * | 209 | static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info * |
253 | filename) | 210 | filename) |
254 | { | 211 | { |
255 | struct tomoyo_globally_readable_file_entry *ptr; | 212 | struct tomoyo_globally_readable_file_entry *ptr; |
256 | bool found = false; | 213 | bool found = false; |
257 | down_read(&tomoyo_globally_readable_list_lock); | 214 | |
258 | list_for_each_entry(ptr, &tomoyo_globally_readable_list, list) { | 215 | list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, list) { |
259 | if (!ptr->is_deleted && | 216 | if (!ptr->is_deleted && |
260 | tomoyo_path_matches_pattern(filename, ptr->filename)) { | 217 | tomoyo_path_matches_pattern(filename, ptr->filename)) { |
261 | found = true; | 218 | found = true; |
262 | break; | 219 | break; |
263 | } | 220 | } |
264 | } | 221 | } |
265 | up_read(&tomoyo_globally_readable_list_lock); | ||
266 | return found; | 222 | return found; |
267 | } | 223 | } |
268 | 224 | ||
@@ -273,6 +229,8 @@ static bool tomoyo_is_globally_readable_file(const struct tomoyo_path_info * | |||
273 | * @is_delete: True if it is a delete request. | 229 | * @is_delete: True if it is a delete request. |
274 | * | 230 | * |
275 | * Returns 0 on success, negative value otherwise. | 231 | * Returns 0 on success, negative value otherwise. |
232 | * | ||
233 | * Caller holds tomoyo_read_lock(). | ||
276 | */ | 234 | */ |
277 | int tomoyo_write_globally_readable_policy(char *data, const bool is_delete) | 235 | int tomoyo_write_globally_readable_policy(char *data, const bool is_delete) |
278 | { | 236 | { |
@@ -285,13 +243,14 @@ int tomoyo_write_globally_readable_policy(char *data, const bool is_delete) | |||
285 | * @head: Pointer to "struct tomoyo_io_buffer". | 243 | * @head: Pointer to "struct tomoyo_io_buffer". |
286 | * | 244 | * |
287 | * Returns true on success, false otherwise. | 245 | * Returns true on success, false otherwise. |
246 | * | ||
247 | * Caller holds tomoyo_read_lock(). | ||
288 | */ | 248 | */ |
289 | bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) | 249 | bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) |
290 | { | 250 | { |
291 | struct list_head *pos; | 251 | struct list_head *pos; |
292 | bool done = true; | 252 | bool done = true; |
293 | 253 | ||
294 | down_read(&tomoyo_globally_readable_list_lock); | ||
295 | list_for_each_cookie(pos, head->read_var2, | 254 | list_for_each_cookie(pos, head->read_var2, |
296 | &tomoyo_globally_readable_list) { | 255 | &tomoyo_globally_readable_list) { |
297 | struct tomoyo_globally_readable_file_entry *ptr; | 256 | struct tomoyo_globally_readable_file_entry *ptr; |
@@ -305,7 +264,6 @@ bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) | |||
305 | if (!done) | 264 | if (!done) |
306 | break; | 265 | break; |
307 | } | 266 | } |
308 | up_read(&tomoyo_globally_readable_list_lock); | ||
309 | return done; | 267 | return done; |
310 | } | 268 | } |
311 | 269 | ||
@@ -338,8 +296,7 @@ bool tomoyo_read_globally_readable_policy(struct tomoyo_io_buffer *head) | |||
338 | * which pretends as if /proc/self/ is not a symlink; so that we can forbid | 296 | * which pretends as if /proc/self/ is not a symlink; so that we can forbid |
339 | * current process from accessing other process's information. | 297 | * current process from accessing other process's information. |
340 | */ | 298 | */ |
341 | static LIST_HEAD(tomoyo_pattern_list); | 299 | LIST_HEAD(tomoyo_pattern_list); |
342 | static DECLARE_RWSEM(tomoyo_pattern_list_lock); | ||
343 | 300 | ||
344 | /** | 301 | /** |
345 | * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list. | 302 | * tomoyo_update_file_pattern_entry - Update "struct tomoyo_pattern_entry" list. |
@@ -348,40 +305,43 @@ static DECLARE_RWSEM(tomoyo_pattern_list_lock); | |||
348 | * @is_delete: True if it is a delete request. | 305 | * @is_delete: True if it is a delete request. |
349 | * | 306 | * |
350 | * Returns 0 on success, negative value otherwise. | 307 | * Returns 0 on success, negative value otherwise. |
308 | * | ||
309 | * Caller holds tomoyo_read_lock(). | ||
351 | */ | 310 | */ |
352 | static int tomoyo_update_file_pattern_entry(const char *pattern, | 311 | static int tomoyo_update_file_pattern_entry(const char *pattern, |
353 | const bool is_delete) | 312 | const bool is_delete) |
354 | { | 313 | { |
355 | struct tomoyo_pattern_entry *new_entry; | 314 | struct tomoyo_pattern_entry *entry = NULL; |
356 | struct tomoyo_pattern_entry *ptr; | 315 | struct tomoyo_pattern_entry *ptr; |
357 | const struct tomoyo_path_info *saved_pattern; | 316 | const struct tomoyo_path_info *saved_pattern; |
358 | int error = -ENOMEM; | 317 | int error = is_delete ? -ENOENT : -ENOMEM; |
359 | 318 | ||
360 | if (!tomoyo_is_correct_path(pattern, 0, 1, 0, __func__)) | 319 | saved_pattern = tomoyo_get_name(pattern); |
361 | return -EINVAL; | ||
362 | saved_pattern = tomoyo_save_name(pattern); | ||
363 | if (!saved_pattern) | 320 | if (!saved_pattern) |
364 | return -ENOMEM; | 321 | return error; |
365 | down_write(&tomoyo_pattern_list_lock); | 322 | if (!saved_pattern->is_patterned) |
366 | list_for_each_entry(ptr, &tomoyo_pattern_list, list) { | 323 | goto out; |
324 | if (!is_delete) | ||
325 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); | ||
326 | mutex_lock(&tomoyo_policy_lock); | ||
327 | list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { | ||
367 | if (saved_pattern != ptr->pattern) | 328 | if (saved_pattern != ptr->pattern) |
368 | continue; | 329 | continue; |
369 | ptr->is_deleted = is_delete; | 330 | ptr->is_deleted = is_delete; |
370 | error = 0; | 331 | error = 0; |
371 | goto out; | 332 | break; |
372 | } | 333 | } |
373 | if (is_delete) { | 334 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
374 | error = -ENOENT; | 335 | entry->pattern = saved_pattern; |
375 | goto out; | 336 | saved_pattern = NULL; |
337 | list_add_tail_rcu(&entry->list, &tomoyo_pattern_list); | ||
338 | entry = NULL; | ||
339 | error = 0; | ||
376 | } | 340 | } |
377 | new_entry = tomoyo_alloc_element(sizeof(*new_entry)); | 341 | mutex_unlock(&tomoyo_policy_lock); |
378 | if (!new_entry) | ||
379 | goto out; | ||
380 | new_entry->pattern = saved_pattern; | ||
381 | list_add_tail(&new_entry->list, &tomoyo_pattern_list); | ||
382 | error = 0; | ||
383 | out: | 342 | out: |
384 | up_write(&tomoyo_pattern_list_lock); | 343 | kfree(entry); |
344 | tomoyo_put_name(saved_pattern); | ||
385 | return error; | 345 | return error; |
386 | } | 346 | } |
387 | 347 | ||
@@ -391,6 +351,8 @@ static int tomoyo_update_file_pattern_entry(const char *pattern, | |||
391 | * @filename: The filename to find patterned pathname. | 351 | * @filename: The filename to find patterned pathname. |
392 | * | 352 | * |
393 | * Returns pointer to pathname pattern if matched, @filename otherwise. | 353 | * Returns pointer to pathname pattern if matched, @filename otherwise. |
354 | * | ||
355 | * Caller holds tomoyo_read_lock(). | ||
394 | */ | 356 | */ |
395 | static const struct tomoyo_path_info * | 357 | static const struct tomoyo_path_info * |
396 | tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) | 358 | tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) |
@@ -398,8 +360,7 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) | |||
398 | struct tomoyo_pattern_entry *ptr; | 360 | struct tomoyo_pattern_entry *ptr; |
399 | const struct tomoyo_path_info *pattern = NULL; | 361 | const struct tomoyo_path_info *pattern = NULL; |
400 | 362 | ||
401 | down_read(&tomoyo_pattern_list_lock); | 363 | list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { |
402 | list_for_each_entry(ptr, &tomoyo_pattern_list, list) { | ||
403 | if (ptr->is_deleted) | 364 | if (ptr->is_deleted) |
404 | continue; | 365 | continue; |
405 | if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) | 366 | if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) |
@@ -412,7 +373,6 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) | |||
412 | break; | 373 | break; |
413 | } | 374 | } |
414 | } | 375 | } |
415 | up_read(&tomoyo_pattern_list_lock); | ||
416 | if (pattern) | 376 | if (pattern) |
417 | filename = pattern; | 377 | filename = pattern; |
418 | return filename; | 378 | return filename; |
@@ -425,6 +385,8 @@ tomoyo_get_file_pattern(const struct tomoyo_path_info *filename) | |||
425 | * @is_delete: True if it is a delete request. | 385 | * @is_delete: True if it is a delete request. |
426 | * | 386 | * |
427 | * Returns 0 on success, negative value otherwise. | 387 | * Returns 0 on success, negative value otherwise. |
388 | * | ||
389 | * Caller holds tomoyo_read_lock(). | ||
428 | */ | 390 | */ |
429 | int tomoyo_write_pattern_policy(char *data, const bool is_delete) | 391 | int tomoyo_write_pattern_policy(char *data, const bool is_delete) |
430 | { | 392 | { |
@@ -437,13 +399,14 @@ int tomoyo_write_pattern_policy(char *data, const bool is_delete) | |||
437 | * @head: Pointer to "struct tomoyo_io_buffer". | 399 | * @head: Pointer to "struct tomoyo_io_buffer". |
438 | * | 400 | * |
439 | * Returns true on success, false otherwise. | 401 | * Returns true on success, false otherwise. |
402 | * | ||
403 | * Caller holds tomoyo_read_lock(). | ||
440 | */ | 404 | */ |
441 | bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) | 405 | bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) |
442 | { | 406 | { |
443 | struct list_head *pos; | 407 | struct list_head *pos; |
444 | bool done = true; | 408 | bool done = true; |
445 | 409 | ||
446 | down_read(&tomoyo_pattern_list_lock); | ||
447 | list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) { | 410 | list_for_each_cookie(pos, head->read_var2, &tomoyo_pattern_list) { |
448 | struct tomoyo_pattern_entry *ptr; | 411 | struct tomoyo_pattern_entry *ptr; |
449 | ptr = list_entry(pos, struct tomoyo_pattern_entry, list); | 412 | ptr = list_entry(pos, struct tomoyo_pattern_entry, list); |
@@ -454,7 +417,6 @@ bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) | |||
454 | if (!done) | 417 | if (!done) |
455 | break; | 418 | break; |
456 | } | 419 | } |
457 | up_read(&tomoyo_pattern_list_lock); | ||
458 | return done; | 420 | return done; |
459 | } | 421 | } |
460 | 422 | ||
@@ -487,8 +449,7 @@ bool tomoyo_read_file_pattern(struct tomoyo_io_buffer *head) | |||
487 | * " (deleted)" suffix if the file is already unlink()ed; so that we don't | 449 | * " (deleted)" suffix if the file is already unlink()ed; so that we don't |
488 | * need to worry whether the file is already unlink()ed or not. | 450 | * need to worry whether the file is already unlink()ed or not. |
489 | */ | 451 | */ |
490 | static LIST_HEAD(tomoyo_no_rewrite_list); | 452 | LIST_HEAD(tomoyo_no_rewrite_list); |
491 | static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock); | ||
492 | 453 | ||
493 | /** | 454 | /** |
494 | * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list. | 455 | * tomoyo_update_no_rewrite_entry - Update "struct tomoyo_no_rewrite_entry" list. |
@@ -497,39 +458,42 @@ static DECLARE_RWSEM(tomoyo_no_rewrite_list_lock); | |||
497 | * @is_delete: True if it is a delete request. | 458 | * @is_delete: True if it is a delete request. |
498 | * | 459 | * |
499 | * Returns 0 on success, negative value otherwise. | 460 | * Returns 0 on success, negative value otherwise. |
461 | * | ||
462 | * Caller holds tomoyo_read_lock(). | ||
500 | */ | 463 | */ |
501 | static int tomoyo_update_no_rewrite_entry(const char *pattern, | 464 | static int tomoyo_update_no_rewrite_entry(const char *pattern, |
502 | const bool is_delete) | 465 | const bool is_delete) |
503 | { | 466 | { |
504 | struct tomoyo_no_rewrite_entry *new_entry, *ptr; | 467 | struct tomoyo_no_rewrite_entry *entry = NULL; |
468 | struct tomoyo_no_rewrite_entry *ptr; | ||
505 | const struct tomoyo_path_info *saved_pattern; | 469 | const struct tomoyo_path_info *saved_pattern; |
506 | int error = -ENOMEM; | 470 | int error = is_delete ? -ENOENT : -ENOMEM; |
507 | 471 | ||
508 | if (!tomoyo_is_correct_path(pattern, 0, 0, 0, __func__)) | 472 | if (!tomoyo_is_correct_path(pattern, 0, 0, 0)) |
509 | return -EINVAL; | 473 | return -EINVAL; |
510 | saved_pattern = tomoyo_save_name(pattern); | 474 | saved_pattern = tomoyo_get_name(pattern); |
511 | if (!saved_pattern) | 475 | if (!saved_pattern) |
512 | return -ENOMEM; | 476 | return error; |
513 | down_write(&tomoyo_no_rewrite_list_lock); | 477 | if (!is_delete) |
514 | list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) { | 478 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
479 | mutex_lock(&tomoyo_policy_lock); | ||
480 | list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { | ||
515 | if (ptr->pattern != saved_pattern) | 481 | if (ptr->pattern != saved_pattern) |
516 | continue; | 482 | continue; |
517 | ptr->is_deleted = is_delete; | 483 | ptr->is_deleted = is_delete; |
518 | error = 0; | 484 | error = 0; |
519 | goto out; | 485 | break; |
520 | } | 486 | } |
521 | if (is_delete) { | 487 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
522 | error = -ENOENT; | 488 | entry->pattern = saved_pattern; |
523 | goto out; | 489 | saved_pattern = NULL; |
490 | list_add_tail_rcu(&entry->list, &tomoyo_no_rewrite_list); | ||
491 | entry = NULL; | ||
492 | error = 0; | ||
524 | } | 493 | } |
525 | new_entry = tomoyo_alloc_element(sizeof(*new_entry)); | 494 | mutex_unlock(&tomoyo_policy_lock); |
526 | if (!new_entry) | 495 | tomoyo_put_name(saved_pattern); |
527 | goto out; | 496 | kfree(entry); |
528 | new_entry->pattern = saved_pattern; | ||
529 | list_add_tail(&new_entry->list, &tomoyo_no_rewrite_list); | ||
530 | error = 0; | ||
531 | out: | ||
532 | up_write(&tomoyo_no_rewrite_list_lock); | ||
533 | return error; | 497 | return error; |
534 | } | 498 | } |
535 | 499 | ||
@@ -540,14 +504,15 @@ static int tomoyo_update_no_rewrite_entry(const char *pattern, | |||
540 | * | 504 | * |
541 | * Returns true if @filename is specified by "deny_rewrite" directive, | 505 | * Returns true if @filename is specified by "deny_rewrite" directive, |
542 | * false otherwise. | 506 | * false otherwise. |
507 | * | ||
508 | * Caller holds tomoyo_read_lock(). | ||
543 | */ | 509 | */ |
544 | static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) | 510 | static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) |
545 | { | 511 | { |
546 | struct tomoyo_no_rewrite_entry *ptr; | 512 | struct tomoyo_no_rewrite_entry *ptr; |
547 | bool found = false; | 513 | bool found = false; |
548 | 514 | ||
549 | down_read(&tomoyo_no_rewrite_list_lock); | 515 | list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { |
550 | list_for_each_entry(ptr, &tomoyo_no_rewrite_list, list) { | ||
551 | if (ptr->is_deleted) | 516 | if (ptr->is_deleted) |
552 | continue; | 517 | continue; |
553 | if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) | 518 | if (!tomoyo_path_matches_pattern(filename, ptr->pattern)) |
@@ -555,7 +520,6 @@ static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) | |||
555 | found = true; | 520 | found = true; |
556 | break; | 521 | break; |
557 | } | 522 | } |
558 | up_read(&tomoyo_no_rewrite_list_lock); | ||
559 | return found; | 523 | return found; |
560 | } | 524 | } |
561 | 525 | ||
@@ -566,6 +530,8 @@ static bool tomoyo_is_no_rewrite_file(const struct tomoyo_path_info *filename) | |||
566 | * @is_delete: True if it is a delete request. | 530 | * @is_delete: True if it is a delete request. |
567 | * | 531 | * |
568 | * Returns 0 on success, negative value otherwise. | 532 | * Returns 0 on success, negative value otherwise. |
533 | * | ||
534 | * Caller holds tomoyo_read_lock(). | ||
569 | */ | 535 | */ |
570 | int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete) | 536 | int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete) |
571 | { | 537 | { |
@@ -578,13 +544,14 @@ int tomoyo_write_no_rewrite_policy(char *data, const bool is_delete) | |||
578 | * @head: Pointer to "struct tomoyo_io_buffer". | 544 | * @head: Pointer to "struct tomoyo_io_buffer". |
579 | * | 545 | * |
580 | * Returns true on success, false otherwise. | 546 | * Returns true on success, false otherwise. |
547 | * | ||
548 | * Caller holds tomoyo_read_lock(). | ||
581 | */ | 549 | */ |
582 | bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) | 550 | bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) |
583 | { | 551 | { |
584 | struct list_head *pos; | 552 | struct list_head *pos; |
585 | bool done = true; | 553 | bool done = true; |
586 | 554 | ||
587 | down_read(&tomoyo_no_rewrite_list_lock); | ||
588 | list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) { | 555 | list_for_each_cookie(pos, head->read_var2, &tomoyo_no_rewrite_list) { |
589 | struct tomoyo_no_rewrite_entry *ptr; | 556 | struct tomoyo_no_rewrite_entry *ptr; |
590 | ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list); | 557 | ptr = list_entry(pos, struct tomoyo_no_rewrite_entry, list); |
@@ -595,7 +562,6 @@ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) | |||
595 | if (!done) | 562 | if (!done) |
596 | break; | 563 | break; |
597 | } | 564 | } |
598 | up_read(&tomoyo_no_rewrite_list_lock); | ||
599 | return done; | 565 | return done; |
600 | } | 566 | } |
601 | 567 | ||
@@ -613,6 +579,8 @@ bool tomoyo_read_no_rewrite_policy(struct tomoyo_io_buffer *head) | |||
613 | * Current policy syntax uses "allow_read/write" instead of "6", | 579 | * Current policy syntax uses "allow_read/write" instead of "6", |
614 | * "allow_read" instead of "4", "allow_write" instead of "2", | 580 | * "allow_read" instead of "4", "allow_write" instead of "2", |
615 | * "allow_execute" instead of "1". | 581 | * "allow_execute" instead of "1". |
582 | * | ||
583 | * Caller holds tomoyo_read_lock(). | ||
616 | */ | 584 | */ |
617 | static int tomoyo_update_file_acl(const char *filename, u8 perm, | 585 | static int tomoyo_update_file_acl(const char *filename, u8 perm, |
618 | struct tomoyo_domain_info * const domain, | 586 | struct tomoyo_domain_info * const domain, |
@@ -630,19 +598,19 @@ static int tomoyo_update_file_acl(const char *filename, u8 perm, | |||
630 | */ | 598 | */ |
631 | return 0; | 599 | return 0; |
632 | if (perm & 4) | 600 | if (perm & 4) |
633 | tomoyo_update_single_path_acl(TOMOYO_TYPE_READ_ACL, filename, | 601 | tomoyo_update_path_acl(TOMOYO_TYPE_READ, filename, domain, |
634 | domain, is_delete); | 602 | is_delete); |
635 | if (perm & 2) | 603 | if (perm & 2) |
636 | tomoyo_update_single_path_acl(TOMOYO_TYPE_WRITE_ACL, filename, | 604 | tomoyo_update_path_acl(TOMOYO_TYPE_WRITE, filename, domain, |
637 | domain, is_delete); | 605 | is_delete); |
638 | if (perm & 1) | 606 | if (perm & 1) |
639 | tomoyo_update_single_path_acl(TOMOYO_TYPE_EXECUTE_ACL, | 607 | tomoyo_update_path_acl(TOMOYO_TYPE_EXECUTE, filename, domain, |
640 | filename, domain, is_delete); | 608 | is_delete); |
641 | return 0; | 609 | return 0; |
642 | } | 610 | } |
643 | 611 | ||
644 | /** | 612 | /** |
645 | * tomoyo_check_single_path_acl2 - Check permission for single path operation. | 613 | * tomoyo_path_acl2 - Check permission for single path operation. |
646 | * | 614 | * |
647 | * @domain: Pointer to "struct tomoyo_domain_info". | 615 | * @domain: Pointer to "struct tomoyo_domain_info". |
648 | * @filename: Filename to check. | 616 | * @filename: Filename to check. |
@@ -650,26 +618,28 @@ static int tomoyo_update_file_acl(const char *filename, u8 perm, | |||
650 | * @may_use_pattern: True if patterned ACL is permitted. | 618 | * @may_use_pattern: True if patterned ACL is permitted. |
651 | * | 619 | * |
652 | * Returns 0 on success, -EPERM otherwise. | 620 | * Returns 0 on success, -EPERM otherwise. |
621 | * | ||
622 | * Caller holds tomoyo_read_lock(). | ||
653 | */ | 623 | */ |
654 | static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * | 624 | static int tomoyo_path_acl2(const struct tomoyo_domain_info *domain, |
655 | domain, | 625 | const struct tomoyo_path_info *filename, |
656 | const struct tomoyo_path_info * | 626 | const u32 perm, const bool may_use_pattern) |
657 | filename, | ||
658 | const u16 perm, | ||
659 | const bool may_use_pattern) | ||
660 | { | 627 | { |
661 | struct tomoyo_acl_info *ptr; | 628 | struct tomoyo_acl_info *ptr; |
662 | int error = -EPERM; | 629 | int error = -EPERM; |
663 | 630 | ||
664 | down_read(&tomoyo_domain_acl_info_list_lock); | 631 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
665 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | 632 | struct tomoyo_path_acl *acl; |
666 | struct tomoyo_single_path_acl_record *acl; | 633 | if (ptr->type != TOMOYO_TYPE_PATH_ACL) |
667 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) | ||
668 | continue; | ||
669 | acl = container_of(ptr, struct tomoyo_single_path_acl_record, | ||
670 | head); | ||
671 | if (!(acl->perm & perm)) | ||
672 | continue; | 634 | continue; |
635 | acl = container_of(ptr, struct tomoyo_path_acl, head); | ||
636 | if (perm <= 0xFFFF) { | ||
637 | if (!(acl->perm & perm)) | ||
638 | continue; | ||
639 | } else { | ||
640 | if (!(acl->perm_high & (perm >> 16))) | ||
641 | continue; | ||
642 | } | ||
673 | if (may_use_pattern || !acl->filename->is_patterned) { | 643 | if (may_use_pattern || !acl->filename->is_patterned) { |
674 | if (!tomoyo_path_matches_pattern(filename, | 644 | if (!tomoyo_path_matches_pattern(filename, |
675 | acl->filename)) | 645 | acl->filename)) |
@@ -680,7 +650,6 @@ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * | |||
680 | error = 0; | 650 | error = 0; |
681 | break; | 651 | break; |
682 | } | 652 | } |
683 | up_read(&tomoyo_domain_acl_info_list_lock); | ||
684 | return error; | 653 | return error; |
685 | } | 654 | } |
686 | 655 | ||
@@ -692,27 +661,28 @@ static int tomoyo_check_single_path_acl2(const struct tomoyo_domain_info * | |||
692 | * @operation: Mode ("read" or "write" or "read/write" or "execute"). | 661 | * @operation: Mode ("read" or "write" or "read/write" or "execute"). |
693 | * | 662 | * |
694 | * Returns 0 on success, -EPERM otherwise. | 663 | * Returns 0 on success, -EPERM otherwise. |
664 | * | ||
665 | * Caller holds tomoyo_read_lock(). | ||
695 | */ | 666 | */ |
696 | static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain, | 667 | static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain, |
697 | const struct tomoyo_path_info *filename, | 668 | const struct tomoyo_path_info *filename, |
698 | const u8 operation) | 669 | const u8 operation) |
699 | { | 670 | { |
700 | u16 perm = 0; | 671 | u32 perm = 0; |
701 | 672 | ||
702 | if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) | 673 | if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) |
703 | return 0; | 674 | return 0; |
704 | if (operation == 6) | 675 | if (operation == 6) |
705 | perm = 1 << TOMOYO_TYPE_READ_WRITE_ACL; | 676 | perm = 1 << TOMOYO_TYPE_READ_WRITE; |
706 | else if (operation == 4) | 677 | else if (operation == 4) |
707 | perm = 1 << TOMOYO_TYPE_READ_ACL; | 678 | perm = 1 << TOMOYO_TYPE_READ; |
708 | else if (operation == 2) | 679 | else if (operation == 2) |
709 | perm = 1 << TOMOYO_TYPE_WRITE_ACL; | 680 | perm = 1 << TOMOYO_TYPE_WRITE; |
710 | else if (operation == 1) | 681 | else if (operation == 1) |
711 | perm = 1 << TOMOYO_TYPE_EXECUTE_ACL; | 682 | perm = 1 << TOMOYO_TYPE_EXECUTE; |
712 | else | 683 | else |
713 | BUG(); | 684 | BUG(); |
714 | return tomoyo_check_single_path_acl2(domain, filename, perm, | 685 | return tomoyo_path_acl2(domain, filename, perm, operation != 1); |
715 | operation != 1); | ||
716 | } | 686 | } |
717 | 687 | ||
718 | /** | 688 | /** |
@@ -725,6 +695,8 @@ static int tomoyo_check_file_acl(const struct tomoyo_domain_info *domain, | |||
725 | * @mode: Access control mode. | 695 | * @mode: Access control mode. |
726 | * | 696 | * |
727 | * Returns 0 on success, negative value otherwise. | 697 | * Returns 0 on success, negative value otherwise. |
698 | * | ||
699 | * Caller holds tomoyo_read_lock(). | ||
728 | */ | 700 | */ |
729 | static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, | 701 | static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, |
730 | const struct tomoyo_path_info *filename, | 702 | const struct tomoyo_path_info *filename, |
@@ -738,18 +710,17 @@ static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, | |||
738 | if (!filename) | 710 | if (!filename) |
739 | return 0; | 711 | return 0; |
740 | error = tomoyo_check_file_acl(domain, filename, perm); | 712 | error = tomoyo_check_file_acl(domain, filename, perm); |
741 | if (error && perm == 4 && | 713 | if (error && perm == 4 && !domain->ignore_global_allow_read |
742 | (domain->flags & TOMOYO_DOMAIN_FLAGS_IGNORE_GLOBAL_ALLOW_READ) == 0 | ||
743 | && tomoyo_is_globally_readable_file(filename)) | 714 | && tomoyo_is_globally_readable_file(filename)) |
744 | error = 0; | 715 | error = 0; |
745 | if (perm == 6) | 716 | if (perm == 6) |
746 | msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_WRITE_ACL); | 717 | msg = tomoyo_path2keyword(TOMOYO_TYPE_READ_WRITE); |
747 | else if (perm == 4) | 718 | else if (perm == 4) |
748 | msg = tomoyo_sp2keyword(TOMOYO_TYPE_READ_ACL); | 719 | msg = tomoyo_path2keyword(TOMOYO_TYPE_READ); |
749 | else if (perm == 2) | 720 | else if (perm == 2) |
750 | msg = tomoyo_sp2keyword(TOMOYO_TYPE_WRITE_ACL); | 721 | msg = tomoyo_path2keyword(TOMOYO_TYPE_WRITE); |
751 | else if (perm == 1) | 722 | else if (perm == 1) |
752 | msg = tomoyo_sp2keyword(TOMOYO_TYPE_EXECUTE_ACL); | 723 | msg = tomoyo_path2keyword(TOMOYO_TYPE_EXECUTE); |
753 | else | 724 | else |
754 | BUG(); | 725 | BUG(); |
755 | if (!error) | 726 | if (!error) |
@@ -778,6 +749,8 @@ static int tomoyo_check_file_perm2(struct tomoyo_domain_info * const domain, | |||
778 | * @is_delete: True if it is a delete request. | 749 | * @is_delete: True if it is a delete request. |
779 | * | 750 | * |
780 | * Returns 0 on success, negative value otherwise. | 751 | * Returns 0 on success, negative value otherwise. |
752 | * | ||
753 | * Caller holds tomoyo_read_lock(). | ||
781 | */ | 754 | */ |
782 | int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, | 755 | int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, |
783 | const bool is_delete) | 756 | const bool is_delete) |
@@ -796,28 +769,28 @@ int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, | |||
796 | if (strncmp(data, "allow_", 6)) | 769 | if (strncmp(data, "allow_", 6)) |
797 | goto out; | 770 | goto out; |
798 | data += 6; | 771 | data += 6; |
799 | for (type = 0; type < TOMOYO_MAX_SINGLE_PATH_OPERATION; type++) { | 772 | for (type = 0; type < TOMOYO_MAX_PATH_OPERATION; type++) { |
800 | if (strcmp(data, tomoyo_sp_keyword[type])) | 773 | if (strcmp(data, tomoyo_path_keyword[type])) |
801 | continue; | 774 | continue; |
802 | return tomoyo_update_single_path_acl(type, filename, | 775 | return tomoyo_update_path_acl(type, filename, domain, |
803 | domain, is_delete); | 776 | is_delete); |
804 | } | 777 | } |
805 | filename2 = strchr(filename, ' '); | 778 | filename2 = strchr(filename, ' '); |
806 | if (!filename2) | 779 | if (!filename2) |
807 | goto out; | 780 | goto out; |
808 | *filename2++ = '\0'; | 781 | *filename2++ = '\0'; |
809 | for (type = 0; type < TOMOYO_MAX_DOUBLE_PATH_OPERATION; type++) { | 782 | for (type = 0; type < TOMOYO_MAX_PATH2_OPERATION; type++) { |
810 | if (strcmp(data, tomoyo_dp_keyword[type])) | 783 | if (strcmp(data, tomoyo_path2_keyword[type])) |
811 | continue; | 784 | continue; |
812 | return tomoyo_update_double_path_acl(type, filename, filename2, | 785 | return tomoyo_update_path2_acl(type, filename, filename2, |
813 | domain, is_delete); | 786 | domain, is_delete); |
814 | } | 787 | } |
815 | out: | 788 | out: |
816 | return -EINVAL; | 789 | return -EINVAL; |
817 | } | 790 | } |
818 | 791 | ||
819 | /** | 792 | /** |
820 | * tomoyo_update_single_path_acl - Update "struct tomoyo_single_path_acl_record" list. | 793 | * tomoyo_update_path_acl - Update "struct tomoyo_path_acl" list. |
821 | * | 794 | * |
822 | * @type: Type of operation. | 795 | * @type: Type of operation. |
823 | * @filename: Filename. | 796 | * @filename: Filename. |
@@ -825,85 +798,82 @@ int tomoyo_write_file_policy(char *data, struct tomoyo_domain_info *domain, | |||
825 | * @is_delete: True if it is a delete request. | 798 | * @is_delete: True if it is a delete request. |
826 | * | 799 | * |
827 | * Returns 0 on success, negative value otherwise. | 800 | * Returns 0 on success, negative value otherwise. |
801 | * | ||
802 | * Caller holds tomoyo_read_lock(). | ||
828 | */ | 803 | */ |
829 | static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | 804 | static int tomoyo_update_path_acl(const u8 type, const char *filename, |
830 | struct tomoyo_domain_info * | 805 | struct tomoyo_domain_info *const domain, |
831 | const domain, const bool is_delete) | 806 | const bool is_delete) |
832 | { | 807 | { |
833 | static const u16 rw_mask = | 808 | static const u32 rw_mask = |
834 | (1 << TOMOYO_TYPE_READ_ACL) | (1 << TOMOYO_TYPE_WRITE_ACL); | 809 | (1 << TOMOYO_TYPE_READ) | (1 << TOMOYO_TYPE_WRITE); |
835 | const struct tomoyo_path_info *saved_filename; | 810 | const struct tomoyo_path_info *saved_filename; |
836 | struct tomoyo_acl_info *ptr; | 811 | struct tomoyo_acl_info *ptr; |
837 | struct tomoyo_single_path_acl_record *acl; | 812 | struct tomoyo_path_acl *entry = NULL; |
838 | int error = -ENOMEM; | 813 | int error = is_delete ? -ENOENT : -ENOMEM; |
839 | const u16 perm = 1 << type; | 814 | const u32 perm = 1 << type; |
840 | 815 | ||
841 | if (!domain) | 816 | if (!domain) |
842 | return -EINVAL; | 817 | return -EINVAL; |
843 | if (!tomoyo_is_correct_path(filename, 0, 0, 0, __func__)) | 818 | if (!tomoyo_is_correct_path(filename, 0, 0, 0)) |
844 | return -EINVAL; | 819 | return -EINVAL; |
845 | saved_filename = tomoyo_save_name(filename); | 820 | saved_filename = tomoyo_get_name(filename); |
846 | if (!saved_filename) | 821 | if (!saved_filename) |
847 | return -ENOMEM; | 822 | return -ENOMEM; |
848 | down_write(&tomoyo_domain_acl_info_list_lock); | 823 | if (!is_delete) |
849 | if (is_delete) | 824 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
850 | goto delete; | 825 | mutex_lock(&tomoyo_policy_lock); |
851 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | 826 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
852 | if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) | 827 | struct tomoyo_path_acl *acl = |
828 | container_of(ptr, struct tomoyo_path_acl, head); | ||
829 | if (ptr->type != TOMOYO_TYPE_PATH_ACL) | ||
853 | continue; | 830 | continue; |
854 | acl = container_of(ptr, struct tomoyo_single_path_acl_record, | ||
855 | head); | ||
856 | if (acl->filename != saved_filename) | 831 | if (acl->filename != saved_filename) |
857 | continue; | 832 | continue; |
858 | /* Special case. Clear all bits if marked as deleted. */ | 833 | if (is_delete) { |
859 | if (ptr->type & TOMOYO_ACL_DELETED) | 834 | if (perm <= 0xFFFF) |
860 | acl->perm = 0; | 835 | acl->perm &= ~perm; |
861 | acl->perm |= perm; | 836 | else |
862 | if ((acl->perm & rw_mask) == rw_mask) | 837 | acl->perm_high &= ~(perm >> 16); |
863 | acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE_ACL; | 838 | if ((acl->perm & rw_mask) != rw_mask) |
864 | else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL)) | 839 | acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE); |
865 | acl->perm |= rw_mask; | 840 | else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE))) |
866 | ptr->type &= ~TOMOYO_ACL_DELETED; | 841 | acl->perm &= ~rw_mask; |
842 | } else { | ||
843 | if (perm <= 0xFFFF) | ||
844 | acl->perm |= perm; | ||
845 | else | ||
846 | acl->perm_high |= (perm >> 16); | ||
847 | if ((acl->perm & rw_mask) == rw_mask) | ||
848 | acl->perm |= 1 << TOMOYO_TYPE_READ_WRITE; | ||
849 | else if (acl->perm & (1 << TOMOYO_TYPE_READ_WRITE)) | ||
850 | acl->perm |= rw_mask; | ||
851 | } | ||
867 | error = 0; | 852 | error = 0; |
868 | goto out; | 853 | break; |
869 | } | 854 | } |
870 | /* Not found. Append it to the tail. */ | 855 | if (!is_delete && error && tomoyo_memory_ok(entry)) { |
871 | acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_SINGLE_PATH_ACL); | 856 | entry->head.type = TOMOYO_TYPE_PATH_ACL; |
872 | if (!acl) | 857 | if (perm <= 0xFFFF) |
873 | goto out; | 858 | entry->perm = perm; |
874 | acl->perm = perm; | 859 | else |
875 | if (perm == (1 << TOMOYO_TYPE_READ_WRITE_ACL)) | 860 | entry->perm_high = (perm >> 16); |
876 | acl->perm |= rw_mask; | 861 | if (perm == (1 << TOMOYO_TYPE_READ_WRITE)) |
877 | acl->filename = saved_filename; | 862 | entry->perm |= rw_mask; |
878 | list_add_tail(&acl->head.list, &domain->acl_info_list); | 863 | entry->filename = saved_filename; |
879 | error = 0; | 864 | saved_filename = NULL; |
880 | goto out; | 865 | list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); |
881 | delete: | 866 | entry = NULL; |
882 | error = -ENOENT; | ||
883 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | ||
884 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_SINGLE_PATH_ACL) | ||
885 | continue; | ||
886 | acl = container_of(ptr, struct tomoyo_single_path_acl_record, | ||
887 | head); | ||
888 | if (acl->filename != saved_filename) | ||
889 | continue; | ||
890 | acl->perm &= ~perm; | ||
891 | if ((acl->perm & rw_mask) != rw_mask) | ||
892 | acl->perm &= ~(1 << TOMOYO_TYPE_READ_WRITE_ACL); | ||
893 | else if (!(acl->perm & (1 << TOMOYO_TYPE_READ_WRITE_ACL))) | ||
894 | acl->perm &= ~rw_mask; | ||
895 | if (!acl->perm) | ||
896 | ptr->type |= TOMOYO_ACL_DELETED; | ||
897 | error = 0; | 867 | error = 0; |
898 | break; | ||
899 | } | 868 | } |
900 | out: | 869 | mutex_unlock(&tomoyo_policy_lock); |
901 | up_write(&tomoyo_domain_acl_info_list_lock); | 870 | kfree(entry); |
871 | tomoyo_put_name(saved_filename); | ||
902 | return error; | 872 | return error; |
903 | } | 873 | } |
904 | 874 | ||
905 | /** | 875 | /** |
906 | * tomoyo_update_double_path_acl - Update "struct tomoyo_double_path_acl_record" list. | 876 | * tomoyo_update_path2_acl - Update "struct tomoyo_path2_acl" list. |
907 | * | 877 | * |
908 | * @type: Type of operation. | 878 | * @type: Type of operation. |
909 | * @filename1: First filename. | 879 | * @filename1: First filename. |
@@ -912,98 +882,88 @@ static int tomoyo_update_single_path_acl(const u8 type, const char *filename, | |||
912 | * @is_delete: True if it is a delete request. | 882 | * @is_delete: True if it is a delete request. |
913 | * | 883 | * |
914 | * Returns 0 on success, negative value otherwise. | 884 | * Returns 0 on success, negative value otherwise. |
885 | * | ||
886 | * Caller holds tomoyo_read_lock(). | ||
915 | */ | 887 | */ |
916 | static int tomoyo_update_double_path_acl(const u8 type, const char *filename1, | 888 | static int tomoyo_update_path2_acl(const u8 type, const char *filename1, |
917 | const char *filename2, | 889 | const char *filename2, |
918 | struct tomoyo_domain_info * | 890 | struct tomoyo_domain_info *const domain, |
919 | const domain, const bool is_delete) | 891 | const bool is_delete) |
920 | { | 892 | { |
921 | const struct tomoyo_path_info *saved_filename1; | 893 | const struct tomoyo_path_info *saved_filename1; |
922 | const struct tomoyo_path_info *saved_filename2; | 894 | const struct tomoyo_path_info *saved_filename2; |
923 | struct tomoyo_acl_info *ptr; | 895 | struct tomoyo_acl_info *ptr; |
924 | struct tomoyo_double_path_acl_record *acl; | 896 | struct tomoyo_path2_acl *entry = NULL; |
925 | int error = -ENOMEM; | 897 | int error = is_delete ? -ENOENT : -ENOMEM; |
926 | const u8 perm = 1 << type; | 898 | const u8 perm = 1 << type; |
927 | 899 | ||
928 | if (!domain) | 900 | if (!domain) |
929 | return -EINVAL; | 901 | return -EINVAL; |
930 | if (!tomoyo_is_correct_path(filename1, 0, 0, 0, __func__) || | 902 | if (!tomoyo_is_correct_path(filename1, 0, 0, 0) || |
931 | !tomoyo_is_correct_path(filename2, 0, 0, 0, __func__)) | 903 | !tomoyo_is_correct_path(filename2, 0, 0, 0)) |
932 | return -EINVAL; | 904 | return -EINVAL; |
933 | saved_filename1 = tomoyo_save_name(filename1); | 905 | saved_filename1 = tomoyo_get_name(filename1); |
934 | saved_filename2 = tomoyo_save_name(filename2); | 906 | saved_filename2 = tomoyo_get_name(filename2); |
935 | if (!saved_filename1 || !saved_filename2) | 907 | if (!saved_filename1 || !saved_filename2) |
936 | return -ENOMEM; | ||
937 | down_write(&tomoyo_domain_acl_info_list_lock); | ||
938 | if (is_delete) | ||
939 | goto delete; | ||
940 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | ||
941 | if (tomoyo_acl_type1(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) | ||
942 | continue; | ||
943 | acl = container_of(ptr, struct tomoyo_double_path_acl_record, | ||
944 | head); | ||
945 | if (acl->filename1 != saved_filename1 || | ||
946 | acl->filename2 != saved_filename2) | ||
947 | continue; | ||
948 | /* Special case. Clear all bits if marked as deleted. */ | ||
949 | if (ptr->type & TOMOYO_ACL_DELETED) | ||
950 | acl->perm = 0; | ||
951 | acl->perm |= perm; | ||
952 | ptr->type &= ~TOMOYO_ACL_DELETED; | ||
953 | error = 0; | ||
954 | goto out; | 908 | goto out; |
955 | } | 909 | if (!is_delete) |
956 | /* Not found. Append it to the tail. */ | 910 | entry = kmalloc(sizeof(*entry), GFP_KERNEL); |
957 | acl = tomoyo_alloc_acl_element(TOMOYO_TYPE_DOUBLE_PATH_ACL); | 911 | mutex_lock(&tomoyo_policy_lock); |
958 | if (!acl) | 912 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
959 | goto out; | 913 | struct tomoyo_path2_acl *acl = |
960 | acl->perm = perm; | 914 | container_of(ptr, struct tomoyo_path2_acl, head); |
961 | acl->filename1 = saved_filename1; | 915 | if (ptr->type != TOMOYO_TYPE_PATH2_ACL) |
962 | acl->filename2 = saved_filename2; | ||
963 | list_add_tail(&acl->head.list, &domain->acl_info_list); | ||
964 | error = 0; | ||
965 | goto out; | ||
966 | delete: | ||
967 | error = -ENOENT; | ||
968 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | ||
969 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) | ||
970 | continue; | 916 | continue; |
971 | acl = container_of(ptr, struct tomoyo_double_path_acl_record, | ||
972 | head); | ||
973 | if (acl->filename1 != saved_filename1 || | 917 | if (acl->filename1 != saved_filename1 || |
974 | acl->filename2 != saved_filename2) | 918 | acl->filename2 != saved_filename2) |
975 | continue; | 919 | continue; |
976 | acl->perm &= ~perm; | 920 | if (is_delete) |
977 | if (!acl->perm) | 921 | acl->perm &= ~perm; |
978 | ptr->type |= TOMOYO_ACL_DELETED; | 922 | else |
923 | acl->perm |= perm; | ||
979 | error = 0; | 924 | error = 0; |
980 | break; | 925 | break; |
981 | } | 926 | } |
927 | if (!is_delete && error && tomoyo_memory_ok(entry)) { | ||
928 | entry->head.type = TOMOYO_TYPE_PATH2_ACL; | ||
929 | entry->perm = perm; | ||
930 | entry->filename1 = saved_filename1; | ||
931 | saved_filename1 = NULL; | ||
932 | entry->filename2 = saved_filename2; | ||
933 | saved_filename2 = NULL; | ||
934 | list_add_tail_rcu(&entry->head.list, &domain->acl_info_list); | ||
935 | entry = NULL; | ||
936 | error = 0; | ||
937 | } | ||
938 | mutex_unlock(&tomoyo_policy_lock); | ||
982 | out: | 939 | out: |
983 | up_write(&tomoyo_domain_acl_info_list_lock); | 940 | tomoyo_put_name(saved_filename1); |
941 | tomoyo_put_name(saved_filename2); | ||
942 | kfree(entry); | ||
984 | return error; | 943 | return error; |
985 | } | 944 | } |
986 | 945 | ||
987 | /** | 946 | /** |
988 | * tomoyo_check_single_path_acl - Check permission for single path operation. | 947 | * tomoyo_path_acl - Check permission for single path operation. |
989 | * | 948 | * |
990 | * @domain: Pointer to "struct tomoyo_domain_info". | 949 | * @domain: Pointer to "struct tomoyo_domain_info". |
991 | * @type: Type of operation. | 950 | * @type: Type of operation. |
992 | * @filename: Filename to check. | 951 | * @filename: Filename to check. |
993 | * | 952 | * |
994 | * Returns 0 on success, negative value otherwise. | 953 | * Returns 0 on success, negative value otherwise. |
954 | * | ||
955 | * Caller holds tomoyo_read_lock(). | ||
995 | */ | 956 | */ |
996 | static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain, | 957 | static int tomoyo_path_acl(struct tomoyo_domain_info *domain, const u8 type, |
997 | const u8 type, | 958 | const struct tomoyo_path_info *filename) |
998 | const struct tomoyo_path_info *filename) | ||
999 | { | 959 | { |
1000 | if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) | 960 | if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) |
1001 | return 0; | 961 | return 0; |
1002 | return tomoyo_check_single_path_acl2(domain, filename, 1 << type, 1); | 962 | return tomoyo_path_acl2(domain, filename, 1 << type, 1); |
1003 | } | 963 | } |
1004 | 964 | ||
1005 | /** | 965 | /** |
1006 | * tomoyo_check_double_path_acl - Check permission for double path operation. | 966 | * tomoyo_path2_acl - Check permission for double path operation. |
1007 | * | 967 | * |
1008 | * @domain: Pointer to "struct tomoyo_domain_info". | 968 | * @domain: Pointer to "struct tomoyo_domain_info". |
1009 | * @type: Type of operation. | 969 | * @type: Type of operation. |
@@ -1011,13 +971,13 @@ static int tomoyo_check_single_path_acl(struct tomoyo_domain_info *domain, | |||
1011 | * @filename2: Second filename to check. | 971 | * @filename2: Second filename to check. |
1012 | * | 972 | * |
1013 | * Returns 0 on success, -EPERM otherwise. | 973 | * Returns 0 on success, -EPERM otherwise. |
974 | * | ||
975 | * Caller holds tomoyo_read_lock(). | ||
1014 | */ | 976 | */ |
1015 | static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, | 977 | static int tomoyo_path2_acl(const struct tomoyo_domain_info *domain, |
1016 | const u8 type, | 978 | const u8 type, |
1017 | const struct tomoyo_path_info * | 979 | const struct tomoyo_path_info *filename1, |
1018 | filename1, | 980 | const struct tomoyo_path_info *filename2) |
1019 | const struct tomoyo_path_info * | ||
1020 | filename2) | ||
1021 | { | 981 | { |
1022 | struct tomoyo_acl_info *ptr; | 982 | struct tomoyo_acl_info *ptr; |
1023 | const u8 perm = 1 << type; | 983 | const u8 perm = 1 << type; |
@@ -1025,13 +985,11 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, | |||
1025 | 985 | ||
1026 | if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) | 986 | if (!tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE)) |
1027 | return 0; | 987 | return 0; |
1028 | down_read(&tomoyo_domain_acl_info_list_lock); | 988 | list_for_each_entry_rcu(ptr, &domain->acl_info_list, list) { |
1029 | list_for_each_entry(ptr, &domain->acl_info_list, list) { | 989 | struct tomoyo_path2_acl *acl; |
1030 | struct tomoyo_double_path_acl_record *acl; | 990 | if (ptr->type != TOMOYO_TYPE_PATH2_ACL) |
1031 | if (tomoyo_acl_type2(ptr) != TOMOYO_TYPE_DOUBLE_PATH_ACL) | ||
1032 | continue; | 991 | continue; |
1033 | acl = container_of(ptr, struct tomoyo_double_path_acl_record, | 992 | acl = container_of(ptr, struct tomoyo_path2_acl, head); |
1034 | head); | ||
1035 | if (!(acl->perm & perm)) | 993 | if (!(acl->perm & perm)) |
1036 | continue; | 994 | continue; |
1037 | if (!tomoyo_path_matches_pattern(filename1, acl->filename1)) | 995 | if (!tomoyo_path_matches_pattern(filename1, acl->filename1)) |
@@ -1041,12 +999,11 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, | |||
1041 | error = 0; | 999 | error = 0; |
1042 | break; | 1000 | break; |
1043 | } | 1001 | } |
1044 | up_read(&tomoyo_domain_acl_info_list_lock); | ||
1045 | return error; | 1002 | return error; |
1046 | } | 1003 | } |
1047 | 1004 | ||
1048 | /** | 1005 | /** |
1049 | * tomoyo_check_single_path_permission2 - Check permission for single path operation. | 1006 | * tomoyo_path_permission2 - Check permission for single path operation. |
1050 | * | 1007 | * |
1051 | * @domain: Pointer to "struct tomoyo_domain_info". | 1008 | * @domain: Pointer to "struct tomoyo_domain_info". |
1052 | * @operation: Type of operation. | 1009 | * @operation: Type of operation. |
@@ -1054,11 +1011,13 @@ static int tomoyo_check_double_path_acl(const struct tomoyo_domain_info *domain, | |||
1054 | * @mode: Access control mode. | 1011 | * @mode: Access control mode. |
1055 | * | 1012 | * |
1056 | * Returns 0 on success, negative value otherwise. | 1013 | * Returns 0 on success, negative value otherwise. |
1014 | * | ||
1015 | * Caller holds tomoyo_read_lock(). | ||
1057 | */ | 1016 | */ |
1058 | static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * | 1017 | static int tomoyo_path_permission2(struct tomoyo_domain_info *const domain, |
1059 | const domain, u8 operation, | 1018 | u8 operation, |
1060 | const struct tomoyo_path_info * | 1019 | const struct tomoyo_path_info *filename, |
1061 | filename, const u8 mode) | 1020 | const u8 mode) |
1062 | { | 1021 | { |
1063 | const char *msg; | 1022 | const char *msg; |
1064 | int error; | 1023 | int error; |
@@ -1067,8 +1026,8 @@ static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * | |||
1067 | if (!mode) | 1026 | if (!mode) |
1068 | return 0; | 1027 | return 0; |
1069 | next: | 1028 | next: |
1070 | error = tomoyo_check_single_path_acl(domain, operation, filename); | 1029 | error = tomoyo_path_acl(domain, operation, filename); |
1071 | msg = tomoyo_sp2keyword(operation); | 1030 | msg = tomoyo_path2keyword(operation); |
1072 | if (!error) | 1031 | if (!error) |
1073 | goto ok; | 1032 | goto ok; |
1074 | if (tomoyo_verbose_mode(domain)) | 1033 | if (tomoyo_verbose_mode(domain)) |
@@ -1077,7 +1036,7 @@ static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * | |||
1077 | tomoyo_get_last_name(domain)); | 1036 | tomoyo_get_last_name(domain)); |
1078 | if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { | 1037 | if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { |
1079 | const char *name = tomoyo_get_file_pattern(filename)->name; | 1038 | const char *name = tomoyo_get_file_pattern(filename)->name; |
1080 | tomoyo_update_single_path_acl(operation, name, domain, false); | 1039 | tomoyo_update_path_acl(operation, name, domain, false); |
1081 | } | 1040 | } |
1082 | if (!is_enforce) | 1041 | if (!is_enforce) |
1083 | error = 0; | 1042 | error = 0; |
@@ -1087,42 +1046,23 @@ static int tomoyo_check_single_path_permission2(struct tomoyo_domain_info * | |||
1087 | * we need to check "allow_rewrite" permission if the filename is | 1046 | * we need to check "allow_rewrite" permission if the filename is |
1088 | * specified by "deny_rewrite" keyword. | 1047 | * specified by "deny_rewrite" keyword. |
1089 | */ | 1048 | */ |
1090 | if (!error && operation == TOMOYO_TYPE_TRUNCATE_ACL && | 1049 | if (!error && operation == TOMOYO_TYPE_TRUNCATE && |
1091 | tomoyo_is_no_rewrite_file(filename)) { | 1050 | tomoyo_is_no_rewrite_file(filename)) { |
1092 | operation = TOMOYO_TYPE_REWRITE_ACL; | 1051 | operation = TOMOYO_TYPE_REWRITE; |
1093 | goto next; | 1052 | goto next; |
1094 | } | 1053 | } |
1095 | return error; | 1054 | return error; |
1096 | } | 1055 | } |
1097 | 1056 | ||
1098 | /** | 1057 | /** |
1099 | * tomoyo_check_file_perm - Check permission for sysctl()'s "read" and "write". | ||
1100 | * | ||
1101 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
1102 | * @filename: Filename to check. | ||
1103 | * @perm: Mode ("read" or "write" or "read/write"). | ||
1104 | * Returns 0 on success, negative value otherwise. | ||
1105 | */ | ||
1106 | int tomoyo_check_file_perm(struct tomoyo_domain_info *domain, | ||
1107 | const char *filename, const u8 perm) | ||
1108 | { | ||
1109 | struct tomoyo_path_info name; | ||
1110 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | ||
1111 | |||
1112 | if (!mode) | ||
1113 | return 0; | ||
1114 | name.name = filename; | ||
1115 | tomoyo_fill_path_info(&name); | ||
1116 | return tomoyo_check_file_perm2(domain, &name, perm, "sysctl", mode); | ||
1117 | } | ||
1118 | |||
1119 | /** | ||
1120 | * tomoyo_check_exec_perm - Check permission for "execute". | 1058 | * tomoyo_check_exec_perm - Check permission for "execute". |
1121 | * | 1059 | * |
1122 | * @domain: Pointer to "struct tomoyo_domain_info". | 1060 | * @domain: Pointer to "struct tomoyo_domain_info". |
1123 | * @filename: Check permission for "execute". | 1061 | * @filename: Check permission for "execute". |
1124 | * | 1062 | * |
1125 | * Returns 0 on success, negativevalue otherwise. | 1063 | * Returns 0 on success, negativevalue otherwise. |
1064 | * | ||
1065 | * Caller holds tomoyo_read_lock(). | ||
1126 | */ | 1066 | */ |
1127 | int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, | 1067 | int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, |
1128 | const struct tomoyo_path_info *filename) | 1068 | const struct tomoyo_path_info *filename) |
@@ -1151,6 +1091,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
1151 | struct tomoyo_path_info *buf; | 1091 | struct tomoyo_path_info *buf; |
1152 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | 1092 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); |
1153 | const bool is_enforce = (mode == 3); | 1093 | const bool is_enforce = (mode == 3); |
1094 | int idx; | ||
1154 | 1095 | ||
1155 | if (!mode || !path->mnt) | 1096 | if (!mode || !path->mnt) |
1156 | return 0; | 1097 | return 0; |
@@ -1162,6 +1103,7 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
1162 | * don't call me. | 1103 | * don't call me. |
1163 | */ | 1104 | */ |
1164 | return 0; | 1105 | return 0; |
1106 | idx = tomoyo_read_lock(); | ||
1165 | buf = tomoyo_get_path(path); | 1107 | buf = tomoyo_get_path(path); |
1166 | if (!buf) | 1108 | if (!buf) |
1167 | goto out; | 1109 | goto out; |
@@ -1174,49 +1116,50 @@ int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | |||
1174 | if ((acc_mode & MAY_WRITE) && | 1116 | if ((acc_mode & MAY_WRITE) && |
1175 | ((flag & O_TRUNC) || !(flag & O_APPEND)) && | 1117 | ((flag & O_TRUNC) || !(flag & O_APPEND)) && |
1176 | (tomoyo_is_no_rewrite_file(buf))) { | 1118 | (tomoyo_is_no_rewrite_file(buf))) { |
1177 | error = tomoyo_check_single_path_permission2(domain, | 1119 | error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE, |
1178 | TOMOYO_TYPE_REWRITE_ACL, | 1120 | buf, mode); |
1179 | buf, mode); | ||
1180 | } | 1121 | } |
1181 | if (!error) | 1122 | if (!error) |
1182 | error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open", | 1123 | error = tomoyo_check_file_perm2(domain, buf, acc_mode, "open", |
1183 | mode); | 1124 | mode); |
1184 | if (!error && (flag & O_TRUNC)) | 1125 | if (!error && (flag & O_TRUNC)) |
1185 | error = tomoyo_check_single_path_permission2(domain, | 1126 | error = tomoyo_path_permission2(domain, TOMOYO_TYPE_TRUNCATE, |
1186 | TOMOYO_TYPE_TRUNCATE_ACL, | 1127 | buf, mode); |
1187 | buf, mode); | ||
1188 | out: | 1128 | out: |
1189 | tomoyo_free(buf); | 1129 | kfree(buf); |
1130 | tomoyo_read_unlock(idx); | ||
1190 | if (!is_enforce) | 1131 | if (!is_enforce) |
1191 | error = 0; | 1132 | error = 0; |
1192 | return error; | 1133 | return error; |
1193 | } | 1134 | } |
1194 | 1135 | ||
1195 | /** | 1136 | /** |
1196 | * tomoyo_check_1path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate" and "symlink". | 1137 | * tomoyo_path_perm - Check permission for "create", "unlink", "mkdir", "rmdir", "mkfifo", "mksock", "mkblock", "mkchar", "truncate", "symlink", "ioctl", "chmod", "chown", "chgrp", "chroot", "mount" and "unmount". |
1197 | * | 1138 | * |
1198 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
1199 | * @operation: Type of operation. | 1139 | * @operation: Type of operation. |
1200 | * @path: Pointer to "struct path". | 1140 | * @path: Pointer to "struct path". |
1201 | * | 1141 | * |
1202 | * Returns 0 on success, negative value otherwise. | 1142 | * Returns 0 on success, negative value otherwise. |
1203 | */ | 1143 | */ |
1204 | int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, | 1144 | int tomoyo_path_perm(const u8 operation, struct path *path) |
1205 | const u8 operation, struct path *path) | ||
1206 | { | 1145 | { |
1207 | int error = -ENOMEM; | 1146 | int error = -ENOMEM; |
1208 | struct tomoyo_path_info *buf; | 1147 | struct tomoyo_path_info *buf; |
1148 | struct tomoyo_domain_info *domain = tomoyo_domain(); | ||
1209 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | 1149 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); |
1210 | const bool is_enforce = (mode == 3); | 1150 | const bool is_enforce = (mode == 3); |
1151 | int idx; | ||
1211 | 1152 | ||
1212 | if (!mode || !path->mnt) | 1153 | if (!mode || !path->mnt) |
1213 | return 0; | 1154 | return 0; |
1155 | idx = tomoyo_read_lock(); | ||
1214 | buf = tomoyo_get_path(path); | 1156 | buf = tomoyo_get_path(path); |
1215 | if (!buf) | 1157 | if (!buf) |
1216 | goto out; | 1158 | goto out; |
1217 | switch (operation) { | 1159 | switch (operation) { |
1218 | case TOMOYO_TYPE_MKDIR_ACL: | 1160 | case TOMOYO_TYPE_MKDIR: |
1219 | case TOMOYO_TYPE_RMDIR_ACL: | 1161 | case TOMOYO_TYPE_RMDIR: |
1162 | case TOMOYO_TYPE_CHROOT: | ||
1220 | if (!buf->is_dir) { | 1163 | if (!buf->is_dir) { |
1221 | /* | 1164 | /* |
1222 | * tomoyo_get_path() reserves space for appending "/." | 1165 | * tomoyo_get_path() reserves space for appending "/." |
@@ -1225,10 +1168,10 @@ int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, | |||
1225 | tomoyo_fill_path_info(buf); | 1168 | tomoyo_fill_path_info(buf); |
1226 | } | 1169 | } |
1227 | } | 1170 | } |
1228 | error = tomoyo_check_single_path_permission2(domain, operation, buf, | 1171 | error = tomoyo_path_permission2(domain, operation, buf, mode); |
1229 | mode); | ||
1230 | out: | 1172 | out: |
1231 | tomoyo_free(buf); | 1173 | kfree(buf); |
1174 | tomoyo_read_unlock(idx); | ||
1232 | if (!is_enforce) | 1175 | if (!is_enforce) |
1233 | error = 0; | 1176 | error = 0; |
1234 | return error; | 1177 | return error; |
@@ -1237,21 +1180,23 @@ int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, | |||
1237 | /** | 1180 | /** |
1238 | * tomoyo_check_rewrite_permission - Check permission for "rewrite". | 1181 | * tomoyo_check_rewrite_permission - Check permission for "rewrite". |
1239 | * | 1182 | * |
1240 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
1241 | * @filp: Pointer to "struct file". | 1183 | * @filp: Pointer to "struct file". |
1242 | * | 1184 | * |
1243 | * Returns 0 on success, negative value otherwise. | 1185 | * Returns 0 on success, negative value otherwise. |
1244 | */ | 1186 | */ |
1245 | int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, | 1187 | int tomoyo_check_rewrite_permission(struct file *filp) |
1246 | struct file *filp) | ||
1247 | { | 1188 | { |
1248 | int error = -ENOMEM; | 1189 | int error = -ENOMEM; |
1190 | struct tomoyo_domain_info *domain = tomoyo_domain(); | ||
1249 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | 1191 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); |
1250 | const bool is_enforce = (mode == 3); | 1192 | const bool is_enforce = (mode == 3); |
1251 | struct tomoyo_path_info *buf; | 1193 | struct tomoyo_path_info *buf; |
1194 | int idx; | ||
1252 | 1195 | ||
1253 | if (!mode || !filp->f_path.mnt) | 1196 | if (!mode || !filp->f_path.mnt) |
1254 | return 0; | 1197 | return 0; |
1198 | |||
1199 | idx = tomoyo_read_lock(); | ||
1255 | buf = tomoyo_get_path(&filp->f_path); | 1200 | buf = tomoyo_get_path(&filp->f_path); |
1256 | if (!buf) | 1201 | if (!buf) |
1257 | goto out; | 1202 | goto out; |
@@ -1259,38 +1204,38 @@ int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, | |||
1259 | error = 0; | 1204 | error = 0; |
1260 | goto out; | 1205 | goto out; |
1261 | } | 1206 | } |
1262 | error = tomoyo_check_single_path_permission2(domain, | 1207 | error = tomoyo_path_permission2(domain, TOMOYO_TYPE_REWRITE, buf, mode); |
1263 | TOMOYO_TYPE_REWRITE_ACL, | ||
1264 | buf, mode); | ||
1265 | out: | 1208 | out: |
1266 | tomoyo_free(buf); | 1209 | kfree(buf); |
1210 | tomoyo_read_unlock(idx); | ||
1267 | if (!is_enforce) | 1211 | if (!is_enforce) |
1268 | error = 0; | 1212 | error = 0; |
1269 | return error; | 1213 | return error; |
1270 | } | 1214 | } |
1271 | 1215 | ||
1272 | /** | 1216 | /** |
1273 | * tomoyo_check_2path_perm - Check permission for "rename" and "link". | 1217 | * tomoyo_path2_perm - Check permission for "rename", "link" and "pivot_root". |
1274 | * | 1218 | * |
1275 | * @domain: Pointer to "struct tomoyo_domain_info". | ||
1276 | * @operation: Type of operation. | 1219 | * @operation: Type of operation. |
1277 | * @path1: Pointer to "struct path". | 1220 | * @path1: Pointer to "struct path". |
1278 | * @path2: Pointer to "struct path". | 1221 | * @path2: Pointer to "struct path". |
1279 | * | 1222 | * |
1280 | * Returns 0 on success, negative value otherwise. | 1223 | * Returns 0 on success, negative value otherwise. |
1281 | */ | 1224 | */ |
1282 | int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain, | 1225 | int tomoyo_path2_perm(const u8 operation, struct path *path1, |
1283 | const u8 operation, struct path *path1, | 1226 | struct path *path2) |
1284 | struct path *path2) | ||
1285 | { | 1227 | { |
1286 | int error = -ENOMEM; | 1228 | int error = -ENOMEM; |
1287 | struct tomoyo_path_info *buf1, *buf2; | 1229 | struct tomoyo_path_info *buf1, *buf2; |
1230 | struct tomoyo_domain_info *domain = tomoyo_domain(); | ||
1288 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); | 1231 | const u8 mode = tomoyo_check_flags(domain, TOMOYO_MAC_FOR_FILE); |
1289 | const bool is_enforce = (mode == 3); | 1232 | const bool is_enforce = (mode == 3); |
1290 | const char *msg; | 1233 | const char *msg; |
1234 | int idx; | ||
1291 | 1235 | ||
1292 | if (!mode || !path1->mnt || !path2->mnt) | 1236 | if (!mode || !path1->mnt || !path2->mnt) |
1293 | return 0; | 1237 | return 0; |
1238 | idx = tomoyo_read_lock(); | ||
1294 | buf1 = tomoyo_get_path(path1); | 1239 | buf1 = tomoyo_get_path(path1); |
1295 | buf2 = tomoyo_get_path(path2); | 1240 | buf2 = tomoyo_get_path(path2); |
1296 | if (!buf1 || !buf2) | 1241 | if (!buf1 || !buf2) |
@@ -1311,8 +1256,8 @@ int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain, | |||
1311 | } | 1256 | } |
1312 | } | 1257 | } |
1313 | } | 1258 | } |
1314 | error = tomoyo_check_double_path_acl(domain, operation, buf1, buf2); | 1259 | error = tomoyo_path2_acl(domain, operation, buf1, buf2); |
1315 | msg = tomoyo_dp2keyword(operation); | 1260 | msg = tomoyo_path22keyword(operation); |
1316 | if (!error) | 1261 | if (!error) |
1317 | goto out; | 1262 | goto out; |
1318 | if (tomoyo_verbose_mode(domain)) | 1263 | if (tomoyo_verbose_mode(domain)) |
@@ -1323,12 +1268,13 @@ int tomoyo_check_2path_perm(struct tomoyo_domain_info * const domain, | |||
1323 | if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { | 1268 | if (mode == 1 && tomoyo_domain_quota_is_ok(domain)) { |
1324 | const char *name1 = tomoyo_get_file_pattern(buf1)->name; | 1269 | const char *name1 = tomoyo_get_file_pattern(buf1)->name; |
1325 | const char *name2 = tomoyo_get_file_pattern(buf2)->name; | 1270 | const char *name2 = tomoyo_get_file_pattern(buf2)->name; |
1326 | tomoyo_update_double_path_acl(operation, name1, name2, domain, | 1271 | tomoyo_update_path2_acl(operation, name1, name2, domain, |
1327 | false); | 1272 | false); |
1328 | } | 1273 | } |
1329 | out: | 1274 | out: |
1330 | tomoyo_free(buf1); | 1275 | kfree(buf1); |
1331 | tomoyo_free(buf2); | 1276 | kfree(buf2); |
1277 | tomoyo_read_unlock(idx); | ||
1332 | if (!is_enforce) | 1278 | if (!is_enforce) |
1333 | error = 0; | 1279 | error = 0; |
1334 | return error; | 1280 | return error; |
diff --git a/security/tomoyo/gc.c b/security/tomoyo/gc.c new file mode 100644 index 000000000000..d9ad35bc7fa8 --- /dev/null +++ b/security/tomoyo/gc.c | |||
@@ -0,0 +1,371 @@ | |||
1 | /* | ||
2 | * security/tomoyo/gc.c | ||
3 | * | ||
4 | * Implementation of the Domain-Based Mandatory Access Control. | ||
5 | * | ||
6 | * Copyright (C) 2005-2010 NTT DATA CORPORATION | ||
7 | * | ||
8 | */ | ||
9 | |||
10 | #include "common.h" | ||
11 | #include <linux/kthread.h> | ||
12 | #include <linux/slab.h> | ||
13 | |||
14 | enum tomoyo_gc_id { | ||
15 | TOMOYO_ID_DOMAIN_INITIALIZER, | ||
16 | TOMOYO_ID_DOMAIN_KEEPER, | ||
17 | TOMOYO_ID_ALIAS, | ||
18 | TOMOYO_ID_GLOBALLY_READABLE, | ||
19 | TOMOYO_ID_PATTERN, | ||
20 | TOMOYO_ID_NO_REWRITE, | ||
21 | TOMOYO_ID_MANAGER, | ||
22 | TOMOYO_ID_NAME, | ||
23 | TOMOYO_ID_ACL, | ||
24 | TOMOYO_ID_DOMAIN | ||
25 | }; | ||
26 | |||
27 | struct tomoyo_gc_entry { | ||
28 | struct list_head list; | ||
29 | int type; | ||
30 | void *element; | ||
31 | }; | ||
32 | static LIST_HEAD(tomoyo_gc_queue); | ||
33 | static DEFINE_MUTEX(tomoyo_gc_mutex); | ||
34 | |||
35 | /* Caller holds tomoyo_policy_lock mutex. */ | ||
36 | static bool tomoyo_add_to_gc(const int type, void *element) | ||
37 | { | ||
38 | struct tomoyo_gc_entry *entry = kzalloc(sizeof(*entry), GFP_ATOMIC); | ||
39 | if (!entry) | ||
40 | return false; | ||
41 | entry->type = type; | ||
42 | entry->element = element; | ||
43 | list_add(&entry->list, &tomoyo_gc_queue); | ||
44 | return true; | ||
45 | } | ||
46 | |||
47 | static void tomoyo_del_allow_read | ||
48 | (struct tomoyo_globally_readable_file_entry *ptr) | ||
49 | { | ||
50 | tomoyo_put_name(ptr->filename); | ||
51 | } | ||
52 | |||
53 | static void tomoyo_del_file_pattern(struct tomoyo_pattern_entry *ptr) | ||
54 | { | ||
55 | tomoyo_put_name(ptr->pattern); | ||
56 | } | ||
57 | |||
58 | static void tomoyo_del_no_rewrite(struct tomoyo_no_rewrite_entry *ptr) | ||
59 | { | ||
60 | tomoyo_put_name(ptr->pattern); | ||
61 | } | ||
62 | |||
63 | static void tomoyo_del_domain_initializer | ||
64 | (struct tomoyo_domain_initializer_entry *ptr) | ||
65 | { | ||
66 | tomoyo_put_name(ptr->domainname); | ||
67 | tomoyo_put_name(ptr->program); | ||
68 | } | ||
69 | |||
70 | static void tomoyo_del_domain_keeper(struct tomoyo_domain_keeper_entry *ptr) | ||
71 | { | ||
72 | tomoyo_put_name(ptr->domainname); | ||
73 | tomoyo_put_name(ptr->program); | ||
74 | } | ||
75 | |||
76 | static void tomoyo_del_alias(struct tomoyo_alias_entry *ptr) | ||
77 | { | ||
78 | tomoyo_put_name(ptr->original_name); | ||
79 | tomoyo_put_name(ptr->aliased_name); | ||
80 | } | ||
81 | |||
82 | static void tomoyo_del_manager(struct tomoyo_policy_manager_entry *ptr) | ||
83 | { | ||
84 | tomoyo_put_name(ptr->manager); | ||
85 | } | ||
86 | |||
87 | static void tomoyo_del_acl(struct tomoyo_acl_info *acl) | ||
88 | { | ||
89 | switch (acl->type) { | ||
90 | case TOMOYO_TYPE_PATH_ACL: | ||
91 | { | ||
92 | struct tomoyo_path_acl *entry | ||
93 | = container_of(acl, typeof(*entry), head); | ||
94 | tomoyo_put_name(entry->filename); | ||
95 | } | ||
96 | break; | ||
97 | case TOMOYO_TYPE_PATH2_ACL: | ||
98 | { | ||
99 | struct tomoyo_path2_acl *entry | ||
100 | = container_of(acl, typeof(*entry), head); | ||
101 | tomoyo_put_name(entry->filename1); | ||
102 | tomoyo_put_name(entry->filename2); | ||
103 | } | ||
104 | break; | ||
105 | default: | ||
106 | printk(KERN_WARNING "Unknown type\n"); | ||
107 | break; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | static bool tomoyo_del_domain(struct tomoyo_domain_info *domain) | ||
112 | { | ||
113 | struct tomoyo_acl_info *acl; | ||
114 | struct tomoyo_acl_info *tmp; | ||
115 | /* | ||
116 | * Since we don't protect whole execve() operation using SRCU, | ||
117 | * we need to recheck domain->users at this point. | ||
118 | * | ||
119 | * (1) Reader starts SRCU section upon execve(). | ||
120 | * (2) Reader traverses tomoyo_domain_list and finds this domain. | ||
121 | * (3) Writer marks this domain as deleted. | ||
122 | * (4) Garbage collector removes this domain from tomoyo_domain_list | ||
123 | * because this domain is marked as deleted and used by nobody. | ||
124 | * (5) Reader saves reference to this domain into | ||
125 | * "struct linux_binprm"->cred->security . | ||
126 | * (6) Reader finishes SRCU section, although execve() operation has | ||
127 | * not finished yet. | ||
128 | * (7) Garbage collector waits for SRCU synchronization. | ||
129 | * (8) Garbage collector kfree() this domain because this domain is | ||
130 | * used by nobody. | ||
131 | * (9) Reader finishes execve() operation and restores this domain from | ||
132 | * "struct linux_binprm"->cred->security. | ||
133 | * | ||
134 | * By updating domain->users at (5), we can solve this race problem | ||
135 | * by rechecking domain->users at (8). | ||
136 | */ | ||
137 | if (atomic_read(&domain->users)) | ||
138 | return false; | ||
139 | list_for_each_entry_safe(acl, tmp, &domain->acl_info_list, list) { | ||
140 | tomoyo_del_acl(acl); | ||
141 | tomoyo_memory_free(acl); | ||
142 | } | ||
143 | tomoyo_put_name(domain->domainname); | ||
144 | return true; | ||
145 | } | ||
146 | |||
147 | |||
148 | static void tomoyo_del_name(const struct tomoyo_name_entry *ptr) | ||
149 | { | ||
150 | } | ||
151 | |||
152 | static void tomoyo_collect_entry(void) | ||
153 | { | ||
154 | mutex_lock(&tomoyo_policy_lock); | ||
155 | { | ||
156 | struct tomoyo_globally_readable_file_entry *ptr; | ||
157 | list_for_each_entry_rcu(ptr, &tomoyo_globally_readable_list, | ||
158 | list) { | ||
159 | if (!ptr->is_deleted) | ||
160 | continue; | ||
161 | if (tomoyo_add_to_gc(TOMOYO_ID_GLOBALLY_READABLE, ptr)) | ||
162 | list_del_rcu(&ptr->list); | ||
163 | else | ||
164 | break; | ||
165 | } | ||
166 | } | ||
167 | { | ||
168 | struct tomoyo_pattern_entry *ptr; | ||
169 | list_for_each_entry_rcu(ptr, &tomoyo_pattern_list, list) { | ||
170 | if (!ptr->is_deleted) | ||
171 | continue; | ||
172 | if (tomoyo_add_to_gc(TOMOYO_ID_PATTERN, ptr)) | ||
173 | list_del_rcu(&ptr->list); | ||
174 | else | ||
175 | break; | ||
176 | } | ||
177 | } | ||
178 | { | ||
179 | struct tomoyo_no_rewrite_entry *ptr; | ||
180 | list_for_each_entry_rcu(ptr, &tomoyo_no_rewrite_list, list) { | ||
181 | if (!ptr->is_deleted) | ||
182 | continue; | ||
183 | if (tomoyo_add_to_gc(TOMOYO_ID_NO_REWRITE, ptr)) | ||
184 | list_del_rcu(&ptr->list); | ||
185 | else | ||
186 | break; | ||
187 | } | ||
188 | } | ||
189 | { | ||
190 | struct tomoyo_domain_initializer_entry *ptr; | ||
191 | list_for_each_entry_rcu(ptr, &tomoyo_domain_initializer_list, | ||
192 | list) { | ||
193 | if (!ptr->is_deleted) | ||
194 | continue; | ||
195 | if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_INITIALIZER, ptr)) | ||
196 | list_del_rcu(&ptr->list); | ||
197 | else | ||
198 | break; | ||
199 | } | ||
200 | } | ||
201 | { | ||
202 | struct tomoyo_domain_keeper_entry *ptr; | ||
203 | list_for_each_entry_rcu(ptr, &tomoyo_domain_keeper_list, list) { | ||
204 | if (!ptr->is_deleted) | ||
205 | continue; | ||
206 | if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN_KEEPER, ptr)) | ||
207 | list_del_rcu(&ptr->list); | ||
208 | else | ||
209 | break; | ||
210 | } | ||
211 | } | ||
212 | { | ||
213 | struct tomoyo_alias_entry *ptr; | ||
214 | list_for_each_entry_rcu(ptr, &tomoyo_alias_list, list) { | ||
215 | if (!ptr->is_deleted) | ||
216 | continue; | ||
217 | if (tomoyo_add_to_gc(TOMOYO_ID_ALIAS, ptr)) | ||
218 | list_del_rcu(&ptr->list); | ||
219 | else | ||
220 | break; | ||
221 | } | ||
222 | } | ||
223 | { | ||
224 | struct tomoyo_policy_manager_entry *ptr; | ||
225 | list_for_each_entry_rcu(ptr, &tomoyo_policy_manager_list, | ||
226 | list) { | ||
227 | if (!ptr->is_deleted) | ||
228 | continue; | ||
229 | if (tomoyo_add_to_gc(TOMOYO_ID_MANAGER, ptr)) | ||
230 | list_del_rcu(&ptr->list); | ||
231 | else | ||
232 | break; | ||
233 | } | ||
234 | } | ||
235 | { | ||
236 | struct tomoyo_domain_info *domain; | ||
237 | list_for_each_entry_rcu(domain, &tomoyo_domain_list, list) { | ||
238 | struct tomoyo_acl_info *acl; | ||
239 | list_for_each_entry_rcu(acl, &domain->acl_info_list, | ||
240 | list) { | ||
241 | switch (acl->type) { | ||
242 | case TOMOYO_TYPE_PATH_ACL: | ||
243 | if (container_of(acl, | ||
244 | struct tomoyo_path_acl, | ||
245 | head)->perm || | ||
246 | container_of(acl, | ||
247 | struct tomoyo_path_acl, | ||
248 | head)->perm_high) | ||
249 | continue; | ||
250 | break; | ||
251 | case TOMOYO_TYPE_PATH2_ACL: | ||
252 | if (container_of(acl, | ||
253 | struct tomoyo_path2_acl, | ||
254 | head)->perm) | ||
255 | continue; | ||
256 | break; | ||
257 | default: | ||
258 | continue; | ||
259 | } | ||
260 | if (tomoyo_add_to_gc(TOMOYO_ID_ACL, acl)) | ||
261 | list_del_rcu(&acl->list); | ||
262 | else | ||
263 | break; | ||
264 | } | ||
265 | if (!domain->is_deleted || atomic_read(&domain->users)) | ||
266 | continue; | ||
267 | /* | ||
268 | * Nobody is referring this domain. But somebody may | ||
269 | * refer this domain after successful execve(). | ||
270 | * We recheck domain->users after SRCU synchronization. | ||
271 | */ | ||
272 | if (tomoyo_add_to_gc(TOMOYO_ID_DOMAIN, domain)) | ||
273 | list_del_rcu(&domain->list); | ||
274 | else | ||
275 | break; | ||
276 | } | ||
277 | } | ||
278 | mutex_unlock(&tomoyo_policy_lock); | ||
279 | mutex_lock(&tomoyo_name_list_lock); | ||
280 | { | ||
281 | int i; | ||
282 | for (i = 0; i < TOMOYO_MAX_HASH; i++) { | ||
283 | struct tomoyo_name_entry *ptr; | ||
284 | list_for_each_entry_rcu(ptr, &tomoyo_name_list[i], | ||
285 | list) { | ||
286 | if (atomic_read(&ptr->users)) | ||
287 | continue; | ||
288 | if (tomoyo_add_to_gc(TOMOYO_ID_NAME, ptr)) | ||
289 | list_del_rcu(&ptr->list); | ||
290 | else { | ||
291 | i = TOMOYO_MAX_HASH; | ||
292 | break; | ||
293 | } | ||
294 | } | ||
295 | } | ||
296 | } | ||
297 | mutex_unlock(&tomoyo_name_list_lock); | ||
298 | } | ||
299 | |||
300 | static void tomoyo_kfree_entry(void) | ||
301 | { | ||
302 | struct tomoyo_gc_entry *p; | ||
303 | struct tomoyo_gc_entry *tmp; | ||
304 | |||
305 | list_for_each_entry_safe(p, tmp, &tomoyo_gc_queue, list) { | ||
306 | switch (p->type) { | ||
307 | case TOMOYO_ID_DOMAIN_INITIALIZER: | ||
308 | tomoyo_del_domain_initializer(p->element); | ||
309 | break; | ||
310 | case TOMOYO_ID_DOMAIN_KEEPER: | ||
311 | tomoyo_del_domain_keeper(p->element); | ||
312 | break; | ||
313 | case TOMOYO_ID_ALIAS: | ||
314 | tomoyo_del_alias(p->element); | ||
315 | break; | ||
316 | case TOMOYO_ID_GLOBALLY_READABLE: | ||
317 | tomoyo_del_allow_read(p->element); | ||
318 | break; | ||
319 | case TOMOYO_ID_PATTERN: | ||
320 | tomoyo_del_file_pattern(p->element); | ||
321 | break; | ||
322 | case TOMOYO_ID_NO_REWRITE: | ||
323 | tomoyo_del_no_rewrite(p->element); | ||
324 | break; | ||
325 | case TOMOYO_ID_MANAGER: | ||
326 | tomoyo_del_manager(p->element); | ||
327 | break; | ||
328 | case TOMOYO_ID_NAME: | ||
329 | tomoyo_del_name(p->element); | ||
330 | break; | ||
331 | case TOMOYO_ID_ACL: | ||
332 | tomoyo_del_acl(p->element); | ||
333 | break; | ||
334 | case TOMOYO_ID_DOMAIN: | ||
335 | if (!tomoyo_del_domain(p->element)) | ||
336 | continue; | ||
337 | break; | ||
338 | default: | ||
339 | printk(KERN_WARNING "Unknown type\n"); | ||
340 | break; | ||
341 | } | ||
342 | tomoyo_memory_free(p->element); | ||
343 | list_del(&p->list); | ||
344 | kfree(p); | ||
345 | } | ||
346 | } | ||
347 | |||
348 | static int tomoyo_gc_thread(void *unused) | ||
349 | { | ||
350 | daemonize("GC for TOMOYO"); | ||
351 | if (mutex_trylock(&tomoyo_gc_mutex)) { | ||
352 | int i; | ||
353 | for (i = 0; i < 10; i++) { | ||
354 | tomoyo_collect_entry(); | ||
355 | if (list_empty(&tomoyo_gc_queue)) | ||
356 | break; | ||
357 | synchronize_srcu(&tomoyo_ss); | ||
358 | tomoyo_kfree_entry(); | ||
359 | } | ||
360 | mutex_unlock(&tomoyo_gc_mutex); | ||
361 | } | ||
362 | do_exit(0); | ||
363 | } | ||
364 | |||
365 | void tomoyo_run_gc(void) | ||
366 | { | ||
367 | struct task_struct *task = kthread_create(tomoyo_gc_thread, NULL, | ||
368 | "GC for TOMOYO"); | ||
369 | if (!IS_ERR(task)) | ||
370 | wake_up_process(task); | ||
371 | } | ||
diff --git a/security/tomoyo/realpath.c b/security/tomoyo/realpath.c index 5f2e33263371..c225c65ce426 100644 --- a/security/tomoyo/realpath.c +++ b/security/tomoyo/realpath.c | |||
@@ -13,8 +13,10 @@ | |||
13 | #include <linux/mount.h> | 13 | #include <linux/mount.h> |
14 | #include <linux/mnt_namespace.h> | 14 | #include <linux/mnt_namespace.h> |
15 | #include <linux/fs_struct.h> | 15 | #include <linux/fs_struct.h> |
16 | #include <linux/hash.h> | ||
17 | #include <linux/magic.h> | ||
18 | #include <linux/slab.h> | ||
16 | #include "common.h" | 19 | #include "common.h" |
17 | #include "realpath.h" | ||
18 | 20 | ||
19 | /** | 21 | /** |
20 | * tomoyo_encode: Convert binary string to ascii string. | 22 | * tomoyo_encode: Convert binary string to ascii string. |
@@ -87,27 +89,21 @@ int tomoyo_realpath_from_path2(struct path *path, char *newname, | |||
87 | sp = dentry->d_op->d_dname(dentry, newname + offset, | 89 | sp = dentry->d_op->d_dname(dentry, newname + offset, |
88 | newname_len - offset); | 90 | newname_len - offset); |
89 | } else { | 91 | } else { |
90 | /* Taken from d_namespace_path(). */ | 92 | struct path ns_root = {.mnt = NULL, .dentry = NULL}; |
91 | struct path root; | ||
92 | struct path ns_root = { }; | ||
93 | struct path tmp; | ||
94 | 93 | ||
95 | read_lock(¤t->fs->lock); | ||
96 | root = current->fs->root; | ||
97 | path_get(&root); | ||
98 | read_unlock(¤t->fs->lock); | ||
99 | spin_lock(&vfsmount_lock); | ||
100 | if (root.mnt && root.mnt->mnt_ns) | ||
101 | ns_root.mnt = mntget(root.mnt->mnt_ns->root); | ||
102 | if (ns_root.mnt) | ||
103 | ns_root.dentry = dget(ns_root.mnt->mnt_root); | ||
104 | spin_unlock(&vfsmount_lock); | ||
105 | spin_lock(&dcache_lock); | 94 | spin_lock(&dcache_lock); |
106 | tmp = ns_root; | 95 | /* go to whatever namespace root we are under */ |
107 | sp = __d_path(path, &tmp, newname, newname_len); | 96 | sp = __d_path(path, &ns_root, newname, newname_len); |
108 | spin_unlock(&dcache_lock); | 97 | spin_unlock(&dcache_lock); |
109 | path_put(&root); | 98 | /* Prepend "/proc" prefix if using internal proc vfs mount. */ |
110 | path_put(&ns_root); | 99 | if (!IS_ERR(sp) && (path->mnt->mnt_flags & MNT_INTERNAL) && |
100 | (path->mnt->mnt_sb->s_magic == PROC_SUPER_MAGIC)) { | ||
101 | sp -= 5; | ||
102 | if (sp >= newname) | ||
103 | memcpy(sp, "/proc", 5); | ||
104 | else | ||
105 | sp = ERR_PTR(-ENOMEM); | ||
106 | } | ||
111 | } | 107 | } |
112 | if (IS_ERR(sp)) | 108 | if (IS_ERR(sp)) |
113 | error = PTR_ERR(sp); | 109 | error = PTR_ERR(sp); |
@@ -138,12 +134,12 @@ int tomoyo_realpath_from_path2(struct path *path, char *newname, | |||
138 | * | 134 | * |
139 | * Returns the realpath of the given @path on success, NULL otherwise. | 135 | * Returns the realpath of the given @path on success, NULL otherwise. |
140 | * | 136 | * |
141 | * These functions use tomoyo_alloc(), so the caller must call tomoyo_free() | 137 | * These functions use kzalloc(), so the caller must call kfree() |
142 | * if these functions didn't return NULL. | 138 | * if these functions didn't return NULL. |
143 | */ | 139 | */ |
144 | char *tomoyo_realpath_from_path(struct path *path) | 140 | char *tomoyo_realpath_from_path(struct path *path) |
145 | { | 141 | { |
146 | char *buf = tomoyo_alloc(sizeof(struct tomoyo_page_buffer)); | 142 | char *buf = kzalloc(sizeof(struct tomoyo_page_buffer), GFP_KERNEL); |
147 | 143 | ||
148 | BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer) | 144 | BUILD_BUG_ON(sizeof(struct tomoyo_page_buffer) |
149 | <= TOMOYO_MAX_PATHNAME_LEN - 1); | 145 | <= TOMOYO_MAX_PATHNAME_LEN - 1); |
@@ -152,7 +148,7 @@ char *tomoyo_realpath_from_path(struct path *path) | |||
152 | if (tomoyo_realpath_from_path2(path, buf, | 148 | if (tomoyo_realpath_from_path2(path, buf, |
153 | TOMOYO_MAX_PATHNAME_LEN - 1) == 0) | 149 | TOMOYO_MAX_PATHNAME_LEN - 1) == 0) |
154 | return buf; | 150 | return buf; |
155 | tomoyo_free(buf); | 151 | kfree(buf); |
156 | return NULL; | 152 | return NULL; |
157 | } | 153 | } |
158 | 154 | ||
@@ -195,97 +191,47 @@ char *tomoyo_realpath_nofollow(const char *pathname) | |||
195 | } | 191 | } |
196 | 192 | ||
197 | /* Memory allocated for non-string data. */ | 193 | /* Memory allocated for non-string data. */ |
198 | static unsigned int tomoyo_allocated_memory_for_elements; | 194 | static atomic_t tomoyo_policy_memory_size; |
199 | /* Quota for holding non-string data. */ | 195 | /* Quota for holding policy. */ |
200 | static unsigned int tomoyo_quota_for_elements; | 196 | static unsigned int tomoyo_quota_for_policy; |
201 | 197 | ||
202 | /** | 198 | /** |
203 | * tomoyo_alloc_element - Allocate permanent memory for structures. | 199 | * tomoyo_memory_ok - Check memory quota. |
204 | * | 200 | * |
205 | * @size: Size in bytes. | 201 | * @ptr: Pointer to allocated memory. |
206 | * | 202 | * |
207 | * Returns pointer to allocated memory on success, NULL otherwise. | 203 | * Returns true on success, false otherwise. |
208 | * | 204 | * |
209 | * Memory has to be zeroed. | 205 | * Caller holds tomoyo_policy_lock. |
210 | * The RAM is chunked, so NEVER try to kfree() the returned pointer. | 206 | * Memory pointed by @ptr will be zeroed on success. |
211 | */ | 207 | */ |
212 | void *tomoyo_alloc_element(const unsigned int size) | 208 | bool tomoyo_memory_ok(void *ptr) |
213 | { | 209 | { |
214 | static char *buf; | 210 | int allocated_len = ptr ? ksize(ptr) : 0; |
215 | static DEFINE_MUTEX(lock); | 211 | atomic_add(allocated_len, &tomoyo_policy_memory_size); |
216 | static unsigned int buf_used_len = PATH_MAX; | 212 | if (ptr && (!tomoyo_quota_for_policy || |
217 | char *ptr = NULL; | 213 | atomic_read(&tomoyo_policy_memory_size) |
218 | /*Assumes sizeof(void *) >= sizeof(long) is true. */ | 214 | <= tomoyo_quota_for_policy)) { |
219 | const unsigned int word_aligned_size | 215 | memset(ptr, 0, allocated_len); |
220 | = roundup(size, max(sizeof(void *), sizeof(long))); | 216 | return true; |
221 | if (word_aligned_size > PATH_MAX) | ||
222 | return NULL; | ||
223 | mutex_lock(&lock); | ||
224 | if (buf_used_len + word_aligned_size > PATH_MAX) { | ||
225 | if (!tomoyo_quota_for_elements || | ||
226 | tomoyo_allocated_memory_for_elements | ||
227 | + PATH_MAX <= tomoyo_quota_for_elements) | ||
228 | ptr = kzalloc(PATH_MAX, GFP_KERNEL); | ||
229 | if (!ptr) { | ||
230 | printk(KERN_WARNING "ERROR: Out of memory " | ||
231 | "for tomoyo_alloc_element().\n"); | ||
232 | if (!tomoyo_policy_loaded) | ||
233 | panic("MAC Initialization failed.\n"); | ||
234 | } else { | ||
235 | buf = ptr; | ||
236 | tomoyo_allocated_memory_for_elements += PATH_MAX; | ||
237 | buf_used_len = word_aligned_size; | ||
238 | ptr = buf; | ||
239 | } | ||
240 | } else if (word_aligned_size) { | ||
241 | int i; | ||
242 | ptr = buf + buf_used_len; | ||
243 | buf_used_len += word_aligned_size; | ||
244 | for (i = 0; i < word_aligned_size; i++) { | ||
245 | if (!ptr[i]) | ||
246 | continue; | ||
247 | printk(KERN_ERR "WARNING: Reserved memory was tainted! " | ||
248 | "The system might go wrong.\n"); | ||
249 | ptr[i] = '\0'; | ||
250 | } | ||
251 | } | 217 | } |
252 | mutex_unlock(&lock); | 218 | printk(KERN_WARNING "ERROR: Out of memory " |
253 | return ptr; | 219 | "for tomoyo_alloc_element().\n"); |
220 | if (!tomoyo_policy_loaded) | ||
221 | panic("MAC Initialization failed.\n"); | ||
222 | return false; | ||
254 | } | 223 | } |
255 | 224 | ||
256 | /* Memory allocated for string data in bytes. */ | 225 | /** |
257 | static unsigned int tomoyo_allocated_memory_for_savename; | 226 | * tomoyo_memory_free - Free memory for elements. |
258 | /* Quota for holding string data in bytes. */ | ||
259 | static unsigned int tomoyo_quota_for_savename; | ||
260 | |||
261 | /* | ||
262 | * TOMOYO uses this hash only when appending a string into the string | ||
263 | * table. Frequency of appending strings is very low. So we don't need | ||
264 | * large (e.g. 64k) hash size. 256 will be sufficient. | ||
265 | */ | ||
266 | #define TOMOYO_MAX_HASH 256 | ||
267 | |||
268 | /* | ||
269 | * tomoyo_name_entry is a structure which is used for linking | ||
270 | * "struct tomoyo_path_info" into tomoyo_name_list . | ||
271 | * | 227 | * |
272 | * Since tomoyo_name_list manages a list of strings which are shared by | 228 | * @ptr: Pointer to allocated memory. |
273 | * multiple processes (whereas "struct tomoyo_path_info" inside | ||
274 | * "struct tomoyo_path_info_with_data" is not shared), a reference counter will | ||
275 | * be added to "struct tomoyo_name_entry" rather than "struct tomoyo_path_info" | ||
276 | * when TOMOYO starts supporting garbage collector. | ||
277 | */ | 229 | */ |
278 | struct tomoyo_name_entry { | 230 | void tomoyo_memory_free(void *ptr) |
279 | struct list_head list; | 231 | { |
280 | struct tomoyo_path_info entry; | 232 | atomic_sub(ksize(ptr), &tomoyo_policy_memory_size); |
281 | }; | 233 | kfree(ptr); |
282 | 234 | } | |
283 | /* Structure for available memory region. */ | ||
284 | struct tomoyo_free_memory_block_list { | ||
285 | struct list_head list; | ||
286 | char *ptr; /* Pointer to a free area. */ | ||
287 | int len; /* Length of the area. */ | ||
288 | }; | ||
289 | 235 | ||
290 | /* | 236 | /* |
291 | * tomoyo_name_list is used for holding string data used by TOMOYO. | 237 | * tomoyo_name_list is used for holding string data used by TOMOYO. |
@@ -293,85 +239,58 @@ struct tomoyo_free_memory_block_list { | |||
293 | * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of | 239 | * "/lib/libc-2.5.so"), TOMOYO shares string data in the form of |
294 | * "const struct tomoyo_path_info *". | 240 | * "const struct tomoyo_path_info *". |
295 | */ | 241 | */ |
296 | static struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; | 242 | struct list_head tomoyo_name_list[TOMOYO_MAX_HASH]; |
243 | /* Lock for protecting tomoyo_name_list . */ | ||
244 | DEFINE_MUTEX(tomoyo_name_list_lock); | ||
297 | 245 | ||
298 | /** | 246 | /** |
299 | * tomoyo_save_name - Allocate permanent memory for string data. | 247 | * tomoyo_get_name - Allocate permanent memory for string data. |
300 | * | 248 | * |
301 | * @name: The string to store into the permernent memory. | 249 | * @name: The string to store into the permernent memory. |
302 | * | 250 | * |
303 | * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise. | 251 | * Returns pointer to "struct tomoyo_path_info" on success, NULL otherwise. |
304 | * | ||
305 | * The RAM is shared, so NEVER try to modify or kfree() the returned name. | ||
306 | */ | 252 | */ |
307 | const struct tomoyo_path_info *tomoyo_save_name(const char *name) | 253 | const struct tomoyo_path_info *tomoyo_get_name(const char *name) |
308 | { | 254 | { |
309 | static LIST_HEAD(fmb_list); | ||
310 | static DEFINE_MUTEX(lock); | ||
311 | struct tomoyo_name_entry *ptr; | 255 | struct tomoyo_name_entry *ptr; |
312 | unsigned int hash; | 256 | unsigned int hash; |
313 | /* fmb contains available size in bytes. | ||
314 | fmb is removed from the fmb_list when fmb->len becomes 0. */ | ||
315 | struct tomoyo_free_memory_block_list *fmb; | ||
316 | int len; | 257 | int len; |
317 | char *cp; | 258 | int allocated_len; |
259 | struct list_head *head; | ||
318 | 260 | ||
319 | if (!name) | 261 | if (!name) |
320 | return NULL; | 262 | return NULL; |
321 | len = strlen(name) + 1; | 263 | len = strlen(name) + 1; |
322 | if (len > TOMOYO_MAX_PATHNAME_LEN) { | ||
323 | printk(KERN_WARNING "ERROR: Name too long " | ||
324 | "for tomoyo_save_name().\n"); | ||
325 | return NULL; | ||
326 | } | ||
327 | hash = full_name_hash((const unsigned char *) name, len - 1); | 264 | hash = full_name_hash((const unsigned char *) name, len - 1); |
328 | mutex_lock(&lock); | 265 | head = &tomoyo_name_list[hash_long(hash, TOMOYO_HASH_BITS)]; |
329 | list_for_each_entry(ptr, &tomoyo_name_list[hash % TOMOYO_MAX_HASH], | 266 | mutex_lock(&tomoyo_name_list_lock); |
330 | list) { | 267 | list_for_each_entry(ptr, head, list) { |
331 | if (hash == ptr->entry.hash && !strcmp(name, ptr->entry.name)) | 268 | if (hash != ptr->entry.hash || strcmp(name, ptr->entry.name)) |
332 | goto out; | 269 | continue; |
333 | } | 270 | atomic_inc(&ptr->users); |
334 | list_for_each_entry(fmb, &fmb_list, list) { | 271 | goto out; |
335 | if (len <= fmb->len) | ||
336 | goto ready; | ||
337 | } | 272 | } |
338 | if (!tomoyo_quota_for_savename || | 273 | ptr = kzalloc(sizeof(*ptr) + len, GFP_KERNEL); |
339 | tomoyo_allocated_memory_for_savename + PATH_MAX | 274 | allocated_len = ptr ? ksize(ptr) : 0; |
340 | <= tomoyo_quota_for_savename) | 275 | if (!ptr || (tomoyo_quota_for_policy && |
341 | cp = kzalloc(PATH_MAX, GFP_KERNEL); | 276 | atomic_read(&tomoyo_policy_memory_size) + allocated_len |
342 | else | 277 | > tomoyo_quota_for_policy)) { |
343 | cp = NULL; | 278 | kfree(ptr); |
344 | fmb = kzalloc(sizeof(*fmb), GFP_KERNEL); | ||
345 | if (!cp || !fmb) { | ||
346 | kfree(cp); | ||
347 | kfree(fmb); | ||
348 | printk(KERN_WARNING "ERROR: Out of memory " | 279 | printk(KERN_WARNING "ERROR: Out of memory " |
349 | "for tomoyo_save_name().\n"); | 280 | "for tomoyo_get_name().\n"); |
350 | if (!tomoyo_policy_loaded) | 281 | if (!tomoyo_policy_loaded) |
351 | panic("MAC Initialization failed.\n"); | 282 | panic("MAC Initialization failed.\n"); |
352 | ptr = NULL; | 283 | ptr = NULL; |
353 | goto out; | 284 | goto out; |
354 | } | 285 | } |
355 | tomoyo_allocated_memory_for_savename += PATH_MAX; | 286 | atomic_add(allocated_len, &tomoyo_policy_memory_size); |
356 | list_add(&fmb->list, &fmb_list); | 287 | ptr->entry.name = ((char *) ptr) + sizeof(*ptr); |
357 | fmb->ptr = cp; | 288 | memmove((char *) ptr->entry.name, name, len); |
358 | fmb->len = PATH_MAX; | 289 | atomic_set(&ptr->users, 1); |
359 | ready: | ||
360 | ptr = tomoyo_alloc_element(sizeof(*ptr)); | ||
361 | if (!ptr) | ||
362 | goto out; | ||
363 | ptr->entry.name = fmb->ptr; | ||
364 | memmove(fmb->ptr, name, len); | ||
365 | tomoyo_fill_path_info(&ptr->entry); | 290 | tomoyo_fill_path_info(&ptr->entry); |
366 | fmb->ptr += len; | 291 | list_add_tail(&ptr->list, head); |
367 | fmb->len -= len; | ||
368 | list_add_tail(&ptr->list, &tomoyo_name_list[hash % TOMOYO_MAX_HASH]); | ||
369 | if (fmb->len == 0) { | ||
370 | list_del(&fmb->list); | ||
371 | kfree(fmb); | ||
372 | } | ||
373 | out: | 292 | out: |
374 | mutex_unlock(&lock); | 293 | mutex_unlock(&tomoyo_name_list_lock); |
375 | return ptr ? &ptr->entry : NULL; | 294 | return ptr ? &ptr->entry : NULL; |
376 | } | 295 | } |
377 | 296 | ||
@@ -386,45 +305,14 @@ void __init tomoyo_realpath_init(void) | |||
386 | for (i = 0; i < TOMOYO_MAX_HASH; i++) | 305 | for (i = 0; i < TOMOYO_MAX_HASH; i++) |
387 | INIT_LIST_HEAD(&tomoyo_name_list[i]); | 306 | INIT_LIST_HEAD(&tomoyo_name_list[i]); |
388 | INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); | 307 | INIT_LIST_HEAD(&tomoyo_kernel_domain.acl_info_list); |
389 | tomoyo_kernel_domain.domainname = tomoyo_save_name(TOMOYO_ROOT_NAME); | 308 | tomoyo_kernel_domain.domainname = tomoyo_get_name(TOMOYO_ROOT_NAME); |
390 | list_add_tail(&tomoyo_kernel_domain.list, &tomoyo_domain_list); | 309 | /* |
391 | down_read(&tomoyo_domain_list_lock); | 310 | * tomoyo_read_lock() is not needed because this function is |
311 | * called before the first "delete" request. | ||
312 | */ | ||
313 | list_add_tail_rcu(&tomoyo_kernel_domain.list, &tomoyo_domain_list); | ||
392 | if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain) | 314 | if (tomoyo_find_domain(TOMOYO_ROOT_NAME) != &tomoyo_kernel_domain) |
393 | panic("Can't register tomoyo_kernel_domain"); | 315 | panic("Can't register tomoyo_kernel_domain"); |
394 | up_read(&tomoyo_domain_list_lock); | ||
395 | } | ||
396 | |||
397 | /* Memory allocated for temporary purpose. */ | ||
398 | static atomic_t tomoyo_dynamic_memory_size; | ||
399 | |||
400 | /** | ||
401 | * tomoyo_alloc - Allocate memory for temporary purpose. | ||
402 | * | ||
403 | * @size: Size in bytes. | ||
404 | * | ||
405 | * Returns pointer to allocated memory on success, NULL otherwise. | ||
406 | */ | ||
407 | void *tomoyo_alloc(const size_t size) | ||
408 | { | ||
409 | void *p = kzalloc(size, GFP_KERNEL); | ||
410 | if (p) | ||
411 | atomic_add(ksize(p), &tomoyo_dynamic_memory_size); | ||
412 | return p; | ||
413 | } | ||
414 | |||
415 | /** | ||
416 | * tomoyo_free - Release memory allocated by tomoyo_alloc(). | ||
417 | * | ||
418 | * @p: Pointer returned by tomoyo_alloc(). May be NULL. | ||
419 | * | ||
420 | * Returns nothing. | ||
421 | */ | ||
422 | void tomoyo_free(const void *p) | ||
423 | { | ||
424 | if (p) { | ||
425 | atomic_sub(ksize(p), &tomoyo_dynamic_memory_size); | ||
426 | kfree(p); | ||
427 | } | ||
428 | } | 316 | } |
429 | 317 | ||
430 | /** | 318 | /** |
@@ -437,32 +325,19 @@ void tomoyo_free(const void *p) | |||
437 | int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head) | 325 | int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head) |
438 | { | 326 | { |
439 | if (!head->read_eof) { | 327 | if (!head->read_eof) { |
440 | const unsigned int shared | 328 | const unsigned int policy |
441 | = tomoyo_allocated_memory_for_savename; | 329 | = atomic_read(&tomoyo_policy_memory_size); |
442 | const unsigned int private | ||
443 | = tomoyo_allocated_memory_for_elements; | ||
444 | const unsigned int dynamic | ||
445 | = atomic_read(&tomoyo_dynamic_memory_size); | ||
446 | char buffer[64]; | 330 | char buffer[64]; |
447 | 331 | ||
448 | memset(buffer, 0, sizeof(buffer)); | 332 | memset(buffer, 0, sizeof(buffer)); |
449 | if (tomoyo_quota_for_savename) | 333 | if (tomoyo_quota_for_policy) |
450 | snprintf(buffer, sizeof(buffer) - 1, | ||
451 | " (Quota: %10u)", | ||
452 | tomoyo_quota_for_savename); | ||
453 | else | ||
454 | buffer[0] = '\0'; | ||
455 | tomoyo_io_printf(head, "Shared: %10u%s\n", shared, buffer); | ||
456 | if (tomoyo_quota_for_elements) | ||
457 | snprintf(buffer, sizeof(buffer) - 1, | 334 | snprintf(buffer, sizeof(buffer) - 1, |
458 | " (Quota: %10u)", | 335 | " (Quota: %10u)", |
459 | tomoyo_quota_for_elements); | 336 | tomoyo_quota_for_policy); |
460 | else | 337 | else |
461 | buffer[0] = '\0'; | 338 | buffer[0] = '\0'; |
462 | tomoyo_io_printf(head, "Private: %10u%s\n", private, buffer); | 339 | tomoyo_io_printf(head, "Policy: %10u%s\n", policy, buffer); |
463 | tomoyo_io_printf(head, "Dynamic: %10u\n", dynamic); | 340 | tomoyo_io_printf(head, "Total: %10u\n", policy); |
464 | tomoyo_io_printf(head, "Total: %10u\n", | ||
465 | shared + private + dynamic); | ||
466 | head->read_eof = true; | 341 | head->read_eof = true; |
467 | } | 342 | } |
468 | return 0; | 343 | return 0; |
@@ -480,9 +355,7 @@ int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head) | |||
480 | char *data = head->write_buf; | 355 | char *data = head->write_buf; |
481 | unsigned int size; | 356 | unsigned int size; |
482 | 357 | ||
483 | if (sscanf(data, "Shared: %u", &size) == 1) | 358 | if (sscanf(data, "Policy: %u", &size) == 1) |
484 | tomoyo_quota_for_savename = size; | 359 | tomoyo_quota_for_policy = size; |
485 | else if (sscanf(data, "Private: %u", &size) == 1) | ||
486 | tomoyo_quota_for_elements = size; | ||
487 | return 0; | 360 | return 0; |
488 | } | 361 | } |
diff --git a/security/tomoyo/realpath.h b/security/tomoyo/realpath.h deleted file mode 100644 index 78217a37960b..000000000000 --- a/security/tomoyo/realpath.h +++ /dev/null | |||
@@ -1,66 +0,0 @@ | |||
1 | /* | ||
2 | * security/tomoyo/realpath.h | ||
3 | * | ||
4 | * Get the canonicalized absolute pathnames. The basis for TOMOYO. | ||
5 | * | ||
6 | * Copyright (C) 2005-2009 NTT DATA CORPORATION | ||
7 | * | ||
8 | * Version: 2.2.0 2009/04/01 | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #ifndef _SECURITY_TOMOYO_REALPATH_H | ||
13 | #define _SECURITY_TOMOYO_REALPATH_H | ||
14 | |||
15 | struct path; | ||
16 | struct tomoyo_path_info; | ||
17 | struct tomoyo_io_buffer; | ||
18 | |||
19 | /* Convert binary string to ascii string. */ | ||
20 | int tomoyo_encode(char *buffer, int buflen, const char *str); | ||
21 | |||
22 | /* Returns realpath(3) of the given pathname but ignores chroot'ed root. */ | ||
23 | int tomoyo_realpath_from_path2(struct path *path, char *newname, | ||
24 | int newname_len); | ||
25 | |||
26 | /* | ||
27 | * Returns realpath(3) of the given pathname but ignores chroot'ed root. | ||
28 | * These functions use tomoyo_alloc(), so the caller must call tomoyo_free() | ||
29 | * if these functions didn't return NULL. | ||
30 | */ | ||
31 | char *tomoyo_realpath(const char *pathname); | ||
32 | /* | ||
33 | * Same with tomoyo_realpath() except that it doesn't follow the final symlink. | ||
34 | */ | ||
35 | char *tomoyo_realpath_nofollow(const char *pathname); | ||
36 | /* Same with tomoyo_realpath() except that the pathname is already solved. */ | ||
37 | char *tomoyo_realpath_from_path(struct path *path); | ||
38 | |||
39 | /* | ||
40 | * Allocate memory for ACL entry. | ||
41 | * The RAM is chunked, so NEVER try to kfree() the returned pointer. | ||
42 | */ | ||
43 | void *tomoyo_alloc_element(const unsigned int size); | ||
44 | |||
45 | /* | ||
46 | * Keep the given name on the RAM. | ||
47 | * The RAM is shared, so NEVER try to modify or kfree() the returned name. | ||
48 | */ | ||
49 | const struct tomoyo_path_info *tomoyo_save_name(const char *name); | ||
50 | |||
51 | /* Allocate memory for temporary use (e.g. permission checks). */ | ||
52 | void *tomoyo_alloc(const size_t size); | ||
53 | |||
54 | /* Free memory allocated by tomoyo_alloc(). */ | ||
55 | void tomoyo_free(const void *p); | ||
56 | |||
57 | /* Check for memory usage. */ | ||
58 | int tomoyo_read_memory_counter(struct tomoyo_io_buffer *head); | ||
59 | |||
60 | /* Set memory quota. */ | ||
61 | int tomoyo_write_memory_quota(struct tomoyo_io_buffer *head); | ||
62 | |||
63 | /* Initialize realpath related code. */ | ||
64 | void __init tomoyo_realpath_init(void); | ||
65 | |||
66 | #endif /* !defined(_SECURITY_TOMOYO_REALPATH_H) */ | ||
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 9548a0984cc4..dedd97d0c163 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c | |||
@@ -11,8 +11,6 @@ | |||
11 | 11 | ||
12 | #include <linux/security.h> | 12 | #include <linux/security.h> |
13 | #include "common.h" | 13 | #include "common.h" |
14 | #include "tomoyo.h" | ||
15 | #include "realpath.h" | ||
16 | 14 | ||
17 | static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) | 15 | static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) |
18 | { | 16 | { |
@@ -23,21 +21,23 @@ static int tomoyo_cred_alloc_blank(struct cred *new, gfp_t gfp) | |||
23 | static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, | 21 | static int tomoyo_cred_prepare(struct cred *new, const struct cred *old, |
24 | gfp_t gfp) | 22 | gfp_t gfp) |
25 | { | 23 | { |
26 | /* | 24 | struct tomoyo_domain_info *domain = old->security; |
27 | * Since "struct tomoyo_domain_info *" is a sharable pointer, | 25 | new->security = domain; |
28 | * we don't need to duplicate. | 26 | if (domain) |
29 | */ | 27 | atomic_inc(&domain->users); |
30 | new->security = old->security; | ||
31 | return 0; | 28 | return 0; |
32 | } | 29 | } |
33 | 30 | ||
34 | static void tomoyo_cred_transfer(struct cred *new, const struct cred *old) | 31 | static void tomoyo_cred_transfer(struct cred *new, const struct cred *old) |
35 | { | 32 | { |
36 | /* | 33 | tomoyo_cred_prepare(new, old, 0); |
37 | * Since "struct tomoyo_domain_info *" is a sharable pointer, | 34 | } |
38 | * we don't need to duplicate. | 35 | |
39 | */ | 36 | static void tomoyo_cred_free(struct cred *cred) |
40 | new->security = old->security; | 37 | { |
38 | struct tomoyo_domain_info *domain = cred->security; | ||
39 | if (domain) | ||
40 | atomic_dec(&domain->users); | ||
41 | } | 41 | } |
42 | 42 | ||
43 | static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) | 43 | static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) |
@@ -61,6 +61,14 @@ static int tomoyo_bprm_set_creds(struct linux_binprm *bprm) | |||
61 | if (!tomoyo_policy_loaded) | 61 | if (!tomoyo_policy_loaded) |
62 | tomoyo_load_policy(bprm->filename); | 62 | tomoyo_load_policy(bprm->filename); |
63 | /* | 63 | /* |
64 | * Release reference to "struct tomoyo_domain_info" stored inside | ||
65 | * "bprm->cred->security". New reference to "struct tomoyo_domain_info" | ||
66 | * stored inside "bprm->cred->security" will be acquired later inside | ||
67 | * tomoyo_find_next_domain(). | ||
68 | */ | ||
69 | atomic_dec(&((struct tomoyo_domain_info *) | ||
70 | bprm->cred->security)->users); | ||
71 | /* | ||
64 | * Tell tomoyo_bprm_check_security() is called for the first time of an | 72 | * Tell tomoyo_bprm_check_security() is called for the first time of an |
65 | * execve operation. | 73 | * execve operation. |
66 | */ | 74 | */ |
@@ -76,156 +84,71 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm) | |||
76 | * Execute permission is checked against pathname passed to do_execve() | 84 | * Execute permission is checked against pathname passed to do_execve() |
77 | * using current domain. | 85 | * using current domain. |
78 | */ | 86 | */ |
79 | if (!domain) | 87 | if (!domain) { |
80 | return tomoyo_find_next_domain(bprm); | 88 | const int idx = tomoyo_read_lock(); |
89 | const int err = tomoyo_find_next_domain(bprm); | ||
90 | tomoyo_read_unlock(idx); | ||
91 | return err; | ||
92 | } | ||
81 | /* | 93 | /* |
82 | * Read permission is checked against interpreters using next domain. | 94 | * Read permission is checked against interpreters using next domain. |
83 | * '1' is the result of open_to_namei_flags(O_RDONLY). | ||
84 | */ | 95 | */ |
85 | return tomoyo_check_open_permission(domain, &bprm->file->f_path, 1); | 96 | return tomoyo_check_open_permission(domain, &bprm->file->f_path, O_RDONLY); |
86 | } | ||
87 | |||
88 | #ifdef CONFIG_SYSCTL | ||
89 | |||
90 | static int tomoyo_prepend(char **buffer, int *buflen, const char *str) | ||
91 | { | ||
92 | int namelen = strlen(str); | ||
93 | |||
94 | if (*buflen < namelen) | ||
95 | return -ENOMEM; | ||
96 | *buflen -= namelen; | ||
97 | *buffer -= namelen; | ||
98 | memcpy(*buffer, str, namelen); | ||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * tomoyo_sysctl_path - return the realpath of a ctl_table. | ||
104 | * @table: pointer to "struct ctl_table". | ||
105 | * | ||
106 | * Returns realpath(3) of the @table on success. | ||
107 | * Returns NULL on failure. | ||
108 | * | ||
109 | * This function uses tomoyo_alloc(), so the caller must call tomoyo_free() | ||
110 | * if this function didn't return NULL. | ||
111 | */ | ||
112 | static char *tomoyo_sysctl_path(struct ctl_table *table) | ||
113 | { | ||
114 | int buflen = TOMOYO_MAX_PATHNAME_LEN; | ||
115 | char *buf = tomoyo_alloc(buflen); | ||
116 | char *end = buf + buflen; | ||
117 | int error = -ENOMEM; | ||
118 | |||
119 | if (!buf) | ||
120 | return NULL; | ||
121 | |||
122 | *--end = '\0'; | ||
123 | buflen--; | ||
124 | while (table) { | ||
125 | char num[32]; | ||
126 | const char *sp = table->procname; | ||
127 | |||
128 | if (!sp) { | ||
129 | memset(num, 0, sizeof(num)); | ||
130 | snprintf(num, sizeof(num) - 1, "=%d=", table->ctl_name); | ||
131 | sp = num; | ||
132 | } | ||
133 | if (tomoyo_prepend(&end, &buflen, sp) || | ||
134 | tomoyo_prepend(&end, &buflen, "/")) | ||
135 | goto out; | ||
136 | table = table->parent; | ||
137 | } | ||
138 | if (tomoyo_prepend(&end, &buflen, "/proc/sys")) | ||
139 | goto out; | ||
140 | error = tomoyo_encode(buf, end - buf, end); | ||
141 | out: | ||
142 | if (!error) | ||
143 | return buf; | ||
144 | tomoyo_free(buf); | ||
145 | return NULL; | ||
146 | } | ||
147 | |||
148 | static int tomoyo_sysctl(struct ctl_table *table, int op) | ||
149 | { | ||
150 | int error; | ||
151 | char *name; | ||
152 | |||
153 | op &= MAY_READ | MAY_WRITE; | ||
154 | if (!op) | ||
155 | return 0; | ||
156 | name = tomoyo_sysctl_path(table); | ||
157 | if (!name) | ||
158 | return -ENOMEM; | ||
159 | error = tomoyo_check_file_perm(tomoyo_domain(), name, op); | ||
160 | tomoyo_free(name); | ||
161 | return error; | ||
162 | } | 97 | } |
163 | #endif | ||
164 | 98 | ||
165 | static int tomoyo_path_truncate(struct path *path, loff_t length, | 99 | static int tomoyo_path_truncate(struct path *path, loff_t length, |
166 | unsigned int time_attrs) | 100 | unsigned int time_attrs) |
167 | { | 101 | { |
168 | return tomoyo_check_1path_perm(tomoyo_domain(), | 102 | return tomoyo_path_perm(TOMOYO_TYPE_TRUNCATE, path); |
169 | TOMOYO_TYPE_TRUNCATE_ACL, | ||
170 | path); | ||
171 | } | 103 | } |
172 | 104 | ||
173 | static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry) | 105 | static int tomoyo_path_unlink(struct path *parent, struct dentry *dentry) |
174 | { | 106 | { |
175 | struct path path = { parent->mnt, dentry }; | 107 | struct path path = { parent->mnt, dentry }; |
176 | return tomoyo_check_1path_perm(tomoyo_domain(), | 108 | return tomoyo_path_perm(TOMOYO_TYPE_UNLINK, &path); |
177 | TOMOYO_TYPE_UNLINK_ACL, | ||
178 | &path); | ||
179 | } | 109 | } |
180 | 110 | ||
181 | static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, | 111 | static int tomoyo_path_mkdir(struct path *parent, struct dentry *dentry, |
182 | int mode) | 112 | int mode) |
183 | { | 113 | { |
184 | struct path path = { parent->mnt, dentry }; | 114 | struct path path = { parent->mnt, dentry }; |
185 | return tomoyo_check_1path_perm(tomoyo_domain(), | 115 | return tomoyo_path_perm(TOMOYO_TYPE_MKDIR, &path); |
186 | TOMOYO_TYPE_MKDIR_ACL, | ||
187 | &path); | ||
188 | } | 116 | } |
189 | 117 | ||
190 | static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) | 118 | static int tomoyo_path_rmdir(struct path *parent, struct dentry *dentry) |
191 | { | 119 | { |
192 | struct path path = { parent->mnt, dentry }; | 120 | struct path path = { parent->mnt, dentry }; |
193 | return tomoyo_check_1path_perm(tomoyo_domain(), | 121 | return tomoyo_path_perm(TOMOYO_TYPE_RMDIR, &path); |
194 | TOMOYO_TYPE_RMDIR_ACL, | ||
195 | &path); | ||
196 | } | 122 | } |
197 | 123 | ||
198 | static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry, | 124 | static int tomoyo_path_symlink(struct path *parent, struct dentry *dentry, |
199 | const char *old_name) | 125 | const char *old_name) |
200 | { | 126 | { |
201 | struct path path = { parent->mnt, dentry }; | 127 | struct path path = { parent->mnt, dentry }; |
202 | return tomoyo_check_1path_perm(tomoyo_domain(), | 128 | return tomoyo_path_perm(TOMOYO_TYPE_SYMLINK, &path); |
203 | TOMOYO_TYPE_SYMLINK_ACL, | ||
204 | &path); | ||
205 | } | 129 | } |
206 | 130 | ||
207 | static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, | 131 | static int tomoyo_path_mknod(struct path *parent, struct dentry *dentry, |
208 | int mode, unsigned int dev) | 132 | int mode, unsigned int dev) |
209 | { | 133 | { |
210 | struct path path = { parent->mnt, dentry }; | 134 | struct path path = { parent->mnt, dentry }; |
211 | int type = TOMOYO_TYPE_CREATE_ACL; | 135 | int type = TOMOYO_TYPE_CREATE; |
212 | 136 | ||
213 | switch (mode & S_IFMT) { | 137 | switch (mode & S_IFMT) { |
214 | case S_IFCHR: | 138 | case S_IFCHR: |
215 | type = TOMOYO_TYPE_MKCHAR_ACL; | 139 | type = TOMOYO_TYPE_MKCHAR; |
216 | break; | 140 | break; |
217 | case S_IFBLK: | 141 | case S_IFBLK: |
218 | type = TOMOYO_TYPE_MKBLOCK_ACL; | 142 | type = TOMOYO_TYPE_MKBLOCK; |
219 | break; | 143 | break; |
220 | case S_IFIFO: | 144 | case S_IFIFO: |
221 | type = TOMOYO_TYPE_MKFIFO_ACL; | 145 | type = TOMOYO_TYPE_MKFIFO; |
222 | break; | 146 | break; |
223 | case S_IFSOCK: | 147 | case S_IFSOCK: |
224 | type = TOMOYO_TYPE_MKSOCK_ACL; | 148 | type = TOMOYO_TYPE_MKSOCK; |
225 | break; | 149 | break; |
226 | } | 150 | } |
227 | return tomoyo_check_1path_perm(tomoyo_domain(), | 151 | return tomoyo_path_perm(type, &path); |
228 | type, &path); | ||
229 | } | 152 | } |
230 | 153 | ||
231 | static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, | 154 | static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, |
@@ -233,9 +156,7 @@ static int tomoyo_path_link(struct dentry *old_dentry, struct path *new_dir, | |||
233 | { | 156 | { |
234 | struct path path1 = { new_dir->mnt, old_dentry }; | 157 | struct path path1 = { new_dir->mnt, old_dentry }; |
235 | struct path path2 = { new_dir->mnt, new_dentry }; | 158 | struct path path2 = { new_dir->mnt, new_dentry }; |
236 | return tomoyo_check_2path_perm(tomoyo_domain(), | 159 | return tomoyo_path2_perm(TOMOYO_TYPE_LINK, &path1, &path2); |
237 | TOMOYO_TYPE_LINK_ACL, | ||
238 | &path1, &path2); | ||
239 | } | 160 | } |
240 | 161 | ||
241 | static int tomoyo_path_rename(struct path *old_parent, | 162 | static int tomoyo_path_rename(struct path *old_parent, |
@@ -245,32 +166,71 @@ static int tomoyo_path_rename(struct path *old_parent, | |||
245 | { | 166 | { |
246 | struct path path1 = { old_parent->mnt, old_dentry }; | 167 | struct path path1 = { old_parent->mnt, old_dentry }; |
247 | struct path path2 = { new_parent->mnt, new_dentry }; | 168 | struct path path2 = { new_parent->mnt, new_dentry }; |
248 | return tomoyo_check_2path_perm(tomoyo_domain(), | 169 | return tomoyo_path2_perm(TOMOYO_TYPE_RENAME, &path1, &path2); |
249 | TOMOYO_TYPE_RENAME_ACL, | ||
250 | &path1, &path2); | ||
251 | } | 170 | } |
252 | 171 | ||
253 | static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, | 172 | static int tomoyo_file_fcntl(struct file *file, unsigned int cmd, |
254 | unsigned long arg) | 173 | unsigned long arg) |
255 | { | 174 | { |
256 | if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)) | 175 | if (cmd == F_SETFL && ((arg ^ file->f_flags) & O_APPEND)) |
257 | return tomoyo_check_rewrite_permission(tomoyo_domain(), file); | 176 | return tomoyo_check_rewrite_permission(file); |
258 | return 0; | 177 | return 0; |
259 | } | 178 | } |
260 | 179 | ||
261 | static int tomoyo_dentry_open(struct file *f, const struct cred *cred) | 180 | static int tomoyo_dentry_open(struct file *f, const struct cred *cred) |
262 | { | 181 | { |
263 | int flags = f->f_flags; | 182 | int flags = f->f_flags; |
264 | |||
265 | if ((flags + 1) & O_ACCMODE) | ||
266 | flags++; | ||
267 | flags |= f->f_flags & (O_APPEND | O_TRUNC); | ||
268 | /* Don't check read permission here if called from do_execve(). */ | 183 | /* Don't check read permission here if called from do_execve(). */ |
269 | if (current->in_execve) | 184 | if (current->in_execve) |
270 | return 0; | 185 | return 0; |
271 | return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags); | 186 | return tomoyo_check_open_permission(tomoyo_domain(), &f->f_path, flags); |
272 | } | 187 | } |
273 | 188 | ||
189 | static int tomoyo_file_ioctl(struct file *file, unsigned int cmd, | ||
190 | unsigned long arg) | ||
191 | { | ||
192 | return tomoyo_path_perm(TOMOYO_TYPE_IOCTL, &file->f_path); | ||
193 | } | ||
194 | |||
195 | static int tomoyo_path_chmod(struct dentry *dentry, struct vfsmount *mnt, | ||
196 | mode_t mode) | ||
197 | { | ||
198 | struct path path = { mnt, dentry }; | ||
199 | return tomoyo_path_perm(TOMOYO_TYPE_CHMOD, &path); | ||
200 | } | ||
201 | |||
202 | static int tomoyo_path_chown(struct path *path, uid_t uid, gid_t gid) | ||
203 | { | ||
204 | int error = 0; | ||
205 | if (uid != (uid_t) -1) | ||
206 | error = tomoyo_path_perm(TOMOYO_TYPE_CHOWN, path); | ||
207 | if (!error && gid != (gid_t) -1) | ||
208 | error = tomoyo_path_perm(TOMOYO_TYPE_CHGRP, path); | ||
209 | return error; | ||
210 | } | ||
211 | |||
212 | static int tomoyo_path_chroot(struct path *path) | ||
213 | { | ||
214 | return tomoyo_path_perm(TOMOYO_TYPE_CHROOT, path); | ||
215 | } | ||
216 | |||
217 | static int tomoyo_sb_mount(char *dev_name, struct path *path, | ||
218 | char *type, unsigned long flags, void *data) | ||
219 | { | ||
220 | return tomoyo_path_perm(TOMOYO_TYPE_MOUNT, path); | ||
221 | } | ||
222 | |||
223 | static int tomoyo_sb_umount(struct vfsmount *mnt, int flags) | ||
224 | { | ||
225 | struct path path = { mnt, mnt->mnt_root }; | ||
226 | return tomoyo_path_perm(TOMOYO_TYPE_UMOUNT, &path); | ||
227 | } | ||
228 | |||
229 | static int tomoyo_sb_pivotroot(struct path *old_path, struct path *new_path) | ||
230 | { | ||
231 | return tomoyo_path2_perm(TOMOYO_TYPE_PIVOT_ROOT, new_path, old_path); | ||
232 | } | ||
233 | |||
274 | /* | 234 | /* |
275 | * tomoyo_security_ops is a "struct security_operations" which is used for | 235 | * tomoyo_security_ops is a "struct security_operations" which is used for |
276 | * registering TOMOYO. | 236 | * registering TOMOYO. |
@@ -280,11 +240,9 @@ static struct security_operations tomoyo_security_ops = { | |||
280 | .cred_alloc_blank = tomoyo_cred_alloc_blank, | 240 | .cred_alloc_blank = tomoyo_cred_alloc_blank, |
281 | .cred_prepare = tomoyo_cred_prepare, | 241 | .cred_prepare = tomoyo_cred_prepare, |
282 | .cred_transfer = tomoyo_cred_transfer, | 242 | .cred_transfer = tomoyo_cred_transfer, |
243 | .cred_free = tomoyo_cred_free, | ||
283 | .bprm_set_creds = tomoyo_bprm_set_creds, | 244 | .bprm_set_creds = tomoyo_bprm_set_creds, |
284 | .bprm_check_security = tomoyo_bprm_check_security, | 245 | .bprm_check_security = tomoyo_bprm_check_security, |
285 | #ifdef CONFIG_SYSCTL | ||
286 | .sysctl = tomoyo_sysctl, | ||
287 | #endif | ||
288 | .file_fcntl = tomoyo_file_fcntl, | 246 | .file_fcntl = tomoyo_file_fcntl, |
289 | .dentry_open = tomoyo_dentry_open, | 247 | .dentry_open = tomoyo_dentry_open, |
290 | .path_truncate = tomoyo_path_truncate, | 248 | .path_truncate = tomoyo_path_truncate, |
@@ -295,8 +253,18 @@ static struct security_operations tomoyo_security_ops = { | |||
295 | .path_mknod = tomoyo_path_mknod, | 253 | .path_mknod = tomoyo_path_mknod, |
296 | .path_link = tomoyo_path_link, | 254 | .path_link = tomoyo_path_link, |
297 | .path_rename = tomoyo_path_rename, | 255 | .path_rename = tomoyo_path_rename, |
256 | .file_ioctl = tomoyo_file_ioctl, | ||
257 | .path_chmod = tomoyo_path_chmod, | ||
258 | .path_chown = tomoyo_path_chown, | ||
259 | .path_chroot = tomoyo_path_chroot, | ||
260 | .sb_mount = tomoyo_sb_mount, | ||
261 | .sb_umount = tomoyo_sb_umount, | ||
262 | .sb_pivotroot = tomoyo_sb_pivotroot, | ||
298 | }; | 263 | }; |
299 | 264 | ||
265 | /* Lock for GC. */ | ||
266 | struct srcu_struct tomoyo_ss; | ||
267 | |||
300 | static int __init tomoyo_init(void) | 268 | static int __init tomoyo_init(void) |
301 | { | 269 | { |
302 | struct cred *cred = (struct cred *) current_cred(); | 270 | struct cred *cred = (struct cred *) current_cred(); |
@@ -304,7 +272,8 @@ static int __init tomoyo_init(void) | |||
304 | if (!security_module_enable(&tomoyo_security_ops)) | 272 | if (!security_module_enable(&tomoyo_security_ops)) |
305 | return 0; | 273 | return 0; |
306 | /* register ourselves with the security framework */ | 274 | /* register ourselves with the security framework */ |
307 | if (register_security(&tomoyo_security_ops)) | 275 | if (register_security(&tomoyo_security_ops) || |
276 | init_srcu_struct(&tomoyo_ss)) | ||
308 | panic("Failure registering TOMOYO Linux"); | 277 | panic("Failure registering TOMOYO Linux"); |
309 | printk(KERN_INFO "TOMOYO Linux initialized\n"); | 278 | printk(KERN_INFO "TOMOYO Linux initialized\n"); |
310 | cred->security = &tomoyo_kernel_domain; | 279 | cred->security = &tomoyo_kernel_domain; |
diff --git a/security/tomoyo/tomoyo.h b/security/tomoyo/tomoyo.h deleted file mode 100644 index cd6ba0bf7069..000000000000 --- a/security/tomoyo/tomoyo.h +++ /dev/null | |||
@@ -1,96 +0,0 @@ | |||
1 | /* | ||
2 | * security/tomoyo/tomoyo.h | ||
3 | * | ||
4 | * Implementation of the Domain-Based Mandatory Access Control. | ||
5 | * | ||
6 | * Copyright (C) 2005-2009 NTT DATA CORPORATION | ||
7 | * | ||
8 | * Version: 2.2.0 2009/04/01 | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #ifndef _SECURITY_TOMOYO_TOMOYO_H | ||
13 | #define _SECURITY_TOMOYO_TOMOYO_H | ||
14 | |||
15 | struct tomoyo_path_info; | ||
16 | struct path; | ||
17 | struct inode; | ||
18 | struct linux_binprm; | ||
19 | struct pt_regs; | ||
20 | |||
21 | int tomoyo_check_file_perm(struct tomoyo_domain_info *domain, | ||
22 | const char *filename, const u8 perm); | ||
23 | int tomoyo_check_exec_perm(struct tomoyo_domain_info *domain, | ||
24 | const struct tomoyo_path_info *filename); | ||
25 | int tomoyo_check_open_permission(struct tomoyo_domain_info *domain, | ||
26 | struct path *path, const int flag); | ||
27 | int tomoyo_check_1path_perm(struct tomoyo_domain_info *domain, | ||
28 | const u8 operation, struct path *path); | ||
29 | int tomoyo_check_2path_perm(struct tomoyo_domain_info *domain, | ||
30 | const u8 operation, struct path *path1, | ||
31 | struct path *path2); | ||
32 | int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, | ||
33 | struct file *filp); | ||
34 | int tomoyo_find_next_domain(struct linux_binprm *bprm); | ||
35 | |||
36 | /* Index numbers for Access Controls. */ | ||
37 | |||
38 | #define TOMOYO_TYPE_SINGLE_PATH_ACL 0 | ||
39 | #define TOMOYO_TYPE_DOUBLE_PATH_ACL 1 | ||
40 | |||
41 | /* Index numbers for File Controls. */ | ||
42 | |||
43 | /* | ||
44 | * TYPE_READ_WRITE_ACL is special. TYPE_READ_WRITE_ACL is automatically set | ||
45 | * if both TYPE_READ_ACL and TYPE_WRITE_ACL are set. Both TYPE_READ_ACL and | ||
46 | * TYPE_WRITE_ACL are automatically set if TYPE_READ_WRITE_ACL is set. | ||
47 | * TYPE_READ_WRITE_ACL is automatically cleared if either TYPE_READ_ACL or | ||
48 | * TYPE_WRITE_ACL is cleared. Both TYPE_READ_ACL and TYPE_WRITE_ACL are | ||
49 | * automatically cleared if TYPE_READ_WRITE_ACL is cleared. | ||
50 | */ | ||
51 | |||
52 | #define TOMOYO_TYPE_READ_WRITE_ACL 0 | ||
53 | #define TOMOYO_TYPE_EXECUTE_ACL 1 | ||
54 | #define TOMOYO_TYPE_READ_ACL 2 | ||
55 | #define TOMOYO_TYPE_WRITE_ACL 3 | ||
56 | #define TOMOYO_TYPE_CREATE_ACL 4 | ||
57 | #define TOMOYO_TYPE_UNLINK_ACL 5 | ||
58 | #define TOMOYO_TYPE_MKDIR_ACL 6 | ||
59 | #define TOMOYO_TYPE_RMDIR_ACL 7 | ||
60 | #define TOMOYO_TYPE_MKFIFO_ACL 8 | ||
61 | #define TOMOYO_TYPE_MKSOCK_ACL 9 | ||
62 | #define TOMOYO_TYPE_MKBLOCK_ACL 10 | ||
63 | #define TOMOYO_TYPE_MKCHAR_ACL 11 | ||
64 | #define TOMOYO_TYPE_TRUNCATE_ACL 12 | ||
65 | #define TOMOYO_TYPE_SYMLINK_ACL 13 | ||
66 | #define TOMOYO_TYPE_REWRITE_ACL 14 | ||
67 | #define TOMOYO_MAX_SINGLE_PATH_OPERATION 15 | ||
68 | |||
69 | #define TOMOYO_TYPE_LINK_ACL 0 | ||
70 | #define TOMOYO_TYPE_RENAME_ACL 1 | ||
71 | #define TOMOYO_MAX_DOUBLE_PATH_OPERATION 2 | ||
72 | |||
73 | #define TOMOYO_DOMAINPOLICY 0 | ||
74 | #define TOMOYO_EXCEPTIONPOLICY 1 | ||
75 | #define TOMOYO_DOMAIN_STATUS 2 | ||
76 | #define TOMOYO_PROCESS_STATUS 3 | ||
77 | #define TOMOYO_MEMINFO 4 | ||
78 | #define TOMOYO_SELFDOMAIN 5 | ||
79 | #define TOMOYO_VERSION 6 | ||
80 | #define TOMOYO_PROFILE 7 | ||
81 | #define TOMOYO_MANAGER 8 | ||
82 | |||
83 | extern struct tomoyo_domain_info tomoyo_kernel_domain; | ||
84 | |||
85 | static inline struct tomoyo_domain_info *tomoyo_domain(void) | ||
86 | { | ||
87 | return current_cred()->security; | ||
88 | } | ||
89 | |||
90 | static inline struct tomoyo_domain_info *tomoyo_real_domain(struct task_struct | ||
91 | *task) | ||
92 | { | ||
93 | return task_cred_xxx(task, security); | ||
94 | } | ||
95 | |||
96 | #endif /* !defined(_SECURITY_TOMOYO_TOMOYO_H) */ | ||