Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2004-04-14 17:40:07 +0400
committerCorinna Vinschen <corinna@vinschen.de>2004-04-14 17:40:07 +0400
commitddf9c4a7444970b5ad4c0ed4a82bdc7bd4964c15 (patch)
tree0f0c9b57900da5163c44f21cc1b3e7288e677d1f
parentba1a97a18b5d629f62c691d62c69fe97da903b05 (diff)
* fhandler.cc (fhandler_base::open): Accomodate query_write_control
query_state. (fhandler_base::fchown): New method. * fhandler.h: Declare fchown method in fhandler_base, fhandler_disk_file and fhandler_virtual. (enum query_state): Add query_write_control. * fhandler_disk_file.cc (fhandler_disk_file::fchmod): Set query_state to query_write_control. Only remove FILE_ATTRIBUTE_READONLY if not setting security descriptor. (fhandler_disk_file::fchown): New method. * fhandler_virtual.cc (fhandler_virtual::fchown): New method. * sec_acl.cc (setacl): Call write_sd with additional handle attribute. * security.cc (write_sd): Take handle argument. Only request owner if getting SE_RESTORE_NAME privilege failed. Only open file if NtSetSecurityObject failed or handle is NULL. (set_nt_attribute): Call write_sd with additional handle attribute. * security.h (write_sd): Declare with additional handle argument.
-rw-r--r--winsup/cygwin/ChangeLog20
-rw-r--r--winsup/cygwin/fhandler.cc20
-rw-r--r--winsup/cygwin/fhandler.h8
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc45
-rw-r--r--winsup/cygwin/fhandler_virtual.cc8
-rw-r--r--winsup/cygwin/sec_acl.cc2
-rw-r--r--winsup/cygwin/security.cc67
-rw-r--r--winsup/cygwin/security.h2
8 files changed, 131 insertions, 41 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 18fc01886..7ee5de3ec 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,5 +1,25 @@
2004-04-14 Corinna Vinschen <corinna@vinschen.de>
+ * fhandler.cc (fhandler_base::open): Accomodate query_write_control
+ query_state.
+ (fhandler_base::fchown): New method.
+ * fhandler.h: Declare fchown method in fhandler_base,
+ fhandler_disk_file and fhandler_virtual.
+ (enum query_state): Add query_write_control.
+ * fhandler_disk_file.cc (fhandler_disk_file::fchmod): Set query_state
+ to query_write_control. Only remove FILE_ATTRIBUTE_READONLY if not
+ setting security descriptor.
+ (fhandler_disk_file::fchown): New method.
+ * fhandler_virtual.cc (fhandler_virtual::fchown): New method.
+ * sec_acl.cc (setacl): Call write_sd with additional handle attribute.
+ * security.cc (write_sd): Take handle argument. Only request owner
+ if getting SE_RESTORE_NAME privilege failed. Only open file if
+ NtSetSecurityObject failed or handle is NULL.
+ (set_nt_attribute): Call write_sd with additional handle attribute.
+ * security.h (write_sd): Declare with additional handle argument.
+
+2004-04-14 Corinna Vinschen <corinna@vinschen.de>
+
* autoload.cc (NtSetSecurityObject): Add.
* fhandler_disk_file.cc (fhandler_disk_file::fchmod): Only request
READ_CONTROL rights when opening the file.
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index 540fca58c..b93102dd1 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -443,7 +443,18 @@ fhandler_base::open (int flags, mode_t mode)
}
if (query_open ())
- access = (query_open () == query_read_control ? READ_CONTROL : 0);
+ switch (query_open ())
+ {
+ case query_null_access:
+ access = 0;
+ break;
+ case query_read_control:
+ access = READ_CONTROL;
+ break;
+ case query_write_control:
+ access = READ_CONTROL | WRITE_OWNER | WRITE_DAC;
+ break;
+ }
else if (get_major () == DEV_TAPE_MAJOR)
access = GENERIC_READ | GENERIC_WRITE;
else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY)
@@ -1411,3 +1422,10 @@ fhandler_base::fchmod (mode_t mode)
/* By default, just succeeds. */
return 0;
}
+
+int
+fhandler_base::fchown (__uid32_t uid, __gid32_t gid)
+{
+ /* By default, just succeeds. */
+ return 0;
+}
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index ece8d4984..0ee198c54 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -62,8 +62,9 @@ enum bg_check_types
enum query_state {
no_query = 0,
- query_read_control = 1,
- query_null_access = 2
+ query_null_access = 1,
+ query_read_control = 2,
+ query_write_control = 3
};
class fhandler_base
@@ -243,6 +244,7 @@ class fhandler_base
int __stdcall fstat_by_handle (struct __stat64 *buf) __attribute__ ((regparm (2)));
int __stdcall fstat_by_name (struct __stat64 *buf) __attribute__ ((regparm (2)));
virtual int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1)));
+ virtual int __stdcall fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2)));
virtual int ioctl (unsigned int cmd, void *);
virtual int fcntl (int cmd, void *);
virtual char const *ttyname () { return get_name (); }
@@ -568,6 +570,7 @@ class fhandler_disk_file: public fhandler_base
bool isdevice () { return false; }
int __stdcall fstat (struct __stat64 *buf) __attribute__ ((regparm (2)));
int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1)));
+ int __stdcall fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2)));
HANDLE mmap (caddr_t *addr, size_t len, DWORD access, int flags, _off64_t off);
int munmap (HANDLE h, caddr_t addr, size_t len);
@@ -1101,6 +1104,7 @@ class fhandler_virtual : public fhandler_base
int close (void);
int __stdcall fstat (struct stat *buf) __attribute__ ((regparm (2)));
int __stdcall fchmod (mode_t mode) __attribute__ ((regparm (1)));
+ int __stdcall fchown (__uid32_t uid, __gid32_t gid) __attribute__ ((regparm (2)));
virtual bool fill_filebuf ();
void fixup_after_exec ();
};
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index 28f930617..f649d4dbd 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -377,14 +377,18 @@ fhandler_disk_file::fchmod (mode_t mode)
if (pc.is_fs_special ())
return chmod_device (pc, mode);
- query_open (query_read_control);
- if (!get_io_handle () && !(oret = open_fs (O_BINARY, 0)))
- return -1;
+ if (!get_io_handle ())
+ {
+ query_open (query_write_control);
+ if (!(oret = open_fs (O_BINARY, 0)))
+ return -1;
+ }
- SetFileAttributes (get_win32_name (), (DWORD) pc & ~FILE_ATTRIBUTE_READONLY);
+ if (!allow_ntsec && allow_ntea) /* Not necessary when manipulating SD. */
+ SetFileAttributes (pc, (DWORD) pc & ~FILE_ATTRIBUTE_READONLY);
if (pc.isdir ())
mode |= S_IFDIR;
- if (!set_file_attribute (pc.has_acls (), get_io_handle (), get_win32_name (),
+ if (!set_file_attribute (pc.has_acls (), get_io_handle (), pc,
ILLEGAL_UID, ILLEGAL_GID, mode)
&& allow_ntsec)
res = 0;
@@ -410,6 +414,37 @@ fhandler_disk_file::fchmod (mode_t mode)
return res;
}
+int __stdcall
+fhandler_disk_file::fchown (__uid32_t uid, __gid32_t gid)
+{
+ int oret = 0;
+ if (!get_io_handle ())
+ {
+ query_open (query_write_control);
+ if (!(oret = open_fs (O_BINARY, 0)))
+ return -1;
+ }
+
+ mode_t attrib = 0;
+ if (pc.isdir ())
+ attrib |= S_IFDIR;
+ int res = get_file_attribute (pc.has_acls (), get_io_handle (), pc, &attrib);
+ if (!res)
+ res = set_file_attribute (pc.has_acls (), get_io_handle (), pc,
+ uid, gid, attrib);
+ if (res && (!pc.has_acls () || !allow_ntsec))
+ {
+ /* fake - if not supported, pretend we're like win95
+ where it just works */
+ res = 0;
+ }
+
+ if (oret)
+ close_fs ();
+
+ return res;
+}
+
fhandler_disk_file::fhandler_disk_file () :
fhandler_base ()
{
diff --git a/winsup/cygwin/fhandler_virtual.cc b/winsup/cygwin/fhandler_virtual.cc
index 65be71b23..16b83923e 100644
--- a/winsup/cygwin/fhandler_virtual.cc
+++ b/winsup/cygwin/fhandler_virtual.cc
@@ -234,3 +234,11 @@ fhandler_virtual::fchmod (mode_t mode)
set_errno (EPERM);
return -1;
}
+
+int
+fhandler_virtual::fchown (__uid32_t uid, __gid32_t gid)
+{
+ /* Same as on Linux. */
+ set_errno (EPERM);
+ return -1;
+}
diff --git a/winsup/cygwin/sec_acl.cc b/winsup/cygwin/sec_acl.cc
index dc2473e9e..a8dbe2f90 100644
--- a/winsup/cygwin/sec_acl.cc
+++ b/winsup/cygwin/sec_acl.cc
@@ -223,7 +223,7 @@ setacl (const char *file, int nentries, __aclent32_t *aclbufp)
return -1;
}
debug_printf ("Created SD-Size: %d", sd_ret.size ());
- return write_sd (file, sd_ret);
+ return write_sd (NULL, file, sd_ret);
}
/* Temporary access denied bits */
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc
index c932c2441..0915a77e6 100644
--- a/winsup/cygwin/security.cc
+++ b/winsup/cygwin/security.cc
@@ -1117,16 +1117,8 @@ read_sd (const char *file, security_descriptor &sd)
}
LONG
-write_sd (const char *file, security_descriptor &sd)
+write_sd (HANDLE fh, const char *file, security_descriptor &sd)
{
- BOOL dummy;
- cygpsid owner;
-
- if (!GetSecurityDescriptorOwner (sd, (PSID *) &owner, &dummy))
- {
- __seterrno ();
- return -1;
- }
/* Try turning privilege on, may not have WRITE_OWNER or WRITE_DAC access.
Must have privilege to set different owner, else BackupWrite misbehaves */
static int NO_COPY saved_res; /* 0: never, 1: failed, 2 & 3: OK */
@@ -1140,29 +1132,42 @@ write_sd (const char *file, security_descriptor &sd)
}
else
res = saved_res;
- if (res == 1 && owner != cygheap->user.sid ())
- {
- set_errno (EPERM);
- return -1;
- }
- HANDLE fh;
- if ((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)) == INVALID_HANDLE_VALUE)
+ if (res == 1)
{
- __seterrno ();
- return -1;
+ BOOL dummy;
+ cygpsid owner;
+
+ if (!GetSecurityDescriptorOwner (sd, (PSID *) &owner, &dummy))
+ {
+ __seterrno ();
+ return -1;
+ }
+ if (owner != cygheap->user.sid ())
+ {
+ set_errno (EPERM);
+ return -1;
+ }
}
- NTSTATUS ret = NtSetSecurityObject (fh,
- DACL_SECURITY_INFORMATION
- | GROUP_SECURITY_INFORMATION
- | OWNER_SECURITY_INFORMATION,
- sd);
- CloseHandle (fh);
+ NTSTATUS ret;
+ int retry = 0;
+ for (; retry < 2; ++retry)
+ {
+ if (retry && (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)) == INVALID_HANDLE_VALUE)
+ break;
+ if (fh && (ret = NtSetSecurityObject (fh,
+ DACL_SECURITY_INFORMATION
+ | GROUP_SECURITY_INFORMATION
+ | OWNER_SECURITY_INFORMATION,
+ sd)) == STATUS_SUCCESS)
+ break;
+ }
+ if (retry && fh != INVALID_HANDLE_VALUE)
+ CloseHandle (fh);
if (ret != STATUS_SUCCESS)
{
__seterrno_from_win_error (RtlNtStatusToDosError (ret));
@@ -1802,7 +1807,7 @@ set_nt_attribute (HANDLE handle, const char *file,
if (!alloc_sd (uid, gid, attribute, sd))
return -1;
- return write_sd (file, sd);
+ return write_sd (handle, file, sd);
}
int
diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h
index 2fb7c8085..e81a8d8ae 100644
--- a/winsup/cygwin/security.h
+++ b/winsup/cygwin/security.h
@@ -256,7 +256,7 @@ int __stdcall set_file_attribute (bool, HANDLE, const char *, __uid32_t, __gid32
int __stdcall get_object_attribute (HANDLE handle, SE_OBJECT_TYPE object_type, mode_t *,
__uid32_t * = NULL, __gid32_t * = NULL);
LONG __stdcall read_sd (const char *file, security_descriptor &sd);
-LONG __stdcall write_sd (const char *file, security_descriptor &sd);
+LONG __stdcall write_sd (HANDLE fh, const char *file, security_descriptor &sd);
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);