On 10/18/18 3:46 PM, jeffm@xxxxxxxx wrote: > From: Jeff Mahoney <jeffm@xxxxxxxx> > > If a directory entry has been corrupted such that the flags reflect > a different visibility state than expected, we will panic the node. > > This patch instead returns -EIO and sets the file system read-only. > > Signed-off-by: Jeff Mahoney <jeffm@xxxxxxxx> > --- > fs/reiserfs/namei.c | 108 ++++++++++++++++++++++++++++++++-------------------- > 1 file changed, 67 insertions(+), 41 deletions(-) > > diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c > index 5be509a9204f..01e788f91a1d 100644 > --- a/fs/reiserfs/namei.c > +++ b/fs/reiserfs/namei.c > @@ -1254,7 +1254,7 @@ static int reiserfs_link(struct dentry *old_dentry, struct inode *dir, > > /* de contains information pointing to an entry which */ > static int de_still_valid(const char *name, int len, > - struct reiserfs_dir_entry *de) > + const struct reiserfs_dir_entry *de) > { > struct reiserfs_dir_entry tmp = *de; > > @@ -1266,23 +1266,31 @@ static int de_still_valid(const char *name, int len, > return 1; > } > > -static int entry_points_to_object(const char *name, int len, > - struct reiserfs_dir_entry *de, > - struct inode *inode) > +static int entry_points_to_object(const struct inode *dir, > + const char *name, int len, > + const struct reiserfs_dir_entry *de, > + const struct inode *inode) > { > if (!de_still_valid(name, len, de)) > return 0; > > if (inode) { > - if (!de_visible(de->de_deh + de->de_entry_num)) > - reiserfs_panic(inode->i_sb, "vs-7042", > - "entry must be visible"); > + if (!de_visible(de->de_deh + de->de_entry_num)) { > + reiserfs_error(dir->i_sb, "vs-7042", > + "entry must be visible (%.*s in dir %k", > + len, name, INODE_PKEY(dir)); > + return -EIO; > + } > return (de->de_objectid == inode->i_ino) ? 1 : 0; > } > > /* this must be added hidden entry */ > - if (de_visible(de->de_deh + de->de_entry_num)) > - reiserfs_panic(NULL, "vs-7043", "entry must be invisible"); > + if (de_visible(de->de_deh + de->de_entry_num)) { > + reiserfs_error(dir->i_sb, "vs-7043", > + "entry must be invisible (%.*s in dir %k", > + len, name, INODE_PKEY(dir)); > + return -EIO; > + } > > return 1; > } > @@ -1541,47 +1549,65 @@ static int reiserfs_rename(struct inode *old_dir, struct dentry *old_dentry, > * of the above checks could have scheduled. We have to be > * sure our items haven't been shifted by another process. > */ > - if (item_moved(&new_entry_ih, &new_entry_path) || > - !entry_points_to_object(new_dentry->d_name.name, > - new_dentry->d_name.len, > - &new_de, new_dentry_inode) || > - item_moved(&old_entry_ih, &old_entry_path) || > - !entry_points_to_object(old_dentry->d_name.name, > - old_dentry->d_name.len, > - &old_de, old_inode)) { > - reiserfs_restore_prepared_buffer(old_inode->i_sb, > - new_de.de_bh); > - reiserfs_restore_prepared_buffer(old_inode->i_sb, > - old_de.de_bh); > - if (S_ISDIR(old_inode_mode)) > - reiserfs_restore_prepared_buffer(old_inode-> > - i_sb, > - dot_dot_de. > - de_bh); > - continue; > + if (item_moved(&new_entry_ih, &new_entry_path)) { > + retval = 0; > + goto restore; > } > + > + retval = entry_points_to_object(new_dir, > + new_dentry->d_name.name, > + new_dentry->d_name.len, > + &new_de, new_dentry_inode); > + if (retval != 1) > + goto restore; > + > + if (item_moved(&old_entry_ih, &old_entry_path)) { > + retval = 0; > + goto restore; > + } > + > + retval = entry_points_to_object(old_dir, > + old_dentry->d_name.name, > + old_dentry->d_name.len, > + &old_de, old_inode); > + if (retval != 1) > + goto restore; > + > if (S_ISDIR(old_inode_mode)) { > - if (item_moved(&dot_dot_ih, &dot_dot_entry_path) || > - !entry_points_to_object("..", 2, &dot_dot_de, > - old_dir)) { > - reiserfs_restore_prepared_buffer(old_inode-> > - i_sb, > - old_de.de_bh); > - reiserfs_restore_prepared_buffer(old_inode-> > - i_sb, > - new_de.de_bh); > - reiserfs_restore_prepared_buffer(old_inode-> > - i_sb, > - dot_dot_de. > - de_bh); > - continue; > + if (item_moved(&dot_dot_ih, &dot_dot_entry_path)) { > + retval = 0; > + goto restore; > } > + > + retval = entry_points_to_object(old_dir, "..", 2, > + &dot_dot_de, old_dir); > + if (retval != 1) > + goto restore; > } > > + retval = 0; > + > RFALSE(S_ISDIR(old_inode_mode) && > !buffer_journal_prepared(dot_dot_de.de_bh), ""); > > break; > + > +restore: > + reiserfs_restore_prepared_buffer(old_inode->i_sb, > + new_de.de_bh); > + reiserfs_restore_prepared_buffer(old_inode->i_sb, > + old_de.de_bh); > + if (S_ISDIR(old_inode_mode)) > + reiserfs_restore_prepared_buffer(old_inode->i_sb, > + dot_dot_de.de_bh); > + if (retval) { > + pathrelse(&dot_dot_entry_path); > + pathrelse(&new_entry_path); > + pathrelse(&old_entry_path); > + journal_end(&th, old_dir->i_sb, jbegin_count); Well that's not gonna work... -Jeff > + reiserfs_write_unlock(old_dir->i_sb); > + return retval; > + } > } > > /* > -- Jeff Mahoney SUSE Labs
Attachment:
signature.asc
Description: OpenPGP digital signature