Cygwin: fix linkat(2) on sockets that are not socket files

If linkat(2) is called with AT_EMPTY_PATH on an AF_LOCAL or
AF_UNIX socket that is not a socket file, the current code calls
fhandler_disk_file::link in most cases.  The latter expects to be
operating on a disk file and uses the socket's io_handle, which
is not a file handle.

Fix this by calling fhandler_disk_file::link only if the
fhandler_socket object is a file (determined by testing
dev().isfs()).

Also fix the case of a socket file opened with O_PATH by setting
the fhandler_disk_file's io_handle.
This commit is contained in:
Ken Brown 2021-02-24 10:43:15 -05:00
parent 012427c96e
commit 425203384a
2 changed files with 12 additions and 4 deletions

View File

@ -750,9 +750,14 @@ fhandler_socket_local::facl (int cmd, int nentries, aclent_t *aclbufp)
int
fhandler_socket_local::link (const char *newpath)
{
if (get_sun_path () && get_sun_path ()[0] == '\0')
if (!dev ().isfs ())
/* linkat w/ AT_EMPTY_PATH called on a socket not opened w/ O_PATH. */
return fhandler_socket_wsock::link (newpath);
/* link on a socket file or linkat w/ AT_EMPTY_PATH called on a
socket opened w/ O_PATH. */
fhandler_disk_file fh (pc);
if (get_flags () & O_PATH)
fh.set_handle (get_handle ());
return fh.link (newpath);
}

View File

@ -2421,11 +2421,14 @@ fhandler_socket_unix::facl (int cmd, int nentries, aclent_t *aclbufp)
int
fhandler_socket_unix::link (const char *newpath)
{
if (sun_path ()
&& (sun_path ()->un_len <= (socklen_t) sizeof (sa_family_t)
|| sun_path ()->un.sun_path[0] == '\0'))
if (!dev ().isfs ())
/* linkat w/ AT_EMPTY_PATH called on a socket not opened w/ O_PATH. */
return fhandler_socket::link (newpath);
/* link on a socket file or linkat w/ AT_EMPTY_PATH called on a
socket opened w/ O_PATH. */
fhandler_disk_file fh (pc);
if (get_flags () & O_PATH)
fh.set_handle (get_handle ());
return fh.link (newpath);
}