aboutsummaryrefslogtreecommitdiffstats
path: root/security/apparmor/lsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/apparmor/lsm.c')
-rw-r--r--security/apparmor/lsm.c36
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;
560out:
561 kfree(largs);
560 return error; 562 return error;
561 563
562fail: 564fail:
@@ -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
573static int apparmor_task_setrlimit(struct task_struct *task, 575static int apparmor_task_setrlimit(struct task_struct *task,