// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (C) 2006-2009 Red Hat, Inc.
 *
 * This file is released under the LGPL.
 */

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <net/sock.h>
#include <linux/workqueue.h>
#include <linux/connector.h>
#include <linux/device-mapper.h>
#include <linux/dm-log-userspace.h>

#include "dm-log-userspace-transfer.h"

static uint32_t dm_ulog_seq;

/*
 * Netlink/Connector is an unreliable protocol.  How long should
 * we wait for a response before assuming it was lost and retrying?
 * (If we do receive a response after this time, it will be discarded
 * and the response to the resent request will be waited for.
 */
#define DM_ULOG_RETRY_TIMEOUT (15 * HZ)

/*
 * Pre-allocated space for speed
 */
#define DM_ULOG_PREALLOCED_SIZE 512
static struct cn_msg *prealloced_cn_msg;
static struct dm_ulog_request *prealloced_ulog_tfr;

static struct cb_id ulog_cn_id = {
	.idx = CN_IDX_DM,
	.val = CN_VAL_DM_USERSPACE_LOG
};

static DEFINE_MUTEX(dm_ulog_lock);

struct receiving_pkg {
	struct list_head list;
	struct completion complete;

	uint32_t seq;

	int error;
	size_t *data_size;
	char *data;
};

static DEFINE_SPINLOCK(receiving_list_lock);
static struct list_head receiving_list;

static int dm_ulog_sendto_server(struct dm_ulog_request *tfr)
{
	int r;
	struct cn_msg *msg = prealloced_cn_msg;

	memset(msg, 0, sizeof(struct cn_msg));

	msg->id.idx = ulog_cn_id.idx;
	msg->id.val = ulog_cn_id.val;
	msg->ack = 0;
	msg->seq = tfr->seq;
	msg->len = sizeof(struct dm_ulog_request) + tfr->data_size;

	r = cn_netlink_send(msg, 0, 0, gfp_any());

	return r;
}

/*
 * Parameters for this function can be either msg or tfr, but not
 * both.  This function fills in the reply for a waiting request.
 * If just msg is given, then the reply is simply an ACK from userspace
 * that the request was received.
 *
 * Returns: 0 on success, -ENOENT on failure
 */
static int fill_pkg(struct cn_msg *msg, struct dm_ulog_request *tfr)
{
	uint32_t rtn_seq = (msg) ? msg->seq : (tfr) ? tfr->seq : 0;
	struct receiving_pkg *pkg;

	/*
	 * The 'receiving_pkg' entries in this list are statically
	 * allocated on the stack in 'dm_consult_userspace'.
	 * Each process that is waiting for a reply from the user
	 * space server will have an entry in this list.
	 *
	 * We are safe to do it this way because the stack space
	 * is unique to each process, but still addressable by
	 * other processes.
	 */
	list_for_each_entry(pkg, &receiving_list, list) {
		if (rtn_seq != pkg->seq)
			continue;

		if (msg) {
			pkg->error = -msg->ack;
			/*
			 * If we are trying again, we will need to know our
			 * storage capacity.  Otherwise, along with the
			 * error code, we make explicit that we have no data.
			 */
			if (pkg->error != -EAGAIN)
				*(pkg->data_size) = 0;
		} else if (tfr->data_size > *(pkg->data_size)) {
			DMERR("Insufficient space to receive package [%u] (%u vs %zu)",
			      tfr->request_type, tfr->data_size, *(pkg->data_size));

			*(pkg->data_size) = 0;
			pkg->error = -ENOSPC;
		} else {
			pkg->error = tfr->error;
			memcpy(pkg->data, tfr->data, tfr->data_size);
			*(pkg->data_size) = tfr->data_size;
		}
		complete(&pkg->complete);
		return 0;
	}

	return -ENOENT;
}

/*
 * This is the connector callback that delivers data
 * that was sent from userspace.
 */
static void cn_ulog_callback(struct cn_msg *msg, struct netlink_skb_parms *nsp)
{
	struct dm_ulog_request *tfr = (struct dm_ulog_request *)(msg + 1);

	if (!capable(CAP_SYS_ADMIN))
		return;

	spin_lock(&receiving_list_lock);
	if (msg->len == 0)
		fill_pkg(msg, NULL);
	else if (msg->len < sizeof(*tfr))
		DMERR("Incomplete message received (expected %u, got %u): [%u]",
		      (unsigned int)sizeof(*tfr), msg->len, msg->seq);
	else
		fill_pkg(NULL, tfr);
	spin_unlock(&receiving_list_lock);
}

