diff options
| -rw-r--r-- | fs/cachefiles/daemon.c | 14 | ||||
| -rw-r--r-- | fs/dcache.c | 12 | ||||
| -rw-r--r-- | fs/fs_struct.c | 7 | ||||
| -rw-r--r-- | fs/namei.c | 15 | ||||
| -rw-r--r-- | fs/namespace.c | 5 | ||||
| -rw-r--r-- | fs/proc/base.c | 22 | ||||
| -rw-r--r-- | include/linux/fs_struct.h | 27 | ||||
| -rw-r--r-- | kernel/auditsc.c | 9 |
8 files changed, 49 insertions, 62 deletions
diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c index 72d4d0042826..727caedcdd92 100644 --- a/fs/cachefiles/daemon.c +++ b/fs/cachefiles/daemon.c | |||
| @@ -552,7 +552,6 @@ static int cachefiles_daemon_tag(struct cachefiles_cache *cache, char *args) | |||
| 552 | */ | 552 | */ |
| 553 | static int cachefiles_daemon_cull(struct cachefiles_cache *cache, char *args) | 553 | static int cachefiles_daemon_cull(struct cachefiles_cache *cache, char *args) |
| 554 | { | 554 | { |
| 555 | struct fs_struct *fs; | ||
| 556 | struct path path; | 555 | struct path path; |
| 557 | const struct cred *saved_cred; | 556 | const struct cred *saved_cred; |
| 558 | int ret; | 557 | int ret; |
| @@ -573,11 +572,7 @@ static int cachefiles_daemon_cull(struct cachefiles_cache *cache, char *args) | |||
| 573 | } | 572 | } |
| 574 | 573 | ||
| 575 | /* extract the directory dentry from the cwd */ | 574 | /* extract the directory dentry from the cwd */ |
| 576 | fs = current->fs; | 575 | get_fs_pwd(current->fs, &path); |
| 577 | read_lock(&fs->lock); | ||
| 578 | path = fs->pwd; | ||
| 579 | path_get(&path); | ||
| 580 | read_unlock(&fs->lock); | ||
| 581 | 576 | ||
| 582 | if (!S_ISDIR(path.dentry->d_inode->i_mode)) | 577 | if (!S_ISDIR(path.dentry->d_inode->i_mode)) |
| 583 | goto notdir; | 578 | goto notdir; |
| @@ -629,7 +624,6 @@ inval: | |||
| 629 | */ | 624 | */ |
| 630 | static int cachefiles_daemon_inuse(struct cachefiles_cache *cache, char *args) | 625 | static int cachefiles_daemon_inuse(struct cachefiles_cache *cache, char *args) |
| 631 | { | 626 | { |
| 632 | struct fs_struct *fs; | ||
| 633 | struct path path; | 627 | struct path path; |
| 634 | const struct cred *saved_cred; | 628 | const struct cred *saved_cred; |
| 635 | int ret; | 629 | int ret; |
| @@ -650,11 +644,7 @@ static int cachefiles_daemon_inuse(struct cachefiles_cache *cache, char *args) | |||
| 650 | } | 644 | } |
| 651 | 645 | ||
| 652 | /* extract the directory dentry from the cwd */ | 646 | /* extract the directory dentry from the cwd */ |
| 653 | fs = current->fs; | 647 | get_fs_pwd(current->fs, &path); |
| 654 | read_lock(&fs->lock); | ||
| 655 | path = fs->pwd; | ||
| 656 | path_get(&path); | ||
| 657 | read_unlock(&fs->lock); | ||
| 658 | 648 | ||
| 659 | if (!S_ISDIR(path.dentry->d_inode->i_mode)) | 649 | if (!S_ISDIR(path.dentry->d_inode->i_mode)) |
| 660 | goto notdir; | 650 | goto notdir; |
diff --git a/fs/dcache.c b/fs/dcache.c index 9f2c13417969..995d08069d26 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
| @@ -2014,10 +2014,7 @@ char *d_path(const struct path *path, char *buf, int buflen) | |||
| 2014 | if (path->dentry->d_op && path->dentry->d_op->d_dname) | 2014 | if (path->dentry->d_op && path->dentry->d_op->d_dname) |
| 2015 | return path->dentry->d_op->d_dname(path->dentry, buf, buflen); | 2015 | return path->dentry->d_op->d_dname(path->dentry, buf, buflen); |
| 2016 | 2016 | ||
| 2017 | read_lock(¤t->fs->lock); | 2017 | get_fs_root(current->fs, &root); |
| 2018 | root = current->fs->root; | ||
| 2019 | path_get(&root); | ||
| 2020 | read_unlock(¤t->fs->lock); | ||
| 2021 | spin_lock(&dcache_lock); | 2018 | spin_lock(&dcache_lock); |
| 2022 | tmp = root; | 2019 | tmp = root; |
| 2023 | res = __d_path(path, &tmp, buf, buflen); | 2020 | res = __d_path(path, &tmp, buf, buflen); |
| @@ -2129,12 +2126,7 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size) | |||
| 2129 | if (!page) | 2126 | if (!page) |
| 2130 | return -ENOMEM; | 2127 | return -ENOMEM; |
| 2131 | 2128 | ||
| 2132 | read_lock(¤t->fs->lock); | 2129 | get_fs_root_and_pwd(current->fs, &root, &pwd); |
| 2133 | pwd = current->fs->pwd; | ||
| 2134 | path_get(&pwd); | ||
| 2135 | root = current->fs->root; | ||
| 2136 | path_get(&root); | ||
| 2137 | read_unlock(¤t->fs->lock); | ||
| 2138 | 2130 | ||
| 2139 | error = -ENOENT; | 2131 | error = -ENOENT; |
| 2140 | spin_lock(&dcache_lock); | 2132 | spin_lock(&dcache_lock); |
diff --git a/fs/fs_struct.c b/fs/fs_struct.c index eee059052db5..1ee40eb9a2c0 100644 --- a/fs/fs_struct.c +++ b/fs/fs_struct.c | |||
| @@ -106,12 +106,7 @@ struct fs_struct *copy_fs_struct(struct fs_struct *old) | |||
| 106 | fs->in_exec = 0; | 106 | fs->in_exec = 0; |
| 107 | rwlock_init(&fs->lock); | 107 | rwlock_init(&fs->lock); |
| 108 | fs->umask = old->umask; | 108 | fs->umask = old->umask; |
| 109 | read_lock(&old->lock); | 109 | get_fs_root_and_pwd(old, &fs->root, &fs->pwd); |
| 110 | fs->root = old->root; | ||
| 111 | path_get(&old->root); | ||
| 112 | fs->pwd = old->pwd; | ||
| 113 | path_get(&old->pwd); | ||
| 114 | read_unlock(&old->lock); | ||
| 115 | } | 110 | } |
| 116 | return fs; | 111 | return fs; |
| 117 | } | 112 | } |
diff --git a/fs/namei.c b/fs/namei.c index 13ff4abdbdca..17ea76bf2fbe 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
| @@ -483,13 +483,8 @@ ok: | |||
| 483 | 483 | ||
| 484 | static __always_inline void set_root(struct nameidata *nd) | 484 | static __always_inline void set_root(struct nameidata *nd) |
| 485 | { | 485 | { |
| 486 | if (!nd->root.mnt) { | 486 | if (!nd->root.mnt) |
| 487 | struct fs_struct *fs = current->fs; | 487 | get_fs_root(current->fs, &nd->root); |
| 488 | read_lock(&fs->lock); | ||
| 489 | nd->root = fs->root; | ||
| 490 | path_get(&nd->root); | ||
| 491 | read_unlock(&fs->lock); | ||
| 492 | } | ||
| 493 | } | 488 | } |
| 494 | 489 | ||
| 495 | static int link_path_walk(const char *, struct nameidata *); | 490 | static int link_path_walk(const char *, struct nameidata *); |
| @@ -1015,11 +1010,7 @@ static int path_init(int dfd, const char *name, unsigned int flags, struct namei | |||
| 1015 | nd->path = nd->root; | 1010 | nd->path = nd->root; |
| 1016 | path_get(&nd->root); | 1011 | path_get(&nd->root); |
| 1017 | } else if (dfd == AT_FDCWD) { | 1012 | } else if (dfd == AT_FDCWD) { |
| 1018 | struct fs_struct *fs = current->fs; | 1013 | get_fs_pwd(current->fs, &nd->path); |
| 1019 | read_lock(&fs->lock); | ||
| 1020 | nd->path = fs->pwd; | ||
| 1021 | path_get(&fs->pwd); | ||
| 1022 | read_unlock(&fs->lock); | ||
| 1023 | } else { | 1014 | } else { |
| 1024 | struct dentry *dentry; | 1015 | struct dentry *dentry; |
| 1025 | 1016 | ||
diff --git a/fs/namespace.c b/fs/namespace.c index 66c4f7e781cb..7972e51ccc06 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -2213,10 +2213,7 @@ SYSCALL_DEFINE2(pivot_root, const char __user *, new_root, | |||
| 2213 | goto out1; | 2213 | goto out1; |
| 2214 | } | 2214 | } |
| 2215 | 2215 | ||
| 2216 | read_lock(¤t->fs->lock); | 2216 | get_fs_root(current->fs, &root); |
| 2217 | root = current->fs->root; | ||
| 2218 | path_get(¤t->fs->root); | ||
| 2219 | read_unlock(¤t->fs->lock); | ||
| 2220 | down_write(&namespace_sem); | 2217 | down_write(&namespace_sem); |
| 2221 | mutex_lock(&old.dentry->d_inode->i_mutex); | 2218 | mutex_lock(&old.dentry->d_inode->i_mutex); |
| 2222 | error = -EINVAL; | 2219 | error = -EINVAL; |
diff --git a/fs/proc/base.c b/fs/proc/base.c index c806dfb24e08..4cf5abf77ddf 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -149,18 +149,13 @@ static unsigned int pid_entry_count_dirs(const struct pid_entry *entries, | |||
| 149 | return count; | 149 | return count; |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | static int get_fs_path(struct task_struct *task, struct path *path, bool root) | 152 | static int get_task_root(struct task_struct *task, struct path *root) |
| 153 | { | 153 | { |
| 154 | struct fs_struct *fs; | ||
| 155 | int result = -ENOENT; | 154 | int result = -ENOENT; |
| 156 | 155 | ||
| 157 | task_lock(task); | 156 | task_lock(task); |
| 158 | fs = task->fs; | 157 | if (task->fs) { |
| 159 | if (fs) { | 158 | get_fs_root(task->fs, root); |
| 160 | read_lock(&fs->lock); | ||
| 161 | *path = root ? fs->root : fs->pwd; | ||
| 162 | path_get(path); | ||
| 163 | read_unlock(&fs->lock); | ||
| 164 | result = 0; | 159 | result = 0; |
| 165 | } | 160 | } |
| 166 | task_unlock(task); | 161 | task_unlock(task); |
| @@ -173,7 +168,12 @@ static int proc_cwd_link(struct inode *inode, struct path *path) | |||
| 173 | int result = -ENOENT; | 168 | int result = -ENOENT; |
| 174 | 169 | ||
| 175 | if (task) { | 170 | if (task) { |
| 176 | result = get_fs_path(task, path, 0); | 171 | task_lock(task); |
| 172 | if (task->fs) { | ||
| 173 | get_fs_pwd(task->fs, path); | ||
| 174 | result = 0; | ||
| 175 | } | ||
| 176 | task_unlock(task); | ||
| 177 | put_task_struct(task); | 177 | put_task_struct(task); |
| 178 | } | 178 | } |
| 179 | return result; | 179 | return result; |
| @@ -185,7 +185,7 @@ static int proc_root_link(struct inode *inode, struct path *path) | |||
| 185 | int result = -ENOENT; | 185 | int result = -ENOENT; |
| 186 | 186 | ||
| 187 | if (task) { | 187 | if (task) { |
| 188 | result = get_fs_path(task, path, 1); | 188 | result = get_task_root(task, path); |
| 189 | put_task_struct(task); | 189 | put_task_struct(task); |
| 190 | } | 190 | } |
| 191 | return result; | 191 | return result; |
| @@ -597,7 +597,7 @@ static int mounts_open_common(struct inode *inode, struct file *file, | |||
| 597 | get_mnt_ns(ns); | 597 | get_mnt_ns(ns); |
| 598 | } | 598 | } |
| 599 | rcu_read_unlock(); | 599 | rcu_read_unlock(); |
| 600 | if (ns && get_fs_path(task, &root, 1) == 0) | 600 | if (ns && get_task_root(task, &root) == 0) |
| 601 | ret = 0; | 601 | ret = 0; |
| 602 | put_task_struct(task); | 602 | put_task_struct(task); |
| 603 | } | 603 | } |
diff --git a/include/linux/fs_struct.h b/include/linux/fs_struct.h index 78a05bfcd8eb..eca3d5202138 100644 --- a/include/linux/fs_struct.h +++ b/include/linux/fs_struct.h | |||
| @@ -21,4 +21,31 @@ extern void free_fs_struct(struct fs_struct *); | |||
| 21 | extern void daemonize_fs_struct(void); | 21 | extern void daemonize_fs_struct(void); |
| 22 | extern int unshare_fs_struct(void); | 22 | extern int unshare_fs_struct(void); |
| 23 | 23 | ||
| 24 | static inline void get_fs_root(struct fs_struct *fs, struct path *root) | ||
| 25 | { | ||
| 26 | read_lock(&fs->lock); | ||
| 27 | *root = fs->root; | ||
| 28 | path_get(root); | ||
| 29 | read_unlock(&fs->lock); | ||
| 30 | } | ||
| 31 | |||
| 32 | static inline void get_fs_pwd(struct fs_struct *fs, struct path *pwd) | ||
| 33 | { | ||
| 34 | read_lock(&fs->lock); | ||
| 35 | *pwd = fs->pwd; | ||
| 36 | path_get(pwd); | ||
| 37 | read_unlock(&fs->lock); | ||
| 38 | } | ||
| 39 | |||
| 40 | static inline void get_fs_root_and_pwd(struct fs_struct *fs, struct path *root, | ||
| 41 | struct path *pwd) | ||
| 42 | { | ||
| 43 | read_lock(&fs->lock); | ||
| 44 | *root = fs->root; | ||
| 45 | path_get(root); | ||
| 46 | *pwd = fs->pwd; | ||
| 47 | path_get(pwd); | ||
| 48 | read_unlock(&fs->lock); | ||
| 49 | } | ||
| 50 | |||
| 24 | #endif /* _LINUX_FS_STRUCT_H */ | 51 | #endif /* _LINUX_FS_STRUCT_H */ |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index b87a63beb66c..1b31c130d034 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -1835,13 +1835,8 @@ void __audit_getname(const char *name) | |||
| 1835 | context->names[context->name_count].ino = (unsigned long)-1; | 1835 | context->names[context->name_count].ino = (unsigned long)-1; |
| 1836 | context->names[context->name_count].osid = 0; | 1836 | context->names[context->name_count].osid = 0; |
| 1837 | ++context->name_count; | 1837 | ++context->name_count; |
| 1838 | if (!context->pwd.dentry) { | 1838 | if (!context->pwd.dentry) |
| 1839 | read_lock(¤t->fs->lock); | 1839 | get_fs_pwd(current->fs, &context->pwd); |
| 1840 | context->pwd = current->fs->pwd; | ||
| 1841 | path_get(¤t->fs->pwd); | ||
| 1842 | read_unlock(¤t->fs->lock); | ||
| 1843 | } | ||
| 1844 | |||
| 1845 | } | 1840 | } |
| 1846 | 1841 | ||
| 1847 | /* audit_putname - intercept a putname request | 1842 | /* audit_putname - intercept a putname request |
