diff -N -u -r kernel-source-2.4.25/Documentation/Configure.help kernel-source-2.4.25-snare/Documentation/Configure.help --- kernel-source-2.4.25/Documentation/Configure.help 2004-02-22 04:27:55.000000000 -0500 +++ kernel-source-2.4.25-snare/Documentation/Configure.help 2004-07-20 16:27:35.000000000 -0400 @@ -4564,6 +4564,15 @@ up to the user level program to do useful things with this information. This is generally a good idea, so say Y. +C2-Style Auditing +CONFIG_C2_AUDIT + If you say Y here, a user level program (SNARE) will be able to + receive system audit events from the kernel. Many government + departments, and organisations that have significant security + requirements, will want to turn this feature on. Most normal + users will not be interested in reviewing audit reports though, + and should answer N here. + Sysctl support CONFIG_SYSCTL The sysctl interface provides a means of dynamically changing diff -N -u -r kernel-source-2.4.25/Makefile kernel-source-2.4.25-snare/Makefile --- kernel-source-2.4.25/Makefile 2004-03-30 05:40:33.000000000 -0500 +++ kernel-source-2.4.25-snare/Makefile 2004-07-20 16:27:35.000000000 -0400 @@ -133,7 +133,8 @@ NETWORKS =net/network.o LIBS =$(TOPDIR)/lib/lib.a -SUBDIRS =kernel drivers mm fs net ipc lib crypto +AUDIT =audit/audit.o +SUBDIRS =kernel drivers mm fs net ipc lib crypto audit DRIVERS-n := DRIVERS-y := @@ -276,7 +277,7 @@ export CPPFLAGS CFLAGS CFLAGS_KERNEL AFLAGS AFLAGS_KERNEL -export NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS +export NETWORKS DRIVERS LIBS HEAD LDFLAGS LINKFLAGS MAKEBOOT ASFLAGS AUDIT .S.s: $(CPP) $(AFLAGS) $(AFLAGS_KERNEL) -traditional -o $*.s $< @@ -295,6 +296,7 @@ $(CORE_FILES) \ $(DRIVERS) \ $(NETWORKS) \ + $(AUDIT) \ $(LIBS) \ --end-group \ -o vmlinux diff -N -u -r kernel-source-2.4.25/README-Snare kernel-source-2.4.25-snare/README-Snare --- kernel-source-2.4.25/README-Snare 1969-12-31 19:00:00.000000000 -0500 +++ kernel-source-2.4.25-snare/README-Snare 2004-07-20 16:27:35.000000000 -0400 @@ -0,0 +1,3 @@ +The files currently in this CVS tree are replacements for Kernel +version 2.4.20-24.9. + diff -N -u -r kernel-source-2.4.25/arch/alpha/config.in kernel-source-2.4.25-snare/arch/alpha/config.in --- kernel-source-2.4.25/arch/alpha/config.in 2004-02-22 04:27:59.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/alpha/config.in 2004-07-20 16:27:35.000000000 -0400 @@ -299,6 +299,7 @@ bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT +bool 'SNARE C2 Auditing' CONFIG_C2_AUDIT bool 'Sysctl support' CONFIG_SYSCTL if [ "$CONFIG_PROC_FS" = "y" ]; then choice 'Kernel core (/proc/kcore) format' \ diff -N -u -r kernel-source-2.4.25/arch/alpha/defconfig kernel-source-2.4.25-snare/arch/alpha/defconfig --- kernel-source-2.4.25/arch/alpha/defconfig 2004-02-22 03:46:35.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/alpha/defconfig 2004-07-20 16:27:35.000000000 -0400 @@ -77,6 +77,7 @@ CONFIG_NET=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_C2_AUDIT is not set CONFIG_SYSCTL=y CONFIG_KCORE_ELF=y # CONFIG_KCORE_AOUT is not set diff -N -u -r kernel-source-2.4.25/arch/arm/config.in kernel-source-2.4.25-snare/arch/arm/config.in --- kernel-source-2.4.25/arch/arm/config.in 2004-02-20 22:46:58.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/arm/config.in 2004-07-20 16:27:35.000000000 -0400 @@ -485,6 +485,7 @@ bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT +bool 'SNARE C2 Auditing' CONFIG_C2_AUDIT bool 'Sysctl support' CONFIG_SYSCTL comment 'At least one math emulation must be selected' tristate 'NWFPE math emulation' CONFIG_FPE_NWFPE diff -N -u -r kernel-source-2.4.25/arch/arm/defconfig kernel-source-2.4.25-snare/arch/arm/defconfig --- kernel-source-2.4.25/arch/arm/defconfig 2004-02-22 03:46:35.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/arm/defconfig 2004-07-20 16:27:35.000000000 -0400 @@ -89,6 +89,7 @@ CONFIG_NET=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_C2_AUDIT is not set CONFIG_SYSCTL=y CONFIG_NWFPE=y CONFIG_KCORE_ELF=y diff -N -u -r kernel-source-2.4.25/arch/cris/config.in kernel-source-2.4.25-snare/arch/cris/config.in --- kernel-source-2.4.25/arch/cris/config.in 2004-02-20 22:46:58.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/cris/config.in 2004-07-20 16:27:35.000000000 -0400 @@ -28,6 +28,7 @@ bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT +bool 'SNARE C2 Auditing' CONFIG_C2_AUDIT bool 'Sysctl support' CONFIG_SYSCTL tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF diff -N -u -r kernel-source-2.4.25/arch/cris/defconfig kernel-source-2.4.25-snare/arch/cris/defconfig --- kernel-source-2.4.25/arch/cris/defconfig 2004-02-22 03:46:35.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/cris/defconfig 2004-07-20 16:27:35.000000000 -0400 @@ -16,6 +16,7 @@ CONFIG_NET=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_C2_AUDIT is not set # CONFIG_SYSCTL is not set CONFIG_BINFMT_ELF=y # CONFIG_ETRAX_KGDB is not set diff -N -u -r kernel-source-2.4.25/arch/i386/config.in kernel-source-2.4.25-snare/arch/i386/config.in --- kernel-source-2.4.25/arch/i386/config.in 2004-02-22 04:28:00.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/i386/config.in 2004-07-20 16:27:35.000000000 -0400 @@ -323,6 +323,7 @@ bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT +bool 'SNARE C2 Auditing' CONFIG_C2_AUDIT bool 'Sysctl support' CONFIG_SYSCTL if [ "$CONFIG_PROC_FS" = "y" ]; then choice 'Kernel core (/proc/kcore) format' \ diff -N -u -r kernel-source-2.4.25/arch/i386/defconfig kernel-source-2.4.25-snare/arch/i386/defconfig --- kernel-source-2.4.25/arch/i386/defconfig 2004-02-22 03:46:35.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/i386/defconfig 2004-07-20 16:27:35.000000000 -0400 @@ -113,6 +113,7 @@ # CONFIG_HOTPLUG_PCI_ACPI is not set CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_C2_AUDIT is not set CONFIG_SYSCTL=y CONFIG_KCORE_ELF=y # CONFIG_KCORE_AOUT is not set diff -N -u -r kernel-source-2.4.25/arch/ia64/config.in kernel-source-2.4.25-snare/arch/ia64/config.in --- kernel-source-2.4.25/arch/ia64/config.in 2004-02-20 22:46:58.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/ia64/config.in 2004-07-20 16:27:35.000000000 -0400 @@ -122,6 +122,7 @@ bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT +bool 'SNARE C2 Auditing' CONFIG_C2_AUDIT bool 'Sysctl support' CONFIG_SYSCTL tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC diff -N -u -r kernel-source-2.4.25/arch/ia64/defconfig kernel-source-2.4.25-snare/arch/ia64/defconfig --- kernel-source-2.4.25/arch/ia64/defconfig 2004-02-22 03:46:35.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/ia64/defconfig 2004-07-20 16:27:35.000000000 -0400 @@ -68,6 +68,7 @@ CONFIG_NET=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_C2_AUDIT is not set CONFIG_SYSCTL=y CONFIG_BINFMT_ELF=y # CONFIG_BINFMT_MISC is not set diff -N -u -r kernel-source-2.4.25/arch/m68k/config.in kernel-source-2.4.25-snare/arch/m68k/config.in --- kernel-source-2.4.25/arch/m68k/config.in 2004-02-20 22:46:58.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/m68k/config.in 2004-07-20 16:27:35.000000000 -0400 @@ -91,6 +91,7 @@ bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT +bool 'SNARE C2 Auditing' CONFIG_C2_AUDIT bool 'Sysctl support' CONFIG_SYSCTL if [ "$CONFIG_PROC_FS" = "y" ]; then choice 'Kernel core (/proc/kcore) format' \ diff -N -u -r kernel-source-2.4.25/arch/m68k/defconfig kernel-source-2.4.25-snare/arch/m68k/defconfig --- kernel-source-2.4.25/arch/m68k/defconfig 2004-02-22 03:46:35.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/m68k/defconfig 2004-07-20 16:27:35.000000000 -0400 @@ -51,6 +51,7 @@ CONFIG_NET=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_C2_AUDIT is not set CONFIG_SYSCTL=y CONFIG_KCORE_ELF=y # CONFIG_KCORE_AOUT is not set diff -N -u -r kernel-source-2.4.25/arch/mips/defconfig kernel-source-2.4.25-snare/arch/mips/defconfig --- kernel-source-2.4.25/arch/mips/defconfig 2004-02-22 03:46:35.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/mips/defconfig 2004-07-20 16:27:35.000000000 -0400 @@ -144,6 +144,7 @@ # CONFIG_HOTPLUG_PCI is not set CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_C2_AUDIT is not set CONFIG_SYSCTL=y CONFIG_KCORE_ELF=y # CONFIG_KCORE_AOUT is not set diff -N -u -r kernel-source-2.4.25/arch/mips64/defconfig kernel-source-2.4.25-snare/arch/mips64/defconfig --- kernel-source-2.4.25/arch/mips64/defconfig 2004-02-22 03:46:35.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/mips64/defconfig 2004-07-20 16:27:35.000000000 -0400 @@ -142,6 +142,7 @@ # CONFIG_HOTPLUG_PCI is not set CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_C2_AUDIT is not set CONFIG_SYSCTL=y CONFIG_KCORE_ELF=y # CONFIG_KCORE_AOUT is not set diff -N -u -r kernel-source-2.4.25/arch/parisc/config.in kernel-source-2.4.25-snare/arch/parisc/config.in --- kernel-source-2.4.25/arch/parisc/config.in 2004-02-20 22:46:59.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/parisc/config.in 2004-07-20 16:27:35.000000000 -0400 @@ -86,6 +86,7 @@ bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT +bool 'SNARE C2 Auditing' CONFIG_C2_AUDIT bool 'Sysctl support' CONFIG_SYSCTL define_bool CONFIG_KCORE_ELF y tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF diff -N -u -r kernel-source-2.4.25/arch/parisc/defconfig kernel-source-2.4.25-snare/arch/parisc/defconfig --- kernel-source-2.4.25/arch/parisc/defconfig 2004-02-22 03:46:35.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/parisc/defconfig 2004-07-20 16:27:35.000000000 -0400 @@ -53,6 +53,7 @@ CONFIG_NET=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_C2_AUDIT is not set CONFIG_SYSCTL=y CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y diff -N -u -r kernel-source-2.4.25/arch/ppc/config.in kernel-source-2.4.25-snare/arch/ppc/config.in --- kernel-source-2.4.25/arch/ppc/config.in 2004-02-20 22:47:00.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/ppc/config.in 2004-07-20 16:27:35.000000000 -0400 @@ -344,6 +344,7 @@ bool 'Sysctl support' CONFIG_SYSCTL bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT +bool 'SNARE C2 Auditing' CONFIG_C2_AUDIT # only elf supported, a.out is not -- Cort if [ "$CONFIG_PROC_FS" = "y" ]; then diff -N -u -r kernel-source-2.4.25/arch/ppc/defconfig kernel-source-2.4.25-snare/arch/ppc/defconfig --- kernel-source-2.4.25/arch/ppc/defconfig 2004-02-22 03:46:35.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/ppc/defconfig 2004-07-20 16:27:35.000000000 -0400 @@ -66,6 +66,7 @@ CONFIG_SYSCTL=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_C2_AUDIT is not set CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y CONFIG_KERNEL_ELF=y diff -N -u -r kernel-source-2.4.25/arch/ppc64/config.in kernel-source-2.4.25-snare/arch/ppc64/config.in --- kernel-source-2.4.25/arch/ppc64/config.in 2004-02-20 22:47:00.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/ppc64/config.in 2004-07-20 16:27:35.000000000 -0400 @@ -75,6 +75,7 @@ bool 'Sysctl support' CONFIG_SYSCTL bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT +bool 'SNARE C2 Auditing' CONFIG_C2_AUDIT # only elf supported, a.out is not -- Cort if [ "$CONFIG_PROC_FS" = "y" ]; then diff -N -u -r kernel-source-2.4.25/arch/ppc64/defconfig kernel-source-2.4.25-snare/arch/ppc64/defconfig --- kernel-source-2.4.25/arch/ppc64/defconfig 2004-02-22 03:46:35.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/ppc64/defconfig 2004-07-20 16:27:35.000000000 -0400 @@ -64,6 +64,7 @@ CONFIG_SYSCTL=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_C2_AUDIT is not set CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y CONFIG_BINFMT_ELF32=y diff -N -u -r kernel-source-2.4.25/arch/s390/config.in kernel-source-2.4.25-snare/arch/s390/config.in --- kernel-source-2.4.25/arch/s390/config.in 2003-11-28 13:26:19.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/s390/config.in 2004-07-20 16:27:35.000000000 -0400 @@ -55,6 +55,7 @@ bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT +bool 'SNARE C2 Auditing' CONFIG_C2_AUDIT bool 'Sysctl support' CONFIG_SYSCTL define_bool CONFIG_KCORE_ELF y tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF diff -N -u -r kernel-source-2.4.25/arch/s390/defconfig kernel-source-2.4.25-snare/arch/s390/defconfig --- kernel-source-2.4.25/arch/s390/defconfig 2004-02-22 03:46:35.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/s390/defconfig 2004-07-20 16:27:35.000000000 -0400 @@ -53,6 +53,7 @@ CONFIG_NET=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_C2_AUDIT is not set CONFIG_SYSCTL=y CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y diff -N -u -r kernel-source-2.4.25/arch/s390x/config.in kernel-source-2.4.25-snare/arch/s390x/config.in --- kernel-source-2.4.25/arch/s390x/config.in 2003-11-28 13:26:19.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/s390x/config.in 2004-07-20 16:27:35.000000000 -0400 @@ -58,6 +58,7 @@ bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT +bool 'SNARE C2 Auditing' CONFIG_C2_AUDIT bool 'Sysctl support' CONFIG_SYSCTL define_bool CONFIG_KCORE_ELF y tristate 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF diff -N -u -r kernel-source-2.4.25/arch/s390x/defconfig kernel-source-2.4.25-snare/arch/s390x/defconfig --- kernel-source-2.4.25/arch/s390x/defconfig 2004-02-22 03:46:35.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/s390x/defconfig 2004-07-20 16:27:35.000000000 -0400 @@ -54,6 +54,7 @@ CONFIG_NET=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_C2_AUDIT is not set CONFIG_SYSCTL=y CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y diff -N -u -r kernel-source-2.4.25/arch/sh/config.in kernel-source-2.4.25-snare/arch/sh/config.in --- kernel-source-2.4.25/arch/sh/config.in 2004-02-20 22:47:00.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/sh/config.in 2004-07-20 16:27:35.000000000 -0400 @@ -276,6 +276,7 @@ bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT +bool 'SNARE C2 Auditing' CONFIG_C2_AUDIT bool 'Sysctl support' CONFIG_SYSCTL if [ "$CONFIG_PROC_FS" = "y" ]; then choice 'Kernel core (/proc/kcore) format' \ diff -N -u -r kernel-source-2.4.25/arch/sh/defconfig kernel-source-2.4.25-snare/arch/sh/defconfig --- kernel-source-2.4.25/arch/sh/defconfig 2004-02-20 22:47:00.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/sh/defconfig 2004-07-20 16:27:35.000000000 -0400 @@ -44,6 +44,7 @@ # CONFIG_PCMCIA is not set # CONFIG_SYSVIPC is not set # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_C2_AUDIT is not set # CONFIG_SYSCTL is not set CONFIG_KCORE_ELF=y # CONFIG_KCORE_AOUT is not set diff -N -u -r kernel-source-2.4.25/arch/sparc/config.in kernel-source-2.4.25-snare/arch/sparc/config.in --- kernel-source-2.4.25/arch/sparc/config.in 2004-02-20 22:47:00.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/sparc/config.in 2004-07-20 16:27:35.000000000 -0400 @@ -68,6 +68,7 @@ bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT +bool 'SNARE C2 Auditing' CONFIG_C2_AUDIT bool 'Sysctl support' CONFIG_SYSCTL if [ "$CONFIG_PROC_FS" = "y" ]; then define_bool CONFIG_KCORE_ELF y diff -N -u -r kernel-source-2.4.25/arch/sparc/defconfig kernel-source-2.4.25-snare/arch/sparc/defconfig --- kernel-source-2.4.25/arch/sparc/defconfig 2004-02-22 03:46:35.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/sparc/defconfig 2004-07-20 16:27:35.000000000 -0400 @@ -57,6 +57,7 @@ CONFIG_NET=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_C2_AUDIT is not set CONFIG_SYSCTL=y CONFIG_KCORE_ELF=y CONFIG_BINFMT_AOUT=y diff -N -u -r kernel-source-2.4.25/arch/sparc64/config.in kernel-source-2.4.25-snare/arch/sparc64/config.in --- kernel-source-2.4.25/arch/sparc64/config.in 2004-02-22 04:28:10.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/sparc64/config.in 2004-07-20 16:27:35.000000000 -0400 @@ -67,6 +67,7 @@ bool 'Networking support' CONFIG_NET bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT +bool 'SNARE C2 Auditing' CONFIG_C2_AUDIT bool 'Sysctl support' CONFIG_SYSCTL if [ "$CONFIG_PROC_FS" = "y" ]; then define_bool CONFIG_KCORE_ELF y diff -N -u -r kernel-source-2.4.25/arch/sparc64/defconfig kernel-source-2.4.25-snare/arch/sparc64/defconfig --- kernel-source-2.4.25/arch/sparc64/defconfig 2004-02-22 03:46:35.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/sparc64/defconfig 2004-07-20 16:27:35.000000000 -0400 @@ -60,6 +60,7 @@ CONFIG_NET=y CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_C2_AUDIT is not set CONFIG_SYSCTL=y CONFIG_KCORE_ELF=y CONFIG_SPARC32_COMPAT=y diff -N -u -r kernel-source-2.4.25/arch/x86_64/config.in kernel-source-2.4.25-snare/arch/x86_64/config.in --- kernel-source-2.4.25/arch/x86_64/config.in 2004-02-20 22:47:00.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/x86_64/config.in 2004-07-20 16:27:35.000000000 -0400 @@ -103,6 +103,7 @@ bool 'System V IPC' CONFIG_SYSVIPC bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT +bool 'SNARE C2 Auditing' CONFIG_C2_AUDIT bool 'Sysctl support' CONFIG_SYSCTL if [ "$CONFIG_PROC_FS" = "y" ]; then define_bool CONFIG_KCORE_ELF y diff -N -u -r kernel-source-2.4.25/arch/x86_64/defconfig kernel-source-2.4.25-snare/arch/x86_64/defconfig --- kernel-source-2.4.25/arch/x86_64/defconfig 2004-02-22 03:46:35.000000000 -0500 +++ kernel-source-2.4.25-snare/arch/x86_64/defconfig 2004-07-20 16:27:35.000000000 -0400 @@ -62,6 +62,7 @@ # CONFIG_HOTPLUG_PCI is not set CONFIG_SYSVIPC=y # CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_C2_AUDIT is not set CONFIG_SYSCTL=y CONFIG_KCORE_ELF=y CONFIG_BINFMT_ELF=y diff -N -u -r kernel-source-2.4.25/audit/Makefile kernel-source-2.4.25-snare/audit/Makefile --- kernel-source-2.4.25/audit/Makefile 1969-12-31 19:00:00.000000000 -0500 +++ kernel-source-2.4.25-snare/audit/Makefile 2004-07-20 16:27:35.000000000 -0400 @@ -0,0 +1,17 @@ +# +# Makefile for the linux audit. +# +# Note! Dependencies are done automagically by 'make dep', which also +# removes any old dependencies. DON'T put your own dependencies here +# unless it's something special (ie not a .c file). +# +# Note 2! The CFLAGS definition is now in the main makefile... + +O_TARGET := audit.o + +export-objs = auditapi.o + +obj-$(CONFIG_C2_AUDIT) += auditapi.o +obj-y += auditapi.o + +include $(TOPDIR)/Rules.make diff -N -u -r kernel-source-2.4.25/audit/auditapi.c kernel-source-2.4.25-snare/audit/auditapi.c --- kernel-source-2.4.25/audit/auditapi.c 1969-12-31 19:00:00.000000000 -0500 +++ kernel-source-2.4.25-snare/audit/auditapi.c 2004-07-20 16:29:00.000000000 -0400 @@ -0,0 +1,1981 @@ +/* $Id: auditapi.c,v 1.2 2004/05/19 02:44:04 redphoenix Exp $ + * + * audit/auditapi.c + * + * Original Copyright (c) 2002-2004 InterSect Alliance Pty Ltd + * - www.intersectalliance.com + * + * Additions: + * 2004: Modified by Mark Westerman mark.westerman@westcam.com + * 2004: Copyright (c) 2004 Silicon Graphics, Inc. All rights reserved. + * + */ + +// If CONFIG_C2_AUDIT is not defined, do NOTHING. +// See also: linux/audit.h - if not configured, all audit_* +// routines will be optimised out of existance by gcc. +// (Thanks to Alan Cox for the suggestion). + +// Memory usage +#include + +#ifdef CONFIG_C2_AUDIT + +// Total events and lost events not working now do not show +// Modification By mark.westerman@westcam.com +#define SHOW_EVENT_COUNTER 0 + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#ifndef LINUX_VERSION_CODE +#include +#endif + +// Externals +// Not certain that we need this. +extern struct socket *sockfd_lookup (int fd, int *err); + + +// Function prototypes +static int info_open(struct inode *inode, struct file *file); +static ssize_t info_read(struct file *file, char *ubuf, size_t length, + loff_t * ppos); +static int info_close(struct inode *inode, struct file *file); + +static int auditproc_ioctl(struct inode *, struct file *, unsigned int, + unsigned long); +static int auditproc_open(struct inode *, struct file *); +static int auditproc_close(struct inode *, struct file *); +static ssize_t auditproc_read(struct file *, char *, size_t, loff_t *); + +static void audit_on(int auditnumber); +static void audit_off(int auditnumber); +static AuditNode *alloc_event(int token_size); +static void append_event(AuditNode * nodepointer); + +static long GrabString(char *destination, const char *kernelstring, + const char *userstring, int length); + +static void audit_hwcheck(void); +int audit_return(int returncode); + +static DECLARE_MUTEX(audit_lock); +static struct task_struct *auditdaemon_task_struct = NULL; // Daemon interaction + +// If we have the audit daemon attached +int AUDIT_IS_RUNNING = 0; +static int AUDIT_IS_PAUSED = 0; // Used for High Water Mark memory testing + +#if defined(RED_HAT_LINUX_KERNEL) || ( LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0) ) +#define PRIO_TO_NICE(prio) ((prio) - MAX_RT_PRIO - 20) +#endif + +// How many packets have we lost this session due to low buffer size? +static int lost_events = 0; +static int total_events = 0; + +// Linked list of audit events - used as an internal buffer +// so that we don't slow down the kernel significantly while waiting +// for the user space audit daemon to catch up. +static AuditNode *list_head = (AuditNode *) NULL; +static AuditNode *list_tail = (AuditNode *) NULL; + +// Audit daemon read position +static void *read_position = (void *) NULL; + +// Setup a bitmask to work out which audit events are currently active. +// Declare as volatile for the compiler not lock for test events +volatile static unsigned long active_events[(MAXAUDIT + sizeof(long) - 1) / + sizeof(long)] = { 0, }; + +#define audit_active(auditnumber) \ + (test_bit((auditnumber),active_events)) + +static struct file_operations file_ops = { + read:auditproc_read, // read + ioctl:auditproc_ioctl, // ioctl + open:auditproc_open, // open + release:auditproc_close, // release +}; + +static struct file_operations info_ops = { + read:info_read, // read + open:info_open, + release:info_close, +}; + +static struct proc_dir_entry *ProcInfoEntry; +static struct proc_dir_entry *ProcEntry; + +// +// For compatibility with Non RedHat i.e. vanilla kernels +// including debian kernels +// + +#if !defined(RED_HAT_LINUX_KERNEL) && ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) ) +#define set_user_nice(tsk, n) do { (tsk)->nice = n; } while(0) +#endif + +// +// Highwater mark varables for memory utilization +// +static unsigned long highwater_mark = 15000000; // Set to 15 MB by Default +static unsigned long memory_usage = 0; // Current Memory Usage +static int nicevalue; // Nice Value that the + // Audit Daemon was stated with +static int prio_change = 0; // Has priority Changed +static int highwater_pause = 100; // % to of memory usage to pause +static int lowwater_pause = 90; // % to resume auditing +static int highwater_nice = 80; // % to change audit priority +static int highwater_nice_val = -10; // Nice value to change to +static int lowwater_nice = 60; // % to change back the priority +static int highwater_mark_percent = 10; // % of memory to use for High water mark + +wait_queue_head_t proc_audit_queue; + +// Use to calculate total ram +#define BSHIFT(x) ((unsigned long)(x) << PAGE_SHIFT) + +// Initialise our audit environment +void audit_init(void) +{ + struct sysinfo i; + + // Initialise audit here + // - create /proc entries etc. + printk("SNARE Audit capability is initialising\n"); + + if ((ProcInfoEntry = + create_proc_entry(AUDITINFO_NAME, S_IRUGO | S_IWUSR, + NULL)) == NULL) { + printk("Audit: Cannot create /proc/auditinfo"); + return; + } + ProcInfoEntry->proc_fops = &info_ops; + + if ((ProcEntry = + create_proc_entry(AUDITDEV_NAME, S_IRUSR | S_IWUSR, + NULL)) == NULL) + return; + + ProcEntry->proc_fops = &file_ops; + + // Initialise the wait queue for blocking read + init_waitqueue_head(&proc_audit_queue); + // Initialise the highwater mark system + memory_usage = 0; + AUDIT_IS_PAUSED = 0; + si_meminfo(&i); + // Set the highwater mark as a percentage of total ram + highwater_mark = (BSHIFT(i.totalram) / 100) * highwater_mark_percent; +} + +static int info_open(struct inode *inode, struct file *file) +{ + enum { DATA_LEN = 500 }; + char *data; + char processid[20]; + int nv; + pid_t ad_task = 0; + int daemon_running = 0; +#if SHOW_EVENT_COUNTER + int l_lost_events, l_total_events; +#endif + + if ((data = kmalloc(DATA_LEN, GFP_KERNEL)) == NULL) + return (0); + + down(&audit_lock); + + if (auditdaemon_task_struct != NULL) { + daemon_running = 1; + ad_task = auditdaemon_task_struct->pid; + } + +#if SHOW_EVENT_COUNTER + l_lost_events = lost_events; + l_total_events = total_events; +#endif + + up(&audit_lock); + + if(daemon_running) { + snprintf(processid, 20, "%d", (int) ad_task); +#if !defined(RED_HAT_LINUX_KERNEL) && ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) ) + nv = auditdaemon_task_struct->nice; +#else + nv = PRIO_TO_NICE(auditdaemon_task_struct->static_prio); +#endif + } else { + snprintf(processid, 20, "No Daemon Running"); + nv = 0; + } + + +#if SHOW_EVENT_COUNTER + // Just my perference I like the output lined up + snprintf(data, DATA_LEN, + "SNARE Version: %d.%d.%d\n" + "Audit Active: %s\n" + "Audit Process ID: %s\n" + "Events Lost This Session: %d\n" + "Events Processed This Session: %d\n" + "HighWater Mark: %lu\n" + "Memory Usage: %lu\n" + "Audit Paused: %s\n" + "Audit Nice Value: %d\n", + SNAREAUDIT_MAJOR_VERSION, SNAREAUDIT_MINOR_VERSION, + SNAREAUDIT_PATCH_VERSION, + (AUDIT_IS_RUNNING ? "yes" : "no"), processid, l_lost_events, + l_total_events, highwater_mark, memory_usage, + (AUDIT_IS_PAUSED ? "yes" : "no"), nv); +#else + snprintf(data, DATA_LEN, + "SNARE Version: %d.%d.%d\n" + "Audit Active: %s\n" + "Audit Process ID: %s\n" + "HighWater Mark: %lu\n" + "Memory Usage: %lu\n" + "Audit Paused: %s\n" + "Audit Nice Value: %d\n", + SNAREAUDIT_MAJOR_VERSION, SNAREAUDIT_MINOR_VERSION, + SNAREAUDIT_PATCH_VERSION, + (AUDIT_IS_RUNNING ? "yes" : "no"), processid, + highwater_mark, memory_usage, + (AUDIT_IS_PAUSED ? "yes" : "no"), nv); +#endif + + if (data == NULL) + return -ENODEV; + + file->private_data = data; + + return (0); +} + +static void audit_hwcheck(void) +{ + unsigned long per; + int paused; + + + // We lock the kerenel here to handle the + // the highwater mark system use lot of + // global varables + + down(&audit_lock); + paused = AUDIT_IS_PAUSED; + per = memory_usage / (highwater_mark / 100); + + if (per > highwater_pause) { + AUDIT_IS_PAUSED = 1; + ++lost_events; + up(&audit_lock); + if (!paused) { + printk("Auditing: is paused\n"); + } + return; + } + if (per > highwater_nice) { + if (!AUDIT_IS_PAUSED) { + if (!prio_change) { + prio_change = 1; + up(&audit_lock); + printk + ("Auditing: Changing Audit daemon Priority\n"); + set_user_nice(auditdaemon_task_struct, + highwater_nice_val); + return; + } + up(&audit_lock); + return; + } + ++lost_events; + up(&audit_lock); + return; + } + if (AUDIT_IS_PAUSED && (per < lowwater_pause)) { + AUDIT_IS_PAUSED = 0; + } else { + paused = 0; + } + if (prio_change && per < lowwater_nice) { + prio_change = 0; + up(&audit_lock); + printk("Auditing: Resuming Audit daemon Priority\n"); + set_user_nice(auditdaemon_task_struct, nicevalue); + return; + } + if (AUDIT_IS_PAUSED) { + ++lost_events; + } + + up(&audit_lock); + if (paused) { + printk("Auditing: is resuming\n"); + } +} + +static int info_close(struct inode *inode, struct file *file) +{ + kfree(file->private_data); + return (0); +} + +static ssize_t info_read(struct file *file, char *ubuf, size_t length, + loff_t * ppos) +{ + int bytes_to_write = 0; + int pos = *ppos; + char *data = file->private_data; + + // User has asked for a zero-length read? + if (length == 0) + return (0); + + if ((bytes_to_write = strlen(data) - pos) <= 0) + return 0; // EOF + if (bytes_to_write >= length) + bytes_to_write = length; + if (copy_to_user(ubuf, data + pos, bytes_to_write)) + return -EFAULT; + *ppos = pos + bytes_to_write; + return (bytes_to_write); +} + + +//////////////////////////////////////////////////////////////////////////////// +// This routine handles ioctl messages from the audit daemon. +//////////////////////////////////////////////////////////////////////////////// + +int auditproc_ioctl(struct inode *node, struct file *the_file, + unsigned int command, unsigned long arg) +{ + // If the audit facility is running, there is not much point starting again! + if ((AUDIT_IS_RUNNING) && (command == AUDIT_START)) { + return -EBUSY; + } + + // Don't alllow a forked or cloned task to ioctl. + // Only the task which opened the audit device may + // control this device. + if(auditdaemon_task_struct != current) { + return -EBUSY; + } + + if (command == AUDIT_START) { + down(&audit_lock); + AUDIT_IS_RUNNING = 1; + up(&audit_lock); + } else if (command == AUDIT_STOP) { + down(&audit_lock); + AUDIT_IS_RUNNING = 0; + up(&audit_lock); + } else if (command == AUDIT_LOSTEVENTS) { + return (lost_events); + } else if (command == AUDIT_TOTALEVENTS) { + return (total_events); + } else if (command == AUDIT_EVENT_ON) { + if(arg <= 0 || arg > MAXAUDIT) { + return -EINVAL; + } + audit_on(arg); + } else if (command == AUDIT_EVENT_OFF) { + if(arg <= 0 || arg > MAXAUDIT) { + return -EINVAL; + } + audit_off(arg); + // Eg: ioctl(x,SYS_exit); + } else if (command == AUDIT_FLUSH) { + // Turn off all auditing. + // This is generally sent when /etc/audit/audit.conf has been updated + // and the user wishes to establish a new audit policy. + int counter; + for (counter = 1; counter <= MAXAUDIT; counter++) { + if (audit_active(counter)) + audit_off(counter); + } + + // Also reset the lost/total event counters here. + lost_events = 0; + total_events = 0; + // High water mark system should add error checking here. + } else if (command == AUDIT_HIGHWATERMARK_MEM) { + highwater_mark = arg; + } else if (command == AUDIT_HIGHWATERMARK_PER) { + struct sysinfo i; + si_meminfo(&i); + highwater_mark_percent = arg; + highwater_mark = + (BSHIFT(i.totalram) / 100) * highwater_mark_percent; + } else if (command == AUDIT_HIGHWATERMARK_PAUSE) { + highwater_pause = arg; + } else if (command == AUDIT_LOWWATERMARK_PAUSE) { + lowwater_pause = arg; + } else if (command == AUDIT_HIGHWATERMARK_NICE) { + highwater_nice_val = arg; + } else if (command == AUDIT_LOWWATERMARK_NICE) { + lowwater_nice = arg; + } else if (command == AUDIT_HIGHWATER_NICE_VAL) { + highwater_nice_val = arg; + } else { + return -ENOSYS; // Redhat kernel team suggest ENOTTY ? Clarify this. + } + + return 0; +} + + +//////////////////////////////////////////////////////////////////////////////// +// Here we give the user the data. +// NOTE that this module may be executed at any time - even in the middle +// of the execution of something else. Hence, any variables that are changed +// by this routine should be surrounded by a kernel lock if they are used +// elsewhere! +// +// In particular: +// read_position +// list_head +// list_tail +// +// Let me just repeat this in another way: +// WARNING: DO NOT CHANGE OR RELY ON THE VARIABLES ABOVE UNLESS YOU ARE +// IN A LOCKED STATE - THEY MAY BE CORRUPTED BY THE +// AUDIT_READ MODULE, WHICH IS CALLED BY SIGNAL/INTERRUPT +// +// Unfortunately, we also need lock within this routine also. +// Otherwise, an interrupt might occur when we were half way through modifying +// something like read_position - and if the interrupt happens to generate an +// audit event, then we may be copying data to the wrong location in the array, +// leading to data corruption. +// Locking too much code slows down the system unfortunately. I'll try +// and keep it minimal. +//////////////////////////////////////////////////////////////////////////////// + +static ssize_t auditproc_read(struct file *file, char *filebuffer, + size_t length, loff_t * ppos) +{ + // Number of bytes actually written to the buffer + int bytes_avail_to_send = 0; + int bytes_to_write = 0; + + + // Don't allow a forked or cloned task to read. + // Only the task which opened the audit device may read. + if(auditdaemon_task_struct != current) { + return -EBUSY; + } + + if (length == 0) + return (0); // Only want zero bytes? Here they are. + + if (ppos != &file->f_pos) + return -ESPIPE; // No pread() thanks. + + BUG_ON(auditdaemon_task_struct == NULL); + + // Do we have any data? + if (list_head == (AuditNode *) NULL) { + if (file->f_flags & O_NONBLOCK) { + return -EAGAIN; + } + if (wait_event_interruptible(proc_audit_queue, list_head)) { + return -ERESTARTSYS; + } + } + + // Lock the kernel + down(&audit_lock); + if (read_position == (void *) NULL) { + // Our first time into this routine, or first time back after all data has been read. + read_position = list_head->location; + } + + bytes_avail_to_send = + (int) (((void *) list_head->location + list_head->size) - + (void *) read_position); + + up(&audit_lock); + + while (bytes_avail_to_send < length) { + // up(&audit_lock); + if (file->f_flags & O_NONBLOCK) { + return -EAGAIN; + } + + if (wait_event_interruptible(proc_audit_queue, + (bytes_avail_to_send = + (int) (list_head->location + + list_head->size - + read_position)) >= + length)) { + return -ERESTARTSYS; + } + // down(&audit_lock); + } + bytes_to_write = length; + + if (copy_to_user(filebuffer, read_position, bytes_to_write)) { + // up(&audit_lock); + return -EFAULT; + } + + down(&audit_lock); + read_position += bytes_to_write; + + // Have we reached the end of the current nodes data? + if ((void *) read_position >= + ((void *) list_head->location + list_head->size)) { + AuditNode *tempnode; + + tempnode = list_head; + list_head = list_head->next; + + if (tempnode->size > memory_usage) { + memory_usage = 0; + } else { + memory_usage -= tempnode->size; + } + // Excellent, we're at the end of the current audit event. + // Remove this from the linked list, and set the read_position to the next record. + if (list_head != (AuditNode *) NULL) { + read_position = list_head->location; + } else { + read_position = (AuditNode *) NULL; + } + + // No events remaining? Set list_tail to null also. + if (tempnode->next == (AuditNode *) NULL) { + list_tail = (AuditNode *) NULL; + } + + // Free our tempnode->location pointer, which actually + // is a pointer to ex current->audit_record + kfree(tempnode->location); + kfree(tempnode); + } + + up(&audit_lock); + + return (bytes_to_write); +} + + +//////////////////////////////////////////////////////////////////////////////// +// open the device +//////////////////////////////////////////////////////////////////////////////// +static int auditproc_open(struct inode *node, struct file *the_file) +{ + // Note: This changes to minor(node...) in 2.6 + int device_minor = MINOR(node->i_rdev) & 0xf; // Device minor number + + // We can only have one audit device, and it can only be open once + if (device_minor) + return -ENODEV; + + down(&audit_lock); + + if (auditdaemon_task_struct != NULL) { + up(&audit_lock); + return -EBUSY; + } + + // reset the lost packets indicator + lost_events = 0; + total_events = 0; + memory_usage = 0; + AUDIT_IS_PAUSED = 0; + + // Fetch the task structure of the process that opened the device + auditdaemon_task_struct = current; +#if !defined(RED_HAT_LINUX_KERNEL) && ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0) ) + nicevalue = auditdaemon_task_struct->nice; +#else + nicevalue = PRIO_TO_NICE(auditdaemon_task_struct->static_prio); +#endif + + // reset our read position to the beginning of head event data + read_position = NULL; + + up(&audit_lock); + + printk("Auditing: Process %d has opened the device\n", + auditdaemon_task_struct->pid); + + return 0; +} + +//////////////////////////////////////////////////////////////////////////////// +// close the device and release resources +//////////////////////////////////////////////////////////////////////////////// +static int auditproc_close(struct inode *node, struct file *the_file) +{ + int counter; +#if SHOW_EVENT_COUNTER + int l_lost_events, l_total_events; +#endif + + // Only the task that opened the audit device can + // close the device. We don't want another thread + // to interfere. + if(auditdaemon_task_struct != current) { + return(0); + } + + for (counter = 1; counter <= MAXAUDIT; counter++) { + audit_off(counter); + } + + down(&audit_lock); + AUDIT_IS_RUNNING = 0; + + auditdaemon_task_struct = NULL; +#if SHOW_EVENT_COUNTER + l_lost_events = lost_events; + l_total_events = total_events; +#endif + lost_events = 0; + total_events = 0; + memory_usage = 0; + AUDIT_IS_PAUSED = 0; + + up(&audit_lock); + + printk("AUDIT: Audit daemon has closed /proc/audit.\n"); +#if SHOW_EVENT_COUNTER + printk("AUDIT: Events lost due low memory this session: %d\n", + l_lost_events); + printk("AUDIT: Total Events processed this session: %d\n", + l_total_events); +#endif + + return 0; +} + +static void audit_on(int auditnumber) +{ + if(auditnumber <= 0 || auditnumber > MAXAUDIT) { + return; + } + down(&audit_lock); + set_bit(auditnumber, active_events); + up(&audit_lock); +} + +static void audit_off(int auditnumber) +{ + if(auditnumber <= 0 || auditnumber > MAXAUDIT) { + return; + } + down(&audit_lock); + clear_bit(auditnumber, active_events); + up(&audit_lock); +} + +int _audit_mknod(const char *kfile, const char *ufile, int mode, dev_t dev, + int retval) +{ + io_class *record; + + // If noone has requested MKNOD to be active, return quickly. + if (!audit_active(AUDIT_mknod)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (1); + + // alloc the audit record + current->audit_record = kmalloc(sizeof(io_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (io_class *) current->audit_record; + + // Filename. + GrabString(record->t_path.path, kfile, ufile, MAX_PATH); + + record->t_attributes.mode = (int) mode; + record->t_attributes.createmode = (unsigned long) dev; + + record->t_header.event_id = AUDIT_mknod; + record->t_header.event_class = AUDIT_CLASS_IO; + audit_return(retval); + return (1); +} + + +char *audit_copy_argv(char **argv) +{ + char *returnstring; + char tempstring[MAX_PATH]; + unsigned int delimiter_required = 0; + + if (!audit_active(AUDIT_execve)) + return ((char *) NULL); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return ((char *) NULL); + + // + // Dont check audit_record for NULL Since it it will be here + // + returnstring = kmalloc(MAX_PATH, GFP_KERNEL); + if (!returnstring) + return ((char *) NULL); // Out of mem + + returnstring[0] = '\0'; + while (argv && *argv) { + strncpy_from_user(tempstring, *argv, MAX_PATH - 1); + tempstring[MAX_PATH-1] = '\0'; + + // Allow for the delimiter + if ((strlen(returnstring) + strlen(tempstring) + 1) < + (MAX_PATH - 1)) { + if (!delimiter_required) { + delimiter_required = 1; + } else { + strcat(returnstring, " "); + } + strcat(returnstring, tempstring); + } else { + // If the argument size is greater than MAX_PATH, then + // ignore this argument, continue on to the next. + argv++; + continue; + } + argv++; + } + + return (returnstring); +} + +int _audit_execve(const char *ufilename, const char *kfilename, + char *arguments, int retval) +{ + ex_class *record; + + if (!audit_active(AUDIT_execve)) { + if (arguments) { + kfree(arguments); + } + return (0); + } + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) { + if (arguments) { + kfree(arguments); + } + return (0); + } + + if (current->audit_record) { + if (arguments) { + kfree(arguments); + } + return (1); + } + + // alloc the audit record + current->audit_record = kmalloc(sizeof(ex_class), GFP_KERNEL); + if (!current->audit_record) { + if (arguments) { + kfree(arguments); + } + return (0); + } + + record = (ex_class *) current->audit_record; + + // Use our new grabstring routine + GrabString(record->t_path.path, kfilename, ufilename, MAX_PATH); + + if (arguments) { + strncpy(record->t_execargs.args, arguments, MAX_PATH); + kfree(arguments); + } else { + strcat(record->t_execargs.args, ""); + } + + record->t_header.event_id = AUDIT_execve; + record->t_header.event_class = AUDIT_CLASS_EXEC; + + audit_return(retval); + return (0); +} + + +int _audit_exit(int retval) +{ + pc_class *record; + + if (!audit_active(AUDIT_exit)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (1); + + // alloc the audit record + current->audit_record = kmalloc(sizeof(pc_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (pc_class *) current->audit_record; + record->t_header.event_id = AUDIT_exit; + record->t_header.event_class = AUDIT_CLASS_PC; + audit_return(retval); + return (1); +} + +int _audit_fork(int retval) +{ + pc_class *record; + + if (!audit_active(AUDIT_fork)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (1); + + // alloc the audit record + current->audit_record = kmalloc(sizeof(pc_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (pc_class *) current->audit_record; + record->t_header.event_id = AUDIT_fork; + record->t_header.event_class = AUDIT_CLASS_PC; + audit_return(retval); + return (1); +} + +int _audit_open(const char *kfile, const char *ufile, int flags, int mode, + int retval) +{ + io_class *record; + + if (!audit_active(AUDIT_open)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (1); + + // alloc the audit record + current->audit_record = kmalloc(sizeof(io_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (io_class *) current->audit_record; + + // Filename. + GrabString(record->t_path.path, kfile, ufile, MAX_PATH); + + record->t_attributes.mode = flags; + record->t_attributes.createmode = mode; + + record->t_header.event_id = AUDIT_open; + record->t_header.event_class = AUDIT_CLASS_IO; + + audit_return(retval); + return (1); +} + +int _audit_mkdir(const char *kfile, const char *ufile, int mode, int retval) +{ + io_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_mkdir)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (1); + + // alloc the audit record + current->audit_record = kmalloc(sizeof(io_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (io_class *) current->audit_record; + + // Filename. + GrabString(record->t_path.path, kfile, ufile, MAX_PATH); + + record->t_attributes.mode = 0; + record->t_attributes.createmode = mode; + + record->t_header.event_id = AUDIT_mkdir; + record->t_header.event_class = AUDIT_CLASS_IO; + audit_return(retval); + return (1); +} + +int _audit_unlink(const char *kfile, const char *ufile, int retval) +{ + io_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_unlink)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (1); + + // alloc the audit record + current->audit_record = kmalloc(sizeof(io_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (io_class *) current->audit_record; + + // Filename. + GrabString(record->t_path.path, kfile, ufile, MAX_PATH); + + record->t_attributes.mode = 0; + record->t_attributes.createmode = 0; + + record->t_header.event_id = AUDIT_unlink; + record->t_header.event_class = AUDIT_CLASS_IO; + audit_return(retval); + return (1); +} + +int _audit_rmdir(const char *kfile, const char *ufile, int retval) +{ + io_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_rmdir)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (1); + + // alloc the audit record + current->audit_record = kmalloc(sizeof(io_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (io_class *) current->audit_record; + + // Filename. + GrabString(record->t_path.path, kfile, ufile, MAX_PATH); + + record->t_attributes.mode = 0; + record->t_attributes.createmode = 0; + + record->t_header.event_id = AUDIT_rmdir; + record->t_header.event_class = AUDIT_CLASS_IO; + audit_return(retval); + return (1); +} + +int _audit_chown(const char *kfile, const char *ufile, uid_t user, + gid_t group, int retval) +{ + ch_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_chown)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (1); + + // alloc the audit record + current->audit_record = kmalloc(sizeof(ch_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (ch_class *) current->audit_record; + + // Filename. + GrabString(record->t_path.path, kfile, ufile, MAX_PATH); + + record->t_owner.owner = (int) user; + record->t_owner.group = (int) group; + + record->t_header.event_id = AUDIT_chown; + record->t_header.event_class = AUDIT_CLASS_CH; + audit_return(retval); + return (1); +} + +int _audit_chmod(const char *kfile, const char *ufile, mode_t mode, + int retval) +{ + io_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_chmod)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (1); + + // alloc the audit record + current->audit_record = kmalloc(sizeof(io_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (io_class *) current->audit_record; + + // Filename. + GrabString(record->t_path.path, kfile, ufile, MAX_PATH); + + record->t_attributes.mode = 0; + record->t_attributes.createmode = (unsigned long) mode; + + record->t_header.event_id = AUDIT_chmod; + record->t_header.event_class = AUDIT_CLASS_IO; + audit_return(retval); + return (1); +} + +int _audit_symlink(const char *kfrom, const char *ufrom, const char *kto, + const char *uto, int retval) +{ + cp_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_symlink)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + + if (current->audit_record) { + return (1); + } + // alloc the audit record + current->audit_record = kmalloc(sizeof(cp_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (cp_class *) current->audit_record; + + // Filename. + GrabString(record->t_sourcepath.path, kfrom, ufrom, MAX_PATH); + GrabString(record->t_destpath.path, kto, uto, MAX_PATH); + + record->t_header.event_id = AUDIT_symlink; + record->t_header.event_class = AUDIT_CLASS_CP; + + audit_return(retval); + return (1); +} + +int _audit_link(const char *kfrom, const char *ufrom, const char *kto, + const char *uto, int retval) +{ + cp_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_link)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + + if (current->audit_record) { + return (1); + } + // alloc the audit record + current->audit_record = kmalloc(sizeof(cp_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (cp_class *) current->audit_record; + + // Filename. + GrabString(record->t_sourcepath.path, kfrom, ufrom, MAX_PATH); + GrabString(record->t_destpath.path, kto, uto, MAX_PATH); + + record->t_header.event_id = AUDIT_link; + record->t_header.event_class = AUDIT_CLASS_CP; + + audit_return(retval); + return (1); +} + +int _audit_rename(const char *kfrom, const char *ufrom, const char *kto, + const char *uto, int retval) +{ + cp_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_rename)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (1); + + // alloc the audit record + current->audit_record = kmalloc(sizeof(cp_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (cp_class *) current->audit_record; + + // Filename. + GrabString(record->t_sourcepath.path, kfrom, ufrom, MAX_PATH); + GrabString(record->t_destpath.path, kto, uto, MAX_PATH); + + record->t_header.event_id = AUDIT_rename; + record->t_header.event_class = AUDIT_CLASS_CP; + audit_return(retval); + return (1); +} + +// Truncate - note that we need to grab the data from userspace. +int _audit_truncate(const char *kfile, const char *ufile, loff_t length, + int retval) +{ + io_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_truncate)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + + if (current->audit_record) { + return (1); + } + // alloc the audit record + current->audit_record = kmalloc(sizeof(io_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (io_class *) current->audit_record; + + // Filename. + GrabString(record->t_path.path, kfile, ufile, MAX_PATH); + + record->t_attributes.createmode = (unsigned long) length; + + record->t_header.event_id = AUDIT_truncate; + record->t_header.event_class = AUDIT_CLASS_IO; + audit_return(retval); + return (1); +} + +int _audit_chroot(const char *kfile, const char *ufile, int retval) +{ + io_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_chroot)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + + if (current->audit_record) { + return (1); + } + // alloc the audit record + current->audit_record = kmalloc(sizeof(io_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (io_class *) current->audit_record; + + // Filename. + GrabString(record->t_path.path, kfile, ufile, MAX_PATH); + + record->t_attributes.createmode = (unsigned long) 0; + + record->t_header.event_id = AUDIT_chroot; + record->t_header.event_class = AUDIT_CLASS_IO; + + audit_return(retval); + return (1); +} + +int _audit_mount(const char *kdev_name, const char *udev_name, + const char *kdir_name, const char *udir_name, + unsigned long flags, int retval) +{ + cp_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_mount)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (1); + + // alloc the audit record + current->audit_record = kmalloc(sizeof(cp_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (cp_class *) current->audit_record; + + GrabString(record->t_sourcepath.path, kdev_name, udev_name, + MAX_PATH); + GrabString(record->t_sourcepath.path, kdir_name, udir_name, + MAX_PATH); + + record->t_header.event_id = AUDIT_mount; + record->t_header.event_class = AUDIT_CLASS_CP; + + audit_return(retval); + return (1); +} + +int _audit_umount(const char *kname, const char *uname, int flags, + int retval) +{ + cp_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_umount)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (1); + + // alloc the audit record + current->audit_record = kmalloc(sizeof(cp_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (cp_class *) current->audit_record; + + record->t_sourcepath.path[0] = '\0'; + // Name has not yet been grabbed from userspace by sys_umount + // Copy it from userspace here. + GrabString(record->t_sourcepath.path, kname, uname, MAX_PATH); + + record->t_destpath.path[0] = '\0'; + + record->t_header.event_id = AUDIT_umount; + record->t_header.event_class = AUDIT_CLASS_CP; + audit_return(retval); + return (1); +} + +int _audit_setuid(uid_t uid, int retval) +{ + su_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_setuid)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (1); + + // alloc the audit record + current->audit_record = kmalloc(sizeof(su_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (su_class *) current->audit_record; + + record->t_target.id = uid; + + record->t_header.event_id = AUDIT_setuid; + record->t_header.event_class = AUDIT_CLASS_SU; + audit_return(retval); + return (1); +} + +int _audit_setreuid(uid_t ruid, uid_t euid, int retval) +{ + su_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_setreuid)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (1); + + // alloc the audit record + current->audit_record = kmalloc(sizeof(su_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (su_class *) current->audit_record; + + record->t_target.id = euid; + record->t_target.rid = ruid; + + record->t_header.event_id = AUDIT_setreuid; + record->t_header.event_class = AUDIT_CLASS_SU; + audit_return(retval); + return (1); +} + +int _audit_setresuid(uid_t ruid, uid_t euid, uid_t suid, int retval) +{ + su_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_setresuid)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (1); + + // alloc the audit record + current->audit_record = kmalloc(sizeof(su_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (su_class *) current->audit_record; + + record->t_target.id = euid; + record->t_target.rid = ruid; + record->t_target.sid = suid; + + record->t_header.event_id = AUDIT_setresuid; + record->t_header.event_class = AUDIT_CLASS_SU; + audit_return(retval); + return (1); +} + +int _audit_setregid(gid_t rgid, gid_t egid, int retval) +{ + su_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_setregid)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (1); + + // alloc the audit record + current->audit_record = kmalloc(sizeof(su_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (su_class *) current->audit_record; + + record->t_target.id = egid; + record->t_target.rid = rgid; + + record->t_header.event_id = AUDIT_setregid; + record->t_header.event_class = AUDIT_CLASS_SU; + audit_return(retval); + return (1); +} + +int _audit_setresgid(gid_t rgid, gid_t egid, gid_t sgid, int retval) +{ + su_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_setresgid)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (1); + + // alloc the audit record + current->audit_record = kmalloc(sizeof(su_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (su_class *) current->audit_record; + + record->t_target.id = egid; + record->t_target.rid = rgid; + record->t_target.sid = sgid; + + record->t_header.event_id = AUDIT_setresgid; + record->t_header.event_class = AUDIT_CLASS_SU; + audit_return(retval); + return (1); +} + +int _audit_setgid(gid_t gid, int retval) +{ + su_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_setgid)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (1); + + // alloc the audit record + current->audit_record = kmalloc(sizeof(su_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (su_class *) current->audit_record; + + record->t_target.id = gid; + + record->t_header.event_id = AUDIT_setgid; + record->t_header.event_class = AUDIT_CLASS_SU; + audit_return(retval); + return (1); +} + +// Create module +int _audit_create_module(const char *kname, const char *uname, int retval) +{ + ad_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_create_module)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + + if (current->audit_record) { + return (1); + } + // alloc the audit record + current->audit_record = kmalloc(sizeof(ad_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (ad_class *) current->audit_record; + + // Module name + GrabString(record->t_name.path, kname, uname, MAX_PATH); + + record->t_header.event_id = AUDIT_create_module; + record->t_header.event_class = AUDIT_CLASS_AD; + audit_return(retval); + return (1); +} + +// Delete module +int _audit_delete_module(const char *kname, const char *uname, int retval) +{ + ad_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_delete_module)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + + if (current->audit_record) { + return (1); + } + // alloc the audit record + current->audit_record = kmalloc(sizeof(ad_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (ad_class *) current->audit_record; + + // Module name + GrabString(record->t_name.path, kname, uname, MAX_PATH); + + record->t_header.event_id = AUDIT_delete_module; + record->t_header.event_class = AUDIT_CLASS_AD; + audit_return(retval); + return (1); +} + +int _audit_reboot(int magic1, int magic2, unsigned int cmd, void *arg, + int retval) +{ + pc_class *record; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_reboot)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (1); + + // alloc the audit record + current->audit_record = kmalloc(sizeof(pc_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (pc_class *) current->audit_record; + record->t_header.event_id = AUDIT_reboot; + record->t_header.event_class = AUDIT_CLASS_PC; + audit_return(retval); + return (1); +} + +int _audit_connect(int sockfd, struct sockaddr *serv_addr, int addrlen, + int retval) +{ + nt_class *record; + struct socket *sock; + int err; + struct sockaddr_in *si; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_connect)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (0); + + // If this is not an AF_INET, drop it. + if (!serv_addr) { + return (0); + } + if (serv_addr->sa_family != AF_INET) { + return (0); + } + // alloc the audit record + current->audit_record = kmalloc(sizeof(nt_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (nt_class *) current->audit_record; + record->t_header.event_id = AUDIT_connect; + record->t_header.event_class = AUDIT_CLASS_NET; + + snprintf(record->t_connection.dst_ip, 16, "%u.%u.%u.%u", + serv_addr->sa_data[2] & 255, + serv_addr->sa_data[3] & 255, + serv_addr->sa_data[4] & 255, serv_addr->sa_data[5] & 255); + strncpy(record->t_connection.src_ip, "127.0.0.1", 16); + + si = (struct sockaddr_in *) serv_addr; + + record->t_connection.src_port = 0; + record->t_connection.dst_port = ntohs(si->sin_port); + + record->t_connection.protocol = 0; + + if ((sock = sockfd_lookup(sockfd, &err)) != NULL) { + record->t_connection.src_port = sock->sk->num; + record->t_connection.protocol = sock->sk->protocol; + } + audit_return(retval); + return (1); +} + +int _audit_accept(int sockfd, struct sockaddr *peer_addr, int *addrlen, + int retval) +{ + nt_class *record; + struct sockaddr_in *si; + struct socket *sock; + int err; + + // If noone has requested the system call to be active, return quickly. + if (!audit_active(AUDIT_accept)) + return (0); + audit_hwcheck(); + if (current == auditdaemon_task_struct || AUDIT_IS_PAUSED) + return (0); + if (current->audit_record) + return (0); + + // If this is not an AF_INET, drop it. + if (!peer_addr) { + return (0); + } + if (peer_addr->sa_family != AF_INET) { + return (0); + } + // alloc the audit record + current->audit_record = kmalloc(sizeof(nt_class), GFP_KERNEL); + if (!current->audit_record) { + return (0); + } + + record = (nt_class *) current->audit_record; + record->t_header.event_id = AUDIT_accept; + record->t_header.event_class = AUDIT_CLASS_NET; + + snprintf(record->t_connection.src_ip, 16, "%u.%u.%u.%u", + peer_addr->sa_data[2] & 255, + peer_addr->sa_data[3] & 255, + peer_addr->sa_data[4] & 255, peer_addr->sa_data[5] & 255); + strncpy(record->t_connection.dst_ip, "127.0.0.1", 16); + + si = (struct sockaddr_in *) peer_addr; + + record->t_connection.dst_port = 0; + record->t_connection.src_port = ntohs(si->sin_port); + + record->t_connection.protocol = 0; + + if ((sock = sockfd_lookup(sockfd, &err)) != NULL) { + record->t_connection.dst_port = ntohs(sock->sk->sport); + record->t_connection.protocol = sock->sk->protocol; + } + audit_return(retval); + return (1); +} + +int audit_return(int returncode) +{ + // The static null_class and timeval were changed to + // Local varable for smp machines + + int class; + null_class *any_event; + AuditNode *node = (AuditNode *) NULL; + struct timeval time_temp; + + if (!auditdaemon_task_struct) { + goto out; + } + + if (current == auditdaemon_task_struct) { + return (0); + } + + // Unaudited event + if (!current->audit_record) { + goto out; + } + + any_event = current->audit_record; + + do_gettimeofday(&time_temp); + + class = any_event->t_header.event_class; + + // Fill out as much of the header structure as we can. + any_event->t_header.user_id = current->uid; + any_event->t_header.group_id = current->gid; + any_event->t_header.euser_id = current->euid; + any_event->t_header.egroup_id = current->egid; + any_event->t_header.time.tv_sec = time_temp.tv_sec; + any_event->t_header.time.tv_usec = time_temp.tv_usec; + any_event->t_header.returncode = returncode; + strncpy(any_event->t_header.processname, current->comm, + MAXCOMMAND); + any_event->t_header.pid = current->pid; + +#if defined(RED_HAT_LINUX_KERNEL) + // Note: RHEL 2.4.18 doesn't have current->parent.. + if (current->parent) { + any_event->t_header.ppid = current->parent->pid; + } else { + any_event->t_header.ppid = 0; + } +#else + if(current->p_pptr) { + any_event->t_header.ppid=current->p_pptr->pid; + } else { + any_event->t_header.ppid=0; + } +#endif + + // Modified by Mark Westerman Replaced the if else code with + // a switch to help perfromace. + switch (class) { + case AUDIT_CLASS_IO: + { + io_class *record; + char tmp[MAX_PATH]; + record = (io_class *) current->audit_record; + + // Current PWD - IO CLASS, EXEC, CH, CP + // NOTE: This will just tell you the file name the user + // tried to access. If it's linked to another file, or + // from a mountpoint, it will just show you the filename + // used in the system call - not the RESOLVED path. + strncpy(record->t_pwd.path, + d_path(current->fs->pwd, + current->fs->pwdmnt, tmp, MAX_PATH), + MAX_PATH); + + record->t_header.event_size = + sizeof(io_class) - sizeof(header_token); + + if ((node = alloc_event(sizeof(io_class))) == NULL) { + goto out; + } + node->location=record; + } + break; + case AUDIT_CLASS_EXEC: + { + ex_class *record; + char tmp[MAX_PATH]; + record = (ex_class *) current->audit_record; + + // Current PWD - IO CLASS, EXEC, CH, CP + strncpy(record->t_pwd.path, + d_path(current->fs->pwd, + current->fs->pwdmnt, tmp, MAX_PATH), + MAX_PATH); + + record->t_header.event_size = + sizeof(ex_class) - sizeof(header_token); + + if ((node = alloc_event(sizeof(ex_class))) == NULL) { + goto out; + } + node->location=record; + } + break; + case AUDIT_CLASS_PC: + { + pc_class *record; + record = (pc_class *) current->audit_record; + + // Current PWD - IO CLASS, EXEC, CH, CP + record->t_header.event_size = + sizeof(pc_class) - sizeof(header_token); + + if ((node = alloc_event(sizeof(pc_class))) == NULL) { + goto out; + } + node->location=record; + } + break; + case AUDIT_CLASS_CH: + { + ch_class *record; + char tmp[MAX_PATH]; + record = (ch_class *) current->audit_record; + + // Current PWD - IO CLASS, EXEC, CH, CP + strncpy(record->t_pwd.path, + d_path(current->fs->pwd, + current->fs->pwdmnt, tmp, MAX_PATH), + MAX_PATH); + record->t_header.event_size = + sizeof(ch_class) - sizeof(header_token); + + if ((node = alloc_event(sizeof(ch_class))) == NULL) { + goto out; + } + node->location=record; + } + break; + case AUDIT_CLASS_CP: + { + cp_class *record; + char tmp[MAX_PATH]; + record = (cp_class *) current->audit_record; + + // Current PWD - IO CLASS, EXEC, CH, CP + strncpy(record->t_pwd.path, + d_path(current->fs->pwd, + current->fs->pwdmnt, tmp, MAX_PATH), + MAX_PATH); + record->t_header.event_size = + sizeof(cp_class) - sizeof(header_token); + + if ((node = alloc_event(sizeof(cp_class))) == NULL) { + goto out; + } + node->location=record; + } + break; + case AUDIT_CLASS_SU: + { + su_class *record; + record = (su_class *) current->audit_record; + + record->t_header.event_size = + sizeof(su_class) - sizeof(header_token); + + if ((node = alloc_event(sizeof(su_class))) == NULL) { + goto out; + } + node->location=record; + } + break; + case AUDIT_CLASS_AD: + { + ad_class *record; + record = (ad_class *) current->audit_record; + + record->t_header.event_size = + sizeof(ad_class) - sizeof(header_token); + + if ((node = alloc_event(sizeof(ad_class))) == NULL) { + goto out; + } + node->location=record; + } + break; + case AUDIT_CLASS_NET: + { + nt_class *record; + record = (nt_class *) current->audit_record; + + record->t_header.event_size = + sizeof(nt_class) - sizeof(header_token); + + if ((node = alloc_event(sizeof(nt_class))) == NULL) { + goto out; + } + node->location=record; + + } + break; + default: + printk("Auditing Invalid class\n"); + } + + // Cant free this here.. we're still using it. + current->audit_record = NULL; + + // Send the audit record out the door. + append_event(node); + wake_up_interruptible(&proc_audit_queue); + + return (1); + + out: + if (current->audit_record) { + current->audit_record = NULL; + } + if(auditdaemon_task_struct) { + down(&audit_lock); + lost_events++; + up(&audit_lock); + } + return (0); +} + +static void append_event(AuditNode * nodepointer) +{ + down(&audit_lock); + + if (list_tail != (AuditNode *) NULL) { + list_tail->next = nodepointer; + } + + list_tail = nodepointer; + + // Is this the first node in our linked list? + if (list_head == (AuditNode *) NULL) { + list_head = nodepointer; + } + memory_usage += nodepointer->size; + ++total_events; + up(&audit_lock); +} + +AuditNode *alloc_event(int token_size) +{ + AuditNode *nodepointer; + + nodepointer = (AuditNode *) kmalloc(sizeof(AuditNode), GFP_KERNEL); + if (nodepointer == (AuditNode *) NULL) { + return (0); + } + + nodepointer->location = (void *)NULL; + nodepointer->size = token_size; + nodepointer->next = (AuditNode *) NULL; // This is the end. + return nodepointer; +} + +// This grabs data from either kernel or userspace into a string. +long GrabString(char *destination, const char *kernelstring, + const char *userstring, int length) +{ + if (!destination) + return (0); + + if (length < 1) + return (0); + + if (!userstring && !kernelstring) { + strncpy(destination, "AUDIT: Invalid data", length); + return (0); + } + + if (kernelstring) { + strncpy(destination, kernelstring, length); + return (1); + } else { + if (strncpy_from_user(destination, userstring, length) == + -EFAULT) { + strncpy(destination, "AUDIT: Invalid data", + length); + return (0); + } + return (1); + } +} +#endif diff -N -u -r kernel-source-2.4.25/fs/exec.c kernel-source-2.4.25-snare/fs/exec.c --- kernel-source-2.4.25/fs/exec.c 2004-02-22 04:28:30.000000000 -0500 +++ kernel-source-2.4.25-snare/fs/exec.c 2004-07-20 16:27:35.000000000 -0400 @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #define __NO_VERSION__ @@ -912,12 +913,20 @@ struct file *file; int retval; int i; +#if defined(CONFIG_C2_AUDIT) + char *SNARE_arguments; + SNARE_arguments=audit_copy_argv(argv); +#else + #define SNARE_arguments (char *)NULL +#endif file = open_exec(filename); retval = PTR_ERR(file); - if (IS_ERR(file)) + if (IS_ERR(file)) { + audit_execve((char *)NULL, filename, SNARE_arguments, retval); return retval; + } bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *); memset(bprm.page, 0, MAX_ARG_PAGES*sizeof(bprm.page[0])); @@ -929,12 +938,14 @@ bprm.exec = 0; if ((bprm.argc = count(argv, bprm.p / sizeof(void *))) < 0) { allow_write_access(file); + audit_execve((char *) NULL, filename, SNARE_arguments, bprm.argc); fput(file); return bprm.argc; } if ((bprm.envc = count(envp, bprm.p / sizeof(void *))) < 0) { allow_write_access(file); + audit_execve((char *) NULL, filename, SNARE_arguments, bprm.envc); fput(file); return bprm.envc; } @@ -957,15 +968,19 @@ goto out; retval = search_binary_handler(&bprm,regs); - if (retval >= 0) + if (retval >= 0) { + audit_execve((char *)NULL, filename, SNARE_arguments, retval); /* execve success */ return retval; + } out: /* Something went wrong, return the inode and free the argument pages*/ allow_write_access(bprm.file); - if (bprm.file) + if (bprm.file) { fput(bprm.file); + } + audit_execve((char *) NULL, filename, SNARE_arguments, retval); for (i = 0 ; i < MAX_ARG_PAGES ; i++) { struct page * page = bprm.page[i]; diff -N -u -r kernel-source-2.4.25/fs/namei.c kernel-source-2.4.25-snare/fs/namei.c --- kernel-source-2.4.25/fs/namei.c 2004-02-22 03:42:20.000000000 -0500 +++ kernel-source-2.4.25-snare/fs/namei.c 2004-07-20 16:27:35.000000000 -0400 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -1269,15 +1270,21 @@ struct dentry * dentry; struct nameidata nd; - if (S_ISDIR(mode)) + if (S_ISDIR(mode)) { + audit_mknod((char *)NULL,filename,mode,dev,-EPERM); return -EPERM; + } tmp = getname(filename); - if (IS_ERR(tmp)) + if (IS_ERR(tmp)) { + audit_mknod((char *)NULL,(char *)NULL,mode,dev,PTR_ERR(tmp)); return PTR_ERR(tmp); + } error = path_lookup(tmp, LOOKUP_PARENT, &nd); - if (error) + if (error) { + audit_mknod(tmp,(char *)NULL,mode,dev,error); goto out; + } dentry = lookup_create(&nd, 0); error = PTR_ERR(dentry); @@ -1300,6 +1307,8 @@ dput(dentry); } up(&nd.dentry->d_inode->i_sem); + + audit_mknod(nd.dentry->d_name.name,(char *)NULL,mode,dev,error); path_release(&nd); out: putname(tmp); @@ -1340,13 +1349,17 @@ tmp = getname(pathname); error = PTR_ERR(tmp); - if (!IS_ERR(tmp)) { + if (IS_ERR(tmp)) { + audit_mkdir((char *)NULL,(char *)NULL,mode & ~current->fs->umask,error); + } else { struct dentry *dentry; struct nameidata nd; error = path_lookup(tmp, LOOKUP_PARENT, &nd); - if (error) + if (error) { + audit_mkdir(tmp,(char *)NULL,mode & ~current->fs->umask,error); goto out; + } dentry = lookup_create(&nd, 1); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { @@ -1356,6 +1369,7 @@ dput(dentry); } up(&nd.dentry->d_inode->i_sem); + audit_mkdir(tmp,(char *)NULL,mode & ~current->fs->umask,error); path_release(&nd); out: putname(tmp); @@ -1438,12 +1452,15 @@ struct nameidata nd; name = getname(pathname); - if(IS_ERR(name)) + if(IS_ERR(name)) { + audit_rmdir((char *)NULL,(char *)NULL,PTR_ERR(name)); return PTR_ERR(name); + } error = path_lookup(name, LOOKUP_PARENT, &nd); - if (error) + if (error) { goto exit; + } switch(nd.last_type) { case LAST_DOTDOT: @@ -1467,6 +1484,7 @@ exit1: path_release(&nd); exit: + audit_rmdir(name,(char *)NULL,error); putname(name); return error; } @@ -1506,12 +1524,16 @@ struct nameidata nd; name = getname(pathname); - if(IS_ERR(name)) + if(IS_ERR(name)) { + audit_unlink(pathname,(char *)NULL,PTR_ERR(name)); return PTR_ERR(name); + } error = path_lookup(name, LOOKUP_PARENT, &nd); - if (error) + if (error) { + audit_unlink(name,(char *)NULL,error); goto exit; + } error = -EISDIR; if (nd.last_type != LAST_NORM) goto exit1; @@ -1528,10 +1550,10 @@ } up(&nd.dentry->d_inode->i_sem); exit1: + audit_unlink(nd.dentry->d_name.name,(char *)NULL,error); path_release(&nd); exit: putname(name); - return error; slashes: @@ -1571,18 +1593,26 @@ char * from; char * to; + // audit_symlink(oldname,newname); + from = getname(oldname); - if(IS_ERR(from)) + if(IS_ERR(from)) { + audit_symlink((char *)NULL,(char *)NULL,(char *)NULL,newname,PTR_ERR(from)); return PTR_ERR(from); + } to = getname(newname); error = PTR_ERR(to); - if (!IS_ERR(to)) { + if(IS_ERR(to)) { + audit_symlink(from,(char *)NULL,(char *)NULL,(char *)NULL,PTR_ERR(to)); + } else { struct dentry *dentry; struct nameidata nd; error = path_lookup(to, LOOKUP_PARENT, &nd); - if (error) + if (error) { + audit_symlink(from,(char *)NULL,to,(char *)NULL,error); goto out; + } dentry = lookup_create(&nd, 0); error = PTR_ERR(dentry); if (!IS_ERR(dentry)) { @@ -1590,6 +1620,7 @@ dput(dentry); } up(&nd.dentry->d_inode->i_sem); + audit_symlink(from,(char *)NULL,nd.dentry->d_name.name,(char *)NULL,error); path_release(&nd); out: putname(to); @@ -1654,19 +1685,26 @@ to = getname(newname); error = PTR_ERR(to); - if (!IS_ERR(to)) { + if (IS_ERR(to)) { + audit_link((char *)NULL,oldname,(char *)NULL,(char *)NULL,error); + } else { struct dentry *new_dentry; struct nameidata nd, old_nd; error = __user_walk(oldname, LOOKUP_POSITIVE, &old_nd); - if (error) + if (error) { + audit_link((char *)NULL,oldname,to,(char *)NULL,error); goto exit; + } error = path_lookup(to, LOOKUP_PARENT, &nd); - if (error) + if (error) { + audit_link(old_nd.dentry->d_name.name,(char *)NULL,to,(char *)NULL,error); goto out; + } error = -EXDEV; - if (old_nd.mnt != nd.mnt) + if (old_nd.mnt != nd.mnt) { goto out_release; + } new_dentry = lookup_create(&nd, 0); error = PTR_ERR(new_dentry); if (!IS_ERR(new_dentry)) { @@ -1675,6 +1713,7 @@ } up(&nd.dentry->d_inode->i_sem); out_release: + audit_link(old_nd.dentry->d_name.name,(char *)NULL,nd.dentry->d_name.name,(char *)NULL,error); path_release(&nd); out: path_release(&old_nd); @@ -1926,13 +1965,18 @@ char * to; from = getname(oldname); - if(IS_ERR(from)) + if(IS_ERR(from)) { + audit_rename((char *)NULL,(char *)NULL,(char *)NULL,newname,PTR_ERR(from)); return PTR_ERR(from); + } to = getname(newname); error = PTR_ERR(to); if (!IS_ERR(to)) { error = do_rename(from,to); + audit_rename(from,(char *)NULL,to,(char *)NULL,error); putname(to); + } else { + audit_rename(from,(char *)NULL,(char *)NULL,(char *)NULL,error); } putname(from); return error; diff -N -u -r kernel-source-2.4.25/fs/namespace.c kernel-source-2.4.25-snare/fs/namespace.c --- kernel-source-2.4.25/fs/namespace.c 2004-02-20 22:47:11.000000000 -0500 +++ kernel-source-2.4.25-snare/fs/namespace.c 2004-07-20 16:27:35.000000000 -0400 @@ -21,6 +21,8 @@ #include #include +#include + struct vfsmount *do_kern_mount(const char *type, int flags, char *name, void *data); int do_remount_sb(struct super_block *sb, int flags, void * data); void kill_super(struct super_block *sb); @@ -366,9 +368,13 @@ struct nameidata nd; int retval; + // audit_umount(name,flags); + retval = __user_walk(name, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &nd); - if (retval) + if (retval) { + audit_umount((char *)NULL,name,flags,retval); goto out; + } retval = -EINVAL; if (nd.dentry != nd.mnt->mnt_root) goto dput_and_out; @@ -381,6 +387,7 @@ retval = do_umount(nd.mnt, flags); dput_and_out: + audit_umount(nd.dentry->d_name.name,(char *)NULL,flags,retval); path_release(&nd); out: return retval; @@ -836,17 +843,23 @@ char *dir_page; retval = copy_mount_options (type, &type_page); - if (retval < 0) + if (retval < 0) { + audit_mount((char *)NULL,dev_name,(char *)NULL,dir_name,flags,retval); return retval; + } dir_page = getname(dir_name); retval = PTR_ERR(dir_page); - if (IS_ERR(dir_page)) + if (IS_ERR(dir_page)) { + audit_mount((char *)NULL,dev_name,(char *)NULL,dir_name,flags,retval); goto out1; + } retval = copy_mount_options (dev_name, &dev_page); - if (retval < 0) + if (retval < 0) { + audit_mount((char *)NULL,dev_name,dir_page,(char *)NULL,flags,retval); goto out2; + } retval = copy_mount_options (data, &data_page); if (retval < 0) @@ -859,6 +872,7 @@ free_page(data_page); out3: + audit_mount((char *)dev_page,(char *)NULL,dir_page,(char *)NULL,flags,retval); free_page(dev_page); out2: putname(dir_page); diff -N -u -r kernel-source-2.4.25/fs/open.c kernel-source-2.4.25-snare/fs/open.c --- kernel-source-2.4.25/fs/open.c 2004-02-22 04:28:30.000000000 -0500 +++ kernel-source-2.4.25-snare/fs/open.c 2004-07-20 16:27:35.000000000 -0400 @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -122,12 +123,16 @@ int error; error = -EINVAL; - if (length < 0) /* sorry, but loff_t says... */ + if (length < 0) { /* sorry, but loff_t says... */ + audit_truncate((char *)NULL,path,length,error); goto out; + } error = user_path_walk(path, &nd); - if (error) + if (error) { + audit_truncate((char *)NULL,path,length,error); goto out; + } inode = nd.dentry->d_inode; /* For directories it's -EISDIR, for other non-regulars - -EINVAL */ @@ -170,6 +175,7 @@ put_write_access(inode); dput_and_out: + audit_truncate(nd.dentry->d_name.name,(char *)NULL,length,error); path_release(&nd); out: return error; @@ -189,12 +195,16 @@ int error; error = -EINVAL; - if (length < 0) + if (length < 0) { + audit_truncate((char *)NULL,(char *)NULL,length,error); goto out; + } error = -EBADF; file = fget(fd); - if (!file) + if (!file) { + audit_truncate((char *)NULL,(char *)NULL,length,error); goto out; + } /* explicitly opened as large or we are on 64-bit box */ if (file->f_flags & O_LARGEFILE) @@ -202,6 +212,7 @@ dentry = file->f_dentry; inode = dentry->d_inode; + error = -EINVAL; if (!S_ISREG(inode->i_mode) || !(file->f_mode & FMODE_WRITE)) goto out_putf; @@ -219,6 +230,7 @@ if (!error) error = do_truncate(dentry, length); out_putf: + audit_truncate(file->f_dentry->d_name.name,(char *)NULL,length,error); fput(file); out: return error; @@ -452,10 +464,13 @@ int error; struct nameidata nd; + error = __user_walk(filename, LOOKUP_POSITIVE | LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd); - if (error) + if (error) { + audit_chroot((char *)NULL,filename,error); goto out; + } error = permission(nd.dentry->d_inode,MAY_EXEC); if (error) @@ -469,6 +484,7 @@ set_fs_altroot(); error = 0; dput_and_out: + audit_chroot(nd.dentry->d_name.name,(char *)NULL,error); path_release(&nd); out: return error; @@ -483,8 +499,10 @@ struct iattr newattrs; file = fget(fd); - if (!file) + if (!file) { + audit_chmod((char *)NULL, (char *)NULL, mode,err); goto out; + } dentry = file->f_dentry; inode = dentry->d_inode; @@ -502,6 +520,7 @@ err = notify_change(dentry, &newattrs); out_putf: + audit_chmod(file->f_dentry->d_name.name, (char *)NULL, mode, err); fput(file); out: return err; @@ -514,9 +533,12 @@ int error; struct iattr newattrs; + error = user_path_walk(filename, &nd); - if (error) + if (error) { + audit_chmod((char *)NULL,filename,mode,error); goto out; + } inode = nd.dentry->d_inode; error = -EROFS; @@ -534,6 +556,7 @@ error = notify_change(nd.dentry, &newattrs); dput_and_out: + audit_chmod(nd.dentry->d_name.name,(char *)NULL,mode,error); path_release(&nd); out: return error; @@ -604,10 +627,14 @@ struct nameidata nd; int error; + error = user_path_walk(filename, &nd); if (!error) { error = chown_common(nd.dentry, user, group); + audit_chown(nd.dentry->d_name.name,(char *)NULL,user,group,error); path_release(&nd); + } else { + audit_chown((char *)NULL,filename,user,group,error); } return error; } @@ -617,10 +644,14 @@ struct nameidata nd; int error; + error = user_path_walk_link(filename, &nd); if (!error) { error = chown_common(nd.dentry, user, group); + audit_chown(nd.dentry->d_name.name,(char *)NULL,user,group,error); path_release(&nd); + } else { + audit_chown((char *)NULL,filename,user,group,error); } return error; } @@ -634,7 +665,10 @@ file = fget(fd); if (file) { error = chown_common(file->f_dentry, user, group); + audit_chown(file->f_dentry->d_name.name,(char *)NULL,user,group,error); fput(file); + } else { + audit_chown((char *)NULL,(char *)NULL,user,group,error); } return error; } @@ -805,16 +839,20 @@ #endif tmp = getname(filename); fd = PTR_ERR(tmp); - if (!IS_ERR(tmp)) { + if (IS_ERR(tmp)) { + audit_open((char *)NULL,(char *)NULL,flags,mode,fd); + } else { fd = get_unused_fd(); if (fd >= 0) { struct file *f = filp_open(tmp, flags, mode); error = PTR_ERR(f); - if (IS_ERR(f)) + if (IS_ERR(f)) { goto out_error; + } fd_install(fd, f); } out: + audit_open(tmp,(char *)NULL,flags,mode,fd); putname(tmp); } return fd; diff -N -u -r kernel-source-2.4.25/include/linux/audit.h kernel-source-2.4.25-snare/include/linux/audit.h --- kernel-source-2.4.25/include/linux/audit.h 1969-12-31 19:00:00.000000000 -0500 +++ kernel-source-2.4.25-snare/include/linux/audit.h 2004-07-20 16:27:35.000000000 -0400 @@ -0,0 +1,500 @@ +/* + * linux/audit/audit.h + * + * Original: + * Copyright (c) 1999-2004 InterSect Alliance Pty Ltd + * - http://www.intersectalliance.com/ + * Additions: + * Copyright (c) 2004 Silicon Graphics, Inc. All rights reserved. + */ + +#ifndef __C2_AUDIT_H +#define __C2_AUDIT_H + +// If the user has not turned on C2 Auditing, define all 'public' routines out. + +#if defined(CONFIG_C2_AUDIT) + +// I was going to use __NR_xxx, but we need audit events for events that +// may NOT be system calls specifically (eg: login, connect/accept) +#define AUDIT_open 1 +#define AUDIT_mkdir 2 +#define AUDIT_unlink 3 +#define AUDIT_rmdir 4 +#define AUDIT_chown 5 +#define AUDIT_chmod 6 +#define AUDIT_symlink 7 +#define AUDIT_link 8 +#define AUDIT_rename 9 +#define AUDIT_mknod 10 +#define AUDIT_truncate 11 +#define AUDIT_ftruncate 12 +#define AUDIT_chroot 13 +#define AUDIT_execve 14 +#define AUDIT_exit 15 +#define AUDIT_setuid 16 +#define AUDIT_setreuid 17 +#define AUDIT_setresuid 18 +#define AUDIT_setgid 19 +#define AUDIT_setregid 20 +#define AUDIT_setresgid 21 +#define AUDIT_create_module 22 +#define AUDIT_delete_module 23 +#define AUDIT_reboot 24 +#define AUDIT_connect 25 +#define AUDIT_accept 26 +#define AUDIT_mount 27 +#define AUDIT_umount 28 +#define AUDIT_fork 29 + +// Size of the bitmask array that we need to store the information +// associated with whether an audit event is currently turned on. +#define MAXAUDIT AUDIT_fork + +// ioctl modes - note that '1' doesnt seem to work. Added 10. +#define AUDIT_STOP 10 // stop auditing +#define AUDIT_START 11 // start auditing +#define AUDIT_INFO 12 // Give me a list of events + // currently active, and other + // info such as the process ID +#define AUDIT_LOSTEVENTS 13 +#define AUDIT_FLUSH 14 // Stop all events. +#define AUDIT_EVENT_ON 15 // Turn on a selected event +#define AUDIT_EVENT_OFF 16 // Turn off a selected event +#define AUDIT_DELIVERY 17 // Do we want to guarantee audit event delivery +#define AUDIT_TOTALEVENTS 18 // How many events have been received this session? + +#define AUDIT_HIGHWATERMARK_MEM 19 // Set the High Water Mark memory usage +#define AUDIT_HIGHWATERMARK_PER 20 // Set the High Water Mark memory as a percentage mem. +#define AUDIT_HIGHWATERMARK_PAUSE 21 // Set the High Water Mark pause percetage +#define AUDIT_LOWWATERMARK_PAUSE 22 // Set the Low Water Mark to resume +#define AUDIT_HIGHWATERMARK_NICE 23 // Set the High Water Mark to change nice value +#define AUDIT_LOWWATERMARK_NICE 24 // Set the Low Water Mark to restore nice value +#define AUDIT_HIGHWATER_NICE_VAL 25 // The nice value to change the audit daemon to + + + + + +#define AUDIT_CLASS_NONE 0 +#define AUDIT_CLASS_IO 1 // Input/output (file opens) +#define AUDIT_CLASS_PC 2 // Process Control +#define AUDIT_CLASS_EXEC 3 // Execution +#define AUDIT_CLASS_NET 4 // Network related +#define AUDIT_CLASS_ADMIN 5 // Administrative events +#define AUDIT_CLASS_CH 6 // CHMOD event. Might not use this for anything else. +#define AUDIT_CLASS_CP 7 // Where more than one pathname is required +#define AUDIT_CLASS_SU 8 // SetUID +#define AUDIT_CLASS_AD 9 // Admin such as create/delete module + +#define SNAREAUDIT_MAJOR_VERSION 0 +#define SNAREAUDIT_MINOR_VERSION 9 +#define SNAREAUDIT_PATCH_VERSION 6 + + +// /proc entry +#define AUDITDEV_NAME "audit" // device name in /dev and /proc/devices +#define AUDITINFO_NAME "auditinfo" // Information about the process +#define AUDITDEV_FILE "/proc/audit" // full file name +#define AUDITINFO_FILE "/proc/auditinfo" // Information about the process. +#define MAX_PATH 512 // NOTE: will migrgate this to PATH_MAX eventually +#define MAXCOMMAND 25 + + +// This contains the details that are common to ALL audit events. +typedef struct +{ + unsigned short event_class; // event class. Each class has a predictable format for tokens. + unsigned short event_id; // number of the event + unsigned short event_size; // size of the event struct - don't include header + // since it's always the same + struct timeval time; // time + + int user_id; // User ID + int euser_id; // Effective User ID + int group_id; // Group ID + int egroup_id; // Effective Group ID + + int returncode; // Make sure that this is big enough to contain the largest returncode. + + pid_t pid; // process ID. + pid_t ppid; // Parent process ID. + char processname[MAXCOMMAND]; // Same as in /usr/include/linux/sched.h for current->comm +} header_token; + +typedef struct +{ + char path[MAX_PATH]; +} path_token; + +typedef struct +{ + int mode; // How the file was attempted to be opened or created + unsigned long createmode; // Flags associated with the file creation. Ulong for mknod. +} attributes_token; + +typedef struct +{ + int owner; // new owner of a file - was uid_t, but these are different between kernel and user. + int group; // new group of a file +} owner_token; + +typedef struct +{ + char args[MAX_PATH]; // Should really allocate more here. Whats is the max command line size? +} execargs_token; + +// System calls like setuid +typedef struct +{ + int id; // uid/gid/euid depending on the call + int rid; // ruid/rgid + int sid; // suid/sgid +} target_token; + +// Network connections +typedef struct +{ + char src_ip[40]; // String containing source dotted ip address - 40 bytes, for IPv6 + int src_port; // Source port + char dst_ip[40]; // String containing destination dotted ip address - 40 bytes, for IPv6 + int dst_port; // Destination port + int protocol; // Protocol type - IPPROTO_UDP or IPPROTO_TCP +} connection_token; + + + +// Now for the audit event classes + +// Just a bare class with the minimal data +// note that this will mean that EVERY class must start with header_token +typedef struct +{ + header_token t_header; +} null_class; + + +// NOTE: ANY CLASS STRUCTURE SHOULD HAVE THE RETURN TOKEN AS THE SECOND ELEMENT. +// SEE AUDITD FOR MORE INFO. +// io - reads/writes +typedef struct +{ + header_token t_header; + path_token t_path; + path_token t_pwd; // Working directory + attributes_token t_attributes; +} io_class; + +typedef struct +{ + header_token t_header; + path_token t_path; + path_token t_pwd; // Working directory + owner_token t_owner; +} ch_class; + +typedef struct +{ + header_token t_header; + path_token t_path; + path_token t_pwd; // Working directory + execargs_token t_execargs; + // environment variables too? +} ex_class; + +typedef struct +{ + header_token t_header; +} pc_class; + +// copy one file to another (amongst others - eg: symlink) +typedef struct +{ + header_token t_header; + path_token t_sourcepath; + path_token t_pwd; // Working directory + path_token t_destpath; +} cp_class; + +typedef struct +{ + header_token t_header; + target_token t_target; // target UID or GID.. I really only need a single value here. +} su_class; + +typedef struct +{ + header_token t_header; + connection_token t_connection; +} nt_class; // Network + +typedef struct +{ + header_token t_header; + path_token t_name; // Name of the module loaded / removed +} ad_class; // General Administrative + +struct _auditnode +{ + void * location; // Location in RAM of the allocated chunk + int size; // Size of the chunk + struct _auditnode *next; // Next node in the series. +}; + +typedef struct _auditnode AuditNode; + + +#ifdef __KERNEL__ +#include + +int _audit_mknod(const char * kfile, const char * ufile, int mode, dev_t dev, int retval); +int _audit_execve(const char * kfilename, const char * ufilename, char *arguments, int retval); +// _Add this back in.. +// _char *audit_copy_exec_strings(char **argv); +int _audit_exit(int retval); +int _audit_fork(int retval); +int _audit_open(const char * kfile,const char *ufile, int flags, int mode, int retval); +int _audit_mkdir(const char * kfile, const char * ufile, int mode, int retval); +int _audit_unlink(const char * kfile,const char * ufile, int retval); +int _audit_rmdir(const char * kfile, const char * ufile, int retval); +int _audit_chown(const char * kfile,const char * ufile, uid_t user, gid_t group, int retval); +int _audit_chmod(const char * kfile, const char * ufile, mode_t mode, int retval); +int _audit_symlink(const char * kfrom,const char * ufrom, const char * kto,const char * uto, int retval); +int _audit_link(const char * kfrom,const char * ufrom, const char * kto,const char * uto, int retval); +int _audit_rename(const char * kfrom,const char * ufrom, const char * kto, const char * uto, int retval); +int _audit_truncate(const char * kfile,const char * ufile, loff_t length, int retval); +int _audit_ftruncate(const char * file, loff_t length, int retval); +int _audit_chroot(const char * kfile, const char * ufile, int retval); +int _audit_setuid(uid_t uid, int retval); +int _audit_setreuid(uid_t ruid, uid_t euid, int retval); +int _audit_setresuid(uid_t ruid, uid_t euid, uid_t suid, int retval); +int _audit_setgid(gid_t gid, int retval); +int _audit_setregid(gid_t rgid, gid_t egid, int retval); +int _audit_setresgid(gid_t rgid, gid_t egid, gid_t sgid, int retval); +int _audit_create_module(const char * kname, const char * uname, int retval); +int _audit_delete_module(const char * kname, const char * uname, int retval); +int _audit_reboot(int magic1, int magic2, unsigned int cmd, void * arg, int retval); +int _audit_connect(int sockfd, struct sockaddr *serv_addr, int addrlen, int retval); +int _audit_accept(int sockfd, struct sockaddr *serv_addr, int *addrlen, int retval); +int _audit_mount(const char *kdev_name, const char *udev_name, const char *kdir_name, const char *udir_name, unsigned long flags, int retval); +int _audit_umount(const char *kname, const char *uname, int flags, int retval); + +void audit_init(void); +char * audit_copy_argv(char **argv); + +extern int AUDIT_IS_RUNNING; + +// Inline routines in order to speed things up a little. +static inline int audit_mknod(const char * kfile, const char * ufile, int mode, dev_t dev, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_mknod(kfile,ufile,mode,dev,retval)); + else + return(0); +} +static inline int audit_execve(const char * kfilename, const char * ufilename, char *arguments, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_execve(kfilename,ufilename,arguments,retval)); + else + return(0); +} +static inline int audit_exit(int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_exit(retval)); + else + return(0); +} +static inline int audit_fork(int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_fork(retval)); + else + return(0); +} +static inline int audit_open(const char * kfile,const char *ufile, int flags, int mode, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_open(kfile,ufile,flags,mode,retval)); + else + return(0); +} +static inline int audit_mkdir(const char * kfile, const char * ufile, int mode, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_mkdir(kfile,ufile,mode,retval)); + else + return(0); +} +static inline int audit_unlink(const char * kfile,const char * ufile, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_unlink(kfile,ufile,retval)); + else + return(0); +} +static inline int audit_rmdir(const char * kfile, const char * ufile, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_rmdir(kfile,ufile,retval)); + else + return(0); +} +static inline int audit_chown(const char * kfile,const char * ufile, uid_t user, gid_t group, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_chown(kfile,ufile,user,group,retval)); + else + return(0); +} +static inline int audit_chmod(const char * kfile, const char * ufile, mode_t mode, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_chmod(kfile,ufile,mode,retval)); + else + return(0); +} +static inline int audit_symlink(const char * kfrom,const char * ufrom, const char * kto,const char * uto, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_symlink(kfrom,ufrom,kto,uto,retval)); + else + return(0); +} +static inline int audit_link(const char * kfrom,const char * ufrom, const char * kto,const char * uto, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_link(kfrom,ufrom,kto,uto,retval)); + else + return(0); +} +static inline int audit_rename(const char * kfrom,const char * ufrom, const char * kto, const char * uto, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_rename(kfrom,ufrom,kto,uto,retval)); + else + return(0); +} +static inline int audit_truncate(const char * kfile,const char * ufile, loff_t length, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_truncate(kfile,ufile,length,retval)); + else + return(0); +} +static inline int audit_ftruncate(const char * file, loff_t length, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_ftruncate(file,length,retval)); + else + return(0); +} +static inline int audit_chroot(const char * kfile, const char * ufile, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_chroot(kfile,ufile,retval)); + else + return(0); +} +static inline int audit_setuid(uid_t uid, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_setuid(uid,retval)); + else + return(0); +} +static inline int audit_setreuid(uid_t ruid, uid_t euid, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_setreuid(ruid,euid,retval)); + else + return(0); +} +static inline int audit_setresuid(uid_t ruid, uid_t euid, uid_t suid, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_setresuid(ruid,euid,suid,retval)); + else + return(0); +} +static inline int audit_setgid(gid_t gid, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_setgid(gid,retval)); + else + return(0); +} +static inline int audit_setregid(gid_t rgid, gid_t egid, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_setregid(rgid,egid,retval)); + else + return(0); +} +static inline int audit_setresgid(gid_t rgid, gid_t egid, gid_t sgid, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_setresgid(rgid,egid,sgid,retval)); + else + return(0); +} +static inline int audit_create_module(const char * kname, const char * uname, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_create_module(kname,uname,retval)); + else + return(0); +} +static inline int audit_delete_module(const char * kname, const char * uname, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_delete_module(kname,uname,retval)); + else + return(0); +} +static inline int audit_reboot(int magic1, int magic2, unsigned int cmd, void * arg, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_reboot(magic1,magic2,cmd,arg,retval)); + else + return(0); +} +static inline int audit_connect(int sockfd, struct sockaddr *serv_addr, int addrlen, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_connect(sockfd,serv_addr,addrlen,retval)); + else + return(0); +} +static inline int audit_accept(int sockfd, struct sockaddr *serv_addr, int *addrlen, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_accept(sockfd,serv_addr,addrlen,retval)); + else + return(0); +} +static inline int audit_mount(const char *kdev_name, const char *udev_name, const char *kdir_name, const char *udir_name, unsigned long flags, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_mount(kdev_name,udev_name,kdir_name,udir_name,flags,retval)); + else + return(0); +} +static inline int audit_umount(const char *kname, const char *uname, int flags, int retval) { + if (unlikely(AUDIT_IS_RUNNING)) + return (_audit_umount(kname,uname,flags,retval)); + else + return(0); +} + +#endif /* __KERNEL__ */ + +#else /* CONFIG_C2_AUDIT */ + +#ifdef __KERNEL__ +static inline int audit_mknod(const char * kfile, const char * ufile, int mode, dev_t dev, int retval) {return(0);} +static inline char * audit_copy_argv(char **argv) {return(0);} +static inline int audit_execve(const char * kfilename, const char * ufilename, char *arguments, int retval) {return(0);} +static inline int audit_exit(int retval) {return(0);} +static inline int audit_fork(int retval) {return(0);} +static inline int audit_open(const char * kfile,const char *ufile, int flags, int mode, int retval) {return(0);} +static inline int audit_mkdir(const char * kfile, const char * ufile, int mode, int retval) {return(0);} +static inline int audit_unlink(const char * kfile,const char * ufile, int retval) {return(0);} +static inline int audit_rmdir(const char * kfile, const char * ufile, int retval) {return(0);} +static inline int audit_chown(const char * kfile,const char * ufile, uid_t user, gid_t group, int retval) {return(0);} +static inline int audit_chmod(const char * kfile, const char * ufile, mode_t mode, int retval) {return(0);} +static inline int audit_symlink(const char * kfrom,const char * ufrom, const char * kto,const char * uto, int retval) {return(0);} +static inline int audit_link(const char * kfrom,const char * ufrom, const char * kto,const char * uto, int retval) {return(0);} +static inline int audit_rename(const char * kfrom,const char * ufrom, const char * kto, const char * uto, int retval) {return(0);} +static inline int audit_truncate(const char * kfile,const char * ufile, loff_t length, int retval) {return(0);} +static inline int audit_ftruncate(const char * file, loff_t length, int retval) {return(0);} +static inline int audit_chroot(const char * kfile, const char * ufile, int retval) {return(0);} +static inline int audit_setuid(uid_t uid, int retval) {return(0);} +static inline int audit_setreuid(uid_t ruid, uid_t euid, int retval) {return(0);} +static inline int audit_setresuid(uid_t ruid, uid_t euid, uid_t suid, int retval) {return(0);} +static inline int audit_setgid(gid_t gid, int retval) {return(0);} +static inline int audit_setregid(gid_t rgid, gid_t egid, int retval) {return(0);} +static inline int audit_setresgid(gid_t rgid, gid_t egid, gid_t sgid, int retval) {return(0);} +static inline int audit_create_module(const char * kname, const char * uname, int retval) {return(0);} +static inline int audit_delete_module(const char * kname, const char * uname, int retval) {return(0);} +static inline int audit_reboot(int magic1, int magic2, unsigned int cmd, void * arg, int retval) {return(0);} +static inline int audit_connect(int sockfd, struct sockaddr *serv_addr, int addrlen, int retval) {return(0);} +static inline int audit_accept(int sockfd, struct sockaddr *serv_addr, int *addrlen, int retval) {return(0);} +static inline int audit_mount(const char *kdev_name, const char *udev_name, const char *kdir_name, const char *udir_name, unsigned long flags, int retval) {return(0);} +static inline int audit_umount(const char *kname, const char *uname, int flags, int retval) {return(0);} +#endif /* KERNEL */ +#endif /* CONFIG_C2_AUDIT */ +#endif /* __C2_AUDIT_H */ diff -N -u -r kernel-source-2.4.25/include/linux/sched.h kernel-source-2.4.25-snare/include/linux/sched.h --- kernel-source-2.4.25/include/linux/sched.h 2004-02-22 04:28:34.000000000 -0500 +++ kernel-source-2.4.25-snare/include/linux/sched.h 2004-07-20 16:27:35.000000000 -0400 @@ -415,6 +415,12 @@ /* journalling filesystem info */ void *journal_info; + +#ifdef CONFIG_C2_AUDIT + /* Audit record pointer */ + void *audit_record; +#endif + }; /* diff -N -u -r kernel-source-2.4.25/init/main.c kernel-source-2.4.25-snare/init/main.c --- kernel-source-2.4.25/init/main.c 2003-11-29 04:53:51.000000000 -0500 +++ kernel-source-2.4.25-snare/init/main.c 2004-07-20 16:27:35.000000000 -0400 @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -443,6 +444,9 @@ #ifdef CONFIG_PROC_FS proc_root_init(); #endif +#if defined(CONFIG_C2_AUDIT) + audit_init(); +#endif check_bugs(); printk("POSIX conformance testing by UNIFIX\n"); diff -N -u -r kernel-source-2.4.25/kernel/exit.c kernel-source-2.4.25-snare/kernel/exit.c --- kernel-source-2.4.25/kernel/exit.c 2002-11-28 18:53:15.000000000 -0500 +++ kernel-source-2.4.25-snare/kernel/exit.c 2004-07-20 16:27:35.000000000 -0400 @@ -13,6 +13,7 @@ #include #include #include +#include #ifdef CONFIG_BSD_PROCESS_ACCT #include #endif @@ -486,6 +487,7 @@ asmlinkage long sys_exit(int error_code) { + audit_exit(error_code); do_exit((error_code&0xff)<<8); } diff -N -u -r kernel-source-2.4.25/kernel/fork.c kernel-source-2.4.25-snare/kernel/fork.c --- kernel-source-2.4.25/kernel/fork.c 2004-02-22 04:28:35.000000000 -0500 +++ kernel-source-2.4.25-snare/kernel/fork.c 2004-07-20 16:27:35.000000000 -0400 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -640,11 +641,16 @@ struct pt_regs *regs, unsigned long stack_size) { int retval; +#ifdef CONFIG_C2_AUDIT + int auditretval=0; +#endif struct task_struct *p; struct completion vfork; - if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) + if ((clone_flags & (CLONE_NEWNS|CLONE_FS)) == (CLONE_NEWNS|CLONE_FS)) { + audit_fork(-1); return -EINVAL; + } retval = -EPERM; @@ -664,6 +670,10 @@ *p = *current; +#ifdef CONFIG_C2_AUDIT + p->audit_record = NULL; +#endif + retval = -EAGAIN; /* * Check if we are over our maximum process limit, but be sure to @@ -788,6 +798,9 @@ */ retval = p->pid; p->tgid = retval; +#ifdef CONFIG_C2_AUDIT + auditretval = 0; +#endif INIT_LIST_HEAD(&p->thread_group); /* Need tasklist lock for parent etc handling! */ @@ -821,6 +834,13 @@ wait_for_completion(&vfork); fork_out: +#ifdef CONFIG_C2_AUDIT + if (auditretval == -1) + audit_fork(-1); + else + audit_fork(p->pid); +#endif + return retval; bad_fork_cleanup_namespace: @@ -842,6 +862,9 @@ free_uid(p->user); bad_fork_free: free_task_struct(p); +#ifdef CONFIG_C2_AUDIT + auditretval = -1; +#endif goto fork_out; } diff -N -u -r kernel-source-2.4.25/kernel/module.c kernel-source-2.4.25-snare/kernel/module.c --- kernel-source-2.4.25/kernel/module.c 2003-09-03 06:27:20.000000000 -0400 +++ kernel-source-2.4.25-snare/kernel/module.c 2004-07-20 16:27:35.000000000 -0400 @@ -10,6 +10,7 @@ #include #include #include +#include /* * Originally by Anonymous (as far as I know...) @@ -296,11 +297,15 @@ struct module *mod; unsigned long flags; - if (!capable(CAP_SYS_MODULE)) + if (!capable(CAP_SYS_MODULE)) { + audit_create_module((char *)NULL,name_user,-EPERM); return -EPERM; + } + lock_kernel(); if ((namelen = get_mod_name(name_user, &name)) < 0) { error = namelen; + audit_create_module((char *)NULL,name_user,error); goto err0; } if (size < sizeof(struct module)+namelen+1) { @@ -322,16 +327,17 @@ mod->size = size; memcpy((char*)(mod+1), name, namelen+1); - put_mod_name(name); - spin_lock_irqsave(&modlist_lock, flags); mod->next = module_list; module_list = mod; /* link it in */ spin_unlock_irqrestore(&modlist_lock, flags); error = (long) mod; + audit_create_module(name,(char *)NULL,error); + put_mod_name(name); goto err0; err1: + audit_create_module(name,(char *)NULL,error); put_mod_name(name); err0: unlock_kernel(); @@ -612,13 +618,17 @@ long error; int something_changed; - if (!capable(CAP_SYS_MODULE)) + + if (!capable(CAP_SYS_MODULE)) { + audit_delete_module((char *)NULL,name_user,-EPERM); return -EPERM; + } lock_kernel(); if (name_user) { - if ((error = get_mod_name(name_user, &name)) < 0) + if ((error = get_mod_name(name_user, &name)) < 0) { goto out; + } error = -ENOENT; if ((mod = find_module(name)) == NULL) { put_mod_name(name); @@ -626,8 +636,9 @@ } put_mod_name(name); error = -EBUSY; - if (mod->refs != NULL) + if (mod->refs != NULL) { goto out; + } spin_lock(&unload_lock); if (!__MOD_IN_USE(mod)) { @@ -678,6 +689,8 @@ error = 0; out: unlock_kernel(); + + audit_delete_module((char *)NULL,name_user,error); return error; } diff -N -u -r kernel-source-2.4.25/kernel/sys.c kernel-source-2.4.25-snare/kernel/sys.c --- kernel-source-2.4.25/kernel/sys.c 2003-11-29 04:53:52.000000000 -0500 +++ kernel-source-2.4.25-snare/kernel/sys.c 2004-07-20 16:27:35.000000000 -0400 @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -291,15 +292,22 @@ char buffer[256]; /* We only trust the superuser with rebooting the system. */ - if (!capable(CAP_SYS_BOOT)) + if (!capable(CAP_SYS_BOOT)) { + audit_reboot(magic1,magic2,cmd,arg,-EPERM); return -EPERM; + } /* For safety, we require "magic" arguments. */ if (magic1 != LINUX_REBOOT_MAGIC1 || (magic2 != LINUX_REBOOT_MAGIC2 && magic2 != LINUX_REBOOT_MAGIC2A && - magic2 != LINUX_REBOOT_MAGIC2B)) + magic2 != LINUX_REBOOT_MAGIC2B)) { + audit_reboot(magic1,magic2,cmd,arg,-EINVAL); return -EINVAL; + } + // Try and audit before we go down. + audit_reboot(magic1,magic2,cmd,arg,0); + lock_kernel(); switch (cmd) { case LINUX_REBOOT_CMD_RESTART: @@ -399,13 +407,16 @@ int new_rgid = old_rgid; int new_egid = old_egid; + if (rgid != (gid_t) -1) { if ((old_rgid == rgid) || (current->egid==rgid) || capable(CAP_SETGID)) new_rgid = rgid; - else + else { + audit_setregid(rgid,egid,-EPERM); return -EPERM; + } } if (egid != (gid_t) -1) { if ((old_rgid == egid) || @@ -414,6 +425,7 @@ capable(CAP_SETGID)) new_egid = egid; else { + audit_setregid(rgid,egid,-EPERM); return -EPERM; } } @@ -428,6 +440,8 @@ current->fsgid = new_egid; current->egid = new_egid; current->gid = new_rgid; + + audit_setregid(rgid,egid,0); return 0; } @@ -439,9 +453,10 @@ asmlinkage long sys_setgid(gid_t gid) { int old_egid = current->egid; - + if (capable(CAP_SETGID)) { + audit_setgid(gid,0); if(old_egid != gid) { current->mm->dumpable=0; @@ -451,6 +466,7 @@ } else if ((gid == current->gid) || (gid == current->sgid)) { + audit_setgid(gid,0); if(old_egid != gid) { current->mm->dumpable=0; @@ -459,7 +475,11 @@ current->egid = current->fsgid = gid; } else + { + audit_setgid(gid,-EPERM); return -EPERM; + } + audit_setgid(gid,0); return 0; } @@ -554,8 +574,10 @@ new_ruid = ruid; if ((old_ruid != ruid) && (current->euid != ruid) && - !capable(CAP_SETUID)) + !capable(CAP_SETUID)) { + audit_setreuid(ruid,euid,-EPERM); return -EPERM; + } } if (euid != (uid_t) -1) { @@ -563,12 +585,18 @@ if ((old_ruid != euid) && (current->euid != euid) && (current->suid != euid) && - !capable(CAP_SETUID)) + !capable(CAP_SETUID)) { + audit_setreuid(ruid,euid,-EPERM); return -EPERM; + } } - if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0) + if (new_ruid != old_ruid && set_user(new_ruid, new_euid != old_euid) < 0) { + audit_setreuid(ruid,euid,-EAGAIN); return -EAGAIN; + } + + audit_setreuid(ruid,euid,0); // Before current->*id is changed if (new_euid != old_euid) { @@ -606,17 +634,24 @@ int old_euid = current->euid; int old_ruid, old_suid, new_ruid, new_suid; + old_ruid = new_ruid = current->uid; old_suid = current->suid; new_suid = old_suid; if (capable(CAP_SETUID)) { - if (uid != old_ruid && set_user(uid, old_euid != uid) < 0) + if (uid != old_ruid && set_user(uid, old_euid != uid) < 0) { + audit_setuid(uid,-EAGAIN); return -EAGAIN; + } new_suid = uid; - } else if ((uid != current->uid) && (uid != new_suid)) + } else if ((uid != current->uid) && (uid != new_suid)) { + audit_setuid(uid,-EPERM); return -EPERM; - + } + + audit_setuid(uid,0); // Before current->*id is changed + if (old_euid != uid) { current->mm->dumpable = 0; @@ -645,19 +680,30 @@ if (!capable(CAP_SETUID)) { if ((ruid != (uid_t) -1) && (ruid != current->uid) && - (ruid != current->euid) && (ruid != current->suid)) + (ruid != current->euid) && (ruid != current->suid)) { + audit_setresuid(ruid,euid,suid,-EPERM); return -EPERM; + } if ((euid != (uid_t) -1) && (euid != current->uid) && - (euid != current->euid) && (euid != current->suid)) + (euid != current->euid) && (euid != current->suid)) { + audit_setresuid(ruid,euid,suid,-EPERM); return -EPERM; + } if ((suid != (uid_t) -1) && (suid != current->uid) && - (suid != current->euid) && (suid != current->suid)) + (suid != current->euid) && (suid != current->suid)) { + audit_setresuid(ruid,euid,suid,-EPERM); return -EPERM; + } } if (ruid != (uid_t) -1) { - if (ruid != current->uid && set_user(ruid, euid != current->euid) < 0) + if (ruid != current->uid && set_user(ruid, euid != current->euid) < 0) { + audit_setresuid(ruid,euid,suid,-EAGAIN); return -EAGAIN; + } } + + audit_setresuid(ruid,euid,suid,0); // Before current->uids change + if (euid != (uid_t) -1) { if (euid != current->euid) { @@ -695,15 +741,24 @@ { if (!capable(CAP_SETGID)) { if ((rgid != (gid_t) -1) && (rgid != current->gid) && - (rgid != current->egid) && (rgid != current->sgid)) + (rgid != current->egid) && (rgid != current->sgid)) { + audit_setresgid(rgid,egid,sgid,-EPERM); return -EPERM; + } if ((egid != (gid_t) -1) && (egid != current->gid) && - (egid != current->egid) && (egid != current->sgid)) + (egid != current->egid) && (egid != current->sgid)) { + audit_setresgid(rgid,egid,sgid,-EPERM); return -EPERM; + } if ((sgid != (gid_t) -1) && (sgid != current->gid) && - (sgid != current->egid) && (sgid != current->sgid)) + (sgid != current->egid) && (sgid != current->sgid)) { + audit_setresgid(rgid,egid,sgid,-EPERM); return -EPERM; + } } + + audit_setresgid(rgid,egid,sgid,0); // Before our current process UIDs change + if (egid != (gid_t) -1) { if (egid != current->egid) { diff -N -u -r kernel-source-2.4.25/net/socket.c kernel-source-2.4.25-snare/net/socket.c --- kernel-source-2.4.25/net/socket.c 2004-02-22 04:28:35.000000000 -0500 +++ kernel-source-2.4.25-snare/net/socket.c 2004-07-20 16:27:35.000000000 -0400 @@ -44,6 +44,7 @@ * Tigran Aivazian : sys_send(args) calls sys_sendto(args, NULL, 0) * Tigran Aivazian : Made listen(2) backlog sanity checks * protocol-independent + * Leigh Purdie : Socketcall auditing. * * * This program is free software; you can redistribute it and/or @@ -74,6 +75,8 @@ #include #include #include +#include + #if defined(CONFIG_KMOD) && defined(CONFIG_NET) #include @@ -1561,12 +1564,14 @@ break; case SYS_CONNECT: err = sys_connect(a0, (struct sockaddr *)a1, a[2]); + audit_connect(a0, (struct sockaddr *)a1, a[2],err); break; case SYS_LISTEN: err = sys_listen(a0,a1); break; case SYS_ACCEPT: err = sys_accept(a0,(struct sockaddr *)a1, (int *)a[2]); + audit_accept(a0, (struct sockaddr *)a1, (int *)a[2],err); break; case SYS_GETSOCKNAME: err = sys_getsockname(a0,(struct sockaddr *)a1, (int *)a[2]);