Source
x
// SPDX-License-Identifier: GPL-2.0
/*
* Deliver z/VM CP special messages (SMSG) as uevents.
*
* The driver registers for z/VM CP special messages with the
* "APP" prefix. Incoming messages are delivered to user space
* as uevents.
*
* Copyright IBM Corp. 2010
* Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
*
*/
/* prefix used for SMSG registration */
/* SMSG related uevent environment variables */
/* z/VM user ID which is permitted to send SMSGs
* If the value is undefined or empty (""), special messages are
* accepted from any z/VM user ID. */
static char *sender;
module_param(sender, charp, 0400);
MODULE_PARM_DESC(sender, "z/VM user ID from which CP SMSGs are accepted");
/* SMSG device representation */
static struct device *smsg_app_dev;
/* list element for queuing received messages for delivery */
struct smsg_app_event {
struct list_head list;
char *buf;
char *envp[4];
};
/* queue for outgoing uevents */
static LIST_HEAD(smsg_event_queue);
static DEFINE_SPINLOCK(smsg_event_queue_lock);
static void smsg_app_event_free(struct smsg_app_event *ev)
{
kfree(ev->buf);
kfree(ev);
}
static struct smsg_app_event *smsg_app_event_alloc(const char *from,
const char *msg)
{
struct smsg_app_event *ev;
ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
if (!ev)
return NULL;
ev->buf = kzalloc(ENV_SENDER_LEN + ENV_PREFIX_LEN +
ENV_TEXT_LEN(msg), GFP_ATOMIC);
if (!ev->buf) {
kfree(ev);
return NULL;
}
/* setting up environment pointers into buf */
ev->envp[0] = ev->buf;
ev->envp[1] = ev->envp[0] + ENV_SENDER_LEN;
ev->envp[2] = ev->envp[1] + ENV_PREFIX_LEN;
ev->envp[3] = NULL;
/* setting up environment: sender, prefix name, and message text */
snprintf(ev->envp[0], ENV_SENDER_LEN, ENV_SENDER_STR "%s", from);
snprintf(ev->envp[1], ENV_PREFIX_LEN, ENV_PREFIX_STR "%s", SMSG_PREFIX);
snprintf(ev->envp[2], ENV_TEXT_LEN(msg), ENV_TEXT_STR "%s", msg);