* [PATCH] hfsplus: pretend special inodes as regular files
@ 2025-12-29 11:42 Tetsuo Handa
2025-12-29 20:28 ` Viacheslav Dubeyko
0 siblings, 1 reply; 8+ messages in thread
From: Tetsuo Handa @ 2025-12-29 11:42 UTC (permalink / raw)
To: Viacheslav Dubeyko, John Paul Adrian Glaubitz, Yangtao Li,
linux-fsdevel
[-- Attachment #1: Type: text/plain, Size: 838 bytes --]
syzbot is reporting that hfsplus_system_read_inode() from hfsplus_iget()
from hfsplus_btree_open() from hfsplus_fill_super() succeeds with
inode->i_mode == 0, for hfsplus_system_read_inode() does not call
hfsplus_get_perms() for updating inode->i_mode value.
Reported-by: syzbot <syzbot+895c23f6917da440ed0d@syzkaller.appspotmail.com>
Closes: https://syzkaller.appspot.com/bug?extid=895c23f6917da440ed0d
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
fs/hfsplus/super.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index aaffa9e060a0..82e0bf066e3b 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -52,6 +52,7 @@ static int hfsplus_system_read_inode(struct inode *inode)
default:
return -EIO;
}
+ inode->i_mode = S_IFREG;
return 0;
}
--
2.47.3
[-- Attachment #2: repro.c --]
[-- Type: text/plain, Size: 24352 bytes --]
// autogenerated by syzkaller (https://github.com/google/syzkaller)
#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");
} else if (strncmp(fs, "gfs2", 4) == 0 &&
(strstr(opts, "errors=panic") || strstr(opts, "debug"))) {
strcat(opts, ",errors=withdraw");
}
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;
}
uint64_t r[4] = {0xffffffffffffffff, 0xffffffffffffffff, 0xffffffffffffffff,
0xffffffffffffffff};
int main(void)
{
syscall(__NR_mmap, /*addr=*/0x1ffffffff000ul, /*len=*/0x1000ul, /*prot=*/0ul,
/*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul,
/*fd=*/(intptr_t)-1, /*offset=*/0ul);
syscall(__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);
syscall(__NR_mmap, /*addr=*/0x200001000000ul, /*len=*/0x1000ul, /*prot=*/0ul,
/*flags=MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE*/ 0x32ul,
/*fd=*/(intptr_t)-1, /*offset=*/0ul);
const char* reason;
(void)reason;
intptr_t res = 0;
if (write(1, "executing program\n", sizeof("executing program\n") - 1)) {
}
// syz_mount_image$hfsplus arguments: [
// fs: ptr[in, buffer] {
// buffer: {68 66 73 70 6c 75 73 00} (length 0x8)
// }
// dir: ptr[in, buffer] {
// buffer: {2e 2f 66 69 6c 65 31 00} (length 0x8)
// }
// flags: mount_flags = 0xc00a (8 bytes)
// opts: ptr[inout, array[ANYUNION]] {
// array[ANYUNION] {
// }
// }
// chdir: int8 = 0x11 (1 bytes)
// size: len = 0x6c2 (8 bytes)
// img: ptr[in, buffer] {
// buffer: (compressed buffer with length 0x6c2)
// }
// ]
// returns fd_dir
memcpy((void*)0x200000000180, "hfsplus\000", 8);
memcpy((void*)0x200000001480, "./file1\000", 8);
memcpy(
(void*)0x200000000ac0,
"\x78\x9c\xec\xdd\xcd\x6f\x1c\x67\x1d\x07\xf0\xef\xac\xd7\x2f\x9b\x4a\xae"
"\xfb\x1e\x50\xa5\x9a\x46\x2a\x88\x88\x26\x8e\x95\x42\xb8\x24\x20\x84\x82"
"\x54\xa1\x2a\x1c\x38\x5b\xc4\x69\xac\x6c\xd2\xe0\xb8\x28\xed\x81\xb8\x80"
"\xc4\x95\x03\x7f\x40\x39\x84\x0b\x9c\x40\x08\x09\x09\x29\x52\x39\xc3\xad"
"\xe2\x66\x71\xaa\x84\xd4\x4b\x4f\x69\x0f\x0c\x9a\xd9\x59\x7b\xed\xee\xda"
"\x9b\x44\xc9\x3a\xf0\xf9\x58\xb3\xf3\x3c\xf3\xcc\x3c\xf3\x9b\xdf\xbc\xed"
"\xae\xb5\x9a\x00\xff\xb7\xce\x1f\x4f\xfb\x4e\x3a\x39\x7f\xfc\xf5\x9b\x55"
"\x7d\xeb\xf6\x72\x77\xeb\xf6\xf2\xd5\x5e\xb9\xd5\x4d\x32\x9b\xa4\x95\xb4"
"\x7b\xa3\x14\xd7\x92\xe2\x83\xe4\x5c\x7a\x43\xbe\x50\x4d\x6c\xba\x2b\x46"
"\xad\xe7\xd7\x6b\x67\x2e\x7c\xf8\xc9\xd6\x47\xbd\x5a\x3b\x3b\xfd\x55\x2f"
"\x9d\xd1\x01\xb6\xc7\xd9\x8a\xcd\x66\xc8\x62\x92\xa9\x66\xfc\x00\x76\xf5"
"\xf7\xa3\xfb\xeb\x6f\x76\xa7\x58\x6c\x67\xa6\x4a\xd8\xb1\x7e\xe2\x60\xd2"
"\xa6\x93\x94\xbb\xfc\xf8\xf9\x9d\x96\x61\xca\xa9\x81\xca\xc8\xf3\x1d\x78"
"\x7c\x14\xbd\xfb\xe6\x80\xde\xf9\xbf\x90\x1c\x49\x32\xd7\xbf\xa1\x6d\xf6"
"\x1a\x5b\x8f\x3e\xc2\x03\xdd\xd3\xb5\x68\xf3\xe1\xc5\x01\x00\x00\x00\x87"
"\xc6\x93\x77\x6f\x25\x37\x33\x3f\xe9\x38\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\xe0\x71\xd2\x3c\xff\xbf\x68\x86\x56\xbf\xbc\x98\xa2\xff\xfc\xff\x99"
"\x81\x67\xec\xcf\x4c\x38\xdc\xd1\xf6\x8f\x6c\xae\x5f\xb8\xd3\x7a\x14\xc1"
"\x00\x00\x00\x00\x00\x00\x00\xc0\xc3\xf5\xd2\xdd\xfc\xee\x42\x59\xce\xf7"
"\xeb\x65\x51\xff\xcf\xff\xe5\xba\xf2\x6c\xfd\xfa\x44\xde\xce\x8d\xac\x66"
"\x3d\xaf\xe6\x66\x56\xb2\x91\x8d\xac\x67\x29\xc9\xc2\x40\x47\x33\x37\x57"
"\x36\x36\xd6\x97\xfa\x4b\x7e\x56\x96\xe5\x88\x25\x4f\xed\xfc\xf7\x7d\x60"
"\xc9\x53\x63\x06\xdc\x79\xf0\x6d\x06\x00\x00\x00\x00\x00\x00\x80\xff\x21"
"\x67\x9b\xf1\xcf\x72\x3e\xf3\x13\x8e\x05\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x76\x29\x92\xa9\xde\xa8\x1e\x9e\xed\x97\x17\xd2\x6a\x27\x99"
"\x4b\x32\x53\xcd\xb7\x99\xfc\xa3\x5f\x7e\x9c\xdd\x99\x74\x00\x00\x00\x00"
"\xf0\x08\x3c\x79\x37\x77\x73\x33\xf3\xfd\x7a\x59\xd4\x9f\xf9\x9f\xaf\x3f"
"\xf7\xcf\xe5\xed\x5c\xcb\x46\xd6\xb2\x91\x6e\x56\x73\xb1\xfe\x2e\xa0\xf7"
"\xa9\xbf\xb5\x75\x7b\xb9\xbb\x75\x7b\xf9\x6a\x35\x7c\xbe\xdf\x6f\x7d\xbc"
"\x53\xfe\xe3\xfc\x81\x61\xd4\x3d\xa6\xf7\xdd\xc3\xf0\x35\x1f\xad\xe7\xe8"
"\xe4\x52\xd6\x9a\xb9\x92\xb7\xd2\xcd\xc5\xb4\xea\x25\x2b\x47\xfb\xf1\x0c"
"\x8f\xeb\xbd\xfa\x9b\x8d\xb3\x3d\x65\x99\xd9\x71\x12\x74\xb1\x19\x57\x5b"
"\xfe\xab\x66\x7c\x38\x2c\xd4\x19\x99\xae\x33\x52\xe5\xe8\x64\x13\x5b\x95"
"\x8d\xa7\xf6\xcf\xc4\xe0\xde\xb9\x8f\x35\x2d\xa5\xb5\xfd\xcd\xcf\x5c\x33"
"\x1e\x95\xf3\x8f\x07\x72\x7e\x76\xdf\xb5\x14\xff\x29\xcb\x5e\xe9\x48\x7f"
"\x4a\xf2\xc4\xf7\x0e\xce\xf9\xf4\x3d\x6d\xcc\x03\xd9\x9b\x89\x53\x03\x47"
"\xdf\xf3\xfb\xe7\x3c\xf9\xf2\x9f\x7e\xff\xc3\xcb\xdd\x6b\x57\x2e\x17\x9b"
"\xc7\x0f\xcf\x61\x34\xcc\x4b\xc3\x27\xcf\xfe\xab\xbf\x87\xfa\x99\xe8\xd9"
"\xcc\x6a\x96\x07\x32\xf1\x42\x93\x81\xa9\xfe\x71\xb1\xb7\xa3\xed\x4c\x5c"
"\xba\x71\xc8\x33\x31\xa6\x56\x9e\xdb\x2e\x9f\xcf\x77\xf3\x83\x1c\xcf\x62"
"\xde\xc8\x7a\xd6\xf2\x93\xac\x64\x23\xab\x59\xcc\x77\xea\xd2\x4a\x73\x3c"
"\x57\xaf\x0b\xfb\x1f\x33\xe7\x76\xd5\xde\x38\x28\x8a\x99\x66\xbf\x4c\xed"
"\x89\xe9\x4b\x4f\xf6\xc6\xfb\xc5\xf4\x72\xbd\xec\x7c\xd6\xf2\xfd\xbc\x95"
"\x8b\x59\xcd\x6b\xf5\xdf\xa9\x2c\xe5\xeb\x39\x9d\xd3\x39\x33\xb0\x87\x9f"
"\x3b\xe0\x4a\x5b\x9d\xf5\xad\x21\x67\xfd\x9f\x47\x07\x7f\xec\x2b\x4d\xa1"
"\x93\xe4\x97\xcd\xf8\x70\xa8\xf2\xfa\xd4\x40\x5e\x07\xaf\xb9\x0b\x75\xdb"
"\xe0\x94\x56\xca\xe6\xce\xf2\xf4\x18\x59\x1a\xef\xda\x98\x94\x65\xef\xdc"
"\xfb\x62\x53\xaf\xf6\xc4\xcf\x07\xce\xc1\xc9\xdb\xce\xc4\x5c\xb6\xef\x12"
"\xfd\xe8\x9e\xe9\x67\x60\x7a\x68\x26\x7e\x53\x6f\xda\x8d\xee\xb5\x2b\xeb"
"\x97\x57\xae\xef\xe9\xb7\xd8\x1c\xbe\xbe\x57\xb2\x7b\xf3\x0f\xcf\x85\xa4"
"\x3a\x5e\x9e\x4e\xd2\xae\x6b\xbb\x8f\x8e\xaa\xed\x99\xa1\x6d\x4b\x75\xdb"
"\xb3\xdb\x6d\xad\xbd\x6d\xbf\xed\x6c\xb7\x1d\x74\xa6\xce\x34\xef\xe1\x3e"
"\xdf\xd3\xa9\xba\xed\x85\xa1\x6d\xcb\x75\xdb\xd1\x81\xb6\xea\xfd\x56\x75"
"\x87\x5f\xcd\x67\x65\x59\xf6\xde\x6f\x01\x70\xe8\x1d\xf9\xea\x91\x99\xce"
"\xbf\x3b\x7f\xef\xbc\xdf\xf9\x45\xe7\x72\xe7\xf5\xb9\x6f\xcf\x7e\x63\xf6"
"\xc5\x99\x4c\xff\x6d\xfa\x9b\xed\x93\x53\xaf\xb4\x5e\x2c\xfe\x90\xf7\xf3"
"\xd3\x1c\xfc\x09\x1d\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x38\xd0\x8d\x77\xde\xbd\xb2\xd2"
"\xed\xae\xae\xef\x29\x94\x65\x79\x6b\x44\xd3\x43\x29\xa4\x9d\xec\x9a\xf2"
"\xd7\xbf\x34\x85\xe6\x29\x6f\xf5\xc3\x80\xc6\xef\xb0\x9a\xfb\x5c\x2b\xa9"
"\xa7\xb4\xd3\x14\xee\x2d\xb0\x5b\xf7\xb7\x39\xef\xdd\x6f\x12\xfe\xd9\xec"
"\x93\x5d\x4d\xf5\x53\x78\x1e\xc9\x2e\xb8\x8f\xc2\xdc\xc8\xe3\x67\x6f\xe1"
"\xd3\xb2\x2c\x0f\x47\xcc\xe3\x14\xca\xc6\x61\x89\x67\x12\x85\xc9\x5d\x93"
"\x80\x47\xe3\xc4\xc6\xd5\xeb\x27\x6e\xbc\xf3\xee\xd7\xd6\xae\xb6\xde\x5c"
"\x7d\x73\xf5\xda\x99\xd3\xa7\xcf\x9c\x3c\x73\xfa\xb5\xe5\x13\x97\xd6\xba"
"\x73\x93\x0e\x0f\x78\x88\xea\x7b\x7d\xfd\x3e\x67\xd2\x91\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\xe3\x1a\xef\xc7\x39\xc5\x83\xfd\xb6\x07\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
"\x00\xe0\x01\x9c\x3f\x9e\xf6\x9d\x14\x59\x3a\xf9\xea\xc9\xaa\xbe\x75\x7b"
"\xb9\x5b\x0d\xfd\xf2\xce\x9c\x9f\x26\x69\x25\x29\x16\x93\xe2\x83\xe4\x5c"
"\x7a\x43\x16\x06\xba\x2b\x46\xad\x67\x33\xb9\xf0\xe1\x27\x5b\x1f\xf5\x6a"
"\xed\x66\xa8\xe7\x6f\xed\xb7\xdc\x78\x36\x9b\x21\x8b\x49\xa6\x9a\xf1\x10"
"\x73\x49\x8e\xec\x9d\x58\xde\x1a\xd5\x5f\x51\xf7\x73\x7d\x74\x7f\x63\x2a"
"\xb6\xb7\xb0\x4a\xd8\xb1\x7e\xe2\x60\xd2\xfe\x1b\x00\x00\xff\xff\xb4\x74"
"\x0f\x0c",
1730);
res = -1;
res = syz_mount_image(/*fs=*/0x200000000180, /*dir=*/0x200000001480,
/*flags=MS_REC|MS_SILENT|MS_NOSUID|MS_NOEXEC*/ 0xc00a,
/*opts=*/0x200000000040, /*chdir=*/0x11, /*size=*/0x6c2,
/*img=*/0x200000000ac0);
if (res != -1)
r[0] = res;
// openat arguments: [
// fd: fd_dir (resource)
// file: ptr[in, buffer] {
// buffer: {2e 2f 66 69 6c 65 31 00} (length 0x8)
// }
// flags: open_flags = 0x183042 (4 bytes)
// mode: open_mode = 0x8 (2 bytes)
// ]
// returns fd
memcpy((void*)0x200000000080, "./file1\000", 8);
res = syscall(__NR_openat, /*fd=*/0xffffff9c, /*file=*/0x200000000080ul,
/*flags=O_SYNC|O_CREAT|O_CLOEXEC|FASYNC|O_RDWR*/ 0x183042,
/*mode=S_IXGRP*/ 8);
if (res != -1)
r[1] = res;
return 0;
}
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH] hfsplus: pretend special inodes as regular files
2025-12-29 11:42 [PATCH] hfsplus: pretend special inodes as regular files Tetsuo Handa
@ 2025-12-29 20:28 ` Viacheslav Dubeyko
2025-12-30 1:07 ` Tetsuo Handa
0 siblings, 1 reply; 8+ messages in thread
From: Viacheslav Dubeyko @ 2025-12-29 20:28 UTC (permalink / raw)
To: glaubitz@physik.fu-berlin.de, frank.li@vivo.com,
penguin-kernel@I-love.SAKURA.ne.jp, slava@dubeyko.com,
linux-fsdevel@vger.kernel.org
On Mon, 2025-12-29 at 20:42 +0900, Tetsuo Handa wrote:
> syzbot is reporting that hfsplus_system_read_inode() from hfsplus_iget()
> from hfsplus_btree_open() from hfsplus_fill_super() succeeds with
> inode->i_mode == 0, for hfsplus_system_read_inode() does not call
> hfsplus_get_perms() for updating inode->i_mode value.
>
Frankly speaking, commit message sounds completely not clear:
(1) What is the problem?
(2) How it can be reproduced?
(3) Why should we fix it?
So, could you please rework the commit message?
> Reported-by: syzbot <syzbot+895c23f6917da440ed0d@syzkaller.appspotmail.com>
> Closes: https://syzkaller.appspot.com/bug?extid=895c23f6917da440ed0d
> Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> ---
> fs/hfsplus/super.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
> index aaffa9e060a0..82e0bf066e3b 100644
> --- a/fs/hfsplus/super.c
> +++ b/fs/hfsplus/super.c
> @@ -52,6 +52,7 @@ static int hfsplus_system_read_inode(struct inode *inode)
> default:
> return -EIO;
> }
> + inode->i_mode = S_IFREG;
It's completely not clear why should it be fixed here? Currently, it looks to me
like not proper place for the fix. Could we use already existing function for
this? Why should we use namely S_IFREG for this case?
Thanks,
Slava.
>
> return 0;
> }
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH] hfsplus: pretend special inodes as regular files
2025-12-29 20:28 ` Viacheslav Dubeyko
@ 2025-12-30 1:07 ` Tetsuo Handa
2026-01-02 10:17 ` [PATCH v2] " Tetsuo Handa
0 siblings, 1 reply; 8+ messages in thread
From: Tetsuo Handa @ 2025-12-30 1:07 UTC (permalink / raw)
To: Viacheslav Dubeyko, glaubitz@physik.fu-berlin.de,
frank.li@vivo.com, slava@dubeyko.com,
linux-fsdevel@vger.kernel.org
On 2025/12/30 5:28, Viacheslav Dubeyko wrote:
> On Mon, 2025-12-29 at 20:42 +0900, Tetsuo Handa wrote:
>> syzbot is reporting that hfsplus_system_read_inode() from hfsplus_iget()
>> from hfsplus_btree_open() from hfsplus_fill_super() succeeds with
>> inode->i_mode == 0, for hfsplus_system_read_inode() does not call
>> hfsplus_get_perms() for updating inode->i_mode value.
>>
>
> Frankly speaking, commit message sounds completely not clear:
> (1) What is the problem?
Commit af153bb63a33 ("vfs: catch invalid modes in may_open()") requires any inode
that can reach may_open() to have a valid file type (one of S_IFDIR/S_IFLNK/S_IFREG/
S_IFCHR/S_IFBLK/S_IFIFO/S_IFSOCK type). Even if an inode is for internal use only,
that inode must have a valid file type if userspace can pass that inode to
may_open(). Commit 4e8011ffec79 ("ntfs3: pretend $Extend records as regular files")
was an example for assigning a valid file type to an inode that is not meant to be
used (but still usable) from userspace. This patch is the same change for hfsplus.
> (2) How it can be reproduced?
Just build and run the attached C reproducer, on a kernel built with
CONFIG_DEBUG_VFS=y .
> (3) Why should we fix it?
Because that is a requirement introduced by commit af153bb63a33.
>
> So, could you please rework the commit message?
F.Y.I. Regarding ntfs3, commit be99c62ac7e7 ("ntfs3: init run lock for extend
inode") was also needed due to hidden dependency. I don't know whether hfsplus
has similar hidden dependency.
>
>> Reported-by: syzbot <syzbot+895c23f6917da440ed0d@syzkaller.appspotmail.com>
>> Closes: https://syzkaller.appspot.com/bug?extid=895c23f6917da440ed0d
>> Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
>> ---
>> fs/hfsplus/super.c | 1 +
>> 1 file changed, 1 insertion(+)
>>
>> diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
>> index aaffa9e060a0..82e0bf066e3b 100644
>> --- a/fs/hfsplus/super.c
>> +++ b/fs/hfsplus/super.c
>> @@ -52,6 +52,7 @@ static int hfsplus_system_read_inode(struct inode *inode)
>> default:
>> return -EIO;
>> }
>> + inode->i_mode = S_IFREG;
>
> It's completely not clear why should it be fixed here? Currently, it looks to me
> like not proper place for the fix. Could we use already existing function for
> this? Why should we use namely S_IFREG for this case?
Do you mean "existing function" == hfsplus_get_perms() ? If yes, where can we find
the parameters needed for calling hfsplus_get_perms() ?
>
> Thanks,
> Slava.
>
>>
>> return 0;
>> }
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v2] hfsplus: pretend special inodes as regular files
2025-12-30 1:07 ` Tetsuo Handa
@ 2026-01-02 10:17 ` Tetsuo Handa
2026-01-06 0:16 ` Viacheslav Dubeyko
0 siblings, 1 reply; 8+ messages in thread
From: Tetsuo Handa @ 2026-01-02 10:17 UTC (permalink / raw)
To: Viacheslav Dubeyko, glaubitz@physik.fu-berlin.de,
frank.li@vivo.com, slava@dubeyko.com,
linux-fsdevel@vger.kernel.org
Since commit af153bb63a33 ("vfs: catch invalid modes in may_open()")
requires any inode be one of S_IFDIR/S_IFLNK/S_IFREG/S_IFCHR/S_IFBLK/
S_IFIFO/S_IFSOCK type, use S_IFREG for special inodes.
Reported-by: syzbot <syzbot+895c23f6917da440ed0d@syzkaller.appspotmail.com>
Closes: https://syzkaller.appspot.com/bug?extid=895c23f6917da440ed0d
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
fs/hfsplus/super.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index aaffa9e060a0..82e0bf066e3b 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -52,6 +52,7 @@ static int hfsplus_system_read_inode(struct inode *inode)
default:
return -EIO;
}
+ inode->i_mode = S_IFREG;
return 0;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v2] hfsplus: pretend special inodes as regular files
2026-01-02 10:17 ` [PATCH v2] " Tetsuo Handa
@ 2026-01-06 0:16 ` Viacheslav Dubeyko
2026-01-06 9:39 ` [PATCH v3] " Tetsuo Handa
0 siblings, 1 reply; 8+ messages in thread
From: Viacheslav Dubeyko @ 2026-01-06 0:16 UTC (permalink / raw)
To: glaubitz@physik.fu-berlin.de, frank.li@vivo.com,
penguin-kernel@I-love.SAKURA.ne.jp, slava@dubeyko.com,
linux-fsdevel@vger.kernel.org
On Fri, 2026-01-02 at 19:17 +0900, Tetsuo Handa wrote:
> Since commit af153bb63a33 ("vfs: catch invalid modes in may_open()")
> requires any inode be one of S_IFDIR/S_IFLNK/S_IFREG/S_IFCHR/S_IFBLK/
> S_IFIFO/S_IFSOCK type, use S_IFREG for special inodes.
>
I assume that we have the same issue for HFS special files too.
> Reported-by: syzbot <syzbot+895c23f6917da440ed0d@syzkaller.appspotmail.com>
> Closes: https://syzkaller.appspot.com/bug?extid=895c23f6917da440ed0d
> Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> ---
> fs/hfsplus/super.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
> index aaffa9e060a0..82e0bf066e3b 100644
> --- a/fs/hfsplus/super.c
> +++ b/fs/hfsplus/super.c
> @@ -52,6 +52,7 @@ static int hfsplus_system_read_inode(struct inode *inode)
> default:
> return -EIO;
> }
Could we add some empty line here?
I think it will be great to have some comment here about why i_mode should be
set for special file. Could you please add this comment here?
Thanks,
Slava.
> + inode->i_mode = S_IFREG;
>
> return 0;
> }
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3] hfsplus: pretend special inodes as regular files
2026-01-06 0:16 ` Viacheslav Dubeyko
@ 2026-01-06 9:39 ` Tetsuo Handa
2026-01-06 20:34 ` Viacheslav Dubeyko
2026-02-01 3:58 ` [PATCH v3 (repost)] " Tetsuo Handa
0 siblings, 2 replies; 8+ messages in thread
From: Tetsuo Handa @ 2026-01-06 9:39 UTC (permalink / raw)
To: Viacheslav Dubeyko, glaubitz@physik.fu-berlin.de,
frank.li@vivo.com, slava@dubeyko.com,
linux-fsdevel@vger.kernel.org
Since commit af153bb63a33 ("vfs: catch invalid modes in may_open()")
requires any inode be one of S_IFDIR/S_IFLNK/S_IFREG/S_IFCHR/S_IFBLK/
S_IFIFO/S_IFSOCK type, use S_IFREG for special inodes.
Reported-by: syzbot <syzbot+895c23f6917da440ed0d@syzkaller.appspotmail.com>
Closes: https://syzkaller.appspot.com/bug?extid=895c23f6917da440ed0d
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
fs/hfsplus/super.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index aaffa9e060a0..7f327b777ece 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -53,6 +53,12 @@ static int hfsplus_system_read_inode(struct inode *inode)
return -EIO;
}
+ /*
+ * Assign a dummy file type, for may_open() requires that
+ * an inode has a valid file type.
+ */
+ inode->i_mode = S_IFREG;
+
return 0;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH v3] hfsplus: pretend special inodes as regular files
2026-01-06 9:39 ` [PATCH v3] " Tetsuo Handa
@ 2026-01-06 20:34 ` Viacheslav Dubeyko
2026-02-01 3:58 ` [PATCH v3 (repost)] " Tetsuo Handa
1 sibling, 0 replies; 8+ messages in thread
From: Viacheslav Dubeyko @ 2026-01-06 20:34 UTC (permalink / raw)
To: glaubitz@physik.fu-berlin.de, frank.li@vivo.com,
penguin-kernel@I-love.SAKURA.ne.jp, slava@dubeyko.com,
linux-fsdevel@vger.kernel.org
On Tue, 2026-01-06 at 18:39 +0900, Tetsuo Handa wrote:
> Since commit af153bb63a33 ("vfs: catch invalid modes in may_open()")
> requires any inode be one of S_IFDIR/S_IFLNK/S_IFREG/S_IFCHR/S_IFBLK/
> S_IFIFO/S_IFSOCK type, use S_IFREG for special inodes.
>
> Reported-by: syzbot <syzbot+895c23f6917da440ed0d@syzkaller.appspotmail.com>
> Closes: https://syzkaller.appspot.com/bug?extid=895c23f6917da440ed0d
> Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
> ---
> fs/hfsplus/super.c | 6 ++++++
> 1 file changed, 6 insertions(+)
>
> diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
> index aaffa9e060a0..7f327b777ece 100644
> --- a/fs/hfsplus/super.c
> +++ b/fs/hfsplus/super.c
> @@ -53,6 +53,12 @@ static int hfsplus_system_read_inode(struct inode *inode)
> return -EIO;
> }
>
> + /*
> + * Assign a dummy file type, for may_open() requires that
> + * an inode has a valid file type.
> + */
> + inode->i_mode = S_IFREG;
> +
> return 0;
> }
>
Looks good.
Reviewed-by: Viacheslav Dubeyko <slava@dubeyko.com>
Thanks,
Slava.
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 (repost)] hfsplus: pretend special inodes as regular files
2026-01-06 9:39 ` [PATCH v3] " Tetsuo Handa
2026-01-06 20:34 ` Viacheslav Dubeyko
@ 2026-02-01 3:58 ` Tetsuo Handa
1 sibling, 0 replies; 8+ messages in thread
From: Tetsuo Handa @ 2026-02-01 3:58 UTC (permalink / raw)
To: Viacheslav Dubeyko, John Paul Adrian Glaubitz, Yangtao Li
Cc: linux-fsdevel@vger.kernel.org, Viacheslav Dubeyko
Since commit af153bb63a33 ("vfs: catch invalid modes in may_open()")
requires any inode be one of S_IFDIR/S_IFLNK/S_IFREG/S_IFCHR/S_IFBLK/
S_IFIFO/S_IFSOCK type, use S_IFREG for special inodes.
Reported-by: syzbot <syzbot+f98189ed18c1f5f32e00@syzkaller.appspotmail.com>
Closes:https://syzkaller.appspot.com/bug?extid=f98189ed18c1f5f32e00
Signed-off-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
---
fs/hfsplus/super.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c
index aaffa9e060a0..7f327b777ece 100644
--- a/fs/hfsplus/super.c
+++ b/fs/hfsplus/super.c
@@ -53,6 +53,12 @@ static int hfsplus_system_read_inode(struct inode *inode)
return -EIO;
}
+ /*
+ * Assign a dummy file type, for may_open() requires that
+ * an inode has a valid file type.
+ */
+ inode->i_mode = S_IFREG;
+
return 0;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-02-01 3:59 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-29 11:42 [PATCH] hfsplus: pretend special inodes as regular files Tetsuo Handa
2025-12-29 20:28 ` Viacheslav Dubeyko
2025-12-30 1:07 ` Tetsuo Handa
2026-01-02 10:17 ` [PATCH v2] " Tetsuo Handa
2026-01-06 0:16 ` Viacheslav Dubeyko
2026-01-06 9:39 ` [PATCH v3] " Tetsuo Handa
2026-01-06 20:34 ` Viacheslav Dubeyko
2026-02-01 3:58 ` [PATCH v3 (repost)] " Tetsuo Handa
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox