Skip to content

Commit

Permalink
socketpair(): allocate descriptors first
Browse files Browse the repository at this point in the history
simplifies failure exits considerably...

Reviewed-by: Eric Dumazet <[email protected]>
Signed-off-by: Al Viro <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Al Viro authored and davem330 committed Dec 5, 2017
1 parent a573943 commit 016a266
Showing 1 changed file with 38 additions and 51 deletions.
89 changes: 38 additions & 51 deletions net/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -1365,88 +1365,75 @@ SYSCALL_DEFINE4(socketpair, int, family, int, type, int, protocol,
if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK))
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;

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;
if (unlikely(err < 0)) {
sock_release(sock1);
goto out;
}

fd2 = get_unused_fd_flags(flags);
if (unlikely(fd2 < 0)) {
err = fd2;
goto out_put_unused_1;
err = sock1->ops->socketpair(sock1, sock2);
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:
out:
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:
return err;
}

Expand Down

0 comments on commit 016a266

Please sign in to comment.