1 /* 2 * cn_proc.c - process events connector 3 * 4 * Copyright (C) Matt Helsley, IBM Corp. 2005 5 * Based on cn_fork.c by Guillaume Thouvenin <guillaume.thouvenin@bull.net> 6 * Original copyright notice follows: 7 * Copyright (C) 2005 BULL SA. 8 * 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 */ 24 25 #include <linux/module.h> 26 #include <linux/kernel.h> 27 #include <linux/ktime.h> 28 #include <linux/init.h> 29 #include <linux/connector.h> 30 #include <linux/gfp.h> 31 #include <linux/ptrace.h> 32 #include <asm/atomic.h> 33 #include <asm/unaligned.h> 34 35 #include <linux/cn_proc.h> 36 37 #define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event)) 38 39 static atomic_t proc_event_num_listeners = ATOMIC_INIT(0); 40 static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC }; 41 42 /* proc_event_counts is used as the sequence number of the netlink message */ 43 static DEFINE_PER_CPU(__u32, proc_event_counts) = { 0 }; 44 45 static inline void get_seq(__u32 *ts, int *cpu) 46 { 47 preempt_disable(); 48 *ts = __this_cpu_inc_return(proc_event_counts) -1; 49 *cpu = smp_processor_id(); 50 preempt_enable(); 51 } 52 53 void proc_fork_connector(struct task_struct *task) 54 { 55 struct cn_msg *msg; 56 struct proc_event *ev; 57 __u8 buffer[CN_PROC_MSG_SIZE]; 58 struct timespec ts; 59 60 if (atomic_read(&proc_event_num_listeners) < 1) 61 return; 62 63 msg = (struct cn_msg*)buffer; 64 ev = (struct proc_event*)msg->data; 65 get_seq(&msg->seq, &ev->cpu); 66 ktime_get_ts(&ts); /* get high res monotonic timestamp */ 67 put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); 68 ev->what = PROC_EVENT_FORK; 69 ev->event_data.fork.parent_pid = task->real_parent->pid; 70 ev->event_data.fork.parent_tgid = task->real_parent->tgid; 71 ev->event_data.fork.child_pid = task->pid; 72 ev->event_data.fork.child_tgid = task->tgid; 73 74 memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); 75 msg->ack = 0; /* not used */ 76 msg->len = sizeof(*ev); 77 /* If cn_netlink_send() failed, the data is not sent */ 78 cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); 79 } 80 81 void proc_exec_connector(struct task_struct *task) 82 { 83 struct cn_msg *msg; 84 struct proc_event *ev; 85 struct timespec ts; 86 __u8 buffer[CN_PROC_MSG_SIZE]; 87 88 if (atomic_read(&proc_event_num_listeners) < 1) 89 return; 90 91 msg = (struct cn_msg*)buffer; 92 ev = (struct proc_event*)msg->data; 93 get_seq(&msg->seq, &ev->cpu); 94 ktime_get_ts(&ts); /* get high res monotonic timestamp */ 95 put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); 96 ev->what = PROC_EVENT_EXEC; 97 ev->event_data.exec.process_pid = task->pid; 98 ev->event_data.exec.process_tgid = task->tgid; 99 100 memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); 101 msg->ack = 0; /* not used */ 102 msg->len = sizeof(*ev); 103 cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); 104 } 105 106 void proc_id_connector(struct task_struct *task, int which_id) 107 { 108 struct cn_msg *msg; 109 struct proc_event *ev; 110 __u8 buffer[CN_PROC_MSG_SIZE]; 111 struct timespec ts; 112 const struct cred *cred; 113 114 if (atomic_read(&proc_event_num_listeners) < 1) 115 return; 116 117 msg = (struct cn_msg*)buffer; 118 ev = (struct proc_event*)msg->data; 119 ev->what = which_id; 120 ev->event_data.id.process_pid = task->pid; 121 ev->event_data.id.process_tgid = task->tgid; 122 rcu_read_lock(); 123 cred = __task_cred(task); 124 if (which_id == PROC_EVENT_UID) { 125 ev->event_data.id.r.ruid = cred->uid; 126 ev->event_data.id.e.euid = cred->euid; 127 } else if (which_id == PROC_EVENT_GID) { 128 ev->event_data.id.r.rgid = cred->gid; 129 ev->event_data.id.e.egid = cred->egid; 130 } else { 131 rcu_read_unlock(); 132 return; 133 } 134 rcu_read_unlock(); 135 get_seq(&msg->seq, &ev->cpu); 136 ktime_get_ts(&ts); /* get high res monotonic timestamp */ 137 put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); 138 139 memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); 140 msg->ack = 0; /* not used */ 141 msg->len = sizeof(*ev); 142 cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); 143 } 144 145 void proc_sid_connector(struct task_struct *task) 146 { 147 struct cn_msg *msg; 148 struct proc_event *ev; 149 struct timespec ts; 150 __u8 buffer[CN_PROC_MSG_SIZE]; 151 152 if (atomic_read(&proc_event_num_listeners) < 1) 153 return; 154 155 msg = (struct cn_msg *)buffer; 156 ev = (struct proc_event *)msg->data; 157 get_seq(&msg->seq, &ev->cpu); 158 ktime_get_ts(&ts); /* get high res monotonic timestamp */ 159 put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); 160 ev->what = PROC_EVENT_SID; 161 ev->event_data.sid.process_pid = task->pid; 162 ev->event_data.sid.process_tgid = task->tgid; 163 164 memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); 165 msg->ack = 0; /* not used */ 166 msg->len = sizeof(*ev); 167 cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); 168 } 169 170 void proc_ptrace_connector(struct task_struct *task, int ptrace_id) 171 { 172 struct cn_msg *msg; 173 struct proc_event *ev; 174 struct timespec ts; 175 __u8 buffer[CN_PROC_MSG_SIZE]; 176 struct task_struct *tracer; 177 178 if (atomic_read(&proc_event_num_listeners) < 1) 179 return; 180 181 msg = (struct cn_msg *)buffer; 182 ev = (struct proc_event *)msg->data; 183 get_seq(&msg->seq, &ev->cpu); 184 ktime_get_ts(&ts); /* get high res monotonic timestamp */ 185 put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); 186 ev->what = PROC_EVENT_PTRACE; 187 ev->event_data.ptrace.process_pid = task->pid; 188 ev->event_data.ptrace.process_tgid = task->tgid; 189 if (ptrace_id == PTRACE_ATTACH) { 190 ev->event_data.ptrace.tracer_pid = current->pid; 191 ev->event_data.ptrace.tracer_tgid = current->tgid; 192 } else if (ptrace_id == PTRACE_DETACH) { 193 ev->event_data.ptrace.tracer_pid = 0; 194 ev->event_data.ptrace.tracer_tgid = 0; 195 } else 196 return; 197 198 memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); 199 msg->ack = 0; /* not used */ 200 msg->len = sizeof(*ev); 201 cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); 202 } 203 204 void proc_exit_connector(struct task_struct *task) 205 { 206 struct cn_msg *msg; 207 struct proc_event *ev; 208 __u8 buffer[CN_PROC_MSG_SIZE]; 209 struct timespec ts; 210 211 if (atomic_read(&proc_event_num_listeners) < 1) 212 return; 213 214 msg = (struct cn_msg*)buffer; 215 ev = (struct proc_event*)msg->data; 216 get_seq(&msg->seq, &ev->cpu); 217 ktime_get_ts(&ts); /* get high res monotonic timestamp */ 218 put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); 219 ev->what = PROC_EVENT_EXIT; 220 ev->event_data.exit.process_pid = task->pid; 221 ev->event_data.exit.process_tgid = task->tgid; 222 ev->event_data.exit.exit_code = task->exit_code; 223 ev->event_data.exit.exit_signal = task->exit_signal; 224 225 memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); 226 msg->ack = 0; /* not used */ 227 msg->len = sizeof(*ev); 228 cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); 229 } 230 231 /* 232 * Send an acknowledgement message to userspace 233 * 234 * Use 0 for success, EFOO otherwise. 235 * Note: this is the negative of conventional kernel error 236 * values because it's not being returned via syscall return 237 * mechanisms. 238 */ 239 static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) 240 { 241 struct cn_msg *msg; 242 struct proc_event *ev; 243 __u8 buffer[CN_PROC_MSG_SIZE]; 244 struct timespec ts; 245 246 if (atomic_read(&proc_event_num_listeners) < 1) 247 return; 248 249 msg = (struct cn_msg*)buffer; 250 ev = (struct proc_event*)msg->data; 251 msg->seq = rcvd_seq; 252 ktime_get_ts(&ts); /* get high res monotonic timestamp */ 253 put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); 254 ev->cpu = -1; 255 ev->what = PROC_EVENT_NONE; 256 ev->event_data.ack.err = err; 257 memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); 258 msg->ack = rcvd_ack + 1; 259 msg->len = sizeof(*ev); 260 cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); 261 } 262 263 /** 264 * cn_proc_mcast_ctl 265 * @data: message sent from userspace via the connector 266 */ 267 static void cn_proc_mcast_ctl(struct cn_msg *msg, 268 struct netlink_skb_parms *nsp) 269 { 270 enum proc_cn_mcast_op *mc_op = NULL; 271 int err = 0; 272 273 if (msg->len != sizeof(*mc_op)) 274 return; 275 276 mc_op = (enum proc_cn_mcast_op*)msg->data; 277 switch (*mc_op) { 278 case PROC_CN_MCAST_LISTEN: 279 atomic_inc(&proc_event_num_listeners); 280 break; 281 case PROC_CN_MCAST_IGNORE: 282 atomic_dec(&proc_event_num_listeners); 283 break; 284 default: 285 err = EINVAL; 286 break; 287 } 288 cn_proc_ack(err, msg->seq, msg->ack); 289 } 290 291 /* 292 * cn_proc_init - initialization entry point 293 * 294 * Adds the connector callback to the connector driver. 295 */ 296 static int __init cn_proc_init(void) 297 { 298 int err; 299 300 if ((err = cn_add_callback(&cn_proc_event_id, "cn_proc", 301 &cn_proc_mcast_ctl))) { 302 printk(KERN_WARNING "cn_proc failed to register\n"); 303 return err; 304 } 305 return 0; 306 } 307 308 module_init(cn_proc_init); 309