diff options
author | Al Viro <viro@ZenIV.linux.org.uk> | 2017-12-05 18:29:09 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-12-05 18:39:29 -0500 |
commit | 8e1611e2357927b22892ecc062d65c99d0d89066 (patch) | |
tree | e96c21ce49a9bb3225e8334f87a64dcd14162a75 | |
parent | 016a266bdfeda268afb2228b6217fd4771334635 (diff) |
make sock_alloc_file() do sock_release() on failures
This changes calling conventions (and simplifies the hell out
the callers). New rules: once struct socket had been passed
to sock_alloc_file(), it's been consumed either by struct file
or by sock_release() done by sock_alloc_file(). Either way
the caller should not do sock_release() after that point.
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/staging/lustre/lnet/lnet/lib-socket.c | 8 | ||||
-rw-r--r-- | net/9p/trans_fd.c | 1 | ||||
-rw-r--r-- | net/kcm/kcmsock.c | 7 | ||||
-rw-r--r-- | net/sctp/socket.c | 1 | ||||
-rw-r--r-- | net/socket.c | 25 |
5 files changed, 11 insertions, 31 deletions
diff --git a/drivers/staging/lustre/lnet/lnet/lib-socket.c b/drivers/staging/lustre/lnet/lnet/lib-socket.c index 539a26444f31..7d49d4865298 100644 --- a/drivers/staging/lustre/lnet/lnet/lib-socket.c +++ b/drivers/staging/lustre/lnet/lnet/lib-socket.c | |||
@@ -71,16 +71,12 @@ lnet_sock_ioctl(int cmd, unsigned long arg) | |||
71 | } | 71 | } |
72 | 72 | ||
73 | sock_filp = sock_alloc_file(sock, 0, NULL); | 73 | sock_filp = sock_alloc_file(sock, 0, NULL); |
74 | if (IS_ERR(sock_filp)) { | 74 | if (IS_ERR(sock_filp)) |
75 | sock_release(sock); | 75 | return PTR_ERR(sock_filp); |
76 | rc = PTR_ERR(sock_filp); | ||
77 | goto out; | ||
78 | } | ||
79 | 76 | ||
80 | rc = kernel_sock_unlocked_ioctl(sock_filp, cmd, arg); | 77 | rc = kernel_sock_unlocked_ioctl(sock_filp, cmd, arg); |
81 | 78 | ||
82 | fput(sock_filp); | 79 | fput(sock_filp); |
83 | out: | ||
84 | return rc; | 80 | return rc; |
85 | } | 81 | } |
86 | 82 | ||
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index 985046ae4231..80f5c79053a4 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c | |||
@@ -839,7 +839,6 @@ static int p9_socket_open(struct p9_client *client, struct socket *csocket) | |||
839 | if (IS_ERR(file)) { | 839 | if (IS_ERR(file)) { |
840 | pr_err("%s (%d): failed to map fd\n", | 840 | pr_err("%s (%d): failed to map fd\n", |
841 | __func__, task_pid_nr(current)); | 841 | __func__, task_pid_nr(current)); |
842 | sock_release(csocket); | ||
843 | kfree(p); | 842 | kfree(p); |
844 | return PTR_ERR(file); | 843 | return PTR_ERR(file); |
845 | } | 844 | } |
diff --git a/net/kcm/kcmsock.c b/net/kcm/kcmsock.c index c5fa634e63ca..d4e98f20fc2a 100644 --- a/net/kcm/kcmsock.c +++ b/net/kcm/kcmsock.c | |||
@@ -1629,7 +1629,6 @@ static struct file *kcm_clone(struct socket *osock) | |||
1629 | { | 1629 | { |
1630 | struct socket *newsock; | 1630 | struct socket *newsock; |
1631 | struct sock *newsk; | 1631 | struct sock *newsk; |
1632 | struct file *file; | ||
1633 | 1632 | ||
1634 | newsock = sock_alloc(); | 1633 | newsock = sock_alloc(); |
1635 | if (!newsock) | 1634 | if (!newsock) |
@@ -1649,11 +1648,7 @@ static struct file *kcm_clone(struct socket *osock) | |||
1649 | sock_init_data(newsock, newsk); | 1648 | sock_init_data(newsock, newsk); |
1650 | init_kcm_sock(kcm_sk(newsk), kcm_sk(osock->sk)->mux); | 1649 | init_kcm_sock(kcm_sk(newsk), kcm_sk(osock->sk)->mux); |
1651 | 1650 | ||
1652 | file = sock_alloc_file(newsock, 0, osock->sk->sk_prot_creator->name); | 1651 | return sock_alloc_file(newsock, 0, osock->sk->sk_prot_creator->name); |
1653 | if (IS_ERR(file)) | ||
1654 | sock_release(newsock); | ||
1655 | |||
1656 | return file; | ||
1657 | } | 1652 | } |
1658 | 1653 | ||
1659 | static int kcm_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | 1654 | static int kcm_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 014847e25648..eb17a911aa29 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -5080,7 +5080,6 @@ static int sctp_getsockopt_peeloff_common(struct sock *sk, sctp_peeloff_arg_t *p | |||
5080 | *newfile = sock_alloc_file(newsock, 0, NULL); | 5080 | *newfile = sock_alloc_file(newsock, 0, NULL); |
5081 | if (IS_ERR(*newfile)) { | 5081 | if (IS_ERR(*newfile)) { |
5082 | put_unused_fd(retval); | 5082 | put_unused_fd(retval); |
5083 | sock_release(newsock); | ||
5084 | retval = PTR_ERR(*newfile); | 5083 | retval = PTR_ERR(*newfile); |
5085 | *newfile = NULL; | 5084 | *newfile = NULL; |
5086 | return retval; | 5085 | return retval; |
diff --git a/net/socket.c b/net/socket.c index 2df83c0bfde9..05f361faec45 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -406,8 +406,10 @@ struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) | |||
406 | name.len = strlen(name.name); | 406 | name.len = strlen(name.name); |
407 | } | 407 | } |
408 | path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name); | 408 | path.dentry = d_alloc_pseudo(sock_mnt->mnt_sb, &name); |
409 | if (unlikely(!path.dentry)) | 409 | if (unlikely(!path.dentry)) { |
410 | sock_release(sock); | ||
410 | return ERR_PTR(-ENOMEM); | 411 | return ERR_PTR(-ENOMEM); |
412 | } | ||
411 | path.mnt = mntget(sock_mnt); | 413 | path.mnt = mntget(sock_mnt); |
412 | 414 | ||
413 | d_instantiate(path.dentry, SOCK_INODE(sock)); | 415 | d_instantiate(path.dentry, SOCK_INODE(sock)); |
@@ -415,9 +417,11 @@ struct file *sock_alloc_file(struct socket *sock, int flags, const char *dname) | |||
415 | file = alloc_file(&path, FMODE_READ | FMODE_WRITE, | 417 | file = alloc_file(&path, FMODE_READ | FMODE_WRITE, |
416 | &socket_file_ops); | 418 | &socket_file_ops); |
417 | if (IS_ERR(file)) { | 419 | if (IS_ERR(file)) { |
418 | /* drop dentry, keep inode */ | 420 | /* drop dentry, keep inode for a bit */ |
419 | ihold(d_inode(path.dentry)); | 421 | ihold(d_inode(path.dentry)); |
420 | path_put(&path); | 422 | path_put(&path); |
423 | /* ... and now kill it properly */ | ||
424 | sock_release(sock); | ||
421 | return file; | 425 | return file; |
422 | } | 426 | } |
423 | 427 | ||
@@ -1330,19 +1334,9 @@ SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) | |||
1330 | 1334 | ||
1331 | retval = sock_create(family, type, protocol, &sock); | 1335 | retval = sock_create(family, type, protocol, &sock); |
1332 | if (retval < 0) | 1336 | if (retval < 0) |
1333 | goto out; | 1337 | return retval; |
1334 | |||
1335 | retval = sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); | ||
1336 | if (retval < 0) | ||
1337 | goto out_release; | ||
1338 | |||
1339 | out: | ||
1340 | /* It may be already another descriptor 8) Not kernel problem. */ | ||
1341 | return retval; | ||
1342 | 1338 | ||
1343 | out_release: | 1339 | return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); |
1344 | sock_release(sock); | ||
1345 | return retval; | ||
1346 | } | 1340 | } |
1347 | 1341 | ||
1348 | /* | 1342 | /* |
@@ -1412,7 +1406,6 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, | |||
1412 | newfile1 = sock_alloc_file(sock1, flags, NULL); | 1406 | newfile1 = sock_alloc_file(sock1, flags, NULL); |
1413 | if (IS_ERR(newfile1)) { | 1407 | if (IS_ERR(newfile1)) { |
1414 | err = PTR_ERR(newfile1); | 1408 | err = PTR_ERR(newfile1); |
1415 | sock_release(sock1); | ||
1416 | sock_release(sock2); | 1409 | sock_release(sock2); |
1417 | goto out; | 1410 | goto out; |
1418 | } | 1411 | } |
@@ -1420,7 +1413,6 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol, | |||
1420 | newfile2 = sock_alloc_file(sock2, flags, NULL); | 1413 | newfile2 = sock_alloc_file(sock2, flags, NULL); |
1421 | if (IS_ERR(newfile2)) { | 1414 | if (IS_ERR(newfile2)) { |
1422 | err = PTR_ERR(newfile2); | 1415 | err = PTR_ERR(newfile2); |
1423 | sock_release(sock2); | ||
1424 | fput(newfile1); | 1416 | fput(newfile1); |
1425 | goto out; | 1417 | goto out; |
1426 | } | 1418 | } |
@@ -1549,7 +1541,6 @@ SYSCALL_DEFINE4(accept4, int, fd, struct sockaddr __user *, upeer_sockaddr, | |||
1549 | if (IS_ERR(newfile)) { | 1541 | if (IS_ERR(newfile)) { |
1550 | err = PTR_ERR(newfile); | 1542 | err = PTR_ERR(newfile); |
1551 | put_unused_fd(newfd); | 1543 | put_unused_fd(newfd); |
1552 | sock_release(newsock); | ||
1553 | goto out_put; | 1544 | goto out_put; |
1554 | } | 1545 | } |
1555 | 1546 | ||