]> xenbits.xensource.com Git - unikraft/unikraft.git/commitdiff
lib/posix-poll: Fix vfscore files w/o epoll support
authorAndrei Tatar <andrei@unikraft.io>
Thu, 11 Jan 2024 14:25:23 +0000 (15:25 +0100)
committerUnikraft Bot <monkey@unikraft.io>
Tue, 6 Feb 2024 17:19:24 +0000 (17:19 +0000)
This change makes epoll correctly handle vfscore files that do not
support being polled, such as filesystem files. Previously these would
be silently ignored, leading to hangs in epoll_wait.
Now epoll_ctl correctly errors out with -EPERM when attempting to
register a file descriptor from an unpollable vfscore file.

Signed-off-by: Andrei Tatar <andrei@unikraft.io>
Reviewed-by: Ioan-Teodor Teugea <ioan_teodor.teugea@stud.acs.upb.ro>
Reviewed-by: Mihnea Firoiu <mihneafiroiu0@gmail.com>
Approved-by: Razvan Deaconescu <razvand@unikraft.io>
GitHub-Closes: #1258

lib/posix-poll/epoll.c

index c7f65834fee47b7cda320b59c58d7ee4db39301f..46325b0b8f9197705dfc13c396801c11ede0069e 100644 (file)
@@ -123,20 +123,18 @@ static int vfs_poll(struct vfscore_file *vfd, unsigned int *revents,
        return VOP_POLL(vnode, revents, ecb);
 }
 
-static void vfs_poll_register(struct vfscore_file *vfd,
-                             struct epoll_legacy *leg)
+static int vfs_poll_register(struct vfscore_file *vfd, struct epoll_legacy *leg)
 {
-       int ret;
+       int ret = vfs_poll(vfd, &leg->revents, &leg->ecb);
 
-       ret = vfs_poll(vfd, &leg->revents, &leg->ecb);
-       if (unlikely(ret)) {
-               leg->revents = EPOLLERR;
-       } else {
-               uk_list_add_tail(&leg->f_link, &vfd->f_ep);
-               (void)uk_and(&leg->revents, leg->mask);
-               if (leg->revents)
-                       uk_file_event_set(leg->epf, UKFD_POLLIN);
-       }
+       if (unlikely(ret))
+               return -ret; /* vfscore uses positive errnos */
+
+       uk_list_add_tail(&leg->f_link, &vfd->f_ep);
+       (void)uk_and(&leg->revents, leg->mask);
+       if (leg->revents)
+               uk_file_event_set(leg->epf, UKFD_POLLIN);
+       return 0;
 }
 #endif /* CONFIG_LIBVFSCORE */
 
@@ -242,6 +240,7 @@ static int epoll_add_legacy(const struct uk_file *epf,
 {
        struct epoll_alloc *al = __containerof(epf, struct epoll_alloc, f);
        struct epoll_entry *ent;
+       int r;
 
        /* New entry */
        ent = uk_malloc(al->alloc, sizeof(*ent));
@@ -263,10 +262,17 @@ static int epoll_add_legacy(const struct uk_file *epf,
        };
        UK_INIT_LIST_HEAD(&ent->legacy_cb.ecb.cb_link);
        UK_INIT_LIST_HEAD(&ent->legacy_cb.f_link);
-       *tail = ent;
        /* Poll, register & update if needed */
-       vfs_poll_register(vf, &ent->legacy_cb);
+       r = vfs_poll_register(vf, &ent->legacy_cb);
+       if (unlikely(r)) {
+               uk_free(al->alloc, ent);
+               if (r == -EINVAL)
+                       return -EPERM;
+               else
+                       return r;
+       }
 
+       *tail = ent;
        return 0;
 }
 #endif /* CONFIG_LIBVFSCORE */