/**
 * dm_consult_userspace
 * @uuid: log's universal unique identifier (must be DM_UUID_LEN in size)
 * @luid: log's local unique identifier
 * @request_type:  found in include/linux/dm-log-userspace.h
 * @data: data to tx to the server
 * @data_size: size of data in bytes
 * @rdata: place to put return data from server
 * @rdata_size: value-result (amount of space given/amount of space used)
 *
 * rdata_size is undefined on failure.
 *
 * Memory used to communicate with userspace is zero'ed
 * before populating to ensure that no unwanted bits leak
 * from kernel space to user-space.  All userspace log communications
 * between kernel and user space go through this function.
 *
 * Returns: 0 on success, -EXXX on failure
 **/
int dm_consult_userspace(const char *uuid, uint64_t luid, int request_type,
			 char *data, size_t data_size,
			 char *rdata, size_t *rdata_size)
{
	int r = 0;
	unsigned long tmo;
	size_t dummy = 0;
	int overhead_size = sizeof(struct dm_ulog_request) + sizeof(struct cn_msg);
	struct dm_ulog_request *tfr = prealloced_ulog_tfr;
	struct receiving_pkg pkg;

	/*
	 * Given the space needed to hold the 'struct cn_msg' and
	 * 'struct dm_ulog_request' - do we have enough payload
	 * space remaining?
	 */
	if (data_size > (DM_ULOG_PREALLOCED_SIZE - overhead_size)) {
		DMINFO("Size of tfr exceeds preallocated size");
		return -EINVAL;
	}

	if (!rdata_size)
		rdata_size = &dummy;
resend:
	/*
	 * We serialize the sending of requests so we can
	 * use the preallocated space.
	 */
	mutex_lock(&dm_ulog_lock);

	memset(tfr, 0, DM_ULOG_PREALLOCED_SIZE - sizeof(struct cn_msg));
	memcpy(tfr->uuid, uuid, DM_UUID_LEN);
	tfr->version = DM_ULOG_REQUEST_VERSION;
	tfr->luid = luid;
	tfr->seq = dm_ulog_seq++;

	/*
	 * Must be valid request type (all other bits set to
	 * zero).  This reserves other bits for possible future
	 * use.
	 */
	tfr->request_type = request_type & DM_ULOG_REQUEST_MASK;

	tfr->data_size = data_size;
	if (data && data_size)
		memcpy(tfr->data, data, data_size);

	memset(&pkg, 0, sizeof(pkg));
	init_completion(&pkg.complete);
	pkg.seq = tfr->seq;
	pkg.data_size = rdata_size;
	pkg.data = rdata;
	spin_lock(&receiving_list_lock);
	list_add(&(pkg.list), &receiving_list);
	spin_unlock(&receiving_list_lock);

	r = dm_ulog_sendto_server(tfr);

	mutex_unlock(&dm_ulog_lock);

	if (r) {
		DMERR("Unable to send log request [%u] to userspace: %d",
		      request_type, r);
		spin_lock(&receiving_list_lock);
		list_del_init(&(pkg.list));
		spin_unlock(&receiving_list_lock);

		goto out;
	}

	tmo = wait_for_completion_timeout(&(pkg.complete), DM_ULOG_RETRY_TIMEOUT);
	spin_lock(&receiving_list_lock);
	list_del_init(&(pkg.list));
	spin_unlock(&receiving_list_lock);
	if (!tmo) {
		DMWARN("[%s] Request timed out: [%u/%u] - retrying",
		       (strlen(uuid) > 8) ?
		       (uuid + (strlen(uuid) - 8)) : (uuid),
		       request_type, pkg.seq);
		goto resend;
	}

	r = pkg.error;
	if (r == -EAGAIN)
		goto resend;

out:
	return r;
}

int dm_ulog_tfr_init(void)
{
	int r;
	void *prealloced;

	INIT_LIST_HEAD(&receiving_list);

	prealloced = kmalloc(DM_ULOG_PREALLOCED_SIZE, GFP_KERNEL);
	if (!prealloced)
		return -ENOMEM;

	prealloced_cn_msg = prealloced;
	prealloced_ulog_tfr = prealloced + sizeof(struct cn_msg);

	r = cn_add_callback(&ulog_cn_id, "dmlogusr", cn_ulog_callback);
	if (r) {
		kfree(prealloced_cn_msg);
		return r;
	}

	return 0;
}

void dm_ulog_tfr_exit(void)
{
	cn_del_callback(&ulog_cn_id);
	kfree(prealloced_cn_msg);
}
