diff options
author | Kees Cook <keescook@chromium.org> | 2012-04-16 14:56:45 -0400 |
---|---|---|
committer | James Morris <james.l.morris@oracle.com> | 2012-04-18 23:39:56 -0400 |
commit | 389da25f93eea8ff64181ae7e3e87da68acaef2e (patch) | |
tree | 09277860746b3372cbb49ea82868709cbae99ec3 /security | |
parent | 8156b451f37898d3c3652b4e988a4d62ae16eaac (diff) |
Yama: add additional ptrace scopes
This expands the available Yama ptrace restrictions to include two more
modes. Mode 2 requires CAP_SYS_PTRACE for PTRACE_ATTACH, and mode 3
completely disables PTRACE_ATTACH (and locks the sysctl).
Signed-off-by: Kees Cook <keescook@chromium.org>
Signed-off-by: James Morris <james.l.morris@oracle.com>
Diffstat (limited to 'security')
-rw-r--r-- | security/yama/yama_lsm.c | 62 |
1 files changed, 51 insertions, 11 deletions
diff --git a/security/yama/yama_lsm.c b/security/yama/yama_lsm.c index 573723843a04..afb04cbb6971 100644 --- a/security/yama/yama_lsm.c +++ b/security/yama/yama_lsm.c | |||
@@ -18,7 +18,12 @@ | |||
18 | #include <linux/prctl.h> | 18 | #include <linux/prctl.h> |
19 | #include <linux/ratelimit.h> | 19 | #include <linux/ratelimit.h> |
20 | 20 | ||
21 | static int ptrace_scope = 1; | 21 | #define YAMA_SCOPE_DISABLED 0 |
22 | #define YAMA_SCOPE_RELATIONAL 1 | ||
23 | #define YAMA_SCOPE_CAPABILITY 2 | ||
24 | #define YAMA_SCOPE_NO_ATTACH 3 | ||
25 | |||
26 | static int ptrace_scope = YAMA_SCOPE_RELATIONAL; | ||
22 | 27 | ||
23 | /* describe a ptrace relationship for potential exception */ | 28 | /* describe a ptrace relationship for potential exception */ |
24 | struct ptrace_relation { | 29 | struct ptrace_relation { |
@@ -251,17 +256,32 @@ static int yama_ptrace_access_check(struct task_struct *child, | |||
251 | return rc; | 256 | return rc; |
252 | 257 | ||
253 | /* require ptrace target be a child of ptracer on attach */ | 258 | /* require ptrace target be a child of ptracer on attach */ |
254 | if (mode == PTRACE_MODE_ATTACH && | 259 | if (mode == PTRACE_MODE_ATTACH) { |
255 | ptrace_scope && | 260 | switch (ptrace_scope) { |
256 | !task_is_descendant(current, child) && | 261 | case YAMA_SCOPE_DISABLED: |
257 | !ptracer_exception_found(current, child) && | 262 | /* No additional restrictions. */ |
258 | !capable(CAP_SYS_PTRACE)) | 263 | break; |
259 | rc = -EPERM; | 264 | case YAMA_SCOPE_RELATIONAL: |
265 | if (!task_is_descendant(current, child) && | ||
266 | !ptracer_exception_found(current, child) && | ||
267 | !capable(CAP_SYS_PTRACE)) | ||
268 | rc = -EPERM; | ||
269 | break; | ||
270 | case YAMA_SCOPE_CAPABILITY: | ||
271 | if (!capable(CAP_SYS_PTRACE)) | ||
272 | rc = -EPERM; | ||
273 | break; | ||
274 | case YAMA_SCOPE_NO_ATTACH: | ||
275 | default: | ||
276 | rc = -EPERM; | ||
277 | break; | ||
278 | } | ||
279 | } | ||
260 | 280 | ||
261 | if (rc) { | 281 | if (rc) { |
262 | char name[sizeof(current->comm)]; | 282 | char name[sizeof(current->comm)]; |
263 | printk_ratelimited(KERN_NOTICE "ptrace of non-child" | 283 | printk_ratelimited(KERN_NOTICE |
264 | " pid %d was attempted by: %s (pid %d)\n", | 284 | "ptrace of pid %d was attempted by: %s (pid %d)\n", |
265 | child->pid, | 285 | child->pid, |
266 | get_task_comm(name, current), | 286 | get_task_comm(name, current), |
267 | current->pid); | 287 | current->pid); |
@@ -279,8 +299,28 @@ static struct security_operations yama_ops = { | |||
279 | }; | 299 | }; |
280 | 300 | ||
281 | #ifdef CONFIG_SYSCTL | 301 | #ifdef CONFIG_SYSCTL |
302 | static int yama_dointvec_minmax(struct ctl_table *table, int write, | ||
303 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
304 | { | ||
305 | int rc; | ||
306 | |||
307 | if (write && !capable(CAP_SYS_PTRACE)) | ||
308 | return -EPERM; | ||
309 | |||
310 | rc = proc_dointvec_minmax(table, write, buffer, lenp, ppos); | ||
311 | if (rc) | ||
312 | return rc; | ||
313 | |||
314 | /* Lock the max value if it ever gets set. */ | ||
315 | if (write && *(int *)table->data == *(int *)table->extra2) | ||
316 | table->extra1 = table->extra2; | ||
317 | |||
318 | return rc; | ||
319 | } | ||
320 | |||
282 | static int zero; | 321 | static int zero; |
283 | static int one = 1; | 322 | static int one = 1; |
323 | static int max_scope = YAMA_SCOPE_NO_ATTACH; | ||
284 | 324 | ||
285 | struct ctl_path yama_sysctl_path[] = { | 325 | struct ctl_path yama_sysctl_path[] = { |
286 | { .procname = "kernel", }, | 326 | { .procname = "kernel", }, |
@@ -294,9 +334,9 @@ static struct ctl_table yama_sysctl_table[] = { | |||
294 | .data = &ptrace_scope, | 334 | .data = &ptrace_scope, |
295 | .maxlen = sizeof(int), | 335 | .maxlen = sizeof(int), |
296 | .mode = 0644, | 336 | .mode = 0644, |
297 | .proc_handler = proc_dointvec_minmax, | 337 | .proc_handler = yama_dointvec_minmax, |
298 | .extra1 = &zero, | 338 | .extra1 = &zero, |
299 | .extra2 = &one, | 339 | .extra2 = &max_scope, |
300 | }, | 340 | }, |
301 | { } | 341 | { } |
302 | }; | 342 | }; |