mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
net: preserve socketpair output on setup failure
socketpair() writes the reserved descriptor numbers to userspace before creating the sockets and their file objects. A later failure therefore leaves a modified caller's array despite returning an error, contrary to POSIX. For example, socketpair(AF_UNIX, SOCK_STREAM, -1, fd) returns EPROTONOSUPPORT but replaces the array's sentinel values with unused fd numbers. Defer the output stores until both file objects have been created, before installing either descriptor. If a store faults, drop both file references before releasing the reserved descriptor slots. Keep the early descriptor reservation and the existing setup-failure cleanup paths. In practice, I doubt anyone notices. But this aligns with the expected behavior Signed-off-by: Steve Grubb <sgrubb@redhat.com> Link: https://patch.msgid.link/JyK226D0S5CWGUpAC4MO4A@redhat.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
c5faf1d4df
commit
65734bbe4a
23
net/socket.c
23
net/socket.c
|
|
@ -1851,10 +1851,7 @@ int __sys_socketpair(int family, int type, int protocol, int __user *usockvec)
|
|||
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.
|
||||
*/
|
||||
/* Reserve both descriptors before creating the sockets. */
|
||||
fd1 = get_unused_fd_flags(flags);
|
||||
if (unlikely(fd1 < 0))
|
||||
return fd1;
|
||||
|
|
@ -1865,14 +1862,6 @@ int __sys_socketpair(int family, int type, int protocol, int __user *usockvec)
|
|||
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.
|
||||
|
|
@ -1916,6 +1905,16 @@ int __sys_socketpair(int family, int type, int protocol, int __user *usockvec)
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* Publish the descriptors now that it shouldn't fail. */
|
||||
err = put_user(fd1, &usockvec[0]);
|
||||
if (!err)
|
||||
err = put_user(fd2, &usockvec[1]);
|
||||
if (err) {
|
||||
fput(newfile2);
|
||||
fput(newfile1);
|
||||
goto out;
|
||||
}
|
||||
|
||||
audit_fd_pair(fd1, fd2);
|
||||
|
||||
fd_install(fd1, newfile1);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user