Control: retitle 854421 kernel dumps arbitrary memory when splice()ing from /dev/null Control: reassign 854421 linux-image-4.9.0-1-amd64 4.9.2-2 Control: fixed 854421 4.9.6-3
i've been able to replicate the misbehavior described in https://bugs.debian.org/854421 on two different machines, each running linux-image-4.9.0-1-amd64 4.9.2-2. I find i'm able to reproduce it with the same series of syscalls that "systemctl cat" used, so i can conclusively say this is not a systemctl bug. Attached is a Makefile and a reproducer C program. I've also published the same thing via git so you should be able to try reproducing with: git clone https://0xacab.org/dkg/debian-bug-854421 cd debian-bug-854421 make I find that it's not reliably reproducible -- sometimes the 4.9.2-2 kernel does the right thing, which is why my test tries 20 times in a row -- to be likely to catch it happening at least once. I note that the data dumped seems arbitrary -- sometimes it's highly-structured, other times just a string of NUL characters. I tried upgrading one of the 4.9.2-2 machines to 4.9.6-3 and was unable to get the reproducer to run after the upgrade, but i don't know whether that means the underlying problem has been robustly fixed or just somehow hidden. Regards, --dkg
#!/usr/bin/make -f # wants hd from bsdmainutils # Author: Daniel Kahn Gillmor <d...@fifthhorseman.net> test: splicenull uname -a for x in $$(seq 1 20); do ./splicenull | hd; done strace: splicenull strace -T -tt ./splicenull | hd splicenull: splicenull.c gcc -o $@ -pedantic -Wall -Werror $< clean: rm -f splicenull .PHONY: test clean strace
#define _GNU_SOURCE #include <sys/types.h> #include <sys/socket.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <sys/sendfile.h> #include <errno.h> #include <sys/syscall.h> /* copy_file_range from: https://github.com/systemd/systemd/blob/master/src/basic/missing_syscall.h#L270 */ static inline ssize_t copy_file_range(int fd_in, loff_t *off_in, int fd_out, loff_t *off_out, size_t len, unsigned int flags) { # ifdef __NR_copy_file_range return syscall(__NR_copy_file_range, fd_in, off_in, fd_out, off_out, len, flags); # else errno = ENOSYS; return -1; # endif } int main() { ssize_t ret = 0; int fd = -1, sock = -1; sock = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); fd = open("/dev/null", O_RDONLY|O_NOCTTY|O_CLOEXEC); if (fd == -1) return 1; ret = write(1, "# /dev/null\n", 12); if (ret != 12) return 2; ret = copy_file_range(fd, NULL, 1, NULL, 0x7fffffffffffffff, 0); if (ret != -1 || errno != EXDEV) return 3; ret = sendfile(1, fd, NULL, 0x7fffffffffffffff); if (ret != -1 || errno != EINVAL) return 4; ret = splice(fd, NULL, 1, NULL, 0x7fffffffffffffff, 0); close (sock); return ret; }
signature.asc
Description: PGP signature