Example #1
0
void proc_coredump_connector(struct task_struct *task)
{
	struct cn_msg *msg;
	struct proc_event *ev;
	__u8 buffer[CN_PROC_MSG_SIZE] __aligned(8);
	struct timespec ts;

	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_COREDUMP;
	ev->event_data.coredump.process_pid = task->pid;
	ev->event_data.coredump.process_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 */
	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];

	if (atomic_read(&proc_event_num_listeners) < 1)
		return;

	msg = (struct cn_msg *)buffer;
	ev = (struct proc_event *)msg->data;
	get_seq(&msg->seq, &ev->cpu);
	ktime_get_ts(&ts); /* get high res monotonic timestamp */
	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
	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);
	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
}
Example #3
0
static void cn_test_timer_func(unsigned long __data)
{
	struct cn_msg *m;
	char data[32];

	pr_debug("%s: timer fired with data %lu\n", __func__, __data);

	m = kzalloc(sizeof(*m) + sizeof(data), GFP_ATOMIC);
	if (m) {

		memcpy(&m->id, &cn_test_id, sizeof(m->id));
		m->seq = cn_test_timer_counter;
		m->len = sizeof(data);

		m->len =
		    scnprintf(data, sizeof(data), "counter = %u",
			      cn_test_timer_counter) + 1;

		memcpy(m + 1, data, m->len);

		cn_netlink_send(m, 0, GFP_ATOMIC);
		kfree(m);
	}

	cn_test_timer_counter++;

	mod_timer(&cn_test_timer, jiffies + msecs_to_jiffies(1000));
}
void proc_exit_connector(struct task_struct *task)
{
	struct cn_msg *msg;
	struct proc_event *ev;
	__u8 buffer[CN_PROC_MSG_SIZE];
	struct timespec ts;

	if (atomic_read(&proc_event_num_listeners) < 1)
		return;

	msg = (struct cn_msg*)buffer;
	ev = (struct proc_event*)msg->data;
	get_seq(&msg->seq, &ev->cpu);
	ktime_get_ts(&ts); /* get high res monotonic timestamp */
	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;
	ev->event_data.exit.exit_code = task->exit_code;
	ev->event_data.exit.exit_signal = task->exit_signal;

	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
	msg->ack = 0; /* not used */
	msg->len = sizeof(*ev);
	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
}
Example #5
0
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];
    const struct cred *cred;

	if (atomic_read(&proc_event_num_listeners) < 1)
		return;

	msg = (struct cn_msg*)buffer;
	ev = (struct proc_event*)msg->data;
	get_seq(&msg->seq, &ev->cpu);
	ktime_get_ts(&ts); /* get high res monotonic timestamp */
	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;

    rcu_read_lock();
    cred = __task_cred(task);
    ev->event_data.exec.process_euid = cred->euid;
    ev->event_data.exec.process_egid = cred->egid;
    rcu_read_unlock();

    proc_get_exe(task, ev->event_data.exec.exe);

	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
	msg->ack = 0; /* not used */
	msg->len = sizeof(*ev);
	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
}
void proc_fork_connector(struct task_struct *task)
{
	struct cn_msg *msg;
	struct proc_event *ev;
	__u8 buffer[CN_PROC_MSG_SIZE];
	struct timespec ts;
	struct task_struct *parent;

	if (atomic_read(&proc_event_num_listeners) < 1)
		return;

	msg = (struct cn_msg*)buffer;
	ev = (struct proc_event*)msg->data;
	get_seq(&msg->seq, &ev->cpu);
	ktime_get_ts(&ts); /* get high res monotonic timestamp */
	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.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);
	/*  If cn_netlink_send() failed, the data is not sent */
	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
}
Example #7
0
static void cn_test_timer_func(unsigned long __data)
{
	struct cn_msg *m;
	char data[32];

	m = kzalloc(sizeof(*m) + sizeof(data), GFP_ATOMIC);
	if (m) {

		memcpy(&m->id, &cn_test_id, sizeof(m->id));
		m->seq = cn_test_timer_counter;
		m->len = sizeof(data);

		m->len =
		    scnprintf(data, sizeof(data), "counter = %u",
			      cn_test_timer_counter) + 1;

		memcpy(m + 1, data, m->len);

		cn_netlink_send(m, 0, gfp_any());
		kfree(m);
	}

	cn_test_timer_counter++;

	mod_timer(&cn_test_timer, jiffies + HZ);
}
Example #8
0
static void vss_send_op(struct work_struct *dummy)
{
	int op = vss_transaction.msg->vss_hdr.operation;
	int rc;
	struct cn_msg *msg;
	struct hv_vss_msg *vss_msg;

	msg = kzalloc(sizeof(*msg) + sizeof(*vss_msg), GFP_ATOMIC);
	if (!msg)
		return;

	vss_msg = (struct hv_vss_msg *)msg->data;

	msg->id.idx =  CN_VSS_IDX;
	msg->id.val = CN_VSS_VAL;

	vss_msg->vss_hdr.operation = op;
	msg->len = sizeof(struct hv_vss_msg);

	rc = cn_netlink_send(msg, 0, 0, GFP_ATOMIC);
	if (rc) {
		pr_warn("VSS: failed to communicate to the daemon: %d\n", rc);
		if (cancel_delayed_work_sync(&vss_timeout_work))
			vss_respond_to_host(HV_E_FAIL);
	}
	kfree(msg);

	return;
}
Example #9
0
/*
 * Send an acknowledgement message to userspace
 *
 * Use 0 for success, EFOO otherwise.
 * Note: this is the negative of conventional kernel error
 * values because it's not being returned via syscall return
 * mechanisms.
 */
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);
	struct timespec ts;

	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));
	msg->seq = rcvd_seq;
	ktime_get_ts(&ts); /* get high res monotonic timestamp */
	ev->timestamp_ns = timespec_to_ns(&ts);
	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);
}
static inline void send_msg(struct cn_msg *msg)
{
	preempt_disable();

	msg->seq = __this_cpu_inc_return(proc_event_counts) - 1;
	((struct proc_event *)msg->data)->cpu = smp_processor_id();

	/*
	 * Preemption remains disabled during send to ensure the messages are
	 * ordered according to their sequence numbers.
	 *
	 * If cn_netlink_send() fails, the data is not sent.
	 */
	cn_netlink_send(msg, 0, CN_IDX_PROC, GFP_NOWAIT);

	preempt_enable();
}
Example #11
0
static void
kvp_register(void)
{

	struct cn_msg *msg;

	msg = kzalloc(sizeof(*msg) + strlen(HV_DRV_VERSION) + 1 , GFP_ATOMIC);

	if (msg) {
		msg->id.idx =  CN_KVP_IDX;
		msg->id.val = CN_KVP_VAL;
		msg->seq = KVP_REGISTER;
		strcpy(msg->data, HV_DRV_VERSION);
		msg->len = strlen(HV_DRV_VERSION) + 1;
		cn_netlink_send(msg, 0, GFP_ATOMIC);
		kfree(msg);
	}
}
Example #12
0
static int
kvp_send_key(int index)
{
	struct cn_msg *msg;

	msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC);

	if (msg) {
		msg->id.idx =  CN_KVP_IDX;
		msg->id.val = CN_KVP_VAL;
		msg->seq = KVP_KERNEL_GET;
		((struct hv_ku_msg *)msg->data)->kvp_index = index;
		msg->len = sizeof(struct hv_ku_msg);
		cn_netlink_send(msg, 0, GFP_ATOMIC);
		kfree(msg);
		return 0;
	}
	return 1;
}
Example #13
0
static void
kvp_send_key(struct work_struct *dummy)
{
	struct cn_msg *msg;
	int index = kvp_transaction.index;

	msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC);

	if (msg) {
		msg->id.idx =  CN_KVP_IDX;
		msg->id.val = CN_KVP_VAL;
		msg->seq = KVP_KERNEL_GET;
		((struct hv_ku_msg *)msg->data)->kvp_index = index;
		msg->len = sizeof(struct hv_ku_msg);
		cn_netlink_send(msg, 0, GFP_ATOMIC);
		kfree(msg);
	}
	return;
}
Example #14
0
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);
	struct timespec ts;
	const struct cred *cred;

	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));
	ev->what = which_id;
	ev->event_data.id.process_pid = task->pid;
	ev->event_data.id.process_tgid = task->tgid;
	rcu_read_lock();
	cred = __task_cred(task);
	if (which_id == PROC_EVENT_UID) {
		ev->event_data.id.r.ruid = from_kuid_munged(&init_user_ns, cred->uid);
		ev->event_data.id.e.euid = from_kuid_munged(&init_user_ns, cred->euid);
	} else if (which_id == PROC_EVENT_GID) {
		ev->event_data.id.r.rgid = from_kgid_munged(&init_user_ns, cred->gid);
		ev->event_data.id.e.egid = from_kgid_munged(&init_user_ns, cred->egid);
	} else {
		rcu_read_unlock();
		return;
	}
	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);

	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);
}
Example #15
0
static void vss_send_op(struct work_struct *dummy)
{
	int op = vss_transaction.msg->vss_hdr.operation;
	struct cn_msg *msg;
	struct hv_vss_msg *vss_msg;

	msg = kzalloc(sizeof(*msg) + sizeof(*vss_msg), GFP_ATOMIC);
	if (!msg)
		return;

	vss_msg = (struct hv_vss_msg *)msg->data;

	msg->id.idx =  CN_VSS_IDX;
	msg->id.val = CN_VSS_VAL;

	vss_msg->vss_hdr.operation = op;
	msg->len = sizeof(struct hv_vss_msg);

	cn_netlink_send(msg, 0, 0, GFP_ATOMIC);
	kfree(msg);

	return;
}
Example #16
0
static void
kvp_register(int reg_value)
{

    struct cn_msg *msg;
    struct hv_kvp_msg *kvp_msg;
    char *version;

    msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg), GFP_ATOMIC);

    if (msg) {
        kvp_msg = (struct hv_kvp_msg *)msg->data;
        version = kvp_msg->body.kvp_register.version;
        msg->id.idx =  CN_KVP_IDX;
        msg->id.val = CN_KVP_VAL;

        kvp_msg->kvp_hdr.operation = reg_value;
        strcpy(version, HV_DRV_VERSION);
        msg->len = sizeof(struct hv_kvp_msg);
        cn_netlink_send(msg, 0, GFP_ATOMIC);
        kfree(msg);
    }
}
Example #17
0
static void
kvp_send_key(struct work_struct *dummy)
{
    struct cn_msg *msg;
    struct hv_kvp_msg *message;
    struct hv_kvp_msg *in_msg;
    __u8 operation = kvp_transaction.kvp_msg->kvp_hdr.operation;
    __u8 pool = kvp_transaction.kvp_msg->kvp_hdr.pool;
    __u32 val32;
    __u64 val64;

    msg = kzalloc(sizeof(*msg) + sizeof(struct hv_kvp_msg) , GFP_ATOMIC);
    if (!msg)
        return;

    msg->id.idx =  CN_KVP_IDX;
    msg->id.val = CN_KVP_VAL;

    message = (struct hv_kvp_msg *)msg->data;
    message->kvp_hdr.operation = operation;
    message->kvp_hdr.pool = pool;
    in_msg = kvp_transaction.kvp_msg;

    /*
     * The key/value strings sent from the host are encoded in
     * in utf16; convert it to utf8 strings.
     * The host assures us that the utf16 strings will not exceed
     * the max lengths specified. We will however, reserve room
     * for the string terminating character - in the utf16s_utf8s()
     * function we limit the size of the buffer where the converted
     * string is placed to HV_KVP_EXCHANGE_MAX_*_SIZE -1 to gaurantee
     * that the strings can be properly terminated!
     */

    switch (message->kvp_hdr.operation) {
    case KVP_OP_SET_IP_INFO:
        process_ib_ipinfo(in_msg, message, KVP_OP_SET_IP_INFO);
        break;
    case KVP_OP_GET_IP_INFO:
        process_ib_ipinfo(in_msg, message, KVP_OP_GET_IP_INFO);
        break;
    case KVP_OP_SET:
        switch (in_msg->body.kvp_set.data.value_type) {
        case REG_SZ:
            /*
             * The value is a string - utf16 encoding.
             */
            message->body.kvp_set.data.value_size =
                utf16s_to_utf8s(
                    (wchar_t *)in_msg->body.kvp_set.data.value,
                    in_msg->body.kvp_set.data.value_size,
                    UTF16_LITTLE_ENDIAN,
                    message->body.kvp_set.data.value,
                    HV_KVP_EXCHANGE_MAX_VALUE_SIZE - 1) + 1;
            break;

        case REG_U32:
            /*
             * The value is a 32 bit scalar.
             * We save this as a utf8 string.
             */
            val32 = in_msg->body.kvp_set.data.value_u32;
            message->body.kvp_set.data.value_size =
                sprintf(message->body.kvp_set.data.value,
                        "%d", val32) + 1;
            break;

        case REG_U64:
            /*
             * The value is a 64 bit scalar.
             * We save this as a utf8 string.
             */
            val64 = in_msg->body.kvp_set.data.value_u64;
            message->body.kvp_set.data.value_size =
                sprintf(message->body.kvp_set.data.value,
                        "%llu", val64) + 1;
            break;

        }
    case KVP_OP_GET:
        message->body.kvp_set.data.key_size =
            utf16s_to_utf8s(
                (wchar_t *)in_msg->body.kvp_set.data.key,
                in_msg->body.kvp_set.data.key_size,
                UTF16_LITTLE_ENDIAN,
                message->body.kvp_set.data.key,
                HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
        break;

    case KVP_OP_DELETE:
        message->body.kvp_delete.key_size =
            utf16s_to_utf8s(
                (wchar_t *)in_msg->body.kvp_delete.key,
                in_msg->body.kvp_delete.key_size,
                UTF16_LITTLE_ENDIAN,
                message->body.kvp_delete.key,
                HV_KVP_EXCHANGE_MAX_KEY_SIZE - 1) + 1;
        break;

    case KVP_OP_ENUMERATE:
        message->body.kvp_enum_data.index =
            in_msg->body.kvp_enum_data.index;
        break;
    }

    msg->len = sizeof(struct hv_kvp_msg);
    cn_netlink_send(msg, 0, GFP_ATOMIC);
    kfree(msg);

    return;
}