From nobody Sat Feb 7 07:24:19 2026 Received: from mail-il1-f198.google.com (mail-il1-f198.google.com [209.85.166.198]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id E1C78337100 for ; Wed, 22 Oct 2025 16:13:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.166.198 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149629; cv=none; b=bzQDUi9Alda3JTksU410A23AeYgu7r0w6NSYVP8L+PE8xS88yxU5pEPCOuPHI6hnARj1rdGQf8sA5vnAOLP1WKjRlsHjFoxL9pQXhzEvqv+OOcHiKFp39Sk7LjzdDBXjboovCyNieM3VWJqSueWQz/9OauUvkfyTCnz53xH5Bt4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1761149629; c=relaxed/simple; bh=Sm4GWPNeJcL5gEwJZRJ5PrguqKuzIn1kzPolyeVZzsY=; h=MIME-Version:Date:In-Reply-To:Message-ID:Subject:From:To: Content-Type; b=rf1D04PcSl2EsudYqI+D51oYJ2IWwwkouBwGNXXlntbjgQatXMdXNll2wweIE4l8Q81LBzZAw8YWU35t9oGIOSJEEqbcZhc8btgAJvz52riA/Xq5lTio5utpvPsGzUi+q749UHVI9DJz8nhsoCqI49nFF8AOcvOcf4A26f6I14Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=syzkaller.appspotmail.com; spf=pass smtp.mailfrom=M3KW2WVRGUFZ5GODRSRYTGD7.apphosting.bounces.google.com; arc=none smtp.client-ip=209.85.166.198 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=syzkaller.appspotmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=M3KW2WVRGUFZ5GODRSRYTGD7.apphosting.bounces.google.com Received: by mail-il1-f198.google.com with SMTP id e9e14a558f8ab-431d3a4db56so47968855ab.1 for ; Wed, 22 Oct 2025 09:13:47 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1761149627; x=1761754427; h=to:from:subject:message-id:in-reply-to:date:mime-version :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=wOrJBT4oSmGN7Bwjcc4GP8AOfbxTb3nBv75gJrMjeOQ=; b=HeyCXD+iQSOFFl1eZzcN/5BmLvJXDmBAsvmC6IhHQQGqIrCVzXkTS2k+6jTU1G/50p 2x2ep0Jx9G+9CxOR1Bi7IuthXoXUVqHq/mjooC09BUwGZLMB1s1/JVdPQStWYBU+l+t5 n8l+FIq/DGyAsqg+Pxxh+zn7aS3ii4W/6VNV85KNUlytI2UoTmQJg4JaSVxruqdhhtFb xhqQETb52nSmf1kaZ0qEuD48pHiIcraYY8Q71ef6tkmOspiTnh77Ora/VRwkQxHmyoGB rjlp/m/XAFQ3gj7W1nQV+O8WBfUhsovitTTpwiw8zi4RCwjRxfIMPSwDOSeXLZbQWqib uxzg== X-Gm-Message-State: AOJu0Yxn+wZpb4uCRi7BM0yYY5GBiFoExDIApr/WJdZP7OACa54HjB1d rmTyOVgH+MC7otacIJbo1dOiVyv92p5dqJOfRB+ckZjTC766X9z/4HVX04rtM8Db1gzHn0fFZy4 /vjUkNMTADtJCXcmv7eZyINUlznLAuPhQcOk2dCc8aSbj5D1wcsHh3bDYHtU= X-Google-Smtp-Source: AGHT+IEKLF5vmsuVezHkwSQAOLuU0WiLbCFUgbD1/uBaSBfNMrt6OgziOJ2W+tz3aYlzP5Dn1wdJJYshy5ND3VTXPwiKDwwuLFQQ Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Received: by 2002:a05:6e02:152d:b0:430:ab80:66f9 with SMTP id e9e14a558f8ab-430c52081femr317941225ab.1.1761149626994; Wed, 22 Oct 2025 09:13:46 -0700 (PDT) Date: Wed, 22 Oct 2025 09:13:46 -0700 In-Reply-To: <000000000000c7e54f0621e8a14f@google.com> X-Google-Appengine-App-Id: s~syzkaller X-Google-Appengine-App-Id-Alias: syzkaller Message-ID: <68f902ba.050a0220.346f24.005a.GAE@google.com> Subject: Forwarded: #syz test https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 552c50713f273b494ac6c77052032a49bc9255e2 From: syzbot To: linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" For archival purposes, forwarding an incoming command email to linux-kernel@vger.kernel.org, syzkaller-bugs@googlegroups.com. *** Subject: #syz test https://git.kernel.org/pub/scm/linux/kernel/git/torvalds= /linux.git 552c50713f273b494ac6c77052032a49bc9255e2 Author: dmantipov@yandex.ru #syz test https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.gi= t 552c50713f273b494ac6c77052032a49bc9255e2 diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c index 162711cc5b20..ce38505a823c 100644 --- a/fs/ocfs2/alloc.c +++ b/fs/ocfs2/alloc.c @@ -6164,7 +6164,7 @@ static int ocfs2_get_truncate_log_info(struct ocfs2_s= uper *osb, struct buffer_head *bh =3D NULL; struct ocfs2_dinode *di; struct ocfs2_truncate_log *tl; - unsigned int tl_count; + unsigned int tl_count, tl_used; =20 inode =3D ocfs2_get_system_file_inode(osb, TRUNCATE_LOG_SYSTEM_INODE, @@ -6184,9 +6184,10 @@ static int ocfs2_get_truncate_log_info(struct ocfs2_= super *osb, =20 di =3D (struct ocfs2_dinode *)bh->b_data; tl =3D &di->id2.i_dealloc; + tl_used =3D le16_to_cpu(tl->tl_used); tl_count =3D le16_to_cpu(tl->tl_count); if (unlikely(tl_count > ocfs2_truncate_recs_per_inode(osb->sb) || - tl_count =3D=3D 0)) { + tl_count =3D=3D 0 || tl_used > tl_count)) { status =3D -EFSCORRUPTED; iput(inode); brelse(bh); diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c index 8c9c4825f984..2785ff245e79 100644 --- a/fs/ocfs2/dir.c +++ b/fs/ocfs2/dir.c @@ -302,8 +302,21 @@ static int ocfs2_check_dir_entry(struct inode *dir, unsigned long offset) { const char *error_msg =3D NULL; - const int rlen =3D le16_to_cpu(de->rec_len); - const unsigned long next_offset =3D ((char *) de - buf) + rlen; + unsigned long next_offset; + int rlen; + + if (offset > size - OCFS2_DIR_REC_LEN(1)) { + /* Dirent is (maybe partially) beyond the buffer + * boundaries so touching 'de' members is unsafe. + */ + mlog(ML_ERROR, "directory entry (#%llu: offset=3D%lu) " + "too close to end or out-of-bounds", + (unsigned long long)OCFS2_I(dir)->ip_blkno, offset); + return 0; + } + + rlen =3D le16_to_cpu(de->rec_len); + next_offset =3D ((char *) de - buf) + rlen; =20 if (unlikely(rlen < OCFS2_DIR_REC_LEN(1))) error_msg =3D "rec_len is smaller than minimal"; @@ -778,6 +791,14 @@ static int ocfs2_dx_dir_lookup_rec(struct inode *inode, struct ocfs2_extent_block *eb; struct ocfs2_extent_rec *rec =3D NULL; =20 + if (le16_to_cpu(el->l_count) !=3D + ocfs2_extent_recs_per_dx_root(inode->i_sb)) { + ret =3D ocfs2_error(inode->i_sb, + "Inode %lu has invalid extent list length %u\n", + inode->i_ino, le16_to_cpu(el->l_count)); + goto out; + } + if (el->l_tree_depth) { ret =3D ocfs2_find_leaf(INODE_CACHE(inode), el, major_hash, &eb_bh); @@ -3423,6 +3444,14 @@ static int ocfs2_find_dir_space_id(struct inode *dir= , struct buffer_head *di_bh, offset +=3D le16_to_cpu(de->rec_len); } =20 + if (!last_de) { + ret =3D ocfs2_error(sb, "Directory entry (#%llu: size=3D%lld) " + "is unexpectedly short", + (unsigned long long)OCFS2_I(dir)->ip_blkno, + i_size_read(dir)); + goto out; + } + /* * We're going to require expansion of the directory - figure * out how many blocks we'll need so that a place for the @@ -4104,10 +4133,15 @@ static int ocfs2_expand_inline_dx_root(struct inode= *dir, } =20 dx_root->dr_flags &=3D ~OCFS2_DX_FLAG_INLINE; - memset(&dx_root->dr_list, 0, osb->sb->s_blocksize - - offsetof(struct ocfs2_dx_root_block, dr_list)); + + dx_root->dr_list.l_tree_depth =3D 0; dx_root->dr_list.l_count =3D cpu_to_le16(ocfs2_extent_recs_per_dx_root(osb->sb)); + dx_root->dr_list.l_next_free_rec =3D 0; + memset(&dx_root->dr_list.l_recs, 0, + osb->sb->s_blocksize - + (offsetof(struct ocfs2_dx_root_block, dr_list) + + offsetof(struct ocfs2_extent_list, l_recs))); =20 /* This should never fail considering we start with an empty * dx_root. */ diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c index d1aa04a5af1b..56be21c695d6 100644 --- a/fs/ocfs2/localalloc.c +++ b/fs/ocfs2/localalloc.c @@ -905,13 +905,11 @@ static int ocfs2_local_alloc_find_clear_bits(struct o= cfs2_super *osb, static void ocfs2_clear_local_alloc(struct ocfs2_dinode *alloc) { struct ocfs2_local_alloc *la =3D OCFS2_LOCAL_ALLOC(alloc); - int i; =20 alloc->id1.bitmap1.i_total =3D 0; alloc->id1.bitmap1.i_used =3D 0; la->la_bm_off =3D 0; - for(i =3D 0; i < le16_to_cpu(la->la_size); i++) - la->la_bitmap[i] =3D 0; + memset(la->la_bitmap, 0, le16_to_cpu(la->la_size)); } =20 #if 0 diff --git a/fs/ocfs2/move_extents.c b/fs/ocfs2/move_extents.c index 86f2631e6360..ba4952b41602 100644 --- a/fs/ocfs2/move_extents.c +++ b/fs/ocfs2/move_extents.c @@ -98,7 +98,13 @@ static int __ocfs2_move_extent(handle_t *handle, =20 rec =3D &el->l_recs[index]; =20 - BUG_ON(ext_flags !=3D rec->e_flags); + if (ext_flags !=3D rec->e_flags) { + ret =3D ocfs2_error(inode->i_sb, + "Inode %llu has corrupted extent %d with flags 0x%x at cpos %u\n", + (unsigned long long)ino, index, rec->e_flags, cpos); + goto out; + } + /* * after moving/defraging to new location, the extent is not going * to be refcounted anymore. @@ -1031,6 +1037,12 @@ int ocfs2_ioctl_move_extents(struct file *filp, void= __user *argp) if (range.me_threshold > i_size_read(inode)) range.me_threshold =3D i_size_read(inode); =20 + if (range.me_flags & ~(OCFS2_MOVE_EXT_FL_AUTO_DEFRAG | + OCFS2_MOVE_EXT_FL_PART_DEFRAG)) { + status =3D -EINVAL; + goto out_free; + } + if (range.me_flags & OCFS2_MOVE_EXT_FL_AUTO_DEFRAG) { context->auto_defrag =3D 1; =20 diff --git a/fs/ocfs2/ocfs2_fs.h b/fs/ocfs2/ocfs2_fs.h index ae0e44e5f2ad..c501eb3cdcda 100644 --- a/fs/ocfs2/ocfs2_fs.h +++ b/fs/ocfs2/ocfs2_fs.h @@ -468,7 +468,8 @@ struct ocfs2_extent_list { __le16 l_reserved1; __le64 l_reserved2; /* Pad to sizeof(ocfs2_extent_rec) */ -/*10*/ struct ocfs2_extent_rec l_recs[]; /* Extent records */ + /* Extent records */ +/*10*/ struct ocfs2_extent_rec l_recs[] __counted_by_le(l_count); }; =20 /* @@ -482,7 +483,8 @@ struct ocfs2_chain_list { __le16 cl_count; /* Total chains in this list */ __le16 cl_next_free_rec; /* Next unused chain slot */ __le64 cl_reserved1; -/*10*/ struct ocfs2_chain_rec cl_recs[]; /* Chain records */ + /* Chain records */ +/*10*/ struct ocfs2_chain_rec cl_recs[] __counted_by_le(cl_count); }; =20 /* @@ -494,7 +496,8 @@ struct ocfs2_truncate_log { /*00*/ __le16 tl_count; /* Total records in this log */ __le16 tl_used; /* Number of records in use */ __le32 tl_reserved1; -/*08*/ struct ocfs2_truncate_rec tl_recs[]; /* Truncate records */ + /* Truncate records */ +/*08*/ struct ocfs2_truncate_rec tl_recs[] __counted_by_le(tl_count); }; =20 /* @@ -638,7 +641,7 @@ struct ocfs2_local_alloc __le16 la_size; /* Size of included bitmap, in bytes */ __le16 la_reserved1; __le64 la_reserved2; -/*10*/ __u8 la_bitmap[]; +/*10*/ __u8 la_bitmap[] __counted_by_le(la_size); }; =20 /* @@ -651,7 +654,7 @@ struct ocfs2_inline_data * for data, starting at id_data */ __le16 id_reserved0; __le32 id_reserved1; - __u8 id_data[]; /* Start of user data */ + __u8 id_data[] __counted_by_le(id_count); /* Start of user data */ }; =20 /* @@ -796,9 +799,10 @@ struct ocfs2_dx_entry_list { * possible in de_entries */ __le16 de_num_used; /* Current number of * de_entries entries */ - struct ocfs2_dx_entry de_entries[]; /* Indexed dir entries - * in a packed array of - * length de_num_used */ + /* Indexed dir entries in a packed + * array of length de_num_used. + */ + struct ocfs2_dx_entry de_entries[] __counted_by_le(de_count); }; =20 #define OCFS2_DX_FLAG_INLINE 0x01 @@ -934,7 +938,8 @@ struct ocfs2_refcount_list { __le16 rl_used; /* Current number of used records */ __le32 rl_reserved2; __le64 rl_reserved1; /* Pad to sizeof(ocfs2_refcount_record) */ -/*10*/ struct ocfs2_refcount_rec rl_recs[]; /* Refcount records */ + /* Refcount records */ +/*10*/ struct ocfs2_refcount_rec rl_recs[] __counted_by_le(rl_count); }; =20 =20 @@ -1020,7 +1025,8 @@ struct ocfs2_xattr_header { buckets. A block uses xb_check and sets this field to zero.) */ - struct ocfs2_xattr_entry xh_entries[]; /* xattr entry list. */ + /* xattr entry list. */ + struct ocfs2_xattr_entry xh_entries[] __counted_by_le(xh_count); }; =20 /* diff --git a/fs/ocfs2/suballoc.c b/fs/ocfs2/suballoc.c index 6ac4dcd54588..9969a041ab18 100644 --- a/fs/ocfs2/suballoc.c +++ b/fs/ocfs2/suballoc.c @@ -649,6 +649,16 @@ ocfs2_block_group_alloc_discontig(handle_t *handle, return status ? ERR_PTR(status) : bg_bh; } =20 +static int ocfs2_check_chain_list(struct ocfs2_chain_list *cl, + struct super_block *sb) +{ + if (le16_to_cpu(cl->cl_count) !=3D ocfs2_chain_recs_per_inode(sb)) + return -EINVAL; + if (le16_to_cpu(cl->cl_next_free_rec) > le16_to_cpu(cl->cl_count)) + return -EINVAL; + return 0; +} + /* * We expect the block group allocator to already be locked. */ @@ -671,6 +681,10 @@ static int ocfs2_block_group_alloc(struct ocfs2_super = *osb, BUG_ON(ocfs2_is_cluster_bitmap(alloc_inode)); =20 cl =3D &fe->id2.i_chain; + status =3D ocfs2_check_chain_list(cl, alloc_inode->i_sb); + if (status) + goto bail; + status =3D ocfs2_reserve_clusters_with_limit(osb, le16_to_cpu(cl->cl_cpg), max_block, flags, &ac); @@ -1992,6 +2006,9 @@ static int ocfs2_claim_suballoc_bits(struct ocfs2_all= oc_context *ac, } =20 cl =3D (struct ocfs2_chain_list *) &fe->id2.i_chain; + status =3D ocfs2_check_chain_list(cl, ac->ac_inode->i_sb); + if (status) + goto bail; =20 victim =3D ocfs2_find_victim_chain(cl); ac->ac_chain =3D victim;