From d6581f44d4471b942692c1bf91624656991a11bd Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Tue, 25 Apr 2000 16:31:14 +0000 Subject: [PATCH] * fhandler.cc (fhandler_disk_file::open): Check for allow_ntsec when determining exec flag. * path.cc (symlink_info::check): Remove call to get_file_attribute(). * security.cc (read_sd): Rename, ditto for variables to conform to common naming convention. Use GetFileSecurity() instead of BackupRead() to avoid permission problems when reading ACLs. (write_sd): Same renaming as for read_sd(). (alloc_sd): Change default permissions according to Linux permissions for group and world when write permission is set. * syscalls.cc (stat_worker): Avoid different permission problems when requesting file informations. --- winsup/cygwin/ChangeLog | 14 ++++ winsup/cygwin/fhandler.cc | 3 +- winsup/cygwin/path.cc | 11 --- winsup/cygwin/security.cc | 147 +++++++++++++------------------------- winsup/cygwin/syscalls.cc | 95 ++++++++++++++---------- 5 files changed, 121 insertions(+), 149 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 4d72a3045..f414852b7 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,17 @@ +Thu Apr 25 16:37:00 2000 Corinna Vinschen + + * fhandler.cc (fhandler_disk_file::open): Check for allow_ntsec + when determining exec flag. + * path.cc (symlink_info::check): Remove call to get_file_attribute(). + * security.cc (read_sd): Rename, ditto for variables to conform + to common naming convention. Use GetFileSecurity() instead of + BackupRead() to avoid permission problems when reading ACLs. + (write_sd): Same renaming as for read_sd(). + (alloc_sd): Change default permissions according to Linux permissions + for group and world when write permission is set. + * syscalls.cc (stat_worker): Avoid different permission problems + when requesting file informations. + Thu Apr 25 10:50:00 2000 Corinna Vinschen * net.cc: Avoid a warning in declaration inet_network. diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index f135b9935..ef4281c7c 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -1187,8 +1187,9 @@ fhandler_disk_file::open (path_conv& real_path, int flags, mode_t mode) goto out; extern BOOL allow_ntea; + extern BOOL allow_ntsec; - if (!real_path.isexec () && !allow_ntea && + if (!real_path.isexec () && !allow_ntea && !allow_ntsec && GetFileType (get_handle ()) == FILE_TYPE_DISK) { DWORD done; diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index 463fb6c4f..30aa3f90b 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -2186,17 +2186,6 @@ symlink_info::check (const char *in_path, const suffix_info *suffixes) if (!(pflags & PATH_SYMLINK) && !SYMLINKATTR (fileattr)) goto file_not_symlink; - /* Check the file's extended attributes, if it has any. */ - int unixattr = 0; - if (fileattr & FILE_ATTRIBUTE_DIRECTORY) - unixattr |= S_IFDIR; - - if (!get_file_attribute (TRUE, path, &unixattr)) - { - if (unixattr & STD_XBITS) - pflags |= PATH_EXEC; - } - /* Open the file. */ h = CreateFileA (path, GENERIC_READ, FILE_SHARE_READ, &sec_none_nih, OPEN_EXISTING, diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index 73e67e468..8ba3bc858 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -374,116 +374,67 @@ got_it: return TRUE; } -/* ReadSD reads a security descriptor from a file. +/* read_sd reads a security descriptor from a file. In case of error, -1 is returned and errno is set. If the file doesn't have a SD, 0 is returned. Otherwise, the size of the SD is returned and - the SD is copied to the buffer, pointed to by sdBuf. - sdBufSize contains the size of the buffer. If + the SD is copied to the buffer, pointed to by sd_buf. + sd_size contains the size of the buffer. If it's too small, to contain the complete SD, 0 is - returned and sdBufSize is set to the needed size + returned and sd_size is set to the needed size of the buffer. */ LONG -ReadSD(const char *file, PSECURITY_DESCRIPTOR sdBuf, LPDWORD sdBufSize) +read_sd(const char *file, PSECURITY_DESCRIPTOR sd_buf, LPDWORD sd_size) { /* Check parameters */ - if (! sdBufSize) + if (! sd_size) { set_errno (EINVAL); return -1; } - /* Open file for read */ debug_printf("file = %s", file); - HANDLE hFile = CreateFile (file, GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &sec_none_nih, OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, - NULL); - if (hFile == INVALID_HANDLE_VALUE) + DWORD len = 0; + if (! GetFileSecurity (file, + OWNER_SECURITY_INFORMATION + | GROUP_SECURITY_INFORMATION + | DACL_SECURITY_INFORMATION, + sd_buf, *sd_size, &len)) { __seterrno (); return -1; } - - /* step through the backup streams and search for the security data */ - WIN32_STREAM_ID header; - DWORD bytes_read = 0; - LPVOID context = NULL; - PSECURITY_DESCRIPTOR psd = NULL; - DWORD datasize; - LONG ret = 0; - - while (BackupRead (hFile, (LPBYTE) &header, - 3 * sizeof (DWORD) + sizeof (LARGE_INTEGER), - &bytes_read, FALSE, TRUE, &context)) + if (len > *sd_size) { - if (header.dwStreamId != BACKUP_SECURITY_DATA) - continue; - - /* security data found */ - datasize = header.Size.LowPart + header.dwStreamNameSize; - char b[datasize]; - - if (! BackupRead (hFile, (LPBYTE) b, datasize, &bytes_read, - FALSE, TRUE, &context)) - { - __seterrno (); - ret = -1; - break; - } - - /* Check validity of the SD */ - psd = (PSECURITY_DESCRIPTOR) &b[header.dwStreamNameSize]; - if (! IsValidSecurityDescriptor (psd)) - continue; - - /* It's a valid SD */ - datasize -= header.dwStreamNameSize; - debug_printf ("SD-Size: %d", datasize); - - /* buffer to small? */ - if (*sdBufSize < datasize) - { - *sdBufSize = datasize; - ret = 0; - break; - } - - if (sdBuf) - memcpy (sdBuf, psd, datasize); - - ret = *sdBufSize = datasize; - break; - + *sd_size = len; + return 0; } - BackupRead (hFile, NULL, 0, &bytes_read, TRUE, TRUE, &context); - CloseHandle (hFile); - return ret; + return len; } LONG -WriteSD(const char *file, PSECURITY_DESCRIPTOR sdBuf, DWORD sdBufSize) +write_sd(const char *file, PSECURITY_DESCRIPTOR sd_buf, DWORD sd_size) { /* Check parameters */ - if (! sdBuf || ! sdBufSize) + if (! sd_buf || ! sd_size) { set_errno (EINVAL); return -1; } - HANDLE hFile = CreateFile (file, - WRITE_OWNER | WRITE_DAC, - FILE_SHARE_READ | FILE_SHARE_WRITE, - &sec_none_nih, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, - NULL); + HANDLE fh; + fh = CreateFile (file, + WRITE_OWNER | WRITE_DAC, + FILE_SHARE_READ | FILE_SHARE_WRITE, + &sec_none_nih, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_BACKUP_SEMANTICS, + NULL); - if (hFile == INVALID_HANDLE_VALUE) + if (fh == INVALID_HANDLE_VALUE) { __seterrno (); return -1; @@ -498,19 +449,19 @@ WriteSD(const char *file, PSECURITY_DESCRIPTOR sdBuf, DWORD sdBufSize) header.dwStreamId = BACKUP_SECURITY_DATA; header.dwStreamAttributes = STREAM_CONTAINS_SECURITY; header.Size.HighPart = 0; - header.Size.LowPart = sdBufSize; + header.Size.LowPart = sd_size; header.dwStreamNameSize = 0; - if (!BackupWrite (hFile, (LPBYTE) &header, + if (!BackupWrite (fh, (LPBYTE) &header, 3 * sizeof (DWORD) + sizeof (LARGE_INTEGER), &bytes_written, FALSE, TRUE, &context)) { __seterrno (); - CloseHandle (hFile); + CloseHandle (fh); return -1; } /* write new security descriptor */ - if (!BackupWrite (hFile, (LPBYTE) sdBuf, + if (!BackupWrite (fh, (LPBYTE) sd_buf, header.Size.LowPart + header.dwStreamNameSize, &bytes_written, FALSE, TRUE, &context)) { @@ -521,15 +472,15 @@ WriteSD(const char *file, PSECURITY_DESCRIPTOR sdBuf, DWORD sdBufSize) if (ret != ERROR_NOT_SUPPORTED && ret != ERROR_INVALID_SECURITY_DESCR) { __seterrno (); - BackupWrite (hFile, NULL, 0, &bytes_written, TRUE, TRUE, &context); - CloseHandle (hFile); + BackupWrite (fh, NULL, 0, &bytes_written, TRUE, TRUE, &context); + CloseHandle (fh); return -1; } } /* terminate the restore process */ - BackupWrite (hFile, NULL, 0, &bytes_written, TRUE, TRUE, &context); - CloseHandle (hFile); + BackupWrite (fh, NULL, 0, &bytes_written, TRUE, TRUE, &context); + CloseHandle (fh); return 0; } @@ -612,9 +563,9 @@ get_nt_attribute (const char *file, int *attribute, PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf; int ret; - if ((ret = ReadSD (file, psd, &sd_size)) <= 0) + if ((ret = read_sd (file, psd, &sd_size)) <= 0) { - debug_printf ("ReadSD %E"); + debug_printf ("read_sd %E"); return ret; } @@ -739,8 +690,8 @@ get_nt_attribute (const char *file, int *attribute, } int -get_file_attribute (int use_ntsec, const char *file, int *attribute, - uid_t *uidret, gid_t *gidret) +get_file_attribute (int use_ntsec, const char *file, + int *attribute, uid_t *uidret, gid_t *gidret) { if (use_ntsec && allow_ntsec) return get_nt_attribute (file, attribute, uidret, gidret); @@ -898,7 +849,7 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, if (attribute & S_IRGRP) group_allow |= FILE_GENERIC_READ; if (attribute & S_IWGRP) - group_allow |= STANDARD_RIGHTS_ALL | FILE_GENERIC_WRITE | DELETE; + group_allow |= STANDARD_RIGHTS_WRITE | FILE_GENERIC_WRITE | DELETE; if (attribute & S_IXGRP) group_allow |= FILE_GENERIC_EXECUTE; if (! (attribute & S_ISVTX)) @@ -910,7 +861,7 @@ alloc_sd (uid_t uid, gid_t gid, const char *logsrv, int attribute, if (attribute & S_IROTH) other_allow |= FILE_GENERIC_READ; if (attribute & S_IWOTH) - other_allow |= STANDARD_RIGHTS_ALL | FILE_GENERIC_WRITE | DELETE; + other_allow |= STANDARD_RIGHTS_WRITE | FILE_GENERIC_WRITE | DELETE; if (attribute & S_IXOTH) other_allow |= FILE_GENERIC_EXECUTE; if (! (attribute & S_ISVTX)) @@ -1034,9 +985,9 @@ set_nt_attribute (const char *file, uid_t uid, gid_t gid, PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf; int ret; - if ((ret = ReadSD (file, psd, &sd_size)) <= 0) + if ((ret = read_sd (file, psd, &sd_size)) <= 0) { - debug_printf ("ReadSD %E"); + debug_printf ("read_sd %E"); return ret; } @@ -1044,7 +995,7 @@ set_nt_attribute (const char *file, uid_t uid, gid_t gid, if (! (psd = alloc_sd (uid, gid, logsrv, attribute, psd, &sd_size))) return -1; - return WriteSD (file, psd, sd_size); + return write_sd (file, psd, sd_size); } int @@ -1100,9 +1051,9 @@ setacl (const char *file, int nentries, aclent_t *aclbufp) char sd_buf[4096]; PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf; - if (ReadSD (file, psd, &sd_size) <= 0) + if (read_sd (file, psd, &sd_size) <= 0) { - debug_printf ("ReadSD %E"); + debug_printf ("read_sd %E"); return -1; } @@ -1265,7 +1216,7 @@ setacl (const char *file, int nentries, aclent_t *aclbufp) return -1; } debug_printf ("Created SD-Size: %d", sd_size); - return WriteSD (file, psd, sd_size); + return write_sd (file, psd, sd_size); } static void @@ -1301,9 +1252,9 @@ getacl (const char *file, DWORD attr, int nentries, aclent_t *aclbufp) PSECURITY_DESCRIPTOR psd = (PSECURITY_DESCRIPTOR) sd_buf; int ret; - if ((ret = ReadSD (file, psd, &sd_size)) <= 0) + if ((ret = read_sd (file, psd, &sd_size)) <= 0) { - debug_printf ("ReadSD %E"); + debug_printf ("read_sd %E"); return ret; } diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 45978bc91..1200d3642 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -982,6 +982,8 @@ stat_worker (const char *caller, const char *name, struct stat *buf, char *win32_name; char root[MAX_PATH]; UINT dtype; + fhandler_disk_file fh (NULL); + MALLOC_CHECK; debug_printf ("%s (%s, %p)", caller, name, buf); @@ -1009,28 +1011,15 @@ stat_worker (const char *caller, const char *name, struct stat *buf, strcpy (root, win32_name); dtype = GetDriveType (rootdir (root)); - if (atts == -1 || !(atts & FILE_ATTRIBUTE_DIRECTORY) || - (os_being_run == winNT - && dtype != DRIVE_NO_ROOT_DIR - && dtype != DRIVE_UNKNOWN)) + if ((atts == -1 || !(atts & FILE_ATTRIBUTE_DIRECTORY) || + (os_being_run == winNT + && dtype != DRIVE_NO_ROOT_DIR + && dtype != DRIVE_UNKNOWN)) + && fh.open (real_path, O_RDONLY | O_BINARY | O_DIROPEN | + (nofollow ? O_NOSYMLINK : 0), 0)) { - fhandler_disk_file fh (NULL); - - if (fh.open (real_path, O_RDONLY | O_BINARY | O_DIROPEN | - (nofollow ? O_NOSYMLINK : 0), 0)) - { - res = fh.fstat (buf); - fh.close (); - /* See the comment 10 lines below */ - if (atts != -1 && (atts & FILE_ATTRIBUTE_DIRECTORY)) - buf->st_nlink = - (dtype == DRIVE_REMOTE ? 1 : num_entries (win32_name)); - } - } - else - { - WIN32_FIND_DATA wfd; - HANDLE handle; + res = fh.fstat (buf); + fh.close (); /* The number of links to a directory includes the number of subdirectories in the directory, since all those subdirectories point to it. @@ -1038,26 +1027,54 @@ stat_worker (const char *caller, const char *name, struct stat *buf, set the number of links to 2. */ /* Unfortunately the count of 2 confuses `find(1)' command. So let's try it with `1' as link count. */ - buf->st_nlink = (dtype == DRIVE_REMOTE ? 1 : num_entries (win32_name)); + if (atts != -1 && (atts & FILE_ATTRIBUTE_DIRECTORY)) + buf->st_nlink = + (dtype == DRIVE_REMOTE ? 1 : num_entries (win32_name)); + } + else if (atts != -1 || GetLastError () != ERROR_FILE_NOT_FOUND) + { + /* Unfortunately, the above open may fail. So we have + to care for this case here, too. */ + WIN32_FIND_DATA wfd; + HANDLE handle; + buf->st_nlink = 1; + if (atts != -1 + && (atts & FILE_ATTRIBUTE_DIRECTORY) + && dtype != DRIVE_REMOTE) + buf->st_nlink = num_entries (win32_name); buf->st_dev = FHDEVN(FH_DISK) << 8; buf->st_ino = hash_path_name (0, real_path.get_win32 ()); - buf->st_mode = S_IFDIR | STD_RBITS | STD_XBITS; - if ((atts & FILE_ATTRIBUTE_READONLY) == 0) - buf->st_mode |= STD_WBITS; - - get_file_attribute (real_path.has_acls (), real_path.get_win32 (), - NULL, &buf->st_uid, &buf->st_gid); - - if ((handle = FindFirstFile (real_path.get_win32(), &wfd)) != INVALID_HANDLE_VALUE) - { - buf->st_atime = to_time_t (&wfd.ftLastAccessTime); - buf->st_mtime = to_time_t (&wfd.ftLastWriteTime); - buf->st_ctime = to_time_t (&wfd.ftCreationTime); - buf->st_size = wfd.nFileSizeLow; - buf->st_blksize = S_BLKSIZE; - buf->st_blocks = (buf->st_size + S_BLKSIZE-1) / S_BLKSIZE; - FindClose (handle); - } + if (atts != -1 && (atts & FILE_ATTRIBUTE_DIRECTORY)) + buf->st_mode = S_IFDIR; + else if (real_path.issymlink ()) + buf->st_mode = S_IFLNK; + else if (real_path.issocket ()) + buf->st_mode = S_IFSOCK; + else + buf->st_mode = S_IFREG; + if (!real_path.has_acls () + || get_file_attribute (real_path.has_acls (), real_path.get_win32 (), + &buf->st_mode, &buf->st_uid, &buf->st_gid)) + { + buf->st_mode |= STD_RBITS | STD_XBITS; + if ((atts & FILE_ATTRIBUTE_READONLY) == 0) + buf->st_mode |= STD_WBITS; + get_file_attribute (FALSE, real_path.get_win32 (), + NULL, &buf->st_uid, &buf->st_gid); + } + if ((handle = FindFirstFile (real_path.get_win32(), &wfd)) + == INVALID_HANDLE_VALUE) + { + __seterrno (); + goto done; + } + buf->st_atime = to_time_t (&wfd.ftLastAccessTime); + buf->st_mtime = to_time_t (&wfd.ftLastWriteTime); + buf->st_ctime = to_time_t (&wfd.ftCreationTime); + buf->st_size = wfd.nFileSizeLow; + buf->st_blksize = S_BLKSIZE; + buf->st_blocks = (buf->st_size + S_BLKSIZE-1) / S_BLKSIZE; + FindClose (handle); res = 0; }