Home
Reading
Searching
Subscribe
Sponsors
Statistics
Posting
Contact
Spam
Lists
Links
About
Hosting
Filtering
Features Download
Marketing
Archives
FAQ
Blog
 
Gmane
From: Tetsuo Handa <penguin-kernel <at> I-love.SAKURA.ne.jp>
Subject: [RFC] TaskTracker : Simplified thread information tracker.
Newsgroups: gmane.linux.kernel.lsm
Date: Tuesday 26th November 2013 14:39:44 UTC (over 4 years ago)
Background:

  When an unexpected system event (e.g. reboot) occurs, the administrator
may
  want to identify which application triggered the event. System call
auditing
  could be used for recording such event. However, the audit log may not be
  able to provide sufficient information for identifying the application
  because the audit log does not reflect how the program was executed.

  I sometimes receive "which application triggered the event" questions on
RHEL
  systems. TOMOYO security module can track how the program was executed,
but
  TOMOYO is not yet available in Fedora/RHEL distributions.

  Although subj= field is added to the audit log if SELinux is not
disabled,
  SELinux is too difficult to customize as fine grained as I expect in
order to
  reflect how the program was executed. Therefore, I'm currently using
AKARI
  and SystemTap for emulating TOMOYO-like tracing.

  But AKARI and SystemTap do not help unless the kernel module is loaded
before
  the unexpected system event occurs. Generally, the administrator is
failing
  to record the first event, and has to wait for the same event to occur
again
  after loading the kernel module and/or configuring auditing. I came to
think
  that we want a built-in kernel routine which is automatically started
upon
  boot so that we don't fail to record the first event.

What I did:

  Assuming that multiple concurrent LSM support comes in the near future,
  I wrote a trivial LSM module which emits TOMOYO-like information into the
  audit logs.

Usage:

  Just register this LSM module. No configuration is needed.

  You will get history of current thread in the form of comm name and time
  stamp pairs in the subj= field of audit logs like an example shown below.

    type=SYSCALL msg=audit(1385429904.655:1293): arch=c000003e syscall=59
    success=yes exit=0 a0=248a770 a1=2471390 a2=24710d0 a3=7fff06272160
    items=2 ppid=1285 pid=1301 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0
    egid=0 sgid=0 fsgid=0 ses=2 tty=pts1 comm="tail" exe="/usr/bin/tail"
    subj="swapper/0(2013/11/26-10:29:59)=>init(2013/11/26-10:30:07)=>
    switch_root(2013/11/26-10:30:09)=>init(2013/11/26-10:30:09)=>
    sh(2013/11/26-01:30:20)=>rc(2013/11/26-01:30:20)=>
    S55sshd(2013/11/26-01:30:28)=>sshd(2013/11/26-01:30:28)=>
    sshd(2013/11/26-01:37:57)=>bash(2013/11/26-01:38:00)=>
    tail(2013/11/26-01:38:24)" key=(null)

One of unfortunate things for this module:

  The information this LSM module tracks is by nature per a task_struct
  variable, but security_task_alloc() and "struct task_struct"->security
are
  missing since Linux 2.6.29. As a result, this module is using per a cred
  variable for tracking per a task_struct variable based on tricky
assumptions.

----------------------------------------
>From 58f39fdee37926338e320d84b772be1b53dd60f9 Mon Sep 17 00:00:00 2001
From: Tetsuo Handa 
Date: Tue, 26 Nov 2013 18:10:37 +0900
Subject: [PATCH] TaskTracker : Simplified thread information tracker.

Existing audit logs generated via system call auditing functionality
include
current thread's comm name. But it is not always sufficient for identifying
which application has requested specific operations because comm name does
not
reflect history of current thread.

This security module adds functionality for adding current thread's history
information like TOMOYO security module does, expecting that this module
can
help us getting more information from system call auditing functionality.

Signed-off-by: Tetsuo Handa 
---
 security/Kconfig                   |    6 +
 security/Makefile                  |    2 +
 security/tasktracker/Kconfig       |   35 +++++
 security/tasktracker/Makefile      |    1 +
 security/tasktracker/tasktracker.c |  268
++++++++++++++++++++++++++++++++++++
 5 files changed, 312 insertions(+), 0 deletions(-)
 create mode 100644 security/tasktracker/Kconfig
 create mode 100644 security/tasktracker/Makefile
 create mode 100644 security/tasktracker/tasktracker.c

diff --git a/security/Kconfig b/security/Kconfig
index e9c6ac7..7108fa7 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -122,6 +122,7 @@ source security/smack/Kconfig
 source security/tomoyo/Kconfig
 source security/apparmor/Kconfig
 source security/yama/Kconfig
