diff options
Diffstat (limited to 'winsup/cygwin')
-rw-r--r-- | winsup/cygwin/ChangeLog | 24 | ||||
-rw-r--r-- | winsup/cygwin/fhandler.cc | 3 | ||||
-rw-r--r-- | winsup/cygwin/fhandler.h | 13 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_disk_file.cc | 34 | ||||
-rw-r--r-- | winsup/cygwin/security.cc | 76 | ||||
-rw-r--r-- | winsup/cygwin/security.h | 2 | ||||
-rw-r--r-- | winsup/cygwin/syscalls.cc | 5 |
7 files changed, 94 insertions, 63 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index efd1730e2..bfbb95f5a 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,27 @@ +2004-04-07 Corinna Vinschen <corinna@vinschen.de> + + * fhandler.cc (fhandler_base::open): Set query access mode according + to query_open setting. + (fhandler_base::fhandler_base): Initialize query_open. + * fhandler.h (FH_QUERYOPEN): Drop. + (enum query_state): Add. + (class fhandler_base): Add query_open member. + (fhandler_base::get_query_open): Redefine to use query_open. + (fhandler_base::set_query_open): Ditto. + * fhandler_disk_file.cc (fhandler_base::fstat_fs): Remove O_DIROPEN + from open_flags since it's added in open_fs anyway. Remove + query_open_already. Use new query_open settings. Rearrange slightly. + (fhandler_base::fstat_helper): Add get_io_handle as parameter to + get_file_attribute. + * security.cc (get_nt_object_attribute): Make returning an int. + Return -1 on error, 0 otherwise. + (get_file_attribute): Take an object handle as argument. Move down + to allow calling get_nt_object_attribute in case a non-NULL handle + is given. + * security.h (get_file_attribute): Add handle to argument list. + * syscalls.cc (chown_worker): Accomodate new definition of + get_file_attribute. + 2004-04-07 Pierre Humblet <pierre.humblet@ieee.org> * path.cc (path_prefix_p): Optimize test order. diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index daf340737..2b364dbec 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -443,7 +443,7 @@ fhandler_base::open (int flags, mode_t mode) } if (get_query_open ()) - access = 0; + access = get_query_open () == query_read_control ? READ_CONTROL : 0; else if (get_major () == DEV_TAPE_MAJOR) access = GENERIC_READ | GENERIC_WRITE; else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY) @@ -1258,6 +1258,7 @@ fhandler_base::operator delete (void *p) /* Normal I/O constructor */ fhandler_base::fhandler_base (): status (0), + query_open (no_query), access (0), io_handle (NULL), namehash (0), diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 0b5c71299..b621dccfa 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -37,8 +37,6 @@ enum FH_ISREMOTE = 0x10000000, /* File is on a remote drive */ FH_DCEXEC = 0x20000000, /* Don't care if this is executable */ FH_HASACLS = 0x40000000, /* True if fs of file has ACLS */ - FH_QUERYOPEN = 0x80000000, /* open file without requesting either read - or write access */ }; #define FHDEVN(n) (n) @@ -95,12 +93,19 @@ enum bg_check_types bg_signalled = 2 }; +enum query_state { + no_query = 0, + query_read_control = 1, + query_null_access = 2 +}; + class fhandler_base { friend class dtable; friend void close_all_files (); protected: DWORD status; + unsigned query_open : 2; private: int access; HANDLE io_handle; @@ -239,8 +244,8 @@ class fhandler_base bool get_fs_flags (DWORD flagval = UINT32_MAX) { return (fs_flags & (flagval)); } - bool get_query_open () { return FHISSETF (QUERYOPEN); } - void set_query_open (bool val) { FHCONDSETF (val, QUERYOPEN); } + query_state get_query_open () { return (query_state) query_open; } + void set_query_open (query_state val) { query_open = val; } bool get_readahead_valid () { return raixget < ralen; } int puts_readahead (const char *s, size_t len = (size_t) -1); diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc index 62e133f76..9da537453 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -160,8 +160,7 @@ fhandler_base::fstat_fs (struct __stat64 *buf) { int res = -1; int oret; - int open_flags = O_RDONLY | O_BINARY | O_DIROPEN; - bool query_open_already; + int open_flags = O_RDONLY | O_BINARY; if (get_io_handle ()) { @@ -173,21 +172,18 @@ fhandler_base::fstat_fs (struct __stat64 *buf) /* If we don't care if the file is executable or we already know if it is, then just do a "query open" as it is apparently much faster. */ if (pc.exec_state () != dont_know_if_executable) - set_query_open (query_open_already = true); - else - query_open_already = false; - - if (query_open_already && strncasematch (pc.volname (), "FAT", 3) - && !strpbrk (get_win32_name (), "?*|<>")) - oret = 0; - else if (!(oret = open_fs (open_flags, 0)) - && !query_open_already - && get_errno () == EACCES) { - /* If we couldn't open the file, try a "query open" with no permissions. - This will allow us to determine *some* things about the file, at least. */ + set_query_open (query_read_control); + if (strncasematch (pc.volname (), "FAT", 3) + && !strpbrk (get_win32_name (), "?*|<>")) + return fstat_by_name (buf); + } + if (!(oret = open_fs (open_flags, 0)) && get_errno () == EACCES) + { + /* If we couldn't open the file, try a query open with no permissions. + This allows us to determine *some* things about the file, at least. */ pc.set_exec (0); - set_query_open (true); + set_query_open (query_null_access); oret = open_fs (open_flags, 0); } @@ -289,15 +285,15 @@ fhandler_base::fstat_helper (struct __stat64 *buf, { /* symlinks are everything for everyone! */ buf->st_mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO; - get_file_attribute (pc.has_acls (), get_win32_name (), NULL, - &buf->st_uid, &buf->st_gid); + get_file_attribute (pc.has_acls (), get_io_handle (), get_win32_name (), + NULL, &buf->st_uid, &buf->st_gid); goto done; } else if (pc.issocket ()) buf->st_mode = S_IFSOCK; - if (get_file_attribute (pc.has_acls (), get_win32_name (), &buf->st_mode, - &buf->st_uid, &buf->st_gid) == 0) + if (!get_file_attribute (pc.has_acls (), get_io_handle (), get_win32_name (), + &buf->st_mode, &buf->st_uid, &buf->st_gid)) { /* If read-only attribute is set, modify ntsec return value */ if (pc.has_attribute (FILE_ATTRIBUTE_READONLY) && !get_symlink_p ()) diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index 8195298ad..c7533dee0 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -1367,40 +1367,7 @@ get_nt_attribute (const char *file, mode_t *attribute, get_info_from_sd (sd, attribute, uidret, gidret); } -int -get_file_attribute (int use_ntsec, const char *file, - mode_t *attribute, __uid32_t *uidret, __gid32_t *gidret) -{ - int res; - syscall_printf ("file: %s", file); - - if (use_ntsec && allow_ntsec && wincap.has_security ()) - { - get_nt_attribute (file, attribute, uidret, gidret); - return 0; - } - - if (uidret) - *uidret = myself->uid; - if (gidret) - *gidret = myself->gid; - - if (!attribute) - return 0; - - if (allow_ntea) - { - int oatt = *attribute; - res = NTReadEA (file, ".UNIXATTR", (char *)attribute, sizeof (*attribute)); - *attribute |= oatt; - } - else - res = 0; - - return res > 0 ? 0 : -1; -} - -static void +static int get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, mode_t *attribute, __uid32_t *uidret, __gid32_t *gidret) @@ -1436,12 +1403,16 @@ get_nt_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, | GROUP_SECURITY_INFORMATION | OWNER_SECURITY_INFORMATION, NULL, NULL, NULL, NULL, &psd))) - __seterrno_from_win_error (ret); + { + __seterrno_from_win_error (ret); + return -1; + } else { get_info_from_sd (psd, attribute, uidret, gidret); LocalFree (psd); } + return 0; } int @@ -1457,6 +1428,41 @@ get_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, return -1; } +int +get_file_attribute (int use_ntsec, HANDLE handle, const char *file, + mode_t *attribute, __uid32_t *uidret, __gid32_t *gidret) +{ + int res; + syscall_printf ("file: %s", file); + + if (use_ntsec && allow_ntsec && wincap.has_security ()) + { + if (handle && get_nt_object_attribute (handle, SE_FILE_OBJECT, + attribute, uidret, gidret)) + get_nt_attribute (file, attribute, uidret, gidret); + return 0; + } + + if (uidret) + *uidret = myself->uid; + if (gidret) + *gidret = myself->gid; + + if (!attribute) + return 0; + + if (allow_ntea) + { + int oatt = *attribute; + res = NTReadEA (file, ".UNIXATTR", (char *)attribute, sizeof (*attribute)); + *attribute |= oatt; + } + else + res = 0; + + return res > 0 ? 0 : -1; +} + bool add_access_allowed_ace (PACL acl, int offset, DWORD attributes, PSID sid, size_t &len_add, DWORD inherit) diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h index 875e2ad44..d9c90cd79 100644 --- a/winsup/cygwin/security.h +++ b/winsup/cygwin/security.h @@ -249,7 +249,7 @@ extern bool allow_smbntsec; /* File manipulation */ int __stdcall set_process_privileges (); -int __stdcall get_file_attribute (int, const char *, mode_t *, +int __stdcall get_file_attribute (int, HANDLE, const char *, mode_t *, __uid32_t * = NULL, __gid32_t * = NULL); int __stdcall set_file_attribute (int, const char *, int); int __stdcall set_file_attribute (int, const char *, __uid32_t, __gid32_t, int); diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 132d22325..006f371a8 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -846,9 +846,8 @@ chown_worker (const char *name, unsigned fmode, __uid32_t uid, __gid32_t gid) mode_t attrib = 0; if (win32_path.isdir ()) attrib |= S_IFDIR; - res = get_file_attribute (win32_path.has_acls (), - win32_path.get_win32 (), - &attrib); + res = get_file_attribute (win32_path.has_acls (), NULL, + win32_path.get_win32 (), &attrib); if (!res) res = set_file_attribute (win32_path.has_acls (), win32_path, uid, gid, attrib); |