diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2009-08-08 16:52:35 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2009-12-16 12:16:42 -0500 |
commit | 2c48b9c45579a9b5e3e74694eebf3d2451f3dbd3 (patch) | |
tree | cecbf786ae0650368a8136bdd90910e05d9b95c3 /net/socket.c | |
parent | a95161aaa801c18c52b2e7cf3d6b4b141c00a20a (diff) |
switch alloc_file() to passing struct path
... and have the caller grab both mnt and dentry; kill
leak in infiniband, while we are at it.
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'net/socket.c')
-rw-r--r-- | net/socket.c | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/net/socket.c b/net/socket.c index eaaba3510e81..dbfdfa96d29b 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -358,7 +358,7 @@ static const struct dentry_operations sockfs_dentry_operations = { | |||
358 | static int sock_alloc_file(struct socket *sock, struct file **f, int flags) | 358 | static int sock_alloc_file(struct socket *sock, struct file **f, int flags) |
359 | { | 359 | { |
360 | struct qstr name = { .name = "" }; | 360 | struct qstr name = { .name = "" }; |
361 | struct dentry *dentry; | 361 | struct path path; |
362 | struct file *file; | 362 | struct file *file; |
363 | int fd; | 363 | int fd; |
364 | 364 | ||
@@ -366,28 +366,29 @@ static int sock_alloc_file(struct socket *sock, struct file **f, int flags) | |||
366 | if (unlikely(fd < 0)) | 366 | if (unlikely(fd < 0)) |
367 | return fd; | 367 | return fd; |
368 | 368 | ||
369 | dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name); | 369 | path.dentry = d_alloc(sock_mnt->mnt_sb->s_root, &name); |
370 | if (unlikely(!dentry)) { | 370 | if (unlikely(!path.dentry)) { |
371 | put_unused_fd(fd); | 371 | put_unused_fd(fd); |
372 | return -ENOMEM; | 372 | return -ENOMEM; |
373 | } | 373 | } |
374 | path.mnt = mntget(sock_mnt); | ||
374 | 375 | ||
375 | dentry->d_op = &sockfs_dentry_operations; | 376 | path.dentry->d_op = &sockfs_dentry_operations; |
376 | /* | 377 | /* |
377 | * We dont want to push this dentry into global dentry hash table. | 378 | * We dont want to push this dentry into global dentry hash table. |
378 | * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED | 379 | * We pretend dentry is already hashed, by unsetting DCACHE_UNHASHED |
379 | * This permits a working /proc/$pid/fd/XXX on sockets | 380 | * This permits a working /proc/$pid/fd/XXX on sockets |
380 | */ | 381 | */ |
381 | dentry->d_flags &= ~DCACHE_UNHASHED; | 382 | path.dentry->d_flags &= ~DCACHE_UNHASHED; |
382 | d_instantiate(dentry, SOCK_INODE(sock)); | 383 | d_instantiate(path.dentry, SOCK_INODE(sock)); |
383 | SOCK_INODE(sock)->i_fop = &socket_file_ops; | 384 | SOCK_INODE(sock)->i_fop = &socket_file_ops; |
384 | 385 | ||
385 | file = alloc_file(sock_mnt, dentry, FMODE_READ | FMODE_WRITE, | 386 | file = alloc_file(&path, FMODE_READ | FMODE_WRITE, |
386 | &socket_file_ops); | 387 | &socket_file_ops); |
387 | if (unlikely(!file)) { | 388 | if (unlikely(!file)) { |
388 | /* drop dentry, keep inode */ | 389 | /* drop dentry, keep inode */ |
389 | atomic_inc(&path.dentry->d_inode->i_count); | 390 | atomic_inc(&path.dentry->d_inode->i_count); |
390 | dput(dentry); | 391 | path_put(&path); |
391 | put_unused_fd(fd); | 392 | put_unused_fd(fd); |
392 | return -ENFILE; | 393 | return -ENFILE; |
393 | } | 394 | } |