From patchwork Fri Nov 30 10:46:57 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Srinivas Kandagatla X-Patchwork-Id: 10706115 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0AC4417D5 for ; Fri, 30 Nov 2018 10:48:17 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id EE8112F90E for ; Fri, 30 Nov 2018 10:48:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id E2A562FE15; Fri, 30 Nov 2018 10:48:16 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2E54D2F90E for ; Fri, 30 Nov 2018 10:48:16 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726900AbeK3V5G (ORCPT ); Fri, 30 Nov 2018 16:57:06 -0500 Received: from mail-wr1-f66.google.com ([209.85.221.66]:33490 "EHLO mail-wr1-f66.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727029AbeK3V47 (ORCPT ); Fri, 30 Nov 2018 16:56:59 -0500 Received: by mail-wr1-f66.google.com with SMTP id c14so4839268wrr.0 for ; Fri, 30 Nov 2018 02:48:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=gLK0lN8bJvyvGg1xxE2GWHn+3LfVBEVtzGLUZwLWRBQ=; b=Fggq+GlBcpvZe1h8SeCFsYJzkQBZZkezhjG6wCvtINKqma0gmiqN/IzEeLWxvm3oST yTGk0mOFatz1UJKe2phjRlxp8WhLniK+lpUKMsx7VRMJHNMROMF7p19RzIlFRbe/8cAc n26NOSPDWwy7FnFG02zR22p8ylXQXisZi3xBw= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=gLK0lN8bJvyvGg1xxE2GWHn+3LfVBEVtzGLUZwLWRBQ=; b=Jki29MCyn4NhQDd5ZRvU4+2UmoEBRGT/f18myCGL5x7XqCm06dwB40pSac1a4mRPZQ 8BvjZ+ZUHnOzKHSpOWxygzmihRbL70WUmNMZRxB49mQL0Qiw5Q41XClHnAN5AgOy6rGI mVwU4GGdmhCjcf/vJ63Y3bp/h16tZdBLZDx3Ig+WdW4zKqicpzY9Sgca+FXt2y0FiIxL fkHbtVqlLLx6RCzeAAH95xFx6Cicl5cCg6/xPn12SNu60fzw37Ai75EqzMFzruL06c8k zHua/0N9JE/nwp5DpHCYpjno8lKi1lJgQm5PtbXkxY3HNUM/PiItHpX7Ajyner0m8ygc Dvaw== X-Gm-Message-State: AA+aEWZOQo+a+1DB1CNh2vcQV0s0QiB3LaDUdrBXi9r5RQh/LS0kMjDy 504iU8xT9vdBE1szJO61FAob6g== X-Google-Smtp-Source: AFSGD/VrqySCwRqH98wYNhDpZ8Ooy9hrfMXJPYEtOxHt7QCSXP9SBSo2nY1xdBLT/MmAnWDiUf4tIw== X-Received: by 2002:a05:6000:f:: with SMTP id h15mr4394140wrx.248.1543574884832; Fri, 30 Nov 2018 02:48:04 -0800 (PST) Received: from srini-hackbox.lan (cpc89974-aztw32-2-0-cust43.18-1.cable.virginm.net. [86.30.250.44]) by smtp.gmail.com with ESMTPSA id 18sm6964211wmm.32.2018.11.30.02.48.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 30 Nov 2018 02:48:04 -0800 (PST) From: Srinivas Kandagatla 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 Subject: [RFC PATCH 6/6] char: fastrpc: Add support for compat ioctls Date: Fri, 30 Nov 2018 10:46:57 +0000 Message-Id: <20181130104657.14875-7-srinivas.kandagatla@linaro.org> X-Mailer: git-send-email 2.19.2 In-Reply-To: <20181130104657.14875-1-srinivas.kandagatla@linaro.org> References: <20181130104657.14875-1-srinivas.kandagatla@linaro.org> MIME-Version: 1.0 Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Thierry Escande 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 Signed-off-by: Thierry Escande Signed-off-by: Srinivas Kandagatla --- 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 +#include #include #include #include @@ -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)