{"id":2218865,"url":"http://patchwork.ozlabs.org/api/1.0/covers/2218865/?format=json","project":{"id":8,"url":"http://patchwork.ozlabs.org/api/1.0/projects/8/?format=json","name":"Linux ext4 filesystem development","link_name":"linux-ext4","list_id":"linux-ext4.vger.kernel.org","list_email":"linux-ext4@vger.kernel.org","web_url":null,"scm_url":null,"webscm_url":null},"msgid":"<20260401220837.2424925-1-kovalev@altlinux.org>","date":"2026-04-01T22:08:35","name":"[0/2] ext2: fix WARN_ON in drop_nlink() triggered by corrupt images","submitter":{"id":86433,"url":"http://patchwork.ozlabs.org/api/1.0/people/86433/?format=json","name":"Vasiliy Kovalev","email":"kovalev@altlinux.org"},"series":[{"id":498405,"url":"http://patchwork.ozlabs.org/api/1.0/series/498405/?format=json","date":"2026-04-01T22:08:37","name":"ext2: fix WARN_ON in drop_nlink() triggered by corrupt images","version":1,"mbox":"http://patchwork.ozlabs.org/series/498405/mbox/"}],"headers":{"Return-Path":"\n <SRS0=gkZ3=CA=vger.kernel.org=linux-ext4+bounces-15594-patchwork-incoming=ozlabs.org@ozlabs.org>","X-Original-To":["incoming@patchwork.ozlabs.org","linux-ext4@vger.kernel.org"],"Delivered-To":["patchwork-incoming@legolas.ozlabs.org","patchwork-incoming@ozlabs.org"],"Authentication-Results":["legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=ozlabs.org\n (client-ip=150.107.74.76; helo=mail.ozlabs.org;\n envelope-from=srs0=gkz3=ca=vger.kernel.org=linux-ext4+bounces-15594-patchwork-incoming=ozlabs.org@ozlabs.org;\n receiver=patchwork.ozlabs.org)","gandalf.ozlabs.org;\n arc=pass smtp.remote-ip=172.234.253.10 arc.chain=subspace.kernel.org","gandalf.ozlabs.org;\n dmarc=none (p=none dis=none) header.from=altlinux.org","gandalf.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=vger.kernel.org\n (client-ip=172.234.253.10; helo=sea.lore.kernel.org;\n envelope-from=linux-ext4+bounces-15594-patchwork-incoming=ozlabs.org@vger.kernel.org;\n receiver=ozlabs.org)","smtp.subspace.kernel.org;\n arc=none smtp.client-ip=193.43.8.18","smtp.subspace.kernel.org;\n dmarc=none (p=none dis=none) header.from=altlinux.org","smtp.subspace.kernel.org;\n spf=pass smtp.mailfrom=altlinux.org"],"Received":["from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fmK5X2L8hz1yFv\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 02 Apr 2026 09:14:08 +1100 (AEDT)","from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3])\n\tby gandalf.ozlabs.org (Postfix) with ESMTP id 4fmK5X1n3xz4wSX\n\tfor <incoming@patchwork.ozlabs.org>; Thu, 02 Apr 2026 09:14:08 +1100 (AEDT)","by gandalf.ozlabs.org (Postfix)\n\tid 4fmK5X1fTfz4wSR; Thu, 02 Apr 2026 09:14:08 +1100 (AEDT)","from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519)\n\t(No client certificate requested)\n\tby gandalf.ozlabs.org (Postfix) with ESMTPS id 4fmK5S47dLz4wSX\n\tfor <patchwork-incoming@ozlabs.org>; Thu, 02 Apr 2026 09:14:04 +1100 (AEDT)","from smtp.subspace.kernel.org (conduit.subspace.kernel.org\n [100.90.174.1])\n\tby sea.lore.kernel.org (Postfix) with ESMTP id DE189308F8CF\n\tfor <patchwork-incoming@ozlabs.org>; Wed,  1 Apr 2026 22:08:52 +0000 (UTC)","from localhost.localdomain (localhost.localdomain [127.0.0.1])\n\tby smtp.subspace.kernel.org (Postfix) with ESMTP id 3E5BD37D111;\n\tWed,  1 Apr 2026 22:08:51 +0000 (UTC)","from air.basealt.ru (air.basealt.ru [193.43.8.18])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby smtp.subspace.kernel.org (Postfix) with ESMTPS id 7749D344D85;\n\tWed,  1 Apr 2026 22:08:47 +0000 (UTC)","from altlinux.ipa.basealt.ru (unknown [193.43.11.2])\n\t(Authenticated sender: kovalevvv)\n\tby air.basealt.ru (Postfix) with ESMTPSA id 3FC55233AB;\n\tThu,  2 Apr 2026 01:08:38 +0300 (MSK)"],"ARC-Seal":["i=2; a=rsa-sha256; d=ozlabs.org; s=201707; t=1775081648; cv=pass;\n\tb=PQonQT+4wz0Y4flVJutK1te7IFh8v0N5HDZHNO/cXtrHV3ykbl/t7BRVTEXtXwo+63O490cus6n8u9sX3j5jt072mqJBSdpudgPfU4LvZ38VH41lf6s2doI1g7jeRcRGiVGNVvOcE5S2bJ/nSwFpHy2sTOdanv/JnXI3AhW7leZ2jGD8EGeBjCCp5Cv6zMoz/NHZrAXVdJHe+ewgS0qKTsuXD496hIYs4g9NCSoGHWdM8qLz7OpzsMOjagaICPsh4PCksPaBQmaVGDJOqIUCaiSjXsiHjCh1Hpwo7gT+7Tc42zoyXAdpPqs7AuzLdzLmdtDFAjHW3VU9unhsNtL0+Q==","i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;\n\tt=1775081331; cv=none;\n b=G/6XnhvwCi6xqmGBsHMXvmHq3rbsstXZeD8EnEEm6Ay/gqbzYk/YpfwIQP/2RWZxTrh6yTFzf8uVFEVCObUpEuFz3i7qOdVlqdazyaJQ0M32miyX+dgcaXcCyn/1CLDkmuRa9kMmqUfbHmZPvduUrz/LYMv0NFyCd4ccXnHixYc="],"ARC-Message-Signature":["i=2; a=rsa-sha256; d=ozlabs.org; s=201707;\n\tt=1775081648; c=relaxed/relaxed;\n\tbh=akHwpbqZAuDNsPXKKDt+ZphHGCQmXoZdICibMJmFhcA=;\n\th=From:To:Cc:Subject:Date:Message-Id:MIME-Version;\n b=pbxwBvPYVhqTQ+ARRrDIqN3vFoAVIzVLagDWGNi3mP7ZvdltgIa0P/GvwYwwmbMZr4nWaaPp66RpzXbrCsUQBgvurIrI0LZe2v/PtesAQmjI0j3IIE0cEqnPY615VZHrkDGPDswdWrEdvMN8aMDUsfZs0j8P+IreJ79R77ElyJrdVvMLqhnHqYnol6iDM551XO77RJPCx1IFT0/aVXZVElsD1bMXkXRoQJwEadTkEF8HXqDnLMIcO2zkbhHDDl5T+Ea2lR4hyIWITRrZp6Nw6+DGJJkzufiHLhk6Dc5scxbF5hggCB2mF02HrZBPbPd17HTxi9/qNBd6qXMi97Mg0A==","i=1; a=rsa-sha256; d=subspace.kernel.org;\n\ts=arc-20240116; t=1775081331; c=relaxed/simple;\n\tbh=zwPY88dG0zvoXZ6euWOlBqEbGJHP7i0uE9pDhYWhB8k=;\n\th=From:To:Cc:Subject:Date:Message-Id:MIME-Version;\n b=nATTDRuL60M65MSQUgsa147nE7uBv5g1WosM9WPxUcMwNBNzYsArTB7Rsmg/Lj1BOUHBsCR5yzALfgwSpicUnLZdrcFEo/K73+Oodhun4Zfum+JHxWZyA/ob8Z4Pnv+jfIzYltZCra5sxfs+kaTZPm8o0CPFl3oL909+Ae1CuWA="],"ARC-Authentication-Results":["i=2; gandalf.ozlabs.org;\n dmarc=none (p=none dis=none) header.from=altlinux.org;\n spf=pass (client-ip=172.234.253.10; helo=sea.lore.kernel.org;\n envelope-from=linux-ext4+bounces-15594-patchwork-incoming=ozlabs.org@vger.kernel.org;\n receiver=ozlabs.org) smtp.mailfrom=vger.kernel.org","i=1; smtp.subspace.kernel.org;\n dmarc=none (p=none dis=none) header.from=altlinux.org;\n spf=pass smtp.mailfrom=altlinux.org; arc=none smtp.client-ip=193.43.8.18"],"From":"Vasiliy Kovalev <kovalev@altlinux.org>","To":"Jan Kara <jack@suse.com>,\n\tAndrew Morton <akpm@osdl.org>,\n\tAlexey Dobriyan <adobriyan@gmail.com>,\n\tlinux-ext4@vger.kernel.org","Cc":"linux-kernel@vger.kernel.org,\n\tlvc-project@linuxtesting.org,\n\tkovalev@altlinux.org","Subject":"[PATCH 0/2] ext2: fix WARN_ON in drop_nlink() triggered by corrupt\n images","Date":"Thu,  2 Apr 2026 01:08:35 +0300","Message-Id":"<20260401220837.2424925-1-kovalev@altlinux.org>","X-Mailer":"git-send-email 2.33.8","Precedence":"bulk","X-Mailing-List":"linux-ext4@vger.kernel.org","List-Id":"<linux-ext4.vger.kernel.org>","List-Subscribe":"<mailto:linux-ext4+subscribe@vger.kernel.org>","List-Unsubscribe":"<mailto:linux-ext4+unsubscribe@vger.kernel.org>","MIME-Version":"1.0","Content-Transfer-Encoding":"quoted-printable","X-Spam-Status":"No, score=-1.1 required=5.0 tests=ARC_SIGNED,ARC_VALID,\n\tDMARC_MISSING,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,\n\tSPF_HELO_NONE,SPF_PASS autolearn=disabled version=4.0.1","X-Spam-Checker-Version":"SpamAssassin 4.0.1 (2024-03-25) on gandalf.ozlabs.org"},"content":"A crafted ext2 image can contain a directory entry pointing to an inode\nwhose on-disk i_links_count is zero. ext2 mounts such an image without\nerror. Any subsequent syscall that decrements i_nlink on that inode\ntriggers WARN_ON inside drop_nlink() in fs/inode.c.\n\nThese patches prevent the warning by validating i_nlink before decrementing\nit in ext2_unlink() and ext2_rename(), reporting the corruption via\next2_error() instead.\n\nThe issues were found by Linux Verification Center (linuxtesting.org)\nwith Syzkaller.\n\nVasiliy Kovalev (2):\n  ext2: validate i_nlink before decrement in ext2_unlink()\n  ext2: guard against zero i_nlink on new_inode in ext2_rename()\n\n fs/ext2/namei.c | 14 +++++++++++++-\n 1 file changed, 13 insertions(+), 1 deletion(-)\n\n--- [Reproducer for PATCH 1/2: ext2_unlink] ---\n\n#define _GNU_SOURCE\n\n#include <dirent.h>\n#include <endian.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <sched.h>\n#include <setjmp.h>\n#include <signal.h>\n#include <stdarg.h>\n#include <stdbool.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/ioctl.h>\n#include <sys/mman.h>\n#include <sys/mount.h>\n#include <sys/prctl.h>\n#include <sys/stat.h>\n#include <sys/syscall.h>\n#include <sys/types.h>\n#include <sys/wait.h>\n#include <time.h>\n#include <unistd.h>\n\n#include <linux/loop.h>\n\n#ifndef __NR_memfd_create\n#define __NR_memfd_create 319\n#endif\n\nstatic unsigned long long procid;\n\nstatic void sleep_ms(uint64_t ms)\n{\n\tusleep(ms * 1000);\n}\n\nstatic uint64_t current_time_ms(void)\n{\n\tstruct timespec ts;\n\tif (clock_gettime(CLOCK_MONOTONIC, &ts))\n\texit(1);\n\treturn (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;\n}\n\nstatic void use_temporary_dir(void)\n{\n\tchar tmpdir_template[] = \"./syzkaller.XXXXXX\";\n\tchar* tmpdir = mkdtemp(tmpdir_template);\n\tif (!tmpdir)\n\texit(1);\n\tif (chmod(tmpdir, 0777))\n\texit(1);\n\tif (chdir(tmpdir))\n\texit(1);\n}\n\nstatic bool write_file(const char* file, const char* what, ...)\n{\n\tchar buf[1024];\n\tva_list args;\n\tva_start(args, what);\n\tvsnprintf(buf, sizeof(buf), what, args);\n\tva_end(args);\n\tbuf[sizeof(buf) - 1] = 0;\n\tint len = strlen(buf);\n\tint fd = open(file, O_WRONLY | O_CLOEXEC);\n\tif (fd == -1)\n\t\treturn false;\n\tif (write(fd, buf, len) != len) {\n\t\tint err = errno;\n\t\tclose(fd);\n\t\terrno = err;\n\t\treturn false;\n\t}\n\tclose(fd);\n\treturn true;\n}\n\n#define MAXBITS 15\n#define MAXLCODES 286\n#define MAXDCODES 30\n#define MAXCODES (MAXLCODES + MAXDCODES)\n#define FIXLCODES 288\n\nstruct puff_state {\n\tunsigned char* out;\n\tunsigned long outlen;\n\tunsigned long outcnt;\n\tconst unsigned char* in;\n\tunsigned long inlen;\n\tunsigned long incnt;\n\tint bitbuf;\n\tint bitcnt;\n\tjmp_buf env;\n};\nstatic int puff_bits(struct puff_state* s, int need)\n{\n\tlong val = s->bitbuf;\n\twhile (s->bitcnt < need) {\n\t\tif (s->incnt == s->inlen)\n\t\t\tlongjmp(s->env, 1);\n\t\tval |= (long)(s->in[s->incnt++]) << s->bitcnt;\n\t\ts->bitcnt += 8;\n\t}\n\ts->bitbuf = (int)(val >> need);\n\ts->bitcnt -= need;\n\treturn (int)(val & ((1L << need) - 1));\n}\nstatic int puff_stored(struct puff_state* s)\n{\n\ts->bitbuf = 0;\n\ts->bitcnt = 0;\n\tif (s->incnt + 4 > s->inlen)\n\t\treturn 2;\n\tunsigned len = s->in[s->incnt++];\n\tlen |= s->in[s->incnt++] << 8;\n\tif (s->in[s->incnt++] != (~len & 0xff) ||\n\t    s->in[s->incnt++] != ((~len >> 8) & 0xff))\n\t\treturn -2;\n\tif (s->incnt + len > s->inlen)\n\t\treturn 2;\n\tif (s->outcnt + len > s->outlen)\n\t\treturn 1;\n\tfor (; len--; s->outcnt++, s->incnt++) {\n\t\tif (s->in[s->incnt])\n\t\t\ts->out[s->outcnt] = s->in[s->incnt];\n\t}\n\treturn 0;\n}\nstruct puff_huffman {\n\tshort* count;\n\tshort* symbol;\n};\nstatic int puff_decode(struct puff_state* s, const struct puff_huffman* h)\n{\n\tint first = 0;\n\tint index = 0;\n\tint bitbuf = s->bitbuf;\n\tint left = s->bitcnt;\n\tint code = first = index = 0;\n\tint len = 1;\n\tshort* next = h->count + 1;\n\twhile (1) {\n\t\twhile (left--) {\n\t\t\tcode |= bitbuf & 1;\n\t\t\tbitbuf >>= 1;\n\t\t\tint count = *next++;\n\t\t\tif (code - count < first) {\n\t\t\t\ts->bitbuf = bitbuf;\n\t\t\t\ts->bitcnt = (s->bitcnt - len) & 7;\n\t\t\t\treturn h->symbol[index + (code - first)];\n\t\t\t}\n\t\t\tindex += count;\n\t\t\tfirst += count;\n\t\t\tfirst <<= 1;\n\t\t\tcode <<= 1;\n\t\t\tlen++;\n\t\t}\n\t\tleft = (MAXBITS + 1) - len;\n\t\tif (left == 0)\n\t\t\tbreak;\n\t\tif (s->incnt == s->inlen)\n\t\t\tlongjmp(s->env, 1);\n\t\tbitbuf = s->in[s->incnt++];\n\t\tif (left > 8)\n\t\t\tleft = 8;\n\t}\n\treturn -10;\n}\nstatic int puff_construct(struct puff_huffman* h, const short* length, int n)\n{\n\tint len;\n\tfor (len = 0; len <= MAXBITS; len++)\n\t\th->count[len] = 0;\n\tint symbol;\n\tfor (symbol = 0; symbol < n; symbol++)\n\t\t(h->count[length[symbol]])++;\n\tif (h->count[0] == n)\n\t\treturn 0;\n\tint left = 1;\n\tfor (len = 1; len <= MAXBITS; len++) {\n\t\tleft <<= 1;\n\t\tleft -= h->count[len];\n\t\tif (left < 0)\n\t\t\treturn left;\n\t}\n\tshort offs[MAXBITS + 1];\n\toffs[1] = 0;\n\tfor (len = 1; len < MAXBITS; len++)\n\t\toffs[len + 1] = offs[len] + h->count[len];\n\tfor (symbol = 0; symbol < n; symbol++)\n\t\tif (length[symbol] != 0)\n\t\t\th->symbol[offs[length[symbol]]++] = symbol;\n\treturn left;\n}\nstatic int puff_codes(struct puff_state* s,\n\t\t      const struct puff_huffman* lencode,\n\t\t      const struct puff_huffman* distcode)\n{\n\tstatic const short lens[29] = {\n\t\t\t\t       3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,\n\t\t\t\t       35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};\n\tstatic const short lext[29] = {\n\t\t\t\t       0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,\n\t\t\t\t       3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};\n\tstatic const short dists[30] = {\n\t\t\t\t\t1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,\n\t\t\t\t\t257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,\n\t\t\t\t\t8193, 12289, 16385, 24577};\n\tstatic const short dext[30] = {\n\t\t\t\t       0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,\n\t\t\t\t       7, 7, 8, 8, 9, 9, 10, 10, 11, 11,\n\t\t\t\t       12, 12, 13, 13};\n\tint symbol;\n\tdo {\n\t\tsymbol = puff_decode(s, lencode);\n\t\tif (symbol < 0)\n\t\t\treturn symbol;\n\t\tif (symbol < 256) {\n\t\t\tif (s->outcnt == s->outlen)\n\t\t\t\treturn 1;\n\t\t\tif (symbol)\n\t\t\t\ts->out[s->outcnt] = symbol;\n\t\t\ts->outcnt++;\n\t\t} else if (symbol > 256) {\n\t\t\tsymbol -= 257;\n\t\t\tif (symbol >= 29)\n\t\t\t\treturn -10;\n\t\t\tint len = lens[symbol] + puff_bits(s, lext[symbol]);\n\t\t\tsymbol = puff_decode(s, distcode);\n\t\t\tif (symbol < 0)\n\t\t\t\treturn symbol;\n\t\t\tunsigned dist = dists[symbol] + puff_bits(s, dext[symbol]);\n\t\t\tif (dist > s->outcnt)\n\t\t\t\treturn -11;\n\t\t\tif (s->outcnt + len > s->outlen)\n\t\t\t\treturn 1;\n\t\t\twhile (len--) {\n\t\t\t\tif (dist <= s->outcnt && s->out[s->outcnt - dist])\n\t\t\t\t\ts->out[s->outcnt] = s->out[s->outcnt - dist];\n\t\t\t\ts->outcnt++;\n\t\t\t}\n\t\t}\n\t} while (symbol != 256);\n\treturn 0;\n}\nstatic int puff_fixed(struct puff_state* s)\n{\n\tstatic int virgin = 1;\n\tstatic short lencnt[MAXBITS + 1], lensym[FIXLCODES];\n\tstatic short distcnt[MAXBITS + 1], distsym[MAXDCODES];\n\tstatic struct puff_huffman lencode, distcode;\n\tif (virgin) {\n\t\tlencode.count = lencnt;\n\t\tlencode.symbol = lensym;\n\t\tdistcode.count = distcnt;\n\t\tdistcode.symbol = distsym;\n\t\tshort lengths[FIXLCODES];\n\t\tint symbol;\n\t\tfor (symbol = 0; symbol < 144; symbol++)\n\t\t\tlengths[symbol] = 8;\n\t\tfor (; symbol < 256; symbol++)\n\t\t\tlengths[symbol] = 9;\n\t\tfor (; symbol < 280; symbol++)\n\t\t\tlengths[symbol] = 7;\n\t\tfor (; symbol < FIXLCODES; symbol++)\n\t\t\tlengths[symbol] = 8;\n\t\tpuff_construct(&lencode, lengths, FIXLCODES);\n\t\tfor (symbol = 0; symbol < MAXDCODES; symbol++)\n\t\t\tlengths[symbol] = 5;\n\t\tpuff_construct(&distcode, lengths, MAXDCODES);\n\t\tvirgin = 0;\n\t}\n\treturn puff_codes(s, &lencode, &distcode);\n}\nstatic int puff_dynamic(struct puff_state* s)\n{\n\tstatic const short order[19] =\n\t    {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};\n\tint nlen = puff_bits(s, 5) + 257;\n\tint ndist = puff_bits(s, 5) + 1;\n\tint ncode = puff_bits(s, 4) + 4;\n\tif (nlen > MAXLCODES || ndist > MAXDCODES)\n\t\treturn -3;\n\tshort lengths[MAXCODES];\n\tint index;\n\tfor (index = 0; index < ncode; index++)\n\t\tlengths[order[index]] = puff_bits(s, 3);\n\tfor (; index < 19; index++)\n\t\tlengths[order[index]] = 0;\n\tshort lencnt[MAXBITS + 1], lensym[MAXLCODES];\n\tstruct puff_huffman lencode = {lencnt, lensym};\n\tint err = puff_construct(&lencode, lengths, 19);\n\tif (err != 0)\n\t\treturn -4;\n\tindex = 0;\n\twhile (index < nlen + ndist) {\n\t\tint symbol;\n\t\tint len;\n\t\tsymbol = puff_decode(s, &lencode);\n\t\tif (symbol < 0)\n\t\t\treturn symbol;\n\t\tif (symbol < 16)\n\t\t\tlengths[index++] = symbol;\n\t\telse {\n\t\t\tlen = 0;\n\t\t\tif (symbol == 16) {\n\t\t\t\tif (index == 0)\n\t\t\t\t\treturn -5;\n\t\t\t\tlen = lengths[index - 1];\n\t\t\t\tsymbol = 3 + puff_bits(s, 2);\n\t\t\t} else if (symbol == 17)\n\t\t\t\tsymbol = 3 + puff_bits(s, 3);\n\t\t\telse\n\t\t\t\tsymbol = 11 + puff_bits(s, 7);\n\t\t\tif (index + symbol > nlen + ndist)\n\t\t\t\treturn -6;\n\t\t\twhile (symbol--)\n\t\t\t\tlengths[index++] = len;\n\t\t}\n\t}\n\tif (lengths[256] == 0)\n\t\treturn -9;\n\terr = puff_construct(&lencode, lengths, nlen);\n\tif (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1]))\n\t\treturn -7;\n\tshort distcnt[MAXBITS + 1], distsym[MAXDCODES];\n\tstruct puff_huffman distcode = {distcnt, distsym};\n\terr = puff_construct(&distcode, lengths + nlen, ndist);\n\tif (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1]))\n\t\treturn -8;\n\treturn puff_codes(s, &lencode, &distcode);\n}\nstatic int puff(\n    unsigned char* dest,\n    unsigned long* destlen,\n    const unsigned char* source,\n    unsigned long sourcelen)\n{\n\tstruct puff_state s = {\n\t    .out = dest,\n\t    .outlen = *destlen,\n\t    .outcnt = 0,\n\t    .in = source,\n\t    .inlen = sourcelen,\n\t    .incnt = 0,\n\t    .bitbuf = 0,\n\t    .bitcnt = 0,\n\t};\n\tint err;\n\tif (setjmp(s.env) != 0)\n\t\terr = 2;\n\telse {\n\t\tint last;\n\t\tdo {\n\t\t\tlast = puff_bits(&s, 1);\n\t\t\tint type = puff_bits(&s, 2);\n\t\t\terr = type == 0 ? puff_stored(&s) : (type == 1 ? puff_fixed(&s) : (type == 2 ? puff_dynamic(&s) : -1));\n\t\t\tif (err != 0)\n\t\t\t\tbreak;\n\t\t} while (!last);\n\t}\n\t*destlen = s.outcnt;\n\treturn err;\n}\n\n#define ZLIB_HEADER_WIDTH 2\n\nstatic int puff_zlib_to_file(const unsigned char* source, unsigned long sourcelen, int dest_fd)\n{\n\tif (sourcelen < ZLIB_HEADER_WIDTH)\n\t\treturn 0;\n\tsource += ZLIB_HEADER_WIDTH;\n\tsourcelen -= ZLIB_HEADER_WIDTH;\n\tconst unsigned long max_destlen = 132 << 20;\n\tvoid* ret = mmap(0, max_destlen, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0);\n\tif (ret == MAP_FAILED)\n\t\treturn -1;\n\tunsigned char* dest = (unsigned char*)ret;\n\tunsigned long destlen = max_destlen;\n\tint err = puff(dest, &destlen, source, sourcelen);\n\tif (err) {\n\t\tmunmap(dest, max_destlen);\n\t\terrno = -err;\n\t\treturn -1;\n\t}\n\tif (write(dest_fd, dest, destlen) != (ssize_t)destlen) {\n\t\tmunmap(dest, max_destlen);\n\t\treturn -1;\n\t}\n\treturn munmap(dest, max_destlen);\n}\n\nstatic int setup_loop_device(unsigned char* data, unsigned long size, const char* loopname, int* loopfd_p)\n{\n\tint err = 0, loopfd = -1;\n\tint memfd = syscall(__NR_memfd_create, \"syzkaller\", 0);\n\tif (memfd == -1) {\n\t\terr = errno;\n\t\tgoto error;\n\t}\n\tif (puff_zlib_to_file(data, size, memfd)) {\n\t\terr = errno;\n\t\tgoto error_close_memfd;\n\t}\n\tloopfd = open(loopname, O_RDWR);\n\tif (loopfd == -1) {\n\t\terr = errno;\n\t\tgoto error_close_memfd;\n\t}\n\tif (ioctl(loopfd, LOOP_SET_FD, memfd)) {\n\t\tif (errno != EBUSY) {\n\t\t\terr = errno;\n\t\t\tgoto error_close_loop;\n\t\t}\n\t\tioctl(loopfd, LOOP_CLR_FD, 0);\n\t\tusleep(1000);\n\t\tif (ioctl(loopfd, LOOP_SET_FD, memfd)) {\n\t\t\terr = errno;\n\t\t\tgoto error_close_loop;\n\t\t}\n\t}\n\tclose(memfd);\n\t*loopfd_p = loopfd;\n\treturn 0;\n\nerror_close_loop:\n\tclose(loopfd);\nerror_close_memfd:\n\tclose(memfd);\nerror:\n\terrno = err;\n\treturn -1;\n}\n\nstatic void reset_loop_device(const char* loopname)\n{\n\tint loopfd = open(loopname, O_RDWR);\n\tif (loopfd == -1) {\n\t\treturn;\n\t}\n\tif (ioctl(loopfd, LOOP_CLR_FD, 0)) {\n\t}\n\tclose(loopfd);\n}\n\nstatic long syz_mount_image(\n    volatile long fsarg,\n    volatile long dir,\n    volatile long flags,\n    volatile long optsarg,\n    volatile long change_dir,\n    volatile unsigned long size,\n    volatile long image)\n{\n\tunsigned char* data = (unsigned char*)image;\n\tint res = -1, err = 0, need_loop_device = !!size;\n\tchar* mount_opts = (char*)optsarg;\n\tchar* target = (char*)dir;\n\tchar* fs = (char*)fsarg;\n\tchar* source = NULL;\n\tchar loopname[64];\n\tif (need_loop_device) {\n\t\tint loopfd;\n\t\tmemset(loopname, 0, sizeof(loopname));\n\t\tsnprintf(loopname, sizeof(loopname), \"/dev/loop%llu\", procid);\n\t\tif (setup_loop_device(data, size, loopname, &loopfd) == -1)\n\t\t\treturn -1;\n\t\tclose(loopfd);\n\t\tsource = loopname;\n\t}\n\tmkdir(target, 0777);\n\tchar opts[256];\n\tmemset(opts, 0, sizeof(opts));\n\tif (strlen(mount_opts) > (sizeof(opts) - 32)) {\n\t}\n\tstrncpy(opts, mount_opts, sizeof(opts) - 32);\n\tif (strcmp(fs, \"iso9660\") == 0) {\n\t\tflags |= MS_RDONLY;\n\t} else if (strncmp(fs, \"ext\", 3) == 0) {\n\t\tbool has_remount_ro = false;\n\t\tchar* remount_ro_start = strstr(opts, \"errors=remount-ro\");\n\t\tif (remount_ro_start != NULL) {\n\t\t\tchar after = *(remount_ro_start + strlen(\"errors=remount-ro\"));\n\t\t\tchar before = remount_ro_start == opts ? '\\0' : *(remount_ro_start - 1);\n\t\t\thas_remount_ro = ((before == '\\0' || before == ',') && (after == '\\0' || after == ','));\n\t\t}\n\t\tif (strstr(opts, \"errors=panic\") || !has_remount_ro)\n\t\t\tstrcat(opts, \",errors=continue\");\n\t} else if (strcmp(fs, \"xfs\") == 0) {\n\t\tstrcat(opts, \",nouuid\");\n\t} else if (strncmp(fs, \"gfs2\", 4) == 0 && (strstr(opts, \"errors=panic\") || strstr(opts, \"debug\"))) {\n\t\tstrcat(opts, \",errors=withdraw\");\n\t}\n\tres = mount(source, target, fs, flags, opts);\n\tif (res == -1) {\n\t\terr = errno;\n\t\tgoto error_clear_loop;\n\t}\n\tres = open(target, O_RDONLY | O_DIRECTORY);\n\tif (res == -1) {\n\t\terr = errno;\n\t\tgoto error_clear_loop;\n\t}\n\tif (change_dir) {\n\t\tres = chdir(target);\n\t\tif (res == -1) {\n\t\t\terr = errno;\n\t\t}\n\t}\n\nerror_clear_loop:\n\tif (need_loop_device)\n\t\treset_loop_device(loopname);\n\terrno = err;\n\treturn res;\n}\n\n#define FS_IOC_SETFLAGS _IOW('f', 2, long)\nstatic void remove_dir(const char* dir)\n{\n\tint iter = 0;\n\tDIR* dp = 0;\n\tconst int umount_flags = MNT_FORCE | UMOUNT_NOFOLLOW;\n\nretry:\n\t\twhile (umount2(dir, umount_flags) == 0) {\n\t\t}\n\tdp = opendir(dir);\n\tif (dp == NULL) {\n\t\tif (errno == EMFILE) {\n\texit(1);\n\t\t}\n\texit(1);\n\t}\n\tstruct dirent* ep = 0;\n\twhile ((ep = readdir(dp))) {\n\t\tif (strcmp(ep->d_name, \".\") == 0 || strcmp(ep->d_name, \"..\") == 0)\n\t\t\tcontinue;\n\t\tchar filename[FILENAME_MAX];\n\t\tsnprintf(filename, sizeof(filename), \"%s/%s\", dir, ep->d_name);\n\t\t\twhile (umount2(filename, umount_flags) == 0) {\n\t\t\t}\n\t\tstruct stat st;\n\t\tif (lstat(filename, &st))\n\texit(1);\n\t\tif (S_ISDIR(st.st_mode)) {\n\t\t\tremove_dir(filename);\n\t\t\tcontinue;\n\t\t}\n\t\tint i;\n\t\tfor (i = 0;; i++) {\n\t\t\tif (unlink(filename) == 0)\n\t\t\t\tbreak;\n\t\t\tif (errno == EPERM) {\n\t\t\t\tint fd = open(filename, O_RDONLY);\n\t\t\t\tif (fd != -1) {\n\t\t\t\t\tlong flags = 0;\n\t\t\t\t\tif (ioctl(fd, FS_IOC_SETFLAGS, &flags) == 0) {\n\t\t\t\t\t}\n\t\t\t\t\tclose(fd);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (errno == EROFS) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (errno != EBUSY || i > 100)\n\texit(1);\n\t\t\t\tif (umount2(filename, umount_flags))\n\texit(1);\n\t\t}\n\t}\n\tclosedir(dp);\n\tfor (int i = 0;; i++) {\n\t\tif (rmdir(dir) == 0)\n\t\t\tbreak;\n\t\tif (i < 100) {\n\t\t\tif (errno == EPERM) {\n\t\t\t\tint fd = open(dir, O_RDONLY);\n\t\t\t\tif (fd != -1) {\n\t\t\t\t\tlong flags = 0;\n\t\t\t\t\tif (ioctl(fd, FS_IOC_SETFLAGS, &flags) == 0) {\n\t\t\t\t\t}\n\t\t\t\t\tclose(fd);\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (errno == EROFS) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tif (errno == EBUSY) {\n\t\t\t\t\tif (umount2(dir, umount_flags))\n\texit(1);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (errno == ENOTEMPTY) {\n\t\t\t\tif (iter < 100) {\n\t\t\t\t\titer++;\n\t\t\t\t\tgoto retry;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\texit(1);\n\t}\n}\n\nstatic void kill_and_wait(int pid, int* status)\n{\n\tkill(-pid, SIGKILL);\n\tkill(pid, SIGKILL);\n\tfor (int i = 0; i < 100; i++) {\n\t\tif (waitpid(-1, status, WNOHANG | __WALL) == pid)\n\t\t\treturn;\n\t\tusleep(1000);\n\t}\n\tDIR* dir = opendir(\"/sys/fs/fuse/connections\");\n\tif (dir) {\n\t\tfor (;;) {\n\t\t\tstruct dirent* ent = readdir(dir);\n\t\t\tif (!ent)\n\t\t\t\tbreak;\n\t\t\tif (strcmp(ent->d_name, \".\") == 0 || strcmp(ent->d_name, \"..\") == 0)\n\t\t\t\tcontinue;\n\t\t\tchar abort[300];\n\t\t\tsnprintf(abort, sizeof(abort), \"/sys/fs/fuse/connections/%s/abort\", ent->d_name);\n\t\t\tint fd = open(abort, O_WRONLY);\n\t\t\tif (fd == -1) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (write(fd, abort, 1) < 0) {\n\t\t\t}\n\t\t\tclose(fd);\n\t\t}\n\t\tclosedir(dir);\n\t} else {\n\t}\n\twhile (waitpid(-1, status, __WALL) != pid) {\n\t}\n}\n\nstatic void reset_loop()\n{\n\tchar buf[64];\n\tsnprintf(buf, sizeof(buf), \"/dev/loop%llu\", procid);\n\tint loopfd = open(buf, O_RDWR);\n\tif (loopfd != -1) {\n\t\tioctl(loopfd, LOOP_CLR_FD, 0);\n\t\tclose(loopfd);\n\t}\n}\n\nstatic void setup_test()\n{\n\tprctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);\n\tsetpgrp();\n\twrite_file(\"/proc/self/oom_score_adj\", \"1000\");\n\tif (symlink(\"/dev/binderfs\", \"./binderfs\")) {\n\t}\n}\n\n#define USLEEP_FORKED_CHILD (3 * 50 *1000)\n\nstatic long handle_clone_ret(long ret)\n{\n\tif (ret != 0) {\n\t\treturn ret;\n\t}\n\tusleep(USLEEP_FORKED_CHILD);\n\tsyscall(__NR_exit, 0);\n\twhile (1) {\n\t}\n}\n\nstatic long syz_clone(volatile long flags, volatile long stack, volatile long stack_len,\n\t\t      volatile long ptid, volatile long ctid, volatile long tls)\n{\n\tlong sp = (stack + stack_len) & ~15;\n\tlong ret = (long)syscall(__NR_clone, flags & ~CLONE_VM, sp, ptid, ctid, tls);\n\treturn handle_clone_ret(ret);\n}\n\nstatic void execute_one(void);\n\n#define WAIT_FLAGS __WALL\n\nstatic void loop(void)\n{\n\tint iter = 0;\n\tfor (;; iter++) {\n\t\tchar cwdbuf[32];\n\t\tsprintf(cwdbuf, \"./%d\", iter);\n\t\tif (mkdir(cwdbuf, 0777))\n\texit(1);\n\t\treset_loop();\n\t\tint pid = fork();\n\t\tif (pid < 0)\n\texit(1);\n\t\tif (pid == 0) {\n\t\t\tif (chdir(cwdbuf))\n\texit(1);\n\t\t\tsetup_test();\n\t\t\texecute_one();\n\t\t\texit(0);\n\t\t}\n\t\tint status = 0;\n\t\tuint64_t start = current_time_ms();\n\t\tfor (;;) {\n\t\t\tsleep_ms(10);\n\t\t\tif (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)\n\t\t\t\tbreak;\n\t\t\tif (current_time_ms() - start < 5000)\n\t\t\t\tcontinue;\n\t\t\tkill_and_wait(pid, &status);\n\t\t\tbreak;\n\t\t}\n\t\tremove_dir(cwdbuf);\n\t}\n}\n\nvoid execute_one(void)\n{\n\t\tif (write(1, \"executing program\\n\", sizeof(\"executing program\\n\") - 1)) {}\nmemcpy((void*)0x200000000240, \"ext2\\000\", 5);\nmemcpy((void*)0x200000000440, \"./file1\\000\", 8);\n*(uint8_t*)0x200000000480 = 0;\nmemcpy((void*)0x2000000008c0, \"\\x78\\x9c\\xec\\xdc\\x4f\\x68\\x1c\\x55\\x18\\x00\\xf0\\x6f\\x66\\xbb\\xd5\\xb6\\x89\\xa9\\x6d\\xfd\\x57\\x95\\x16\\x14\\x2a\\x88\\xf9\\xab\\x98\\x9b\\x54\\xef\\x0a\\x56\\xc1\\x6b\\x30\\x9b\\xb6\\x74\\xdb\\x48\\x12\\xa9\\x09\\xb4\\xd8\\xb3\\xe2\\x21\\x08\\x0a\\x9e\\xf4\\xec\\xa1\\x37\\xf1\\xa6\\x37\\x2f\\x1e\\x04\\x0f\\x82\\x17\\x0f\\x05\\x41\\x28\\xf6\\xe0\\xc1\\xff\\x2b\\xb3\\x33\\xb3\\xa6\\xe9\\x6e\\x68\\x93\\xdd\\xae\\x76\\x7e\\x3f\\x98\\xdd\\xf7\\x66\\x66\\xf9\\xde\\xcb\\xf2\\x4d\\xde\\x7c\\x64\\x12\\x40\\x65\\x1d\\xcd\\x5e\\x92\\x88\\x91\\x88\\xf8\\x3e\\x22\\xc6\\xf2\\xee\\xf5\\x27\\x1c\\xcd\\xdf\\xd6\\x67\\x2e\\x9f\\xca\\xb6\\x24\\x5a\\xad\\x13\\x3f\\x27\\xed\\xf3\\x2e\\xce\\x5c\\x3e\\x55\\x9e\\x5a\\x7e\\x6e\\x5f\\x44\\xbc\\x1d\\x11\\x77\\x47\\xc4\\x81\\x88\\xa8\\x75\\x89\\xbb\\xbc\\xba\\x76\\x66\\xae\\xd9\\x6c\\x2c\\x15\\xfd\\x89\\x95\\xb3\\x6f\\x4c\\x2c\\xaf\\xae\\x3d\\x75\\xfa\\xec\\xdc\\xc9\\xc6\\xc9\\xc6\\xb9\\xa9\\x99\\x67\\x9f\\x9e\\x9c\\x7d\\x66\\x72\\x76\\xb6\\x6f\\x73\\xbd\\xfa\\xe5\\xbb\\xaf\\xc5\\x2b\\x2f\\x4d\\xbf\\x77\\xe4\\x87\\x4f\\x5e\\xf8\\xfc\\xe0\\x85\\x6c\\xbc\\x23\\xc5\\xb1\\x8d\\xf3\\xe8\\xa7\\xa4\\xc7\\xfe\\x07\\x07\\x11\\x6c\\x88\\xf6\\x0c\\x7b\\x00\\x6c\\x4b\\x96\\x9b\\xbb\\x22\\xa2\\xde\\xce\\xff\\xb1\\xa8\\xb5\\x7b\\x40\\x15\\xb4\\x5a\\xad\\x23\\x5b\\x1f\\x06\\xee\\x5c\\x89\\x24\\x87\\x8a\\x2a\\x7f\\xd1\\x67\\xf7\\xbf\\xe5\\x76\\x7b\\x56\\x1e\\xb9\\xab\\xc7\\xf3\\x1b\\x90\\x8b\\x45\\x6d\\x61\\xbd\\x13\\x7f\\x57\\xa4\\xc5\\x39\\x75\\xf7\\x97\\xc0\\x00\\x7c\\x91\\x5d\\x7f\\x26\\xbb\\x5d\\xff\\xd2\\xeb\\x6a\\x74\\x7b\\x8b\\xba\\xe6\\x48\\x44\\x8c\\x46\\xc4\\x3d\\x45\\xad\\x74\\x7f\\x44\\xdc\\x5b\\xd4\\x39\\x0f\\x46\\xc4\\xa1\\x88\\xb8\\xef\\x16\\xe2\\x97\\xd7\\xbf\\xf5\\x1b\\xae\\x7f\\x69\\xe7\\xfa\\x57\\x8b\\x88\\xfb\\x77\\x30\\xc7\\x77\\x9a\\xd7\\xae\\xf4\\x8c\\x7f\\x69\\x34\\x0e\\x77\\x8d\\x9f\\x74\\x2a\\x41\\x49\\x76\\x23\\x18\\x11\\x0f\\x6c\\x33\\xfe\\x67\\xcf\\x5d\\xf8\\xaa\\xd7\\xb1\\xd6\\xc7\\x11\\xc7\\xa2\\x7b\\xfc\\xd8\\x10\\x7f\\x8b\\xfa\\xf0\\xc4\\xc2\\xe9\\x66\\x63\\x32\\x7f\\xed\\x1a\\xe3\\xf9\\x57\\x17\\xbe\\xee\\x3d\\xff\\xfc\\xbb\\xbd\\x21\\xfe\\x86\\xa2\\x75\\x6d\\x87\\xf5\\xda\\x2b\\x7b\\x5e\\x8e\\xbf\\xb6\\x88\\xff\\xc4\\x63\\xdd\\xbf\\xff\\x03\\xc5\\x39\\xd9\\xfc\\xff\\x8e\\x88\\xdf\\x22\\xe2\\xf7\\x88\\xf8\\x23\\x22\\xfe\\x8c\\x88\\x87\\x22\\xe2\\x70\\x44\\x3c\\x1c\\x11\\x8f\\x6c\\x11\\xff\\xf8\\x37\\xdf\\x2e\\xf6\\x3a\\x96\\xc5\\x9f\\xef\\xf1\\xf3\\x4f\\x37\\xc4\\x7f\\x74\\x3b\\x13\\x2f\\x9c\\xff\\xf1\\xd3\\x4b\\x3b\\xf8\\x38\\x00\\xd0\\x67\\x69\\x7b\\x4d\\x9b\\xa4\\xe3\\x9d\\x76\\x9a\\x8e\\x8f\\xe7\\x6b\\xdd\\x43\\xb1\\x37\\x6d\\x2e\\x2e\\xaf\\x3c\\xb9\\xb0\\xf8\\xe6\\xb9\\xf9\\x7c\\xed\\xbb\\x3f\\xea\\x69\\xb9\\xd2\\xca\\xd7\\xbf\\xf5\\x24\\xeb\\x4f\\x15\\x6b\\xe1\\xb2\\x3f\\xbd\\xa9\\x3f\\x53\\xac\\x93\\xdf\\xaf\\xed\\x69\\xf7\\xc7\\x5f\\x5f\\x6c\\xce\\x0f\\x7b\\xf2\\x50\\x71\\xfb\\x36\\xe5\\xff\\x2f\\xb5\\x3c\\xff\\x81\\x8a\\xf0\\x27\\x3f\\x50\\x5d\\xf2\\x1f\\xaa\\x4b\\xfe\\x43\\x75\\xc9\\x7f\\xa8\\x2e\\xf9\\x0f\\xd5\\x25\\xff\\xa1\\xba\\xe4\\x3f\\x54\\x97\\xfc\\x87\\xea\\x92\\xff\\x50\\x5d\\xf2\\x1f\\xaa\\xeb\\xe6\\xf2\\x7f\\xf7\\xc0\\xc7\\x01\\xdc\\x56\\x23\\x3d\\x9e\\xff\\x19\\xdd\\xf0\\xec\\xce\\x64\\xf1\\xbc\\xfb\\x77\\xb5\\xfa\\x5d\\xe5\\xb3\\x3e\\xc0\\xff\\x5f\\x63\\xa9\\xf3\\x9f\\x78\\x37\\x35\\x86\\x3d\\x32\\x60\\xd0\\xfe\\x4d\\xfa\\x61\\x8f\\x04\\x00\\x00\\x00\\x00\\xe8\\xb7\\x5e\\xd5\\xff\\x7e\\x36\\x86\\x3d\\x47\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x80\\x5b\\x93\\xfe\\x94\\x44\\x44\\xb6\\x1d\\x1b\\x7b\\x7c\\x64\\xf3\\xd1\\xdd\\xc9\\xaf\\xb5\\xf6\\x7b\\x44\\x9c\\xff\\xe8\\xc4\\x07\\x6f\\xcd\\xad\\xac\\x2c\\x4d\\x65\\xfb\\xaf\\x75\\xf6\\xaf\\x7c\\x58\\xec\\x9f\\x1e\\xc6\\xf8\\x81\\x9b\\x55\\xe6\\x69\\x99\\xc7\\x40\\x75\\x2d\\xaf\\xae\\x9d\\x99\\x6b\\x36\\x1b\\x4b\\x1a\\xfd\\x68\\xbc\\xf8\\xdf\\x18\\x86\\xc6\\x9d\\xd2\\xa8\\xc7\\x60\\x43\\xfc\\x13\\x00\\x00\\xff\\xff\\x52\\x90\\x78\\x22\", 999);\nsyz_mount_image(/*fs=*/0x200000000240, /*dir=*/0x200000000440, /*flags=*/0, /*opts=*/0x200000000480, /*chdir=*/1, /*size=*/0x3e7, /*img=*/0x2000000008c0);\nsyz_clone(/*flags=*/0, /*stack=*/0, /*stack_len=*/0, /*parentid=*/0, /*childtid=*/0, /*tls=*/0);\n\n}\nint main(void)\n{\n\t\tsyscall(__NR_mmap, /*addr=*/0x1ffffffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);\n\tsyscall(__NR_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul, /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/7ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);\n\tsyscall(__NR_mmap, /*addr=*/0x200001000000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);\n\tconst char* reason;\n\t(void)reason;\n\t\t\tuse_temporary_dir();\n\t\t\tloop();\n\treturn 0;\n}\n\n--- [Reproducer for PATCH 2/2: ext2_rename] ---\n\n#define _GNU_SOURCE\n\n#include <dirent.h>\n#include <endian.h>\n#include <errno.h>\n#include <fcntl.h>\n#include <setjmp.h>\n#include <signal.h>\n#include <stdarg.h>\n#include <stdbool.h>\n#include <stddef.h>\n#include <stdint.h>\n#include <stdio.h>\n#include <stdlib.h>\n#include <string.h>\n#include <sys/ioctl.h>\n#include <sys/mman.h>\n#include <sys/mount.h>\n#include <sys/prctl.h>\n#include <sys/stat.h>\n#include <sys/syscall.h>\n#include <sys/types.h>\n#include <sys/wait.h>\n#include <time.h>\n#include <unistd.h>\n\n#include <linux/loop.h>\n\n#ifndef __NR_memfd_create\n#define __NR_memfd_create 319\n#endif\n\nstatic unsigned long long procid;\n\nstatic void sleep_ms(uint64_t ms)\n{\n\tusleep(ms * 1000);\n}\n\nstatic uint64_t current_time_ms(void)\n{\n\tstruct timespec ts;\n\tif (clock_gettime(CLOCK_MONOTONIC, &ts))\n\texit(1);\n\treturn (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;\n}\n\nstatic bool write_file(const char* file, const char* what, ...)\n{\n\tchar buf[1024];\n\tva_list args;\n\tva_start(args, what);\n\tvsnprintf(buf, sizeof(buf), what, args);\n\tva_end(args);\n\tbuf[sizeof(buf) - 1] = 0;\n\tint len = strlen(buf);\n\tint fd = open(file, O_WRONLY | O_CLOEXEC);\n\tif (fd == -1)\n\t\treturn false;\n\tif (write(fd, buf, len) != len) {\n\t\tint err = errno;\n\t\tclose(fd);\n\t\terrno = err;\n\t\treturn false;\n\t}\n\tclose(fd);\n\treturn true;\n}\n\n#define MAXBITS 15\n#define MAXLCODES 286\n#define MAXDCODES 30\n#define MAXCODES (MAXLCODES + MAXDCODES)\n#define FIXLCODES 288\n\nstruct puff_state {\n\tunsigned char* out;\n\tunsigned long outlen;\n\tunsigned long outcnt;\n\tconst unsigned char* in;\n\tunsigned long inlen;\n\tunsigned long incnt;\n\tint bitbuf;\n\tint bitcnt;\n\tjmp_buf env;\n};\nstatic int puff_bits(struct puff_state* s, int need)\n{\n\tlong val = s->bitbuf;\n\twhile (s->bitcnt < need) {\n\t\tif (s->incnt == s->inlen)\n\t\t\tlongjmp(s->env, 1);\n\t\tval |= (long)(s->in[s->incnt++]) << s->bitcnt;\n\t\ts->bitcnt += 8;\n\t}\n\ts->bitbuf = (int)(val >> need);\n\ts->bitcnt -= need;\n\treturn (int)(val & ((1L << need) - 1));\n}\nstatic int puff_stored(struct puff_state* s)\n{\n\ts->bitbuf = 0;\n\ts->bitcnt = 0;\n\tif (s->incnt + 4 > s->inlen)\n\t\treturn 2;\n\tunsigned len = s->in[s->incnt++];\n\tlen |= s->in[s->incnt++] << 8;\n\tif (s->in[s->incnt++] != (~len & 0xff) ||\n\t    s->in[s->incnt++] != ((~len >> 8) & 0xff))\n\t\treturn -2;\n\tif (s->incnt + len > s->inlen)\n\t\treturn 2;\n\tif (s->outcnt + len > s->outlen)\n\t\treturn 1;\n\tfor (; len--; s->outcnt++, s->incnt++) {\n\t\tif (s->in[s->incnt])\n\t\t\ts->out[s->outcnt] = s->in[s->incnt];\n\t}\n\treturn 0;\n}\nstruct puff_huffman {\n\tshort* count;\n\tshort* symbol;\n};\nstatic int puff_decode(struct puff_state* s, const struct puff_huffman* h)\n{\n\tint first = 0;\n\tint index = 0;\n\tint bitbuf = s->bitbuf;\n\tint left = s->bitcnt;\n\tint code = first = index = 0;\n\tint len = 1;\n\tshort* next = h->count + 1;\n\twhile (1) {\n\t\twhile (left--) {\n\t\t\tcode |= bitbuf & 1;\n\t\t\tbitbuf >>= 1;\n\t\t\tint count = *next++;\n\t\t\tif (code - count < first) {\n\t\t\t\ts->bitbuf = bitbuf;\n\t\t\t\ts->bitcnt = (s->bitcnt - len) & 7;\n\t\t\t\treturn h->symbol[index + (code - first)];\n\t\t\t}\n\t\t\tindex += count;\n\t\t\tfirst += count;\n\t\t\tfirst <<= 1;\n\t\t\tcode <<= 1;\n\t\t\tlen++;\n\t\t}\n\t\tleft = (MAXBITS + 1) - len;\n\t\tif (left == 0)\n\t\t\tbreak;\n\t\tif (s->incnt == s->inlen)\n\t\t\tlongjmp(s->env, 1);\n\t\tbitbuf = s->in[s->incnt++];\n\t\tif (left > 8)\n\t\t\tleft = 8;\n\t}\n\treturn -10;\n}\nstatic int puff_construct(struct puff_huffman* h, const short* length, int n)\n{\n\tint len;\n\tfor (len = 0; len <= MAXBITS; len++)\n\t\th->count[len] = 0;\n\tint symbol;\n\tfor (symbol = 0; symbol < n; symbol++)\n\t\t(h->count[length[symbol]])++;\n\tif (h->count[0] == n)\n\t\treturn 0;\n\tint left = 1;\n\tfor (len = 1; len <= MAXBITS; len++) {\n\t\tleft <<= 1;\n\t\tleft -= h->count[len];\n\t\tif (left < 0)\n\t\t\treturn left;\n\t}\n\tshort offs[MAXBITS + 1];\n\toffs[1] = 0;\n\tfor (len = 1; len < MAXBITS; len++)\n\t\toffs[len + 1] = offs[len] + h->count[len];\n\tfor (symbol = 0; symbol < n; symbol++)\n\t\tif (length[symbol] != 0)\n\t\t\th->symbol[offs[length[symbol]]++] = symbol;\n\treturn left;\n}\nstatic int puff_codes(struct puff_state* s,\n\t\t      const struct puff_huffman* lencode,\n\t\t      const struct puff_huffman* distcode)\n{\n\tstatic const short lens[29] = {\n\t\t\t\t       3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,\n\t\t\t\t       35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};\n\tstatic const short lext[29] = {\n\t\t\t\t       0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,\n\t\t\t\t       3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};\n\tstatic const short dists[30] = {\n\t\t\t\t\t1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,\n\t\t\t\t\t257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,\n\t\t\t\t\t8193, 12289, 16385, 24577};\n\tstatic const short dext[30] = {\n\t\t\t\t       0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,\n\t\t\t\t       7, 7, 8, 8, 9, 9, 10, 10, 11, 11,\n\t\t\t\t       12, 12, 13, 13};\n\tint symbol;\n\tdo {\n\t\tsymbol = puff_decode(s, lencode);\n\t\tif (symbol < 0)\n\t\t\treturn symbol;\n\t\tif (symbol < 256) {\n\t\t\tif (s->outcnt == s->outlen)\n\t\t\t\treturn 1;\n\t\t\tif (symbol)\n\t\t\t\ts->out[s->outcnt] = symbol;\n\t\t\ts->outcnt++;\n\t\t} else if (symbol > 256) {\n\t\t\tsymbol -= 257;\n\t\t\tif (symbol >= 29)\n\t\t\t\treturn -10;\n\t\t\tint len = lens[symbol] + puff_bits(s, lext[symbol]);\n\t\t\tsymbol = puff_decode(s, distcode);\n\t\t\tif (symbol < 0)\n\t\t\t\treturn symbol;\n\t\t\tunsigned dist = dists[symbol] + puff_bits(s, dext[symbol]);\n\t\t\tif (dist > s->outcnt)\n\t\t\t\treturn -11;\n\t\t\tif (s->outcnt + len > s->outlen)\n\t\t\t\treturn 1;\n\t\t\twhile (len--) {\n\t\t\t\tif (dist <= s->outcnt && s->out[s->outcnt - dist])\n\t\t\t\t\ts->out[s->outcnt] = s->out[s->outcnt - dist];\n\t\t\t\ts->outcnt++;\n\t\t\t}\n\t\t}\n\t} while (symbol != 256);\n\treturn 0;\n}\nstatic int puff_fixed(struct puff_state* s)\n{\n\tstatic int virgin = 1;\n\tstatic short lencnt[MAXBITS + 1], lensym[FIXLCODES];\n\tstatic short distcnt[MAXBITS + 1], distsym[MAXDCODES];\n\tstatic struct puff_huffman lencode, distcode;\n\tif (virgin) {\n\t\tlencode.count = lencnt;\n\t\tlencode.symbol = lensym;\n\t\tdistcode.count = distcnt;\n\t\tdistcode.symbol = distsym;\n\t\tshort lengths[FIXLCODES];\n\t\tint symbol;\n\t\tfor (symbol = 0; symbol < 144; symbol++)\n\t\t\tlengths[symbol] = 8;\n\t\tfor (; symbol < 256; symbol++)\n\t\t\tlengths[symbol] = 9;\n\t\tfor (; symbol < 280; symbol++)\n\t\t\tlengths[symbol] = 7;\n\t\tfor (; symbol < FIXLCODES; symbol++)\n\t\t\tlengths[symbol] = 8;\n\t\tpuff_construct(&lencode, lengths, FIXLCODES);\n\t\tfor (symbol = 0; symbol < MAXDCODES; symbol++)\n\t\t\tlengths[symbol] = 5;\n\t\tpuff_construct(&distcode, lengths, MAXDCODES);\n\t\tvirgin = 0;\n\t}\n\treturn puff_codes(s, &lencode, &distcode);\n}\nstatic int puff_dynamic(struct puff_state* s)\n{\n\tstatic const short order[19] =\n\t    {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};\n\tint nlen = puff_bits(s, 5) + 257;\n\tint ndist = puff_bits(s, 5) + 1;\n\tint ncode = puff_bits(s, 4) + 4;\n\tif (nlen > MAXLCODES || ndist > MAXDCODES)\n\t\treturn -3;\n\tshort lengths[MAXCODES];\n\tint index;\n\tfor (index = 0; index < ncode; index++)\n\t\tlengths[order[index]] = puff_bits(s, 3);\n\tfor (; index < 19; index++)\n\t\tlengths[order[index]] = 0;\n\tshort lencnt[MAXBITS + 1], lensym[MAXLCODES];\n\tstruct puff_huffman lencode = {lencnt, lensym};\n\tint err = puff_construct(&lencode, lengths, 19);\n\tif (err != 0)\n\t\treturn -4;\n\tindex = 0;\n\twhile (index < nlen + ndist) {\n\t\tint symbol;\n\t\tint len;\n\t\tsymbol = puff_decode(s, &lencode);\n\t\tif (symbol < 0)\n\t\t\treturn symbol;\n\t\tif (symbol < 16)\n\t\t\tlengths[index++] = symbol;\n\t\telse {\n\t\t\tlen = 0;\n\t\t\tif (symbol == 16) {\n\t\t\t\tif (index == 0)\n\t\t\t\t\treturn -5;\n\t\t\t\tlen = lengths[index - 1];\n\t\t\t\tsymbol = 3 + puff_bits(s, 2);\n\t\t\t} else if (symbol == 17)\n\t\t\t\tsymbol = 3 + puff_bits(s, 3);\n\t\t\telse\n\t\t\t\tsymbol = 11 + puff_bits(s, 7);\n\t\t\tif (index + symbol > nlen + ndist)\n\t\t\t\treturn -6;\n\t\t\twhile (symbol--)\n\t\t\t\tlengths[index++] = len;\n\t\t}\n\t}\n\tif (lengths[256] == 0)\n\t\treturn -9;\n\terr = puff_construct(&lencode, lengths, nlen);\n\tif (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1]))\n\t\treturn -7;\n\tshort distcnt[MAXBITS + 1], distsym[MAXDCODES];\n\tstruct puff_huffman distcode = {distcnt, distsym};\n\terr = puff_construct(&distcode, lengths + nlen, ndist);\n\tif (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1]))\n\t\treturn -8;\n\treturn puff_codes(s, &lencode, &distcode);\n}\nstatic int puff(\n    unsigned char* dest,\n    unsigned long* destlen,\n    const unsigned char* source,\n    unsigned long sourcelen)\n{\n\tstruct puff_state s = {\n\t    .out = dest,\n\t    .outlen = *destlen,\n\t    .outcnt = 0,\n\t    .in = source,\n\t    .inlen = sourcelen,\n\t    .incnt = 0,\n\t    .bitbuf = 0,\n\t    .bitcnt = 0,\n\t};\n\tint err;\n\tif (setjmp(s.env) != 0)\n\t\terr = 2;\n\telse {\n\t\tint last;\n\t\tdo {\n\t\t\tlast = puff_bits(&s, 1);\n\t\t\tint type = puff_bits(&s, 2);\n\t\t\terr = type == 0 ? puff_stored(&s) : (type == 1 ? puff_fixed(&s) : (type == 2 ? puff_dynamic(&s) : -1));\n\t\t\tif (err != 0)\n\t\t\t\tbreak;\n\t\t} while (!last);\n\t}\n\t*destlen = s.outcnt;\n\treturn err;\n}\n\n#define ZLIB_HEADER_WIDTH 2\n\nstatic int puff_zlib_to_file(const unsigned char* source, unsigned long sourcelen, int dest_fd)\n{\n\tif (sourcelen < ZLIB_HEADER_WIDTH)\n\t\treturn 0;\n\tsource += ZLIB_HEADER_WIDTH;\n\tsourcelen -= ZLIB_HEADER_WIDTH;\n\tconst unsigned long max_destlen = 132 << 20;\n\tvoid* ret = mmap(0, max_destlen, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0);\n\tif (ret == MAP_FAILED)\n\t\treturn -1;\n\tunsigned char* dest = (unsigned char*)ret;\n\tunsigned long destlen = max_destlen;\n\tint err = puff(dest, &destlen, source, sourcelen);\n\tif (err) {\n\t\tmunmap(dest, max_destlen);\n\t\terrno = -err;\n\t\treturn -1;\n\t}\n\tif (write(dest_fd, dest, destlen) != (ssize_t)destlen) {\n\t\tmunmap(dest, max_destlen);\n\t\treturn -1;\n\t}\n\treturn munmap(dest, max_destlen);\n}\n\nstatic int setup_loop_device(unsigned char* data, unsigned long size, const char* loopname, int* loopfd_p)\n{\n\tint err = 0, loopfd = -1;\n\tint memfd = syscall(__NR_memfd_create, \"syzkaller\", 0);\n\tif (memfd == -1) {\n\t\terr = errno;\n\t\tgoto error;\n\t}\n\tif (puff_zlib_to_file(data, size, memfd)) {\n\t\terr = errno;\n\t\tgoto error_close_memfd;\n\t}\n\tloopfd = open(loopname, O_RDWR);\n\tif (loopfd == -1) {\n\t\terr = errno;\n\t\tgoto error_close_memfd;\n\t}\n\tif (ioctl(loopfd, LOOP_SET_FD, memfd)) {\n\t\tif (errno != EBUSY) {\n\t\t\terr = errno;\n\t\t\tgoto error_close_loop;\n\t\t}\n\t\tioctl(loopfd, LOOP_CLR_FD, 0);\n\t\tusleep(1000);\n\t\tif (ioctl(loopfd, LOOP_SET_FD, memfd)) {\n\t\t\terr = errno;\n\t\t\tgoto error_close_loop;\n\t\t}\n\t}\n\tclose(memfd);\n\t*loopfd_p = loopfd;\n\treturn 0;\n\nerror_close_loop:\n\tclose(loopfd);\nerror_close_memfd:\n\tclose(memfd);\nerror:\n\terrno = err;\n\treturn -1;\n}\n\nstatic void reset_loop_device(const char* loopname)\n{\n\tint loopfd = open(loopname, O_RDWR);\n\tif (loopfd == -1) {\n\t\treturn;\n\t}\n\tif (ioctl(loopfd, LOOP_CLR_FD, 0)) {\n\t}\n\tclose(loopfd);\n}\n\nstatic long syz_mount_image(\n    volatile long fsarg,\n    volatile long dir,\n    volatile long flags,\n    volatile long optsarg,\n    volatile long change_dir,\n    volatile unsigned long size,\n    volatile long image)\n{\n\tunsigned char* data = (unsigned char*)image;\n\tint res = -1, err = 0, need_loop_device = !!size;\n\tchar* mount_opts = (char*)optsarg;\n\tchar* target = (char*)dir;\n\tchar* fs = (char*)fsarg;\n\tchar* source = NULL;\n\tchar loopname[64];\n\tif (need_loop_device) {\n\t\tint loopfd;\n\t\tmemset(loopname, 0, sizeof(loopname));\n\t\tsnprintf(loopname, sizeof(loopname), \"/dev/loop%llu\", procid);\n\t\tif (setup_loop_device(data, size, loopname, &loopfd) == -1)\n\t\t\treturn -1;\n\t\tclose(loopfd);\n\t\tsource = loopname;\n\t}\n\tmkdir(target, 0777);\n\tchar opts[256];\n\tmemset(opts, 0, sizeof(opts));\n\tif (strlen(mount_opts) > (sizeof(opts) - 32)) {\n\t}\n\tstrncpy(opts, mount_opts, sizeof(opts) - 32);\n\tif (strcmp(fs, \"iso9660\") == 0) {\n\t\tflags |= MS_RDONLY;\n\t} else if (strncmp(fs, \"ext\", 3) == 0) {\n\t\tbool has_remount_ro = false;\n\t\tchar* remount_ro_start = strstr(opts, \"errors=remount-ro\");\n\t\tif (remount_ro_start != NULL) {\n\t\t\tchar after = *(remount_ro_start + strlen(\"errors=remount-ro\"));\n\t\t\tchar before = remount_ro_start == opts ? '\\0' : *(remount_ro_start - 1);\n\t\t\thas_remount_ro = ((before == '\\0' || before == ',') && (after == '\\0' || after == ','));\n\t\t}\n\t\tif (strstr(opts, \"errors=panic\") || !has_remount_ro)\n\t\t\tstrcat(opts, \",errors=continue\");\n\t} else if (strcmp(fs, \"xfs\") == 0) {\n\t\tstrcat(opts, \",nouuid\");\n\t} else if (strncmp(fs, \"gfs2\", 4) == 0 && (strstr(opts, \"errors=panic\") || strstr(opts, \"debug\"))) {\n\t\tstrcat(opts, \",errors=withdraw\");\n\t}\n\tres = mount(source, target, fs, flags, opts);\n\tif (res == -1) {\n\t\terr = errno;\n\t\tgoto error_clear_loop;\n\t}\n\tres = open(target, O_RDONLY | O_DIRECTORY);\n\tif (res == -1) {\n\t\terr = errno;\n\t\tgoto error_clear_loop;\n\t}\n\tif (change_dir) {\n\t\tres = chdir(target);\n\t\tif (res == -1) {\n\t\t\terr = errno;\n\t\t}\n\t}\n\nerror_clear_loop:\n\tif (need_loop_device)\n\t\treset_loop_device(loopname);\n\terrno = err;\n\treturn res;\n}\n\nstatic void kill_and_wait(int pid, int* status)\n{\n\tkill(-pid, SIGKILL);\n\tkill(pid, SIGKILL);\n\tfor (int i = 0; i < 100; i++) {\n\t\tif (waitpid(-1, status, WNOHANG | __WALL) == pid)\n\t\t\treturn;\n\t\tusleep(1000);\n\t}\n\tDIR* dir = opendir(\"/sys/fs/fuse/connections\");\n\tif (dir) {\n\t\tfor (;;) {\n\t\t\tstruct dirent* ent = readdir(dir);\n\t\t\tif (!ent)\n\t\t\t\tbreak;\n\t\t\tif (strcmp(ent->d_name, \".\") == 0 || strcmp(ent->d_name, \"..\") == 0)\n\t\t\t\tcontinue;\n\t\t\tchar abort[300];\n\t\t\tsnprintf(abort, sizeof(abort), \"/sys/fs/fuse/connections/%s/abort\", ent->d_name);\n\t\t\tint fd = open(abort, O_WRONLY);\n\t\t\tif (fd == -1) {\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (write(fd, abort, 1) < 0) {\n\t\t\t}\n\t\t\tclose(fd);\n\t\t}\n\t\tclosedir(dir);\n\t} else {\n\t}\n\twhile (waitpid(-1, status, __WALL) != pid) {\n\t}\n}\n\nstatic void reset_loop()\n{\n\tchar buf[64];\n\tsnprintf(buf, sizeof(buf), \"/dev/loop%llu\", procid);\n\tint loopfd = open(buf, O_RDWR);\n\tif (loopfd != -1) {\n\t\tioctl(loopfd, LOOP_CLR_FD, 0);\n\t\tclose(loopfd);\n\t}\n}\n\nstatic void setup_test()\n{\n\tprctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);\n\tsetpgrp();\n\twrite_file(\"/proc/self/oom_score_adj\", \"1000\");\n}\n\nstatic void execute_one(void);\n\n#define WAIT_FLAGS __WALL\n\nstatic void loop(void)\n{\n\tint iter = 0;\n\tfor (;; iter++) {\n\t\treset_loop();\n\t\tint pid = fork();\n\t\tif (pid < 0)\n\texit(1);\n\t\tif (pid == 0) {\n\t\t\tsetup_test();\n\t\t\texecute_one();\n\t\t\texit(0);\n\t\t}\n\t\tint status = 0;\n\t\tuint64_t start = current_time_ms();\n\t\tfor (;;) {\n\t\t\tsleep_ms(10);\n\t\t\tif (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)\n\t\t\t\tbreak;\n\t\t\tif (current_time_ms() - start < 5000)\n\t\t\t\tcontinue;\n\t\t\tkill_and_wait(pid, &status);\n\t\t\tbreak;\n\t\t}\n\t}\n}\n\nvoid execute_one(void)\n{\n\t\tif (write(1, \"executing program\\n\", sizeof(\"executing program\\n\") - 1)) {}\nmemcpy((void*)0x200000000400, \"ext2\\000\", 5);\nmemcpy((void*)0x200000000440, \"./file0\\000\", 8);\n*(uint8_t*)0x200000000480 = 0;\nmemcpy((void*)0x2000000004c0, \"\\x78\\x9c\\xec\\xdc\\xcd\\x6b\\x1c\\x65\\x1c\\x07\\xf0\\xef\\xce\\x36\\xda\\x97\\xd4\\xd6\\xb6\\xbe\\x55\\xa5\\x05\\x85\\x0a\\x62\\x9a\\x36\\x8a\\xbd\\x49\\xf5\\x0f\\x10\\xac\\x82\\xd7\\x60\\xd3\\x17\\xba\\x6d\\x24\\x89\\xd4\\x16\\x5a\\xec\\x5d\\x3c\\x14\\x41\\xc1\\x93\\x9e\\x3d\\xf4\\x26\\xde\\xf4\\xe6\\xc5\\x83\\xe0\\x41\\xf0\\xe2\\xa1\\x20\\x08\\xc5\\x1e\\x3c\\xf8\\xbe\\x32\\xbb\\xb3\\xeb\\x36\\xee\\x06\\xdb\\x26\\x6e\\xec\\x7c\\x3e\\x30\\xbb\\xcf\\x33\\x33\\xcb\\xef\\x79\\x92\\xfc\\x26\\xcf\\xfc\\xc8\\x24\\x40\\x6d\\xed\\x2d\\x5f\\x1a\\xc9\\x64\\x92\\x6f\\x93\\x6c\\xeb\\x76\\x6f\\x3c\\x61\\x6f\\xf7\\xed\\xf2\\xcc\\x95\\x13\\xe5\\xd6\\x48\\xbb\\x7d\\xe4\\xc7\\x46\\xe7\\xbc\\x8b\\x33\\x57\\x4e\\xf4\\x4e\\xed\\x7d\\x6e\\x4b\\x92\\xb7\\x92\\x6c\\x4c\\xb2\\x23\\x49\\x73\\x48\\xdc\\xc5\\x73\\xe7\\x4f\\xcd\\xb6\\x5a\\x73\\x0b\\x55\\x7f\\xff\\xd2\\xe9\\xd7\\xf7\\x2f\\x9e\\x3b\\xff\\xd4\\xc9\\xd3\\xb3\\xc7\\xe7\\x8e\\xcf\\x9d\\x39\\x30\\xf3\\xec\\xd3\\xd3\\x87\\x9e\\x99\\x3e\\x74\\x68\\xd5\\xe6\\x7a\\xed\\xf3\\xb7\\x5f\\xcd\\xcb\\x2f\\x1e\\x7c\\x67\\xcf\\x77\\x1f\\xbd\\xf0\\xe9\\xce\\x0b\\xe5\\x78\\x27\\xab\\x63\\x83\\xf3\\x58\\x4d\\x8d\\x11\\xfb\\x1f\\x5c\\x8b\\x60\\x63\\xb4\\x69\\xdc\\x03\\xe0\\x96\\x94\\xb9\\xb9\\x21\\xc9\\x44\\x27\\xff\\xb7\\xa5\\xd9\\xe9\\x01\\x75\\xd0\\x6e\\xb7\\xf7\\xac\\x7c\\x18\\xb8\\x73\\x35\\x24\\x39\\xd4\\x54\\xef\\x17\\x7d\\x79\\xff\\xdb\\xdb\\xfe\\x9b\\x95\\x47\\xd7\\xb5\\xc3\\xdd\\x1b\\x90\\x8b\\x55\\x6d\\xe1\\x72\\x3f\\xfe\\x86\\x14\\xd5\\x39\\x13\\xee\\x2f\\x81\\x35\\xf0\\x59\\x79\\xfd\\x99\\x1e\\x76\\xfd\\x2b\\x6e\\xa8\\xd1\\x6d\\xae\\xea\\x9a\\x93\\x49\\xb6\\x26\\xb9\\xa7\\xaa\\x95\\x6e\\x4f\\x72\\x6f\\x55\\xe7\\xdc\\x99\\x64\\x57\\x92\\xfb\\x6e\\x22\\x7e\\xef\\xfa\\x77\\xf9\\x1f\\xd7\\xbf\\xa2\\x7f\\xfd\\x6b\\x26\\xb9\\xff\\x36\\xe6\\x38\\xd1\\xba\\x7e\\x75\\xb0\\x3f\\x58\\x8f\\xbd\\x76\\x29\\xd9\\x3d\\x34\\x7e\\xa3\\x5f\\x09\\x6a\\x94\\x37\\x82\\x49\\x1e\\xb8\\xc5\\xf8\\x9f\\x3c\\x77\\xe1\\x8b\\x51\\xc7\\xda\\x1f\\x26\\xfb\\x32\\x3c\\x7e\\x06\\xe2\\xaf\\x50\\x1f\\xde\\x7f\\xec\\x64\\x6b\\x6e\\xba\\xfb\\x3a\\x34\\xc6\\xf3\\xaf\\x1c\\xfb\\x72\\x54\\xfc\\x72\\xfe\\x9b\\x87\\xc5\\x2f\\xd2\\x9f\\x7f\\xf3\\x36\\xeb\\xb5\\x57\\x37\\xbd\\x94\\x3f\\x56\\x88\\xff\\xc4\\x63\\xc3\\xbf\\xff\\x3b\\x06\\xe6\\xff\\x67\\x92\\x5f\\x92\\xfc\\x9a\\xe4\\xb7\\x24\\xbf\\x27\\x79\\x28\\xc9\\xee\\x24\\x0f\\x27\\x79\\x64\\x85\\xf8\\x87\\xbf\\xfa\\x7a\\x7e\\xd4\\xb1\\x32\\xfe\\xd1\\x11\\x5f\\xff\\x62\\x20\\xfe\\xa3\\xb7\\x32\\xf1\\xca\\xd9\\xef\\x3f\\xbe\\x74\\x1b\\x1f\\x07\\x00\\x56\\x59\\xd1\\x59\\xd3\\x36\\x8a\\xa9\\x7e\\xbb\\x28\\xa6\\xa6\\xba\\x6b\\xdd\\x5d\\xd9\\x5c\\xb4\\xe6\\x17\\x97\\x9e\\x3c\\x36\\xff\\xc6\\x99\\xa3\\xdd\\xb5\\xef\\xf6\\x4c\\x14\\xbd\\x95\\x56\\x77\\xfd\\x3b\\xd1\\x28\\xfb\\x07\\xaa\\xb5\\x70\\xaf\\x7f\\x70\\x59\\x7f\\xa6\\x5a\\x27\\xbf\\xdb\\xdc\\xd4\\xe9\\x4f\\xbd\\x36\\xdf\\x3a\\x3a\\xee\\xc9\\x43\\xcd\\x6d\\x59\\x96\\xff\\x3f\\x35\\xbb\\xf9\\x0f\\xd4\\x84\\x3f\\xf9\\x81\\xfa\\x92\\xff\\x50\\x5f\\xf2\\x1f\\xea\\x4b\\xfe\\x43\\x7d\\xc9\\x7f\\xa8\\x2f\\xf9\\x0f\\xf5\\x25\\xff\\xa1\\xbe\\xe4\\x3f\\xd4\\x97\\xfc\\x87\\xfa\\x92\\xff\\x50\\x5f\\xf2\\x1f\\x6a\\x69\\x72\\xc4\\xf3\\x3f\\x5b\\x07\\x9e\\xdd\\x99\\xae\\x9e\\x77\\xff\\xa6\\x39\\x71\\x77\\xef\\x59\\x1f\\xe0\\xff\\x6f\\x6e\\xa1\\xff\\x9f\\x78\\x97\\x35\\xc6\\x3d\\x32\\x60\\xad\\xfd\\x9d\\xf4\\xe3\\x1e\\x09\\x00\\x00\\x00\\x00\\xb0\\xda\\x46\\x55\\xff\\x57\\xb3\\x31\\xee\\x39\\x02\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\xdc\\x9c\\xe2\\x87\\x46\\x92\\x72\\xdb\\xb7\\xed\\xf1\\xc9\\xe5\\x47\\xef\\x6a\\xfc\\xdc\\xec\\xbc\\x27\\x39\\xfb\\xc1\\x91\\xf7\\xde\\x9c\\x5d\\x5a\\x5a\\x38\\x50\\xee\\xbf\\xde\\xdf\\xbf\\xf4\\x7e\\xb5\\xff\\xe0\\x38\\xc6\\x0f\\xfc\\x5b\\xbd\\x3c\\xed\\xe5\\x31\\x50\\x5f\\x8b\\xe7\\xce\\x9f\\x9a\\x6d\\xb5\\xe6\\x16\\xee\\x9c\\xc6\\xc6\\x24\\xeb\\x60\\x18\\x1a\\xeb\\xa9\\xb1\\xbd\\xfa\\x79\\x5f\\x2f\\xe3\\x59\\x2f\\x8d\\xbf\\x02\\x00\\x00\\xff\\xff\\x87\\xb5\\x73\\xae\", 1002);\nsyz_mount_image(/*fs=*/0x200000000400, /*dir=*/0x200000000440, /*flags=*/0, /*opts=*/0x200000000480, /*chdir=*/1, /*size=*/0x3ea, /*img=*/0x2000000004c0);\nmemcpy((void*)0x200000000000, \"./file0/file0\\000\", 14);\nmemcpy((void*)0x2000000000c0, \"./file1\\000\", 8);\n\tsyscall(__NR_rename, /*old=*/0x200000000000ul, /*new=*/0x2000000000c0ul);\n\n}\nint main(void)\n{\n\t\tsyscall(__NR_mmap, /*addr=*/0x1ffffffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);\n\tsyscall(__NR_mmap, /*addr=*/0x200000000000ul, /*len=*/0x1000000ul, /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/7ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);\n\tsyscall(__NR_mmap, /*addr=*/0x200001000000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/(intptr_t)-1, /*offset=*/0ul);\n\tconst char* reason;\n\t(void)reason;\n\t\t\tloop();\n\treturn 0;\n}\n\n--\n2.50.1"}