diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c index 2a6f463701e1..bb708afad103 100644 --- a/sys/fs/devfs/devfs_vnops.c +++ b/sys/fs/devfs/devfs_vnops.c @@ -921,6 +921,22 @@ fiodgname_buf_get_ptr(void *fgnp, u_long com) } } +static int +devfs_inotify(struct vop_inotify_args *ap) +{ + /* + * Don't provide inotify for devfs nodes. Most of the inotify hooks + * don't fire anyway since devfs files do not use the vnode I/O path. + * If that were not the case, however, inotify could be abused to leak + * sensitive timing information, e.g., by watching for reads from + * /dev/input. Thus, we make inotify do nothing here as a safeguard. + * + * At some point it may be desirable to enable inotify for specific + * device files. + */ + return (0); +} + static int devfs_ioctl(struct vop_ioctl_args *ap) { @@ -2126,6 +2142,7 @@ static struct vop_vector devfs_vnodeops = { .vop_access = devfs_access, .vop_getattr = devfs_getattr, + .vop_inotify = devfs_inotify, .vop_ioctl = devfs_rioctl, .vop_lookup = devfs_lookup, .vop_mknod = devfs_mknod, @@ -2159,6 +2176,7 @@ static struct vop_vector devfs_specops = { .vop_create = VOP_PANIC, .vop_fsync = vop_stdfsync, .vop_getattr = devfs_getattr, + .vop_inotify = devfs_inotify, .vop_ioctl = devfs_ioctl, .vop_link = VOP_PANIC, .vop_mkdir = VOP_PANIC, diff --git a/tests/sys/kern/inotify_test.c b/tests/sys/kern/inotify_test.c index 0c2cc260f29e..8f16b9949932 100644 --- a/tests/sys/kern/inotify_test.c +++ b/tests/sys/kern/inotify_test.c @@ -318,6 +318,40 @@ ATF_TC_BODY(inotify_mask_create, tc) close_inotify(ifd); } +/* + * Verify that inotify events are not generated for devfs. In principle such + * events could leak timing information about I/O device accesses. + */ +ATF_TC_WITHOUT_HEAD(inotify_devfs); +ATF_TC_BODY(inotify_devfs, tc) +{ + char buf[1]; + int fd, ifd, n, wd1, wd2, wd3; + + ifd = inotify(IN_NONBLOCK); + + wd1 = inotify_add_watch(ifd, "/dev", IN_ALL_EVENTS); + ATF_REQUIRE(wd1 >= 0); + wd2 = inotify_add_watch(ifd, "/dev/null", IN_ALL_EVENTS); + ATF_REQUIRE(wd2 >= 0); + wd3 = inotify_add_watch(ifd, "/dev/zero", IN_ALL_EVENTS); + ATF_REQUIRE(wd3 >= 0); + + fd = open("/dev/null", O_WRONLY); + ATF_REQUIRE(fd != -1); + ATF_REQUIRE(write(fd, buf, sizeof(buf)) == (ssize_t)sizeof(buf)); + close_checked(fd); + + fd = open("/dev/zero", O_RDONLY); + ATF_REQUIRE(fd != -1); + ATF_REQUIRE(read(fd, buf, sizeof(buf)) == (ssize_t)sizeof(buf)); + close_checked(fd); + + ATF_REQUIRE(ioctl(ifd, FIONREAD, &n) == 0); + ATF_REQUIRE_MSG(n == 0, "unexpected %d bytes of inotify events", n); + close_checked(ifd); +} + /* * Make sure that inotify cooperates with nullfs: if a lower vnode is the * subject of an event, the upper vnode should be notified, and if the upper @@ -1011,6 +1045,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, inotify_capsicum); ATF_TP_ADD_TC(tp, inotify_coalesce); ATF_TP_ADD_TC(tp, inotify_mask_create); + ATF_TP_ADD_TC(tp, inotify_devfs); ATF_TP_ADD_TC(tp, inotify_nullfs); ATF_TP_ADD_TC(tp, inotify_nullfs_remove); ATF_TP_ADD_TC(tp, inotify_nullfs_rename);