Skip to content

Commit aa3d4e0

Browse files
Russell KingAl Viro
authored andcommitted
fs/adfs: bigdir: directory validation strengthening
Strengthen the directory validation by ensuring that the header fields contain sensible values that fit inside the directory, and limit the directory size to 4MB as per RISC OS requirements. Signed-off-by: Russell King <[email protected]> Signed-off-by: Al Viro <[email protected]>
1 parent 6674eca commit aa3d4e0

File tree

1 file changed

+28
-1
lines changed

1 file changed

+28
-1
lines changed

fs/adfs/dir_fplus.c

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,38 @@ static unsigned int adfs_fplus_offset(const struct adfs_bigdirheader *h,
1919
static int adfs_fplus_validate_header(const struct adfs_bigdirheader *h)
2020
{
2121
unsigned int size = le32_to_cpu(h->bigdirsize);
22+
unsigned int len;
2223

2324
if (h->bigdirversion[0] != 0 || h->bigdirversion[1] != 0 ||
2425
h->bigdirversion[2] != 0 ||
2526
h->bigdirstartname != cpu_to_le32(BIGDIRSTARTNAME) ||
26-
size & 2047)
27+
!size || size & 2047 || size > SZ_4M)
28+
return -EIO;
29+
30+
size -= sizeof(struct adfs_bigdirtail) +
31+
offsetof(struct adfs_bigdirheader, bigdirname);
32+
33+
/* Check that bigdirnamelen fits within the directory */
34+
len = ALIGN(le32_to_cpu(h->bigdirnamelen), 4);
35+
if (len > size)
36+
return -EIO;
37+
38+
size -= len;
39+
40+
/* Check that bigdirnamesize fits within the directory */
41+
len = le32_to_cpu(h->bigdirnamesize);
42+
if (len > size)
43+
return -EIO;
44+
45+
size -= len;
46+
47+
/*
48+
* Avoid division, we know that absolute maximum number of entries
49+
* can not be so large to cause overflow of the multiplication below.
50+
*/
51+
len = le32_to_cpu(h->bigdirentries);
52+
if (len > SZ_4M / sizeof(struct adfs_bigdirentry) ||
53+
len * sizeof(struct adfs_bigdirentry) > size)
2754
return -EIO;
2855

2956
return 0;

0 commit comments

Comments
 (0)