aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Moore <pmoore@redhat.com>2015-01-22 00:00:03 -0500
committerAl Viro <viro@zeniv.linux.org.uk>2015-01-23 00:22:20 -0500
commit5168910413830435fa3f0a593933a83721ec8bad (patch)
tree72c23b2a0c98aad8d04670cb32903253e76c41ce
parent08518549722f0c992a9e4be71a0777f37147e9d2 (diff)
fs: create proper filename objects using getname_kernel()
There are several areas in the kernel that create temporary filename objects using the following pattern: int func(const char *name) { struct filename *file = { .name = name }; ... return 0; } ... which for the most part works okay, but it causes havoc within the audit subsystem as the filename object does not persist beyond the lifetime of the function. This patch converts all of these temporary filename objects into proper filename objects using getname_kernel() and putname() which ensure that the filename object persists until the audit subsystem is finished with it. Also, a special thanks to Al Viro, Guenter Roeck, and Sabrina Dubroca for helping resolve a difficult kernel panic on boot related to a use-after-free problem in kern_path_create(); the thread can be seen at the link below: * https://lkml.org/lkml/2015/1/20/710 This patch includes code that was either based on, or directly written by Al in the above thread. CC: viro@zeniv.linux.org.uk CC: linux@roeck-us.net CC: sd@queasysnail.net CC: linux-fsdevel@vger.kernel.org Signed-off-by: Paul Moore <pmoore@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
-rw-r--r--fs/exec.c10
-rw-r--r--fs/namei.c64
-rw-r--r--fs/open.c10
3 files changed, 64 insertions, 20 deletions
diff --git a/fs/exec.c b/fs/exec.c
index ad8798e26be9..c7f9b733406d 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -794,8 +794,14 @@ exit:
794 794
795struct file *open_exec(const char *name) 795struct file *open_exec(const char *name)
796{ 796{
797 struct filename tmp = { .name = name }; 797 struct filename *filename = getname_kernel(name);
798 return do_open_execat(AT_FDCWD, &tmp, 0); 798 struct file *f = ERR_CAST(filename);
799
800 if (!IS_ERR(filename)) {
801 f = do_open_execat(AT_FDCWD, filename, 0);
802 putname(filename);
803 }
804 return f;
799} 805}
800EXPORT_SYMBOL(open_exec); 806EXPORT_SYMBOL(open_exec);
801 807
diff --git a/fs/namei.c b/fs/namei.c
index 71dc1cc23b1a..0bc7742a591d 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2042,32 +2042,47 @@ static int filename_lookup(int dfd, struct filename *name,
2042static int do_path_lookup(int dfd, const char *name, 2042static int do_path_lookup(int dfd, const char *name,
2043 unsigned int flags, struct nameidata *nd) 2043 unsigned int flags, struct nameidata *nd)
2044{ 2044{
2045 struct filename filename = { .name = name }; 2045 struct filename *filename = getname_kernel(name);
2046 int retval = PTR_ERR(filename);
2046 2047
2047 return filename_lookup(dfd, &filename, flags, nd); 2048 if (!IS_ERR(filename)) {
2049 retval = filename_lookup(dfd, filename, flags, nd);
2050 putname(filename);
2051 }
2052 return retval;
2048} 2053}
2049 2054
2050/* does lookup, returns the object with parent locked */ 2055/* does lookup, returns the object with parent locked */
2051struct dentry *kern_path_locked(const char *name, struct path *path) 2056struct dentry *kern_path_locked(const char *name, struct path *path)
2052{ 2057{
2058 struct filename *filename = getname_kernel(name);
2053 struct nameidata nd; 2059 struct nameidata nd;
2054 struct dentry *d; 2060 struct dentry *d;
2055 struct filename filename = {.name = name}; 2061 int err;
2056 int err = filename_lookup(AT_FDCWD, &filename, LOOKUP_PARENT, &nd); 2062
2057 if (err) 2063 if (IS_ERR(filename))
2058 return ERR_PTR(err); 2064 return ERR_CAST(filename);
2065
2066 err = filename_lookup(AT_FDCWD, filename, LOOKUP_PARENT, &nd);
2067 if (err) {
2068 d = ERR_PTR(err);
2069 goto out;
2070 }
2059 if (nd.last_type != LAST_NORM) { 2071 if (nd.last_type != LAST_NORM) {
2060 path_put(&nd.path); 2072 path_put(&nd.path);
2061 return ERR_PTR(-EINVAL); 2073 d = ERR_PTR(-EINVAL);
2074 goto out;
2062 } 2075 }
2063 mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT); 2076 mutex_lock_nested(&nd.path.dentry->d_inode->i_mutex, I_MUTEX_PARENT);
2064 d = __lookup_hash(&nd.last, nd.path.dentry, 0); 2077 d = __lookup_hash(&nd.last, nd.path.dentry, 0);
2065 if (IS_ERR(d)) { 2078 if (IS_ERR(d)) {
2066 mutex_unlock(&nd.path.dentry->d_inode->i_mutex); 2079 mutex_unlock(&nd.path.dentry->d_inode->i_mutex);
2067 path_put(&nd.path); 2080 path_put(&nd.path);
2068 return d; 2081 goto out;
2069 } 2082 }
2070 *path = nd.path; 2083 *path = nd.path;
2084out:
2085 putname(filename);
2071 return d; 2086 return d;
2072} 2087}
2073 2088
@@ -2399,8 +2414,14 @@ int
2399kern_path_mountpoint(int dfd, const char *name, struct path *path, 2414kern_path_mountpoint(int dfd, const char *name, struct path *path,
2400 unsigned int flags) 2415 unsigned int flags)
2401{ 2416{
2402 struct filename s = {.name = name}; 2417 struct filename *s = getname_kernel(name);
2403 return filename_mountpoint(dfd, &s, path, flags); 2418 int retval = PTR_ERR(s);
2419
2420 if (!IS_ERR(s)) {
2421 retval = filename_mountpoint(dfd, s, path, flags);
2422 putname(s);
2423 }
2424 return retval;
2404} 2425}
2405EXPORT_SYMBOL(kern_path_mountpoint); 2426EXPORT_SYMBOL(kern_path_mountpoint);
2406 2427
@@ -3280,7 +3301,7 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
3280{ 3301{
3281 struct nameidata nd; 3302 struct nameidata nd;
3282 struct file *file; 3303 struct file *file;
3283 struct filename filename = { .name = name }; 3304 struct filename *filename;
3284 int flags = op->lookup_flags | LOOKUP_ROOT; 3305 int flags = op->lookup_flags | LOOKUP_ROOT;
3285 3306
3286 nd.root.mnt = mnt; 3307 nd.root.mnt = mnt;
@@ -3289,11 +3310,16 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt,
3289 if (d_is_symlink(dentry) && op->intent & LOOKUP_OPEN) 3310 if (d_is_symlink(dentry) && op->intent & LOOKUP_OPEN)
3290 return ERR_PTR(-ELOOP); 3311 return ERR_PTR(-ELOOP);
3291 3312
3292 file = path_openat(-1, &filename, &nd, op, flags | LOOKUP_RCU); 3313 filename = getname_kernel(name);
3314 if (unlikely(IS_ERR(filename)))
3315 return ERR_CAST(filename);
3316
3317 file = path_openat(-1, filename, &nd, op, flags | LOOKUP_RCU);
3293 if (unlikely(file == ERR_PTR(-ECHILD))) 3318 if (unlikely(file == ERR_PTR(-ECHILD)))
3294 file = path_openat(-1, &filename, &nd, op, flags); 3319 file = path_openat(-1, filename, &nd, op, flags);
3295 if (unlikely(file == ERR_PTR(-ESTALE))) 3320 if (unlikely(file == ERR_PTR(-ESTALE)))
3296 file = path_openat(-1, &filename, &nd, op, flags | LOOKUP_REVAL); 3321 file = path_openat(-1, filename, &nd, op, flags | LOOKUP_REVAL);
3322 putname(filename);
3297 return file; 3323 return file;
3298} 3324}
3299 3325
@@ -3370,8 +3396,14 @@ out:
3370struct dentry *kern_path_create(int dfd, const char *pathname, 3396struct dentry *kern_path_create(int dfd, const char *pathname,
3371 struct path *path, unsigned int lookup_flags) 3397 struct path *path, unsigned int lookup_flags)
3372{ 3398{
3373 struct filename filename = {.name = pathname}; 3399 struct filename *filename = getname_kernel(pathname);
3374 return filename_create(dfd, &filename, path, lookup_flags); 3400 struct dentry *res;
3401
3402 if (IS_ERR(filename))
3403 return ERR_CAST(filename);
3404 res = filename_create(dfd, filename, path, lookup_flags);
3405 putname(filename);
3406 return res;
3375} 3407}
3376EXPORT_SYMBOL(kern_path_create); 3408EXPORT_SYMBOL(kern_path_create);
3377 3409
diff --git a/fs/open.c b/fs/open.c
index 813be037b412..d36c42ff019d 100644
--- a/fs/open.c
+++ b/fs/open.c
@@ -971,8 +971,14 @@ struct file *file_open_name(struct filename *name, int flags, umode_t mode)
971 */ 971 */
972struct file *filp_open(const char *filename, int flags, umode_t mode) 972struct file *filp_open(const char *filename, int flags, umode_t mode)
973{ 973{
974 struct filename name = {.name = filename}; 974 struct filename *name = getname_kernel(filename);
975 return file_open_name(&name, flags, mode); 975 struct file *file = ERR_CAST(name);
976
977 if (!IS_ERR(name)) {
978 file = file_open_name(name, flags, mode);
979 putname(name);
980 }
981 return file;
976} 982}
977EXPORT_SYMBOL(filp_open); 983EXPORT_SYMBOL(filp_open);
978 984