sys_chdir and sys_fchdir changes. Signed-off-by: Jaroslav Sykora <jaroslav.sykora@xxxxxxxxx> fs/open.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 73 insertions(+), 6 deletions(-) --- orig/fs/open.c 2007-10-07 19:00:19.000000000 +0200 +++ new/fs/open.c 2007-10-16 21:04:56.000000000 +0200 @@ -476,13 +476,51 @@ asmlinkage long sys_access(const char __ return sys_faccessat(AT_FDCWD, filename, mode); } +static inline int read_fs_flags(void) +{ + int res; + read_lock(¤t->fs->lock); + res = current->fs->flags; + read_unlock(¤t->fs->lock); + return res; +} + +void set_fs_shdwpwd(struct fs_struct *fs, + struct vfsmount *mnt, struct dentry *dentry) +{ + struct dentry *old_dentry; + struct vfsmount *old_mnt; + + BUG_ON(dentry != NULL && mnt == NULL); + write_lock(&fs->lock); + /* set shadow pwd */ + old_dentry = fs->shdwpwd; + old_mnt = fs->shdwpwdmnt; + fs->shdwpwd = dget(dentry); + if (dentry) + fs->shdwpwdmnt = mntget(mnt); + else + /* PTR_ERR flag */ + fs->shdwpwdmnt = mnt; + write_unlock(&fs->lock); + + if (old_dentry) { + mntput(old_mnt); + dput(old_dentry); + } +} + asmlinkage long sys_chdir(const char __user * filename) { struct nameidata nd; - int error; + char *tmp = getname(filename); + int error = PTR_ERR(tmp);; + + if (IS_ERR(tmp)) + goto out_badname; - error = __user_walk(filename, - LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_CHDIR, &nd); + error = path_lookup(tmp, LOOKUP_FOLLOW | LOOKUP_DIRECTORY + | LOOKUP_CHDIR, &nd); if (error) goto out; @@ -490,11 +528,23 @@ asmlinkage long sys_chdir(const char __u if (error) goto dput_and_out; - set_fs_pwd(current->fs, nd.mnt, nd.dentry); + if (!(read_fs_flags() & SHDW_ENABLED)) + goto set_std; + if (!(nd.flags & LOOKUP_INSHDW)) + set_fs_shdwpwd(current->fs, NULL, NULL); + else + /* shadow == std */ + set_fs_shdwpwd(current->fs, nd.mnt, nd.dentry); + +set_std: + /* set std cwd */ + set_fs_pwd(current->fs, nd.mnt, nd.dentry); dput_and_out: path_release(&nd); out: + putname(tmp); +out_badname: return error; } @@ -520,8 +570,25 @@ asmlinkage long sys_fchdir(unsigned int goto out_putf; error = file_permission(file, MAY_EXEC); - if (!error) - set_fs_pwd(current->fs, mnt, dentry); + if (error) + goto out_putf; + + set_fs_pwd(current->fs, mnt, dentry); + + if (!(read_fs_flags() & SHDW_ENABLED)) + /* shadow dirs aren't enabled */ + goto out_putf; + + if (get_file_shdwdir(file, &dentry, &mnt)) + /* some error ocured */ + set_fs_shdwpwd(current->fs, NULL, NULL); + else { + /* ok */ + set_fs_shdwpwd(current->fs, mnt, dentry); + mntput(mnt); + dput(dentry); + } + out_putf: fput(file); out: - To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html