diff options
Diffstat (limited to 'drivers/connector')
-rw-r--r-- | drivers/connector/cn_proc.c | 147 | ||||
-rw-r--r-- | drivers/connector/connector.c | 7 |
2 files changed, 26 insertions, 128 deletions
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c index 094a710..2b46a7e 100644 --- a/drivers/connector/cn_proc.c +++ b/drivers/connector/cn_proc.c @@ -28,26 +28,12 @@ #include <linux/init.h> #include <linux/connector.h> #include <linux/gfp.h> -#include <linux/ptrace.h> -#include <linux/atomic.h> +#include <asm/atomic.h> +#include <asm/unaligned.h> #include <linux/cn_proc.h> -/* - * Size of a cn_msg followed by a proc_event structure. Since the - * sizeof struct cn_msg is a multiple of 4 bytes, but not 8 bytes, we - * add one 4-byte word to the size here, and then start the actual - * cn_msg structure 4 bytes into the stack buffer. The result is that - * the immediately following proc_event structure is aligned to 8 bytes. - */ -#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event) + 4) - -/* See comment above; we test our assumption about sizeof struct cn_msg here. */ -static inline struct cn_msg *buffer_to_cn_msg(__u8 *buffer) -{ - BUILD_BUG_ON(sizeof(struct cn_msg) != 20); - return (struct cn_msg *)(buffer + 4); -} +#define CN_PROC_MSG_SIZE (sizeof(struct cn_msg) + sizeof(struct proc_event)) static atomic_t proc_event_num_listeners = ATOMIC_INIT(0); static struct cb_id cn_proc_event_id = { CN_IDX_PROC, CN_VAL_PROC }; @@ -67,32 +53,26 @@ void proc_fork_connector(struct task_struct *task) { struct cn_msg *msg; struct proc_event *ev; - __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); + __u8 buffer[CN_PROC_MSG_SIZE]; struct timespec ts; - struct task_struct *parent; if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = buffer_to_cn_msg(buffer); + msg = (struct cn_msg*)buffer; ev = (struct proc_event*)msg->data; - memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - ev->timestamp_ns = timespec_to_ns(&ts); + put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); ev->what = PROC_EVENT_FORK; - rcu_read_lock(); - parent = rcu_dereference(task->real_parent); - ev->event_data.fork.parent_pid = parent->pid; - ev->event_data.fork.parent_tgid = parent->tgid; - rcu_read_unlock(); + ev->event_data.fork.parent_pid = task->real_parent->pid; + ev->event_data.fork.parent_tgid = task->real_parent->tgid; ev->event_data.fork.child_pid = task->pid; ev->event_data.fork.child_tgid = task->tgid; memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); - msg->flags = 0; /* not used */ /* If cn_netlink_send() failed, the data is not sent */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -102,17 +82,16 @@ void proc_exec_connector(struct task_struct *task) struct cn_msg *msg; struct proc_event *ev; struct timespec ts; - __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); + __u8 buffer[CN_PROC_MSG_SIZE]; if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = buffer_to_cn_msg(buffer); + msg = (struct cn_msg*)buffer; ev = (struct proc_event*)msg->data; - memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - ev->timestamp_ns = timespec_to_ns(&ts); + put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); ev->what = PROC_EVENT_EXEC; ev->event_data.exec.process_pid = task->pid; ev->event_data.exec.process_tgid = task->tgid; @@ -120,7 +99,6 @@ void proc_exec_connector(struct task_struct *task) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); - msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -128,16 +106,15 @@ void proc_id_connector(struct task_struct *task, int which_id) { struct cn_msg *msg; struct proc_event *ev; - __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); + __u8 buffer[CN_PROC_MSG_SIZE]; struct timespec ts; const struct cred *cred; if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = buffer_to_cn_msg(buffer); + msg = (struct cn_msg*)buffer; ev = (struct proc_event*)msg->data; - memset(&ev->event_data, 0, sizeof(ev->event_data)); ev->what = which_id; ev->event_data.id.process_pid = task->pid; ev->event_data.id.process_tgid = task->tgid; @@ -156,12 +133,11 @@ void proc_id_connector(struct task_struct *task, int which_id) rcu_read_unlock(); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - ev->timestamp_ns = timespec_to_ns(&ts); + put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); - msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -170,17 +146,16 @@ void proc_sid_connector(struct task_struct *task) struct cn_msg *msg; struct proc_event *ev; struct timespec ts; - __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); + __u8 buffer[CN_PROC_MSG_SIZE]; if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = buffer_to_cn_msg(buffer); + msg = (struct cn_msg *)buffer; ev = (struct proc_event *)msg->data; - memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - ev->timestamp_ns = timespec_to_ns(&ts); + put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); ev->what = PROC_EVENT_SID; ev->event_data.sid.process_pid = task->pid; ev->event_data.sid.process_tgid = task->tgid; @@ -188,70 +163,6 @@ void proc_sid_connector(struct task_struct *task) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); - msg->flags = 0; /* not used */ - cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); -} - -void proc_ptrace_connector(struct task_struct *task, int ptrace_id) -{ - struct cn_msg *msg; - struct proc_event *ev; - struct timespec ts; - __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); - - if (atomic_read(&proc_event_num_listeners) < 1) - return; - - msg = buffer_to_cn_msg(buffer); - ev = (struct proc_event *)msg->data; - memset(&ev->event_data, 0, sizeof(ev->event_data)); - get_seq(&msg->seq, &ev->cpu); - ktime_get_ts(&ts); /* get high res monotonic timestamp */ - ev->timestamp_ns = timespec_to_ns(&ts); - ev->what = PROC_EVENT_PTRACE; - ev->event_data.ptrace.process_pid = task->pid; - ev->event_data.ptrace.process_tgid = task->tgid; - if (ptrace_id == PTRACE_ATTACH) { - ev->event_data.ptrace.tracer_pid = current->pid; - ev->event_data.ptrace.tracer_tgid = current->tgid; - } else if (ptrace_id == PTRACE_DETACH) { - ev->event_data.ptrace.tracer_pid = 0; - ev->event_data.ptrace.tracer_tgid = 0; - } else - return; - - memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); - msg->ack = 0; /* not used */ - msg->len = sizeof(*ev); - msg->flags = 0; /* not used */ - cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); -} - -void proc_comm_connector(struct task_struct *task) -{ - struct cn_msg *msg; - struct proc_event *ev; - struct timespec ts; - __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); - - if (atomic_read(&proc_event_num_listeners) < 1) - return; - - msg = buffer_to_cn_msg(buffer); - ev = (struct proc_event *)msg->data; - memset(&ev->event_data, 0, sizeof(ev->event_data)); - get_seq(&msg->seq, &ev->cpu); - ktime_get_ts(&ts); /* get high res monotonic timestamp */ - ev->timestamp_ns = timespec_to_ns(&ts); - ev->what = PROC_EVENT_COMM; - ev->event_data.comm.process_pid = task->pid; - ev->event_data.comm.process_tgid = task->tgid; - get_task_comm(ev->event_data.comm.comm, task); - - memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); - msg->ack = 0; /* not used */ - msg->len = sizeof(*ev); - msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -259,18 +170,17 @@ void proc_exit_connector(struct task_struct *task) { struct cn_msg *msg; struct proc_event *ev; - __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); + __u8 buffer[CN_PROC_MSG_SIZE]; struct timespec ts; if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = buffer_to_cn_msg(buffer); + msg = (struct cn_msg*)buffer; ev = (struct proc_event*)msg->data; - memset(&ev->event_data, 0, sizeof(ev->event_data)); get_seq(&msg->seq, &ev->cpu); ktime_get_ts(&ts); /* get high res monotonic timestamp */ - ev->timestamp_ns = timespec_to_ns(&ts); + put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); ev->what = PROC_EVENT_EXIT; ev->event_data.exit.process_pid = task->pid; ev->event_data.exit.process_tgid = task->tgid; @@ -280,7 +190,6 @@ void proc_exit_connector(struct task_struct *task) memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = 0; /* not used */ msg->len = sizeof(*ev); - msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -296,25 +205,23 @@ static void cn_proc_ack(int err, int rcvd_seq, int rcvd_ack) { struct cn_msg *msg; struct proc_event *ev; - __u8 buffer[CN_PROC_MSG_SIZE] __aligned(8); + __u8 buffer[CN_PROC_MSG_SIZE]; struct timespec ts; if (atomic_read(&proc_event_num_listeners) < 1) return; - msg = buffer_to_cn_msg(buffer); + msg = (struct cn_msg*)buffer; ev = (struct proc_event*)msg->data; - memset(&ev->event_data, 0, sizeof(ev->event_data)); msg->seq = rcvd_seq; ktime_get_ts(&ts); /* get high res monotonic timestamp */ - ev->timestamp_ns = timespec_to_ns(&ts); + put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); ev->cpu = -1; ev->what = PROC_EVENT_NONE; ev->event_data.ack.err = err; memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); msg->ack = rcvd_ack + 1; msg->len = sizeof(*ev); - msg->flags = 0; /* not used */ cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } @@ -331,12 +238,6 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg, if (msg->len != sizeof(*mc_op)) return; - /* Can only change if privileged. */ - if (!capable(CAP_NET_ADMIN)) { - err = EPERM; - goto out; - } - mc_op = (enum proc_cn_mcast_op*)msg->data; switch (*mc_op) { case PROC_CN_MCAST_LISTEN: @@ -349,8 +250,6 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg, err = EINVAL; break; } - -out: cn_proc_ack(err, msg->seq, msg->ack); } diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index ea6efe8..dde6a0f 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -157,18 +157,17 @@ static int cn_call_callback(struct sk_buff *skb) static void cn_rx_skb(struct sk_buff *__skb) { struct nlmsghdr *nlh; + int err; struct sk_buff *skb; - int len, err; skb = skb_get(__skb); if (skb->len >= NLMSG_SPACE(0)) { nlh = nlmsg_hdr(skb); - len = nlmsg_len(nlh); - if (len < (int)sizeof(struct cn_msg) || + if (nlh->nlmsg_len < sizeof(struct cn_msg) || skb->len < nlh->nlmsg_len || - len > CONNECTOR_MAX_MSG_SIZE) { + nlh->nlmsg_len > CONNECTOR_MAX_MSG_SIZE) { kfree_skb(skb); return; } |