aboutsummaryrefslogtreecommitdiffstats
path: root/fs/isofs
diff options
context:
space:
mode:
authorAndrew Morton <akpm@osdl.org>2005-06-21 20:16:51 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-21 22:07:38 -0400
commitf2966632a134e865db3c819346a1dc7d96e05309 (patch)
tree7285849b32f99b40de71e647366f1703a612e2c2 /fs/isofs
parent642217c17b9a56c7e4cf48f6a13dfd5e4a4c2e10 (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.c76
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 */
133static 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 */
132int get_rock_ridge_filename(struct iso_directory_record *de, 192int 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:
213out: 275out:
214 kfree(rs.buffer); 276 kfree(rs.buffer);
215 return ret; 277 return ret;
278eio:
279 ret = -EIO;
280 goto out;
216} 281}
217 282
218static int 283static 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:
479out: 546out:
480 kfree(rs.buffer); 547 kfree(rs.buffer);
481 return ret; 548 return ret;
549eio:
550 ret = -EIO;
551 goto out;
482} 552}
483 553
484static char *get_symlink_chunk(char *rpnt, struct rock_ridge *rr, char *plimit) 554static 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)