diff options
author | Jan Kara <jack@suse.cz> | 2014-08-17 11:49:57 +0200 |
---|---|---|
committer | Jan Kara <jack@suse.cz> | 2014-08-19 18:29:30 +0200 |
commit | 410dd3cf4c9b36f27ed4542ee18b1af5e68645a4 (patch) | |
tree | be3af2da6fcc9bd0ef2518e6d344d726670b2df7 /fs/isofs/isofs.h | |
parent | 85cd083b498572fb9fa575cce3ed910c8ee84294 (diff) | |
download | linux-410dd3cf4c9b36f27ed4542ee18b1af5e68645a4.tar.gz linux-410dd3cf4c9b36f27ed4542ee18b1af5e68645a4.tar.bz2 linux-410dd3cf4c9b36f27ed4542ee18b1af5e68645a4.zip |
isofs: Fix unbounded recursion when processing relocated directories
We did not check relocated directory in any way when processing Rock
Ridge 'CL' tag. Thus a corrupted isofs image can possibly have a CL
entry pointing to another CL entry leading to possibly unbounded
recursion in kernel code and thus stack overflow or deadlocks (if there
is a loop created from CL entries).
Fix the problem by not allowing CL entry to point to a directory entry
with CL entry (such use makes no good sense anyway) and by checking
whether CL entry doesn't point to itself.
CC: stable@vger.kernel.org
Reported-by: Chris Evans <cevans@google.com>
Signed-off-by: Jan Kara <jack@suse.cz>
Diffstat (limited to 'fs/isofs/isofs.h')
-rw-r--r-- | fs/isofs/isofs.h | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h index 99167238518d..0ac4c1f73fbd 100644 --- a/fs/isofs/isofs.h +++ b/fs/isofs/isofs.h @@ -107,7 +107,7 @@ extern int iso_date(char *, int); struct inode; /* To make gcc happy */ -extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *); +extern int parse_rock_ridge_inode(struct iso_directory_record *, struct inode *, int relocated); extern int get_rock_ridge_filename(struct iso_directory_record *, char *, struct inode *); extern int isofs_name_translate(struct iso_directory_record *, char *, struct inode *); @@ -118,9 +118,24 @@ extern struct dentry *isofs_lookup(struct inode *, struct dentry *, unsigned int extern struct buffer_head *isofs_bread(struct inode *, sector_t); extern int isofs_get_blocks(struct inode *, sector_t, struct buffer_head **, unsigned long); -extern struct inode *isofs_iget(struct super_block *sb, - unsigned long block, - unsigned long offset); +struct inode *__isofs_iget(struct super_block *sb, + unsigned long block, + unsigned long offset, + int relocated); + +static inline struct inode *isofs_iget(struct super_block *sb, + unsigned long block, + unsigned long offset) +{ + return __isofs_iget(sb, block, offset, 0); +} + +static inline struct inode *isofs_iget_reloc(struct super_block *sb, + unsigned long block, + unsigned long offset) +{ + return __isofs_iget(sb, block, offset, 1); +} /* Because the inode number is no longer relevant to finding the * underlying meta-data for an inode, we are free to choose a more |