Skip to contentSkip to conversation

execve argument logging

PATCH In review Alexander Viro 3 participants 8 messages Apr 21, 2006 – Apr 22, 2006

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 execve argument logging

fs/exec.c +6 -0
@@ -49,6 +49,7 @@
 #include <linux/rmap.h>
 #include <linux/acct.h>
 #include <linux/cn_proc.h>
+#include <linux/audit.h>
 
 #include <asm/uaccess.h>
 #include <asm/mmu_context.h>
@@ -1085,6 +1086,11 @@ int search_binary_handler(struct linux_b
 	/* kernel module loader fixup */
 	/* so we don't try to load run modprobe in kernel space. */
 	set_fs(USER_DS);
+
+	retval = audit_bprm(bprm);
+	if (retval)
+		return retval;
+
 	retval = -ENOENT;
 	for (try=0; try<2; try++) {
 		read_lock(&binfmt_lock);
include/linux/audit.h +5 -1
@@ -83,6 +83,7 @@
 #define AUDIT_CONFIG_CHANGE	1305	/* Audit system configuration change */
 #define AUDIT_SOCKADDR		1306	/* sockaddr copied as syscall arg */
 #define AUDIT_CWD		1307	/* Current working directory */
+#define AUDIT_EXECVE		1309	/* execve arguments */
 #define AUDIT_IPC_SET_PERM	1311	/* IPC new permissions record type */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
@@ -283,6 +284,7 @@ struct audit_buffer;
 struct audit_context;
 struct inode;
 struct netlink_skb_parms;
+struct linux_binprm;
 
 #define AUDITSC_INVALID 0
 #define AUDITSC_SUCCESS 1
@@ -322,6 +324,7 @@ extern int  audit_set_loginuid(struct ta
 extern uid_t audit_get_loginuid(struct audit_context *ctx);
 extern int audit_ipc_obj(struct kern_ipc_perm *ipcp);
 extern int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode, struct kern_ipc_perm *ipcp);
+extern int audit_bprm(struct linux_binprm *bprm);
 extern int audit_socketcall(int nargs, unsigned long *args);
 extern int audit_sockaddr(int len, void *addr);
 extern int audit_avc_path(struct dentry *dentry, struct vfsmount *mnt);
@@ -342,6 +345,7 @@ extern int audit_set_macxattr(const char
 #define audit_get_loginuid(c) ({ -1; })
 #define audit_ipc_obj(i) ({ 0; })
 #define audit_ipc_set_perm(q,u,g,m,i) ({ 0; })
+#define audit_bprm(p) ({ 0; })
 #define audit_socketcall(n,a) ({ 0; })
 #define audit_sockaddr(len, addr) ({ 0; })
 #define audit_avc_path(dentry, mnt) ({ 0; })
@@ -364,7 +368,7 @@ extern void		    audit_log_end(struct au
 extern void		    audit_log_hex(struct audit_buffer *ab,
 					  const unsigned char *buf,
 					  size_t len);
-extern void		    audit_log_untrustedstring(struct audit_buffer *ab,
+extern const char *	    audit_log_untrustedstring(struct audit_buffer *ab,
 						      const char *string);
 extern void		    audit_log_d_path(struct audit_buffer *ab,
 					     const char *prefix,
kernel/audit.c +5 -3
@@ -998,18 +998,20 @@ void audit_log_hex(struct audit_buffer *
  * or a space. Unescaped strings will start and end with a double quote mark.
  * Strings that are escaped are printed in hex (2 digits per char).
  */
-void audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
+const char *audit_log_untrustedstring(struct audit_buffer *ab, const char *string)
 {
 	const unsigned char *p = string;
+	size_t len = strlen(string);
 
 	while (*p) {
 		if (*p == '"' || *p < 0x21 || *p > 0x7f) {
-			audit_log_hex(ab, string, strlen(string));
-			return;
+			audit_log_hex(ab, string, len);
+			return string + len + 1;
 		}
 		p++;
 	}
 	audit_log_format(ab, "\"%s\"", string);
+	return p + 1;
 }
 
 /* This is a helper-function to print the escaped d_path */
kernel/auditsc.c +51 -0

75 lines not on this page · raw message

#1 lore raw

Al,

Thanks for posting this.

Amy,

To give some background...we have this open bugzilla:
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=168285

It was agreed last summer that this would be useful for people. It has nothing to do with CAPP certification, so it was put on the back burner. No one had the time to complete it until now. What the patch does is collect the string arguments to execve and logs them as an auxiliary record. It was also put onto linux-audit mail list as a proposal, item #1 here:

https://www.redhat.com/archives/linux-audit/2005-September/msg00061.html

Hope this helps...

-Steve

#2 lore raw
Quoted 10 lines · Steve Grubb

To give some background...we have this open bugzilla:
https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=168285

It was agreed last summer that this would be useful for people. It has nothing to do with CAPP certification, so it was put on the back burner. No one had the time to complete it until now. What the patch does is collect the string arguments to execve and logs them as an auxiliary record. It was also put onto linux-audit mail list as a proposal, item #1 here:

https://www.redhat.com/archives/linux-audit/2005-September/msg00061.html

Does this allow an attacker to DoS the audit log by creating a fork/exec loop intentionally invoking a totally duff binary, but that includes a very long argument?

Maybe a "first 32/64 bytes of each argument" limit is needed? Or is there one there and I missed it?

#3 lore raw
Quoted 2 lines · On Fri, Apr 21, 2006 at 04:19:09PM -0400, [email protected] wrote:

Maybe a "first 32/64 bytes of each argument" limit is needed? Or is there one there and I missed it?

You do realize that it makes e.g. any pathname arguments in effect not logged at all - just slap 64 '/' in front of absolute pathname and you are done.

#4 lore raw
Quoted 7 lines · Alexander Viro
Quoted 2 lines · On Fri, Apr 21, 2006 at 04:19:09PM -0400, [email protected] wrote:

Maybe a "first 32/64 bytes of each argument" limit is needed? Or is there one there and I missed it?

You do realize that it makes e.g. any pathname arguments in effect not logged at all - just slap 64 '/' in front of absolute pathname and you are done.

On the other hand, the 2.6.17-rc1-mm3 kernel I'm on now has:

include/linux/limits.h:#define ARG_MAX 131072 /* # bytes of args + environ for exec() */

which implies to me that I can blat a bit over 128K to the audit log per syscall.

With the default Fedora-rawhide auditd.conf config of:

num_logs = 4
max_log_file = 5
max_log_file_action = ROTATE

I can roll through all the logs and *effectively* make the arguments of whatever I wanted to hide not visible with only 160 syscalls. 'man auditd.conf' says:

Space_left should be set to a number that gives the admin enough time to react to any alert message and perform some maintenance to free up disk space. This would typically involve running the aureport -t report and moving the oldest logs to an archive area. The value of space_left is site dependant since the rate at which events are generated varies with each deployment. The space_left_action is recommended to be set to email.

(And yes, I know if you're *serious* about this, you have action set to 'single' or 'halt' or similar "die rather than lose records" setting. The problem is that when you can blow through a megabyte of logspace with only 8 syscalls, finding a good setting for "gives enough time" becomes a lot more challenging...)

How would everybody feel about wrapping this in a CONFIG_AUDIT_ARGV, and some Kconfig wording warning about this burning through your audit space?

#5 lore raw
Quoted 2 lines · On Friday 21 April 2006 17:22, [email protected] wrote:

which implies to me that I can blat a bit over 128K to the audit log per syscall.

Users can do this already. Maybe not as quickly, but they can certainly fill up your logs if they feel like it. If you do not want this message type in your logs, then use this in your audit rules:

-a always,exclude -F msgtype=EXECVE

Problem Solved (tm).

-Steve

#6 lore raw
Quoted 3 lines · Steve Grubb

-a always,exclude -F msgtype=EXECVE

Problem Solved (tm).

Damn, I read the patch over like 3 times, and didn't twig into it using AUDIT_EXECVE (1309) - I managed to convince myself this was an expansion of the record cut for the execve under AUDIT_SYSCALL (1300).

<mode="Emily Litella">
Nevermind...
</mode>

:)

#7 lore raw
In reply to [email protected]
Quoted 3 lines · On Friday 21 April 2006 16:19, [email protected] wrote:

Does this allow an attacker to DoS the audit log by creating a fork/exec loop intentionally invoking a totally duff binary, but that includes a very long argument?

I personally haven't tried. Try it and let us know if you can DoS the machine.

Quoted 2 lines

Maybe a "first 32/64 bytes of each argument" limit is needed?  Or is there one there and I missed it?

There's no limit other than what the kernel imposes.

-Steve