* fhandler_socket.cc (get_inet_addr): Rearrange for better readability.
Make waiting loop interruptible and cancelable. Check for SYSTEM DOS flag before reading the file. Change return value to return 0 on success, SOCKET_ERROR on failure. (fhandler_socket::bind): Only set R/O DOS flag on filesystems not supporting ACLs. (fhandler_socket::connect): Accommodate changed return values from get_inet_addr. Use SOCKET_ERROR instead of -1. (fhandler_socket::sendto): Accommodate changed return values from get_inet_addr. * syslog.cc (connect_syslogd): Ditto.
This commit is contained in:
parent
3bcc74a9ae
commit
933d2af50d
|
@ -1,3 +1,17 @@
|
||||||
|
2011-05-11 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* fhandler_socket.cc (get_inet_addr): Rearrange for better readability.
|
||||||
|
Make waiting loop interruptible and cancelable. Check for SYSTEM DOS
|
||||||
|
flag before reading the file. Change return value to return 0 on
|
||||||
|
success, SOCKET_ERROR on failure.
|
||||||
|
(fhandler_socket::bind): Only set R/O DOS flag on filesystems not
|
||||||
|
supporting ACLs.
|
||||||
|
(fhandler_socket::connect): Accommodate changed return values from
|
||||||
|
get_inet_addr. Use SOCKET_ERROR instead of -1.
|
||||||
|
(fhandler_socket::sendto): Accommodate changed return values from
|
||||||
|
get_inet_addr.
|
||||||
|
* syslog.cc (connect_syslogd): Ditto.
|
||||||
|
|
||||||
2011-05-10 Christian Franke <franke@computer.org>
|
2011-05-10 Christian Franke <franke@computer.org>
|
||||||
|
|
||||||
* security.cc (check_registry_access): Handle missing
|
* security.cc (check_registry_access): Handle missing
|
||||||
|
|
|
@ -71,95 +71,123 @@ get_inet_addr (const struct sockaddr *in, int inlen,
|
||||||
int secret_buf [4];
|
int secret_buf [4];
|
||||||
int* secret_ptr = (secret ? : secret_buf);
|
int* secret_ptr = (secret ? : secret_buf);
|
||||||
|
|
||||||
if (in->sa_family == AF_INET || in->sa_family == AF_INET6)
|
switch (in->sa_family)
|
||||||
{
|
{
|
||||||
|
case AF_LOCAL:
|
||||||
|
break;
|
||||||
|
case AF_INET:
|
||||||
|
case AF_INET6:
|
||||||
memcpy (out, in, inlen);
|
memcpy (out, in, inlen);
|
||||||
*outlen = inlen;
|
*outlen = inlen;
|
||||||
return 1;
|
return 0;
|
||||||
}
|
default:
|
||||||
else if (in->sa_family == AF_LOCAL)
|
|
||||||
{
|
|
||||||
NTSTATUS status;
|
|
||||||
HANDLE fh;
|
|
||||||
OBJECT_ATTRIBUTES attr;
|
|
||||||
IO_STATUS_BLOCK io;
|
|
||||||
|
|
||||||
path_conv pc (in->sa_data, PC_SYM_FOLLOW);
|
|
||||||
if (pc.error)
|
|
||||||
{
|
|
||||||
set_errno (pc.error);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (!pc.exists ())
|
|
||||||
{
|
|
||||||
set_errno (ENOENT);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
/* Do NOT test for the file being a socket file here. The socket file
|
|
||||||
creation is not an atomic operation, so there is a chance that socket
|
|
||||||
files which are just in the process of being created are recognized
|
|
||||||
as non-socket files. To work around this problem we now create the
|
|
||||||
file with all sharing disabled. If the below NtOpenFile fails
|
|
||||||
with STATUS_SHARING_VIOLATION we know that the file already exists,
|
|
||||||
but the creating process isn't finished yet. So we yield and try
|
|
||||||
again, until we can either open the file successfully, or some error
|
|
||||||
other than STATUS_SHARING_VIOLATION occurs.
|
|
||||||
Since we now don't know if the file is actually a socket file, we
|
|
||||||
perform this check here explicitely. */
|
|
||||||
pc.get_object_attr (attr, sec_none_nih);
|
|
||||||
do
|
|
||||||
{
|
|
||||||
status = NtOpenFile (&fh, GENERIC_READ | SYNCHRONIZE, &attr, &io,
|
|
||||||
FILE_SHARE_VALID_FLAGS,
|
|
||||||
FILE_SYNCHRONOUS_IO_NONALERT
|
|
||||||
| FILE_OPEN_FOR_BACKUP_INTENT);
|
|
||||||
if (status == STATUS_SHARING_VIOLATION)
|
|
||||||
yield ();
|
|
||||||
else if (!NT_SUCCESS (status))
|
|
||||||
{
|
|
||||||
__seterrno_from_nt_status (status);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (status == STATUS_SHARING_VIOLATION);
|
|
||||||
int ret = 0;
|
|
||||||
char buf[128];
|
|
||||||
memset (buf, 0, sizeof buf);
|
|
||||||
status = NtReadFile (fh, NULL, NULL, NULL, &io, buf, 128, NULL, NULL);
|
|
||||||
NtClose (fh);
|
|
||||||
if (NT_SUCCESS (status))
|
|
||||||
{
|
|
||||||
struct sockaddr_in sin;
|
|
||||||
char ctype;
|
|
||||||
sin.sin_family = AF_INET;
|
|
||||||
if (strncmp (buf, SOCKET_COOKIE, strlen (SOCKET_COOKIE)))
|
|
||||||
{
|
|
||||||
set_errno (EBADF);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
sscanf (buf + strlen (SOCKET_COOKIE), "%hu %c %08x-%08x-%08x-%08x",
|
|
||||||
&sin.sin_port,
|
|
||||||
&ctype,
|
|
||||||
secret_ptr, secret_ptr + 1, secret_ptr + 2, secret_ptr + 3);
|
|
||||||
sin.sin_port = htons (sin.sin_port);
|
|
||||||
sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
|
||||||
memcpy (out, &sin, sizeof sin);
|
|
||||||
*outlen = sizeof sin;
|
|
||||||
if (type)
|
|
||||||
*type = (ctype == 's' ? SOCK_STREAM :
|
|
||||||
ctype == 'd' ? SOCK_DGRAM
|
|
||||||
: 0);
|
|
||||||
ret = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
__seterrno_from_nt_status (status);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
set_errno (EAFNOSUPPORT);
|
set_errno (EAFNOSUPPORT);
|
||||||
|
return SOCKET_ERROR;
|
||||||
|
}
|
||||||
|
/* AF_LOCAL/AF_UNIX only */
|
||||||
|
path_conv pc (in->sa_data, PC_SYM_FOLLOW);
|
||||||
|
if (pc.error)
|
||||||
|
{
|
||||||
|
set_errno (pc.error);
|
||||||
|
return SOCKET_ERROR;
|
||||||
|
}
|
||||||
|
if (!pc.exists ())
|
||||||
|
{
|
||||||
|
set_errno (ENOENT);
|
||||||
|
return SOCKET_ERROR;
|
||||||
|
}
|
||||||
|
/* Do NOT test for the file being a socket file here. The socket file
|
||||||
|
creation is not an atomic operation, so there is a chance that socket
|
||||||
|
files which are just in the process of being created are recognized
|
||||||
|
as non-socket files. To work around this problem we now create the
|
||||||
|
file with all sharing disabled. If the below NtOpenFile fails
|
||||||
|
with STATUS_SHARING_VIOLATION we know that the file already exists,
|
||||||
|
but the creating process isn't finished yet. So we yield and try
|
||||||
|
again, until we can either open the file successfully, or some error
|
||||||
|
other than STATUS_SHARING_VIOLATION occurs.
|
||||||
|
Since we now don't know if the file is actually a socket file, we
|
||||||
|
perform this check here explicitely. */
|
||||||
|
NTSTATUS status;
|
||||||
|
HANDLE fh;
|
||||||
|
OBJECT_ATTRIBUTES attr;
|
||||||
|
IO_STATUS_BLOCK io;
|
||||||
|
|
||||||
|
pc.get_object_attr (attr, sec_none_nih);
|
||||||
|
do
|
||||||
|
{
|
||||||
|
status = NtOpenFile (&fh, GENERIC_READ | SYNCHRONIZE, &attr, &io,
|
||||||
|
FILE_SHARE_VALID_FLAGS,
|
||||||
|
FILE_SYNCHRONOUS_IO_NONALERT
|
||||||
|
| FILE_OPEN_FOR_BACKUP_INTENT
|
||||||
|
| FILE_NON_DIRECTORY_FILE);
|
||||||
|
if (status == STATUS_SHARING_VIOLATION)
|
||||||
|
{
|
||||||
|
/* While we hope that the sharing violation is only temporary, we
|
||||||
|
also could easily get stuck here, waiting for a file in use by
|
||||||
|
some greedy Win32 application. Therefore we should never wait
|
||||||
|
endlessly without checking for signals and thread cancel event. */
|
||||||
|
pthread_testcancel ();
|
||||||
|
if (IsEventSignalled (signal_arrived)
|
||||||
|
&& !_my_tls.call_signal_handler ())
|
||||||
|
{
|
||||||
|
set_errno (EINTR);
|
||||||
|
return SOCKET_ERROR;
|
||||||
|
}
|
||||||
|
yield ();
|
||||||
|
}
|
||||||
|
else if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
__seterrno_from_nt_status (status);
|
||||||
|
return SOCKET_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (status == STATUS_SHARING_VIOLATION);
|
||||||
|
/* Now test for the SYSTEM bit. */
|
||||||
|
FILE_BASIC_INFORMATION fbi;
|
||||||
|
status = NtQueryInformationFile (fh, &io, &fbi, sizeof fbi,
|
||||||
|
FileBasicInformation);
|
||||||
|
if (!NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
__seterrno_from_nt_status (status);
|
||||||
|
return SOCKET_ERROR;
|
||||||
|
}
|
||||||
|
if (!(fbi.FileAttributes & FILE_ATTRIBUTE_SYSTEM))
|
||||||
|
{
|
||||||
|
NtClose (fh);
|
||||||
|
set_errno (EBADF);
|
||||||
|
return SOCKET_ERROR;
|
||||||
|
}
|
||||||
|
/* Eventually check the content and fetch the required information. */
|
||||||
|
char buf[128];
|
||||||
|
memset (buf, 0, sizeof buf);
|
||||||
|
status = NtReadFile (fh, NULL, NULL, NULL, &io, buf, 128, NULL, NULL);
|
||||||
|
NtClose (fh);
|
||||||
|
if (NT_SUCCESS (status))
|
||||||
|
{
|
||||||
|
struct sockaddr_in sin;
|
||||||
|
char ctype;
|
||||||
|
sin.sin_family = AF_INET;
|
||||||
|
if (strncmp (buf, SOCKET_COOKIE, strlen (SOCKET_COOKIE)))
|
||||||
|
{
|
||||||
|
set_errno (EBADF);
|
||||||
|
return SOCKET_ERROR;
|
||||||
|
}
|
||||||
|
sscanf (buf + strlen (SOCKET_COOKIE), "%hu %c %08x-%08x-%08x-%08x",
|
||||||
|
&sin.sin_port,
|
||||||
|
&ctype,
|
||||||
|
secret_ptr, secret_ptr + 1, secret_ptr + 2, secret_ptr + 3);
|
||||||
|
sin.sin_port = htons (sin.sin_port);
|
||||||
|
sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
|
||||||
|
memcpy (out, &sin, sizeof sin);
|
||||||
|
*outlen = sizeof sin;
|
||||||
|
if (type)
|
||||||
|
*type = (ctype == 's' ? SOCK_STREAM :
|
||||||
|
ctype == 'd' ? SOCK_DGRAM
|
||||||
|
: 0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
__seterrno_from_nt_status (status);
|
||||||
|
return SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************/
|
/**********************************************************************/
|
||||||
|
@ -930,7 +958,7 @@ fhandler_socket::bind (const struct sockaddr *name, int namelen)
|
||||||
mode_t mode = adjust_socket_file_mode ((S_IRWXU | S_IRWXG | S_IRWXO)
|
mode_t mode = adjust_socket_file_mode ((S_IRWXU | S_IRWXG | S_IRWXO)
|
||||||
& ~cygheap->umask);
|
& ~cygheap->umask);
|
||||||
DWORD fattr = FILE_ATTRIBUTE_SYSTEM;
|
DWORD fattr = FILE_ATTRIBUTE_SYSTEM;
|
||||||
if (!(mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
|
if (!(mode & (S_IWUSR | S_IWGRP | S_IWOTH)) && !pc.has_acls ())
|
||||||
fattr |= FILE_ATTRIBUTE_READONLY;
|
fattr |= FILE_ATTRIBUTE_READONLY;
|
||||||
SECURITY_ATTRIBUTES sa = sec_none_nih;
|
SECURITY_ATTRIBUTES sa = sec_none_nih;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
|
@ -1020,7 +1048,6 @@ out:
|
||||||
int
|
int
|
||||||
fhandler_socket::connect (const struct sockaddr *name, int namelen)
|
fhandler_socket::connect (const struct sockaddr *name, int namelen)
|
||||||
{
|
{
|
||||||
int res = -1;
|
|
||||||
bool in_progress = false;
|
bool in_progress = false;
|
||||||
struct sockaddr_storage sst;
|
struct sockaddr_storage sst;
|
||||||
DWORD err;
|
DWORD err;
|
||||||
|
@ -1028,17 +1055,18 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen)
|
||||||
|
|
||||||
pthread_testcancel ();
|
pthread_testcancel ();
|
||||||
|
|
||||||
if (!get_inet_addr (name, namelen, &sst, &namelen, &type, connect_secret))
|
if (get_inet_addr (name, namelen, &sst, &namelen, &type, connect_secret)
|
||||||
return -1;
|
== SOCKET_ERROR)
|
||||||
|
return SOCKET_ERROR;
|
||||||
|
|
||||||
if (get_addr_family () == AF_LOCAL && get_socket_type () != type)
|
if (get_addr_family () == AF_LOCAL && get_socket_type () != type)
|
||||||
{
|
{
|
||||||
WSASetLastError (WSAEPROTOTYPE);
|
WSASetLastError (WSAEPROTOTYPE);
|
||||||
set_winsock_errno ();
|
set_winsock_errno ();
|
||||||
return -1;
|
return SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = ::connect (get_socket (), (struct sockaddr *) &sst, namelen);
|
int res = ::connect (get_socket (), (struct sockaddr *) &sst, namelen);
|
||||||
if (!is_nonblocking ()
|
if (!is_nonblocking ()
|
||||||
&& res == SOCKET_ERROR
|
&& res == SOCKET_ERROR
|
||||||
&& WSAGetLastError () == WSAEWOULDBLOCK)
|
&& WSAGetLastError () == WSAEWOULDBLOCK)
|
||||||
|
@ -1075,7 +1103,7 @@ fhandler_socket::connect (const struct sockaddr *name, int namelen)
|
||||||
if (!res && af_local_connect ())
|
if (!res && af_local_connect ())
|
||||||
{
|
{
|
||||||
set_winsock_errno ();
|
set_winsock_errno ();
|
||||||
return -1;
|
return SOCKET_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1652,7 +1680,7 @@ fhandler_socket::sendto (const void *ptr, size_t len, int flags,
|
||||||
|
|
||||||
pthread_testcancel ();
|
pthread_testcancel ();
|
||||||
|
|
||||||
if (to && !get_inet_addr (to, tolen, &sst, &tolen))
|
if (to && get_inet_addr (to, tolen, &sst, &tolen) == SOCKET_ERROR)
|
||||||
return SOCKET_ERROR;
|
return SOCKET_ERROR;
|
||||||
|
|
||||||
WSABUF wsabuf = { len, (char *) ptr };
|
WSABUF wsabuf = { len, (char *) ptr };
|
||||||
|
|
|
@ -206,7 +206,7 @@ connect_syslogd ()
|
||||||
syslogd_sock = -1;
|
syslogd_sock = -1;
|
||||||
sun.sun_family = AF_LOCAL;
|
sun.sun_family = AF_LOCAL;
|
||||||
strncpy (sun.sun_path, _PATH_LOG, sizeof sun.sun_path);
|
strncpy (sun.sun_path, _PATH_LOG, sizeof sun.sun_path);
|
||||||
if (!get_inet_addr ((struct sockaddr *) &sun, sizeof sun, &sst, &len, &type))
|
if (get_inet_addr ((struct sockaddr *) &sun, sizeof sun, &sst, &len, &type))
|
||||||
return;
|
return;
|
||||||
if ((fd = cygwin_socket (AF_LOCAL, type, 0)) < 0)
|
if ((fd = cygwin_socket (AF_LOCAL, type, 0)) < 0)
|
||||||
return;
|
return;
|
||||||
|
|
Loading…
Reference in New Issue