mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-12-29 09:16:33 +00:00
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: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
parent
8935989798
commit
66635b0776
@ -113,7 +113,6 @@ int vfio_virqfd_enable(void *opaque,
|
|||||||
void (*thread)(void *, void *),
|
void (*thread)(void *, void *),
|
||||||
void *data, struct virqfd **pvirqfd, int fd)
|
void *data, struct virqfd **pvirqfd, int fd)
|
||||||
{
|
{
|
||||||
struct fd irqfd;
|
|
||||||
struct eventfd_ctx *ctx;
|
struct eventfd_ctx *ctx;
|
||||||
struct virqfd *virqfd;
|
struct virqfd *virqfd;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
@ -133,8 +132,8 @@ int vfio_virqfd_enable(void *opaque,
|
|||||||
INIT_WORK(&virqfd->inject, virqfd_inject);
|
INIT_WORK(&virqfd->inject, virqfd_inject);
|
||||||
INIT_WORK(&virqfd->flush_inject, virqfd_flush_inject);
|
INIT_WORK(&virqfd->flush_inject, virqfd_flush_inject);
|
||||||
|
|
||||||
irqfd = fdget(fd);
|
CLASS(fd, irqfd)(fd);
|
||||||
if (!fd_file(irqfd)) {
|
if (fd_empty(irqfd)) {
|
||||||
ret = -EBADF;
|
ret = -EBADF;
|
||||||
goto err_fd;
|
goto err_fd;
|
||||||
}
|
}
|
||||||
@ -142,7 +141,7 @@ int vfio_virqfd_enable(void *opaque,
|
|||||||
ctx = eventfd_ctx_fileget(fd_file(irqfd));
|
ctx = eventfd_ctx_fileget(fd_file(irqfd));
|
||||||
if (IS_ERR(ctx)) {
|
if (IS_ERR(ctx)) {
|
||||||
ret = PTR_ERR(ctx);
|
ret = PTR_ERR(ctx);
|
||||||
goto err_ctx;
|
goto err_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
virqfd->eventfd = ctx;
|
virqfd->eventfd = ctx;
|
||||||
@ -181,18 +180,9 @@ int vfio_virqfd_enable(void *opaque,
|
|||||||
if ((!handler || handler(opaque, data)) && thread)
|
if ((!handler || handler(opaque, data)) && thread)
|
||||||
schedule_work(&virqfd->inject);
|
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;
|
return 0;
|
||||||
err_busy:
|
err_busy:
|
||||||
eventfd_ctx_put(ctx);
|
eventfd_ctx_put(ctx);
|
||||||
err_ctx:
|
|
||||||
fdput(irqfd);
|
|
||||||
err_fd:
|
err_fd:
|
||||||
kfree(virqfd);
|
kfree(virqfd);
|
||||||
|
|
||||||
|
@ -112,7 +112,6 @@ static int acrn_irqfd_assign(struct acrn_vm *vm, struct acrn_irqfd *args)
|
|||||||
struct eventfd_ctx *eventfd = NULL;
|
struct eventfd_ctx *eventfd = NULL;
|
||||||
struct hsm_irqfd *irqfd, *tmp;
|
struct hsm_irqfd *irqfd, *tmp;
|
||||||
__poll_t events;
|
__poll_t events;
|
||||||
struct fd f;
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
irqfd = kzalloc(sizeof(*irqfd), GFP_KERNEL);
|
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_LIST_HEAD(&irqfd->list);
|
||||||
INIT_WORK(&irqfd->shutdown, hsm_irqfd_shutdown_work);
|
INIT_WORK(&irqfd->shutdown, hsm_irqfd_shutdown_work);
|
||||||
|
|
||||||
f = fdget(args->fd);
|
CLASS(fd, f)(args->fd);
|
||||||
if (!fd_file(f)) {
|
if (fd_empty(f)) {
|
||||||
ret = -EBADF;
|
ret = -EBADF;
|
||||||
goto out;
|
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));
|
eventfd = eventfd_ctx_fileget(fd_file(f));
|
||||||
if (IS_ERR(eventfd)) {
|
if (IS_ERR(eventfd)) {
|
||||||
ret = PTR_ERR(eventfd);
|
ret = PTR_ERR(eventfd);
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
irqfd->eventfd = eventfd;
|
irqfd->eventfd = eventfd;
|
||||||
@ -162,13 +161,9 @@ static int acrn_irqfd_assign(struct acrn_vm *vm, struct acrn_irqfd *args)
|
|||||||
if (events & EPOLLIN)
|
if (events & EPOLLIN)
|
||||||
acrn_irqfd_inject(irqfd);
|
acrn_irqfd_inject(irqfd);
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
return 0;
|
return 0;
|
||||||
fail:
|
fail:
|
||||||
if (eventfd && !IS_ERR(eventfd))
|
eventfd_ctx_put(eventfd);
|
||||||
eventfd_ctx_put(eventfd);
|
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
out:
|
out:
|
||||||
kfree(irqfd);
|
kfree(irqfd);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -967,10 +967,11 @@ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
|
|||||||
struct privcmd_kernel_irqfd *kirqfd, *tmp;
|
struct privcmd_kernel_irqfd *kirqfd, *tmp;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
__poll_t events;
|
__poll_t events;
|
||||||
struct fd f;
|
|
||||||
void *dm_op;
|
void *dm_op;
|
||||||
int ret, idx;
|
int ret, idx;
|
||||||
|
|
||||||
|
CLASS(fd, f)(irqfd->fd);
|
||||||
|
|
||||||
kirqfd = kzalloc(sizeof(*kirqfd) + irqfd->size, GFP_KERNEL);
|
kirqfd = kzalloc(sizeof(*kirqfd) + irqfd->size, GFP_KERNEL);
|
||||||
if (!kirqfd)
|
if (!kirqfd)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@ -986,8 +987,7 @@ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
|
|||||||
kirqfd->dom = irqfd->dom;
|
kirqfd->dom = irqfd->dom;
|
||||||
INIT_WORK(&kirqfd->shutdown, irqfd_shutdown);
|
INIT_WORK(&kirqfd->shutdown, irqfd_shutdown);
|
||||||
|
|
||||||
f = fdget(irqfd->fd);
|
if (fd_empty(f)) {
|
||||||
if (!fd_file(f)) {
|
|
||||||
ret = -EBADF;
|
ret = -EBADF;
|
||||||
goto error_kfree;
|
goto error_kfree;
|
||||||
}
|
}
|
||||||
@ -995,7 +995,7 @@ static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
|
|||||||
kirqfd->eventfd = eventfd_ctx_fileget(fd_file(f));
|
kirqfd->eventfd = eventfd_ctx_fileget(fd_file(f));
|
||||||
if (IS_ERR(kirqfd->eventfd)) {
|
if (IS_ERR(kirqfd->eventfd)) {
|
||||||
ret = PTR_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);
|
irqfd_inject(kirqfd);
|
||||||
|
|
||||||
srcu_read_unlock(&irqfds_srcu, idx);
|
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;
|
return 0;
|
||||||
|
|
||||||
error_eventfd:
|
error_eventfd:
|
||||||
eventfd_ctx_put(kirqfd->eventfd);
|
eventfd_ctx_put(kirqfd->eventfd);
|
||||||
|
|
||||||
error_fd_put:
|
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
error_kfree:
|
error_kfree:
|
||||||
kfree(kirqfd);
|
kfree(kirqfd);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -304,7 +304,6 @@ static int
|
|||||||
kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
|
kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
|
||||||
{
|
{
|
||||||
struct kvm_kernel_irqfd *irqfd, *tmp;
|
struct kvm_kernel_irqfd *irqfd, *tmp;
|
||||||
struct fd f;
|
|
||||||
struct eventfd_ctx *eventfd = NULL, *resamplefd = NULL;
|
struct eventfd_ctx *eventfd = NULL, *resamplefd = NULL;
|
||||||
int ret;
|
int ret;
|
||||||
__poll_t events;
|
__poll_t events;
|
||||||
@ -327,8 +326,8 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
|
|||||||
INIT_WORK(&irqfd->shutdown, irqfd_shutdown);
|
INIT_WORK(&irqfd->shutdown, irqfd_shutdown);
|
||||||
seqcount_spinlock_init(&irqfd->irq_entry_sc, &kvm->irqfds.lock);
|
seqcount_spinlock_init(&irqfd->irq_entry_sc, &kvm->irqfds.lock);
|
||||||
|
|
||||||
f = fdget(args->fd);
|
CLASS(fd, f)(args->fd);
|
||||||
if (!fd_file(f)) {
|
if (fd_empty(f)) {
|
||||||
ret = -EBADF;
|
ret = -EBADF;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@ -336,7 +335,7 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
|
|||||||
eventfd = eventfd_ctx_fileget(fd_file(f));
|
eventfd = eventfd_ctx_fileget(fd_file(f));
|
||||||
if (IS_ERR(eventfd)) {
|
if (IS_ERR(eventfd)) {
|
||||||
ret = PTR_ERR(eventfd);
|
ret = PTR_ERR(eventfd);
|
||||||
goto fail;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
irqfd->eventfd = eventfd;
|
irqfd->eventfd = eventfd;
|
||||||
@ -440,12 +439,6 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
srcu_read_unlock(&kvm->irq_srcu, idx);
|
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;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
@ -458,8 +451,6 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
|
|||||||
if (eventfd && !IS_ERR(eventfd))
|
if (eventfd && !IS_ERR(eventfd))
|
||||||
eventfd_ctx_put(eventfd);
|
eventfd_ctx_put(eventfd);
|
||||||
|
|
||||||
fdput(f);
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
kfree(irqfd);
|
kfree(irqfd);
|
||||||
return ret;
|
return ret;
|
||||||
|
Loading…
Reference in New Issue
Block a user