cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

serio_raw.c (9978B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Raw serio device providing access to a raw byte stream from underlying
      4 * serio port. Closely emulates behavior of pre-2.6 /dev/psaux device
      5 *
      6 * Copyright (c) 2004 Dmitry Torokhov
      7 */
      8
      9#include <linux/kref.h>
     10#include <linux/sched.h>
     11#include <linux/slab.h>
     12#include <linux/poll.h>
     13#include <linux/module.h>
     14#include <linux/serio.h>
     15#include <linux/major.h>
     16#include <linux/device.h>
     17#include <linux/miscdevice.h>
     18#include <linux/wait.h>
     19#include <linux/mutex.h>
     20
     21#define DRIVER_DESC	"Raw serio driver"
     22
     23MODULE_AUTHOR("Dmitry Torokhov <dtor@mail.ru>");
     24MODULE_DESCRIPTION(DRIVER_DESC);
     25MODULE_LICENSE("GPL");
     26
     27#define SERIO_RAW_QUEUE_LEN	64
     28struct serio_raw {
     29	unsigned char queue[SERIO_RAW_QUEUE_LEN];
     30	unsigned int tail, head;
     31
     32	char name[16];
     33	struct kref kref;
     34	struct serio *serio;
     35	struct miscdevice dev;
     36	wait_queue_head_t wait;
     37	struct list_head client_list;
     38	struct list_head node;
     39	bool dead;
     40};
     41
     42struct serio_raw_client {
     43	struct fasync_struct *fasync;
     44	struct serio_raw *serio_raw;
     45	struct list_head node;
     46};
     47
     48static DEFINE_MUTEX(serio_raw_mutex);
     49static LIST_HEAD(serio_raw_list);
     50
     51/*********************************************************************
     52 *             Interface with userspace (file operations)            *
     53 *********************************************************************/
     54
     55static int serio_raw_fasync(int fd, struct file *file, int on)
     56{
     57	struct serio_raw_client *client = file->private_data;
     58
     59	return fasync_helper(fd, file, on, &client->fasync);
     60}
     61
     62static struct serio_raw *serio_raw_locate(int minor)
     63{
     64	struct serio_raw *serio_raw;
     65
     66	list_for_each_entry(serio_raw, &serio_raw_list, node) {
     67		if (serio_raw->dev.minor == minor)
     68			return serio_raw;
     69	}
     70
     71	return NULL;
     72}
     73
     74static int serio_raw_open(struct inode *inode, struct file *file)
     75{
     76	struct serio_raw *serio_raw;
     77	struct serio_raw_client *client;
     78	int retval;
     79
     80	retval = mutex_lock_interruptible(&serio_raw_mutex);
     81	if (retval)
     82		return retval;
     83
     84	serio_raw = serio_raw_locate(iminor(inode));
     85	if (!serio_raw) {
     86		retval = -ENODEV;
     87		goto out;
     88	}
     89
     90	if (serio_raw->dead) {
     91		retval = -ENODEV;
     92		goto out;
     93	}
     94
     95	client = kzalloc(sizeof(struct serio_raw_client), GFP_KERNEL);
     96	if (!client) {
     97		retval = -ENOMEM;
     98		goto out;
     99	}
    100
    101	client->serio_raw = serio_raw;
    102	file->private_data = client;
    103
    104	kref_get(&serio_raw->kref);
    105
    106	serio_pause_rx(serio_raw->serio);
    107	list_add_tail(&client->node, &serio_raw->client_list);
    108	serio_continue_rx(serio_raw->serio);
    109
    110out:
    111	mutex_unlock(&serio_raw_mutex);
    112	return retval;
    113}
    114
    115static void serio_raw_free(struct kref *kref)
    116{
    117	struct serio_raw *serio_raw =
    118			container_of(kref, struct serio_raw, kref);
    119
    120	put_device(&serio_raw->serio->dev);
    121	kfree(serio_raw);
    122}
    123
    124static int serio_raw_release(struct inode *inode, struct file *file)
    125{
    126	struct serio_raw_client *client = file->private_data;
    127	struct serio_raw *serio_raw = client->serio_raw;
    128
    129	serio_pause_rx(serio_raw->serio);
    130	list_del(&client->node);
    131	serio_continue_rx(serio_raw->serio);
    132
    133	kfree(client);
    134
    135	kref_put(&serio_raw->kref, serio_raw_free);
    136
    137	return 0;
    138}
    139
    140static bool serio_raw_fetch_byte(struct serio_raw *serio_raw, char *c)
    141{
    142	bool empty;
    143
    144	serio_pause_rx(serio_raw->serio);
    145
    146	empty = serio_raw->head == serio_raw->tail;
    147	if (!empty) {
    148		*c = serio_raw->queue[serio_raw->tail];
    149		serio_raw->tail = (serio_raw->tail + 1) % SERIO_RAW_QUEUE_LEN;
    150	}
    151
    152	serio_continue_rx(serio_raw->serio);
    153
    154	return !empty;
    155}
    156
    157static ssize_t serio_raw_read(struct file *file, char __user *buffer,
    158			      size_t count, loff_t *ppos)
    159{
    160	struct serio_raw_client *client = file->private_data;
    161	struct serio_raw *serio_raw = client->serio_raw;
    162	char c;
    163	ssize_t read = 0;
    164	int error;
    165
    166	for (;;) {
    167		if (serio_raw->dead)
    168			return -ENODEV;
    169
    170		if (serio_raw->head == serio_raw->tail &&
    171		    (file->f_flags & O_NONBLOCK))
    172			return -EAGAIN;
    173
    174		if (count == 0)
    175			break;
    176
    177		while (read < count && serio_raw_fetch_byte(serio_raw, &c)) {
    178			if (put_user(c, buffer++))
    179				return -EFAULT;
    180			read++;
    181		}
    182
    183		if (read)
    184			break;
    185
    186		if (!(file->f_flags & O_NONBLOCK)) {
    187			error = wait_event_interruptible(serio_raw->wait,
    188					serio_raw->head != serio_raw->tail ||
    189					serio_raw->dead);
    190			if (error)
    191				return error;
    192		}
    193	}
    194
    195	return read;
    196}
    197
    198static ssize_t serio_raw_write(struct file *file, const char __user *buffer,
    199			       size_t count, loff_t *ppos)
    200{
    201	struct serio_raw_client *client = file->private_data;
    202	struct serio_raw *serio_raw = client->serio_raw;
    203	int retval = 0;
    204	unsigned char c;
    205
    206	retval = mutex_lock_interruptible(&serio_raw_mutex);
    207	if (retval)
    208		return retval;
    209
    210	if (serio_raw->dead) {
    211		retval = -ENODEV;
    212		goto out;
    213	}
    214
    215	if (count > 32)
    216		count = 32;
    217
    218	while (count--) {
    219		if (get_user(c, buffer++)) {
    220			retval = -EFAULT;
    221			goto out;
    222		}
    223
    224		if (serio_write(serio_raw->serio, c)) {
    225			/* Either signal error or partial write */
    226			if (retval == 0)
    227				retval = -EIO;
    228			goto out;
    229		}
    230
    231		retval++;
    232	}
    233
    234out:
    235	mutex_unlock(&serio_raw_mutex);
    236	return retval;
    237}
    238
    239static __poll_t serio_raw_poll(struct file *file, poll_table *wait)
    240{
    241	struct serio_raw_client *client = file->private_data;
    242	struct serio_raw *serio_raw = client->serio_raw;
    243	__poll_t mask;
    244
    245	poll_wait(file, &serio_raw->wait, wait);
    246
    247	mask = serio_raw->dead ? EPOLLHUP | EPOLLERR : EPOLLOUT | EPOLLWRNORM;
    248	if (serio_raw->head != serio_raw->tail)
    249		mask |= EPOLLIN | EPOLLRDNORM;
    250
    251	return mask;
    252}
    253
    254static const struct file_operations serio_raw_fops = {
    255	.owner		= THIS_MODULE,
    256	.open		= serio_raw_open,
    257	.release	= serio_raw_release,
    258	.read		= serio_raw_read,
    259	.write		= serio_raw_write,
    260	.poll		= serio_raw_poll,
    261	.fasync		= serio_raw_fasync,
    262	.llseek		= noop_llseek,
    263};
    264
    265
    266/*********************************************************************
    267 *                   Interface with serio port                       *
    268 *********************************************************************/
    269
    270static irqreturn_t serio_raw_interrupt(struct serio *serio, unsigned char data,
    271					unsigned int dfl)
    272{
    273	struct serio_raw *serio_raw = serio_get_drvdata(serio);
    274	struct serio_raw_client *client;
    275	unsigned int head = serio_raw->head;
    276
    277	/* we are holding serio->lock here so we are protected */
    278	serio_raw->queue[head] = data;
    279	head = (head + 1) % SERIO_RAW_QUEUE_LEN;
    280	if (likely(head != serio_raw->tail)) {
    281		serio_raw->head = head;
    282		list_for_each_entry(client, &serio_raw->client_list, node)
    283			kill_fasync(&client->fasync, SIGIO, POLL_IN);
    284		wake_up_interruptible(&serio_raw->wait);
    285	}
    286
    287	return IRQ_HANDLED;
    288}
    289
    290static int serio_raw_connect(struct serio *serio, struct serio_driver *drv)
    291{
    292	static atomic_t serio_raw_no = ATOMIC_INIT(-1);
    293	struct serio_raw *serio_raw;
    294	int err;
    295
    296	serio_raw = kzalloc(sizeof(struct serio_raw), GFP_KERNEL);
    297	if (!serio_raw) {
    298		dev_dbg(&serio->dev, "can't allocate memory for a device\n");
    299		return -ENOMEM;
    300	}
    301
    302	snprintf(serio_raw->name, sizeof(serio_raw->name),
    303		 "serio_raw%ld", (long)atomic_inc_return(&serio_raw_no));
    304	kref_init(&serio_raw->kref);
    305	INIT_LIST_HEAD(&serio_raw->client_list);
    306	init_waitqueue_head(&serio_raw->wait);
    307
    308	serio_raw->serio = serio;
    309	get_device(&serio->dev);
    310
    311	serio_set_drvdata(serio, serio_raw);
    312
    313	err = serio_open(serio, drv);
    314	if (err)
    315		goto err_free;
    316
    317	err = mutex_lock_killable(&serio_raw_mutex);
    318	if (err)
    319		goto err_close;
    320
    321	list_add_tail(&serio_raw->node, &serio_raw_list);
    322	mutex_unlock(&serio_raw_mutex);
    323
    324	serio_raw->dev.minor = PSMOUSE_MINOR;
    325	serio_raw->dev.name = serio_raw->name;
    326	serio_raw->dev.parent = &serio->dev;
    327	serio_raw->dev.fops = &serio_raw_fops;
    328
    329	err = misc_register(&serio_raw->dev);
    330	if (err) {
    331		serio_raw->dev.minor = MISC_DYNAMIC_MINOR;
    332		err = misc_register(&serio_raw->dev);
    333	}
    334
    335	if (err) {
    336		dev_err(&serio->dev,
    337			"failed to register raw access device for %s\n",
    338			serio->phys);
    339		goto err_unlink;
    340	}
    341
    342	dev_info(&serio->dev, "raw access enabled on %s (%s, minor %d)\n",
    343		 serio->phys, serio_raw->name, serio_raw->dev.minor);
    344	return 0;
    345
    346err_unlink:
    347	list_del_init(&serio_raw->node);
    348err_close:
    349	serio_close(serio);
    350err_free:
    351	serio_set_drvdata(serio, NULL);
    352	kref_put(&serio_raw->kref, serio_raw_free);
    353	return err;
    354}
    355
    356static int serio_raw_reconnect(struct serio *serio)
    357{
    358	struct serio_raw *serio_raw = serio_get_drvdata(serio);
    359	struct serio_driver *drv = serio->drv;
    360
    361	if (!drv || !serio_raw) {
    362		dev_dbg(&serio->dev,
    363			"reconnect request, but serio is disconnected, ignoring...\n");
    364		return -1;
    365	}
    366
    367	/*
    368	 * Nothing needs to be done here, we just need this method to
    369	 * keep the same device.
    370	 */
    371	return 0;
    372}
    373
    374/*
    375 * Wake up users waiting for IO so they can disconnect from
    376 * dead device.
    377 */
    378static void serio_raw_hangup(struct serio_raw *serio_raw)
    379{
    380	struct serio_raw_client *client;
    381
    382	serio_pause_rx(serio_raw->serio);
    383	list_for_each_entry(client, &serio_raw->client_list, node)
    384		kill_fasync(&client->fasync, SIGIO, POLL_HUP);
    385	serio_continue_rx(serio_raw->serio);
    386
    387	wake_up_interruptible(&serio_raw->wait);
    388}
    389
    390
    391static void serio_raw_disconnect(struct serio *serio)
    392{
    393	struct serio_raw *serio_raw = serio_get_drvdata(serio);
    394
    395	misc_deregister(&serio_raw->dev);
    396
    397	mutex_lock(&serio_raw_mutex);
    398	serio_raw->dead = true;
    399	list_del_init(&serio_raw->node);
    400	mutex_unlock(&serio_raw_mutex);
    401
    402	serio_raw_hangup(serio_raw);
    403
    404	serio_close(serio);
    405	kref_put(&serio_raw->kref, serio_raw_free);
    406
    407	serio_set_drvdata(serio, NULL);
    408}
    409
    410static const struct serio_device_id serio_raw_serio_ids[] = {
    411	{
    412		.type	= SERIO_8042,
    413		.proto	= SERIO_ANY,
    414		.id	= SERIO_ANY,
    415		.extra	= SERIO_ANY,
    416	},
    417	{
    418		.type	= SERIO_8042_XL,
    419		.proto	= SERIO_ANY,
    420		.id	= SERIO_ANY,
    421		.extra	= SERIO_ANY,
    422	},
    423	{ 0 }
    424};
    425
    426MODULE_DEVICE_TABLE(serio, serio_raw_serio_ids);
    427
    428static struct serio_driver serio_raw_drv = {
    429	.driver		= {
    430		.name	= "serio_raw",
    431	},
    432	.description	= DRIVER_DESC,
    433	.id_table	= serio_raw_serio_ids,
    434	.interrupt	= serio_raw_interrupt,
    435	.connect	= serio_raw_connect,
    436	.reconnect	= serio_raw_reconnect,
    437	.disconnect	= serio_raw_disconnect,
    438	.manual_bind	= true,
    439};
    440
    441module_serio_driver(serio_raw_drv);