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:
-rw-r--r--winsup/cygwin/ChangeLog35
-rw-r--r--winsup/cygwin/autoload.cc1
-rw-r--r--winsup/cygwin/dir.cc2
-rw-r--r--winsup/cygwin/fhandler.cc206
-rw-r--r--winsup/cygwin/fhandler.h5
-rw-r--r--winsup/cygwin/fhandler_disk_file.cc83
-rw-r--r--winsup/cygwin/fhandler_raw.cc33
-rw-r--r--winsup/cygwin/ntdll.h3
-rw-r--r--winsup/cygwin/path.cc3
-rw-r--r--winsup/cygwin/sec_acl.cc2
-rw-r--r--winsup/cygwin/sec_helper.cc14
-rw-r--r--winsup/cygwin/security.cc41
-rw-r--r--winsup/cygwin/security.h6
-rw-r--r--winsup/cygwin/syscalls.cc3
14 files changed, 293 insertions, 144 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 669c5c9e7..df7cf3eff 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,38 @@
+2004-04-16 Corinna Vinschen <corinna@vinschen.de>
+
+ * autoload.cc (NtCreateFile): Add.
+ * dir.cc (mkdir): Change set_file_attribute call to indicate that
+ NT security isn't used.
+ * fhandler.cc (fhandler_base::open_9x): New method, created from
+ fhandler_base::open.
+ (fhandler_base::open): Rearrange to use NtCreateFile instead of
+ CreateFile.
+ * fhandler.h (enum query_state): Redefine query_null_access to
+ query_stat_control. query_null_access isn't allowed in NtCreateFile.
+ (fhandler_base::open_9x): Declare.
+ * fhandler_disk_file.cc (fhandler_base::fstat_fs): Use
+ query_stat_control first, query_read_control if that fails.
+ (fhandler_disk_file::fchmod): Call enable_restore_privilege before
+ trying to open for query_write_control. Don't fall back to
+ opening for query_read_control.
+ (fhandler_disk_file::fchown): Ditto.
+ (fhandler_disk_file::facl): Only request restore privilege and query
+ access necessary for given cmd.
+ * fhandler_raw.cc (fhandler_dev_raw::open): Call fhandler_base::open
+ instead of opening device here.
+ * ntdll.h (NtCreateFile): Declare.
+ * path.cc (symlink_worker): Change set_file_attribute call to indicate
+ that NT security isn't used.
+ * sec_acl.cc (getacl): Fix bracketing.
+ * sec_helper.cc (enable_restore_privilege): New function.
+ * security.cc (str2buf2uni_cat): New function.
+ (write_sd): Don't request restore permission here.
+ * security.h (set_process_privileges): Drop stale declaration.
+ (str2buf2uni): Declare.
+ (str2buf2uni_cat): Declare.
+ (enable_restore_privilege): Declare.
+ * syscalls.cc (fchown32): Return immediate success on 9x.
+
2004-04-15 Christopher Faylor <cgf@alum.bu.edu>
* autoload.cc (dll_chain1): Rename to dll_chain. Remove old dll_chain
diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc
index 7e9e71536..bccc3ad72 100644
--- a/winsup/cygwin/autoload.cc
+++ b/winsup/cygwin/autoload.cc
@@ -375,6 +375,7 @@ LoadDLLfunc (NetUserGetGroups, 28, netapi32)
LoadDLLfunc (NetUserGetInfo, 16, netapi32)
LoadDLLfunc (NetWkstaUserGetInfo, 12, netapi32)
+LoadDLLfuncEx (NtCreateFile, 44, ntdll, 1)
LoadDLLfuncEx (NtCreateToken, 52, ntdll, 1)
LoadDLLfuncEx (NtMapViewOfSection, 40, ntdll, 1)
LoadDLLfuncEx (NtOpenFile, 24, ntdll, 1)
diff --git a/winsup/cygwin/dir.cc b/winsup/cygwin/dir.cc
index 4fc1932da..1bb7f0013 100644
--- a/winsup/cygwin/dir.cc
+++ b/winsup/cygwin/dir.cc
@@ -284,7 +284,7 @@ mkdir (const char *dir, mode_t mode)
if (CreateDirectoryA (real_dir.get_win32 (), &sa))
{
if (!allow_ntsec && allow_ntea)
- set_file_attribute (real_dir.has_acls (), NULL, real_dir.get_win32 (),
+ set_file_attribute (false, NULL, real_dir.get_win32 (),
S_IFDIR | ((mode & 07777) & ~cygheap->umask));
#ifdef HIDDEN_DOT_FILES
char *c = strrchr (real_dir.get_win32 (), '\\');
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index af9d63313..f1dfed8c4 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -28,6 +28,8 @@ details. */
#include <assert.h>
#include <limits.h>
#include <winioctl.h>
+#include <ntdef.h>
+#include "ntdll.h"
static NO_COPY const int CHUNK_SIZE = 1024; /* Used for crlf conversions */
@@ -425,7 +427,7 @@ done:
/* Open system call handler function. */
int
-fhandler_base::open (int flags, mode_t mode)
+fhandler_base::open_9x (int flags, mode_t mode)
{
int res = 0;
HANDLE x;
@@ -435,7 +437,7 @@ fhandler_base::open (int flags, mode_t mode)
SECURITY_ATTRIBUTES sa = sec_none;
security_descriptor sd;
- syscall_printf ("(%s, %p) query_open %d", get_win32_name (), flags, query_open ());
+ syscall_printf ("(%s, %p)", get_win32_name (), flags);
if (get_win32_name () == NULL)
{
@@ -443,34 +445,12 @@ fhandler_base::open (int flags, mode_t mode)
goto done;
}
- 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;
- default:
- if (get_major () == DEV_TAPE_MAJOR)
- access = GENERIC_READ | GENERIC_WRITE;
- else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY)
- access = GENERIC_READ;
- else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY)
- access = GENERIC_WRITE;
- else
- access = GENERIC_READ | GENERIC_WRITE;
- break;
- }
-
- /* Allow reliable lseek on disk devices. */
- if (get_major () == DEV_FLOPPY_MAJOR)
- access |= GENERIC_READ;
-
- /* FIXME: O_EXCL handling? */
+ if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY)
+ access = GENERIC_READ;
+ else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY)
+ access = GENERIC_WRITE;
+ else
+ access = GENERIC_READ | GENERIC_WRITE;
if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY))
{
@@ -508,16 +488,6 @@ fhandler_base::open (int flags, mode_t mode)
}
#endif
- /* CreateFile() with dwDesiredAccess == 0 when called on remote
- share returns some handle, even if file doesn't exist. This code
- works around this bug. */
- if (query_open () && isremote () &&
- creation_distribution == OPEN_EXISTING && !pc.exists ())
- {
- set_errno (ENOENT);
- goto done;
- }
-
/* If mode has no write bits set, we set the R/O attribute. */
if (!(mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
file_attributes |= FILE_ATTRIBUTE_READONLY;
@@ -564,6 +534,162 @@ done:
return res;
}
+/* Open system call handler function. */
+int
+fhandler_base::open (int flags, mode_t mode)
+{
+ if (!wincap.is_winnt ())
+ return fhandler_base::open_9x (flags, mode);
+
+ int res = 0;
+ HANDLE x;
+ ULONG file_attributes = 0;
+ ULONG shared = wincap.shared ();
+ ULONG create_disposition;
+ ULONG create_options;
+ SECURITY_ATTRIBUTES sa = sec_none;
+ security_descriptor sd;
+ UNICODE_STRING upath;
+ WCHAR wpath[CYG_MAX_PATH + 10];
+ OBJECT_ATTRIBUTES attr;
+ IO_STATUS_BLOCK io;
+ NTSTATUS status;
+
+ syscall_printf ("(%s, %p)", get_win32_name (), flags);
+ if (get_win32_name () == NULL)
+ {
+ set_errno (ENOENT);
+ goto done;
+ }
+ if (get_win32_name ()[0] == '\\')
+ {
+ if (get_win32_name ()[1] == '\\')
+ {
+ str2buf2uni (upath, wpath, "\\??\\UNC");
+ str2buf2uni_cat (upath, get_win32_name () + 1);
+ }
+ else
+ str2buf2uni (upath, wpath, get_win32_name ());
+ }
+ else
+ {
+ str2buf2uni (upath, wpath, "\\??\\");
+ str2buf2uni_cat (upath, get_win32_name ());
+ }
+ InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
+ sa.lpSecurityDescriptor, NULL);
+
+ switch (query_open ())
+ {
+ case query_read_control:
+ access = READ_CONTROL;
+ create_options = FILE_OPEN_FOR_BACKUP_INTENT;
+ break;
+ case query_stat_control:
+ access = READ_CONTROL | FILE_READ_ATTRIBUTES;
+ create_options = FILE_OPEN_FOR_BACKUP_INTENT;
+ break;
+ case query_write_control:
+ access = READ_CONTROL | WRITE_OWNER | WRITE_DAC;
+ create_options = FILE_OPEN_FOR_BACKUP_INTENT | FILE_OPEN_FOR_RECOVERY;
+ break;
+ default:
+ create_options = 0;
+ if (get_major () == DEV_TAPE_MAJOR && (flags & O_TEXT))
+ {
+ /* O_TEXT is used to indicate write-through on tape devices */
+ create_options |= FILE_WRITE_THROUGH;
+ flags &= ~O_TEXT;
+ }
+ if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY)
+ access = GENERIC_READ;
+ else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY)
+ access = GENERIC_WRITE;
+ else
+ access = GENERIC_READ | GENERIC_WRITE;
+ /* Allow reliable lseek on disk devices. */
+ if (get_major () == DEV_FLOPPY_MAJOR)
+ access |= GENERIC_READ;
+ else if (get_major () != DEV_SERIAL_MAJOR)
+ {
+ create_options |= FILE_SYNCHRONOUS_IO_NONALERT;
+ access |= SYNCHRONIZE;
+ }
+ break;
+ }
+
+ if ((flags & O_TRUNC) && ((flags & O_ACCMODE) != O_RDONLY))
+ {
+ if (flags & O_CREAT)
+ create_disposition = FILE_SUPERSEDE;
+ else
+ create_disposition = FILE_OVERWRITE;
+ }
+ else if (flags & O_CREAT)
+ create_disposition = FILE_OPEN_IF;
+ else
+ create_disposition = FILE_OPEN;
+
+ if ((flags & O_EXCL) && (flags & O_CREAT))
+ create_disposition = FILE_CREATE;
+
+ if (flags & O_APPEND)
+ append_mode (true);
+
+ if (flags & O_CREAT && get_device () == FH_FS)
+ {
+ file_attributes = FILE_ATTRIBUTE_NORMAL;
+ /* If mode has no write bits set, we set the R/O attribute. */
+ if (!(mode & (S_IWUSR | S_IWGRP | S_IWOTH)))
+ file_attributes |= FILE_ATTRIBUTE_READONLY;
+#ifdef HIDDEN_DOT_FILES
+ char *c = strrchr (get_win32_name (), '\\');
+ if ((c && c[1] == '.') || *get_win32_name () == '.')
+ file_attributes |= FILE_ATTRIBUTE_HIDDEN;
+#endif
+ /* If the file should actually be created and ntsec is on,
+ set files attributes. */
+ if (allow_ntsec && has_acls ())
+ {
+ set_security_attribute (mode, &sa, sd);
+ attr.SecurityDescriptor = sa.lpSecurityDescriptor;
+ }
+ }
+
+ status = NtCreateFile (&x, access, &attr, &io, NULL, file_attributes, shared,
+ create_disposition, create_options, NULL, 0);
+ if (!NT_SUCCESS (status))
+ {
+ if (!wincap.can_open_directories () && pc.isdir ())
+ {
+ if (flags & (O_CREAT | O_EXCL) == (O_CREAT | O_EXCL))
+ set_errno (EEXIST);
+ else if (flags & (O_WRONLY | O_RDWR))
+ set_errno (EISDIR);
+ else
+ nohandle (true);
+ }
+ __seterrno_from_win_error (RtlNtStatusToDosError (status));
+ if (!nohandle ())
+ goto done;
+ }
+
+ syscall_printf ("%x = NtCreateFile "
+ "(%p, %x, %s, io, NULL, %x, %x, %x, %x, NULL, 0)",
+ status, x, access, get_win32_name (), file_attributes, shared,
+ create_disposition, create_options);
+
+ set_io_handle (x);
+ set_flags (flags, pc.binmode ());
+
+ res = 1;
+ set_open_status ();
+done:
+ syscall_printf ("%d = fhandler_base::open (%s, %p)", res, get_win32_name (),
+ flags);
+ return res;
+}
+
/* states:
open buffer in binary mode? Just do the read.
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 3e27b7b8f..17f3ade02 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -63,8 +63,8 @@ enum bg_check_types
enum query_state {
no_query = 0,
- query_null_access = 1,
- query_read_control = 2,
+ query_read_control = 1,
+ query_stat_control = 2,
query_write_control = 3
};
@@ -226,6 +226,7 @@ class fhandler_base
void fork_fixup (HANDLE parent, HANDLE &h, const char *name);
virtual bool need_fixup_before () const {return false;}
+ int open_9x (int flags, mode_t mode = 0);
virtual int open (int flags, mode_t mode = 0);
int open_fs (int flags, mode_t mode = 0);
virtual int close ();
diff --git a/winsup/cygwin/fhandler_disk_file.cc b/winsup/cygwin/fhandler_disk_file.cc
index 9b1d769c8..fcc4417e3 100644
--- a/winsup/cygwin/fhandler_disk_file.cc
+++ b/winsup/cygwin/fhandler_disk_file.cc
@@ -174,16 +174,16 @@ fhandler_base::fstat_fs (struct __stat64 *buf)
then just do a "query open" as it is apparently much faster. */
if (pc.exec_state () != dont_know_if_executable)
{
- query_open (query_read_control);
if (pc.fs_is_fat () && !strpbrk (get_win32_name (), "?*|<>"))
return fstat_by_name (buf);
+ query_open (query_stat_control);
}
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);
- query_open (query_null_access);
+ query_open (query_read_control);
oret = open_fs (open_flags, 0);
}
@@ -378,15 +378,15 @@ fhandler_disk_file::fchmod (mode_t mode)
if (pc.is_fs_special ())
return chmod_device (pc, mode);
- if (!get_io_handle ())
+ if (wincap.has_security ())
{
- query_open (query_write_control);
- if (!(oret = open_fs (O_BINARY, 0)))
- {
- query_open (query_read_control);
+ enable_restore_privilege ();
+ if (!get_io_handle ())
+ {
+ query_open (query_write_control);
if (!(oret = open_fs (O_BINARY, 0)))
return -1;
- }
+ }
}
if (!allow_ntsec && allow_ntea) /* Not necessary when manipulating SD. */
@@ -423,15 +423,13 @@ int __stdcall
fhandler_disk_file::fchown (__uid32_t uid, __gid32_t gid)
{
int oret = 0;
+
+ enable_restore_privilege ();
if (!get_io_handle ())
{
query_open (query_write_control);
if (!(oret = open_fs (O_BINARY, 0)))
- {
- query_open (query_read_control);
- if (!(oret = open_fs (O_BINARY, 0)))
- return -1;
- }
+ return -1;
}
mode_t attrib = 0;
@@ -460,17 +458,6 @@ fhandler_disk_file::facl (int cmd, int nentries, __aclent32_t *aclbufp)
int res = -1;
int oret = 0;
- if (!get_io_handle ())
- {
- query_open (query_write_control);
- if (!(oret = open_fs (O_BINARY, 0)))
- {
- query_open (query_read_control);
- if (!(oret = open_fs (O_BINARY, 0)))
- return -1;
- }
- }
-
if (!pc.has_acls () || !allow_ntsec)
{
switch (cmd)
@@ -485,30 +472,50 @@ fhandler_disk_file::facl (int cmd, int nentries, __aclent32_t *aclbufp)
set_errno(EFAULT);
else if (nentries < MIN_ACL_ENTRIES)
set_errno (ENOSPC);
- else if (!fstat_by_handle (&st))
+ else
{
- aclbufp[0].a_type = USER_OBJ;
- aclbufp[0].a_id = st.st_uid;
- aclbufp[0].a_perm = (st.st_mode & S_IRWXU) >> 6;
- aclbufp[1].a_type = GROUP_OBJ;
- aclbufp[1].a_id = st.st_gid;
- aclbufp[1].a_perm = (st.st_mode & S_IRWXG) >> 3;
- aclbufp[2].a_type = OTHER_OBJ;
- aclbufp[2].a_id = ILLEGAL_GID;
- aclbufp[2].a_perm = st.st_mode & S_IRWXO;
- aclbufp[3].a_type = CLASS_OBJ;
- aclbufp[3].a_id = ILLEGAL_GID;
- aclbufp[3].a_perm = S_IRWXU | S_IRWXG | S_IRWXO;
- res = MIN_ACL_ENTRIES;
+ if (!get_io_handle ())
+ {
+ query_open (query_read_control);
+ if (!(oret = open_fs (O_BINARY, 0)))
+ return -1;
+ }
+ if (!fstat_by_handle (&st))
+ {
+ aclbufp[0].a_type = USER_OBJ;
+ aclbufp[0].a_id = st.st_uid;
+ aclbufp[0].a_perm = (st.st_mode & S_IRWXU) >> 6;
+ aclbufp[1].a_type = GROUP_OBJ;
+ aclbufp[1].a_id = st.st_gid;
+ aclbufp[1].a_perm = (st.st_mode & S_IRWXG) >> 3;
+ aclbufp[2].a_type = OTHER_OBJ;
+ aclbufp[2].a_id = ILLEGAL_GID;
+ aclbufp[2].a_perm = st.st_mode & S_IRWXO;
+ aclbufp[3].a_type = CLASS_OBJ;
+ aclbufp[3].a_id = ILLEGAL_GID;
+ aclbufp[3].a_perm = S_IRWXU | S_IRWXG | S_IRWXO;
+ res = MIN_ACL_ENTRIES;
+ }
}
break;
case GETACLCNT:
res = MIN_ACL_ENTRIES;
break;
+ default:
+ set_errno (EINVAL);
+ break;
}
}
else
{
+ if (cmd == SETACL)
+ enable_restore_privilege ();
+ if (!get_io_handle ())
+ {
+ query_open (cmd == SETACL ? query_write_control : query_read_control);
+ if (!(oret = open_fs (O_BINARY, 0)))
+ return -1;
+ }
switch (cmd)
{
case SETACL:
diff --git a/winsup/cygwin/fhandler_raw.cc b/winsup/cygwin/fhandler_raw.cc
index 5a05e704f..4fafe20cf 100644
--- a/winsup/cygwin/fhandler_raw.cc
+++ b/winsup/cygwin/fhandler_raw.cc
@@ -144,41 +144,16 @@ fhandler_dev_raw::open (int flags, mode_t)
flags &= ~(O_CREAT | O_TRUNC);
flags |= O_BINARY;
- DWORD access = GENERIC_READ | SYNCHRONIZE;
if (get_major () == DEV_TAPE_MAJOR
|| (flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY
|| (flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDWR)
- access |= GENERIC_WRITE;
-
- extern void str2buf2uni (UNICODE_STRING &, WCHAR *, const char *);
- UNICODE_STRING dev;
- WCHAR devname[CYG_MAX_PATH + 1];
- str2buf2uni (dev, devname, get_win32_name ());
- OBJECT_ATTRIBUTES attr;
- ULONG options = FILE_SYNCHRONOUS_IO_NONALERT;
- /* The O_TEXT flag is used to indicate write-through on tape devices */
- if (get_major () == DEV_TAPE_MAJOR && (flags & O_TEXT))
- options |= FILE_WRITE_THROUGH;
- flags &= ~O_TEXT;
- InitializeObjectAttributes (&attr, &dev, OBJ_CASE_INSENSITIVE, NULL, NULL);
-
- HANDLE h;
- IO_STATUS_BLOCK io;
- NTSTATUS status = NtOpenFile (&h, access, &attr, &io, 0 /* excl. access */,
- options);
- if (!NT_SUCCESS (status))
- {
- __seterrno_from_win_error (RtlNtStatusToDosError (status));
- return 0;
- }
+ flags = ((flags & ~(O_WRONLY | O_RDWR)) | O_RDWR);
- set_io_handle (h);
- set_flags ((flags & ~O_TEXT) | O_BINARY);
-
- if (devbufsiz > 1L)
+ int res = fhandler_base::open (flags, 0);
+ if (res && devbufsiz > 1L)
devbuf = new char [devbufsiz];
- return 1;
+ return res;
}
int
diff --git a/winsup/cygwin/ntdll.h b/winsup/cygwin/ntdll.h
index 2ecedcf01..0fb7c0e5a 100644
--- a/winsup/cygwin/ntdll.h
+++ b/winsup/cygwin/ntdll.h
@@ -389,6 +389,9 @@ typedef struct _OBJECT_NAME_INFORMATION
standard Win32 header. */
extern "C"
{
+ NTSTATUS NTAPI NtCreateFile (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
+ PIO_STATUS_BLOCK, PLARGE_INTEGER, ULONG, ULONG,
+ ULONG, ULONG, PVOID, ULONG);
NTSTATUS NTAPI NtCreateToken (PHANDLE, ACCESS_MASK, POBJECT_ATTRIBUTES,
TOKEN_TYPE, PLUID, PLARGE_INTEGER, PTOKEN_USER,
PTOKEN_GROUPS, PTOKEN_PRIVILEGES, PTOKEN_OWNER,
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 1b4000fe7..a99198bd6 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -2648,8 +2648,7 @@ symlink_worker (const char *topath, const char *frompath, bool use_winsym,
{
CloseHandle (h);
if (!allow_ntsec && allow_ntea)
- set_file_attribute (win32_path.has_acls (), NULL,
- win32_path.get_win32 (),
+ set_file_attribute (false, NULL, win32_path.get_win32 (),
S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO);
DWORD attr = use_winsym ? FILE_ATTRIBUTE_READONLY
diff --git a/winsup/cygwin/sec_acl.cc b/winsup/cygwin/sec_acl.cc
index 0e20a9fc5..268f378db 100644
--- a/winsup/cygwin/sec_acl.cc
+++ b/winsup/cygwin/sec_acl.cc
@@ -261,7 +261,7 @@ getacl (HANDLE handle, const char *file, DWORD attr, int nentries,
{
security_descriptor sd;
- if (!handle || get_nt_object_security (handle, SE_FILE_OBJECT, sd)
+ if ((!handle || get_nt_object_security (handle, SE_FILE_OBJECT, sd))
&& read_sd (file, sd) <= 0)
{
debug_printf ("read_sd %E");
diff --git a/winsup/cygwin/sec_helper.cc b/winsup/cygwin/sec_helper.cc
index 0c44c6f7c..b97dcd028 100644
--- a/winsup/cygwin/sec_helper.cc
+++ b/winsup/cygwin/sec_helper.cc
@@ -375,6 +375,20 @@ out:
return ret;
}
+/* Helper function to set the SE_RESTORE_NAME privilege once. */
+void
+enable_restore_privilege ()
+{
+ static int NO_COPY saved_res;
+ bool issetuid = cygheap->user.issetuid ();
+ if (!saved_res || issetuid)
+ {
+ int res = 2 + set_process_privilege (SE_RESTORE_NAME, true, issetuid);
+ if (!issetuid)
+ saved_res = res;
+ }
+}
+
/*
* Function to return a common SECURITY_DESCRIPTOR * that
* allows all access.
diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc
index 239505128..29dd0a056 100644
--- a/winsup/cygwin/security.cc
+++ b/winsup/cygwin/security.cc
@@ -165,6 +165,16 @@ str2buf2uni (UNICODE_STRING &tgt, WCHAR *buf, const char *srcstr)
sys_mbstowcs (buf, srcstr, tgt.MaximumLength);
}
+void
+str2buf2uni_cat (UNICODE_STRING &tgt, const char *srcstr)
+{
+ DWORD len = strlen (srcstr) * sizeof (WCHAR);
+ sys_mbstowcs (tgt.Buffer + tgt.Length / sizeof (WCHAR), srcstr,
+ len + tgt.MaximumLength);
+ tgt.Length += len;
+ tgt.MaximumLength += len;
+}
+
#if 0 /* unused */
static void
lsa2wchar (WCHAR *tgt, LSA_UNICODE_STRING &src, int size)
@@ -1119,38 +1129,9 @@ read_sd (const char *file, security_descriptor &sd)
LONG
write_sd (HANDLE fh, const char *file, security_descriptor &sd)
{
- /* 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 */
- int res;
- if (!saved_res || cygheap->user.issetuid ())
- {
- res = 2 + set_process_privilege (SE_RESTORE_NAME, true,
- cygheap->user.issetuid ());
- if (!cygheap->user.issetuid ())
- saved_res = res;
- }
- else
- res = saved_res;
- if (res == 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 = STATUS_SUCCESS;
int retry = 0;
- res = -1;
+ int res = -1;
for (; retry < 2; ++retry)
{
if (retry && (fh = CreateFile (file, WRITE_OWNER | WRITE_DAC,
diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h
index df78775e5..b0bc6e414 100644
--- a/winsup/cygwin/security.h
+++ b/winsup/cygwin/security.h
@@ -248,7 +248,6 @@ extern bool allow_ntsec;
extern bool allow_smbntsec;
/* File manipulation */
-int __stdcall set_process_privileges ();
int __stdcall get_file_attribute (int, HANDLE, const char *, mode_t *,
__uid32_t * = NULL, __gid32_t * = NULL);
int __stdcall set_file_attribute (bool, HANDLE, const char *, int);
@@ -275,6 +274,10 @@ extern "C" int acl32 (const char *, int, int, __acl32 *);
int getacl (HANDLE, const char *, DWORD, int, __acl32 *);
int setacl (HANDLE, const char *, int, __acl32 *);
+struct _UNICODE_STRING;
+void __stdcall str2buf2uni (_UNICODE_STRING &, WCHAR *, const char *) __attribute__ ((regparm (3)));
+void __stdcall str2buf2uni_cat (_UNICODE_STRING &, const char *) __attribute__ ((regparm (2)));
+
/* Try a subauthentication. */
HANDLE subauth (struct passwd *pw);
/* Try creating a token directly. */
@@ -289,6 +292,7 @@ bool get_logon_server (const char * domain, char * server, WCHAR *wserver = NULL
/* sec_helper.cc: Security helper functions. */
int set_process_privilege (const char *privilege, bool enable = true, bool use_thread = false);
+void enable_restore_privilege (void);
/* shared.cc: */
/* Retrieve a security descriptor that allows all access */
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 659f33185..d89b86484 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -872,6 +872,9 @@ lchown (const char * name, __uid16_t uid, __gid16_t gid)
extern "C" int
fchown32 (int fd, __uid32_t uid, __gid32_t gid)
{
+ if (!wincap.has_security ()) // real chown only works on NT
+ return 0; // return zero (and do nothing) under Windows 9x
+
cygheap_fdget cfd (fd);
if (cfd < 0)
{