+source security/tasktracker/Kconfig
 
 source security/integrity/Kconfig
 
@@ -132,6 +133,7 @@ choice
 	default DEFAULT_SECURITY_TOMOYO if SECURITY_TOMOYO
 	default DEFAULT_SECURITY_APPARMOR if SECURITY_APPARMOR
 	default DEFAULT_SECURITY_YAMA if SECURITY_YAMA
+	default DEFAULT_SECURITY_TT if SECURITY_TT
 	default DEFAULT_SECURITY_DAC
 
 	help
@@ -153,6 +155,9 @@ choice
 	config DEFAULT_SECURITY_YAMA
 		bool "Yama" if SECURITY_YAMA=y
 
+	config DEFAULT_SECURITY_TT
+		bool "TaskTracker" if SECURITY_TT=y
+
 	config DEFAULT_SECURITY_DAC
 		bool "Unix Discretionary Access Controls"
 
@@ -165,6 +170,7 @@ config DEFAULT_SECURITY
 	default "tomoyo" if DEFAULT_SECURITY_TOMOYO
 	default "apparmor" if DEFAULT_SECURITY_APPARMOR
 	default "yama" if DEFAULT_SECURITY_YAMA
+	default "tt" if DEFAULT_SECURITY_TT
 	default "" if DEFAULT_SECURITY_DAC
 
 endmenu
diff --git a/security/Makefile b/security/Makefile
index a5918e0..32aecd3 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -8,6 +8,7 @@ subdir-$(CONFIG_SECURITY_SMACK)		+= smack
 subdir-$(CONFIG_SECURITY_TOMOYO)        += tomoyo
 subdir-$(CONFIG_SECURITY_APPARMOR)	+= apparmor
 subdir-$(CONFIG_SECURITY_YAMA)		+= yama
+subdir-$(CONFIG_SECURITY_TT)		+= tasktracker
 
 # always enable default capabilities
 obj-y					+= commoncap.o
@@ -22,6 +23,7 @@ obj-$(CONFIG_AUDIT)			+= lsm_audit.o
 obj-$(CONFIG_SECURITY_TOMOYO)		+= tomoyo/built-in.o
 obj-$(CONFIG_SECURITY_APPARMOR)		+= apparmor/built-in.o
 obj-$(CONFIG_SECURITY_YAMA)		+= yama/built-in.o
+obj-$(CONFIG_SECURITY_TT)		+= tasktracker/built-in.o
 obj-$(CONFIG_CGROUP_DEVICE)		+= device_cgroup.o
 
 # Object integrity file lists
