From: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
To: robh+dt@kernel.org, gregkh@linuxfoundation.org, arnd@arndb.de
Cc: mark.rutland@arm.com, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org, bjorn.andersson@linaro.org,
linux-arm-msm@vger.kernel.org, bkumar@qti.qualcomm.com,
thierry.escande@linaro.org,
Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
Subject: [RFC PATCH 6/6] char: fastrpc: Add support for compat ioctls
Date: Fri, 30 Nov 2018 10:46:57 +0000 [thread overview]
Message-ID: <20181130104657.14875-7-srinivas.kandagatla@linaro.org> (raw)
In-Reply-To: <20181130104657.14875-1-srinivas.kandagatla@linaro.org>
From: Thierry Escande <thierry.escande@linaro.org>
This patch adds support for compat ioctl from 32 bits userland to
Qualcomm fastrpc driver.
Supported ioctls in this change are INIT, INVOKE, and ALLOC/FREE_DMA.
Most of the work is derived from various downstream Qualcomm kernels.
Credits to various Qualcomm authors who have contributed to this code.
Specially Tharun Kumar Merugu <mtharu@codeaurora.org>
Signed-off-by: Thierry Escande <thierry.escande@linaro.org>
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
---
drivers/char/fastrpc.c | 279 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 279 insertions(+)
diff --git a/drivers/char/fastrpc.c b/drivers/char/fastrpc.c
index 3c52502eae9f..0b99a13109ea 100644
--- a/drivers/char/fastrpc.c
+++ b/drivers/char/fastrpc.c
@@ -3,6 +3,7 @@
// Copyright (c) 2018, Linaro Limited
#include <linux/cdev.h>
+#include <linux/compat.h>
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/dma-buf.h>
@@ -1207,10 +1208,288 @@ static long fastrpc_device_ioctl(struct file *file, unsigned int cmd,
return err;
}
+#ifdef CONFIG_COMPAT
+
+#define FASTRPC_COMPAT_IOCTL_ALLOC_DMA_BUFF \
+ _IOWR('R', 1, struct fastrpc_compat_ioctl_alloc_dma_buf)
+#define FASTRPC_COMPAT_IOCTL_FREE_DMA_BUFF \
+ _IOWR('R', 2, uint32_t)
+#define FASTRPC_COMPAT_IOCTL_INVOKE \
+ _IOWR('R', 3, struct fastrpc_compat_ioctl_invoke)
+#define FASTRPC_COMPAT_IOCTL_INIT \
+ _IOWR('R', 4, struct fastrpc_compat_ioctl_init)
+
+struct compat_remote_buf {
+ compat_uptr_t pv; /* buffer pointer */
+ compat_size_t len; /* length of buffer */
+};
+
+union compat_remote_arg {
+ struct compat_remote_buf buf;
+ compat_uint_t h;
+};
+
+struct fastrpc_compat_ioctl_alloc_dma_buf {
+ compat_int_t fd;
+ compat_ssize_t size;
+ compat_uint_t flags;
+};
+
+struct fastrpc_compat_ioctl_invoke {
+ compat_uint_t handle; /* remote handle */
+ compat_uint_t sc; /* scalars describing the data */
+ compat_uptr_t pra; /* remote arguments list */
+ compat_uptr_t fds; /* fd list */
+ compat_uptr_t attrs; /* attribute list */
+ compat_uptr_t crc; /* crc list */
+};
+
+struct fastrpc_compat_ioctl_init {
+ compat_uint_t flags; /* one of FASTRPC_INIT_* macros */
+ compat_uptr_t file; /* pointer to elf file */
+ compat_int_t filelen; /* elf file length */
+ compat_int_t filefd; /* dmabuf fd for the file */
+ compat_uptr_t mem; /* mem for the PD */
+ compat_int_t memlen; /* mem length */
+ compat_int_t memfd; /* dmabuf fd for the mem */
+ compat_int_t attrs; /* attributes to init process */
+ compat_int_t siglen; /* test signature file length */
+};
+
+static int fastrpc_compat_get_ioctl_alloc_dma_buf(
+ struct fastrpc_compat_ioctl_alloc_dma_buf __user *buf32,
+ struct fastrpc_ioctl_alloc_dma_buf __user *buf)
+{
+ compat_size_t size;
+ compat_uint_t flags;
+ int err;
+
+ err = put_user(0, &buf->fd);
+ err |= get_user(size, &buf32->size);
+ err |= put_user(size, &buf->size);
+ err |= get_user(flags, &buf32->flags);
+ err |= put_user(flags, &buf->flags);
+
+ return err;
+}
+
+static int fastrpc_compat_put_ioctl_alloc_dma_buf(
+ struct fastrpc_compat_ioctl_alloc_dma_buf __user *buf32,
+ struct fastrpc_ioctl_alloc_dma_buf __user *buf)
+{
+ compat_int_t fd;
+ int err;
+
+ err = get_user(fd, &buf->fd);
+ err |= put_user(fd, &buf32->fd);
+
+ return err;
+}
+
+static int compat_get_fastrpc_ioctl_invoke(
+ struct fastrpc_compat_ioctl_invoke __user *inv32,
+ struct fastrpc_ioctl_invoke __user **inva)
+{
+ compat_uint_t u, sc;
+ compat_size_t s;
+ compat_uptr_t p;
+ struct fastrpc_ioctl_invoke *inv;
+ union compat_remote_arg *pra32;
+ union remote_arg *pra;
+ int err, len, j;
+
+ err = get_user(sc, &inv32->sc);
+ if (err)
+ return err;
+
+ len = REMOTE_SCALARS_LENGTH(sc);
+ inv = compat_alloc_user_space(sizeof(*inv) + len * sizeof(*pra));
+ if (!inv)
+ return -EFAULT;
+
+ pra = (union remote_arg *)(inv + 1);
+ err = put_user(pra, &inv->pra);
+ err |= put_user(sc, &inv->sc);
+ err |= get_user(u, &inv32->handle);
+ err |= put_user(u, &inv->handle);
+ err |= get_user(p, &inv32->pra);
+ if (err)
+ return err;
+
+ pra32 = compat_ptr(p);
+ pra = (union remote_arg *)(inv + 1);
+ for (j = 0; j < len; j++) {
+ err |= get_user(p, &pra32[j].buf.pv);
+ err |= put_user(p, (uintptr_t *)&pra[j].buf.pv);
+ err |= get_user(s, &pra32[j].buf.len);
+ err |= put_user(s, &pra[j].buf.len);
+ }
+
+ err |= put_user(NULL, &inv->fds);
+ if (inv32->fds) {
+ err |= get_user(p, &inv32->fds);
+ err |= put_user(p, (compat_uptr_t *)&inv->fds);
+ }
+
+ err |= put_user(NULL, &inv->attrs);
+ if (inv32->attrs) {
+ err |= get_user(p, &inv32->attrs);
+ err |= put_user(p, (compat_uptr_t *)&inv->attrs);
+ }
+
+ err |= put_user(NULL, (compat_uptr_t __user **)&inv->crc);
+ if (inv32->crc) {
+ err |= get_user(p, &inv32->crc);
+ err |= put_user(p, (compat_uptr_t __user *)&inv->crc);
+ }
+
+ *inva = inv;
+
+ return err;
+}
+
+static int compat_get_fastrpc_ioctl_init(
+ struct fastrpc_compat_ioctl_init __user *init32,
+ struct fastrpc_ioctl_init __user *init)
+{
+ compat_uint_t u;
+ compat_uptr_t p;
+ compat_int_t i;
+ int err;
+
+ err = get_user(u, &init32->flags);
+ err |= put_user(u, &init->flags);
+ err |= get_user(p, &init32->file);
+ err |= put_user(p, &init->file);
+ err |= get_user(i, &init32->filelen);
+ err |= put_user(i, &init->filelen);
+ err |= get_user(i, &init32->filefd);
+ err |= put_user(i, &init->filefd);
+ err |= get_user(p, &init32->mem);
+ err |= put_user(p, &init->mem);
+ err |= get_user(i, &init32->memlen);
+ err |= put_user(i, &init->memlen);
+ err |= get_user(i, &init32->memfd);
+ err |= put_user(i, &init->memfd);
+
+ err |= put_user(0, &init->attrs);
+ if (init32->attrs) {
+ err |= get_user(i, &init32->attrs);
+ err |= put_user(i, &init->attrs);
+ }
+
+ err |= put_user(0, &init->siglen);
+ if (init32->siglen) {
+ err |= get_user(i, &init32->siglen);
+ err |= put_user(i, &init->siglen);
+ }
+
+ return err;
+}
+
+static long fastrpc_compat_device_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ int err;
+
+ if (!filp->f_op || !filp->f_op->unlocked_ioctl)
+ return -ENOTTY;
+
+ switch (cmd) {
+ case FASTRPC_COMPAT_IOCTL_ALLOC_DMA_BUFF: {
+ struct fastrpc_compat_ioctl_alloc_dma_buf __user *buf32;
+ struct fastrpc_ioctl_alloc_dma_buf __user *buf;
+
+ buf32 = compat_ptr(arg);
+ buf = compat_alloc_user_space(sizeof(*buf));
+ if (!buf) {
+ err = -EFAULT;
+ break;
+ }
+
+ err = fastrpc_compat_get_ioctl_alloc_dma_buf(buf32, buf);
+ if (err)
+ break;
+
+ err = filp->f_op->unlocked_ioctl(filp,
+ FASTRPC_IOCTL_ALLOC_DMA_BUFF,
+ (unsigned long)buf);
+ if (err)
+ break;
+
+ err = fastrpc_compat_put_ioctl_alloc_dma_buf(buf32, buf);
+ break;
+ }
+ case FASTRPC_COMPAT_IOCTL_FREE_DMA_BUFF: {
+ compat_uptr_t __user *info32;
+ uint32_t __user *info;
+ compat_uint_t u;
+
+ info32 = compat_ptr(arg);
+ info = compat_alloc_user_space(sizeof(*info));
+ if (!info) {
+ err = -EFAULT;
+ break;
+ }
+
+ err = get_user(u, info32);
+ err |= put_user(u, info);
+ if (err)
+ break;
+
+ err = filp->f_op->unlocked_ioctl(filp,
+ FASTRPC_IOCTL_FREE_DMA_BUFF,
+ (unsigned long)info);
+ break;
+ }
+ case FASTRPC_COMPAT_IOCTL_INVOKE: {
+ struct fastrpc_compat_ioctl_invoke __user *inv32;
+ struct fastrpc_ioctl_invoke __user *inv;
+
+ inv32 = compat_ptr(arg);
+
+ err = compat_get_fastrpc_ioctl_invoke(inv32, &inv);
+ if (err)
+ break;
+
+ err = filp->f_op->unlocked_ioctl(filp,
+ FASTRPC_IOCTL_INVOKE, (unsigned long)inv);
+ break;
+ }
+ case FASTRPC_COMPAT_IOCTL_INIT: {
+ struct fastrpc_compat_ioctl_init __user *init32;
+ struct fastrpc_ioctl_init __user *init;
+
+ init32 = compat_ptr(arg);
+ init = compat_alloc_user_space(sizeof(*init));
+ if (!init)
+ return -EFAULT;
+
+ err = compat_get_fastrpc_ioctl_init(init32, init);
+ if (err)
+ return err;
+
+ err = filp->f_op->unlocked_ioctl(filp, FASTRPC_IOCTL_INIT,
+ (unsigned long)init);
+ break;
+ }
+ default:
+ err = -ENOTTY;
+ pr_info("bad ioctl: %d\n", cmd);
+ break;
+ }
+
+ return err;
+}
+#endif /* CONFIG_COMPAT */
+
static const struct file_operations fastrpc_fops = {
.open = fastrpc_device_open,
.release = fastrpc_device_release,
.unlocked_ioctl = fastrpc_device_ioctl,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl = fastrpc_compat_device_ioctl,
+#endif
};
static int fastrpc_cb_probe(struct platform_device *pdev)
--
2.19.2
next prev parent reply other threads:[~2018-11-30 10:48 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-11-30 10:46 [RFC PATCH 0/6] char: Add support to Qualcomm FastRPC driver Srinivas Kandagatla
2018-11-30 10:46 ` [RFC PATCH 1/6] char: dt-bindings: Add Qualcomm Fastrpc bindings Srinivas Kandagatla
2018-11-30 10:46 ` [RFC PATCH 2/6] char: fastrpc: Add Qualcomm fastrpc basic driver model Srinivas Kandagatla
2018-11-30 16:13 ` Greg KH
2018-11-30 16:19 ` Srinivas Kandagatla
2018-11-30 10:46 ` [RFC PATCH 3/6] char: fastrpc: Add support for context Invoke method Srinivas Kandagatla
2018-11-30 13:41 ` Arnd Bergmann
2018-11-30 15:01 ` Srinivas Kandagatla
2018-11-30 15:08 ` Arnd Bergmann
2018-11-30 16:03 ` Srinivas Kandagatla
2018-11-30 16:19 ` Arnd Bergmann
2018-11-30 16:40 ` Srinivas Kandagatla
2018-11-30 10:46 ` [RFC PATCH 4/6] char: fastrpc: Add support for create remote init process Srinivas Kandagatla
2018-11-30 13:26 ` Arnd Bergmann
2018-11-30 13:34 ` Srinivas Kandagatla
2018-11-30 10:46 ` [RFC PATCH 5/6] char: fastrpc: Add support for dmabuf exporter Srinivas Kandagatla
2018-11-30 10:46 ` Srinivas Kandagatla [this message]
2018-11-30 12:58 ` [RFC PATCH 6/6] char: fastrpc: Add support for compat ioctls Arnd Bergmann
2018-11-30 13:20 ` Thierry Escande
2018-11-30 13:46 ` Arnd Bergmann
2018-11-30 13:50 ` Thierry Escande
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20181130104657.14875-7-srinivas.kandagatla@linaro.org \
--to=srinivas.kandagatla@linaro.org \
--cc=arnd@arndb.de \
--cc=bjorn.andersson@linaro.org \
--cc=bkumar@qti.qualcomm.com \
--cc=devicetree@vger.kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=linux-arm-msm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mark.rutland@arm.com \
--cc=robh+dt@kernel.org \
--cc=thierry.escande@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).