Re: [syzbot] [fs?] general protection fault in splice_to_socket

From: David Howells
Date: Wed Jun 14 2023 - 04:58:32 EST


Here's a much reduced test program. The key is to splice more than a page
from the pipe into the second socket (AF_ALG in this case) and more than that
into the pipe.

David
---
// https://syzkaller.appspot.com/bug?id=613f5060400df25674e1b213295ef45a8422b077
// autogenerated by syzkaller (https://github.com/google/syzkaller)
#define _GNU_SOURCE
#include <endian.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/socket.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <netinet/in.h>
#include <linux/if_alg.h>

#define OSERROR(R, S) do { if ((long)(R) == -1L) { perror((S)); exit(1); } } while(0)

static const unsigned char data[1024 * 1024] = {
"\x44\xf9\xb1\x08\xb1\xcd\xc8\x85\xc9\xc5\x33\xd2\x1f\x47\x4b\xec\x8b"
"\xfe\xf1\xdf\x1e\x2d\xa7\x1e\x57\x8d\xc6\xb9\x1d\x09\xf7\xab\x15\x37"
"\x85\x71\xd8\xe2\x75\x46\x09\x00\x00\x00\x6e\x75\x43\x69\x14\xab\x71"
"\x75\x28\xee\x4b\x7a\x9b\xea\xf9\x08\xd1\x11\x37\xc1\x19\x03\x06\x4e"
"\x83\xb4\x95\x1f\x4d\x43\x3a\x54\x04\x97\x0c\x85\xd9\x2d\x70\x83\xfd"
"\x38\x84\x4c\xbb\x0c\x6c\x5e\xb5\x08\xdd\xc2\xdc\x7a\x59\x0a\xa7\x94"
"\x1b\x1e\x9e\xeb\x5a\x68\x81\x38\xde\xa0\x9b\x77\x6c\xbf\xa7\x84\xcb"
"\xf5\x50\xbf\x30\x74\xfb\x0d\x77\x5d\xa4\xdf\x5a\x3f\x48\xbb\xdf\x45"
"\x2e\xeb\x6b\x92\x3d\xa9\xd0\xe2\x5b\x80\xf7\x6a\x87\x36\x64\xb5\x75"
"\x34\x44\xfe\x05\xf3\x3e\x5f\x91\x04\x55\x40\x83\x6c\x3c\xd6\xaf\x10"
"\xf0\xcd\x01\x8f\x0c\x6f\x57\xf9\x26\xac\x95\x9a\x56\x28\xc4\x50\x88"
"\xfb\xe0\xc8\x7f\xbe\x6c\xbc\xda\x46\x62\xd2\xa1\x2f\x6d\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",
};

int main(int argc, char *argv[])
{
struct sockaddr_in6 sin6;
struct sockaddr_alg salg;
int pipefd[2], ipv6fd, algfd, hashfd, res, wt;

res = pipe(pipefd);
OSERROR(res, "pipe");

ipv6fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_IP);
OSERROR(ipv6fd, "socket/inet6");

memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_port = htons(2);

res = bind(ipv6fd, (struct sockaddr *)&sin6, sizeof(sin6));
OSERROR(res, "bind/inet6");

memset(&sin6, 0, sizeof(sin6));
sin6.sin6_family = AF_INET6;
sin6.sin6_port = htons(2);
sin6.sin6_addr.s6_addr[15] = 1;
res = sendto(ipv6fd, NULL, 0, MSG_OOB|MSG_NOSIGNAL|MSG_FASTOPEN|0x2000000,
(struct sockaddr *)&sin6, sizeof(sin6));
OSERROR(res, "sendto_1");

res = send(ipv6fd, data, 0xd0d0c2ac /* massive overrun */, MSG_OOB);
OSERROR(res, "sendto_2");

algfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
OSERROR(algfd, "socket/alg");

memset(&salg, 0, sizeof(salg));
salg.salg_family = AF_ALG;
strcpy(salg.salg_type, "hash");
strcpy(salg.salg_name, "sha3-512");
res = bind(algfd, (struct sockaddr *)&salg, sizeof(salg));
OSERROR(res, "bind/alg");

hashfd = accept4(algfd, NULL, 0, 0);
OSERROR(hashfd, "accept/alg");

switch (fork()) {
case -1:
OSERROR(-1, "fork");
case 0:
res = splice(pipefd[0], 0, hashfd, 0, 65536, 0);
OSERROR(res, "splice/p->h");
return 0;
default:
sleep(1);
break;
}

res = splice(ipv6fd, 0, pipefd[1], 0, 32767, 0);
OSERROR(res, "splice/i->p");
wait(&wt);
return 0;
}