diff --git a/security/tasktracker/Kconfig b/security/tasktracker/Kconfig
new file mode 100644
index 0000000..3381383
--- /dev/null
+++ b/security/tasktracker/Kconfig
@@ -0,0 +1,35 @@
+config SECURITY_TT
+	bool "TaskTracker support"
+	depends on SECURITY
+	default n
+	help
+	  Existing audit logs generated via system call auditing functionality
+	  include current thread's comm name. But it is not always sufficient
+	  for identifying which application has requested specific operations
+	  because comm name does not reflect history of current thread.
+	  
+	  This security module adds functionality for adding current thread's
+	  history information like TOMOYO security module does, expecting that
+	  this module can help us getting more information from system call
+	  auditing functionality.
+	  
+	  If you are unsure how to answer this question, answer N.
+	  
+	  Usage:
+	  
+	  Just register this module. No configuration is needed.
+	  
+	  You will get history of current thread in the form of
+	  comm name and time stamp pairs in the subj= field of audit logs
+	  like an example shown below.
+	  
+	  type=SYSCALL msg=audit(1385429904.655:1293): arch=c000003e syscall=59
+	  success=yes exit=0 a0=248a770 a1=2471390 a2=24710d0 a3=7fff06272160
+	  items=2 ppid=1285 pid=1301 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0
+	  egid=0 sgid=0 fsgid=0 ses=2 tty=pts1 comm="tail" exe="/usr/bin/tail"
+	  subj="swapper/0(2013/11/26-10:29:59)=>init(2013/11/26-10:30:07)=>
+	  switch_root(2013/11/26-10:30:09)=>init(2013/11/26-10:30:09)=>
+	  sh(2013/11/26-01:30:20)=>rc(2013/11/26-01:30:20)=>
+	  S55sshd(2013/11/26-01:30:28)=>sshd(2013/11/26-01:30:28)=>
+	  sshd(2013/11/26-01:37:57)=>bash(2013/11/26-01:38:00)=>
+	  tail(2013/11/26-01:38:24)" key=(null)
diff --git a/security/tasktracker/Makefile b/security/tasktracker/Makefile
new file mode 100644
index 0000000..15d03ce
--- /dev/null
+++ b/security/tasktracker/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_SECURITY_TT) := tasktracker.o
diff --git a/security/tasktracker/tasktracker.c
b/security/tasktracker/tasktracker.c
new file mode 100644
index 0000000..29af1b5
--- /dev/null
+++ b/security/tasktracker/tasktracker.c
@@ -0,0 +1,268 @@
+/*
+ * tasktracker.c - Simplified thread information tracker.
+ */
+#include 
+#include 
+
+/* Wrapper structure for passing string buffer. */
+struct tt_record {
+	char history[1024];
+};
+
+/* Structure for representing YYYY/MM/DD hh/mm/ss. */
+struct tt_time {
+	u16 year;
+	u8 month;
+	u8 day;
+	u8 hour;
+	u8 min;
+	u8 sec;
+};
+
+/**
+ * tt_get_time - Get current time in YYYY/MM/DD hh/mm/ss format.
+ *
+ * @stamp: Pointer to "struct tt_time".
+ *
+ * Returns nothing.
+ *
+ * This function does not handle Y2038 problem.
+ */
+static void tt_get_time(struct tt_time *stamp)
+{
+	struct timeval tv;
+	static const u16 tt_eom[2][12] = {
+		{ 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 },
+		{ 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 }
+	};
+	u16 y;
+	u8 m;
+	bool r;
+	time_t time;
+	do_gettimeofday(&tv);
+	time = tv.tv_sec;
+	stamp->sec = time % 60;
+	time /= 60;
+	stamp->min = time % 60;
+	time /= 60;
+	stamp->hour = time % 24;
+	time /= 24;
+	for (y = 1970;; y++) {
+		const unsigned short days = (y & 3) ? 365 : 366;
+		if (time < days)
+			break;
+		time -= days;
+	}
+	r = (y & 3) == 0;
+	for (m = 0; m < 11 && time >= tt_eom[r][m]; m++)
+		;
+	if (m)
+		time -= tt_eom[r][m - 1];
+	stamp->year = y;
+	stamp->month = ++m;
+	stamp->day = ++time;
+}
+
+/**
+ * tt_update_record - Update "struct tt_record" for given credential.
+ *
+ * @record: Pointer to "struct tt_record".
+ *
+ * Returns nothing.
+ */
+static void tt_update_record(struct tt_record *record)
+{
+	char *cp;
+	int i;
+	struct tt_time stamp;
+	tt_get_time(&stamp);
+	/*
+	 * Lockless update because current thread's record is not concurrently
+	 * accessible, for "struct cred"->security is not visible from other
+	 * threads because this function is called upon only boot up and
+	 * successful execve() operation.
+	 */
+	cp = record->history;
+	i = strlen(cp);
+	while (i >= sizeof(record->history) - (TASK_COMM_LEN * 4 + 30)) {
+		/*
+		 * Since this record is not for making security decision,
+		 * I don't care by-chance matching "=>" in task's commname.
+		 */
+		char *cp2 = strstr(cp + 2, "=>");
+		if (!cp2)
+			return;
+		memmove(cp + 1, cp2, strlen(cp2) + 1);
+		i = strlen(cp);
+	}
+	if (!i)
+		*cp++ = '"';
+	else {
+		cp += i - 1;
+		*cp++ = '=';
+		*cp++ = '>';
+	}
+	/*
+	 * Lockless read because this is current thread and being unexpectedly
+	 * modified by other thread is not a fatal problem.
+	 */
+	for (i = 0; i < TASK_COMM_LEN; i++) {
+		const unsigned char c = current->comm[i];
+		if (!c)
+			break;
+		else if (c == '"' || c == '\\' || c < 0x21 || c > 0x7e) {
+			*cp++ = '\\';
+			*cp++ = (c >> 6) + '0';
+			*cp++ = ((c >> 3) & 7)+ '0';
+			*cp++ = (c & 7) + '0';
+		} else
+			*cp++ = c;
+	}
+	sprintf(cp, "(%04u/%02u/%02u-%02u:%02u:%02u)\"", stamp.year,
+		stamp.month, stamp.day, stamp.hour, stamp.min, stamp.sec);
+}
+
+/**
+ * tt_find_record - Find "struct tt_record" for given credential.
+ *
+ * @cred: Pointer to "struct cred".
+ *
+ * Returns pointer to "struct tt_record".
+ */
+static inline struct tt_record *tt_find_record(const struct cred *cred)
+{
+	return cred->security;
+}
+
+/**
+ * tt_cred_alloc_blank - Allocate memory for new credentials.
+ *
+ * @new: Pointer to "struct cred".
+ * @gfp: Memory allocation flags.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tt_cred_alloc_blank(struct cred *new, gfp_t gfp)
+{
+	new->security = kzalloc(sizeof(struct tt_record), gfp);
+	return new->security ? 0 : -ENOMEM;
+}
+
+/**
+ * tt_cred_prepare - Allocate memory for new credentials.
+ *
+ * @new: Pointer to "struct cred".
+ * @old: Pointer to "struct cred".
+ * @gfp: Memory allocation flags.
+ *
+ * Returns 0 on success, negative value otherwise.
+ */
+static int tt_cred_prepare(struct cred *new, const struct cred *old,
+			   gfp_t gfp)
+{
+	if (tt_cred_alloc_blank(new, gfp))
+		return -ENOMEM;
+	strcpy(tt_find_record(new)->history, tt_find_record(old)->history);
+	return 0;
+}
+
+/**
+ * tt_cred_free - Release memory used by credentials.
+ *
+ * @cred: Pointer to "struct cred".
+ *
+ * Returns nothing.
+ */
+static void tt_cred_free(struct cred *cred)
+{
+	kfree(cred->security);
+}
+
+/**
+ * tt_cred_transfer - Transfer "struct tt_record" between credentials.
+ *
+ * @new: Pointer to "struct cred".
+ * @old: Pointer to "struct cred".
+ *
+ * Returns nothing.
+ */
+static void tt_cred_transfer(struct cred *new, const struct cred *old)
+{
+	strcpy(tt_find_record(new)->history, tt_find_record(old)->history);
+}
+
+/**
+ * tt_bprm_committing_creds - A hook which is called when do_execve()
succeeded.
+ *
+ * @bprm: Pointer to "struct linux_binprm".
+ *
+ * Returns nothing.
+ */
+static void tt_bprm_committing_creds(struct linux_binprm *bprm)
+{
+	tt_update_record(tt_find_record(bprm->cred));
+}
+
+/**
+ * tt_task_getsecid - Check whether to audit or not.
+ *
+ * @p:     Pointer to "struct task_struct".
+ * @secid: Pointer to flag.
+ */
+static void tt_task_getsecid(struct task_struct *p, u32 *secid)
+{
+	*secid = (p == current);
+}
+
+/**
+ * tt_secid_to_secctx - Allocate memory used for auditing.
+ *
+ * @secid:   Unused.
+ * @secdata: Pointer to store allocated memory.
+ * @seclen:  Unused.
+ *
+ * Returns 0.
+ */
+static int tt_secid_to_secctx(u32 secid, char **secdata, u32 *seclen)
+{
+	/*
+	 * We don't need to duplicate the string because current thread's
+	 * record is updated upon only boot up and successful execve()
+	 * operation, even if current thread's record is shared between
+	 * multiple threads.
+	 */
+	*secdata = tt_find_record(current->real_cred)->history;
+	return 0;
+}
+
+/* List of hooks. */
+static struct security_operations tasktracker_ops = {
+	.name                  = "tt",
+	.secid_to_secctx       = tt_secid_to_secctx,
+	.task_getsecid         = tt_task_getsecid,
+	.cred_prepare          = tt_cred_prepare,
+	.cred_free             = tt_cred_free,
+	.cred_alloc_blank      = tt_cred_alloc_blank,
+	.cred_transfer         = tt_cred_transfer,
+	.bprm_committing_creds = tt_bprm_committing_creds,
+};
+
+/**
+ * tt_init - Initialize this module.
+ *
+ * Returns 0 on success, panic otherwise.
+ */
+static int __init tt_init(void)
+{
+	struct cred *cred = (struct cred *) current_cred();
+	if (!security_module_enable(&tasktracker_ops))
+		return 0;
+	if (tt_cred_alloc_blank(cred, GFP_ATOMIC) ||
+	    register_security(&tasktracker_ops))
+		panic("Failure registering TaskTracker");
+	tt_update_record(tt_find_record(cred));
+	pr_info("TaskTracker initialized\n");
+	return 0;
+}
+
+security_initcall(tt_init);
-- 
1.7.1
--
To unsubscribe from this list: send the line "unsubscribe
linux-security-module" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
 
CD: 4ms