if(LEN & 1) LEN++; \
CHR = ((unsigned char *) DE) + LEN; \
LEN = *((unsigned char *) DE) - LEN; \
+ if (LEN<0) LEN=0; \
if (ISOFS_SB(inode->i_sb)->s_rock_offset!=-1) \
{ \
LEN-=ISOFS_SB(inode->i_sb)->s_rock_offset; \
}
#define MAYBE_CONTINUE(LABEL,DEV) \
- {if (buffer) kfree(buffer); \
+ {if (buffer) { kfree(buffer); buffer = NULL; } \
if (cont_extent){ \
int block, offset, offset1; \
struct buffer_head * pbh; \
offset1 = 0; \
pbh = sb_bread(DEV->i_sb, block); \
if(pbh){ \
+ if (offset > pbh->b_size || offset + cont_size > pbh->b_size){ \
+ brelse(pbh); \
+ goto out; \
+ } \
memcpy(buffer + offset1, pbh->b_data + offset, cont_size - offset1); \
brelse(pbh); \
chr = (unsigned char *) buffer; \
struct rock_ridge * rr;
int sig;
- while (len > 1){ /* There may be one byte for padding somewhere */
+ while (len > 2){ /* There may be one byte for padding somewhere */
rr = (struct rock_ridge *) chr;
- if (rr->len == 0) goto out; /* Something got screwed up here */
+ if (rr->len < 3) goto out; /* Something got screwed up here */
sig = isonum_721(chr);
chr += rr->len;
len -= rr->len;
+ if (len < 0) goto out; /* corrupted isofs */
switch(sig){
case SIG('R','R'):
break;
case SIG('N','M'):
if (truncate) break;
+ if (rr->len < 5) break;
/*
* If the flags are 2 or 4, this indicates '.' or '..'.
* We don't want to do anything with this, because it
}
}
MAYBE_CONTINUE(repeat,inode);
+ if (buffer) kfree(buffer);
return retnamlen; /* If 0, this file did not have a NM field */
out:
if(buffer) kfree(buffer);
return 0;
}
-int parse_rock_ridge_inode_internal(struct iso_directory_record * de,
- struct inode * inode,int regard_xa){
+static int
+parse_rock_ridge_inode_internal(struct iso_directory_record *de,
+ struct inode *inode, int regard_xa)
+{
int len;
unsigned char * chr;
int symlink_len = 0;
chr+=14;
len-=14;
if (len<0) len=0;
- };
+ }
repeat:
{
struct rock_ridge * rr;
int rootflag;
- while (len > 1){ /* There may be one byte for padding somewhere */
+ while (len > 2){ /* There may be one byte for padding somewhere */
rr = (struct rock_ridge *) chr;
- if (rr->len == 0) goto out; /* Something got screwed up here */
+ if (rr->len < 3) goto out; /* Something got screwed up here */
sig = isonum_721(chr);
chr += rr->len;
len -= rr->len;
+ if (len < 0) goto out; /* corrupted isofs */
switch(sig){
#ifndef CONFIG_ZISOFS /* No flag for SF or ZF */
}
}
MAYBE_CONTINUE(repeat,inode);
- return 0;
out:
if(buffer) kfree(buffer);
return 0;
&&(ISOFS_SB(inode->i_sb)->s_rock==2))
{
result=parse_rock_ridge_inode_internal(de,inode,14);
- };
+ }
return result;
-};
+}
/* readpage() for symlinks: reads symlink contents into the page and either
makes it uptodate and returns 0 or returns error (-EIO) */
struct rock_ridge *rr;
if (!ISOFS_SB(inode->i_sb)->s_rock)
- panic ("Cannot have symlink with high sierra variant of iso filesystem\n");
+ goto error;
block = ei->i_iget5_block;
lock_kernel();
SETUP_ROCK_RIDGE(raw_inode, chr, len);
repeat:
- while (len > 1) { /* There may be one byte for padding somewhere */
+ while (len > 2) { /* There may be one byte for padding somewhere */
rr = (struct rock_ridge *) chr;
- if (rr->len == 0)
+ if (rr->len < 3)
goto out; /* Something got screwed up here */
sig = isonum_721(chr);
chr += rr->len;
len -= rr->len;
+ if (len < 0)
+ goto out; /* corrupted isofs */
switch (sig) {
case SIG('R', 'R'):
}
}
MAYBE_CONTINUE(repeat, inode);
+ if (buffer)
+ kfree(buffer);
if (rpnt == link)
goto fail;
fail:
brelse(bh);
unlock_kernel();
+ error:
SetPageError(page);
kunmap(page);
unlock_page(page);