diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-17 18:27:47 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-02-17 18:27:47 -0500 |
commit | 05016b0f0a9d900e976db7f50a7761c0aefe5a1c (patch) | |
tree | 20b2f04fee785dc9ef81596cb2f7deec6d8016e0 | |
parent | c6b1de1b646fe232206d4065df4d14040cebd613 (diff) | |
parent | 55422d0bd292f5ad143cc32cb8bb8505257274c4 (diff) |
Merge branch 'getname2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs
Pull getname/putname updates from Al Viro:
"Rework of getname/getname_kernel/etc., mostly from Paul Moore. Gets
rid of quite a pile of kludges between namei and audit..."
* 'getname2' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs:
audit: replace getname()/putname() hacks with reference counters
audit: fix filename matching in __audit_inode() and __audit_inode_child()
audit: enable filename recording via getname_kernel()
simpler calling conventions for filename_mountpoint()
fs: create proper filename objects using getname_kernel()
fs: rework getname_kernel to handle up to PATH_MAX sized filenames
cut down the number of do_path_lookup() callers
-rw-r--r-- | fs/exec.c | 10 | ||||
-rw-r--r-- | fs/namei.c | 143 | ||||
-rw-r--r-- | fs/open.c | 10 | ||||
-rw-r--r-- | include/linux/audit.h | 3 | ||||
-rw-r--r-- | include/linux/fs.h | 9 | ||||
-rw-r--r-- | kernel/audit.h | 17 | ||||
-rw-r--r-- | kernel/auditsc.c | 171 |
7 files changed, 145 insertions, 218 deletions
@@ -794,8 +794,14 @@ exit: | |||
794 | 794 | ||
795 | struct file *open_exec(const char *name) | 795 | struct 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 | } |
800 | EXPORT_SYMBOL(open_exec); | 806 | EXPORT_SYMBOL(open_exec); |
801 | 807 | ||
diff --git a/fs/namei.c b/fs/namei.c index bc35b02883bb..96ca11dea4a2 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -118,15 +118,6 @@ | |||
118 | * POSIX.1 2.4: an empty pathname is invalid (ENOENT). | 118 | * POSIX.1 2.4: an empty pathname is invalid (ENOENT). |
119 | * PATH_MAX includes the nul terminator --RR. | 119 | * PATH_MAX includes the nul terminator --RR. |
120 | */ | 120 | */ |
121 | void final_putname(struct filename *name) | ||
122 | { | ||
123 | if (name->separate) { | ||
124 | __putname(name->name); | ||
125 | kfree(name); | ||
126 | } else { | ||
127 | __putname(name); | ||
128 | } | ||
129 | } | ||
130 | 121 | ||
131 | #define EMBEDDED_NAME_MAX (PATH_MAX - sizeof(struct filename)) | 122 | #define EMBEDDED_NAME_MAX (PATH_MAX - sizeof(struct filename)) |
132 | 123 | ||
@@ -145,6 +136,7 @@ getname_flags(const char __user *filename, int flags, int *empty) | |||
145 | result = __getname(); | 136 | result = __getname(); |
146 | if (unlikely(!result)) | 137 | if (unlikely(!result)) |
147 | return ERR_PTR(-ENOMEM); | 138 | return ERR_PTR(-ENOMEM); |
139 | result->refcnt = 1; | ||
148 | 140 | ||
149 | /* | 141 | /* |
150 | * First, try to embed the struct filename inside the names_cache | 142 | * First, try to embed the struct filename inside the names_cache |
@@ -179,6 +171,7 @@ recopy: | |||
179 | } | 171 | } |
180 | result->name = kname; | 172 | result->name = kname; |
181 | result->separate = true; | 173 | result->separate = true; |
174 | result->refcnt = 1; | ||
182 | max = PATH_MAX; | 175 | max = PATH_MAX; |
183 | goto recopy; | 176 | goto recopy; |
184 | } | 177 | } |
@@ -202,7 +195,7 @@ recopy: | |||
202 | return result; | 195 | return result; |
203 | 196 | ||
204 | error: | 197 | error: |
205 | final_putname(result); | 198 | putname(result); |
206 | return err; | 199 | return err; |
207 | } | 200 | } |
208 | 201 | ||
@@ -212,43 +205,56 @@ getname(const char __user * filename) | |||
212 | return getname_flags(filename, 0, NULL); | 205 | return getname_flags(filename, 0, NULL); |
213 | } | 206 | } |
214 | 207 | ||
215 | /* | ||
216 | * The "getname_kernel()" interface doesn't do pathnames longer | ||
217 | * than EMBEDDED_NAME_MAX. Deal with it - you're a kernel user. | ||
218 | */ | ||
219 | struct filename * | 208 | struct filename * |
220 | getname_kernel(const char * filename) | 209 | getname_kernel(const char * filename) |
221 | { | 210 | { |
222 | struct filename *result; | 211 | struct filename *result; |
223 | char *kname; | 212 | int len = strlen(filename) + 1; |
224 | int len; | ||
225 | |||
226 | len = strlen(filename); | ||
227 | if (len >= EMBEDDED_NAME_MAX) | ||
228 | return ERR_PTR(-ENAMETOOLONG); | ||
229 | 213 | ||
230 | result = __getname(); | 214 | result = __getname(); |
231 | if (unlikely(!result)) | 215 | if (unlikely(!result)) |
232 | return ERR_PTR(-ENOMEM); | 216 | return ERR_PTR(-ENOMEM); |
233 | 217 | ||
234 | kname = (char *)result + sizeof(*result); | 218 | if (len <= EMBEDDED_NAME_MAX) { |
235 | result->name = kname; | 219 | result->name = (char *)(result) + sizeof(*result); |
220 | result->separate = false; | ||
221 | } else if (len <= PATH_MAX) { | ||
222 | struct filename *tmp; | ||
223 | |||
224 | tmp = kmalloc(sizeof(*tmp), GFP_KERNEL); | ||
225 | if (unlikely(!tmp)) { | ||
226 | __putname(result); | ||
227 | return ERR_PTR(-ENOMEM); | ||
228 | } | ||
229 | tmp->name = (char *)result; | ||
230 | tmp->separate = true; | ||
231 | result = tmp; | ||
232 | } else { | ||
233 | __putname(result); | ||
234 | return ERR_PTR(-ENAMETOOLONG); | ||
235 | } | ||
236 | memcpy((char *)result->name, filename, len); | ||
236 | result->uptr = NULL; | 237 | result->uptr = NULL; |
237 | result->aname = NULL; | 238 | result->aname = NULL; |
238 | result->separate = false; | 239 | result->refcnt = 1; |
240 | audit_getname(result); | ||
239 | 241 | ||
240 | strlcpy(kname, filename, EMBEDDED_NAME_MAX); | ||
241 | return result; | 242 | return result; |
242 | } | 243 | } |
243 | 244 | ||
244 | #ifdef CONFIG_AUDITSYSCALL | ||
245 | void putname(struct filename *name) | 245 | void putname(struct filename *name) |
246 | { | 246 | { |
247 | if (unlikely(!audit_dummy_context())) | 247 | BUG_ON(name->refcnt <= 0); |
248 | return audit_putname(name); | 248 | |
249 | final_putname(name); | 249 | if (--name->refcnt > 0) |
250 | return; | ||
251 | |||
252 | if (name->separate) { | ||
253 | __putname(name->name); | ||
254 | kfree(name); | ||
255 | } else | ||
256 | __putname(name); | ||
250 | } | 257 | } |
251 | #endif | ||
252 | 258 | ||
253 | static int check_acl(struct inode *inode, int mask) | 259 | static int check_acl(struct inode *inode, int mask) |
254 | { | 260 | { |
@@ -2036,31 +2042,47 @@ static int filename_lookup(int dfd, struct filename *name, | |||
2036 | static int do_path_lookup(int dfd, const char *name, | 2042 | static int do_path_lookup(int dfd, const char *name, |
2037 | unsigned int flags, struct nameidata *nd) | 2043 | unsigned int flags, struct nameidata *nd) |
2038 | { | 2044 | { |
2039 | struct filename filename = { .name = name }; | 2045 | struct filename *filename = getname_kernel(name); |
2046 | int retval = PTR_ERR(filename); | ||
2040 | 2047 | ||
2041 | 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; | ||
2042 | } | 2053 | } |
2043 | 2054 | ||
2044 | /* does lookup, returns the object with parent locked */ | 2055 | /* does lookup, returns the object with parent locked */ |
2045 | struct dentry *kern_path_locked(const char *name, struct path *path) | 2056 | struct dentry *kern_path_locked(const char *name, struct path *path) |
2046 | { | 2057 | { |
2058 | struct filename *filename = getname_kernel(name); | ||
2047 | struct nameidata nd; | 2059 | struct nameidata nd; |
2048 | struct dentry *d; | 2060 | struct dentry *d; |
2049 | int err = do_path_lookup(AT_FDCWD, name, LOOKUP_PARENT, &nd); | 2061 | int err; |
2050 | if (err) | 2062 | |
2051 | return ERR_PTR(err); | 2063 | if (IS_ERR(filename)) |
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 | } | ||
2052 | if (nd.last_type != LAST_NORM) { | 2071 | if (nd.last_type != LAST_NORM) { |
2053 | path_put(&nd.path); | 2072 | path_put(&nd.path); |
2054 | return ERR_PTR(-EINVAL); | 2073 | d = ERR_PTR(-EINVAL); |
2074 | goto out; | ||
2055 | } | 2075 | } |
2056 | 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); |
2057 | d = __lookup_hash(&nd.last, nd.path.dentry, 0); | 2077 | d = __lookup_hash(&nd.last, nd.path.dentry, 0); |
2058 | if (IS_ERR(d)) { | 2078 | if (IS_ERR(d)) { |
2059 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); | 2079 | mutex_unlock(&nd.path.dentry->d_inode->i_mutex); |
2060 | path_put(&nd.path); | 2080 | path_put(&nd.path); |
2061 | return d; | 2081 | goto out; |
2062 | } | 2082 | } |
2063 | *path = nd.path; | 2083 | *path = nd.path; |
2084 | out: | ||
2085 | putname(filename); | ||
2064 | return d; | 2086 | return d; |
2065 | } | 2087 | } |
2066 | 2088 | ||
@@ -2351,13 +2373,17 @@ static int | |||
2351 | filename_mountpoint(int dfd, struct filename *s, struct path *path, | 2373 | filename_mountpoint(int dfd, struct filename *s, struct path *path, |
2352 | unsigned int flags) | 2374 | unsigned int flags) |
2353 | { | 2375 | { |
2354 | int error = path_mountpoint(dfd, s->name, path, flags | LOOKUP_RCU); | 2376 | int error; |
2377 | if (IS_ERR(s)) | ||
2378 | return PTR_ERR(s); | ||
2379 | error = path_mountpoint(dfd, s->name, path, flags | LOOKUP_RCU); | ||
2355 | if (unlikely(error == -ECHILD)) | 2380 | if (unlikely(error == -ECHILD)) |
2356 | error = path_mountpoint(dfd, s->name, path, flags); | 2381 | error = path_mountpoint(dfd, s->name, path, flags); |
2357 | if (unlikely(error == -ESTALE)) | 2382 | if (unlikely(error == -ESTALE)) |
2358 | error = path_mountpoint(dfd, s->name, path, flags | LOOKUP_REVAL); | 2383 | error = path_mountpoint(dfd, s->name, path, flags | LOOKUP_REVAL); |
2359 | if (likely(!error)) | 2384 | if (likely(!error)) |
2360 | audit_inode(s, path->dentry, 0); | 2385 | audit_inode(s, path->dentry, 0); |
2386 | putname(s); | ||
2361 | return error; | 2387 | return error; |
2362 | } | 2388 | } |
2363 | 2389 | ||
@@ -2379,21 +2405,14 @@ int | |||
2379 | user_path_mountpoint_at(int dfd, const char __user *name, unsigned int flags, | 2405 | user_path_mountpoint_at(int dfd, const char __user *name, unsigned int flags, |
2380 | struct path *path) | 2406 | struct path *path) |
2381 | { | 2407 | { |
2382 | struct filename *s = getname(name); | 2408 | return filename_mountpoint(dfd, getname(name), path, flags); |
2383 | int error; | ||
2384 | if (IS_ERR(s)) | ||
2385 | return PTR_ERR(s); | ||
2386 | error = filename_mountpoint(dfd, s, path, flags); | ||
2387 | putname(s); | ||
2388 | return error; | ||
2389 | } | 2409 | } |
2390 | 2410 | ||
2391 | int | 2411 | int |
2392 | kern_path_mountpoint(int dfd, const char *name, struct path *path, | 2412 | kern_path_mountpoint(int dfd, const char *name, struct path *path, |
2393 | unsigned int flags) | 2413 | unsigned int flags) |
2394 | { | 2414 | { |
2395 | struct filename s = {.name = name}; | 2415 | return filename_mountpoint(dfd, getname_kernel(name), path, flags); |
2396 | return filename_mountpoint(dfd, &s, path, flags); | ||
2397 | } | 2416 | } |
2398 | EXPORT_SYMBOL(kern_path_mountpoint); | 2417 | EXPORT_SYMBOL(kern_path_mountpoint); |
2399 | 2418 | ||
@@ -3273,7 +3292,7 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt, | |||
3273 | { | 3292 | { |
3274 | struct nameidata nd; | 3293 | struct nameidata nd; |
3275 | struct file *file; | 3294 | struct file *file; |
3276 | struct filename filename = { .name = name }; | 3295 | struct filename *filename; |
3277 | int flags = op->lookup_flags | LOOKUP_ROOT; | 3296 | int flags = op->lookup_flags | LOOKUP_ROOT; |
3278 | 3297 | ||
3279 | nd.root.mnt = mnt; | 3298 | nd.root.mnt = mnt; |
@@ -3282,15 +3301,20 @@ struct file *do_file_open_root(struct dentry *dentry, struct vfsmount *mnt, | |||
3282 | if (d_is_symlink(dentry) && op->intent & LOOKUP_OPEN) | 3301 | if (d_is_symlink(dentry) && op->intent & LOOKUP_OPEN) |
3283 | return ERR_PTR(-ELOOP); | 3302 | return ERR_PTR(-ELOOP); |
3284 | 3303 | ||
3285 | file = path_openat(-1, &filename, &nd, op, flags | LOOKUP_RCU); | 3304 | filename = getname_kernel(name); |
3305 | if (unlikely(IS_ERR(filename))) | ||
3306 | return ERR_CAST(filename); | ||
3307 | |||
3308 | file = path_openat(-1, filename, &nd, op, flags | LOOKUP_RCU); | ||
3286 | if (unlikely(file == ERR_PTR(-ECHILD))) | 3309 | if (unlikely(file == ERR_PTR(-ECHILD))) |
3287 | file = path_openat(-1, &filename, &nd, op, flags); | 3310 | file = path_openat(-1, filename, &nd, op, flags); |
3288 | if (unlikely(file == ERR_PTR(-ESTALE))) | 3311 | if (unlikely(file == ERR_PTR(-ESTALE))) |
3289 | file = path_openat(-1, &filename, &nd, op, flags | LOOKUP_REVAL); | 3312 | file = path_openat(-1, filename, &nd, op, flags | LOOKUP_REVAL); |
3313 | putname(filename); | ||
3290 | return file; | 3314 | return file; |
3291 | } | 3315 | } |
3292 | 3316 | ||
3293 | struct dentry *kern_path_create(int dfd, const char *pathname, | 3317 | static struct dentry *filename_create(int dfd, struct filename *name, |
3294 | struct path *path, unsigned int lookup_flags) | 3318 | struct path *path, unsigned int lookup_flags) |
3295 | { | 3319 | { |
3296 | struct dentry *dentry = ERR_PTR(-EEXIST); | 3320 | struct dentry *dentry = ERR_PTR(-EEXIST); |
@@ -3305,7 +3329,7 @@ struct dentry *kern_path_create(int dfd, const char *pathname, | |||
3305 | */ | 3329 | */ |
3306 | lookup_flags &= LOOKUP_REVAL; | 3330 | lookup_flags &= LOOKUP_REVAL; |
3307 | 3331 | ||
3308 | error = do_path_lookup(dfd, pathname, LOOKUP_PARENT|lookup_flags, &nd); | 3332 | error = filename_lookup(dfd, name, LOOKUP_PARENT|lookup_flags, &nd); |
3309 | if (error) | 3333 | if (error) |
3310 | return ERR_PTR(error); | 3334 | return ERR_PTR(error); |
3311 | 3335 | ||
@@ -3359,6 +3383,19 @@ out: | |||
3359 | path_put(&nd.path); | 3383 | path_put(&nd.path); |
3360 | return dentry; | 3384 | return dentry; |
3361 | } | 3385 | } |
3386 | |||
3387 | struct dentry *kern_path_create(int dfd, const char *pathname, | ||
3388 | struct path *path, unsigned int lookup_flags) | ||
3389 | { | ||
3390 | struct filename *filename = getname_kernel(pathname); | ||
3391 | struct dentry *res; | ||
3392 | |||
3393 | if (IS_ERR(filename)) | ||
3394 | return ERR_CAST(filename); | ||
3395 | res = filename_create(dfd, filename, path, lookup_flags); | ||
3396 | putname(filename); | ||
3397 | return res; | ||
3398 | } | ||
3362 | EXPORT_SYMBOL(kern_path_create); | 3399 | EXPORT_SYMBOL(kern_path_create); |
3363 | 3400 | ||
3364 | void done_path_create(struct path *path, struct dentry *dentry) | 3401 | void done_path_create(struct path *path, struct dentry *dentry) |
@@ -3377,7 +3414,7 @@ struct dentry *user_path_create(int dfd, const char __user *pathname, | |||
3377 | struct dentry *res; | 3414 | struct dentry *res; |
3378 | if (IS_ERR(tmp)) | 3415 | if (IS_ERR(tmp)) |
3379 | return ERR_CAST(tmp); | 3416 | return ERR_CAST(tmp); |
3380 | res = kern_path_create(dfd, tmp->name, path, lookup_flags); | 3417 | res = filename_create(dfd, tmp, path, lookup_flags); |
3381 | putname(tmp); | 3418 | putname(tmp); |
3382 | return res; | 3419 | return res; |
3383 | } | 3420 | } |
@@ -968,8 +968,14 @@ struct file *file_open_name(struct filename *name, int flags, umode_t mode) | |||
968 | */ | 968 | */ |
969 | struct file *filp_open(const char *filename, int flags, umode_t mode) | 969 | struct file *filp_open(const char *filename, int flags, umode_t mode) |
970 | { | 970 | { |
971 | struct filename name = {.name = filename}; | 971 | struct filename *name = getname_kernel(filename); |
972 | return file_open_name(&name, flags, mode); | 972 | struct file *file = ERR_CAST(name); |
973 | |||
974 | if (!IS_ERR(name)) { | ||
975 | file = file_open_name(name, flags, mode); | ||
976 | putname(name); | ||
977 | } | ||
978 | return file; | ||
973 | } | 979 | } |
974 | EXPORT_SYMBOL(filp_open); | 980 | EXPORT_SYMBOL(filp_open); |
975 | 981 | ||
diff --git a/include/linux/audit.h b/include/linux/audit.h index 599f3bd2d6c5..c2e7e3a83965 100644 --- a/include/linux/audit.h +++ b/include/linux/audit.h | |||
@@ -127,7 +127,6 @@ extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long a1, | |||
127 | extern void __audit_syscall_exit(int ret_success, long ret_value); | 127 | extern void __audit_syscall_exit(int ret_success, long ret_value); |
128 | extern struct filename *__audit_reusename(const __user char *uptr); | 128 | extern struct filename *__audit_reusename(const __user char *uptr); |
129 | extern void __audit_getname(struct filename *name); | 129 | extern void __audit_getname(struct filename *name); |
130 | extern void audit_putname(struct filename *name); | ||
131 | 130 | ||
132 | #define AUDIT_INODE_PARENT 1 /* dentry represents the parent */ | 131 | #define AUDIT_INODE_PARENT 1 /* dentry represents the parent */ |
133 | #define AUDIT_INODE_HIDDEN 2 /* audit record should be hidden */ | 132 | #define AUDIT_INODE_HIDDEN 2 /* audit record should be hidden */ |
@@ -352,8 +351,6 @@ static inline struct filename *audit_reusename(const __user char *name) | |||
352 | } | 351 | } |
353 | static inline void audit_getname(struct filename *name) | 352 | static inline void audit_getname(struct filename *name) |
354 | { } | 353 | { } |
355 | static inline void audit_putname(struct filename *name) | ||
356 | { } | ||
357 | static inline void __audit_inode(struct filename *name, | 354 | static inline void __audit_inode(struct filename *name, |
358 | const struct dentry *dentry, | 355 | const struct dentry *dentry, |
359 | unsigned int flags) | 356 | unsigned int flags) |
diff --git a/include/linux/fs.h b/include/linux/fs.h index ed5a0900b94d..a9250b2a11ba 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
@@ -2141,6 +2141,7 @@ struct filename { | |||
2141 | const char *name; /* pointer to actual string */ | 2141 | const char *name; /* pointer to actual string */ |
2142 | const __user char *uptr; /* original userland pointer */ | 2142 | const __user char *uptr; /* original userland pointer */ |
2143 | struct audit_names *aname; | 2143 | struct audit_names *aname; |
2144 | int refcnt; | ||
2144 | bool separate; /* should "name" be freed? */ | 2145 | bool separate; /* should "name" be freed? */ |
2145 | }; | 2146 | }; |
2146 | 2147 | ||
@@ -2162,6 +2163,7 @@ extern int filp_close(struct file *, fl_owner_t id); | |||
2162 | extern struct filename *getname_flags(const char __user *, int, int *); | 2163 | extern struct filename *getname_flags(const char __user *, int, int *); |
2163 | extern struct filename *getname(const char __user *); | 2164 | extern struct filename *getname(const char __user *); |
2164 | extern struct filename *getname_kernel(const char *); | 2165 | extern struct filename *getname_kernel(const char *); |
2166 | extern void putname(struct filename *name); | ||
2165 | 2167 | ||
2166 | enum { | 2168 | enum { |
2167 | FILE_CREATED = 1, | 2169 | FILE_CREATED = 1, |
@@ -2182,15 +2184,8 @@ extern void __init vfs_caches_init(unsigned long); | |||
2182 | 2184 | ||
2183 | extern struct kmem_cache *names_cachep; | 2185 | extern struct kmem_cache *names_cachep; |
2184 | 2186 | ||
2185 | extern void final_putname(struct filename *name); | ||
2186 | |||
2187 | #define __getname() kmem_cache_alloc(names_cachep, GFP_KERNEL) | 2187 | #define __getname() kmem_cache_alloc(names_cachep, GFP_KERNEL) |
2188 | #define __putname(name) kmem_cache_free(names_cachep, (void *)(name)) | 2188 | #define __putname(name) kmem_cache_free(names_cachep, (void *)(name)) |
2189 | #ifndef CONFIG_AUDITSYSCALL | ||
2190 | #define putname(name) final_putname(name) | ||
2191 | #else | ||
2192 | extern void putname(struct filename *name); | ||
2193 | #endif | ||
2194 | 2189 | ||
2195 | #ifdef CONFIG_BLOCK | 2190 | #ifdef CONFIG_BLOCK |
2196 | extern int register_blkdev(unsigned int, const char *); | 2191 | extern int register_blkdev(unsigned int, const char *); |
diff --git a/kernel/audit.h b/kernel/audit.h index 3cdffad5a1d9..1caa0d345d90 100644 --- a/kernel/audit.h +++ b/kernel/audit.h | |||
@@ -24,12 +24,6 @@ | |||
24 | #include <linux/skbuff.h> | 24 | #include <linux/skbuff.h> |
25 | #include <uapi/linux/mqueue.h> | 25 | #include <uapi/linux/mqueue.h> |
26 | 26 | ||
27 | /* 0 = no checking | ||
28 | 1 = put_count checking | ||
29 | 2 = verbose put_count checking | ||
30 | */ | ||
31 | #define AUDIT_DEBUG 0 | ||
32 | |||
33 | /* AUDIT_NAMES is the number of slots we reserve in the audit_context | 27 | /* AUDIT_NAMES is the number of slots we reserve in the audit_context |
34 | * for saving names from getname(). If we get more names we will allocate | 28 | * for saving names from getname(). If we get more names we will allocate |
35 | * a name dynamically and also add those to the list anchored by names_list. */ | 29 | * a name dynamically and also add those to the list anchored by names_list. */ |
@@ -74,9 +68,8 @@ struct audit_cap_data { | |||
74 | }; | 68 | }; |
75 | }; | 69 | }; |
76 | 70 | ||
77 | /* When fs/namei.c:getname() is called, we store the pointer in name and | 71 | /* When fs/namei.c:getname() is called, we store the pointer in name and bump |
78 | * we don't let putname() free it (instead we free all of the saved | 72 | * the refcnt in the associated filename struct. |
79 | * pointers at syscall exit time). | ||
80 | * | 73 | * |
81 | * Further, in fs/namei.c:path_lookup() we store the inode and device. | 74 | * Further, in fs/namei.c:path_lookup() we store the inode and device. |
82 | */ | 75 | */ |
@@ -86,7 +79,6 @@ struct audit_names { | |||
86 | struct filename *name; | 79 | struct filename *name; |
87 | int name_len; /* number of chars to log */ | 80 | int name_len; /* number of chars to log */ |
88 | bool hidden; /* don't log this record */ | 81 | bool hidden; /* don't log this record */ |
89 | bool name_put; /* call __putname()? */ | ||
90 | 82 | ||
91 | unsigned long ino; | 83 | unsigned long ino; |
92 | dev_t dev; | 84 | dev_t dev; |
@@ -208,11 +200,6 @@ struct audit_context { | |||
208 | }; | 200 | }; |
209 | int fds[2]; | 201 | int fds[2]; |
210 | struct audit_proctitle proctitle; | 202 | struct audit_proctitle proctitle; |
211 | |||
212 | #if AUDIT_DEBUG | ||
213 | int put_count; | ||
214 | int ino_count; | ||
215 | #endif | ||
216 | }; | 203 | }; |
217 | 204 | ||
218 | extern u32 audit_ever_enabled; | 205 | extern u32 audit_ever_enabled; |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 55f82fce2526..dc4ae70a7413 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
@@ -866,33 +866,10 @@ static inline void audit_free_names(struct audit_context *context) | |||
866 | { | 866 | { |
867 | struct audit_names *n, *next; | 867 | struct audit_names *n, *next; |
868 | 868 | ||
869 | #if AUDIT_DEBUG == 2 | ||
870 | if (context->put_count + context->ino_count != context->name_count) { | ||
871 | int i = 0; | ||
872 | |||
873 | pr_err("%s:%d(:%d): major=%d in_syscall=%d" | ||
874 | " name_count=%d put_count=%d ino_count=%d" | ||
875 | " [NOT freeing]\n", __FILE__, __LINE__, | ||
876 | context->serial, context->major, context->in_syscall, | ||
877 | context->name_count, context->put_count, | ||
878 | context->ino_count); | ||
879 | list_for_each_entry(n, &context->names_list, list) { | ||
880 | pr_err("names[%d] = %p = %s\n", i++, n->name, | ||
881 | n->name->name ?: "(null)"); | ||
882 | } | ||
883 | dump_stack(); | ||
884 | return; | ||
885 | } | ||
886 | #endif | ||
887 | #if AUDIT_DEBUG | ||
888 | context->put_count = 0; | ||
889 | context->ino_count = 0; | ||
890 | #endif | ||
891 | |||
892 | list_for_each_entry_safe(n, next, &context->names_list, list) { | 869 | list_for_each_entry_safe(n, next, &context->names_list, list) { |
893 | list_del(&n->list); | 870 | list_del(&n->list); |
894 | if (n->name && n->name_put) | 871 | if (n->name) |
895 | final_putname(n->name); | 872 | putname(n->name); |
896 | if (n->should_free) | 873 | if (n->should_free) |
897 | kfree(n); | 874 | kfree(n); |
898 | } | 875 | } |
@@ -1711,9 +1688,6 @@ static struct audit_names *audit_alloc_name(struct audit_context *context, | |||
1711 | list_add_tail(&aname->list, &context->names_list); | 1688 | list_add_tail(&aname->list, &context->names_list); |
1712 | 1689 | ||
1713 | context->name_count++; | 1690 | context->name_count++; |
1714 | #if AUDIT_DEBUG | ||
1715 | context->ino_count++; | ||
1716 | #endif | ||
1717 | return aname; | 1691 | return aname; |
1718 | } | 1692 | } |
1719 | 1693 | ||
@@ -1734,8 +1708,10 @@ __audit_reusename(const __user char *uptr) | |||
1734 | list_for_each_entry(n, &context->names_list, list) { | 1708 | list_for_each_entry(n, &context->names_list, list) { |
1735 | if (!n->name) | 1709 | if (!n->name) |
1736 | continue; | 1710 | continue; |
1737 | if (n->name->uptr == uptr) | 1711 | if (n->name->uptr == uptr) { |
1712 | n->name->refcnt++; | ||
1738 | return n->name; | 1713 | return n->name; |
1714 | } | ||
1739 | } | 1715 | } |
1740 | return NULL; | 1716 | return NULL; |
1741 | } | 1717 | } |
@@ -1752,19 +1728,8 @@ void __audit_getname(struct filename *name) | |||
1752 | struct audit_context *context = current->audit_context; | 1728 | struct audit_context *context = current->audit_context; |
1753 | struct audit_names *n; | 1729 | struct audit_names *n; |
1754 | 1730 | ||
1755 | if (!context->in_syscall) { | 1731 | if (!context->in_syscall) |
1756 | #if AUDIT_DEBUG == 2 | ||
1757 | pr_err("%s:%d(:%d): ignoring getname(%p)\n", | ||
1758 | __FILE__, __LINE__, context->serial, name); | ||
1759 | dump_stack(); | ||
1760 | #endif | ||
1761 | return; | 1732 | return; |
1762 | } | ||
1763 | |||
1764 | #if AUDIT_DEBUG | ||
1765 | /* The filename _must_ have a populated ->name */ | ||
1766 | BUG_ON(!name->name); | ||
1767 | #endif | ||
1768 | 1733 | ||
1769 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); | 1734 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); |
1770 | if (!n) | 1735 | if (!n) |
@@ -1772,56 +1737,13 @@ void __audit_getname(struct filename *name) | |||
1772 | 1737 | ||
1773 | n->name = name; | 1738 | n->name = name; |
1774 | n->name_len = AUDIT_NAME_FULL; | 1739 | n->name_len = AUDIT_NAME_FULL; |
1775 | n->name_put = true; | ||
1776 | name->aname = n; | 1740 | name->aname = n; |
1741 | name->refcnt++; | ||
1777 | 1742 | ||
1778 | if (!context->pwd.dentry) | 1743 | if (!context->pwd.dentry) |
1779 | get_fs_pwd(current->fs, &context->pwd); | 1744 | get_fs_pwd(current->fs, &context->pwd); |
1780 | } | 1745 | } |
1781 | 1746 | ||
1782 | /* audit_putname - intercept a putname request | ||
1783 | * @name: name to intercept and delay for putname | ||
1784 | * | ||
1785 | * If we have stored the name from getname in the audit context, | ||
1786 | * then we delay the putname until syscall exit. | ||
1787 | * Called from include/linux/fs.h:putname(). | ||
1788 | */ | ||
1789 | void audit_putname(struct filename *name) | ||
1790 | { | ||
1791 | struct audit_context *context = current->audit_context; | ||
1792 | |||
1793 | BUG_ON(!context); | ||
1794 | if (!name->aname || !context->in_syscall) { | ||
1795 | #if AUDIT_DEBUG == 2 | ||
1796 | pr_err("%s:%d(:%d): final_putname(%p)\n", | ||
1797 | __FILE__, __LINE__, context->serial, name); | ||
1798 | if (context->name_count) { | ||
1799 | struct audit_names *n; | ||
1800 | int i = 0; | ||
1801 | |||
1802 | list_for_each_entry(n, &context->names_list, list) | ||
1803 | pr_err("name[%d] = %p = %s\n", i++, n->name, | ||
1804 | n->name->name ?: "(null)"); | ||
1805 | } | ||
1806 | #endif | ||
1807 | final_putname(name); | ||
1808 | } | ||
1809 | #if AUDIT_DEBUG | ||
1810 | else { | ||
1811 | ++context->put_count; | ||
1812 | if (context->put_count > context->name_count) { | ||
1813 | pr_err("%s:%d(:%d): major=%d in_syscall=%d putname(%p)" | ||
1814 | " name_count=%d put_count=%d\n", | ||
1815 | __FILE__, __LINE__, | ||
1816 | context->serial, context->major, | ||
1817 | context->in_syscall, name->name, | ||
1818 | context->name_count, context->put_count); | ||
1819 | dump_stack(); | ||
1820 | } | ||
1821 | } | ||
1822 | #endif | ||
1823 | } | ||
1824 | |||
1825 | /** | 1747 | /** |
1826 | * __audit_inode - store the inode and device from a lookup | 1748 | * __audit_inode - store the inode and device from a lookup |
1827 | * @name: name being audited | 1749 | * @name: name being audited |
@@ -1842,10 +1764,6 @@ void __audit_inode(struct filename *name, const struct dentry *dentry, | |||
1842 | if (!name) | 1764 | if (!name) |
1843 | goto out_alloc; | 1765 | goto out_alloc; |
1844 | 1766 | ||
1845 | #if AUDIT_DEBUG | ||
1846 | /* The struct filename _must_ have a populated ->name */ | ||
1847 | BUG_ON(!name->name); | ||
1848 | #endif | ||
1849 | /* | 1767 | /* |
1850 | * If we have a pointer to an audit_names entry already, then we can | 1768 | * If we have a pointer to an audit_names entry already, then we can |
1851 | * just use it directly if the type is correct. | 1769 | * just use it directly if the type is correct. |
@@ -1863,7 +1781,17 @@ void __audit_inode(struct filename *name, const struct dentry *dentry, | |||
1863 | } | 1781 | } |
1864 | 1782 | ||
1865 | list_for_each_entry_reverse(n, &context->names_list, list) { | 1783 | list_for_each_entry_reverse(n, &context->names_list, list) { |
1866 | if (!n->name || strcmp(n->name->name, name->name)) | 1784 | if (n->ino) { |
1785 | /* valid inode number, use that for the comparison */ | ||
1786 | if (n->ino != inode->i_ino || | ||
1787 | n->dev != inode->i_sb->s_dev) | ||
1788 | continue; | ||
1789 | } else if (n->name) { | ||
1790 | /* inode number has not been set, check the name */ | ||
1791 | if (strcmp(n->name->name, name->name)) | ||
1792 | continue; | ||
1793 | } else | ||
1794 | /* no inode and no name (?!) ... this is odd ... */ | ||
1867 | continue; | 1795 | continue; |
1868 | 1796 | ||
1869 | /* match the correct record type */ | 1797 | /* match the correct record type */ |
@@ -1882,44 +1810,11 @@ out_alloc: | |||
1882 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); | 1810 | n = audit_alloc_name(context, AUDIT_TYPE_UNKNOWN); |
1883 | if (!n) | 1811 | if (!n) |
1884 | return; | 1812 | return; |
1885 | /* unfortunately, while we may have a path name to record with the | ||
1886 | * inode, we can't always rely on the string lasting until the end of | ||
1887 | * the syscall so we need to create our own copy, it may fail due to | ||
1888 | * memory allocation issues, but we do our best */ | ||
1889 | if (name) { | 1813 | if (name) { |
1890 | /* we can't use getname_kernel() due to size limits */ | 1814 | n->name = name; |
1891 | size_t len = strlen(name->name) + 1; | 1815 | name->refcnt++; |
1892 | struct filename *new = __getname(); | ||
1893 | |||
1894 | if (unlikely(!new)) | ||
1895 | goto out; | ||
1896 | |||
1897 | if (len <= (PATH_MAX - sizeof(*new))) { | ||
1898 | new->name = (char *)(new) + sizeof(*new); | ||
1899 | new->separate = false; | ||
1900 | } else if (len <= PATH_MAX) { | ||
1901 | /* this looks odd, but is due to final_putname() */ | ||
1902 | struct filename *new2; | ||
1903 | |||
1904 | new2 = kmalloc(sizeof(*new2), GFP_KERNEL); | ||
1905 | if (unlikely(!new2)) { | ||
1906 | __putname(new); | ||
1907 | goto out; | ||
1908 | } | ||
1909 | new2->name = (char *)new; | ||
1910 | new2->separate = true; | ||
1911 | new = new2; | ||
1912 | } else { | ||
1913 | /* we should never get here, but let's be safe */ | ||
1914 | __putname(new); | ||
1915 | goto out; | ||
1916 | } | ||
1917 | strlcpy((char *)new->name, name->name, len); | ||
1918 | new->uptr = NULL; | ||
1919 | new->aname = n; | ||
1920 | n->name = new; | ||
1921 | n->name_put = true; | ||
1922 | } | 1816 | } |
1817 | |||
1923 | out: | 1818 | out: |
1924 | if (parent) { | 1819 | if (parent) { |
1925 | n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL; | 1820 | n->name_len = n->name ? parent_len(n->name->name) : AUDIT_NAME_FULL; |
@@ -1970,11 +1865,16 @@ void __audit_inode_child(const struct inode *parent, | |||
1970 | 1865 | ||
1971 | /* look for a parent entry first */ | 1866 | /* look for a parent entry first */ |
1972 | list_for_each_entry(n, &context->names_list, list) { | 1867 | list_for_each_entry(n, &context->names_list, list) { |
1973 | if (!n->name || n->type != AUDIT_TYPE_PARENT) | 1868 | if (!n->name || |
1869 | (n->type != AUDIT_TYPE_PARENT && | ||
1870 | n->type != AUDIT_TYPE_UNKNOWN)) | ||
1974 | continue; | 1871 | continue; |
1975 | 1872 | ||
1976 | if (n->ino == parent->i_ino && | 1873 | if (n->ino == parent->i_ino && n->dev == parent->i_sb->s_dev && |
1977 | !audit_compare_dname_path(dname, n->name->name, n->name_len)) { | 1874 | !audit_compare_dname_path(dname, |
1875 | n->name->name, n->name_len)) { | ||
1876 | if (n->type == AUDIT_TYPE_UNKNOWN) | ||
1877 | n->type = AUDIT_TYPE_PARENT; | ||
1978 | found_parent = n; | 1878 | found_parent = n; |
1979 | break; | 1879 | break; |
1980 | } | 1880 | } |
@@ -1983,11 +1883,8 @@ void __audit_inode_child(const struct inode *parent, | |||
1983 | /* is there a matching child entry? */ | 1883 | /* is there a matching child entry? */ |
1984 | list_for_each_entry(n, &context->names_list, list) { | 1884 | list_for_each_entry(n, &context->names_list, list) { |
1985 | /* can only match entries that have a name */ | 1885 | /* can only match entries that have a name */ |
1986 | if (!n->name || n->type != type) | 1886 | if (!n->name || |
1987 | continue; | 1887 | (n->type != type && n->type != AUDIT_TYPE_UNKNOWN)) |
1988 | |||
1989 | /* if we found a parent, make sure this one is a child of it */ | ||
1990 | if (found_parent && (n->name != found_parent->name)) | ||
1991 | continue; | 1888 | continue; |
1992 | 1889 | ||
1993 | if (!strcmp(dname, n->name->name) || | 1890 | if (!strcmp(dname, n->name->name) || |
@@ -1995,6 +1892,8 @@ void __audit_inode_child(const struct inode *parent, | |||
1995 | found_parent ? | 1892 | found_parent ? |
1996 | found_parent->name_len : | 1893 | found_parent->name_len : |
1997 | AUDIT_NAME_FULL)) { | 1894 | AUDIT_NAME_FULL)) { |
1895 | if (n->type == AUDIT_TYPE_UNKNOWN) | ||
1896 | n->type = type; | ||
1998 | found_child = n; | 1897 | found_child = n; |
1999 | break; | 1898 | break; |
2000 | } | 1899 | } |
@@ -2019,10 +1918,10 @@ void __audit_inode_child(const struct inode *parent, | |||
2019 | if (found_parent) { | 1918 | if (found_parent) { |
2020 | found_child->name = found_parent->name; | 1919 | found_child->name = found_parent->name; |
2021 | found_child->name_len = AUDIT_NAME_FULL; | 1920 | found_child->name_len = AUDIT_NAME_FULL; |
2022 | /* don't call __putname() */ | 1921 | found_child->name->refcnt++; |
2023 | found_child->name_put = false; | ||
2024 | } | 1922 | } |
2025 | } | 1923 | } |
1924 | |||
2026 | if (inode) | 1925 | if (inode) |
2027 | audit_copy_inode(found_child, dentry, inode); | 1926 | audit_copy_inode(found_child, dentry, inode); |
2028 | else | 1927 | else |