Cygwin: improve storage and handling of AF_UNIX socket path

Define new struct sun_name_t and use throughout internally.

Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
Corinna Vinschen 2018-02-28 19:06:41 +01:00
parent 892efccb25
commit a27a7752ec
2 changed files with 77 additions and 29 deletions

View File

@ -12,6 +12,7 @@ details. */
#include "tty.h" #include "tty.h"
#include <cygwin/_socketflags.h> #include <cygwin/_socketflags.h>
#include <cygwin/_ucred.h> #include <cygwin/_ucred.h>
#include <sys/un.h>
/* fcntl flags used only internaly. */ /* fcntl flags used only internaly. */
#define O_NOSYMLINK 0x080000 #define O_NOSYMLINK 0x080000
@ -816,15 +817,31 @@ class fhandler_socket_local: public fhandler_socket_wsock
} }
}; };
struct sun_name_t
{
__socklen_t un_len;
union
{
struct sockaddr_un un;
/* Allows 108 bytes sun_path plus trailing NUL */
char _nul[sizeof (struct sockaddr_un) + 1];
};
};
class fhandler_socket_unix : public fhandler_socket class fhandler_socket_unix : public fhandler_socket
{ {
protected: protected:
char *sun_path; sun_name_t *sun_path;
char *peer_sun_path; sun_name_t *peer_sun_path;
void set_sun_path (const char *path); sun_name_t *get_sun_path () {return sun_path;}
char *get_sun_path () {return sun_path;} sun_name_t *get_peer_sun_path () {return peer_sun_path;}
void set_peer_sun_path (const char *path); void set_sun_path (struct sockaddr_un *un, __socklen_t unlen);
char *get_peer_sun_path () {return peer_sun_path;} void set_sun_path (sun_name_t *snt)
{ snt ? set_sun_path (&snt->un, snt->un_len) : set_sun_path (NULL, 0); }
void set_peer_sun_path (struct sockaddr_un *un, __socklen_t unlen);
void set_peer_sun_path (sun_name_t *snt)
{ snt ? set_peer_sun_path (&snt->un, snt->un_len)
: set_peer_sun_path (NULL, 0); }
protected: protected:
struct ucred peer_cred; struct ucred peer_cred;

View File

@ -164,15 +164,28 @@ fhandler_socket_unix::~fhandler_socket_unix ()
} }
void void
fhandler_socket_unix::set_sun_path (const char *path) fhandler_socket_unix::set_sun_path (struct sockaddr_un *un, socklen_t unlen)
{ {
sun_path = path ? cstrdup (path) : NULL; if (!un)
sun_path = NULL;
sun_path = (struct sun_name_t *) cmalloc_abort (HEAP_FHANDLER,
sizeof *sun_path);
sun_path->un_len = unlen;
memcpy (&sun_path->un, un, sizeof (*un));
sun_path->_nul[sizeof (struct sockaddr_un)] = '\0';
} }
void void
fhandler_socket_unix::set_peer_sun_path (const char *path) fhandler_socket_unix::set_peer_sun_path (struct sockaddr_un *un,
socklen_t unlen)
{ {
peer_sun_path = path ? cstrdup (path) : NULL; if (!un)
peer_sun_path = NULL;
peer_sun_path = (struct sun_name_t *) cmalloc_abort (HEAP_FHANDLER,
sizeof *peer_sun_path);
peer_sun_path->un_len = unlen;
memcpy (&peer_sun_path->un, un, sizeof (*un));
peer_sun_path->_nul[sizeof (struct sockaddr_un)] = '\0';
} }
void void
@ -258,28 +271,34 @@ fhandler_socket_unix::connect (const struct sockaddr *name, int namelen)
int int
fhandler_socket_unix::getsockname (struct sockaddr *name, int *namelen) fhandler_socket_unix::getsockname (struct sockaddr *name, int *namelen)
{ {
struct sockaddr_un sun; sun_name_t sun;
sun.sun_family = AF_UNIX;
sun.sun_path[0] = '\0';
if (get_sun_path ()) if (get_sun_path ())
strncat (sun.sun_path, get_sun_path (), UNIX_PATH_MAX - 1); memcpy (&sun, &get_sun_path ()->un, get_sun_path ()->un_len);
memcpy (name, &sun, MIN (*namelen, (int) SUN_LEN (&sun) + 1)); else
*namelen = (int) SUN_LEN (&sun) + (get_sun_path () ? 1 : 0); {
sun.un_len = sizeof (sa_family_t);
sun.un.sun_family = AF_UNIX;
sun.un.sun_path[0] = '\0';
}
memcpy (name, &sun, MIN (*namelen, sun.un_len));
return 0; return 0;
} }
int int
fhandler_socket_unix::getpeername (struct sockaddr *name, int *namelen) fhandler_socket_unix::getpeername (struct sockaddr *name, int *namelen)
{ {
struct sockaddr_un sun; sun_name_t sun;
memset (&sun, 0, sizeof sun);
sun.sun_family = AF_UNIX;
sun.sun_path[0] = '\0';
if (get_peer_sun_path ()) if (get_peer_sun_path ())
strncat (sun.sun_path, get_peer_sun_path (), UNIX_PATH_MAX - 1); memcpy (&sun, &get_peer_sun_path ()->un, get_peer_sun_path ()->un_len);
memcpy (name, &sun, MIN (*namelen, (int) SUN_LEN (&sun) + 1)); else
*namelen = (int) SUN_LEN (&sun) + (get_peer_sun_path () ? 1 : 0); {
sun.un_len = sizeof (sa_family_t);
sun.un.sun_family = AF_UNIX;
sun.un.sun_path[0] = '\0';
}
memcpy (name, &sun, MIN (*namelen, sun.un_len));
return 0; return 0;
} }
@ -598,7 +617,9 @@ fhandler_socket_unix::fstat (struct stat *buf)
{ {
int ret = 0; int ret = 0;
if (!get_sun_path () || get_sun_path ()[0] == '\0') if (!get_sun_path ()
|| get_sun_path ()->un_len <= (socklen_t) sizeof (sa_family_t)
|| get_sun_path ()->un.sun_path[0] == '\0')
return fhandler_socket::fstat (buf); return fhandler_socket::fstat (buf);
ret = fhandler_base::fstat_fs (buf); ret = fhandler_base::fstat_fs (buf);
if (!ret) if (!ret)
@ -612,7 +633,9 @@ fhandler_socket_unix::fstat (struct stat *buf)
int __reg2 int __reg2
fhandler_socket_unix::fstatvfs (struct statvfs *sfs) fhandler_socket_unix::fstatvfs (struct statvfs *sfs)
{ {
if (!get_sun_path () || get_sun_path ()[0] == '\0') if (!get_sun_path ()
|| get_sun_path ()->un_len <= (socklen_t) sizeof (sa_family_t)
|| get_sun_path ()->un.sun_path[0] == '\0')
return fhandler_socket::fstatvfs (sfs); return fhandler_socket::fstatvfs (sfs);
fhandler_disk_file fh (pc); fhandler_disk_file fh (pc);
fh.get_device () = FH_FS; fh.get_device () = FH_FS;
@ -622,7 +645,9 @@ fhandler_socket_unix::fstatvfs (struct statvfs *sfs)
int int
fhandler_socket_unix::fchmod (mode_t newmode) fhandler_socket_unix::fchmod (mode_t newmode)
{ {
if (!get_sun_path () || get_sun_path ()[0] == '\0') if (!get_sun_path ()
|| get_sun_path ()->un_len <= (socklen_t) sizeof (sa_family_t)
|| get_sun_path ()->un.sun_path[0] == '\0')
return fhandler_socket::fchmod (newmode); return fhandler_socket::fchmod (newmode);
fhandler_disk_file fh (pc); fhandler_disk_file fh (pc);
fh.get_device () = FH_FS; fh.get_device () = FH_FS;
@ -639,7 +664,9 @@ fhandler_socket_unix::fchmod (mode_t newmode)
int int
fhandler_socket_unix::fchown (uid_t uid, gid_t gid) fhandler_socket_unix::fchown (uid_t uid, gid_t gid)
{ {
if (!get_sun_path () || get_sun_path ()[0] == '\0') if (!get_sun_path ()
|| get_sun_path ()->un_len <= (socklen_t) sizeof (sa_family_t)
|| get_sun_path ()->un.sun_path[0] == '\0')
return fhandler_socket::fchown (uid, gid); return fhandler_socket::fchown (uid, gid);
fhandler_disk_file fh (pc); fhandler_disk_file fh (pc);
return fh.fchown (uid, gid); return fh.fchown (uid, gid);
@ -648,7 +675,9 @@ fhandler_socket_unix::fchown (uid_t uid, gid_t gid)
int int
fhandler_socket_unix::facl (int cmd, int nentries, aclent_t *aclbufp) fhandler_socket_unix::facl (int cmd, int nentries, aclent_t *aclbufp)
{ {
if (!get_sun_path () || get_sun_path ()[0] == '\0') if (!get_sun_path ()
|| get_sun_path ()->un_len <= (socklen_t) sizeof (sa_family_t)
|| get_sun_path ()->un.sun_path[0] == '\0')
return fhandler_socket::facl (cmd, nentries, aclbufp); return fhandler_socket::facl (cmd, nentries, aclbufp);
fhandler_disk_file fh (pc); fhandler_disk_file fh (pc);
return fh.facl (cmd, nentries, aclbufp); return fh.facl (cmd, nentries, aclbufp);
@ -657,7 +686,9 @@ fhandler_socket_unix::facl (int cmd, int nentries, aclent_t *aclbufp)
int int
fhandler_socket_unix::link (const char *newpath) fhandler_socket_unix::link (const char *newpath)
{ {
if (!get_sun_path () || get_sun_path ()[0] == '\0') if (!get_sun_path ()
|| get_sun_path ()->un_len <= (socklen_t) sizeof (sa_family_t)
|| get_sun_path ()->un.sun_path[0] == '\0')
return fhandler_socket::link (newpath); return fhandler_socket::link (newpath);
fhandler_disk_file fh (pc); fhandler_disk_file fh (pc);
return fh.link (newpath); return fh.link (newpath);