blob: b3ed4ab7d1d6550d68c83143622cd772e3cfc685 [file] [log] [blame]
Carl van Schaik6d7b2ff2018-07-06 22:00:55 +10001/*
2 * devio.c - cdev I/O for service devices
3 *
4 * Copyright (c) 2016 Cog Systems Pty Ltd
5 * Author: Philip Derrin <philip@cog.systems>
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 */
11
12#include <linux/version.h>
13#include <linux/types.h>
14#include <linux/device.h>
15#include <linux/cdev.h>
16#include <linux/pagemap.h>
17#include <linux/fs.h>
18#include <linux/sched.h>
19#include <linux/wait.h>
20#include <linux/list.h>
21#include <linux/atomic.h>
22#include <linux/module.h>
23#include <linux/spinlock.h>
24#include <linux/uio.h>
25#include <linux/uaccess.h>
26#include <linux/poll.h>
27#include <linux/security.h>
28#include <linux/compat.h>
29
30#include <vservices/types.h>
31#include <vservices/buffer.h>
32#include <vservices/transport.h>
33#include <vservices/session.h>
34#include <vservices/service.h>
35#include <vservices/ioctl.h>
36#include "session.h"
37
38#define VSERVICES_DEVICE_MAX (VS_MAX_SERVICES * VS_MAX_SESSIONS)
39
40struct vs_devio_priv {
41 struct kref kref;
42 bool running, reset;
43
44 /* Receive queue */
45 wait_queue_head_t recv_wq;
46 atomic_t notify_pending;
47 struct list_head recv_queue;
48};
49
50static void
51vs_devio_priv_free(struct kref *kref)
52{
53 struct vs_devio_priv *priv = container_of(kref, struct vs_devio_priv,
54 kref);
55
56 WARN_ON(priv->running);
57 WARN_ON(!list_empty_careful(&priv->recv_queue));
58 WARN_ON(waitqueue_active(&priv->recv_wq));
59
60 kfree(priv);
61}
62
63static void vs_devio_priv_put(struct vs_devio_priv *priv)
64{
65 kref_put(&priv->kref, vs_devio_priv_free);
66}
67
68static int
69vs_devio_service_probe(struct vs_service_device *service)
70{
71 struct vs_devio_priv *priv;
72
73 priv = kmalloc(sizeof(*priv), GFP_KERNEL);
74 if (!priv)
75 return -ENOMEM;
76
77 kref_init(&priv->kref);
78 priv->running = false;
79 priv->reset = false;
80 init_waitqueue_head(&priv->recv_wq);
81 atomic_set(&priv->notify_pending, 0);
82 INIT_LIST_HEAD(&priv->recv_queue);
83
84 dev_set_drvdata(&service->dev, priv);
85
86 wake_up(&service->quota_wq);
87
88 return 0;
89}
90
91static int
92vs_devio_service_remove(struct vs_service_device *service)
93{
94 struct vs_devio_priv *priv = dev_get_drvdata(&service->dev);
95
96 WARN_ON(priv->running);
97 WARN_ON(!list_empty_careful(&priv->recv_queue));
98 WARN_ON(waitqueue_active(&priv->recv_wq));
99
100 vs_devio_priv_put(priv);
101
102 return 0;
103}
104
105static int
106vs_devio_service_receive(struct vs_service_device *service,
107 struct vs_mbuf *mbuf)
108{
109 struct vs_devio_priv *priv = dev_get_drvdata(&service->dev);
110
111 WARN_ON(!priv->running);
112
113 spin_lock(&priv->recv_wq.lock);
114 list_add_tail(&mbuf->queue, &priv->recv_queue);
115 wake_up_locked(&priv->recv_wq);
116 spin_unlock(&priv->recv_wq.lock);
117
118 return 0;
119}
120
121static void
122vs_devio_service_notify(struct vs_service_device *service, u32 flags)
123{
124 struct vs_devio_priv *priv = dev_get_drvdata(&service->dev);
125 int old, cur;
126
127 WARN_ON(!priv->running);
128
129 if (!flags)
130 return;
131
132 /* open-coded atomic_or() */
133 cur = atomic_read(&priv->notify_pending);
134 while ((old = atomic_cmpxchg(&priv->notify_pending,
135 cur, cur | flags)) != cur)
136 cur = old;
137
138 wake_up(&priv->recv_wq);
139}
140
141static void
142vs_devio_service_start(struct vs_service_device *service)
143{
144 struct vs_devio_priv *priv = dev_get_drvdata(&service->dev);
145
146 if (!priv->reset) {
147 WARN_ON(priv->running);
148 priv->running = true;
149 wake_up(&service->quota_wq);
150 }
151}
152
153static void
154vs_devio_service_reset(struct vs_service_device *service)
155{
156 struct vs_devio_priv *priv = dev_get_drvdata(&service->dev);
157 struct vs_mbuf *mbuf, *tmp;
158
159 WARN_ON(!priv->running && !priv->reset);
160
161 /*
162 * Mark the service as being in reset. This flag can never be cleared
163 * on an open device; the user must acknowledge the reset by closing
164 * and reopening the device.
165 */
166 priv->reset = true;
167 priv->running = false;
168
169 spin_lock_irq(&priv->recv_wq.lock);
170 list_for_each_entry_safe(mbuf, tmp, &priv->recv_queue, queue)
171 vs_service_free_mbuf(service, mbuf);
172 INIT_LIST_HEAD(&priv->recv_queue);
173 spin_unlock_irq(&priv->recv_wq.lock);
174 wake_up_all(&priv->recv_wq);
175}
176
177/*
178 * This driver will be registered by the core server module, which must also
179 * set its bus and owner function pointers.
180 */
181struct vs_service_driver vs_devio_server_driver = {
182 /* No protocol, so the normal bus match will never bind this. */
183 .protocol = NULL,
184 .is_server = true,
185 .rx_atomic = true,
186
187 .probe = vs_devio_service_probe,
188 .remove = vs_devio_service_remove,
189 .receive = vs_devio_service_receive,
190 .notify = vs_devio_service_notify,
191 .start = vs_devio_service_start,
192 .reset = vs_devio_service_reset,
193
194 /*
195 * Set reasonable default quotas. These can be overridden by passing
196 * nonzero values to IOCTL_VS_BIND_SERVER, which will set the
197 * service's *_quota_set fields.
198 */
199 .in_quota_min = 1,
200 .in_quota_best = 8,
201 .out_quota_min = 1,
202 .out_quota_best = 8,
203
204 /* Mark the notify counts as invalid; the service's will be used. */
205 .in_notify_count = (unsigned)-1,
206 .out_notify_count = (unsigned)-1,
207
208 .driver = {
209 .name = "vservices-server-devio",
210 .owner = NULL, /* set by core server */
211 .bus = NULL, /* set by core server */
212 .suppress_bind_attrs = true, /* see vs_devio_poll */
213 },
214};
215EXPORT_SYMBOL_GPL(vs_devio_server_driver);
216
217static int
218vs_devio_bind_server(struct vs_service_device *service,
219 struct vs_ioctl_bind *bind)
220{
221 int ret = -ENODEV;
222
223 /* Ensure the server module is loaded and the driver is registered. */
224 if (!try_module_get(vs_devio_server_driver.driver.owner))
225 goto fail_module_get;
226
227 device_lock(&service->dev);
228 ret = -EBUSY;
229 if (service->dev.driver != NULL)
230 goto fail_device_unbound;
231
232 /* Set up the quota and notify counts. */
233 service->in_quota_set = bind->recv_quota;
234 service->out_quota_set = bind->send_quota;
235 service->notify_send_bits = bind->send_notify_bits;
236 service->notify_recv_bits = bind->recv_notify_bits;
237
238 /* Manually probe the driver. */
239 service->dev.driver = &vs_devio_server_driver.driver;
240 ret = service->dev.bus->probe(&service->dev);
241 if (ret < 0)
242 goto fail_probe_driver;
243
244 ret = device_bind_driver(&service->dev);
245 if (ret < 0)
246 goto fail_bind_driver;
247
248 /* Pass the allocated quotas back to the user. */
249 bind->recv_quota = service->recv_quota;
250 bind->send_quota = service->send_quota;
251 bind->msg_size = vs_service_max_mbuf_size(service);
252
253 device_unlock(&service->dev);
254 module_put(vs_devio_server_driver.driver.owner);
255
256 return 0;
257
258fail_bind_driver:
259 ret = service->dev.bus->remove(&service->dev);
260fail_probe_driver:
261 service->dev.driver = NULL;
262fail_device_unbound:
263 device_unlock(&service->dev);
264 module_put(vs_devio_server_driver.driver.owner);
265fail_module_get:
266 return ret;
267}
268
269/*
270 * This driver will be registered by the core client module, which must also
271 * set its bus and owner pointers.
272 */
273struct vs_service_driver vs_devio_client_driver = {
274 /* No protocol, so the normal bus match will never bind this. */
275 .protocol = NULL,
276 .is_server = false,
277 .rx_atomic = true,
278
279 .probe = vs_devio_service_probe,
280 .remove = vs_devio_service_remove,
281 .receive = vs_devio_service_receive,
282 .notify = vs_devio_service_notify,
283 .start = vs_devio_service_start,
284 .reset = vs_devio_service_reset,
285
286 .driver = {
287 .name = "vservices-client-devio",
288 .owner = NULL, /* set by core client */
289 .bus = NULL, /* set by core client */
290 .suppress_bind_attrs = true, /* see vs_devio_poll */
291 },
292};
293EXPORT_SYMBOL_GPL(vs_devio_client_driver);
294
295static int
296vs_devio_bind_client(struct vs_service_device *service,
297 struct vs_ioctl_bind *bind)
298{
299 int ret = -ENODEV;
300
301 /* Ensure the client module is loaded and the driver is registered. */
302 if (!try_module_get(vs_devio_client_driver.driver.owner))
303 goto fail_module_get;
304
305 device_lock(&service->dev);
306 ret = -EBUSY;
307 if (service->dev.driver != NULL)
308 goto fail_device_unbound;
309
310 /* Manually probe the driver. */
311 service->dev.driver = &vs_devio_client_driver.driver;
312 ret = service->dev.bus->probe(&service->dev);
313 if (ret < 0)
314 goto fail_probe_driver;
315
316 ret = device_bind_driver(&service->dev);
317 if (ret < 0)
318 goto fail_bind_driver;
319
320 /* Pass the allocated quotas back to the user. */
321 bind->recv_quota = service->recv_quota;
322 bind->send_quota = service->send_quota;
323 bind->msg_size = vs_service_max_mbuf_size(service);
324 bind->send_notify_bits = service->notify_send_bits;
325 bind->recv_notify_bits = service->notify_recv_bits;
326
327 device_unlock(&service->dev);
328 module_put(vs_devio_client_driver.driver.owner);
329
330 return 0;
331
332fail_bind_driver:
333 ret = service->dev.bus->remove(&service->dev);
334fail_probe_driver:
335 service->dev.driver = NULL;
336fail_device_unbound:
337 device_unlock(&service->dev);
338 module_put(vs_devio_client_driver.driver.owner);
339fail_module_get:
340 return ret;
341}
342
343static struct vs_devio_priv *
344vs_devio_priv_get_from_service(struct vs_service_device *service)
345{
346 struct vs_devio_priv *priv = NULL;
347 struct device_driver *drv;
348
349 if (!service)
350 return NULL;
351
352 device_lock(&service->dev);
353 drv = service->dev.driver;
354
355 if ((drv == &vs_devio_client_driver.driver) ||
356 (drv == &vs_devio_server_driver.driver)) {
357 vs_service_state_lock(service);
358 priv = dev_get_drvdata(&service->dev);
359 if (priv)
360 kref_get(&priv->kref);
361 vs_service_state_unlock(service);
362 }
363
364 device_unlock(&service->dev);
365
366 return priv;
367}
368
369static int
370vs_devio_open(struct inode *inode, struct file *file)
371{
372 struct vs_service_device *service;
373
374 if (imajor(inode) != vservices_cdev_major)
375 return -ENODEV;
376
377 service = vs_service_lookup_by_devt(inode->i_rdev);
378 if (!service)
379 return -ENODEV;
380
381 file->private_data = service;
382
383 return 0;
384}
385
386static int
387vs_devio_release(struct inode *inode, struct file *file)
388{
389 struct vs_service_device *service = file->private_data;
390
391 if (service) {
392 struct vs_devio_priv *priv =
393 vs_devio_priv_get_from_service(service);
394
395 if (priv) {
396 device_release_driver(&service->dev);
397 vs_devio_priv_put(priv);
398 }
399
400 file->private_data = NULL;
401 vs_put_service(service);
402 }
403
404 return 0;
405}
406
407static struct iovec *
408vs_devio_check_iov(struct vs_ioctl_iovec *io, bool is_send, ssize_t *total)
409{
410 struct iovec *iov;
411 unsigned i;
412 int ret;
413
414 if (io->iovcnt > UIO_MAXIOV)
415 return ERR_PTR(-EINVAL);
416
417 iov = kmalloc(sizeof(*iov) * io->iovcnt, GFP_KERNEL);
418 if (!iov)
419 return ERR_PTR(-ENOMEM);
420
421 if (copy_from_user(iov, io->iov, sizeof(*iov) * io->iovcnt)) {
422 ret = -EFAULT;
423 goto fail;
424 }
425
426 *total = 0;
427 for (i = 0; i < io->iovcnt; i++) {
428 ssize_t iov_len = (ssize_t)iov[i].iov_len;
429
430 if (iov_len > MAX_RW_COUNT - *total) {
431 ret = -EINVAL;
432 goto fail;
433 }
434
435 if (!access_ok(is_send ? VERIFY_READ : VERIFY_WRITE,
436 iov[i].iov_base, iov_len)) {
437 ret = -EFAULT;
438 goto fail;
439 }
440
441 *total += iov_len;
442 }
443
444 return iov;
445
446fail:
447 kfree(iov);
448 return ERR_PTR(ret);
449}
450
451static ssize_t
452vs_devio_send(struct vs_service_device *service, struct iovec *iov,
453 size_t iovcnt, ssize_t to_send, bool nonblocking)
454{
455 struct vs_mbuf *mbuf = NULL;
456 struct vs_devio_priv *priv;
457 unsigned i;
458 ssize_t offset = 0;
459 ssize_t ret;
460 DEFINE_WAIT(wait);
461
462 priv = vs_devio_priv_get_from_service(service);
463 ret = -ENODEV;
464 if (!priv)
465 goto fail_priv_get;
466
467 vs_service_state_lock(service);
468
469 /*
470 * Waiting alloc. We must open-code this because there is no real
471 * state structure or base state.
472 */
473 ret = 0;
474 while (!vs_service_send_mbufs_available(service)) {
475 if (nonblocking) {
476 ret = -EAGAIN;
477 break;
478 }
479
480 if (signal_pending(current)) {
481 ret = -ERESTARTSYS;
482 break;
483 }
484
485 prepare_to_wait_exclusive(&service->quota_wq, &wait,
486 TASK_INTERRUPTIBLE);
487
488 vs_service_state_unlock(service);
489 schedule();
490 vs_service_state_lock(service);
491
492 if (priv->reset) {
493 ret = -ECONNRESET;
494 break;
495 }
496
497 if (!priv->running) {
498 ret = -ENOTCONN;
499 break;
500 }
501 }
502 finish_wait(&service->quota_wq, &wait);
503
504 if (ret)
505 goto fail_alloc;
506
507 mbuf = vs_service_alloc_mbuf(service, to_send, GFP_KERNEL);
508 if (IS_ERR(mbuf)) {
509 ret = PTR_ERR(mbuf);
510 goto fail_alloc;
511 }
512
513 /* Ready to send; copy data into the mbuf. */
514 ret = -EFAULT;
515 for (i = 0; i < iovcnt; i++) {
516 if (copy_from_user(mbuf->data + offset, iov[i].iov_base,
517 iov[i].iov_len))
518 goto fail_copy;
519 offset += iov[i].iov_len;
520 }
521 mbuf->size = to_send;
522
523 /* Send the message. */
524 ret = vs_service_send(service, mbuf);
525 if (ret < 0)
526 goto fail_send;
527
528 /* Wake the next waiter, if there's more quota available. */
529 if (waitqueue_active(&service->quota_wq) &&
530 vs_service_send_mbufs_available(service) > 0)
531 wake_up(&service->quota_wq);
532
533 vs_service_state_unlock(service);
534 vs_devio_priv_put(priv);
535
536 return to_send;
537
538fail_send:
539fail_copy:
540 vs_service_free_mbuf(service, mbuf);
541 wake_up(&service->quota_wq);
542fail_alloc:
543 vs_service_state_unlock(service);
544 vs_devio_priv_put(priv);
545fail_priv_get:
546 return ret;
547}
548
549static ssize_t
550vs_devio_recv(struct vs_service_device *service, struct iovec *iov,
551 size_t iovcnt, u32 *notify_bits, ssize_t recv_space,
552 bool nonblocking)
553{
554 struct vs_mbuf *mbuf = NULL;
555 struct vs_devio_priv *priv;
556 unsigned i;
557 ssize_t offset = 0;
558 ssize_t ret;
559 DEFINE_WAIT(wait);
560
561 priv = vs_devio_priv_get_from_service(service);
562 ret = -ENODEV;
563 if (!priv)
564 goto fail_priv_get;
565
566 /* Take the recv_wq lock, which also protects recv_queue. */
567 spin_lock_irq(&priv->recv_wq.lock);
568
569 /* Wait for a message, notification, or reset. */
570 ret = wait_event_interruptible_exclusive_locked_irq(priv->recv_wq,
571 !list_empty(&priv->recv_queue) || priv->reset ||
572 atomic_read(&priv->notify_pending) || nonblocking);
573
574 if (priv->reset)
575 ret = -ECONNRESET; /* Service reset */
576 else if (!ret && list_empty(&priv->recv_queue))
577 ret = -EAGAIN; /* Nonblocking, or notification */
578
579 if (ret < 0) {
580 spin_unlock_irq(&priv->recv_wq.lock);
581 goto no_mbuf;
582 }
583
584 /* Take the first mbuf from the list, and check its size. */
585 mbuf = list_first_entry(&priv->recv_queue, struct vs_mbuf, queue);
586 if (mbuf->size > recv_space) {
587 spin_unlock_irq(&priv->recv_wq.lock);
588 ret = -EMSGSIZE;
589 goto fail_msg_size;
590 }
591 list_del_init(&mbuf->queue);
592
593 spin_unlock_irq(&priv->recv_wq.lock);
594
595 /* Copy to user. */
596 ret = -EFAULT;
597 for (i = 0; (mbuf->size > offset) && (i < iovcnt); i++) {
598 size_t len = min(mbuf->size - offset, iov[i].iov_len);
599 if (copy_to_user(iov[i].iov_base, mbuf->data + offset, len))
600 goto fail_copy;
601 offset += len;
602 }
603 ret = offset;
604
605no_mbuf:
606 /*
607 * Read and clear the pending notification bits. If any notifications
608 * are received, don't return an error, even if we failed to receive a
609 * message.
610 */
611 *notify_bits = atomic_xchg(&priv->notify_pending, 0);
612 if ((ret < 0) && *notify_bits)
613 ret = 0;
614
615fail_copy:
616 if (mbuf)
617 vs_service_free_mbuf(service, mbuf);
618fail_msg_size:
619 vs_devio_priv_put(priv);
620fail_priv_get:
621 return ret;
622}
623
624static int
625vs_devio_check_perms(struct file *file, unsigned flags)
626{
627 if ((flags & MAY_READ) & !(file->f_mode & FMODE_READ))
628 return -EBADF;
629
630 if ((flags & MAY_WRITE) & !(file->f_mode & FMODE_WRITE))
631 return -EBADF;
632
633 return security_file_permission(file, flags);
634}
635
636static long
637vs_devio_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
638{
639 void __user *ptr = (void __user *)arg;
640 struct vs_service_device *service = file->private_data;
641 struct vs_ioctl_bind bind;
642 struct vs_ioctl_iovec io;
643 u32 flags;
644 long ret;
645 ssize_t iov_total;
646 struct iovec *iov;
647
648 if (!service)
649 return -ENODEV;
650
651 switch (cmd) {
652 case IOCTL_VS_RESET_SERVICE:
653 ret = vs_devio_check_perms(file, MAY_WRITE);
654 if (ret < 0)
655 break;
656 ret = vs_service_reset(service, service);
657 break;
658 case IOCTL_VS_GET_NAME:
659 ret = vs_devio_check_perms(file, MAY_READ);
660 if (ret < 0)
661 break;
662 if (service->name != NULL) {
663 size_t len = strnlen(service->name,
664 _IOC_SIZE(IOCTL_VS_GET_NAME) - 1);
665 if (copy_to_user(ptr, service->name, len + 1))
666 ret = -EFAULT;
667 } else {
668 ret = -EINVAL;
669 }
670 break;
671 case IOCTL_VS_GET_PROTOCOL:
672 ret = vs_devio_check_perms(file, MAY_READ);
673 if (ret < 0)
674 break;
675 if (service->protocol != NULL) {
676 size_t len = strnlen(service->protocol,
677 _IOC_SIZE(IOCTL_VS_GET_PROTOCOL) - 1);
678 if (copy_to_user(ptr, service->protocol, len + 1))
679 ret = -EFAULT;
680 } else {
681 ret = -EINVAL;
682 }
683 break;
684 case IOCTL_VS_BIND_CLIENT:
685 ret = vs_devio_check_perms(file, MAY_EXEC);
686 if (ret < 0)
687 break;
688 ret = vs_devio_bind_client(service, &bind);
689 if (!ret && copy_to_user(ptr, &bind, sizeof(bind)))
690 ret = -EFAULT;
691 break;
692 case IOCTL_VS_BIND_SERVER:
693 ret = vs_devio_check_perms(file, MAY_EXEC);
694 if (ret < 0)
695 break;
696 if (copy_from_user(&bind, ptr, sizeof(bind))) {
697 ret = -EFAULT;
698 break;
699 }
700 ret = vs_devio_bind_server(service, &bind);
701 if (!ret && copy_to_user(ptr, &bind, sizeof(bind)))
702 ret = -EFAULT;
703 break;
704 case IOCTL_VS_NOTIFY:
705 ret = vs_devio_check_perms(file, MAY_WRITE);
706 if (ret < 0)
707 break;
708 if (copy_from_user(&flags, ptr, sizeof(flags))) {
709 ret = -EFAULT;
710 break;
711 }
712 ret = vs_service_notify(service, flags);
713 break;
714 case IOCTL_VS_SEND:
715 ret = vs_devio_check_perms(file, MAY_WRITE);
716 if (ret < 0)
717 break;
718 if (copy_from_user(&io, ptr, sizeof(io))) {
719 ret = -EFAULT;
720 break;
721 }
722
723 iov = vs_devio_check_iov(&io, true, &iov_total);
724 if (IS_ERR(iov)) {
725 ret = PTR_ERR(iov);
726 break;
727 }
728
729 ret = vs_devio_send(service, iov, io.iovcnt, iov_total,
730 file->f_flags & O_NONBLOCK);
731 kfree(iov);
732 break;
733 case IOCTL_VS_RECV:
734 ret = vs_devio_check_perms(file, MAY_READ);
735 if (ret < 0)
736 break;
737 if (copy_from_user(&io, ptr, sizeof(io))) {
738 ret = -EFAULT;
739 break;
740 }
741
742 iov = vs_devio_check_iov(&io, true, &iov_total);
743 if (IS_ERR(iov)) {
744 ret = PTR_ERR(iov);
745 break;
746 }
747
748 ret = vs_devio_recv(service, iov, io.iovcnt,
749 &io.notify_bits, iov_total,
750 file->f_flags & O_NONBLOCK);
751 kfree(iov);
752
753 if (ret >= 0) {
754 u32 __user *notify_bits_ptr = ptr + offsetof(
755 struct vs_ioctl_iovec, notify_bits);
756 if (copy_to_user(notify_bits_ptr, &io.notify_bits,
757 sizeof(io.notify_bits)))
758 ret = -EFAULT;
759 }
760 break;
761 default:
762 dev_dbg(&service->dev, "Unknown ioctl %#x, arg: %lx\n", cmd,
763 arg);
764 ret = -ENOSYS;
765 break;
766 }
767
768 return ret;
769}
770
771#ifdef CONFIG_COMPAT
772
773struct vs_compat_ioctl_bind {
774 __u32 send_quota;
775 __u32 recv_quota;
776 __u32 send_notify_bits;
777 __u32 recv_notify_bits;
778 compat_size_t msg_size;
779};
780
781#define compat_ioctl_bind_conv(dest, src) ({ \
782 dest.send_quota = src.send_quota; \
783 dest.recv_quota = src.recv_quota; \
784 dest.send_notify_bits = src.send_notify_bits; \
785 dest.recv_notify_bits = src.recv_notify_bits; \
786 dest.msg_size = (compat_size_t)src.msg_size; \
787})
788
789#define COMPAT_IOCTL_VS_BIND_CLIENT _IOR('4', 3, struct vs_compat_ioctl_bind)
790#define COMPAT_IOCTL_VS_BIND_SERVER _IOWR('4', 4, struct vs_compat_ioctl_bind)
791
792struct vs_compat_ioctl_iovec {
793 union {
794 __u32 iovcnt; /* input */
795 __u32 notify_bits; /* output (recv only) */
796 };
797 compat_uptr_t iov;
798};
799
800#define COMPAT_IOCTL_VS_SEND \
801 _IOW('4', 6, struct vs_compat_ioctl_iovec)
802#define COMPAT_IOCTL_VS_RECV \
803 _IOWR('4', 7, struct vs_compat_ioctl_iovec)
804
805static struct iovec *
806vs_devio_check_compat_iov(struct vs_compat_ioctl_iovec *c_io,
807 bool is_send, ssize_t *total)
808{
809 struct iovec *iov;
810 struct compat_iovec *c_iov;
811
812 unsigned i;
813 int ret;
814
815 if (c_io->iovcnt > UIO_MAXIOV)
816 return ERR_PTR(-EINVAL);
817
818 c_iov = kzalloc(sizeof(*c_iov) * c_io->iovcnt, GFP_KERNEL);
819 if (!c_iov)
820 return ERR_PTR(-ENOMEM);
821
822 iov = kzalloc(sizeof(*iov) * c_io->iovcnt, GFP_KERNEL);
823 if (!iov) {
824 kfree(c_iov);
825 return ERR_PTR(-ENOMEM);
826 }
827
828 if (copy_from_user(c_iov, (struct compat_iovec __user *)
829 compat_ptr(c_io->iov), sizeof(*c_iov) * c_io->iovcnt)) {
830 ret = -EFAULT;
831 goto fail;
832 }
833
834 *total = 0;
835 for (i = 0; i < c_io->iovcnt; i++) {
836 ssize_t iov_len;
837 iov[i].iov_base = compat_ptr (c_iov[i].iov_base);
838 iov[i].iov_len = (compat_size_t) c_iov[i].iov_len;
839
840 iov_len = (ssize_t)iov[i].iov_len;
841
842 if (iov_len > MAX_RW_COUNT - *total) {
843 ret = -EINVAL;
844 goto fail;
845 }
846
847 if (!access_ok(is_send ? VERIFY_READ : VERIFY_WRITE,
848 iov[i].iov_base, iov_len)) {
849 ret = -EFAULT;
850 goto fail;
851 }
852
853 *total += iov_len;
854 }
855
856 kfree (c_iov);
857 return iov;
858
859fail:
860 kfree(c_iov);
861 kfree(iov);
862 return ERR_PTR(ret);
863}
864
865static long
866vs_devio_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
867{
868 void __user *ptr = (void __user *)arg;
869 struct vs_service_device *service = file->private_data;
870 struct vs_ioctl_bind bind;
871 struct vs_compat_ioctl_bind compat_bind;
872 struct vs_compat_ioctl_iovec compat_io;
873 long ret;
874 ssize_t iov_total;
875 struct iovec *iov;
876
877 if (!service)
878 return -ENODEV;
879
880 switch (cmd) {
881 case IOCTL_VS_RESET_SERVICE:
882 case IOCTL_VS_GET_NAME:
883 case IOCTL_VS_GET_PROTOCOL:
884 return vs_devio_ioctl (file, cmd, arg);
885 case COMPAT_IOCTL_VS_SEND:
886 ret = vs_devio_check_perms(file, MAY_WRITE);
887 if (ret < 0)
888 break;
889 if (copy_from_user(&compat_io, ptr, sizeof(compat_io))) {
890 ret = -EFAULT;
891 break;
892 }
893
894 iov = vs_devio_check_compat_iov(&compat_io, true, &iov_total);
895 if (IS_ERR(iov)) {
896 ret = PTR_ERR(iov);
897 break;
898 }
899
900 ret = vs_devio_send(service, iov, compat_io.iovcnt, iov_total,
901 file->f_flags & O_NONBLOCK);
902 kfree(iov);
903
904 break;
905 case COMPAT_IOCTL_VS_RECV:
906 ret = vs_devio_check_perms(file, MAY_READ);
907 if (ret < 0)
908 break;
909 if (copy_from_user(&compat_io, ptr, sizeof(compat_io))) {
910 ret = -EFAULT;
911 break;
912 }
913
914 iov = vs_devio_check_compat_iov(&compat_io, true, &iov_total);
915 if (IS_ERR(iov)) {
916 ret = PTR_ERR(iov);
917 break;
918 }
919
920 ret = vs_devio_recv(service, iov, compat_io.iovcnt,
921 &compat_io.notify_bits, iov_total,
922 file->f_flags & O_NONBLOCK);
923 kfree(iov);
924
925 if (ret >= 0) {
926 u32 __user *notify_bits_ptr = ptr + offsetof(
927 struct vs_compat_ioctl_iovec, notify_bits);
928 if (copy_to_user(notify_bits_ptr, &compat_io.notify_bits,
929 sizeof(compat_io.notify_bits)))
930 ret = -EFAULT;
931 }
932 break;
933 case COMPAT_IOCTL_VS_BIND_CLIENT:
934 ret = vs_devio_check_perms(file, MAY_EXEC);
935 if (ret < 0)
936 break;
937 ret = vs_devio_bind_client(service, &bind);
938 compat_ioctl_bind_conv(compat_bind, bind);
939 if (!ret && copy_to_user(ptr, &compat_bind,
940 sizeof(compat_bind)))
941 ret = -EFAULT;
942 break;
943 case COMPAT_IOCTL_VS_BIND_SERVER:
944 ret = vs_devio_check_perms(file, MAY_EXEC);
945 if (ret < 0)
946 break;
947 if (copy_from_user(&compat_bind, ptr, sizeof(compat_bind))) {
948 ret = -EFAULT;
949 break;
950 }
951 compat_ioctl_bind_conv(bind, compat_bind);
952 ret = vs_devio_bind_server(service, &bind);
953 compat_ioctl_bind_conv(compat_bind, bind);
954 if (!ret && copy_to_user(ptr, &compat_bind,
955 sizeof(compat_bind)))
956 ret = -EFAULT;
957 break;
958 default:
959 dev_dbg(&service->dev, "Unknown ioctl %#x, arg: %lx\n", cmd,
960 arg);
961 ret = -ENOSYS;
962 break;
963 }
964
965 return ret;
966}
967
968#endif /* CONFIG_COMPAT */
969
970static unsigned int
971vs_devio_poll(struct file *file, struct poll_table_struct *wait)
972{
973 struct vs_service_device *service = file->private_data;
974 struct vs_devio_priv *priv = vs_devio_priv_get_from_service(service);
975 unsigned int flags = 0;
976
977 poll_wait(file, &service->quota_wq, wait);
978
979 if (priv) {
980 /*
981 * Note: there is no way for us to ensure that all poll
982 * waiters on a given workqueue have gone away, other than to
983 * actually close the file. So, this poll_wait() is only safe
984 * if we never release our claim on the service before the
985 * file is closed.
986 *
987 * We try to guarantee this by only unbinding the devio driver
988 * on close, and setting suppress_bind_attrs in the driver so
989 * root can't unbind us with sysfs.
990 */
991 poll_wait(file, &priv->recv_wq, wait);
992
993 if (priv->reset) {
994 /* Service reset; raise poll error. */
995 flags |= POLLERR | POLLHUP;
996 } else if (priv->running) {
997 if (!list_empty_careful(&priv->recv_queue))
998 flags |= POLLRDNORM | POLLIN;
999 if (atomic_read(&priv->notify_pending))
1000 flags |= POLLRDNORM | POLLIN;
1001 if (vs_service_send_mbufs_available(service) > 0)
1002 flags |= POLLWRNORM | POLLOUT;
1003 }
1004
1005 vs_devio_priv_put(priv);
1006 } else {
1007 /* No driver attached. Return error flags. */
1008 flags |= POLLERR | POLLHUP;
1009 }
1010
1011 return flags;
1012}
1013
1014static const struct file_operations vs_fops = {
1015 .owner = THIS_MODULE,
1016 .open = vs_devio_open,
1017 .release = vs_devio_release,
1018 .unlocked_ioctl = vs_devio_ioctl,
1019#ifdef CONFIG_COMPAT
1020 .compat_ioctl = vs_devio_compat_ioctl,
1021#endif
1022 .poll = vs_devio_poll,
1023};
1024
1025int vservices_cdev_major;
1026static struct cdev vs_cdev;
1027
1028int __init
1029vs_devio_init(void)
1030{
1031 dev_t dev;
1032 int r;
1033
1034 r = alloc_chrdev_region(&dev, 0, VSERVICES_DEVICE_MAX,
1035 "vs_service");
1036 if (r < 0)
1037 goto fail_alloc_chrdev;
1038 vservices_cdev_major = MAJOR(dev);
1039
1040 cdev_init(&vs_cdev, &vs_fops);
1041 r = cdev_add(&vs_cdev, dev, VSERVICES_DEVICE_MAX);
1042 if (r < 0)
1043 goto fail_cdev_add;
1044
1045 return 0;
1046
1047fail_cdev_add:
1048 unregister_chrdev_region(dev, VSERVICES_DEVICE_MAX);
1049fail_alloc_chrdev:
1050 return r;
1051}
1052
1053void __exit
1054vs_devio_exit(void)
1055{
1056 cdev_del(&vs_cdev);
1057 unregister_chrdev_region(MKDEV(vservices_cdev_major, 0),
1058 VSERVICES_DEVICE_MAX);
1059}