On Fri, May 01, 2020 at 11:18:05AM -0600, Jens Axboe wrote:

> -     if (res > 0 && put_user(ucnt, (__u64 __user *)buf))
> +     if (res > 0 && copy_to_iter(&ucnt, res, iov) < res)

*whoa*

It is correct, but only because here res > 0 <=> res == 8.
And that's not trivial at the first glance.

Please, turn that into something like

        if (iov_iter_count(to) < sizeof(ucnt))
                return -EINVAL;
        spin_lock_irq(&ctx->wqh.lock);
        if (!ctx->count) {
                if (unlikely(file->f_flags & O_NONBLOCK) {
                        spin_unlock_irq(&ctx->wqh.lock)
                        return -EAGAIN;
                }
                __add_wait_queue(&ctx->wqh, &wait);
                for (;;) {
                        set_current_state(TASK_INTERRUPTIBLE);
                        if (ctx->count)
                                break;
                        if (signal_pending(current)) {
                                spin_unlock_irq(&ctx->wqh.lock)
                                return -ERESTARTSYS;
                        }
                        spin_unlock_irq(&ctx->wqh.lock);
                        schedule();
                        spin_lock_irq(&ctx->wqh.lock);
                }
                __remove_wait_queue(&ctx->wqh, &wait);
                __set_current_state(TASK_RUNNING);
        }
        eventfd_ctx_do_read(ctx, &ucnt);
        if (waitqueue_active(&ctx->wqh))
                wake_up_locked_poll(&ctx->wqh, EPOLLOUT);
        spin_unlock_irq(&ctx->wqh.lock);
        if (unlikely(copy_to_iter(&ucnt, sizeof(ucnt), to) != sizeof(ucnt)))
                return -EFAULT;
        return sizeof(ucnt);

Reply via email to