* fhandler.cc (fhandler_base::open): When creating a file on a
filesystem supporting ACLs, create the file with WRITE_DAC access. Explain why. * fhandler_disk_file.cc (fhandler_disk_file::mkdir): Ditto for directories. * fhandler_socket.cc (fhandler_socket::bind): Ditto for sockets. * path.cc (symlink_worker): Ditto for symlinks. * security.cc (get_file_sd): Always call GetSecurityInfo for directories on XP and Server 2003. Improve comment to explain why. (set_file_attribute): Explicitely cast mode_t value to bool in call to get_file_sd. * wincap.h (wincaps::use_get_sec_info_on_dirs): New element. * wincap.cc: Implement above element throughout.
This commit is contained in:
parent
6777e53972
commit
69d7815eae
|
@ -1,3 +1,19 @@
|
||||||
|
2011-03-07 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
|
* fhandler.cc (fhandler_base::open): When creating a file on a
|
||||||
|
filesystem supporting ACLs, create the file with WRITE_DAC access.
|
||||||
|
Explain why.
|
||||||
|
* fhandler_disk_file.cc (fhandler_disk_file::mkdir): Ditto for
|
||||||
|
directories.
|
||||||
|
* fhandler_socket.cc (fhandler_socket::bind): Ditto for sockets.
|
||||||
|
* path.cc (symlink_worker): Ditto for symlinks.
|
||||||
|
* security.cc (get_file_sd): Always call GetSecurityInfo for directories
|
||||||
|
on XP and Server 2003. Improve comment to explain why.
|
||||||
|
(set_file_attribute): Explicitely cast mode_t value to bool in call to
|
||||||
|
get_file_sd.
|
||||||
|
* wincap.h (wincaps::use_get_sec_info_on_dirs): New element.
|
||||||
|
* wincap.cc: Implement above element throughout.
|
||||||
|
|
||||||
2011-03-04 Corinna Vinschen <corinna@vinschen.de>
|
2011-03-04 Corinna Vinschen <corinna@vinschen.de>
|
||||||
|
|
||||||
* fhandler_procsys.cc (fhandler_procsys::exists): Rewrite.
|
* fhandler_procsys.cc (fhandler_procsys::exists): Rewrite.
|
||||||
|
|
|
@ -577,6 +577,13 @@ fhandler_base::open (int flags, mode_t mode)
|
||||||
/* If mode has no write bits set, and ACLs are not used, we set
|
/* If mode has no write bits set, and ACLs are not used, we set
|
||||||
the DOS R/O attribute. */
|
the DOS R/O attribute. */
|
||||||
file_attributes |= FILE_ATTRIBUTE_READONLY;
|
file_attributes |= FILE_ATTRIBUTE_READONLY;
|
||||||
|
else if (!exists () && has_acls ())
|
||||||
|
/* If we are about to create the file and the filesystem supports
|
||||||
|
ACLs, we will overwrite the DACL after the call to NtCreateFile.
|
||||||
|
This requires a handle with additional WRITE_DAC access,
|
||||||
|
otherwise set_file_sd has to open the file again. */
|
||||||
|
access |= WRITE_DAC;
|
||||||
|
|
||||||
/* The file attributes are needed for later use in, e.g. fchmod. */
|
/* The file attributes are needed for later use in, e.g. fchmod. */
|
||||||
pc.file_attributes (file_attributes);
|
pc.file_attributes (file_attributes);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1460,6 +1460,7 @@ fhandler_disk_file::mkdir (mode_t mode)
|
||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
PFILE_FULL_EA_INFORMATION p = NULL;
|
PFILE_FULL_EA_INFORMATION p = NULL;
|
||||||
ULONG plen = 0;
|
ULONG plen = 0;
|
||||||
|
ULONG access = FILE_LIST_DIRECTORY | SYNCHRONIZE;
|
||||||
|
|
||||||
if (pc.fs_is_nfs ())
|
if (pc.fs_is_nfs ())
|
||||||
{
|
{
|
||||||
|
@ -1479,8 +1480,13 @@ fhandler_disk_file::mkdir (mode_t mode)
|
||||||
nfs_attr->type = NF3DIR;
|
nfs_attr->type = NF3DIR;
|
||||||
nfs_attr->mode = (mode & 07777) & ~cygheap->umask;
|
nfs_attr->mode = (mode & 07777) & ~cygheap->umask;
|
||||||
}
|
}
|
||||||
status = NtCreateFile (&dir, FILE_LIST_DIRECTORY | SYNCHRONIZE,
|
else if (has_acls ())
|
||||||
pc.get_object_attr (attr, sa), &io, NULL,
|
/* If the filesystem supports ACLs, we will overwrite the DACL after the
|
||||||
|
call to NtCreateFile. This requires a handle with READ_CONTROL and
|
||||||
|
WRITE_DAC access, otherwise get_file_sd and set_file_sd both have to
|
||||||
|
open the file again. */
|
||||||
|
access |= READ_CONTROL | WRITE_DAC;
|
||||||
|
status = NtCreateFile (&dir, access, pc.get_object_attr (attr, sa), &io, NULL,
|
||||||
FILE_ATTRIBUTE_DIRECTORY, FILE_SHARE_VALID_FLAGS,
|
FILE_ATTRIBUTE_DIRECTORY, FILE_SHARE_VALID_FLAGS,
|
||||||
FILE_CREATE,
|
FILE_CREATE,
|
||||||
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
|
FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT
|
||||||
|
|
|
@ -996,10 +996,17 @@ fhandler_socket::bind (const struct sockaddr *name, int namelen)
|
||||||
HANDLE fh;
|
HANDLE fh;
|
||||||
OBJECT_ATTRIBUTES attr;
|
OBJECT_ATTRIBUTES attr;
|
||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
|
ULONG access = DELETE | FILE_GENERIC_WRITE;
|
||||||
|
|
||||||
status = NtCreateFile (&fh, DELETE | FILE_GENERIC_WRITE,
|
/* If the filesystem supports ACLs, we will overwrite the DACL after the
|
||||||
pc.get_object_attr (attr, sa), &io, NULL, fattr,
|
call to NtCreateFile. This requires a handle with READ_CONTROL and
|
||||||
0, FILE_CREATE,
|
WRITE_DAC access, otherwise get_file_sd and set_file_sd both have to
|
||||||
|
open the file again. */
|
||||||
|
if (pc.has_acls ())
|
||||||
|
access |= READ_CONTROL | WRITE_DAC;
|
||||||
|
|
||||||
|
status = NtCreateFile (&fh, access, pc.get_object_attr (attr, sa), &io,
|
||||||
|
NULL, fattr, 0, FILE_CREATE,
|
||||||
FILE_NON_DIRECTORY_FILE
|
FILE_NON_DIRECTORY_FILE
|
||||||
| FILE_SYNCHRONOUS_IO_NONALERT
|
| FILE_SYNCHRONOUS_IO_NONALERT
|
||||||
| FILE_OPEN_FOR_BACKUP_INTENT,
|
| FILE_OPEN_FOR_BACKUP_INTENT,
|
||||||
|
|
|
@ -1415,6 +1415,7 @@ symlink_worker (const char *oldpath, const char *newpath, bool use_winsym,
|
||||||
IO_STATUS_BLOCK io;
|
IO_STATUS_BLOCK io;
|
||||||
NTSTATUS status;
|
NTSTATUS status;
|
||||||
HANDLE fh;
|
HANDLE fh;
|
||||||
|
ULONG access = DELETE | FILE_GENERIC_WRITE;
|
||||||
tmp_pathbuf tp;
|
tmp_pathbuf tp;
|
||||||
unsigned check_opt;
|
unsigned check_opt;
|
||||||
bool mk_winsym = use_winsym;
|
bool mk_winsym = use_winsym;
|
||||||
|
@ -1671,8 +1672,14 @@ symlink_worker (const char *oldpath, const char *newpath, bool use_winsym,
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
status = NtCreateFile (&fh, DELETE | FILE_GENERIC_WRITE,
|
else if (!isdevice && win32_newpath.has_acls ())
|
||||||
win32_newpath.get_object_attr (attr, sa),
|
/* If the filesystem supports ACLs, we will overwrite the DACL after the
|
||||||
|
call to NtCreateFile. This requires a handle with READ_CONTROL and
|
||||||
|
WRITE_DAC access, otherwise get_file_sd and set_file_sd both have to
|
||||||
|
open the file again. */
|
||||||
|
access |= READ_CONTROL | WRITE_DAC;
|
||||||
|
|
||||||
|
status = NtCreateFile (&fh, access, win32_newpath.get_object_attr (attr, sa),
|
||||||
&io, NULL, FILE_ATTRIBUTE_NORMAL,
|
&io, NULL, FILE_ATTRIBUTE_NORMAL,
|
||||||
FILE_SHARE_VALID_FLAGS,
|
FILE_SHARE_VALID_FLAGS,
|
||||||
isdevice ? FILE_OVERWRITE_IF : FILE_CREATE,
|
isdevice ? FILE_OVERWRITE_IF : FILE_CREATE,
|
||||||
|
|
|
@ -43,21 +43,31 @@ get_file_sd (HANDLE fh, path_conv &pc, security_descriptor &sd,
|
||||||
{
|
{
|
||||||
if (fh)
|
if (fh)
|
||||||
{
|
{
|
||||||
if (justcreated)
|
/* Amazing but true. If you want to know if an ACE is inherited
|
||||||
|
from the parent object, you can't use the NtQuerySecurityObject
|
||||||
|
function. In the DACL returned by this functions, the
|
||||||
|
INHERITED_ACE flag is never set. Only by calling GetSecurityInfo
|
||||||
|
you get this information.
|
||||||
|
|
||||||
|
However, this functionality is slow, and the extra information is
|
||||||
|
only required when the file has been created and the permissions
|
||||||
|
are about to be set to POSIX permissions. Therefore we only use
|
||||||
|
it in case the file just got created. In all other cases we
|
||||||
|
rather call NtQuerySecurityObject directly...
|
||||||
|
|
||||||
|
...except that there's a problem on 5.1 and 5.2 kernels. The
|
||||||
|
GetSecurityInfo call on a file sometimes returns with
|
||||||
|
ERROR_INVALID_ADDRESS if a former request for the SD of the
|
||||||
|
parent directory (or one of the parent directories?) used the
|
||||||
|
NtQuerySecurityObject call, rather than GetSecurityInfo as well.
|
||||||
|
As soon as all directory SDs are fetched using GetSecurityInfo,
|
||||||
|
the problem disappears. */
|
||||||
|
if (justcreated
|
||||||
|
|| (pc.isdir () && wincap.use_get_sec_info_on_dirs ()))
|
||||||
{
|
{
|
||||||
/* Amazing but true. If you want to know if an ACE is inherited
|
|
||||||
from the parent object, you can't use the NtQuerySecurityObject
|
|
||||||
function. In the DACL returned by this functions, the
|
|
||||||
INHERITED_ACE flag is never set. Only by calling
|
|
||||||
GetSecurityInfo you get this information.
|
|
||||||
|
|
||||||
This functionality is slow, and the extra information is only
|
|
||||||
required when the file has been created and the permissions
|
|
||||||
are about to be set to POSIX permissions. Therefore we only
|
|
||||||
use it in case the file just got created. In all other cases
|
|
||||||
we rather call NtQuerySecurityObject directly. */
|
|
||||||
PSECURITY_DESCRIPTOR psd;
|
PSECURITY_DESCRIPTOR psd;
|
||||||
error = GetSecurityInfo (fh, SE_FILE_OBJECT, ALL_SECURITY_INFORMATION,
|
error = GetSecurityInfo (fh, SE_FILE_OBJECT,
|
||||||
|
ALL_SECURITY_INFORMATION,
|
||||||
NULL, NULL, NULL, NULL, &psd);
|
NULL, NULL, NULL, NULL, &psd);
|
||||||
if (error == ERROR_SUCCESS)
|
if (error == ERROR_SUCCESS)
|
||||||
{
|
{
|
||||||
|
@ -876,7 +886,7 @@ set_file_attribute (HANDLE handle, path_conv &pc,
|
||||||
{
|
{
|
||||||
security_descriptor sd;
|
security_descriptor sd;
|
||||||
|
|
||||||
if (!get_file_sd (handle, pc, sd, attribute & S_JUSTCREATED)
|
if (!get_file_sd (handle, pc, sd, (bool)(attribute & S_JUSTCREATED))
|
||||||
&& alloc_sd (pc, uid, gid, attribute, sd))
|
&& alloc_sd (pc, uid, gid, attribute, sd))
|
||||||
ret = set_file_sd (handle, pc, sd,
|
ret = set_file_sd (handle, pc, sd,
|
||||||
uid != ILLEGAL_UID || gid != ILLEGAL_GID);
|
uid != ILLEGAL_UID || gid != ILLEGAL_GID);
|
||||||
|
|
|
@ -62,6 +62,7 @@ wincaps wincap_nt4sp4 __attribute__((section (".cygwin_dll_common"), shared)) =
|
||||||
has_fast_cwd:false,
|
has_fast_cwd:false,
|
||||||
has_restricted_raw_disk_access:false,
|
has_restricted_raw_disk_access:false,
|
||||||
use_dont_resolve_hack:false,
|
use_dont_resolve_hack:false,
|
||||||
|
use_get_sec_info_on_dirs:false,
|
||||||
};
|
};
|
||||||
|
|
||||||
wincaps wincap_2000 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
wincaps wincap_2000 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
||||||
|
@ -103,6 +104,7 @@ wincaps wincap_2000 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
||||||
has_fast_cwd:false,
|
has_fast_cwd:false,
|
||||||
has_restricted_raw_disk_access:false,
|
has_restricted_raw_disk_access:false,
|
||||||
use_dont_resolve_hack:false,
|
use_dont_resolve_hack:false,
|
||||||
|
use_get_sec_info_on_dirs:false,
|
||||||
};
|
};
|
||||||
|
|
||||||
wincaps wincap_2000sp4 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
wincaps wincap_2000sp4 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
||||||
|
@ -144,6 +146,7 @@ wincaps wincap_2000sp4 __attribute__((section (".cygwin_dll_common"), shared)) =
|
||||||
has_fast_cwd:false,
|
has_fast_cwd:false,
|
||||||
has_restricted_raw_disk_access:false,
|
has_restricted_raw_disk_access:false,
|
||||||
use_dont_resolve_hack:false,
|
use_dont_resolve_hack:false,
|
||||||
|
use_get_sec_info_on_dirs:false,
|
||||||
};
|
};
|
||||||
|
|
||||||
wincaps wincap_xp __attribute__((section (".cygwin_dll_common"), shared)) = {
|
wincaps wincap_xp __attribute__((section (".cygwin_dll_common"), shared)) = {
|
||||||
|
@ -185,6 +188,7 @@ wincaps wincap_xp __attribute__((section (".cygwin_dll_common"), shared)) = {
|
||||||
has_fast_cwd:false,
|
has_fast_cwd:false,
|
||||||
has_restricted_raw_disk_access:false,
|
has_restricted_raw_disk_access:false,
|
||||||
use_dont_resolve_hack:true,
|
use_dont_resolve_hack:true,
|
||||||
|
use_get_sec_info_on_dirs:true,
|
||||||
};
|
};
|
||||||
|
|
||||||
wincaps wincap_xpsp1 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
wincaps wincap_xpsp1 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
||||||
|
@ -226,6 +230,7 @@ wincaps wincap_xpsp1 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
||||||
has_fast_cwd:false,
|
has_fast_cwd:false,
|
||||||
has_restricted_raw_disk_access:false,
|
has_restricted_raw_disk_access:false,
|
||||||
use_dont_resolve_hack:true,
|
use_dont_resolve_hack:true,
|
||||||
|
use_get_sec_info_on_dirs:true,
|
||||||
};
|
};
|
||||||
|
|
||||||
wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
||||||
|
@ -267,6 +272,7 @@ wincaps wincap_xpsp2 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
||||||
has_fast_cwd:false,
|
has_fast_cwd:false,
|
||||||
has_restricted_raw_disk_access:false,
|
has_restricted_raw_disk_access:false,
|
||||||
use_dont_resolve_hack:true,
|
use_dont_resolve_hack:true,
|
||||||
|
use_get_sec_info_on_dirs:true,
|
||||||
};
|
};
|
||||||
|
|
||||||
wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
||||||
|
@ -308,6 +314,7 @@ wincaps wincap_2003 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
||||||
has_fast_cwd:false,
|
has_fast_cwd:false,
|
||||||
has_restricted_raw_disk_access:false,
|
has_restricted_raw_disk_access:false,
|
||||||
use_dont_resolve_hack:false,
|
use_dont_resolve_hack:false,
|
||||||
|
use_get_sec_info_on_dirs:true,
|
||||||
};
|
};
|
||||||
|
|
||||||
wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
|
wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
|
||||||
|
@ -349,6 +356,7 @@ wincaps wincap_vista __attribute__((section (".cygwin_dll_common"), shared)) = {
|
||||||
has_fast_cwd:true,
|
has_fast_cwd:true,
|
||||||
has_restricted_raw_disk_access:true,
|
has_restricted_raw_disk_access:true,
|
||||||
use_dont_resolve_hack:false,
|
use_dont_resolve_hack:false,
|
||||||
|
use_get_sec_info_on_dirs:false,
|
||||||
};
|
};
|
||||||
|
|
||||||
wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
||||||
|
@ -390,6 +398,7 @@ wincaps wincap_7 __attribute__((section (".cygwin_dll_common"), shared)) = {
|
||||||
has_fast_cwd:true,
|
has_fast_cwd:true,
|
||||||
has_restricted_raw_disk_access:true,
|
has_restricted_raw_disk_access:true,
|
||||||
use_dont_resolve_hack:false,
|
use_dont_resolve_hack:false,
|
||||||
|
use_get_sec_info_on_dirs:false,
|
||||||
};
|
};
|
||||||
|
|
||||||
wincapc wincap __attribute__((section (".cygwin_dll_common"), shared));
|
wincapc wincap __attribute__((section (".cygwin_dll_common"), shared));
|
||||||
|
|
|
@ -52,6 +52,7 @@ struct wincaps
|
||||||
unsigned has_fast_cwd : 1;
|
unsigned has_fast_cwd : 1;
|
||||||
unsigned has_restricted_raw_disk_access : 1;
|
unsigned has_restricted_raw_disk_access : 1;
|
||||||
unsigned use_dont_resolve_hack : 1;
|
unsigned use_dont_resolve_hack : 1;
|
||||||
|
unsigned use_get_sec_info_on_dirs : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
class wincapc
|
class wincapc
|
||||||
|
@ -109,6 +110,7 @@ public:
|
||||||
bool IMPLEMENT (has_fast_cwd)
|
bool IMPLEMENT (has_fast_cwd)
|
||||||
bool IMPLEMENT (has_restricted_raw_disk_access)
|
bool IMPLEMENT (has_restricted_raw_disk_access)
|
||||||
bool IMPLEMENT (use_dont_resolve_hack)
|
bool IMPLEMENT (use_dont_resolve_hack)
|
||||||
|
bool IMPLEMENT (use_get_sec_info_on_dirs)
|
||||||
|
|
||||||
#undef IMPLEMENT
|
#undef IMPLEMENT
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue