[RFC PATCH 3/5] Shadow directories: chdir, fchdir

From: Jaroslav Sykora
Date: Thu Oct 18 2007 - 11:57:59 EST


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(&current->fs->lock);
+ res = current->fs->flags;
+ read_unlock(&current->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-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/