Commit 66635b07 authored by Al Viro's avatar Al Viro
Browse files

assorted variants of irqfd setup: convert to CLASS(fd)



in all of those failure exits prior to fdget() are plain returns and
the only thing done after fdput() is (on failure exits) a kfree(),
which can be done before fdput() just fine.

NOTE: in acrn_irqfd_assign() 'fail:' failure exit is wrong for
eventfd_ctx_fileget() failure (we only want fdput() there) and once
we stop doing that, it doesn't need to check if eventfd is NULL or
ERR_PTR(...) there.

NOTE: in privcmd we move fdget() up before the allocation - more
to the point, before the copy_from_user() attempt.

Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 89359897
Loading
Loading
Loading
Loading
+3 −13
Original line number Diff line number Diff line
@@ -113,7 +113,6 @@ int vfio_virqfd_enable(void *opaque,
		       void (*thread)(void *, void *),
		       void *data, struct virqfd **pvirqfd, int fd)
{
	struct fd irqfd;
	struct eventfd_ctx *ctx;
	struct virqfd *virqfd;
	int ret = 0;
@@ -133,8 +132,8 @@ int vfio_virqfd_enable(void *opaque,
	INIT_WORK(&virqfd->inject, virqfd_inject);
	INIT_WORK(&virqfd->flush_inject, virqfd_flush_inject);

	irqfd = fdget(fd);
	if (!fd_file(irqfd)) {
	CLASS(fd, irqfd)(fd);
	if (fd_empty(irqfd)) {
		ret = -EBADF;
		goto err_fd;
	}
@@ -142,7 +141,7 @@ int vfio_virqfd_enable(void *opaque,
	ctx = eventfd_ctx_fileget(fd_file(irqfd));
	if (IS_ERR(ctx)) {
		ret = PTR_ERR(ctx);
		goto err_ctx;
		goto err_fd;
	}

	virqfd->eventfd = ctx;
@@ -181,18 +180,9 @@ int vfio_virqfd_enable(void *opaque,
		if ((!handler || handler(opaque, data)) && thread)
			schedule_work(&virqfd->inject);
	}

	/*
	 * Do not drop the file until the irqfd is fully initialized,
	 * otherwise we might race against the EPOLLHUP.
	 */
	fdput(irqfd);

	return 0;
err_busy:
	eventfd_ctx_put(ctx);
err_ctx:
	fdput(irqfd);
err_fd:
	kfree(virqfd);

+4 −9
Original line number Diff line number Diff line
@@ -112,7 +112,6 @@ static int acrn_irqfd_assign(struct acrn_vm *vm, struct acrn_irqfd *args)
	struct eventfd_ctx *eventfd = NULL;
	struct hsm_irqfd *irqfd, *tmp;
	__poll_t events;
	struct fd f;
	int ret = 0;

	irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL);
@@ -124,8 +123,8 @@ static int acrn_irqfd_assign(struct acrn_vm *vm, struct acrn_irqfd *args)
	INIT_LIST_HEAD(&irqfd->list);
	INIT_WORK(&irqfd->shutdown, hsm_irqfd_shutdown_work);

	f = fdget(args->fd);
	if (!fd_file(f)) {
	CLASS(fd, f)(args->fd);
	if (fd_empty(f)) {
		ret = -EBADF;
		goto out;
	}
@@ -133,7 +132,7 @@ static int acrn_irqfd_assign(struct acrn_vm *vm, struct acrn_irqfd *args)
	eventfd = eventfd_ctx_fileget(fd_file(f));
	if (IS_ERR(eventfd)) {
		ret = PTR_ERR(eventfd);
		goto fail;
		goto out;
	}

	irqfd->eventfd = eventfd;
@@ -162,13 +161,9 @@ static int acrn_irqfd_assign(struct acrn_vm *vm, struct acrn_irqfd *args)
	if (events & EPOLLIN)
		acrn_irqfd_inject(irqfd);

	fdput(f);
	return 0;
fail:
	if (eventfd && !IS_ERR(eventfd))
	eventfd_ctx_put(eventfd);

	fdput(f);
out:
	kfree(irqfd);
	return ret;
+4 −13
Original line number Diff line number Diff line
@@ -967,10 +967,11 @@ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
	struct privcmd_kernel_irqfd *kirqfd, *tmp;
	unsigned long flags;
	__poll_t events;
	struct fd f;
	void *dm_op;
	int ret, idx;

	CLASS(fd, f)(irqfd->fd);

	kirqfd = kzalloc(sizeof(*kirqfd) + irqfd->size, GFP_KERNEL);
	if (!kirqfd)
		return -ENOMEM;
@@ -986,8 +987,7 @@ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
	kirqfd->dom = irqfd->dom;
	INIT_WORK(&kirqfd->shutdown, irqfd_shutdown);

	f = fdget(irqfd->fd);
	if (!fd_file(f)) {
	if (fd_empty(f)) {
		ret = -EBADF;
		goto error_kfree;
	}
@@ -995,7 +995,7 @@ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
	kirqfd->eventfd = eventfd_ctx_fileget(fd_file(f));
	if (IS_ERR(kirqfd->eventfd)) {
		ret = PTR_ERR(kirqfd->eventfd);
		goto error_fd_put;
		goto error_kfree;
	}

	/*
@@ -1028,20 +1028,11 @@ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
		irqfd_inject(kirqfd);

	srcu_read_unlock(&irqfds_srcu, idx);

	/*
	 * Do not drop the file until the kirqfd is fully initialized, otherwise
	 * we might race against the EPOLLHUP.
	 */
	fdput(f);
	return 0;

error_eventfd:
	eventfd_ctx_put(kirqfd->eventfd);

error_fd_put:
	fdput(f);

error_kfree:
	kfree(kirqfd);
	return ret;
+3 −12
Original line number Diff line number Diff line
@@ -304,7 +304,6 @@ static int
kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
{
	struct kvm_kernel_irqfd *irqfd, *tmp;
	struct fd f;
	struct eventfd_ctx *eventfd = NULL, *resamplefd = NULL;
	int ret;
	__poll_t events;
@@ -327,8 +326,8 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
	INIT_WORK(&irqfd->shutdown, irqfd_shutdown);
	seqcount_spinlock_init(&irqfd->irq_entry_sc, &kvm->irqfds.lock);

	f = fdget(args->fd);
	if (!fd_file(f)) {
	CLASS(fd, f)(args->fd);
	if (fd_empty(f)) {
		ret = -EBADF;
		goto out;
	}
@@ -336,7 +335,7 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
	eventfd = eventfd_ctx_fileget(fd_file(f));
	if (IS_ERR(eventfd)) {
		ret = PTR_ERR(eventfd);
		goto fail;
		goto out;
	}

	irqfd->eventfd = eventfd;
@@ -440,12 +439,6 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
#endif

	srcu_read_unlock(&kvm->irq_srcu, idx);

	/*
	 * do not drop the file until the irqfd is fully initialized, otherwise
	 * we might race against the EPOLLHUP
	 */
	fdput(f);
	return 0;

fail:
@@ -458,8 +451,6 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
	if (eventfd && !IS_ERR(eventfd))
		eventfd_ctx_put(eventfd);

	fdput(f);

out:
	kfree(irqfd);
	return ret;