Commit b80697c1 authored by Jan Kara's avatar Jan Kara

udf: Remove declarations of arrays of size UDF_NAME_LEN (256 bytes)

There are several places in UDF where we declared temporary arrays of
UDF_NAME_LEN bytes on stack. This is not nice to stack usage so this patch
changes those places to use kmalloc() instead. Also clean up bail-out paths
in those functions when we are changing them.
Signed-off-by: default avatarJan Kara <jack@suse.cz>
parent 9bf2c6b8
...@@ -39,13 +39,13 @@ ...@@ -39,13 +39,13 @@
static int do_udf_readdir(struct inode *dir, struct file *filp, static int do_udf_readdir(struct inode *dir, struct file *filp,
filldir_t filldir, void *dirent) filldir_t filldir, void *dirent)
{ {
struct udf_fileident_bh fibh; struct udf_fileident_bh fibh = { .sbh = NULL, .ebh = NULL};
struct fileIdentDesc *fi = NULL; struct fileIdentDesc *fi = NULL;
struct fileIdentDesc cfi; struct fileIdentDesc cfi;
int block, iblock; int block, iblock;
loff_t nf_pos = (filp->f_pos - 1) << 2; loff_t nf_pos = (filp->f_pos - 1) << 2;
int flen; int flen;
char fname[UDF_NAME_LEN]; char *fname = NULL;
char *nameptr; char *nameptr;
uint16_t liu; uint16_t liu;
uint8_t lfi; uint8_t lfi;
...@@ -54,23 +54,32 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, ...@@ -54,23 +54,32 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
kernel_lb_addr eloc; kernel_lb_addr eloc;
uint32_t elen; uint32_t elen;
sector_t offset; sector_t offset;
int i, num; int i, num, ret = 0;
unsigned int dt_type; unsigned int dt_type;
struct extent_position epos = { NULL, 0, {0, 0} }; struct extent_position epos = { NULL, 0, {0, 0} };
struct udf_inode_info *iinfo; struct udf_inode_info *iinfo;
if (nf_pos >= size) if (nf_pos >= size)
return 0; goto out;
fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
if (!fname) {
ret = -ENOMEM;
goto out;
}
if (nf_pos == 0) if (nf_pos == 0)
nf_pos = udf_ext0_offset(dir); nf_pos = udf_ext0_offset(dir);
fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1); fibh.soffset = fibh.eoffset = nf_pos & (dir->i_sb->s_blocksize - 1);
iinfo = UDF_I(dir); iinfo = UDF_I(dir);
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) { if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
fibh.sbh = fibh.ebh = NULL; if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits,
} else if (inode_bmap(dir, nf_pos >> dir->i_sb->s_blocksize_bits, &epos, &eloc, &elen, &offset)
&epos, &eloc, &elen, &offset) == (EXT_RECORDED_ALLOCATED >> 30)) { != (EXT_RECORDED_ALLOCATED >> 30)) {
ret = -ENOENT;
goto out;
}
block = udf_get_lb_pblock(dir->i_sb, eloc, offset); block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
...@@ -83,8 +92,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, ...@@ -83,8 +92,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
} }
if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) { if (!(fibh.sbh = fibh.ebh = udf_tread(dir->i_sb, block))) {
brelse(epos.bh); ret = -EIO;
return -EIO; goto out;
} }
if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9)) - 1))) { if (!(offset & ((16 >> (dir->i_sb->s_blocksize_bits - 9)) - 1))) {
...@@ -105,9 +114,6 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, ...@@ -105,9 +114,6 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
brelse(bha[i]); brelse(bha[i]);
} }
} }
} else {
brelse(epos.bh);
return -ENOENT;
} }
while (nf_pos < size) { while (nf_pos < size) {
...@@ -115,13 +121,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, ...@@ -115,13 +121,8 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc, fi = udf_fileident_read(dir, &nf_pos, &fibh, &cfi, &epos, &eloc,
&elen, &offset); &elen, &offset);
if (!fi) { if (!fi)
if (fibh.sbh != fibh.ebh) goto out;
brelse(fibh.ebh);
brelse(fibh.sbh);
brelse(epos.bh);
return 0;
}
liu = le16_to_cpu(cfi.lengthOfImpUse); liu = le16_to_cpu(cfi.lengthOfImpUse);
lfi = cfi.lengthFileIdent; lfi = cfi.lengthFileIdent;
...@@ -167,25 +168,21 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, ...@@ -167,25 +168,21 @@ static int do_udf_readdir(struct inode *dir, struct file *filp,
dt_type = DT_UNKNOWN; dt_type = DT_UNKNOWN;
} }
if (flen) { if (flen && filldir(dirent, fname, flen, filp->f_pos,
if (filldir(dirent, fname, flen, filp->f_pos, iblock, dt_type) < 0) { iblock, dt_type) < 0)
if (fibh.sbh != fibh.ebh) goto out;
brelse(fibh.ebh);
brelse(fibh.sbh);
brelse(epos.bh);
return 0;
}
}
} /* end while */ } /* end while */
filp->f_pos = (nf_pos >> 2) + 1; filp->f_pos = (nf_pos >> 2) + 1;
out:
if (fibh.sbh != fibh.ebh) if (fibh.sbh != fibh.ebh)
brelse(fibh.ebh); brelse(fibh.ebh);
brelse(fibh.sbh); brelse(fibh.sbh);
brelse(epos.bh); brelse(epos.bh);
kfree(fname);
return 0; return ret;
} }
static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir) static int udf_readdir(struct file *filp, void *dirent, filldir_t filldir)
......
...@@ -149,7 +149,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, ...@@ -149,7 +149,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
struct fileIdentDesc *fi = NULL; struct fileIdentDesc *fi = NULL;
loff_t f_pos; loff_t f_pos;
int block, flen; int block, flen;
char fname[UDF_NAME_LEN]; char *fname = NULL;
char *nameptr; char *nameptr;
uint8_t lfi; uint8_t lfi;
uint16_t liu; uint16_t liu;
...@@ -163,12 +163,12 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, ...@@ -163,12 +163,12 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
size = udf_ext0_offset(dir) + dir->i_size; size = udf_ext0_offset(dir) + dir->i_size;
f_pos = udf_ext0_offset(dir); f_pos = udf_ext0_offset(dir);
fibh->sbh = fibh->ebh = NULL;
fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1); fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
fibh->sbh = fibh->ebh = NULL; if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30))
&epos, &eloc, &elen, &offset) == goto out_err;
(EXT_RECORDED_ALLOCATED >> 30)) {
block = udf_get_lb_pblock(dir->i_sb, eloc, offset); block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
...@@ -179,25 +179,19 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, ...@@ -179,25 +179,19 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
offset = 0; offset = 0;
fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block); fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
if (!fibh->sbh) { if (!fibh->sbh)
brelse(epos.bh); goto out_err;
return NULL;
}
} else {
brelse(epos.bh);
return NULL;
} }
fname = kmalloc(UDF_NAME_LEN, GFP_NOFS);
if (!fname)
goto out_err;
while (f_pos < size) { while (f_pos < size) {
fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc, fi = udf_fileident_read(dir, &f_pos, fibh, cfi, &epos, &eloc,
&elen, &offset); &elen, &offset);
if (!fi) { if (!fi)
if (fibh->sbh != fibh->ebh) goto out_err;
brelse(fibh->ebh);
brelse(fibh->sbh);
brelse(epos.bh);
return NULL;
}
liu = le16_to_cpu(cfi->lengthOfImpUse); liu = le16_to_cpu(cfi->lengthOfImpUse);
lfi = cfi->lengthFileIdent; lfi = cfi->lengthFileIdent;
...@@ -237,18 +231,20 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, ...@@ -237,18 +231,20 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir,
flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi);
if (flen && udf_match(flen, fname, dentry->d_name.len, if (flen && udf_match(flen, fname, dentry->d_name.len,
dentry->d_name.name)) { dentry->d_name.name))
brelse(epos.bh); goto out_ok;
return fi;
}
} }
out_err:
fi = NULL;
if (fibh->sbh != fibh->ebh) if (fibh->sbh != fibh->ebh)
brelse(fibh->ebh); brelse(fibh->ebh);
brelse(fibh->sbh); brelse(fibh->sbh);
out_ok:
brelse(epos.bh); brelse(epos.bh);
kfree(fname);
return NULL; return fi;
} }
static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry,
...@@ -303,7 +299,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, ...@@ -303,7 +299,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
{ {
struct super_block *sb = dir->i_sb; struct super_block *sb = dir->i_sb;
struct fileIdentDesc *fi = NULL; struct fileIdentDesc *fi = NULL;
char name[UDF_NAME_LEN]; char *name = NULL;
int namelen; int namelen;
loff_t f_pos; loff_t f_pos;
loff_t size = udf_ext0_offset(dir) + dir->i_size; loff_t size = udf_ext0_offset(dir) + dir->i_size;
...@@ -317,16 +313,23 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, ...@@ -317,16 +313,23 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
struct extent_position epos = {}; struct extent_position epos = {};
struct udf_inode_info *dinfo; struct udf_inode_info *dinfo;
fibh->sbh = fibh->ebh = NULL;
name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
if (!name) {
*err = -ENOMEM;
goto out_err;
}
if (dentry) { if (dentry) {
if (!dentry->d_name.len) { if (!dentry->d_name.len) {
*err = -EINVAL; *err = -EINVAL;
return NULL; goto out_err;
} }
namelen = udf_put_filename(sb, dentry->d_name.name, name, namelen = udf_put_filename(sb, dentry->d_name.name, name,
dentry->d_name.len); dentry->d_name.len);
if (!namelen) { if (!namelen) {
*err = -ENAMETOOLONG; *err = -ENAMETOOLONG;
return NULL; goto out_err;
} }
} else { } else {
namelen = 0; namelen = 0;
...@@ -338,11 +341,14 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, ...@@ -338,11 +341,14 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1); fibh->soffset = fibh->eoffset = f_pos & (dir->i_sb->s_blocksize - 1);
dinfo = UDF_I(dir); dinfo = UDF_I(dir);
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) {
fibh->sbh = fibh->ebh = NULL; if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos,
else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) {
&epos, &eloc, &elen, &offset) == block = udf_get_lb_pblock(dir->i_sb,
(EXT_RECORDED_ALLOCATED >> 30)) { dinfo->i_location, 0);
fibh->soffset = fibh->eoffset = sb->s_blocksize;
goto add;
}
block = udf_get_lb_pblock(dir->i_sb, eloc, offset); block = udf_get_lb_pblock(dir->i_sb, eloc, offset);
if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { if ((++offset << dir->i_sb->s_blocksize_bits) < elen) {
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT)
...@@ -354,17 +360,11 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, ...@@ -354,17 +360,11 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block); fibh->sbh = fibh->ebh = udf_tread(dir->i_sb, block);
if (!fibh->sbh) { if (!fibh->sbh) {
brelse(epos.bh);
*err = -EIO; *err = -EIO;
return NULL; goto out_err;
} }
block = dinfo->i_location.logicalBlockNum; block = dinfo->i_location.logicalBlockNum;
} else {
block = udf_get_lb_pblock(dir->i_sb, dinfo->i_location, 0);
fibh->sbh = fibh->ebh = NULL;
fibh->soffset = fibh->eoffset = sb->s_blocksize;
goto add;
} }
while (f_pos < size) { while (f_pos < size) {
...@@ -372,12 +372,8 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, ...@@ -372,12 +372,8 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
&elen, &offset); &elen, &offset);
if (!fi) { if (!fi) {
if (fibh->sbh != fibh->ebh)
brelse(fibh->ebh);
brelse(fibh->sbh);
brelse(epos.bh);
*err = -EIO; *err = -EIO;
return NULL; goto out_err;
} }
liu = le16_to_cpu(cfi->lengthOfImpUse); liu = le16_to_cpu(cfi->lengthOfImpUse);
...@@ -386,7 +382,6 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, ...@@ -386,7 +382,6 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) { if ((cfi->fileCharacteristics & FID_FILE_CHAR_DELETED) != 0) {
if (((sizeof(struct fileIdentDesc) + if (((sizeof(struct fileIdentDesc) +
liu + lfi + 3) & ~3) == nfidlen) { liu + lfi + 3) & ~3) == nfidlen) {
brelse(epos.bh);
cfi->descTag.tagSerialNum = cpu_to_le16(1); cfi->descTag.tagSerialNum = cpu_to_le16(1);
cfi->fileVersionNum = cpu_to_le16(1); cfi->fileVersionNum = cpu_to_le16(1);
cfi->fileCharacteristics = 0; cfi->fileCharacteristics = 0;
...@@ -394,10 +389,10 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, ...@@ -394,10 +389,10 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
cfi->lengthOfImpUse = cpu_to_le16(0); cfi->lengthOfImpUse = cpu_to_le16(0);
if (!udf_write_fi(dir, cfi, fi, fibh, NULL, if (!udf_write_fi(dir, cfi, fi, fibh, NULL,
name)) name))
return fi; goto out_ok;
else { else {
*err = -EIO; *err = -EIO;
return NULL; goto out_err;
} }
} }
} }
...@@ -427,7 +422,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, ...@@ -427,7 +422,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
fibh->sbh = fibh->ebh = fibh->sbh = fibh->ebh =
udf_expand_dir_adinicb(dir, &block, err); udf_expand_dir_adinicb(dir, &block, err);
if (!fibh->sbh) if (!fibh->sbh)
return NULL; goto out_err;
epos.block = dinfo->i_location; epos.block = dinfo->i_location;
epos.offset = udf_file_entry_alloc_offset(dir); epos.offset = udf_file_entry_alloc_offset(dir);
/* Load extent udf_expand_dir_adinicb() has created */ /* Load extent udf_expand_dir_adinicb() has created */
...@@ -468,11 +463,8 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, ...@@ -468,11 +463,8 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
dir->i_sb->s_blocksize_bits); dir->i_sb->s_blocksize_bits);
fibh->ebh = udf_bread(dir, fibh->ebh = udf_bread(dir,
f_pos >> dir->i_sb->s_blocksize_bits, 1, err); f_pos >> dir->i_sb->s_blocksize_bits, 1, err);
if (!fibh->ebh) { if (!fibh->ebh)
brelse(epos.bh); goto out_err;
brelse(fibh->sbh);
return NULL;
}
if (!fibh->soffset) { if (!fibh->soffset) {
if (udf_next_aext(dir, &epos, &eloc, &elen, 1) == if (udf_next_aext(dir, &epos, &eloc, &elen, 1) ==
...@@ -503,20 +495,25 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, ...@@ -503,20 +495,25 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir,
cfi->lengthFileIdent = namelen; cfi->lengthFileIdent = namelen;
cfi->lengthOfImpUse = cpu_to_le16(0); cfi->lengthOfImpUse = cpu_to_le16(0);
if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) { if (!udf_write_fi(dir, cfi, fi, fibh, NULL, name)) {
brelse(epos.bh);
dir->i_size += nfidlen; dir->i_size += nfidlen;
if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB) if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_IN_ICB)
dinfo->i_lenAlloc += nfidlen; dinfo->i_lenAlloc += nfidlen;
mark_inode_dirty(dir); mark_inode_dirty(dir);
return fi; goto out_ok;
} else { } else {
brelse(epos.bh);
if (fibh->sbh != fibh->ebh)
brelse(fibh->ebh);
brelse(fibh->sbh);
*err = -EIO; *err = -EIO;
return NULL; goto out_err;
} }
out_err:
fi = NULL;
if (fibh->sbh != fibh->ebh)
brelse(fibh->ebh);
brelse(fibh->sbh);
out_ok:
brelse(epos.bh);
kfree(name);
return fi;
} }
static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi, static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi,
...@@ -871,7 +868,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, ...@@ -871,7 +868,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
char *ea; char *ea;
int err; int err;
int block; int block;
char name[UDF_NAME_LEN]; char *name = NULL;
int namelen; int namelen;
struct buffer_head *bh; struct buffer_head *bh;
struct udf_inode_info *iinfo; struct udf_inode_info *iinfo;
...@@ -881,6 +878,12 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, ...@@ -881,6 +878,12 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
if (!inode) if (!inode)
goto out; goto out;
name = kmalloc(UDF_NAME_LEN, GFP_NOFS);
if (!name) {
err = -ENOMEM;
goto out_no_entry;
}
iinfo = UDF_I(inode); iinfo = UDF_I(inode);
inode->i_mode = S_IFLNK | S_IRWXUGO; inode->i_mode = S_IFLNK | S_IRWXUGO;
inode->i_data.a_ops = &udf_symlink_aops; inode->i_data.a_ops = &udf_symlink_aops;
...@@ -1020,6 +1023,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, ...@@ -1020,6 +1023,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry,
err = 0; err = 0;
out: out:
kfree(name);
unlock_kernel(); unlock_kernel();
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment