]>
Commit | Line | Data |
---|---|---|
4ab73572 | 1 | From security-bounces@linux.kernel.org Tue Mar 15 16:25:33 2005 |
2 | From: Linus Torvalds <torvalds@osdl.org> | |
3 | Subject: [PATCH] isofs: Handle corupted rock-ridge info slightly better | |
4 | ||
5 | Michal Zalewski <lcamtuf@dione.ids.pl> discovers range checking flaws in | |
6 | iso9660 filesystem. | |
7 | ||
8 | http://marc.theaimsgroup.com/?l=bugtraq&m=111110067304783&w=2 | |
9 | ||
10 | CAN-2005-0815 is assigned to this issue. | |
11 | ||
12 | From: Linus Torvalds <torvalds@osdl.org> | |
13 | ||
14 | isofs: Handle corupted rock-ridge info slightly better. | |
15 | ||
16 | Keyword here being 'slightly'. The code is a mess. | |
17 | ||
18 | Signed-off-by: Chris Wright <chrisw@osdl.org> | |
19 | ||
20 | diff -Nru a/fs/isofs/rock.c b/fs/isofs/rock.c | |
21 | --- a/fs/isofs/rock.c 2005-03-25 15:25:50 -08:00 | |
22 | +++ b/fs/isofs/rock.c 2005-03-25 15:25:50 -08:00 | |
23 | @@ -53,6 +53,7 @@ | |
24 | if(LEN & 1) LEN++; \ | |
25 | CHR = ((unsigned char *) DE) + LEN; \ | |
26 | LEN = *((unsigned char *) DE) - LEN; \ | |
27 | + if (LEN<0) LEN=0; \ | |
28 | if (ISOFS_SB(inode->i_sb)->s_rock_offset!=-1) \ | |
29 | { \ | |
30 | LEN-=ISOFS_SB(inode->i_sb)->s_rock_offset; \ | |
31 | @@ -103,12 +104,13 @@ | |
32 | struct rock_ridge * rr; | |
33 | int sig; | |
34 | ||
35 | - while (len > 1){ /* There may be one byte for padding somewhere */ | |
36 | + while (len > 2){ /* There may be one byte for padding somewhere */ | |
37 | rr = (struct rock_ridge *) chr; | |
38 | - if (rr->len == 0) goto out; /* Something got screwed up here */ | |
39 | + if (rr->len < 3) goto out; /* Something got screwed up here */ | |
40 | sig = isonum_721(chr); | |
41 | chr += rr->len; | |
42 | len -= rr->len; | |
43 | + if (len < 0) goto out; /* corrupted isofs */ | |
44 | ||
45 | switch(sig){ | |
46 | case SIG('R','R'): | |
47 | @@ -122,6 +124,7 @@ | |
48 | break; | |
49 | case SIG('N','M'): | |
50 | if (truncate) break; | |
51 | + if (rr->len < 5) break; | |
52 | /* | |
53 | * If the flags are 2 or 4, this indicates '.' or '..'. | |
54 | * We don't want to do anything with this, because it | |
55 | @@ -186,12 +189,13 @@ | |
56 | struct rock_ridge * rr; | |
57 | int rootflag; | |
58 | ||
59 | - while (len > 1){ /* There may be one byte for padding somewhere */ | |
60 | + while (len > 2){ /* There may be one byte for padding somewhere */ | |
61 | rr = (struct rock_ridge *) chr; | |
62 | - if (rr->len == 0) goto out; /* Something got screwed up here */ | |
63 | + if (rr->len < 3) goto out; /* Something got screwed up here */ | |
64 | sig = isonum_721(chr); | |
65 | chr += rr->len; | |
66 | len -= rr->len; | |
67 | + if (len < 0) goto out; /* corrupted isofs */ | |
68 | ||
69 | switch(sig){ | |
70 | #ifndef CONFIG_ZISOFS /* No flag for SF or ZF */ | |
71 | @@ -462,7 +466,7 @@ | |
72 | struct rock_ridge *rr; | |
73 | ||
74 | if (!ISOFS_SB(inode->i_sb)->s_rock) | |
75 | - panic ("Cannot have symlink with high sierra variant of iso filesystem\n"); | |
76 | + goto error; | |
77 | ||
78 | block = ei->i_iget5_block; | |
79 | lock_kernel(); | |
80 | @@ -487,13 +491,15 @@ | |
81 | SETUP_ROCK_RIDGE(raw_inode, chr, len); | |
82 | ||
83 | repeat: | |
84 | - while (len > 1) { /* There may be one byte for padding somewhere */ | |
85 | + while (len > 2) { /* There may be one byte for padding somewhere */ | |
86 | rr = (struct rock_ridge *) chr; | |
87 | - if (rr->len == 0) | |
88 | + if (rr->len < 3) | |
89 | goto out; /* Something got screwed up here */ | |
90 | sig = isonum_721(chr); | |
91 | chr += rr->len; | |
92 | len -= rr->len; | |
93 | + if (len < 0) | |
94 | + goto out; /* corrupted isofs */ | |
95 | ||
96 | switch (sig) { | |
97 | case SIG('R', 'R'): | |
98 | @@ -543,6 +549,7 @@ | |
99 | fail: | |
100 | brelse(bh); | |
101 | unlock_kernel(); | |
102 | + error: | |
103 | SetPageError(page); | |
104 | kunmap(page); | |
105 | unlock_page(page); |