aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVladimir Zapolskiy <vzapolskiy@gmail.com>2011-09-21 05:26:44 -0400
committerDavid S. Miller <davem@davemloft.net>2011-09-28 13:41:50 -0400
commitf786ecba4158880f8cdc0ebb93e7d78e6c125449 (patch)
tree0291e9079912f41ad2dd67ffd609a554e98b7850
parent5dd17e08f333cde0fa11000792e33d8d39b5599f (diff)
connector: add comm change event report to proc connector
Add an event to monitor comm value changes of tasks. Such an event becomes vital, if someone desires to control threads of a process in different manner. A natural characteristic of threads is its comm value, and helpfully application developers have an opportunity to change it in runtime. Reporting about such events via proc connector allows to fine-grain monitoring and control potentials, for instance a process control daemon listening to proc connector and following comm value policies can place specific threads to assigned cgroup partitions. It might be possible to achieve a pale partial one-shot likeness without this update, if an application changes comm value of a thread generator task beforehand, then a new thread is cloned, and after that proc connector listener gets the fork event and reads new thread's comm value from procfs stat file, but this change visibly simplifies and extends the matter. Signed-off-by: Vladimir Zapolskiy <vzapolskiy@gmail.com> Acked-by: Evgeniy Polyakov <zbr@ioremap.net> Cc: David Miller <davem@davemloft.net> Signed-off-by: Andrew Morton <akpm@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/connector/cn_proc.c26
-rw-r--r--include/linux/cn_proc.h11
-rw-r--r--kernel/sys.c1
3 files changed, 38 insertions, 0 deletions
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index e55814bc0d06..77e1e6cd66ce 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -205,6 +205,32 @@ void proc_ptrace_connector(struct task_struct *task, int ptrace_id)
205 cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); 205 cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
206} 206}
207 207
208void proc_comm_connector(struct task_struct *task)
209{
210 struct cn_msg *msg;
211 struct proc_event *ev;
212 struct timespec ts;
213 __u8 buffer[CN_PROC_MSG_SIZE];
214
215 if (atomic_read(&proc_event_num_listeners) < 1)
216 return;
217
218 msg = (struct cn_msg *)buffer;
219 ev = (struct proc_event *)msg->data;
220 get_seq(&msg->seq, &ev->cpu);
221 ktime_get_ts(&ts); /* get high res monotonic timestamp */
222 put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
223 ev->what = PROC_EVENT_COMM;
224 ev->event_data.comm.process_pid = task->pid;
225 ev->event_data.comm.process_tgid = task->tgid;
226 get_task_comm(ev->event_data.comm.comm, task);
227
228 memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
229 msg->ack = 0; /* not used */
230 msg->len = sizeof(*ev);
231 cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
232}
233
208void proc_exit_connector(struct task_struct *task) 234void proc_exit_connector(struct task_struct *task)
209{ 235{
210 struct cn_msg *msg; 236 struct cn_msg *msg;
diff --git a/include/linux/cn_proc.h b/include/linux/cn_proc.h
index 12c517b51ca2..d03612b196e1 100644
--- a/include/linux/cn_proc.h
+++ b/include/linux/cn_proc.h
@@ -54,6 +54,7 @@ struct proc_event {
54 PROC_EVENT_GID = 0x00000040, 54 PROC_EVENT_GID = 0x00000040,
55 PROC_EVENT_SID = 0x00000080, 55 PROC_EVENT_SID = 0x00000080,
56 PROC_EVENT_PTRACE = 0x00000100, 56 PROC_EVENT_PTRACE = 0x00000100,
57 PROC_EVENT_COMM = 0x00000200,
57 /* "next" should be 0x00000400 */ 58 /* "next" should be 0x00000400 */
58 /* "last" is the last process event: exit */ 59 /* "last" is the last process event: exit */
59 PROC_EVENT_EXIT = 0x80000000 60 PROC_EVENT_EXIT = 0x80000000
@@ -103,6 +104,12 @@ struct proc_event {
103 __kernel_pid_t tracer_tgid; 104 __kernel_pid_t tracer_tgid;
104 } ptrace; 105 } ptrace;
105 106
107 struct comm_proc_event {
108 __kernel_pid_t process_pid;
109 __kernel_pid_t process_tgid;
110 char comm[16];
111 } comm;
112
106 struct exit_proc_event { 113 struct exit_proc_event {
107 __kernel_pid_t process_pid; 114 __kernel_pid_t process_pid;
108 __kernel_pid_t process_tgid; 115 __kernel_pid_t process_tgid;
@@ -118,6 +125,7 @@ void proc_exec_connector(struct task_struct *task);
118void proc_id_connector(struct task_struct *task, int which_id); 125void proc_id_connector(struct task_struct *task, int which_id);
119void proc_sid_connector(struct task_struct *task); 126void proc_sid_connector(struct task_struct *task);
120void proc_ptrace_connector(struct task_struct *task, int which_id); 127void proc_ptrace_connector(struct task_struct *task, int which_id);
128void proc_comm_connector(struct task_struct *task);
121void proc_exit_connector(struct task_struct *task); 129void proc_exit_connector(struct task_struct *task);
122#else 130#else
123static inline void proc_fork_connector(struct task_struct *task) 131static inline void proc_fork_connector(struct task_struct *task)
@@ -133,6 +141,9 @@ static inline void proc_id_connector(struct task_struct *task,
133static inline void proc_sid_connector(struct task_struct *task) 141static inline void proc_sid_connector(struct task_struct *task)
134{} 142{}
135 143
144static inline void proc_comm_connector(struct task_struct *task)
145{}
146
136static inline void proc_ptrace_connector(struct task_struct *task, 147static inline void proc_ptrace_connector(struct task_struct *task,
137 int ptrace_id) 148 int ptrace_id)
138{} 149{}
diff --git a/kernel/sys.c b/kernel/sys.c
index 18ee1d2f6474..b3dfb76f8073 100644
--- a/kernel/sys.c
+++ b/kernel/sys.c
@@ -1759,6 +1759,7 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3,
1759 sizeof(me->comm) - 1) < 0) 1759 sizeof(me->comm) - 1) < 0)
1760 return -EFAULT; 1760 return -EFAULT;
1761 set_task_comm(me, comm); 1761 set_task_comm(me, comm);
1762 proc_comm_connector(me);
1762 return 0; 1763 return 0;
1763 case PR_GET_NAME: 1764 case PR_GET_NAME:
1764 get_task_comm(comm, me); 1765 get_task_comm(comm, me);