diff options
author | Steve French <stevef@steveft21.ltcsamba> | 2004-07-06 21:27:18 -0500 |
---|---|---|
committer | Steve French <stevef@steveft21.ltcsamba> | 2004-07-06 21:27:18 -0500 |
commit | 8540342d7331064ac1da8d967ecaa59e896db026 (patch) | |
tree | 036167e1d00a74cc4564cac0b48311ae6312023e /fs | |
parent | afb7238dafb663a283e30ee623713205cc08ebe2 (diff) | |
download | history-8540342d7331064ac1da8d967ecaa59e896db026.tar.gz |
fix oops in build_wildcard_path_from_dentry
Diffstat (limited to 'fs')
-rw-r--r-- | fs/cifs/CHANGES | 3 | ||||
-rw-r--r-- | fs/cifs/dir.c | 51 | ||||
-rw-r--r-- | fs/cifs/file.c | 7 |
3 files changed, 50 insertions, 11 deletions
diff --git a/fs/cifs/CHANGES b/fs/cifs/CHANGES index dbaeb10f04f25c..146651efd1d1ba 100644 --- a/fs/cifs/CHANGES +++ b/fs/cifs/CHANGES @@ -1,7 +1,8 @@ Version 1.20 ------------ Make transaction counts more consistent. Merge /proc/fs/cifs/SimultaneousOps -info into /proc/fs/cifs/DebugData +info into /proc/fs/cifs/DebugData. Fix oops in rare oops in readdir +(in build_wildcard_path_from_dentry). Version 1.19 ------------ diff --git a/fs/cifs/dir.c b/fs/cifs/dir.c index 13e6ff9216522a..95d68da2aaff28 100644 --- a/fs/cifs/dir.c +++ b/fs/cifs/dir.c @@ -101,6 +101,7 @@ cifs_bp_rename_retry: return full_path; } +/* Note: caller must free return buffer */ char * build_wildcard_path_from_dentry(struct dentry *direntry) { @@ -108,18 +109,28 @@ build_wildcard_path_from_dentry(struct dentry *direntry) int namelen = 0; char *full_path; + if(direntry == NULL) + return NULL; /* not much we can do if dentry is freed and + we need to reopen the file after it was closed implicitly + when the server crashed */ + +cifs_bwp_rename_retry: for (temp = direntry; !IS_ROOT(temp);) { namelen += (1 + temp->d_name.len); temp = temp->d_parent; + if(temp == NULL) { + cERROR(1,("corrupt dentry")); + return NULL; + } } - namelen += 3; /* allow for trailing null and wildcard (slash and *) */ - full_path = kmalloc(namelen, GFP_KERNEL); - namelen--; - full_path[namelen] = 0; /* trailing null */ - namelen--; - full_path[namelen] = '*'; - namelen--; + + full_path = kmalloc(namelen+3, GFP_KERNEL); + if(full_path == NULL) + return full_path; + full_path[namelen] = '\\'; + full_path[namelen+1] = '*'; + full_path[namelen+2] = 0; /* trailing null */ for (temp = direntry; !IS_ROOT(temp);) { namelen -= 1 + temp->d_name.len; @@ -129,13 +140,26 @@ build_wildcard_path_from_dentry(struct dentry *direntry) full_path[namelen] = '\\'; strncpy(full_path + namelen + 1, temp->d_name.name, temp->d_name.len); + cFYI(0, (" name: %s ", full_path + namelen)); } temp = temp->d_parent; + if(temp == NULL) { + cERROR(1,("corrupt dentry")); + kfree(full_path); + return NULL; + } } - if (namelen != 0) + if (namelen != 0) { cERROR(1, ("We did not end path lookup where we expected namelen is %d", namelen)); + /* presumably this is only possible if we were racing with a rename + of one of the parent directories (we can not lock the dentries + above us to prevent this, but retrying should be harmless) */ + kfree(full_path); + namelen = 0; + goto cifs_bwp_rename_retry; + } return full_path; } @@ -431,9 +455,16 @@ cifs_dir_open(struct inode *inode, struct file *file) cifs_sb = CIFS_SB(inode->i_sb); pTcon = cifs_sb->tcon; - full_path = build_wildcard_path_from_dentry(file->f_dentry); + if(file->f_dentry) { + down(&file->f_dentry->d_sb->s_vfs_rename_sem); + full_path = build_wildcard_path_from_dentry(file->f_dentry); + up(&file->f_dentry->d_sb->s_vfs_rename_sem); + } else { + FreeXid(xid); + return -EIO; + } - cFYI(1, (" inode = 0x%p and full path is %s", inode, full_path)); + cFYI(1, ("inode = 0x%p and full path is %s", inode, full_path)); if (full_path) kfree(full_path); diff --git a/fs/cifs/file.c b/fs/cifs/file.c index a27ee87d93c97c..375b1cc6e923a0 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c @@ -1682,7 +1682,14 @@ cifs_readdir(struct file *file, void *direntry, filldir_t filldir) data = kmalloc(bufsize, GFP_KERNEL); pfindData = (FILE_DIRECTORY_INFO *) data; + if(file->f_dentry == NULL) { + FreeXid(xid); + return -EIO; + } + down(&file->f_dentry->d_sb->s_vfs_rename_sem); full_path = build_wildcard_path_from_dentry(file->f_dentry); + up(&file->f_dentry->d_sb->s_vfs_rename_sem); + cFYI(1, ("Full path: %s start at: %lld ", full_path, file->f_pos)); |