lkml.org 
[lkml]   [2019]   [Mar]   [6]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 8/8] aio: move sanity checks and request allocation to io_submit_one()
    Date
    From: Al Viro <viro@zeniv.linux.org.uk>

    makes for somewhat cleaner control flow in __io_submit_one()

    Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
    ---
    fs/aio.c | 86 +++++++++++++++++++++++++++++++---------------------------------
    1 file changed, 42 insertions(+), 44 deletions(-)

    diff --git a/fs/aio.c b/fs/aio.c
    index af51b1360305..6993581b77b2 100644
    --- a/fs/aio.c
    +++ b/fs/aio.c
    @@ -1788,36 +1788,15 @@ static int aio_poll(struct aio_kiocb *aiocb, const struct iocb *iocb)
    }

    static int __io_submit_one(struct kioctx *ctx, const struct iocb *iocb,
    - struct iocb __user *user_iocb, bool compat)
    + struct iocb __user *user_iocb, struct aio_kiocb *req,
    + bool compat)
    {
    - struct aio_kiocb *req;
    struct file *file;
    int ret;

    - /* enforce forwards compatibility on users */
    - if (unlikely(iocb->aio_reserved2)) {
    - pr_debug("EINVAL: reserve field set\n");
    - return -EINVAL;
    - }
    -
    - /* prevent overflows */
    - if (unlikely(
    - (iocb->aio_buf != (unsigned long)iocb->aio_buf) ||
    - (iocb->aio_nbytes != (size_t)iocb->aio_nbytes) ||
    - ((ssize_t)iocb->aio_nbytes < 0)
    - )) {
    - pr_debug("EINVAL: overflow check\n");
    - return -EINVAL;
    - }
    -
    - req = aio_get_req(ctx);
    - if (unlikely(!req))
    - return -EAGAIN;
    -
    req->ki_filp = fget(iocb->aio_fildes);
    - ret = -EBADF;
    if (unlikely(!req->ki_filp))
    - goto out_put_req;
    + return -EBADF;

    if (iocb->aio_flags & IOCB_FLAG_RESFD) {
    struct eventfd_ctx *eventfd;
    @@ -1828,17 +1807,15 @@ static int __io_submit_one(struct kioctx *ctx, const struct iocb *iocb,
    * event using the eventfd_signal() function.
    */
    eventfd = eventfd_ctx_fdget((int) iocb->aio_resfd);
    - if (IS_ERR(eventfd)) {
    - ret = PTR_ERR(eventfd);
    - goto out_put_req;
    - }
    + if (IS_ERR(eventfd))
    + return PTR_ERR(req->ki_eventfd);
    +
    req->ki_eventfd = eventfd;
    }

    - ret = put_user(KIOCB_KEY, &user_iocb->aio_key);
    - if (unlikely(ret)) {
    + if (unlikely(put_user(KIOCB_KEY, &user_iocb->aio_key))) {
    pr_debug("EFAULT: aio_key\n");
    - goto out_put_req;
    + return -EFAULT;
    }

    req->ki_user_iocb = user_iocb;
    @@ -1873,30 +1850,51 @@ static int __io_submit_one(struct kioctx *ctx, const struct iocb *iocb,
    break;
    }
    fput(file);
    -
    - /*
    - * If ret is 0, we'd either done aio_complete() ourselves or have
    - * arranged for that to be done asynchronously. Anything non-zero
    - * means that we need to destroy req ourselves.
    - */
    - if (ret)
    - goto out_put_req;
    - return 0;
    -out_put_req:
    - iocb_put(req);
    - put_reqs_available(ctx, 1);
    return ret;
    }

    static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
    bool compat)
    {
    + struct aio_kiocb *req;
    struct iocb iocb;
    + int err;

    if (unlikely(copy_from_user(&iocb, user_iocb, sizeof(iocb))))
    return -EFAULT;

    - return __io_submit_one(ctx, &iocb, user_iocb, compat);
    + /* enforce forwards compatibility on users */
    + if (unlikely(iocb.aio_reserved2)) {
    + pr_debug("EINVAL: reserve field set\n");
    + return -EINVAL;
    + }
    +
    + /* prevent overflows */
    + if (unlikely(
    + (iocb.aio_buf != (unsigned long)iocb.aio_buf) ||
    + (iocb.aio_nbytes != (size_t)iocb.aio_nbytes) ||
    + ((ssize_t)iocb.aio_nbytes < 0)
    + )) {
    + pr_debug("EINVAL: overflow check\n");
    + return -EINVAL;
    + }
    +
    + req = aio_get_req(ctx);
    + if (unlikely(!req))
    + return -EAGAIN;
    +
    + err = __io_submit_one(ctx, &iocb, user_iocb, req, compat);
    +
    + /*
    + * If err is 0, we'd either done aio_complete() ourselves or have
    + * arranged for that to be done asynchronously. Anything non-zero
    + * means that we need to destroy req ourselves.
    + */
    + if (unlikely(err)) {
    + iocb_put(req);
    + put_reqs_available(ctx, 1);
    + }
    + return err;
    }

    /* sys_io_submit:
    --
    2.11.0
    \
     
     \ /
      Last update: 2019-03-07 01:04    [W:5.441 / U:0.224 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site