DF-2732 / iovcnt0.c
/* * DF-2732 PoC: readv/writev/extpreadv/extpwritev accept iovcnt == 0. * sys/kern/sys_generic.c:188-210,391-414,218-246,422-450 + kern_subr.c * iovec_copyin() (kern_subr.c:455 `if ((u_int)iov_cnt > UIO_MAXIOV)`). * * With iovcnt==0 the syscall proceeds with auio.uio_iov pointing at an * UNINITIALIZED stack iovec (aiov[] in sys_readv) and uio_resid==0. * POSIX: "If iovcnt is less than or equal to zero ... EINVAL". * * Build: cc -O -o iovcnt0 iovcnt0.c */ #include <sys/types.h> #include <sys/syscall.h> #include <sys/socket.h> #include <sys/uio.h> #include <errno.h> #include <stdio.h> #include <string.h> #include <unistd.h> #include <fcntl.h> #define SYS_EXTPREADV 289 #define SYS_EXTPWRITEV 290 static void show(const char *what, ssize_t r, int e) { printf("%-52s ret=%zd errno=%d (%s)\n", what, r, e, e ? strerror(e) : "-"); } int main(void) { char tmpfile[] = "/tmp/df2732.scratch"; struct iovec iov[1] = { { (void *)tmpfile, 1 } }; char buf[16]; int sv[2], fd, pf[2]; ssize_t r; fd = open(tmpfile, O_RDWR | O_CREAT | O_TRUNC, 0644); if (fd < 0) { perror("open"); return 1; } if (write(fd, "HELLO", 5) != 5) { perror("write"); } if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) < 0) { perror("socketpair"); return 1; } if (pipe(pf) < 0) { perror("pipe"); return 1; } puts("--- regular file ---"); errno = 0; r = readv(fd, NULL, 0); show("readv(file, NULL, 0) [expect EINVAL]", r, errno); errno = 0; r = readv(fd, iov, 0); show("readv(file, iov, 0)", r, errno); errno = 0; r = writev(fd, NULL, 0); show("writev(file, NULL, 0)", r, errno); errno = 0; r = syscall(SYS_EXTPREADV, fd, NULL, 0, (off_t)0, 0); show("extpreadv(file, NULL, 0, 0, 0)", r, errno); errno = 0; r = syscall(SYS_EXTPWRITEV, fd, NULL, 0, (off_t)0, 0); show("extpwritev(file, NULL, 0, 0, 0)", r, errno); puts("--- socket ---"); errno = 0; r = readv(sv[0], NULL, 0); show("readv(sock, NULL, 0)", r, errno); errno = 0; r = writev(sv[0], NULL, 0); show("writev(sock, NULL, 0)", r, errno); puts("--- pipe ---"); errno = 0; r = readv(pf[0], NULL, 0); show("readv(pipe, NULL, 0)", r, errno); errno = 0; r = writev(pf[1], NULL, 0); show("writev(pipe, NULL, 0)", r, errno); puts("--- /dev/zero ---"); { int z = open("/dev/zero", O_RDONLY); if (z >= 0) { errno = 0; r = readv(z, NULL, 0); show("readv(/dev/zero, NULL, 0)", r, errno); close(z); } } puts("--- negative control ---"); errno = 0; r = readv(fd, NULL, (int)-1); show("readv(file, NULL, -1)", r, errno); errno = 0; r = readv(fd, iov, 1); show("readv(file, iov, 1) [sanity]", r, errno); (void)buf; printf("DONE df2732\n"); return 0; } |