diff options
author | Andrew Morton <akpm@osdl.org> | 2005-06-21 20:16:51 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2005-06-21 22:07:38 -0400 |
commit | f2966632a134e865db3c819346a1dc7d96e05309 (patch) | |
tree | 7285849b32f99b40de71e647366f1703a612e2c2 /fs/isofs | |
parent | 642217c17b9a56c7e4cf48f6a13dfd5e4a4c2e10 (diff) |
[PATCH] rock: handle directory overflows
Handle the case where the variable-sized part of a rock-ridge directory entry
overhangs the end of the buffer which we allocated for it.
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'fs/isofs')
-rw-r--r-- | fs/isofs/rock.c | 76 |
1 files changed, 74 insertions, 2 deletions
diff --git a/fs/isofs/rock.c b/fs/isofs/rock.c index 9a81830abff8..4326cb47f8fa 100644 --- a/fs/isofs/rock.c +++ b/fs/isofs/rock.c | |||
@@ -127,6 +127,66 @@ out: | |||
127 | } | 127 | } |
128 | 128 | ||
129 | /* | 129 | /* |
130 | * We think there's a record of type `sig' at rs->chr. Parse the signature | ||
131 | * and make sure that there's really room for a record of that type. | ||
132 | */ | ||
133 | static int rock_check_overflow(struct rock_state *rs, int sig) | ||
134 | { | ||
135 | int len; | ||
136 | |||
137 | switch (sig) { | ||
138 | case SIG('S', 'P'): | ||
139 | len = sizeof(struct SU_SP_s); | ||
140 | break; | ||
141 | case SIG('C', 'E'): | ||
142 | len = sizeof(struct SU_CE_s); | ||
143 | break; | ||
144 | case SIG('E', 'R'): | ||
145 | len = sizeof(struct SU_ER_s); | ||
146 | break; | ||
147 | case SIG('R', 'R'): | ||
148 | len = sizeof(struct RR_RR_s); | ||
149 | break; | ||
150 | case SIG('P', 'X'): | ||
151 | len = sizeof(struct RR_PX_s); | ||
152 | break; | ||
153 | case SIG('P', 'N'): | ||
154 | len = sizeof(struct RR_PN_s); | ||
155 | break; | ||
156 | case SIG('S', 'L'): | ||
157 | len = sizeof(struct RR_SL_s); | ||
158 | break; | ||
159 | case SIG('N', 'M'): | ||
160 | len = sizeof(struct RR_NM_s); | ||
161 | break; | ||
162 | case SIG('C', 'L'): | ||
163 | len = sizeof(struct RR_CL_s); | ||
164 | break; | ||
165 | case SIG('P', 'L'): | ||
166 | len = sizeof(struct RR_PL_s); | ||
167 | break; | ||
168 | case SIG('T', 'F'): | ||
169 | len = sizeof(struct RR_TF_s); | ||
170 | break; | ||
171 | case SIG('Z', 'F'): | ||
172 | len = sizeof(struct RR_ZF_s); | ||
173 | break; | ||
174 | default: | ||
175 | len = 0; | ||
176 | break; | ||
177 | } | ||
178 | len += offsetof(struct rock_ridge, u); | ||
179 | if (len > rs->len) { | ||
180 | printk(KERN_NOTICE "rock: directory entry would overflow " | ||
181 | "storage\n"); | ||
182 | printk(KERN_NOTICE "rock: sig=0x%02x, size=%d, remaining=%d\n", | ||
183 | sig, len, rs->len); | ||
184 | return -EIO; | ||
185 | } | ||
186 | return 0; | ||
187 | } | ||
188 | |||
189 | /* | ||
130 | * return length of name field; 0: not found, -1: to be ignored | 190 | * return length of name field; 0: not found, -1: to be ignored |
131 | */ | 191 | */ |
132 | int get_rock_ridge_filename(struct iso_directory_record *de, | 192 | int get_rock_ridge_filename(struct iso_directory_record *de, |
@@ -152,10 +212,12 @@ repeat: | |||
152 | if (rr->len < 3) | 212 | if (rr->len < 3) |
153 | goto out; /* Something got screwed up here */ | 213 | goto out; /* Something got screwed up here */ |
154 | sig = isonum_721(rs.chr); | 214 | sig = isonum_721(rs.chr); |
215 | if (rock_check_overflow(&rs, sig)) | ||
216 | goto eio; | ||
155 | rs.chr += rr->len; | 217 | rs.chr += rr->len; |
156 | rs.len -= rr->len; | 218 | rs.len -= rr->len; |
157 | if (rs.len < 0) | 219 | if (rs.len < 0) |
158 | goto out; /* corrupted isofs */ | 220 | goto eio; /* corrupted isofs */ |
159 | 221 | ||
160 | switch (sig) { | 222 | switch (sig) { |
161 | case SIG('R', 'R'): | 223 | case SIG('R', 'R'): |
@@ -213,6 +275,9 @@ repeat: | |||
213 | out: | 275 | out: |
214 | kfree(rs.buffer); | 276 | kfree(rs.buffer); |
215 | return ret; | 277 | return ret; |
278 | eio: | ||
279 | ret = -EIO; | ||
280 | goto out; | ||
216 | } | 281 | } |
217 | 282 | ||
218 | static int | 283 | static int |
@@ -245,10 +310,12 @@ repeat: | |||
245 | if (rr->len < 3) | 310 | if (rr->len < 3) |
246 | goto out; /* Something got screwed up here */ | 311 | goto out; /* Something got screwed up here */ |
247 | sig = isonum_721(rs.chr); | 312 | sig = isonum_721(rs.chr); |
313 | if (rock_check_overflow(&rs, sig)) | ||
314 | goto eio; | ||
248 | rs.chr += rr->len; | 315 | rs.chr += rr->len; |
249 | rs.len -= rr->len; | 316 | rs.len -= rr->len; |
250 | if (rs.len < 0) | 317 | if (rs.len < 0) |
251 | goto out; /* corrupted isofs */ | 318 | goto eio; /* corrupted isofs */ |
252 | 319 | ||
253 | switch (sig) { | 320 | switch (sig) { |
254 | #ifndef CONFIG_ZISOFS /* No flag for SF or ZF */ | 321 | #ifndef CONFIG_ZISOFS /* No flag for SF or ZF */ |
@@ -479,6 +546,9 @@ repeat: | |||
479 | out: | 546 | out: |
480 | kfree(rs.buffer); | 547 | kfree(rs.buffer); |
481 | return ret; | 548 | return ret; |
549 | eio: | ||
550 | ret = -EIO; | ||
551 | goto out; | ||
482 | } | 552 | } |
483 | 553 | ||
484 | static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit) | 554 | static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit) |
@@ -618,6 +688,8 @@ repeat: | |||
618 | if (rr->len < 3) | 688 | if (rr->len < 3) |
619 | goto out; /* Something got screwed up here */ | 689 | goto out; /* Something got screwed up here */ |
620 | sig = isonum_721(rs.chr); | 690 | sig = isonum_721(rs.chr); |
691 | if (rock_check_overflow(&rs, sig)) | ||
692 | goto out; | ||
621 | rs.chr += rr->len; | 693 | rs.chr += rr->len; |
622 | rs.len -= rr->len; | 694 | rs.len -= rr->len; |
623 | if (rs.len < 0) | 695 | if (rs.len < 0) |