[Devel] [PATCH RH7 2/4] ms/socketpair(): allocate descriptors first
Vasily Averin
vvs at virtuozzo.com
Wed Dec 2 12:56:24 MSK 2020
From: Al Viro <viro at ZenIV.linux.org.uk>
simplifies failure exits considerably...
Reviewed-by: Eric Dumazet <edumazet at google.com>
Signed-off-by: Al Viro <viro at zeniv.linux.org.uk>
Signed-off-by: David S. Miller <davem at davemloft.net>
(cherry-picked from commit 016a266bdfeda268afb2228b6217fd4771334635)
https://syzkaller.appspot.com/bug?id=23d0799f98b7c8c4bc3f5ecff7c28a87c64e40e8
https://jira.sw.ru/browse/PSBM-123046
Signed-off-by: Vasily Averin <vvs at virtuozzo.com>
---
net/socket.c | 91 ++++++++++++++++++++++++++----------------------------------
1 file changed, 39 insertions(+), 52 deletions(-)
diff --git a/net/socket.c b/net/socket.c
index dd8fa2d..6ea6b18 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1512,87 +1512,74 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
flags = (flags & ~SOCK_NONBLOCK) | O_NONBLOCK;
/*
+ * reserve descriptors and make sure we won't fail
+ * to return them to userland.
+ */
+ fd1 = get_unused_fd_flags(flags);
+ if (unlikely(fd1 < 0))
+ return fd1;
+
+ fd2 = get_unused_fd_flags(flags);
+ if (unlikely(fd2 < 0)) {
+ put_unused_fd(fd1);
+ return fd2;
+ }
+
+ err = put_user(fd1, &usockvec[0]);
+ if (err)
+ goto out;
+
+ err = put_user(fd2, &usockvec[1]);
+ if (err)
+ goto out;
+
+ /*
* Obtain the first socket and check if the underlying protocol
* supports the socketpair call.
*/
err = sock_create(family, type, protocol, &sock1);
- if (err < 0)
+ if (unlikely(err < 0))
goto out;
err = sock_create(family, type, protocol, &sock2);
- if (err < 0)
- goto out_release_1;
+ if (unlikely(err < 0)) {
+ sock_release(sock1);
+ goto out;
+ }
err = sock1->ops->socketpair(sock1, sock2);
- if (err < 0)
- goto out_release_both;
-
- fd1 = get_unused_fd_flags(flags);
- if (unlikely(fd1 < 0)) {
- err = fd1;
- goto out_release_both;
- }
-
- fd2 = get_unused_fd_flags(flags);
- if (unlikely(fd2 < 0)) {
- err = fd2;
- goto out_put_unused_1;
+ if (unlikely(err < 0)) {
+ sock_release(sock2);
+ sock_release(sock1);
+ goto out;
}
newfile1 = sock_alloc_file(sock1, flags, NULL);
if (IS_ERR(newfile1)) {
err = PTR_ERR(newfile1);
- goto out_put_unused_both;
+ sock_release(sock1);
+ sock_release(sock2);
+ goto out;
}
newfile2 = sock_alloc_file(sock2, flags, NULL);
if (IS_ERR(newfile2)) {
err = PTR_ERR(newfile2);
- goto out_fput_1;
+ sock_release(sock2);
+ fput(newfile1);
+ goto out;
}
- err = put_user(fd1, &usockvec[0]);
- if (err)
- goto out_fput_both;
-
- err = put_user(fd2, &usockvec[1]);
- if (err)
- goto out_fput_both;
-
audit_fd_pair(fd1, fd2);
fd_install(fd1, newfile1);
fd_install(fd2, newfile2);
- /* fd1 and fd2 may be already another descriptors.
- * Not kernel problem.
- */
-
return 0;
-out_fput_both:
- fput(newfile2);
- fput(newfile1);
- put_unused_fd(fd2);
- put_unused_fd(fd1);
- goto out;
-
-out_fput_1:
- fput(newfile1);
- put_unused_fd(fd2);
- put_unused_fd(fd1);
- sock_release(sock2);
- goto out;
-
-out_put_unused_both:
- put_unused_fd(fd2);
-out_put_unused_1:
- put_unused_fd(fd1);
-out_release_both:
- sock_release(sock2);
-out_release_1:
- sock_release(sock1);
out:
+ put_unused_fd(fd2);
+ put_unused_fd(fd1);
return err;
}
--
1.8.3.1
More information about the Devel
mailing list