aboutsummaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2003-02-21 14:29:18 +0000
committerCorinna Vinschen <corinna@vinschen.de>2003-02-21 14:29:18 +0000
commitcf762b08cfb010d9d63e4ca44658c80bdf6ed8cb (patch)
tree18f96c59a7ee7b81b288251ebf493e5bd0e62637 /winsup
parentd05ef21d4f7e409472361b98945099485052efc0 (diff)
downloadnewlib-cf762b08cfb010d9d63e4ca44658c80bdf6ed8cb.zip
newlib-cf762b08cfb010d9d63e4ca44658c80bdf6ed8cb.tar.gz
newlib-cf762b08cfb010d9d63e4ca44658c80bdf6ed8cb.tar.bz2
* dtable.cc (dtable::build_fhandler_from_name): Set some fhandler
data on sockets to evaluate AF_LOCAL sockets correctly. (dtable::build_fhandler): Set unit number on sockets. * fhandler.h (fhandler_socket): Add unit number. (fhandler_socket::get_unit): New method. * fhandler_socket.cc (fhandler_socket::fhandler_socket): Set unit number. (fhandler_socket::fstat): Reorganize to return more Linux-like values. * net.cc: include ctype.h. (fdsock): Set unit number when building fhandler. * path.cc (path_conv::check): Set device type to FH_SOCKET if file is a AF_UNIX socket. (get_devn): Evaluate unit for virtual socket devices. (win32_device_name): Set windows path for sockets to unix_path with just backslashes to keep the different names. * syscalls.cc (fstat64): Don't override st_ino, st_dev and st_rdev for sockets. (stat_worker): Ditto. From Pierre Humblet: * autoload.cc (AccessCheck): Add. (DuplicateToken): Add. * security.h (check_file_access): Declare. * syscalls.cc (access): Convert path to Windows, check existence and readonly attribute. Call check_file_access instead of acl_access. * security.cc (check_file_access): Create. * sec_acl (acl_access): Delete.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog32
-rw-r--r--winsup/cygwin/autoload.cc2
-rw-r--r--winsup/cygwin/dtable.cc12
-rw-r--r--winsup/cygwin/fhandler.h4
-rw-r--r--winsup/cygwin/fhandler_socket.cc47
-rw-r--r--winsup/cygwin/net.cc6
-rw-r--r--winsup/cygwin/path.cc13
-rw-r--r--winsup/cygwin/sec_acl.cc63
-rw-r--r--winsup/cygwin/security.cc51
-rw-r--r--winsup/cygwin/security.h1
-rw-r--r--winsup/cygwin/syscalls.cc34
11 files changed, 180 insertions, 85 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index b05cdc4..ab1c240 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,35 @@
+2003-02-21 Corinna Vinschen <corinna@vinschen.de>
+
+ * dtable.cc (dtable::build_fhandler_from_name): Set some fhandler
+ data on sockets to evaluate AF_LOCAL sockets correctly.
+ (dtable::build_fhandler): Set unit number on sockets.
+ * fhandler.h (fhandler_socket): Add unit number.
+ (fhandler_socket::get_unit): New method.
+ * fhandler_socket.cc (fhandler_socket::fhandler_socket): Set unit
+ number.
+ (fhandler_socket::fstat): Reorganize to return more Linux-like
+ values.
+ * net.cc: include ctype.h.
+ (fdsock): Set unit number when building fhandler.
+ * path.cc (path_conv::check): Set device type to FH_SOCKET if file
+ is a AF_UNIX socket.
+ (get_devn): Evaluate unit for virtual socket devices.
+ (win32_device_name): Set windows path for sockets to unix_path with
+ just backslashes to keep the different names.
+ * syscalls.cc (fstat64): Don't override st_ino, st_dev and st_rdev
+ for sockets.
+ (stat_worker): Ditto.
+
+2003-02-21 Pierre Humblet <pierre.humblet@ieee.org>
+
+ * autoload.cc (AccessCheck): Add.
+ (DuplicateToken): Add.
+ * security.h (check_file_access): Declare.
+ * syscalls.cc (access): Convert path to Windows, check existence
+ and readonly attribute. Call check_file_access instead of acl_access.
+ * security.cc (check_file_access): Create.
+ * sec_acl (acl_access): Delete.
+
2003-02-19 Christopher Faylor <cgf@redhat.com>
* fhandler.cc (fhandler_base::open): Move some filesystem specific
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index d071ab1..b29c9d2 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -307,6 +307,7 @@ wsock_init ()
LoadDLLprime (wsock32, wsock_init)
LoadDLLprime (ws2_32, wsock_init)
+LoadDLLfunc (AccessCheck, 32, advapi32)
LoadDLLfunc (AddAccessAllowedAce, 16, advapi32)
LoadDLLfunc (AddAccessDeniedAce, 16, advapi32)
LoadDLLfunc (AddAce, 20, advapi32)
@@ -318,6 +319,7 @@ LoadDLLfuncEx (CryptAcquireContextA, 20, advapi32, 1)
LoadDLLfuncEx (CryptGenRandom, 12, advapi32, 1)
LoadDLLfuncEx (CryptReleaseContext, 8, advapi32, 1)
LoadDLLfunc (DeregisterEventSource, 4, advapi32)
+LoadDLLfunc (DuplicateToken, 12, advapi32)
LoadDLLfuncEx (DuplicateTokenEx, 24, advapi32, 1)
LoadDLLfunc (EqualSid, 8, advapi32)
LoadDLLfunc (GetAce, 12, advapi32)
diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc
index 03490b6..73af42e 100644
--- a/winsup/cygwin/dtable.cc
+++ b/winsup/cygwin/dtable.cc
@@ -299,9 +299,15 @@ dtable::build_fhandler_from_name (int fd, const char *name, HANDLE handle,
if (!pc.exists () && handle)
pc.fillin (handle);
- fhandler_base *fh = build_fhandler (fd, pc.get_devn (),
- pc.return_and_clear_normalized_path (),
+ char *posix_path = pc.return_and_clear_normalized_path ();
+ fhandler_base *fh = build_fhandler (fd, pc.get_devn (), posix_path,
pc, pc.get_unitn ());
+ if (pc.issocket ()) /* Only true for files pretending an AF_LOCAL socket. */
+ {
+ fhandler_socket * fhs = (fhandler_socket *) fh;
+ fhs->set_addr_family (AF_LOCAL);
+ fhs->set_sun_path (posix_path);
+ }
return fh;
}
@@ -352,7 +358,7 @@ dtable::build_fhandler (int fd, DWORD dev, char *unix_name,
fh = cnew (fhandler_pipe) (dev);
break;
case FH_SOCKET:
- if ((fh = cnew (fhandler_socket) ()))
+ if ((fh = cnew (fhandler_socket) (unit)))
inc_need_fixup_before ();
break;
case FH_DISK:
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 8840cb8..cc6ae7c 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -385,12 +385,14 @@ class fhandler_socket: public fhandler_base
struct _WSAPROTOCOL_INFOA *prot_info_ptr;
char *sun_path;
int had_connect_or_listen;
+ int unit;
public:
- fhandler_socket ();
+ fhandler_socket (int unit);
~fhandler_socket ();
int get_socket () { return (int) get_handle(); }
fhandler_socket * is_socket () { return this; }
+ int get_unit () { return unit; }
bool saw_shutdown_read () const {return FHISSETF (SHUTRD);}
bool saw_shutdown_write () const {return FHISSETF (SHUTWR);}
diff --git a/winsup/cygwin/fhandler_socket.cc b/winsup/cygwin/fhandler_socket.cc
index 6c867f9..b10e28a 100644
--- a/winsup/cygwin/fhandler_socket.cc
+++ b/winsup/cygwin/fhandler_socket.cc
@@ -94,8 +94,8 @@ get_inet_addr (const struct sockaddr *in, int inlen,
/**********************************************************************/
/* fhandler_socket */
-fhandler_socket::fhandler_socket ()
- : fhandler_base (FH_SOCKET), sun_path (NULL)
+fhandler_socket::fhandler_socket (int nunit)
+ : fhandler_base (FH_SOCKET), unit (nunit), sun_path (NULL)
{
set_need_fork_fixup ();
prot_info_ptr = (LPWSAPROTOCOL_INFOA) cmalloc (HEAP_BUF,
@@ -309,12 +309,47 @@ fhandler_socket::dup (fhandler_base *child)
int __stdcall
fhandler_socket::fstat (struct __stat64 *buf, path_conv *pc)
{
- int res = fhandler_base::fstat (buf, pc);
+ int res;
+ if (get_addr_family () == AF_LOCAL && get_sun_path ())
+ {
+ path_conv spc (get_sun_path (),
+ PC_SYM_NOFOLLOW | PC_NULLEMPTY | PC_FULL | PC_POSIX,
+ NULL);
+ fhandler_base *fh = cygheap->fdtab.build_fhandler (-1, FH_DISK,
+ get_sun_path (),
+ spc, 0);
+ if (fh)
+ {
+ res = fh->fstat (buf, &spc);
+ /* Faking Linux like values on top of the file specific values. */
+ if (get_socket_type ()) /* fstat() */
+ {
+ buf->st_dev = 0;
+ buf->st_mode |= S_IRWXU | S_IRWXG | S_IRWXO;
+ buf->st_ino = (ino_t) get_handle ();
+ }
+ buf->st_rdev = buf->st_size = buf->st_blocks = 0;
+ return res;
+ }
+ }
+
+ res = fhandler_base::fstat (buf, pc);
if (!res)
{
- buf->st_mode &= ~_IFMT;
- buf->st_mode |= _IFSOCK;
- buf->st_ino = (ino_t) get_handle ();
+ if (get_socket_type ()) /* fstat */
+ {
+ buf->st_ino = (ino_t) get_handle ();
+ buf->st_mode &= ~S_IFMT;
+ buf->st_mode |= S_IFSOCK;
+ }
+ else
+ {
+ path_conv spc ("/dev", PC_SYM_NOFOLLOW | PC_NULLEMPTY, NULL);
+ buf->st_dev = spc.volser ();
+ buf->st_ino = (ino_t) get_namehash ();
+ buf->st_mode &= ~S_IRWXO;
+ buf->st_rdev = (get_device () << 16) | get_unit ();
+ }
}
return res;
}
diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc
index 6bfec1f..cfc716c 100644
--- a/winsup/cygwin/net.cc
+++ b/winsup/cygwin/net.cc
@@ -14,6 +14,7 @@ details. */
#include "winsup.h"
#include <errno.h>
+#include <ctype.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <iphlpapi.h>
@@ -521,8 +522,9 @@ fdsock (int &fd, const char *name, SOCKET soc)
else
debug_printf ("not setting socket inheritance since winsock2_active %d",
winsock2_active);
- fhandler_socket *fh =
- (fhandler_socket *) cygheap->fdtab.build_fhandler (fd, FH_SOCKET, name);
+ fhandler_socket *fh = (fhandler_socket *)
+ cygheap->fdtab.build_fhandler (fd, FH_SOCKET, name, NULL,
+ tolower (name[5]) - 'a');
if (!fh)
return NULL;
fh->set_io_handle ((HANDLE) soc);
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index d75f8a0..dea1d37 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -799,10 +799,8 @@ out:
set_has_buggy_open (strcmp (fs.name, "SUNWNFS") == 0);
}
}
-#if 0
if (issocket ())
devn = FH_SOCKET;
-#endif
if (!(opt & PC_FULL))
{
@@ -954,7 +952,10 @@ get_devn (const char *name, int &unit)
devn = FH_PIPEW;
else if (deveq ("tcp") || deveq ("udp") || deveq ("streamsocket")
|| deveq ("dgsocket"))
- devn = FH_SOCKET;
+ {
+ devn = FH_SOCKET;
+ unit = tolower (*name) - 'a';
+ }
return devn;
}
@@ -1118,6 +1119,12 @@ win32_device_name (const char *src_path, char *win32_path,
return false;
switch (devn)
{
+ case FH_SOCKET:
+ char *c;
+ strcpy (win32_path, src_path);
+ while (c = strchr (win32_path, '/'))
+ *c = '\\';
+ break;
case FH_RANDOM:
__small_sprintf (win32_path, devfmt, unit == 8 ? "" : "u");
break;
diff --git a/winsup/cygwin/sec_acl.cc b/winsup/cygwin/sec_acl.cc
index febda4f..3a9f08b 100644
--- a/winsup/cygwin/sec_acl.cc
+++ b/winsup/cygwin/sec_acl.cc
@@ -413,69 +413,6 @@ getacl (const char *file, DWORD attr, int nentries, __aclent32_t *aclbufp)
return pos;
}
-int
-acl_access (const char *path, int flags)
-{
- __aclent32_t acls[MAX_ACL_ENTRIES];
- int cnt;
-
- if ((cnt = acl32 (path, GETACL, MAX_ACL_ENTRIES, acls)) < 1)
- return -1;
-
- /* Only check existence. */
- if (!(flags & (R_OK | W_OK | X_OK)))
- return 0;
-
- for (int i = 0; i < cnt; ++i)
- {
- switch (acls[i].a_type)
- {
- case USER_OBJ:
- case USER:
- if (acls[i].a_id != myself->uid)
- {
- /*
- * Check if user is a NT group:
- * Take SID from passwd, search SID in token groups
- */
- cygsid owner;
- struct passwd *pw;
-
- if ((pw = internal_getpwuid (acls[i].a_id)) != NULL
- && owner.getfrompw (pw)
- && internal_getgroups (0, NULL, &owner) > 0)
- break;
- continue;
- }
- break;
- case GROUP_OBJ:
- case GROUP:
- if (acls[i].a_id != myself->gid)
- {
- cygsid group;
- struct __group32 *gr = NULL;
-
- if ((gr = internal_getgrgid (acls[i].a_id)) != NULL
- && group.getfromgr (gr)
- && internal_getgroups (0, NULL, &group) > 0)
- break;
- continue;
- }
- break;
- case OTHER_OBJ:
- break;
- default:
- continue;
- }
- if ((!(flags & R_OK) || (acls[i].a_perm & S_IROTH))
- && (!(flags & W_OK) || (acls[i].a_perm & S_IWOTH))
- && (!(flags & X_OK) || (acls[i].a_perm & S_IXOTH)))
- return 0;
- }
- set_errno (EACCES);
- return -1;
-}
-
static
int
acl_worker (const char *path, int cmd, int nentries, __aclent32_t *aclbufp,
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc
index 35ac5cf..847aa4a 100644
--- a/winsup/cygwin/security.cc
+++ b/winsup/cygwin/security.cc
@@ -1918,3 +1918,54 @@ set_file_attribute (int use_ntsec, const char *file, int attribute)
return set_file_attribute (use_ntsec, file,
myself->uid, myself->gid, attribute);
}
+
+int
+check_file_access (const char *fn, int flags)
+{
+ int ret = -1;
+ char sd_buf[4096];
+ DWORD sd_size = sizeof sd_buf;
+ PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf;
+ HANDLE hToken, hIToken;
+ BOOL status;
+ char pbuf[sizeof (PRIVILEGE_SET) + 3 * sizeof (LUID_AND_ATTRIBUTES)];
+ DWORD desired = 0, granted, plength = sizeof pbuf;
+ static GENERIC_MAPPING NO_COPY mapping = { FILE_GENERIC_READ,
+ FILE_GENERIC_WRITE,
+ FILE_GENERIC_EXECUTE,
+ FILE_ALL_ACCESS };
+ if (read_sd (fn, psd, &sd_size) <= 0)
+ goto done;
+
+ if (cygheap->user.issetuid ())
+ hToken = cygheap->user.token;
+ else if (!OpenProcessToken (hMainProc, TOKEN_DUPLICATE, &hToken))
+ {
+ __seterrno ();
+ goto done;
+ }
+ if (!(status = DuplicateToken (hToken, SecurityIdentification, &hIToken)))
+ __seterrno ();
+ if (hToken != cygheap->user.token)
+ CloseHandle (hToken);
+ if (!status)
+ goto done;
+
+ if (flags & R_OK)
+ desired |= FILE_READ_DATA;
+ if (flags & W_OK)
+ desired |= FILE_WRITE_DATA;
+ if (flags & X_OK)
+ desired |= FILE_EXECUTE;
+ if (!AccessCheck (psd, hIToken, desired, &mapping,
+ (PPRIVILEGE_SET) pbuf, &plength, &granted, &status))
+ __seterrno ();
+ else if (!status)
+ set_errno (EACCES);
+ else
+ ret = 0;
+ CloseHandle (hIToken);
+ done:
+ debug_printf ("flags %x, ret %d", flags, ret);
+ return ret;
+}
diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h
index 9cbea2f..a859526 100644
--- a/winsup/cygwin/security.h
+++ b/winsup/cygwin/security.h
@@ -225,6 +225,7 @@ LONG __stdcall read_sd(const char *file, PSECURITY_DESCRIPTOR sd_buf, LPDWORD sd
LONG __stdcall write_sd(const char *file, PSECURITY_DESCRIPTOR sd_buf, DWORD sd_size);
BOOL __stdcall add_access_allowed_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit);
BOOL __stdcall add_access_denied_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit);
+int __stdcall check_file_access (const char *, int);
void set_security_attribute (int attribute, PSECURITY_ATTRIBUTES psa,
void *sd_buf, DWORD sd_buf_size);
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 59bb531..cd3f2e6 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -1016,7 +1016,7 @@ fstat64 (int fd, struct __stat64 *buf)
path_conv pc (cfd->get_win32_name (), PC_SYM_NOFOLLOW);
memset (buf, 0, sizeof (struct __stat64));
res = cfd->fstat (buf, &pc);
- if (!res)
+ if (!res && cfd->get_device () != FH_SOCKET)
{
if (!buf->st_ino)
buf->st_ino = hash_path_name (0, cfd->get_win32_name ());
@@ -1106,7 +1106,7 @@ stat_worker (const char *name, struct __stat64 *buf, int nofollow,
pc, (DWORD) real_path);
memset (buf, 0, sizeof (*buf));
res = fh->fstat (buf, pc);
- if (!res)
+ if (!res && fh->get_device () != FH_SOCKET)
{
if (!buf->st_ino)
buf->st_ino = hash_path_name (0, fh->get_win32_name ());
@@ -1163,8 +1163,6 @@ cygwin_lstat (const char *name, struct __stat32 *buf)
return ret;
}
-extern int acl_access (const char *, int);
-
extern "C" int
access (const char *fn, int flags)
{
@@ -1176,11 +1174,33 @@ access (const char *fn, int flags)
return -1;
}
- if (allow_ntsec)
- return acl_access (fn, flags);
+ path_conv real_path (fn, PC_SYM_FOLLOW | PC_FULL, stat_suffixes);
+ if (real_path.error)
+ {
+ set_errno (real_path.error);
+ return -1;
+ }
+
+ if (!real_path.exists ())
+ {
+ set_errno (ENOENT);
+ return -1;
+ }
+
+ if (!(flags & (R_OK | W_OK | X_OK)))
+ return 0;
+
+ if (real_path.has_attribute (FILE_ATTRIBUTE_READONLY) && (flags & W_OK))
+ {
+ set_errno (EACCES);
+ return -1;
+ }
+
+ if (real_path.has_acls () && allow_ntsec)
+ return check_file_access (real_path, flags);
struct __stat64 st;
- int r = stat_worker (fn, &st, 0);
+ int r = stat_worker (real_path, &st, 0);
if (r)
return -1;
r = -1;