diff options
Diffstat (limited to 'security/apparmor/lsm.c')
-rw-r--r-- | security/apparmor/lsm.c | 36 |
1 files changed, 19 insertions, 17 deletions
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c index 2660fbcf94d1..7798e1608f4f 100644 --- a/security/apparmor/lsm.c +++ b/security/apparmor/lsm.c | |||
@@ -500,34 +500,34 @@ static int apparmor_setprocattr(struct task_struct *task, char *name, | |||
500 | { | 500 | { |
501 | struct common_audit_data sa; | 501 | struct common_audit_data sa; |
502 | struct apparmor_audit_data aad = {0,}; | 502 | struct apparmor_audit_data aad = {0,}; |
503 | char *command, *args = value; | 503 | char *command, *largs = NULL, *args = value; |
504 | size_t arg_size; | 504 | size_t arg_size; |
505 | int error; | 505 | int error; |
506 | 506 | ||
507 | if (size == 0) | 507 | if (size == 0) |
508 | return -EINVAL; | 508 | return -EINVAL; |
509 | /* args points to a PAGE_SIZE buffer, AppArmor requires that | ||
510 | * the buffer must be null terminated or have size <= PAGE_SIZE -1 | ||
511 | * so that AppArmor can null terminate them | ||
512 | */ | ||
513 | if (args[size - 1] != '\0') { | ||
514 | if (size == PAGE_SIZE) | ||
515 | return -EINVAL; | ||
516 | args[size] = '\0'; | ||
517 | } | ||
518 | |||
519 | /* task can only write its own attributes */ | 509 | /* task can only write its own attributes */ |
520 | if (current != task) | 510 | if (current != task) |
521 | return -EACCES; | 511 | return -EACCES; |
522 | 512 | ||
523 | args = value; | 513 | /* AppArmor requires that the buffer must be null terminated atm */ |
514 | if (args[size - 1] != '\0') { | ||
515 | /* null terminate */ | ||
516 | largs = args = kmalloc(size + 1, GFP_KERNEL); | ||
517 | if (!args) | ||
518 | return -ENOMEM; | ||
519 | memcpy(args, value, size); | ||
520 | args[size] = '\0'; | ||
521 | } | ||
522 | |||
523 | error = -EINVAL; | ||
524 | args = strim(args); | 524 | args = strim(args); |
525 | command = strsep(&args, " "); | 525 | command = strsep(&args, " "); |
526 | if (!args) | 526 | if (!args) |
527 | return -EINVAL; | 527 | goto out; |
528 | args = skip_spaces(args); | 528 | args = skip_spaces(args); |
529 | if (!*args) | 529 | if (!*args) |
530 | return -EINVAL; | 530 | goto out; |
531 | 531 | ||
532 | arg_size = size - (args - (char *) value); | 532 | arg_size = size - (args - (char *) value); |
533 | if (strcmp(name, "current") == 0) { | 533 | if (strcmp(name, "current") == 0) { |
@@ -553,10 +553,12 @@ static int apparmor_setprocattr(struct task_struct *task, char *name, | |||
553 | goto fail; | 553 | goto fail; |
554 | } else | 554 | } else |
555 | /* only support the "current" and "exec" process attributes */ | 555 | /* only support the "current" and "exec" process attributes */ |
556 | return -EINVAL; | 556 | goto fail; |
557 | 557 | ||
558 | if (!error) | 558 | if (!error) |
559 | error = size; | 559 | error = size; |
560 | out: | ||
561 | kfree(largs); | ||
560 | return error; | 562 | return error; |
561 | 563 | ||
562 | fail: | 564 | fail: |
@@ -565,9 +567,9 @@ fail: | |||
565 | aad.profile = aa_current_profile(); | 567 | aad.profile = aa_current_profile(); |
566 | aad.op = OP_SETPROCATTR; | 568 | aad.op = OP_SETPROCATTR; |
567 | aad.info = name; | 569 | aad.info = name; |
568 | aad.error = -EINVAL; | 570 | aad.error = error = -EINVAL; |
569 | aa_audit_msg(AUDIT_APPARMOR_DENIED, &sa, NULL); | 571 | aa_audit_msg(AUDIT_APPARMOR_DENIED, &sa, NULL); |
570 | return -EINVAL; | 572 | goto out; |
571 | } | 573 | } |
572 | 574 | ||
573 | static int apparmor_task_setrlimit(struct task_struct *task, | 575 | static int apparmor_task_setrlimit(struct task_struct *task, |