diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2006-10-16 16:26:59 +0400 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2006-10-16 16:26:59 +0400 |
commit | 2c1ffdbf5e6f2767ab63e67834530539d36c6c0b (patch) | |
tree | 52cf8a418ca2727ea55f7918705fa7067275066b /winsup/cygwin/security.cc | |
parent | 7af26e0cc039517e3528ccedee7b778f479104c9 (diff) |
* autoload.cc (PrivilegeCheck): Define.
* fhandler.cc (fhandler_base::open): Always try opening with backup
resp. restore intent.
* fhandler_disk_file.cc (fhandler_disk_file::opendir): Always try
opening with backup intent.
(fhandler_disk_file::readdir): Ditto when trying to retrieve file id
explicitely.
* security.cc (check_file_access): Replace pbuf with correctly
PPRIVILEGE_SET typed pset. Check explicitely for backup and/or restore
privileges when AccessCheck fails, to circumvent AccessCheck
shortcoming. Add comment to explain.
Diffstat (limited to 'winsup/cygwin/security.cc')
-rw-r--r-- | winsup/cygwin/security.cc | 45 |
1 files changed, 41 insertions, 4 deletions
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index a0bcba33b..5484b7028 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -1953,8 +1953,9 @@ check_file_access (const char *fn, int flags) HANDLE hToken; BOOL status; - char pbuf[sizeof (PRIVILEGE_SET) + 3 * sizeof (LUID_AND_ATTRIBUTES)]; - DWORD desired = 0, granted, plength = sizeof pbuf; + DWORD desired = 0, granted; + DWORD plength = sizeof (PRIVILEGE_SET) + 3 * sizeof (LUID_AND_ATTRIBUTES); + PPRIVILEGE_SET pset = (PPRIVILEGE_SET) alloca (plength); static GENERIC_MAPPING NO_COPY mapping = { FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE, @@ -1974,10 +1975,46 @@ check_file_access (const char *fn, int flags) if (flags & X_OK) desired |= FILE_EXECUTE; if (!AccessCheck (sd, hToken, desired, &mapping, - (PPRIVILEGE_SET) pbuf, &plength, &granted, &status)) + pset, &plength, &granted, &status)) __seterrno (); else if (!status) - set_errno (EACCES); + { + /* CV, 2006-10-16: Now, that's really weird. Imagine a user who has no + standard access to a file, but who has backup and restore privileges + and these privileges are enabled in the access token. One would + expect that the AccessCheck function takes this into consideration + when returning the access status. Otherwise, why bother with the + pset parameter, right? + But not so. AccessCheck actually returns a status of "false" here, + even though opening a file with backup resp. restore intent + naturally succeeds for this user. This definitely spoils the results + of access(2) for administrative users or the SYSTEM account. So, in + case the access check fails, another check against the user's + backup/restore privileges has to be made. Sigh. */ + int granted_flags = 0; + if (flags & R_OK) + { + pset->PrivilegeCount = 1; + pset->Control = 0; + pset->Privilege[0].Luid = *privilege_luid (SE_BACKUP_PRIV); + pset->Privilege[0].Attributes = 0; + if (PrivilegeCheck (hToken, pset, &status) && status) + granted_flags |= R_OK; + } + if (flags & W_OK) + { + pset->PrivilegeCount = 1; + pset->Control = 0; + pset->Privilege[0].Luid = *privilege_luid (SE_RESTORE_PRIV); + pset->Privilege[0].Attributes = 0; + if (PrivilegeCheck (hToken, pset, &status) && status) + granted_flags |= W_OK; + } + if (granted_flags == flags) + ret = 0; + else + set_errno (EACCES); + } else ret = 0; done: |