Issue created by Sang Woo Kim:
https://gitlab.rtems.org/rtems/pkg/rtems-libbsd/-/work_items/104
## Summary
`read()` on a socket intermittently answers `EINVAL` and, in a libevent
program, wedges the event loop. Which descriptors are hit depends on the
numbers a program happens to get, so it looks like a race. Present on
`7-freebsd-14`, `6-freebsd-14` and `6-freebsd-12`.
`rtems_bsd_sysgen_read()` is the `read_h` of all four handler tables and starts
with
```c
struct vnode *vp = rtems_bsd_libio_iop_to_vnode(iop);
...
if (vp->v_type == VDIR)
return kern_getdirentries(...);
```
but `node_access` carries a `struct vnode *` only for descriptors opened
through the VFS — `rtems_bsd_libio_loc_set_vnode()` is called only on the
`dirops` and `fileops` paths. For a socket, a pipe or a kqueue,
`rtems_bsd_libio_iop_set_bsd_descriptor()` parks the iop itself there. Reading
`v_type` out of that is a read several hundred bytes past the end of a 44-byte
`rtems_libio_tt`, landing inside a neighbouring iop; when that word happens to
be `VDIR`, `read()` on a socket calls `kern_getdirentries()` and answers
`EINVAL`. Seen on libevent's notify socketpair, 32 times in one run:
```
BSDREAD PUN fd=13 bsd=6 iop=0x610ee8 v_type=2
```
Fix: `rtems_bsd_is_libbsd_nvops(iop)` is already the discriminator — it is true
exactly for the two handler tables whose `node_access` is a vnode. Have
`rtems_bsd_libio_iop_to_vnode()` answer NULL for the rest rather than hand back
a punned pointer.
[7-freebsd-14](https://github.com/physwkim/rtems-libbsd/commit/d4f32ebb1a1455a5800fcf0dd4574856afbfce2a)
·
[6-freebsd-14](https://github.com/physwkim/rtems-libbsd/commit/aaa929f60ca06aaec9c0e8798884ff6758c3a029)
·
[6-freebsd-12](https://github.com/physwkim/rtems-libbsd/commit/e1c3bbd6d8147ac2acfd5b9c94823be2d63e361f)
## Steps to reproduce
```c
for (i = 0; i < 48; i++) {
socketpair(AF_UNIX, SOCK_STREAM, 0, p[i]);
write(p[i][1], "x", 1);
if (read(p[i][0], b, sizeof b) != 1)
printf("fd %d: errno %d\n", p[i][0], errno); /* EINVAL */
}
```
`recv()` on the same descriptor succeeds — the two differ only in that `read()`
goes through `rtems_bsd_sysgen_read()`.
--
View it on GitLab:
https://gitlab.rtems.org/rtems/pkg/rtems-libbsd/-/work_items/104
You're receiving this email because of your account on gitlab.rtems.org.
Unsubscribe from this thread:
https://gitlab.rtems.org/-/sent_notifications/4-54senvnc1wdrtgv6y43f9mo5f-k/unsubscribe
| Manage all notifications: https://gitlab.rtems.org/-/profile/notifications |
Help: https://gitlab.rtems.org/help
_______________________________________________
bugs mailing list
[email protected]
http://lists.rtems.org/mailman/listinfo/bugs