diff options
-rw-r--r-- | fs/proc/base.c | 23 | ||||
-rw-r--r-- | include/linux/security.h | 14 | ||||
-rw-r--r-- | kernel/ptrace.c | 2 | ||||
-rw-r--r-- | security/capability.c | 2 | ||||
-rw-r--r-- | security/commoncap.c | 4 | ||||
-rw-r--r-- | security/keys/proc.c | 4 | ||||
-rw-r--r-- | security/security.c | 4 | ||||
-rw-r--r-- | security/selinux/avc.c | 8 | ||||
-rw-r--r-- | security/selinux/hooks.c | 24 | ||||
-rw-r--r-- | security/selinux/include/avc.h | 6 | ||||
-rw-r--r-- | security/selinux/ss/services.c | 142 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 8 | ||||
-rw-r--r-- | security/tomoyo/common.c | 30 | ||||
-rw-r--r-- | security/tomoyo/common.h | 2 | ||||
-rw-r--r-- | security/tomoyo/domain.c | 42 | ||||
-rw-r--r-- | security/tomoyo/tomoyo.c | 10 | ||||
-rw-r--r-- | security/tomoyo/tomoyo.h | 3 |
17 files changed, 216 insertions, 112 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 3ce5ae9e3d2d..917f338a6739 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -237,20 +237,19 @@ struct mm_struct *mm_for_maps(struct task_struct *task) | |||
237 | struct mm_struct *mm = get_task_mm(task); | 237 | struct mm_struct *mm = get_task_mm(task); |
238 | if (!mm) | 238 | if (!mm) |
239 | return NULL; | 239 | return NULL; |
240 | if (mm != current->mm) { | ||
241 | /* | ||
242 | * task->mm can be changed before security check, | ||
243 | * in that case we must notice the change after. | ||
244 | */ | ||
245 | if (!ptrace_may_access(task, PTRACE_MODE_READ) || | ||
246 | mm != task->mm) { | ||
247 | mmput(mm); | ||
248 | return NULL; | ||
249 | } | ||
250 | } | ||
240 | down_read(&mm->mmap_sem); | 251 | down_read(&mm->mmap_sem); |
241 | task_lock(task); | ||
242 | if (task->mm != mm) | ||
243 | goto out; | ||
244 | if (task->mm != current->mm && | ||
245 | __ptrace_may_access(task, PTRACE_MODE_READ) < 0) | ||
246 | goto out; | ||
247 | task_unlock(task); | ||
248 | return mm; | 252 | return mm; |
249 | out: | ||
250 | task_unlock(task); | ||
251 | up_read(&mm->mmap_sem); | ||
252 | mmput(mm); | ||
253 | return NULL; | ||
254 | } | 253 | } |
255 | 254 | ||
256 | static int proc_pid_cmdline(struct task_struct *task, char * buffer) | 255 | static int proc_pid_cmdline(struct task_struct *task, char * buffer) |
diff --git a/include/linux/security.h b/include/linux/security.h index 5eff459b3833..145909165dbf 100644 --- a/include/linux/security.h +++ b/include/linux/security.h | |||
@@ -52,7 +52,7 @@ struct audit_krule; | |||
52 | extern int cap_capable(struct task_struct *tsk, const struct cred *cred, | 52 | extern int cap_capable(struct task_struct *tsk, const struct cred *cred, |
53 | int cap, int audit); | 53 | int cap, int audit); |
54 | extern int cap_settime(struct timespec *ts, struct timezone *tz); | 54 | extern int cap_settime(struct timespec *ts, struct timezone *tz); |
55 | extern int cap_ptrace_may_access(struct task_struct *child, unsigned int mode); | 55 | extern int cap_ptrace_access_check(struct task_struct *child, unsigned int mode); |
56 | extern int cap_ptrace_traceme(struct task_struct *parent); | 56 | extern int cap_ptrace_traceme(struct task_struct *parent); |
57 | extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); | 57 | extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); |
58 | extern int cap_capset(struct cred *new, const struct cred *old, | 58 | extern int cap_capset(struct cred *new, const struct cred *old, |
@@ -1209,7 +1209,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
1209 | * @alter contains the flag indicating whether changes are to be made. | 1209 | * @alter contains the flag indicating whether changes are to be made. |
1210 | * Return 0 if permission is granted. | 1210 | * Return 0 if permission is granted. |
1211 | * | 1211 | * |
1212 | * @ptrace_may_access: | 1212 | * @ptrace_access_check: |
1213 | * Check permission before allowing the current process to trace the | 1213 | * Check permission before allowing the current process to trace the |
1214 | * @child process. | 1214 | * @child process. |
1215 | * Security modules may also want to perform a process tracing check | 1215 | * Security modules may also want to perform a process tracing check |
@@ -1224,7 +1224,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
1224 | * Check that the @parent process has sufficient permission to trace the | 1224 | * Check that the @parent process has sufficient permission to trace the |
1225 | * current process before allowing the current process to present itself | 1225 | * current process before allowing the current process to present itself |
1226 | * to the @parent process for tracing. | 1226 | * to the @parent process for tracing. |
1227 | * The parent process will still have to undergo the ptrace_may_access | 1227 | * The parent process will still have to undergo the ptrace_access_check |
1228 | * checks before it is allowed to trace this one. | 1228 | * checks before it is allowed to trace this one. |
1229 | * @parent contains the task_struct structure for debugger process. | 1229 | * @parent contains the task_struct structure for debugger process. |
1230 | * Return 0 if permission is granted. | 1230 | * Return 0 if permission is granted. |
@@ -1336,7 +1336,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) | |||
1336 | struct security_operations { | 1336 | struct security_operations { |
1337 | char name[SECURITY_NAME_MAX + 1]; | 1337 | char name[SECURITY_NAME_MAX + 1]; |
1338 | 1338 | ||
1339 | int (*ptrace_may_access) (struct task_struct *child, unsigned int mode); | 1339 | int (*ptrace_access_check) (struct task_struct *child, unsigned int mode); |
1340 | int (*ptrace_traceme) (struct task_struct *parent); | 1340 | int (*ptrace_traceme) (struct task_struct *parent); |
1341 | int (*capget) (struct task_struct *target, | 1341 | int (*capget) (struct task_struct *target, |
1342 | kernel_cap_t *effective, | 1342 | kernel_cap_t *effective, |
@@ -1617,7 +1617,7 @@ extern int security_module_enable(struct security_operations *ops); | |||
1617 | extern int register_security(struct security_operations *ops); | 1617 | extern int register_security(struct security_operations *ops); |
1618 | 1618 | ||
1619 | /* Security operations */ | 1619 | /* Security operations */ |
1620 | int security_ptrace_may_access(struct task_struct *child, unsigned int mode); | 1620 | int security_ptrace_access_check(struct task_struct *child, unsigned int mode); |
1621 | int security_ptrace_traceme(struct task_struct *parent); | 1621 | int security_ptrace_traceme(struct task_struct *parent); |
1622 | int security_capget(struct task_struct *target, | 1622 | int security_capget(struct task_struct *target, |
1623 | kernel_cap_t *effective, | 1623 | kernel_cap_t *effective, |
@@ -1798,10 +1798,10 @@ static inline int security_init(void) | |||
1798 | return 0; | 1798 | return 0; |
1799 | } | 1799 | } |
1800 | 1800 | ||
1801 | static inline int security_ptrace_may_access(struct task_struct *child, | 1801 | static inline int security_ptrace_access_check(struct task_struct *child, |
1802 | unsigned int mode) | 1802 | unsigned int mode) |
1803 | { | 1803 | { |
1804 | return cap_ptrace_may_access(child, mode); | 1804 | return cap_ptrace_access_check(child, mode); |
1805 | } | 1805 | } |
1806 | 1806 | ||
1807 | static inline int security_ptrace_traceme(struct task_struct *parent) | 1807 | static inline int security_ptrace_traceme(struct task_struct *parent) |
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 61c78b2c07ba..9a4184e04f29 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -152,7 +152,7 @@ int __ptrace_may_access(struct task_struct *task, unsigned int mode) | |||
152 | if (!dumpable && !capable(CAP_SYS_PTRACE)) | 152 | if (!dumpable && !capable(CAP_SYS_PTRACE)) |
153 | return -EPERM; | 153 | return -EPERM; |
154 | 154 | ||
155 | return security_ptrace_may_access(task, mode); | 155 | return security_ptrace_access_check(task, mode); |
156 | } | 156 | } |
157 | 157 | ||
158 | bool ptrace_may_access(struct task_struct *task, unsigned int mode) | 158 | bool ptrace_may_access(struct task_struct *task, unsigned int mode) |
diff --git a/security/capability.c b/security/capability.c index 21b6cead6a8e..f218dd361647 100644 --- a/security/capability.c +++ b/security/capability.c | |||
@@ -863,7 +863,7 @@ struct security_operations default_security_ops = { | |||
863 | 863 | ||
864 | void security_fixup_ops(struct security_operations *ops) | 864 | void security_fixup_ops(struct security_operations *ops) |
865 | { | 865 | { |
866 | set_to_cap_if_null(ops, ptrace_may_access); | 866 | set_to_cap_if_null(ops, ptrace_access_check); |
867 | set_to_cap_if_null(ops, ptrace_traceme); | 867 | set_to_cap_if_null(ops, ptrace_traceme); |
868 | set_to_cap_if_null(ops, capget); | 868 | set_to_cap_if_null(ops, capget); |
869 | set_to_cap_if_null(ops, capset); | 869 | set_to_cap_if_null(ops, capset); |
diff --git a/security/commoncap.c b/security/commoncap.c index 48b7e0228fa3..aa97704564d4 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
@@ -101,7 +101,7 @@ int cap_settime(struct timespec *ts, struct timezone *tz) | |||
101 | } | 101 | } |
102 | 102 | ||
103 | /** | 103 | /** |
104 | * cap_ptrace_may_access - Determine whether the current process may access | 104 | * cap_ptrace_access_check - Determine whether the current process may access |
105 | * another | 105 | * another |
106 | * @child: The process to be accessed | 106 | * @child: The process to be accessed |
107 | * @mode: The mode of attachment. | 107 | * @mode: The mode of attachment. |
@@ -109,7 +109,7 @@ int cap_settime(struct timespec *ts, struct timezone *tz) | |||
109 | * Determine whether a process may access another, returning 0 if permission | 109 | * Determine whether a process may access another, returning 0 if permission |
110 | * granted, -ve if denied. | 110 | * granted, -ve if denied. |
111 | */ | 111 | */ |
112 | int cap_ptrace_may_access(struct task_struct *child, unsigned int mode) | 112 | int cap_ptrace_access_check(struct task_struct *child, unsigned int mode) |
113 | { | 113 | { |
114 | int ret = 0; | 114 | int ret = 0; |
115 | 115 | ||
diff --git a/security/keys/proc.c b/security/keys/proc.c index 769f9bdfd2b3..39793c774f33 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
@@ -120,6 +120,7 @@ static int proc_keys_open(struct inode *inode, struct file *file) | |||
120 | } | 120 | } |
121 | 121 | ||
122 | static void *proc_keys_start(struct seq_file *p, loff_t *_pos) | 122 | static void *proc_keys_start(struct seq_file *p, loff_t *_pos) |
123 | __acquires(key_serial_lock) | ||
123 | { | 124 | { |
124 | struct rb_node *_p; | 125 | struct rb_node *_p; |
125 | loff_t pos = *_pos; | 126 | loff_t pos = *_pos; |
@@ -144,6 +145,7 @@ static void *proc_keys_next(struct seq_file *p, void *v, loff_t *_pos) | |||
144 | } | 145 | } |
145 | 146 | ||
146 | static void proc_keys_stop(struct seq_file *p, void *v) | 147 | static void proc_keys_stop(struct seq_file *p, void *v) |
148 | __releases(key_serial_lock) | ||
147 | { | 149 | { |
148 | spin_unlock(&key_serial_lock); | 150 | spin_unlock(&key_serial_lock); |
149 | } | 151 | } |
@@ -257,6 +259,7 @@ static int proc_key_users_open(struct inode *inode, struct file *file) | |||
257 | } | 259 | } |
258 | 260 | ||
259 | static void *proc_key_users_start(struct seq_file *p, loff_t *_pos) | 261 | static void *proc_key_users_start(struct seq_file *p, loff_t *_pos) |
262 | __acquires(key_user_lock) | ||
260 | { | 263 | { |
261 | struct rb_node *_p; | 264 | struct rb_node *_p; |
262 | loff_t pos = *_pos; | 265 | loff_t pos = *_pos; |
@@ -281,6 +284,7 @@ static void *proc_key_users_next(struct seq_file *p, void *v, loff_t *_pos) | |||
281 | } | 284 | } |
282 | 285 | ||
283 | static void proc_key_users_stop(struct seq_file *p, void *v) | 286 | static void proc_key_users_stop(struct seq_file *p, void *v) |
287 | __releases(key_user_lock) | ||
284 | { | 288 | { |
285 | spin_unlock(&key_user_lock); | 289 | spin_unlock(&key_user_lock); |
286 | } | 290 | } |
diff --git a/security/security.c b/security/security.c index dc7674fbfc7a..4501c5e1f988 100644 --- a/security/security.c +++ b/security/security.c | |||
@@ -124,9 +124,9 @@ int register_security(struct security_operations *ops) | |||
124 | 124 | ||
125 | /* Security operations */ | 125 | /* Security operations */ |
126 | 126 | ||
127 | int security_ptrace_may_access(struct task_struct *child, unsigned int mode) | 127 | int security_ptrace_access_check(struct task_struct *child, unsigned int mode) |
128 | { | 128 | { |
129 | return security_ops->ptrace_may_access(child, mode); | 129 | return security_ops->ptrace_access_check(child, mode); |
130 | } | 130 | } |
131 | 131 | ||
132 | int security_ptrace_traceme(struct task_struct *parent) | 132 | int security_ptrace_traceme(struct task_struct *parent) |
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index b2ab60859832..236aaa2ea86d 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -137,7 +137,7 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass) | |||
137 | * @tclass: target security class | 137 | * @tclass: target security class |
138 | * @av: access vector | 138 | * @av: access vector |
139 | */ | 139 | */ |
140 | void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) | 140 | static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av) |
141 | { | 141 | { |
142 | const char **common_pts = NULL; | 142 | const char **common_pts = NULL; |
143 | u32 common_base = 0; | 143 | u32 common_base = 0; |
@@ -970,3 +970,9 @@ u32 avc_policy_seqno(void) | |||
970 | { | 970 | { |
971 | return avc_cache.latest_notif; | 971 | return avc_cache.latest_notif; |
972 | } | 972 | } |
973 | |||
974 | void avc_disable(void) | ||
975 | { | ||
976 | if (avc_node_cachep) | ||
977 | kmem_cache_destroy(avc_node_cachep); | ||
978 | } | ||
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 15c2a08a66f1..2081055f6783 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -1854,12 +1854,12 @@ static inline u32 open_file_to_av(struct file *file) | |||
1854 | 1854 | ||
1855 | /* Hook functions begin here. */ | 1855 | /* Hook functions begin here. */ |
1856 | 1856 | ||
1857 | static int selinux_ptrace_may_access(struct task_struct *child, | 1857 | static int selinux_ptrace_access_check(struct task_struct *child, |
1858 | unsigned int mode) | 1858 | unsigned int mode) |
1859 | { | 1859 | { |
1860 | int rc; | 1860 | int rc; |
1861 | 1861 | ||
1862 | rc = cap_ptrace_may_access(child, mode); | 1862 | rc = cap_ptrace_access_check(child, mode); |
1863 | if (rc) | 1863 | if (rc) |
1864 | return rc; | 1864 | return rc; |
1865 | 1865 | ||
@@ -2938,11 +2938,6 @@ static int selinux_revalidate_file_permission(struct file *file, int mask) | |||
2938 | const struct cred *cred = current_cred(); | 2938 | const struct cred *cred = current_cred(); |
2939 | struct inode *inode = file->f_path.dentry->d_inode; | 2939 | struct inode *inode = file->f_path.dentry->d_inode; |
2940 | 2940 | ||
2941 | if (!mask) { | ||
2942 | /* No permission to check. Existence test. */ | ||
2943 | return 0; | ||
2944 | } | ||
2945 | |||
2946 | /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */ | 2941 | /* file_mask_to_av won't add FILE__WRITE if MAY_APPEND is set */ |
2947 | if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) | 2942 | if ((file->f_flags & O_APPEND) && (mask & MAY_WRITE)) |
2948 | mask |= MAY_APPEND; | 2943 | mask |= MAY_APPEND; |
@@ -2953,10 +2948,20 @@ static int selinux_revalidate_file_permission(struct file *file, int mask) | |||
2953 | 2948 | ||
2954 | static int selinux_file_permission(struct file *file, int mask) | 2949 | static int selinux_file_permission(struct file *file, int mask) |
2955 | { | 2950 | { |
2951 | struct inode *inode = file->f_path.dentry->d_inode; | ||
2952 | struct file_security_struct *fsec = file->f_security; | ||
2953 | struct inode_security_struct *isec = inode->i_security; | ||
2954 | u32 sid = current_sid(); | ||
2955 | |||
2956 | if (!mask) | 2956 | if (!mask) |
2957 | /* No permission to check. Existence test. */ | 2957 | /* No permission to check. Existence test. */ |
2958 | return 0; | 2958 | return 0; |
2959 | 2959 | ||
2960 | if (sid == fsec->sid && fsec->isid == isec->sid && | ||
2961 | fsec->pseqno == avc_policy_seqno()) | ||
2962 | /* No change since dentry_open check. */ | ||
2963 | return 0; | ||
2964 | |||
2960 | return selinux_revalidate_file_permission(file, mask); | 2965 | return selinux_revalidate_file_permission(file, mask); |
2961 | } | 2966 | } |
2962 | 2967 | ||
@@ -5310,7 +5315,7 @@ static int selinux_key_getsecurity(struct key *key, char **_buffer) | |||
5310 | static struct security_operations selinux_ops = { | 5315 | static struct security_operations selinux_ops = { |
5311 | .name = "selinux", | 5316 | .name = "selinux", |
5312 | 5317 | ||
5313 | .ptrace_may_access = selinux_ptrace_may_access, | 5318 | .ptrace_access_check = selinux_ptrace_access_check, |
5314 | .ptrace_traceme = selinux_ptrace_traceme, | 5319 | .ptrace_traceme = selinux_ptrace_traceme, |
5315 | .capget = selinux_capget, | 5320 | .capget = selinux_capget, |
5316 | .capset = selinux_capset, | 5321 | .capset = selinux_capset, |
@@ -5678,6 +5683,9 @@ int selinux_disable(void) | |||
5678 | selinux_disabled = 1; | 5683 | selinux_disabled = 1; |
5679 | selinux_enabled = 0; | 5684 | selinux_enabled = 0; |
5680 | 5685 | ||
5686 | /* Try to destroy the avc node cache */ | ||
5687 | avc_disable(); | ||
5688 | |||
5681 | /* Reset security_ops to the secondary module, dummy or capability. */ | 5689 | /* Reset security_ops to the secondary module, dummy or capability. */ |
5682 | security_ops = secondary_ops; | 5690 | security_ops = secondary_ops; |
5683 | 5691 | ||
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index d12ff1a9c0aa..ae4c3a0e2c1a 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h | |||
@@ -127,13 +127,13 @@ int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid, | |||
127 | u32 events, u32 ssid, u32 tsid, | 127 | u32 events, u32 ssid, u32 tsid, |
128 | u16 tclass, u32 perms); | 128 | u16 tclass, u32 perms); |
129 | 129 | ||
130 | /* Shows permission in human readable form */ | ||
131 | void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av); | ||
132 | |||
133 | /* Exported to selinuxfs */ | 130 | /* Exported to selinuxfs */ |
134 | int avc_get_hash_stats(char *page); | 131 | int avc_get_hash_stats(char *page); |
135 | extern unsigned int avc_cache_threshold; | 132 | extern unsigned int avc_cache_threshold; |
136 | 133 | ||
134 | /* Attempt to free avc node cache */ | ||
135 | void avc_disable(void); | ||
136 | |||
137 | #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS | 137 | #ifdef CONFIG_SECURITY_SELINUX_AVC_STATS |
138 | DECLARE_PER_CPU(struct avc_cache_stats, avc_cache_stats); | 138 | DECLARE_PER_CPU(struct avc_cache_stats, avc_cache_stats); |
139 | #endif | 139 | #endif |
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 500e6f78e115..ff17820d35ec 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -22,6 +22,11 @@ | |||
22 | * | 22 | * |
23 | * Added validation of kernel classes and permissions | 23 | * Added validation of kernel classes and permissions |
24 | * | 24 | * |
25 | * Updated: KaiGai Kohei <kaigai@ak.jp.nec.com> | ||
26 | * | ||
27 | * Added support for bounds domain and audit messaged on masked permissions | ||
28 | * | ||
29 | * Copyright (C) 2008, 2009 NEC Corporation | ||
25 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. | 30 | * Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P. |
26 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. | 31 | * Copyright (C) 2004-2006 Trusted Computer Solutions, Inc. |
27 | * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC | 32 | * Copyright (C) 2003 - 2004, 2006 Tresys Technology, LLC |
@@ -279,6 +284,95 @@ mls_ops: | |||
279 | } | 284 | } |
280 | 285 | ||
281 | /* | 286 | /* |
287 | * security_dump_masked_av - dumps masked permissions during | ||
288 | * security_compute_av due to RBAC, MLS/Constraint and Type bounds. | ||
289 | */ | ||
290 | static int dump_masked_av_helper(void *k, void *d, void *args) | ||
291 | { | ||
292 | struct perm_datum *pdatum = d; | ||
293 | char **permission_names = args; | ||
294 | |||
295 | BUG_ON(pdatum->value < 1 || pdatum->value > 32); | ||
296 | |||
297 | permission_names[pdatum->value - 1] = (char *)k; | ||
298 | |||
299 | return 0; | ||
300 | } | ||
301 | |||
302 | static void security_dump_masked_av(struct context *scontext, | ||
303 | struct context *tcontext, | ||
304 | u16 tclass, | ||
305 | u32 permissions, | ||
306 | const char *reason) | ||
307 | { | ||
308 | struct common_datum *common_dat; | ||
309 | struct class_datum *tclass_dat; | ||
310 | struct audit_buffer *ab; | ||
311 | char *tclass_name; | ||
312 | char *scontext_name = NULL; | ||
313 | char *tcontext_name = NULL; | ||
314 | char *permission_names[32]; | ||
315 | int index, length; | ||
316 | bool need_comma = false; | ||
317 | |||
318 | if (!permissions) | ||
319 | return; | ||
320 | |||
321 | tclass_name = policydb.p_class_val_to_name[tclass - 1]; | ||
322 | tclass_dat = policydb.class_val_to_struct[tclass - 1]; | ||
323 | common_dat = tclass_dat->comdatum; | ||
324 | |||
325 | /* init permission_names */ | ||
326 | if (common_dat && | ||
327 | hashtab_map(common_dat->permissions.table, | ||
328 | dump_masked_av_helper, permission_names) < 0) | ||
329 | goto out; | ||
330 | |||
331 | if (hashtab_map(tclass_dat->permissions.table, | ||
332 | dump_masked_av_helper, permission_names) < 0) | ||
333 | goto out; | ||
334 | |||
335 | /* get scontext/tcontext in text form */ | ||
336 | if (context_struct_to_string(scontext, | ||
337 | &scontext_name, &length) < 0) | ||
338 | goto out; | ||
339 | |||
340 | if (context_struct_to_string(tcontext, | ||
341 | &tcontext_name, &length) < 0) | ||
342 | goto out; | ||
343 | |||
344 | /* audit a message */ | ||
345 | ab = audit_log_start(current->audit_context, | ||
346 | GFP_ATOMIC, AUDIT_SELINUX_ERR); | ||
347 | if (!ab) | ||
348 | goto out; | ||
349 | |||
350 | audit_log_format(ab, "op=security_compute_av reason=%s " | ||
351 | "scontext=%s tcontext=%s tclass=%s perms=", | ||
352 | reason, scontext_name, tcontext_name, tclass_name); | ||
353 | |||
354 | for (index = 0; index < 32; index++) { | ||
355 | u32 mask = (1 << index); | ||
356 | |||
357 | if ((mask & permissions) == 0) | ||
358 | continue; | ||
359 | |||
360 | audit_log_format(ab, "%s%s", | ||
361 | need_comma ? "," : "", | ||
362 | permission_names[index] | ||
363 | ? permission_names[index] : "????"); | ||
364 | need_comma = true; | ||
365 | } | ||
366 | audit_log_end(ab); | ||
367 | out: | ||
368 | /* release scontext/tcontext */ | ||
369 | kfree(tcontext_name); | ||
370 | kfree(scontext_name); | ||
371 | |||
372 | return; | ||
373 | } | ||
374 | |||
375 | /* | ||
282 | * security_boundary_permission - drops violated permissions | 376 | * security_boundary_permission - drops violated permissions |
283 | * on boundary constraint. | 377 | * on boundary constraint. |
284 | */ | 378 | */ |
@@ -347,28 +441,12 @@ static void type_attribute_bounds_av(struct context *scontext, | |||
347 | } | 441 | } |
348 | 442 | ||
349 | if (masked) { | 443 | if (masked) { |
350 | struct audit_buffer *ab; | ||
351 | char *stype_name | ||
352 | = policydb.p_type_val_to_name[source->value - 1]; | ||
353 | char *ttype_name | ||
354 | = policydb.p_type_val_to_name[target->value - 1]; | ||
355 | char *tclass_name | ||
356 | = policydb.p_class_val_to_name[tclass - 1]; | ||
357 | |||
358 | /* mask violated permissions */ | 444 | /* mask violated permissions */ |
359 | avd->allowed &= ~masked; | 445 | avd->allowed &= ~masked; |
360 | 446 | ||
361 | /* notice to userspace via audit message */ | 447 | /* audit masked permissions */ |
362 | ab = audit_log_start(current->audit_context, | 448 | security_dump_masked_av(scontext, tcontext, |
363 | GFP_ATOMIC, AUDIT_SELINUX_ERR); | 449 | tclass, masked, "bounds"); |
364 | if (!ab) | ||
365 | return; | ||
366 | |||
367 | audit_log_format(ab, "av boundary violation: " | ||
368 | "source=%s target=%s tclass=%s", | ||
369 | stype_name, ttype_name, tclass_name); | ||
370 | avc_dump_av(ab, tclass, masked); | ||
371 | audit_log_end(ab); | ||
372 | } | 450 | } |
373 | } | 451 | } |
374 | 452 | ||
@@ -480,7 +558,7 @@ static int context_struct_compute_av(struct context *scontext, | |||
480 | if ((constraint->permissions & (avd->allowed)) && | 558 | if ((constraint->permissions & (avd->allowed)) && |
481 | !constraint_expr_eval(scontext, tcontext, NULL, | 559 | !constraint_expr_eval(scontext, tcontext, NULL, |
482 | constraint->expr)) { | 560 | constraint->expr)) { |
483 | avd->allowed = (avd->allowed) & ~(constraint->permissions); | 561 | avd->allowed &= ~(constraint->permissions); |
484 | } | 562 | } |
485 | constraint = constraint->next; | 563 | constraint = constraint->next; |
486 | } | 564 | } |
@@ -499,8 +577,8 @@ static int context_struct_compute_av(struct context *scontext, | |||
499 | break; | 577 | break; |
500 | } | 578 | } |
501 | if (!ra) | 579 | if (!ra) |
502 | avd->allowed = (avd->allowed) & ~(PROCESS__TRANSITION | | 580 | avd->allowed &= ~(PROCESS__TRANSITION | |
503 | PROCESS__DYNTRANSITION); | 581 | PROCESS__DYNTRANSITION); |
504 | } | 582 | } |
505 | 583 | ||
506 | /* | 584 | /* |
@@ -687,6 +765,26 @@ int security_bounded_transition(u32 old_sid, u32 new_sid) | |||
687 | } | 765 | } |
688 | index = type->bounds; | 766 | index = type->bounds; |
689 | } | 767 | } |
768 | |||
769 | if (rc) { | ||
770 | char *old_name = NULL; | ||
771 | char *new_name = NULL; | ||
772 | int length; | ||
773 | |||
774 | if (!context_struct_to_string(old_context, | ||
775 | &old_name, &length) && | ||
776 | !context_struct_to_string(new_context, | ||
777 | &new_name, &length)) { | ||
778 | audit_log(current->audit_context, | ||
779 | GFP_ATOMIC, AUDIT_SELINUX_ERR, | ||
780 | "op=security_bounded_transition " | ||
781 | "result=denied " | ||
782 | "oldcontext=%s newcontext=%s", | ||
783 | old_name, new_name); | ||
784 | } | ||
785 | kfree(new_name); | ||
786 | kfree(old_name); | ||
787 | } | ||
690 | out: | 788 | out: |
691 | read_unlock(&policy_rwlock); | 789 | read_unlock(&policy_rwlock); |
692 | 790 | ||
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 0023182078c7..1c9bdbcbe3d2 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -91,7 +91,7 @@ struct inode_smack *new_inode_smack(char *smack) | |||
91 | */ | 91 | */ |
92 | 92 | ||
93 | /** | 93 | /** |
94 | * smack_ptrace_may_access - Smack approval on PTRACE_ATTACH | 94 | * smack_ptrace_access_check - Smack approval on PTRACE_ATTACH |
95 | * @ctp: child task pointer | 95 | * @ctp: child task pointer |
96 | * @mode: ptrace attachment mode | 96 | * @mode: ptrace attachment mode |
97 | * | 97 | * |
@@ -99,13 +99,13 @@ struct inode_smack *new_inode_smack(char *smack) | |||
99 | * | 99 | * |
100 | * Do the capability checks, and require read and write. | 100 | * Do the capability checks, and require read and write. |
101 | */ | 101 | */ |
102 | static int smack_ptrace_may_access(struct task_struct *ctp, unsigned int mode) | 102 | static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) |
103 | { | 103 | { |
104 | int rc; | 104 | int rc; |
105 | struct smk_audit_info ad; | 105 | struct smk_audit_info ad; |
106 | char *sp, *tsp; | 106 | char *sp, *tsp; |
107 | 107 | ||
108 | rc = cap_ptrace_may_access(ctp, mode); | 108 | rc = cap_ptrace_access_check(ctp, mode); |
109 | if (rc != 0) | 109 | if (rc != 0) |
110 | return rc; | 110 | return rc; |
111 | 111 | ||
@@ -3032,7 +3032,7 @@ static void smack_release_secctx(char *secdata, u32 seclen) | |||
3032 | struct security_operations smack_ops = { | 3032 | struct security_operations smack_ops = { |
3033 | .name = "smack", | 3033 | .name = "smack", |
3034 | 3034 | ||
3035 | .ptrace_may_access = smack_ptrace_may_access, | 3035 | .ptrace_access_check = smack_ptrace_access_check, |
3036 | .ptrace_traceme = smack_ptrace_traceme, | 3036 | .ptrace_traceme = smack_ptrace_traceme, |
3037 | .syslog = smack_syslog, | 3037 | .syslog = smack_syslog, |
3038 | 3038 | ||
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index fdd1f4b8c448..3c8bd8ee0b95 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -1285,6 +1285,36 @@ static bool tomoyo_is_select_one(struct tomoyo_io_buffer *head, | |||
1285 | } | 1285 | } |
1286 | 1286 | ||
1287 | /** | 1287 | /** |
1288 | * tomoyo_delete_domain - Delete a domain. | ||
1289 | * | ||
1290 | * @domainname: The name of domain. | ||
1291 | * | ||
1292 | * Returns 0. | ||
1293 | */ | ||
1294 | static int tomoyo_delete_domain(char *domainname) | ||
1295 | { | ||
1296 | struct tomoyo_domain_info *domain; | ||
1297 | struct tomoyo_path_info name; | ||
1298 | |||
1299 | name.name = domainname; | ||
1300 | tomoyo_fill_path_info(&name); | ||
1301 | down_write(&tomoyo_domain_list_lock); | ||
1302 | /* Is there an active domain? */ | ||
1303 | list_for_each_entry(domain, &tomoyo_domain_list, list) { | ||
1304 | /* Never delete tomoyo_kernel_domain */ | ||
1305 | if (domain == &tomoyo_kernel_domain) | ||
1306 | continue; | ||
1307 | if (domain->is_deleted || | ||
1308 | tomoyo_pathcmp(domain->domainname, &name)) | ||
1309 | continue; | ||
1310 | domain->is_deleted = true; | ||
1311 | break; | ||
1312 | } | ||
1313 | up_write(&tomoyo_domain_list_lock); | ||
1314 | return 0; | ||
1315 | } | ||
1316 | |||
1317 | /** | ||
1288 | * tomoyo_write_domain_policy - Write domain policy. | 1318 | * tomoyo_write_domain_policy - Write domain policy. |
1289 | * | 1319 | * |
1290 | * @head: Pointer to "struct tomoyo_io_buffer". | 1320 | * @head: Pointer to "struct tomoyo_io_buffer". |
diff --git a/security/tomoyo/common.h b/security/tomoyo/common.h index 6d6ba09af457..31df541911f7 100644 --- a/security/tomoyo/common.h +++ b/security/tomoyo/common.h | |||
@@ -339,8 +339,6 @@ const char *tomoyo_get_last_name(const struct tomoyo_domain_info *domain); | |||
339 | const char *tomoyo_get_msg(const bool is_enforce); | 339 | const char *tomoyo_get_msg(const bool is_enforce); |
340 | /* Convert single path operation to operation name. */ | 340 | /* Convert single path operation to operation name. */ |
341 | const char *tomoyo_sp2keyword(const u8 operation); | 341 | const char *tomoyo_sp2keyword(const u8 operation); |
342 | /* Delete a domain. */ | ||
343 | int tomoyo_delete_domain(char *data); | ||
344 | /* Create "alias" entry in exception policy. */ | 342 | /* Create "alias" entry in exception policy. */ |
345 | int tomoyo_write_alias_policy(char *data, const bool is_delete); | 343 | int tomoyo_write_alias_policy(char *data, const bool is_delete); |
346 | /* | 344 | /* |
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c index 1d8b16960576..fcf52accce2b 100644 --- a/security/tomoyo/domain.c +++ b/security/tomoyo/domain.c | |||
@@ -717,38 +717,6 @@ int tomoyo_write_alias_policy(char *data, const bool is_delete) | |||
717 | return tomoyo_update_alias_entry(data, cp, is_delete); | 717 | return tomoyo_update_alias_entry(data, cp, is_delete); |
718 | } | 718 | } |
719 | 719 | ||
720 | /* Domain create/delete handler. */ | ||
721 | |||
722 | /** | ||
723 | * tomoyo_delete_domain - Delete a domain. | ||
724 | * | ||
725 | * @domainname: The name of domain. | ||
726 | * | ||
727 | * Returns 0. | ||
728 | */ | ||
729 | int tomoyo_delete_domain(char *domainname) | ||
730 | { | ||
731 | struct tomoyo_domain_info *domain; | ||
732 | struct tomoyo_path_info name; | ||
733 | |||
734 | name.name = domainname; | ||
735 | tomoyo_fill_path_info(&name); | ||
736 | down_write(&tomoyo_domain_list_lock); | ||
737 | /* Is there an active domain? */ | ||
738 | list_for_each_entry(domain, &tomoyo_domain_list, list) { | ||
739 | /* Never delete tomoyo_kernel_domain */ | ||
740 | if (domain == &tomoyo_kernel_domain) | ||
741 | continue; | ||
742 | if (domain->is_deleted || | ||
743 | tomoyo_pathcmp(domain->domainname, &name)) | ||
744 | continue; | ||
745 | domain->is_deleted = true; | ||
746 | break; | ||
747 | } | ||
748 | up_write(&tomoyo_domain_list_lock); | ||
749 | return 0; | ||
750 | } | ||
751 | |||
752 | /** | 720 | /** |
753 | * tomoyo_find_or_assign_new_domain - Create a domain. | 721 | * tomoyo_find_or_assign_new_domain - Create a domain. |
754 | * | 722 | * |
@@ -818,13 +786,11 @@ struct tomoyo_domain_info *tomoyo_find_or_assign_new_domain(const char * | |||
818 | /** | 786 | /** |
819 | * tomoyo_find_next_domain - Find a domain. | 787 | * tomoyo_find_next_domain - Find a domain. |
820 | * | 788 | * |
821 | * @bprm: Pointer to "struct linux_binprm". | 789 | * @bprm: Pointer to "struct linux_binprm". |
822 | * @next_domain: Pointer to pointer to "struct tomoyo_domain_info". | ||
823 | * | 790 | * |
824 | * Returns 0 on success, negative value otherwise. | 791 | * Returns 0 on success, negative value otherwise. |
825 | */ | 792 | */ |
826 | int tomoyo_find_next_domain(struct linux_binprm *bprm, | 793 | int tomoyo_find_next_domain(struct linux_binprm *bprm) |
827 | struct tomoyo_domain_info **next_domain) | ||
828 | { | 794 | { |
829 | /* | 795 | /* |
830 | * This function assumes that the size of buffer returned by | 796 | * This function assumes that the size of buffer returned by |
@@ -946,9 +912,11 @@ int tomoyo_find_next_domain(struct linux_binprm *bprm, | |||
946 | tomoyo_set_domain_flag(old_domain, false, | 912 | tomoyo_set_domain_flag(old_domain, false, |
947 | TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED); | 913 | TOMOYO_DOMAIN_FLAGS_TRANSITION_FAILED); |
948 | out: | 914 | out: |
915 | if (!domain) | ||
916 | domain = old_domain; | ||
917 | bprm->cred->security = domain; | ||
949 | tomoyo_free(real_program_name); | 918 | tomoyo_free(real_program_name); |
950 | tomoyo_free(symlink_program_name); | 919 | tomoyo_free(symlink_program_name); |
951 | *next_domain = domain ? domain : old_domain; | ||
952 | tomoyo_free(tmp); | 920 | tomoyo_free(tmp); |
953 | return retval; | 921 | return retval; |
954 | } | 922 | } |
diff --git a/security/tomoyo/tomoyo.c b/security/tomoyo/tomoyo.c index 3194d09fe0f4..35a13e7915e4 100644 --- a/security/tomoyo/tomoyo.c +++ b/security/tomoyo/tomoyo.c | |||
@@ -61,14 +61,8 @@ static int tomoyo_bprm_check_security(struct linux_binprm *bprm) | |||
61 | * Execute permission is checked against pathname passed to do_execve() | 61 | * Execute permission is checked against pathname passed to do_execve() |
62 | * using current domain. | 62 | * using current domain. |
63 | */ | 63 | */ |
64 | if (!domain) { | 64 | if (!domain) |
65 | struct tomoyo_domain_info *next_domain = NULL; | 65 | return tomoyo_find_next_domain(bprm); |
66 | int retval = tomoyo_find_next_domain(bprm, &next_domain); | ||
67 | |||
68 | if (!retval) | ||
69 | bprm->cred->security = next_domain; | ||
70 | return retval; | ||
71 | } | ||
72 | /* | 66 | /* |
73 | * Read permission is checked against interpreters using next domain. | 67 | * Read permission is checked against interpreters using next domain. |
74 | * '1' is the result of open_to_namei_flags(O_RDONLY). | 68 | * '1' is the result of open_to_namei_flags(O_RDONLY). |
diff --git a/security/tomoyo/tomoyo.h b/security/tomoyo/tomoyo.h index 0fd588a629cf..cd6ba0bf7069 100644 --- a/security/tomoyo/tomoyo.h +++ b/security/tomoyo/tomoyo.h | |||
@@ -31,8 +31,7 @@ int tomoyo_check_2path_perm(struct tomoyo_domain_info *domain, | |||
31 | struct path *path2); | 31 | struct path *path2); |
32 | int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, | 32 | int tomoyo_check_rewrite_permission(struct tomoyo_domain_info *domain, |
33 | struct file *filp); | 33 | struct file *filp); |
34 | int tomoyo_find_next_domain(struct linux_binprm *bprm, | 34 | int tomoyo_find_next_domain(struct linux_binprm *bprm); |
35 | struct tomoyo_domain_info **next_domain); | ||
36 | 35 | ||
37 | /* Index numbers for Access Controls. */ | 36 | /* Index numbers for Access Controls. */ |
38 | 37 | ||