rfkill: use short writes and accept long reads
I'm seeing the following with kernel-core-5.10.16-200.fc33.x86_64: $ sudo SYSTEMD_LOG_LEVEL=debug build/systemd-rfkill Reading struct rfkill_event: got 8 bytes. A new rfkill device has been added with index 0 and type bluetooth. Found cgroup2 on /sys/fs/cgroup/, full unified hierarchy Found container virtualization none. rfkill0: Operating on rfkill device 'tpacpi_bluetooth_sw'. Writing struct rfkill_event successful (8 of 9 bytes). Loaded state '0' from /var/lib/systemd/rfkill/platform-thinkpad_acpi:bluetooth. Reading struct rfkill_event: got 8 bytes. A new rfkill device has been added with index 1 and type wwan. rfkill1: Operating on rfkill device 'tpacpi_wwan_sw'. Writing struct rfkill_event successful (8 of 9 bytes). Loaded state '0' from /var/lib/systemd/rfkill/platform-thinkpad_acpi:wwan. Reading struct rfkill_event: got 8 bytes. A new rfkill device has been added with index 2 and type bluetooth. rfkill2: Operating on rfkill device 'hci0'. Writing struct rfkill_event successful (8 of 9 bytes). Loaded state '0' from /var/lib/systemd/rfkill/pci-0000:00:14.0-usb-0:7:1.0:bluetooth. Reading struct rfkill_event: got 8 bytes. A new rfkill device has been added with index 3 and type wlan. rfkill3: Operating on rfkill device 'phy0'. Writing struct rfkill_event successful (8 of 9 bytes). Loaded state '0' from /var/lib/systemd/rfkill/pci-0000:04:00.0:wlan. All events read and idle, exiting. We were expecting a read of exactly RFKILL_EVENT_SIZE_V1==8 bytes. But the structure has 9 after [1]. [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=14486c82612a177cb910980c70ba900827ca0894 For some reason the kernel does not accept the full structure size, but cuts the write short after 8 bytes: static ssize_t rfkill_fop_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) { struct rfkill_event ev; /* we don't need the 'hard' variable but accept it */ if (count < RFKILL_EVENT_SIZE_V1 - 1) return -EINVAL; /* * Copy as much data as we can accept into our 'ev' buffer, * but tell userspace how much we've copied so it can determine * our API version even in a write() call, if it cares. */ count = min(count, sizeof(ev)); if (copy_from_user(&ev, buf, count)) return -EFAULT; ... so it should accept the full size. I'm not sure what is going on here. But we don't care about the extra fields, so let's accept a write as long as it's at least RFKILL_EVENT_SIZE_V1. Fixes #18677. (cherry picked from commit a71c0968) (cherry picked from commit 310c58b1)
Loading
Please register or sign in to comment