aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorPeter Zijlstra <a.p.zijlstra@chello.nl>2007-07-19 04:48:15 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-19 13:04:45 -0400
commitbdf4c48af20a3b0f01671799ace345e3d49576da (patch)
tree7c3b903d2de1cba6e212ad6f347bc8742b08035a /kernel
parentb111757c50ee30dad162192df6168e270a90c252 (diff)
audit: rework execve audit
The purpose of audit_bprm() is to log the argv array to a userspace daemon at the end of the execve system call. Since user-space hasn't had time to run, this array is still in pristine state on the process' stack; so no need to copy it, we can just grab it from there. In order to minimize the damage to audit_log_*() copy each string into a temporary kernel buffer first. Currently the audit code requires that the full argument vector fits in a single packet. So currently it does clip the argv size to a (sysctl) limit, but only when execve auditing is enabled. If the audit protocol gets extended to allow for multiple packets this check can be removed. Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> Signed-off-by: Ollie Wild <aaw@google.com> Cc: <linux-audit@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/auditsc.c84
-rw-r--r--kernel/sysctl.c11
2 files changed, 74 insertions, 21 deletions
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index b7640a5f382a..535586fc498b 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -153,7 +153,7 @@ struct audit_aux_data_execve {
153 struct audit_aux_data d; 153 struct audit_aux_data d;
154 int argc; 154 int argc;
155 int envc; 155 int envc;
156 char mem[0]; 156 struct mm_struct *mm;
157}; 157};
158 158
159struct audit_aux_data_socketcall { 159struct audit_aux_data_socketcall {
@@ -831,6 +831,55 @@ static int audit_log_pid_context(struct audit_context *context, pid_t pid,
831 return rc; 831 return rc;
832} 832}
833 833
834static void audit_log_execve_info(struct audit_buffer *ab,
835 struct audit_aux_data_execve *axi)
836{
837 int i;
838 long len, ret;
839 const char __user *p = (const char __user *)axi->mm->arg_start;
840 char *buf;
841
842 if (axi->mm != current->mm)
843 return; /* execve failed, no additional info */
844
845 for (i = 0; i < axi->argc; i++, p += len) {
846 len = strnlen_user(p, MAX_ARG_PAGES*PAGE_SIZE);
847 /*
848 * We just created this mm, if we can't find the strings
849 * we just copied into it something is _very_ wrong. Similar
850 * for strings that are too long, we should not have created
851 * any.
852 */
853 if (!len || len > MAX_ARG_STRLEN) {
854 WARN_ON(1);
855 send_sig(SIGKILL, current, 0);
856 }
857
858 buf = kmalloc(len, GFP_KERNEL);
859 if (!buf) {
860 audit_panic("out of memory for argv string\n");
861 break;
862 }
863
864 ret = copy_from_user(buf, p, len);
865 /*
866 * There is no reason for this copy to be short. We just
867 * copied them here, and the mm hasn't been exposed to user-
868 * space yet.
869 */
870 if (!ret) {
871 WARN_ON(1);
872 send_sig(SIGKILL, current, 0);
873 }
874
875 audit_log_format(ab, "a%d=", i);
876 audit_log_untrustedstring(ab, buf);
877 audit_log_format(ab, "\n");
878
879 kfree(buf);
880 }
881}
882
834static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) 883static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
835{ 884{
836 int i, call_panic = 0; 885 int i, call_panic = 0;
@@ -971,13 +1020,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
971 1020
972 case AUDIT_EXECVE: { 1021 case AUDIT_EXECVE: {
973 struct audit_aux_data_execve *axi = (void *)aux; 1022 struct audit_aux_data_execve *axi = (void *)aux;
974 int i; 1023 audit_log_execve_info(ab, axi);
975 const char *p;
976 for (i = 0, p = axi->mem; i < axi->argc; i++) {
977 audit_log_format(ab, "a%d=", i);
978 p = audit_log_untrustedstring(ab, p);
979 audit_log_format(ab, "\n");
980 }
981 break; } 1024 break; }
982 1025
983 case AUDIT_SOCKETCALL: { 1026 case AUDIT_SOCKETCALL: {
@@ -1821,32 +1864,31 @@ int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode
1821 return 0; 1864 return 0;
1822} 1865}
1823 1866
1867int audit_argv_kb = 32;
1868
1824int audit_bprm(struct linux_binprm *bprm) 1869int audit_bprm(struct linux_binprm *bprm)
1825{ 1870{
1826 struct audit_aux_data_execve *ax; 1871 struct audit_aux_data_execve *ax;
1827 struct audit_context *context = current->audit_context; 1872 struct audit_context *context = current->audit_context;
1828 unsigned long p, next;
1829 void *to;
1830 1873
1831 if (likely(!audit_enabled || !context || context->dummy)) 1874 if (likely(!audit_enabled || !context || context->dummy))
1832 return 0; 1875 return 0;
1833 1876
1834 ax = kmalloc(sizeof(*ax) + PAGE_SIZE * MAX_ARG_PAGES - bprm->p, 1877 /*
1835 GFP_KERNEL); 1878 * Even though the stack code doesn't limit the arg+env size any more,
1879 * the audit code requires that _all_ arguments be logged in a single
1880 * netlink skb. Hence cap it :-(
1881 */
1882 if (bprm->argv_len > (audit_argv_kb << 10))
1883 return -E2BIG;
1884
1885 ax = kmalloc(sizeof(*ax), GFP_KERNEL);
1836 if (!ax) 1886 if (!ax)
1837 return -ENOMEM; 1887 return -ENOMEM;
1838 1888
1839 ax->argc = bprm->argc; 1889 ax->argc = bprm->argc;
1840 ax->envc = bprm->envc; 1890 ax->envc = bprm->envc;
1841 for (p = bprm->p, to = ax->mem; p < MAX_ARG_PAGES*PAGE_SIZE; p = next) { 1891 ax->mm = bprm->mm;
1842 struct page *page = bprm->page[p / PAGE_SIZE];
1843 void *kaddr = kmap(page);
1844 next = (p + PAGE_SIZE) & ~(PAGE_SIZE - 1);
1845 memcpy(to, kaddr + (p & (PAGE_SIZE - 1)), next - p);
1846 to += next - p;
1847 kunmap(page);
1848 }
1849
1850 ax->d.type = AUDIT_EXECVE; 1892 ax->d.type = AUDIT_EXECVE;
1851 ax->d.next = context->aux; 1893 ax->d.next = context->aux;
1852 context->aux = (void *)ax; 1894 context->aux = (void *)ax;
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 3ed4912bf183..8db41764e2a1 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -78,6 +78,7 @@ extern int percpu_pagelist_fraction;
78extern int compat_log; 78extern int compat_log;
79extern int maps_protect; 79extern int maps_protect;
80extern int sysctl_stat_interval; 80extern int sysctl_stat_interval;
81extern int audit_argv_kb;
81 82
82/* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */ 83/* this is needed for the proc_dointvec_minmax for [fs_]overflow UID and GID */
83static int maxolduid = 65535; 84static int maxolduid = 65535;
@@ -306,6 +307,16 @@ static ctl_table kern_table[] = {
306 .mode = 0644, 307 .mode = 0644,
307 .proc_handler = &proc_dointvec, 308 .proc_handler = &proc_dointvec,
308 }, 309 },
310#ifdef CONFIG_AUDITSYSCALL
311 {
312 .ctl_name = CTL_UNNUMBERED,
313 .procname = "audit_argv_kb",
314 .data = &audit_argv_kb,
315 .maxlen = sizeof(int),
316 .mode = 0644,
317 .proc_handler = &proc_dointvec,
318 },
319#endif
309 { 320 {
310 .ctl_name = KERN_CORE_PATTERN, 321 .ctl_name = KERN_CORE_PATTERN,
311 .procname = "core_pattern", 322 .procname = "core_pattern",