Reporting file descriptors and exec args
Subsystems (5)
PATCH 1/1 Reporting file descriptors and exec args
Here is a version of the previous patch that was produced using the correct options to diff. This patch is by Jeremy Latt. In addition to adding reports of the file descriptors created by the pipe and socketpair system calls, it also adds reports of the string arguments to the system calls open and execve. Knowing the name of the file opened or exec'ed is also crucial to the analysis performed by Polgen.
John
fs/exec.c +3 -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>
@@ -1173,6 +1174,8 @@ int do_execve(char * filename,if ((retval = bprm->argc) <0 ) goto out_mm; +audit_execve (bprm->argc, argv); + bprm->envc =count (envp, bprm->p /sizeof (void *));if ((retval = bprm->envc) <0 ) goto out_mm;
fs/pipe.c +2 -0
@@ -15,6 +15,7 @@#include <linux/pipe_fs_i.h> #include <linux/uio.h> #include <linux/highmem.h> +#include <linux/audit.h> #include <asm/uaccess.h> #include <asm/ioctls.h>
@@ -781,6 +782,7 @@ int do_pipe(int *fd)fd_install (j, f2); fd[0 ] = i; fd[1 ] = j; +audit_fd_pair (i, j);return 0 ; close_f12_inode_i_j:
include/linux/audit.h +6 -0
@@ -68,6 +68,8 @@#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/* exec arguments */ +#define AUDIT_FD_PAIR 1312/* audit record for pipe/socketpair */ #define AUDIT_AVC 1400/* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401/* Internal SE Linux Errors */
@@ -238,6 +240,8 @@ extern int audit_sockaddr(int len, voidextern int audit_avc_path (struct dentry *dentry,struct vfsmount *mnt);extern void audit_signal_info (int sig,struct task_struct *t);extern int audit_filter_user (struct netlink_skb_parms *cb,int type); +extern int audit_execve (int argc,char __user *__user *argv); +extern int audit_fd_pair (int fd1,int fd2);#else #define audit_alloc (t) ({ 0; })#define audit_free (t) do { ; } while (0)
@@ -255,6 +259,8 @@ extern int audit_filter_user(struct netl#define audit_avc_path (dentry, mnt) ({ 0; })#define audit_signal_info (s,t) do { ; } while (0)#define audit_filter_user (cb,t) ({ 1; }) +#define audit_execve (a, b) ({ 0; }) +#define audit_fd_pair (a, b) ({ 0; })#endif #ifdef CONFIG_AUDIT
kernel/auditsc.c +148 -2
192 lines not on this page · raw message
net/socket.c +3 -1
@@ -1256,8 +1256,10 @@ asmlinkage long sys_socketpair(int famil err =put_user (fd1, &usockvec[0 ]);if (!err) err =put_user (fd2, &usockvec[1 ]); -if (!err) +if (!err) { +audit_fd_pair (fd1, fd2);return 0 ; + }sys_close (fd2);sys_close (fd1);
Quoted 5 lines · John D. Ramsdell
kernel/auditsc.c +5
-0+static const char *elide (const char *str) +{ +static char buf[1025 ]; + +if (strnlen (str,1025 ) >=1025 ) {
kernel/auditsc.c static void audit_log_task_info(struct a · line 835
Quoted 10 lines
kernel/auditsc.c +10
-0+memcpy (buf, str,1021 ); + buf[1021 ] ='.' ; + buf[1022 ] ='.' ; + buf[1023 ] ='.' ; + buf[1024 ] ='\0' ; +return buf; + } + +return str; +}
... serialized by...?
kernel/auditsc.c static void audit_log_exit(struct audit_ · line 859
Quoted 13 lines
static void
audit_log_exit(struct audit_context *context, gfp_t gfp_mask){kernel/auditsc.c +6
-0int i;@@ -820,6 +851,16 @@ static void audit_log_exit(struct audit_audit_log_format (ab," success=%s exit=%ld" , (context->return_valid==AUDITSC_SUCCESS )?"yes" :"no" , context->return_code); + +switch (context->major) { +case __NR_open: +audit_log_format (ab," filename=" ); +audit_log_untrustedstring (ab, +elide ((const char *)context->argv[0 ]));
Oh, lovely. So let me see if I've got it right - now anybody can trigger reading from any location in kernel memory. Including iomem. Or not mapped address range - less interesting (oops instead of mangling hardware), but easier to guess.
BTW, you still have problem with __NR_open on biarch targets...
Do we really want to start adding information to the audit records that isn't security relevant? There are alot of system calls that return data through pointer arguments. Would we stop with just these two?
For open and execve, does the PATH part of the audit record not give you what you need?
-- ljk
Quoted 301 lines · John D. Ramsdell
Here is a version of the previous patch that was produced using the correct options to diff. This patch is by Jeremy Latt. In addition to adding reports of the file descriptors created by the pipe and socketpair system calls, it also adds reports of the string arguments to the system calls open and execve. Knowing the name of the file opened or exec'ed is also crucial to the analysis performed by Polgen.
John
Signed-off-by John D. Ramsdell <[email protected]>diff -uprN -X 2.6.16/Documentation/dontdiff
2.6.16/fs/exec.clinux-2.6.16-jlatt/fs/exec.cfs/exec.c +3
-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> @@ -1173,6 +1174,8 @@ int do_execve(char * filename,if ((retval = bprm->argc) <0 ) goto out_mm; +audit_execve (bprm->argc, argv); + bprm->envc =count (envp, bprm->p /sizeof (void *));if ((retval = bprm->envc) <0 ) goto out_mm;diff -uprN -X 2.6.16/Documentation/dontdiff
2.6.16/fs/pipe.clinux-2.6.16-jlatt/fs/pipe.cfs/pipe.c +2
-0@@ -15,6 +15,7 @@#include <linux/pipe_fs_i.h> #include <linux/uio.h> #include <linux/highmem.h> +#include <linux/audit.h> #include <asm/uaccess.h> #include <asm/ioctls.h> @@ -781,6 +782,7 @@ int do_pipe(int *fd)fd_install (j, f2); fd[0 ] = i; fd[1 ] = j; +audit_fd_pair (i, j);return 0 ; close_f12_inode_i_j:diff -uprN -X 2.6.16/Documentation/dontdiff
2.6.16/include/linux/audit.hlinux-2.6.16-jlatt/include/linux/audit.hinclude/linux/audit.h +6
-0@@ -68,6 +68,8 @@#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/* exec arguments */ +#define AUDIT_FD_PAIR 1312/* audit record for pipe/socketpair */ #define AUDIT_AVC 1400/* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401/* Internal SE Linux Errors */ @@ -238,6 +240,8 @@ extern int audit_sockaddr(int len, voidextern int audit_avc_path (struct dentry *dentry,struct vfsmount *mnt);extern void audit_signal_info (int sig,struct task_struct *t);extern int audit_filter_user (struct netlink_skb_parms *cb,int type); +extern int audit_execve (int argc,char __user *__user *argv); +extern int audit_fd_pair (int fd1,int fd2);#else #define audit_alloc (t) ({ 0; })#define audit_free (t) do { ; } while (0)@@ -255,6 +259,8 @@ extern int audit_filter_user(struct netl#define audit_avc_path (dentry, mnt) ({ 0; })#define audit_signal_info (s,t) do { ; } while (0)#define audit_filter_user (cb,t) ({ 1; }) +#define audit_execve (a, b) ({ 0; }) +#define audit_fd_pair (a, b) ({ 0; })#endif #ifdef CONFIG_AUDIT diff -uprN -X 2.6.16/Documentation/dontdiff
2.6.16/kernel/auditsc.clinux-2.6.16-jlatt/kernel/auditsc.ckernel/auditsc.c +148
-2@@ -44,6 +44,10 @@#include <linux/compiler.h> #include <asm/unistd.h> +#include <linux/in.h> +#include <linux/socket.h> +#include <linux/binfmts.h> +/* 0 = no checking 1 = put_count checking 2 = verbose put_count checking @@ -129,6 +133,17 @@ struct audit_aux_data_sockaddr {char a[0 ]; }; +struct audit_aux_data_fd_pair { +struct audit_aux_data d; +int fd[2 ]; +}; + +struct audit_aux_data_execve { +struct audit_aux_data d; +int argc; +char args[0 ]; +}; +struct audit_aux_data_path {struct audit_aux_data d;struct dentry *dentry;@@ -598,7 +613,7 @@ static int audit_filter_user_rules(strucint audit_filter_user (struct netlink_skb_parms *cb,int type) {struct audit_entry *e; -enum audit_state state; +enum audit_state state =AUDIT_DISABLED ;int ret =1 ;rcu_read_lock ();@@ -803,6 +818,22 @@ static void audit_log_task_info(struct aup_read (&mm->mmap_sem); } +static const char *elide (const char *str) +{ +static char buf[1025 ]; + +if (strnlen (str,1025 ) >=1025 ) { +memcpy (buf, str,1021 ); + buf[1021 ] ='.' ; + buf[1022 ] ='.' ; + buf[1023 ] ='.' ; + buf[1024 ] ='\0' ; +return buf; + } + +return str; +} +static void audit_log_exit (struct audit_context *context,gfp_t gfp_mask) {int i;@@ -820,6 +851,16 @@ static void audit_log_exit(struct audit_audit_log_format (ab," success=%s exit=%ld" , (context->return_valid==AUDITSC_SUCCESS )?"yes" :"no" , context->return_code); + +switch (context->major) { +case __NR_open: +audit_log_format (ab," filename=" ); +audit_log_untrustedstring (ab, +elide ((const char *)context->argv[0 ])); +break ; + } + +audit_log_format (ab," a0=%lx a1=%lx a2=%lx a3=%lx items=%d" " pid=%d auid=%u uid=%u gid=%u"@@ -872,7 +913,21 @@ static void audit_log_exit(struct audit_struct audit_aux_data_path *axi = (void *)aux;audit_log_d_path (ab,"path=" , axi->dentry, axi->mnt);break ; } - +case AUDIT_EXECVE : { +int i, pos; +struct audit_aux_data_execve *axs = (void *)aux; +audit_log_format (ab,"argc=%d" , axs->argc); + pos =0 ; +for (i=0 ; i < axs->argc; i++) { +audit_log_format (ab," arg%d=" , i); +audit_log_untrustedstring (ab,elide (axs->args+pos)); + pos +=strlen (axs->args+pos)+1 ; + } +break ; } +case AUDIT_FD_PAIR : { +struct audit_aux_data_fd_pair *axs = (void *)aux; +audit_log_format (ab,"fd0=%d fd1=%d" , axs->fd[0 ], axs->fd[1 ]); +break ; } }audit_log_end (ab); }@@ -1237,6 +1292,97 @@ int audit_socketcall(int nargs, unsignedreturn 0 ; } +int audit_fd_pair (int fd1,int fd2) +{ +struct audit_context *context; +struct audit_aux_data_fd_pair *ax; + + context = current->audit_context; +if (likely (!context)) { +return 0 ; + } + + ax =kmalloc (sizeof (*ax),GFP_KERNEL ); +if (!ax) { +return -ENOMEM ; + } + + ax->fd[0 ] = fd1; + ax->fd[1 ] = fd2; + + ax->d.type =AUDIT_FD_PAIR ; + ax->d.next = context->aux; + context->aux = (void *)ax; +return 0 ; +} + +/* includes \0 at end, and just long enough to trigger elipsis */ +#define MAX_ARG_LENGTH 1026 + +int audit_execve (int argc,char __user *__user *argv) +{ +struct audit_aux_data_execve *ax; +int i; +int off; +int bytes_to_malloc; +struct audit_context *context; + + context = current->audit_context; +if (likely (!context)) { +return 0 ; + } + + bytes_to_malloc =sizeof (*ax); + +for (i =0 ; i < argc; i++) { +int len; + + len =strnlen_user (argv[i],MAX_ARG_LENGTH ); +if (!len) { +return -EFAULT ; + }else if (len >MAX_ARG_LENGTH ) { + len =MAX_ARG_LENGTH ; + } + bytes_to_malloc += len; + } + + ax =kmalloc (bytes_to_malloc,GFP_KERNEL ); +if (!ax) { +return -ENOMEM ; + } + + off =0 ; +for (i=0 ; i<argc; i++) { +int len; +char __user *arg; + +if (get_user (arg, argv+i)) { + goto err_out; + } + + len =strnlen_user (arg,MAX_ARG_LENGTH ); +if (!len) { + goto err_out; + }else if (len >MAX_ARG_LENGTH ) { + len =MAX_ARG_LENGTH ; + } +if (copy_from_user (ax->args+off, arg, len-1 )) { + goto err_out; + } + off += len; + ax->args[off-1 ] ='\0' ; + } + + ax->d.type =AUDIT_EXECVE ; + ax->d.next = context->aux; + ax->argc = argc; + context->aux = (void *)ax; +return 0 ; +err_out: +kfree (ax); +return -EFAULT ; +} +int audit_sockaddr (int len,void *a) {struct audit_aux_data_sockaddr *ax;diff -uprN -X 2.6.16/Documentation/dontdiff
2.6.16/net/socket.clinux-2.6.16-jlatt/net/socket.cnet/socket.c +3
-2@@ -1256,8 +1256,10 @@ asmlinkage long sys_socketpair(int famil err =put_user (fd1, &usockvec[0 ]);if (!err) err =put_user (fd2, &usockvec[1 ]); -if (!err) +if (!err) { +audit_fd_pair (fd1, fd2);return 0 ; + }sys_close (fd2);sys_close (fd1); --Linux-audit mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/linux-audit
I withdraw the previously submitted kernel patch. In addition to the errors already pointed out on this list, the patch was produced several months ago, and the kernel has changed since then. In addition, the audit records for execve and open in the latest kernel already includes the information of interest. From the perspective of polgen, all that is currently missing is the file descriptors created by the pipe and socketpair system calls, and we'll be back with just that patch once it's properly prepared.
I have been relying on others to create kernel patches, and neglected to familiarize myself with the accepted practice for submitting patches. I will ensure that future patches follow the rules.
John