aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAl Viro <viro@ZenIV.linux.org.uk>2017-12-05 18:29:09 -0500
committerDavid S. Miller <davem@davemloft.net>2017-12-05 18:39:29 -0500
commit8e1611e2357927b22892ecc062d65c99d0d89066 (patch)
treee96c21ce49a9bb3225e8334f87a64dcd14162a75
parent016a266bdfeda268afb2228b6217fd4771334635 (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.c8
-rw-r--r--net/9p/trans_fd.c1
-rw-r--r--net/kcm/kcmsock.c7
-rw-r--r--net/sctp/socket.c1
-rw-r--r--net/socket.c25
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);
83out:
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
1659static int kcm_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) 1654static 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
1339out:
1340 /* It may be already another descriptor 8) Not kernel problem. */
1341 return retval;
1342 1338
1343out_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