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;
}
  

Attachment: signature.asc
Description: PGP signature

_______________________________________________
Pkg-systemd-maintainers mailing list
Pkg-systemd-maintainers@lists.alioth.debian.org
http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-systemd-maintainers

Reply via email to