From: eadaivs <eadaivs@xxxxxxxx> Syzbot reports a slab out of bounds read in ntfs_get_ea, According to splat, the final problem is in the function find_ea, 1) If parameter "bytes" less than the structure EA_ FULL Pointer Object Size, then the unpacked_ea_size() is an out of bounds read. 2) The *off + unpacked_ea_size() can have an integer overflow. Change the type of the parameter bytes to size_t, add sanity check for ensuring that the parameter bytes within reason. And instead of calculating the offset, use the function size add. Link: https://syzkaller.appspot.com/bug?extid=c4d950787fd5553287b7 Reported-and-tested-by: syzbot+c4d950787fd5553287b7@xxxxxxxxxxxxxxxxxxxxxxxxx Fixes: (be71b5cba2e6) fs/ntfs3: Add attrib operations Signed-off-by: eadaivs <eadaivs@xxxxxxxx> --- Changes in v5: Refactor the code and pass syzbot test. fs/ntfs3/xattr.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/fs/ntfs3/xattr.c b/fs/ntfs3/xattr.c index afd0ddad826f..188a76c28233 100644 --- a/fs/ntfs3/xattr.c +++ b/fs/ntfs3/xattr.c @@ -41,17 +41,23 @@ static inline size_t packed_ea_size(const struct EA_FULL *ea) * * Assume there is at least one xattr in the list. */ -static inline bool find_ea(const struct EA_FULL *ea_all, u32 bytes, +static inline bool find_ea(const struct EA_FULL *ea_all, size_t bytes, const char *name, u8 name_len, u32 *off) { + const struct EA_FULL *eb; + u32 next_off; *off = 0; - if (!ea_all || !bytes) + if (!ea_all || bytes < sizeof(*eb)) return false; for (;;) { const struct EA_FULL *ea = Add2Ptr(ea_all, *off); - u32 next_off = *off + unpacked_ea_size(ea); + + if (sizeof(*ea) + *off > bytes) + return false; + + next_off = size_add(*off, unpacked_ea_size(ea)); if (next_off > bytes) return false; @@ -61,8 +67,6 @@ static inline bool find_ea(const struct EA_FULL *ea_all, u32 bytes, return true; *off = next_off; - if (next_off >= bytes) - return false; } } -- 2.37.2