Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751210AbcDDEDi (ORCPT ); Mon, 4 Apr 2016 00:03:38 -0400 Received: from mail-pf0-f177.google.com ([209.85.192.177]:33668 "EHLO mail-pf0-f177.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750753AbcDDEDg (ORCPT ); Mon, 4 Apr 2016 00:03:36 -0400 From: wmealing X-Google-Original-From: wmealing To: linux-audit@redhat.com Cc: linux-kernel@vger.kernel.org, linux-usb@vger.kernel.org, Wade Mealing Subject: [RFC] Create an audit record of USB specific details Date: Mon, 4 Apr 2016 00:02:42 -0400 Message-Id: <1459742562-22803-1-git-send-email-wmail@redhat.com> X-Mailer: git-send-email 1.8.3.1 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6128 Lines: 188 From: Wade Mealing Gday, I'm looking to create an audit trail for when devices are added or removed from the system. The audit subsystem is a logging subsystem in kernel space that can be used to create advanced filters on generated events. It has partnered userspace utilities ausearch, auditd, aureport, auditctl which work exclusively on audit records. These tools are able to set filters to "trigger" on specific in-kernel events specified by privileged users. While the userspace tools can create audit events these are not able to be handled intelligently (decoded,filtered or ignored) as kernel generated audit events are. I have this working at the moment with the USB subsystem (as an example). Its been suggested that I use systemd-udev however this means that the audit tools (ausearch) will not be able to index these records. Here is an example of picking out the AUDIT_DEVICE record type for example. > # ausearch -l -i -ts today -m AUDIT_DEVICE > ---- > type=AUDIT_DEVICE msg=audit(31/03/16 16:37:15.642:2) : action=add > manufacturer=Linux 4.4.0-ktest ehci_hcd product=EHCI Host Controller > serial=0000:00:06.7 major=189 minor=0 bus="usb" Admittedly this is only the USB device type at the moment, but I'd like to break this out into other bus types at some time in the future, gotta start somewhere. Thanks, Wade Mealing --- include/uapi/linux/audit.h | 1 + init/Kconfig | 10 ++++++ kernel/Makefile | 1 + kernel/audit_device.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 102 insertions(+) create mode 100644 kernel/audit_device.c diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h index 843540c..344c97b 100644 --- a/include/uapi/linux/audit.h +++ b/include/uapi/linux/audit.h @@ -110,6 +110,7 @@ #define AUDIT_SECCOMP 1326 /* Secure Computing event */ #define AUDIT_PROCTITLE 1327 /* Proctitle emit event */ #define AUDIT_FEATURE_CHANGE 1328 /* audit log listing feature changes */ +#define AUDIT_DEVICE_CHANGE 1330 /* Device added/removed to the system */ #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ diff --git a/init/Kconfig b/init/Kconfig index 2232080..e171f74 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -309,6 +309,16 @@ config AUDITSYSCALL def_bool y depends on AUDIT && HAVE_ARCH_AUDITSYSCALL +config DEVICE_AUDIT + bool "Create audit records for devices added to the systems" + depends on AUDIT && USB + default y + help + Generate audit events in the system for USB devices that + are added or removed from the system from boot time onwards. + Records the manufacturer, product serial number, device major + and minor number and bus which the device was added to. + config AUDIT_WATCH def_bool y depends on AUDITSYSCALL diff --git a/kernel/Makefile b/kernel/Makefile index 53abf00..909c869 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -68,6 +68,7 @@ obj-$(CONFIG_AUDIT) += audit.o auditfilter.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o obj-$(CONFIG_AUDIT_WATCH) += audit_watch.o audit_fsnotify.o obj-$(CONFIG_AUDIT_TREE) += audit_tree.o +obj-$(CONFIG_DEVICE_AUDIT) += audit_device.o obj-$(CONFIG_GCOV_KERNEL) += gcov/ obj-$(CONFIG_KPROBES) += kprobes.o obj-$(CONFIG_KGDB) += debug/ diff --git a/kernel/audit_device.c b/kernel/audit_device.c new file mode 100644 index 0000000..8dfdf04 --- /dev/null +++ b/kernel/audit_device.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void log_string(struct audit_buffer *ab, char *key, char *val) +{ + if (val) { + audit_log_format(ab, " %s=", key); + audit_log_untrustedstring(ab, val); + } + else { + audit_log_format(ab, " %s=%s", key, "?"); + } + +} + +static void log_major_minor(struct audit_buffer *ab, struct device *dev) +{ + if (dev && dev->devt) { + audit_log_format(ab, " major=%d", MAJOR(dev->devt)); + audit_log_format(ab, " minor=%d", MINOR(dev->devt)); + } +} + +/* Blocking call when device has reference and will keep reference until + * all notifiers are done, no usb_dev_get/ usb_dev_put required. + */ +static int audit_notify(struct notifier_block *self, + unsigned long action, void *d) +{ + struct usb_device *usbdev = (struct usb_device *)d; + char *op; + struct audit_buffer *ab; + + switch (action) { + case USB_DEVICE_ADD: + op = "add"; + break; + case USB_DEVICE_REMOVE: + op = "remove"; + break; + default: /* ignore any other USB events */ + return NOTIFY_DONE; + } + + ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_DEVICE_CHANGE); + + if (ab) { + audit_log_format(ab, "action=%s", op); + log_string(ab, "manufacturer", usbdev->manufacturer); + log_string(ab, "product", usbdev->product); + log_string(ab, "serial", usbdev->serial); + log_major_minor(ab, &usbdev->dev); + log_string(ab, "bus", "usb"); + audit_log_end(ab); + } + + return NOTIFY_DONE; +} + +static struct notifier_block audit_nb = { + .notifier_call = audit_notify, + .priority = INT_MIN +}; + +static int __init audit_device_init(void) +{ + pr_info("Registering usb audit notification callback\n"); + usb_register_notify(&audit_nb); + return 0; +} + +static void __exit audit_device_exit(void) +{ + pr_info("Unregistering usb audit notification callback\n"); + usb_unregister_notify(&audit_nb); +} + +module_init(audit_device_init); +module_exit(audit_device_exit); + +MODULE_LICENSE("GPL"); -- 1.8.3.1