[PATCH 3/4] add task handling notifier: connector based procevents

From: Jan Beulich
Date: Thu Dec 20 2007 - 08:13:07 EST


This has the additional benefit of allowing the code to now be built
as a module (which made it necessary to add MODULE_xxx declarations).

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
Cc: Matt Helsley <matthltc@xxxxxxxxxx>
---
drivers/connector/Kconfig | 5 +--
drivers/connector/cn_proc.c | 57 ++++++++++++++++++++++++++++++++++++++++----
fs/exec.c | 5 ++-
include/linux/cn_proc.h | 21 ----------------
include/linux/sched.h | 4 +++
kernel/exit.c | 5 ++-
kernel/fork.c | 2 -
kernel/sys.c | 27 +++++++++++++-------
8 files changed, 83 insertions(+), 43 deletions(-)

--- 2.6.24-rc5-notify-task.orig/drivers/connector/Kconfig
+++ 2.6.24-rc5-notify-task/drivers/connector/Kconfig
@@ -12,9 +12,8 @@ menuconfig CONNECTOR
if CONNECTOR

config PROC_EVENTS
- boolean "Report process events to userspace"
- depends on CONNECTOR=y
- default y
+ tristate "Report process events to userspace"
+ default CONNECTOR
---help---
Provide a connector that reports process events to userspace. Send
events such as fork, exec, id change (uid, gid, suid, etc), and exit.
--- 2.6.24-rc5-notify-task.orig/drivers/connector/cn_proc.c
+++ 2.6.24-rc5-notify-task/drivers/connector/cn_proc.c
@@ -26,12 +26,17 @@
#include <linux/kernel.h>
#include <linux/ktime.h>
#include <linux/init.h>
+#include <linux/notifier.h>
#include <linux/connector.h>
#include <asm/atomic.h>
#include <asm/unaligned.h>

#include <linux/cn_proc.h>

+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Matt Helsley <matthltc@xxxxxxxxxx>");
+MODULE_DESCRIPTION("Process events -> userspace connector");
+
#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event))

static atomic_t proc_event_num_listeners = ATOMIC_INIT(0);
@@ -47,7 +52,7 @@ static inline void get_seq(__u32 *ts, in
put_cpu_var(proc_event_counts);
}

