mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-22 01:57:43 +00:00
119 lines
3.4 KiB
Diff
119 lines
3.4 KiB
Diff
|
From 24b6ac149a57c2d3d5a9920e64d914e8ff00d346 Mon Sep 17 00:00:00 2001
|
||
|
From: Vegard Nossum <vegard.nossum@oracle.com>
|
||
|
Date: Thu, 7 Jul 2016 13:41:11 -0700
|
||
|
Subject: [PATCH 01/27] apparmor: fix oops, validate buffer size in
|
||
|
apparmor_setprocattr()
|
||
|
|
||
|
When proc_pid_attr_write() was changed to use memdup_user apparmor's
|
||
|
(interface violating) assumption that the setprocattr buffer was always
|
||
|
a single page was violated.
|
||
|
|
||
|
The size test is not strictly speaking needed as proc_pid_attr_write()
|
||
|
will reject anything larger, but for the sake of robustness we can keep
|
||
|
it in.
|
||
|
|
||
|
SMACK and SELinux look safe to me, but somebody else should probably
|
||
|
have a look just in case.
|
||
|
|
||
|
Based on original patch from Vegard Nossum <vegard.nossum@oracle.com>
|
||
|
modified for the case that apparmor provides null termination.
|
||
|
|
||
|
Fixes: bb646cdb12e75d82258c2f2e7746d5952d3e321a
|
||
|
Reported-by: Vegard Nossum <vegard.nossum@oracle.com>
|
||
|
Cc: Al Viro <viro@zeniv.linux.org.uk>
|
||
|
Cc: John Johansen <john.johansen@canonical.com>
|
||
|
Cc: Paul Moore <paul@paul-moore.com>
|
||
|
Cc: Stephen Smalley <sds@tycho.nsa.gov>
|
||
|
Cc: Eric Paris <eparis@parisplace.org>
|
||
|
Cc: Casey Schaufler <casey@schaufler-ca.com>
|
||
|
Cc: stable@kernel.org
|
||
|
Signed-off-by: John Johansen <john.johansen@canonical.com>
|
||
|
Reviewed-by: Tyler Hicks <tyhicks@canonical.com>
|
||
|
Signed-off-by: James Morris <james.l.morris@oracle.com>
|
||
|
---
|
||
|
security/apparmor/lsm.c | 36 +++++++++++++++++++-----------------
|
||
|
1 file changed, 19 insertions(+), 17 deletions(-)
|
||
|
|
||
|
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
|
||
|
index dec607c..5ee8201 100644
|
||
|
--- a/security/apparmor/lsm.c
|
||
|
+++ b/security/apparmor/lsm.c
|
||
|
@@ -523,34 +523,34 @@ static int apparmor_setprocattr(struct task_struct *task, char *name,
|
||
|
{
|
||
|
struct common_audit_data sa;
|
||
|
struct apparmor_audit_data aad = {0,};
|
||
|
- char *command, *args = value;
|
||
|
+ char *command, *largs = NULL, *args = value;
|
||
|
size_t arg_size;
|
||
|
int error;
|
||
|
|
||
|
if (size == 0)
|
||
|
return -EINVAL;
|
||
|
- /* args points to a PAGE_SIZE buffer, AppArmor requires that
|
||
|
- * the buffer must be null terminated or have size <= PAGE_SIZE -1
|
||
|
- * so that AppArmor can null terminate them
|
||
|
- */
|
||
|
- if (args[size - 1] != '\0') {
|
||
|
- if (size == PAGE_SIZE)
|
||
|
- return -EINVAL;
|
||
|
- args[size] = '\0';
|
||
|
- }
|
||
|
-
|
||
|
/* task can only write its own attributes */
|
||
|
if (current != task)
|
||
|
return -EACCES;
|
||
|
|
||
|
- args = value;
|
||
|
+ /* AppArmor requires that the buffer must be null terminated atm */
|
||
|
+ if (args[size - 1] != '\0') {
|
||
|
+ /* null terminate */
|
||
|
+ largs = args = kmalloc(size + 1, GFP_KERNEL);
|
||
|
+ if (!args)
|
||
|
+ return -ENOMEM;
|
||
|
+ memcpy(args, value, size);
|
||
|
+ args[size] = '\0';
|
||
|
+ }
|
||
|
+
|
||
|
+ error = -EINVAL;
|
||
|
args = strim(args);
|
||
|
command = strsep(&args, " ");
|
||
|
if (!args)
|
||
|
- return -EINVAL;
|
||
|
+ goto out;
|
||
|
args = skip_spaces(args);
|
||
|
if (!*args)
|
||
|
- return -EINVAL;
|
||
|
+ goto out;
|
||
|
|
||
|
arg_size = size - (args - (char *) value);
|
||
|
if (strcmp(name, "current") == 0) {
|
||
|
@@ -576,10 +576,12 @@ static int apparmor_setprocattr(struct task_struct *task, char *name,
|
||
|
goto fail;
|
||
|
} else
|
||
|
/* only support the "current" and "exec" process attributes */
|
||
|
- return -EINVAL;
|
||
|
+ goto fail;
|
||
|
|
||
|
if (!error)
|
||
|
error = size;
|
||
|
+out:
|
||
|
+ kfree(largs);
|
||
|
return error;
|
||
|
|
||
|
fail:
|
||
|
@@ -588,9 +590,9 @@ fail:
|
||
|
aad.profile = aa_current_profile();
|
||
|
aad.op = OP_SETPROCATTR;
|
||
|
aad.info = name;
|
||
|
- aad.error = -EINVAL;
|
||
|
+ aad.error = error = -EINVAL;
|
||
|
aa_audit_msg(AUDIT_APPARMOR_DENIED, &sa, NULL);
|
||
|
- return -EINVAL;
|
||
|
+ goto out;
|
||
|
}
|
||
|
|
||
|
static int apparmor_task_setrlimit(struct task_struct *task,
|
||
|
--
|
||
|
2.7.4
|
||
|
|