-void proc_fork_connector(struct task_struct *task)
+static void proc_fork_connector(struct task_struct *task)
{
struct cn_msg *msg;
struct proc_event *ev;
@@ -75,7 +80,7 @@ void proc_fork_connector(struct task_str
cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
}

-void proc_exec_connector(struct task_struct *task)
+static void proc_exec_connector(struct task_struct *task)
{
struct cn_msg *msg;
struct proc_event *ev;
@@ -100,7 +105,7 @@ void proc_exec_connector(struct task_str
cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
}

-void proc_id_connector(struct task_struct *task, int which_id)
+static void proc_id_connector(struct task_struct *task, int which_id)
{
struct cn_msg *msg;
struct proc_event *ev;
@@ -133,7 +138,7 @@ void proc_id_connector(struct task_struc
cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
}

-void proc_exit_connector(struct task_struct *task)
+static void proc_exit_connector(struct task_struct *task)
{
struct cn_msg *msg;
struct proc_event *ev;
@@ -220,6 +225,35 @@ static void cn_proc_mcast_ctl(void *data
cn_proc_ack(err, msg->seq, msg->ack);
}

+static int connector_task_notifier(struct notifier_block *nb,
+ unsigned long action,
+ void *task)
+{
+ switch (action) {
+ case TASK_NEW:
+ proc_fork_connector(task);
+ break;
+ case TASK_EXEC:
+ proc_exec_connector(task);
+ break;
+ case TASK_EXIT:
+ proc_exit_connector(task);
+ break;
+ case TASK_UID_CHANGE:
+ proc_id_connector(task, PROC_EVENT_UID);
+ break;
+ case TASK_GID_CHANGE:
+ proc_id_connector(task, PROC_EVENT_GID);
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block connector_task_notifier_block = {
+ .notifier_call = connector_task_notifier
+};
+
/*
* cn_proc_init - initialization entry point
*
@@ -234,7 +268,22 @@ static int __init cn_proc_init(void)
printk(KERN_WARNING "cn_proc failed to register\n");
return err;
}
+ blocking_notifier_chain_register(&task_notifier_list,
+ &connector_task_notifier_block);
return 0;
}

+/*
+ * cn_proc_exit - unload entry point
+ *
+ * Removes the connector callback from the connector driver.
+ */
+static void __exit cn_proc_exit(void)
+{
+ blocking_notifier_chain_unregister(&task_notifier_list,
+ &connector_task_notifier_block);
+ cn_del_callback(&cn_proc_event_id);
+}
+
module_init(cn_proc_init);
+module_exit(cn_proc_exit);
--- 2.6.24-rc5-notify-task.orig/fs/exec.c
+++ 2.6.24-rc5-notify-task/fs/exec.c
@@ -49,7 +49,7 @@
#include <linux/syscalls.h>
#include <linux/rmap.h>
#include <linux/tsacct_kern.h>
-#include <linux/cn_proc.h>
+#include <linux/notifier.h>
#include <linux/audit.h>

#include <asm/uaccess.h>
@@ -1253,7 +1253,8 @@ int search_binary_handler(struct linux_b
fput(bprm->file);
bprm->file = NULL;
current->did_exec = 1;
- proc_exec_connector(current);
+ blocking_notifier_call_chain(&task_notifier_list,
+ TASK_EXEC, current);
return retval;
}
read_lock(&binfmt_lock);
--- 2.6.24-rc5-notify-task.orig/include/linux/cn_proc.h
+++ 2.6.24-rc5-notify-task/include/linux/cn_proc.h
@@ -97,25 +97,4 @@ struct proc_event {
} event_data;
};

-#ifdef __KERNEL__
-#ifdef CONFIG_PROC_EVENTS
-void proc_fork_connector(struct task_struct *task);
-void proc_exec_connector(struct task_struct *task);
-void proc_id_connector(struct task_struct *task, int which_id);
-void proc_exit_connector(struct task_struct *task);
-#else
-static inline void proc_fork_connector(struct task_struct *task)
-{}
-
-static inline void proc_exec_connector(struct task_struct *task)
-{}
-
-static inline void proc_id_connector(struct task_struct *task,
- int which_id)
-{}
-
-static inline void proc_exit_connector(struct task_struct *task)
-{}
-#endif /* CONFIG_PROC_EVENTS */
-#endif /* __KERNEL__ */
#endif /* CN_PROC_H */
--- 2.6.24-rc5-notify-task.orig/include/linux/sched.h
+++ 2.6.24-rc5-notify-task/include/linux/sched.h
@@ -1702,6 +1702,10 @@ struct task_struct *fork_idle(int);

#define TASK_NEW 1
#define TASK_DELETE 2
+#define TASK_EXEC 3
+#define TASK_EXIT 4
+#define TASK_UID_CHANGE 5
+#define TASK_GID_CHANGE 6

extern struct blocking_notifier_head task_notifier_list;
extern struct atomic_notifier_head atomic_task_notifier_list;
--- 2.6.24-rc5-notify-task.orig/kernel/exit.c
+++ 2.6.24-rc5-notify-task/kernel/exit.c
@@ -35,7 +35,7 @@
#include <linux/syscalls.h>
#include <linux/signal.h>
#include <linux/posix-timers.h>
-#include <linux/cn_proc.h>
+#include <linux/notifier.h>
#include <linux/mutex.h>
#include <linux/futex.h>
#include <linux/compat.h>
@@ -747,6 +747,8 @@ static void exit_notify(struct task_stru
struct task_struct *t;
struct pid *pgrp;

+ blocking_notifier_call_chain(&task_notifier_list, TASK_EXIT, tsk);
+
if (signal_pending(tsk) && !(tsk->signal->flags & SIGNAL_GROUP_EXIT)
&& !thread_group_empty(tsk)) {
/*
@@ -1009,7 +1011,6 @@ fastcall NORET_TYPE void do_exit(long co
if (tsk->binfmt)
module_put(tsk->binfmt->module);

- proc_exit_connector(tsk);
exit_notify(tsk);
#ifdef CONFIG_NUMA
mpol_free(tsk->mempolicy);
--- 2.6.24-rc5-notify-task.orig/kernel/fork.c
+++ 2.6.24-rc5-notify-task/kernel/fork.c
@@ -44,7 +44,6 @@
#include <linux/rmap.h>
#include <linux/acct.h>
#include <linux/tsacct_kern.h>
-#include <linux/cn_proc.h>
#include <linux/freezer.h>
#include <linux/notifier.h>
#include <linux/taskstats_kern.h>
@@ -1316,7 +1315,6 @@ static struct task_struct *copy_process(
total_forks++;
spin_unlock(&current->sighand->siglock);
write_unlock_irq(&tasklist_lock);
- proc_fork_connector(p);
cgroup_post_fork(p);
return p;

--- 2.6.24-rc5-notify-task.orig/kernel/sys.c
+++ 2.6.24-rc5-notify-task/kernel/sys.c
@@ -28,7 +28,6 @@
#include <linux/suspend.h>
#include <linux/tty.h>
#include <linux/signal.h>
-#include <linux/cn_proc.h>
#include <linux/getcpu.h>
#include <linux/task_io_accounting_ops.h>
#include <linux/seccomp.h>
@@ -519,7 +518,9 @@ asmlinkage long sys_setregid(gid_t rgid,
current->egid = new_egid;
current->gid = new_rgid;
key_fsgid_changed(current);
- proc_id_connector(current, PROC_EVENT_GID);
+ blocking_notifier_call_chain(&task_notifier_list,
+ TASK_GID_CHANGE, current);
+
return 0;
}

@@ -554,7 +555,9 @@ asmlinkage long sys_setgid(gid_t gid)
return -EPERM;

key_fsgid_changed(current);
- proc_id_connector(current, PROC_EVENT_GID);
+ blocking_notifier_call_chain(&task_notifier_list,
+ TASK_GID_CHANGE, current);
+
return 0;
}

@@ -642,7 +645,8 @@ asmlinkage long sys_setreuid(uid_t ruid,
current->fsuid = current->euid;

key_fsuid_changed(current);
- proc_id_connector(current, PROC_EVENT_UID);
+ blocking_notifier_call_chain(&task_notifier_list,
+ TASK_UID_CHANGE, current);

return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RE);
}
@@ -689,7 +693,8 @@ asmlinkage long sys_setuid(uid_t uid)
current->suid = new_suid;

key_fsuid_changed(current);
- proc_id_connector(current, PROC_EVENT_UID);
+ blocking_notifier_call_chain(&task_notifier_list,
+ TASK_UID_CHANGE, current);

return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_ID);
}
@@ -737,7 +742,8 @@ asmlinkage long sys_setresuid(uid_t ruid
current->suid = suid;

key_fsuid_changed(current);
- proc_id_connector(current, PROC_EVENT_UID);
+ blocking_notifier_call_chain(&task_notifier_list,
+ TASK_UID_CHANGE, current);

return security_task_post_setuid(old_ruid, old_euid, old_suid, LSM_SETID_RES);
}
@@ -789,7 +795,8 @@ asmlinkage long sys_setresgid(gid_t rgid
current->sgid = sgid;

key_fsgid_changed(current);
- proc_id_connector(current, PROC_EVENT_GID);
+ blocking_notifier_call_chain(&task_notifier_list,
+ TASK_GID_CHANGE, current);
return 0;
}

@@ -830,7 +837,8 @@ asmlinkage long sys_setfsuid(uid_t uid)
}

key_fsuid_changed(current);
- proc_id_connector(current, PROC_EVENT_UID);
+ blocking_notifier_call_chain(&task_notifier_list,
+ TASK_UID_CHANGE, current);

security_task_post_setuid(old_fsuid, (uid_t)-1, (uid_t)-1, LSM_SETID_FS);

@@ -857,7 +865,8 @@ asmlinkage long sys_setfsgid(gid_t gid)
}
current->fsgid = gid;
key_fsgid_changed(current);
- proc_id_connector(current, PROC_EVENT_GID);
+ blocking_notifier_call_chain(&task_notifier_list,
+ TASK_GID_CHANGE, current);
}
return old_fsgid;
}


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/