From e3d1d51579d6128f36c08f3c7c488e5efbed7b72 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Wed, 14 Apr 2004 16:36:26 +0000 Subject: [PATCH] * fhandler.cc (fhandler_base::open): Simplify access evaluation expression. (fhandler_base::facl): New method. * fhandler.h: Declare facl method in fhandler_base, fhandler_disk_file and fhandler_virtual. * fhandler_disk_file.cc (fhandler_disk_file::facl): New method. * fhandler_virtual.cc (fhandler_virtual::facl): New method. * sec_acl.cc: Remove forward declaration for aclsort32 and acl32. (setacl): Remove static. Add and use handle parameter. (getacl): Ditto. (acl_worker): Reorganize to call fhandler's facl method eventually. (facl32): Ditto. * security.cc (get_nt_object_security): Remove static. * security.h: Add extern declarations for get_nt_object_security, aclsort32, acl32, getacl and setacl. Apply missing syscalls.cc patch and ChangeLog of previous check in. * syscalls.cc (chown_worker): Reorganize to call fhandler's fchown method eventually. (fchown): Ditto. --- winsup/cygwin/ChangeLog | 21 +++++ winsup/cygwin/fhandler.cc | 51 +++++++----- winsup/cygwin/fhandler.h | 4 + winsup/cygwin/fhandler_disk_file.cc | 78 ++++++++++++++++++ winsup/cygwin/fhandler_virtual.cc | 9 +++ winsup/cygwin/sec_acl.cc | 118 ++++++---------------------- winsup/cygwin/security.cc | 2 +- winsup/cygwin/security.h | 9 +++ winsup/cygwin/syscalls.cc | 64 +++------------ 9 files changed, 191 insertions(+), 165 deletions(-) diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 7ee5de3ec..a93aa2707 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,21 @@ +2004-04-14 Corinna Vinschen + + * fhandler.cc (fhandler_base::open): Simplify access evaluation + expression. + (fhandler_base::facl): New method. + * fhandler.h: Declare facl method in fhandler_base, + fhandler_disk_file and fhandler_virtual. + * fhandler_disk_file.cc (fhandler_disk_file::facl): New method. + * fhandler_virtual.cc (fhandler_virtual::facl): New method. + * sec_acl.cc: Remove forward declaration for aclsort32 and acl32. + (setacl): Remove static. Add and use handle parameter. + (getacl): Ditto. + (acl_worker): Reorganize to call fhandler's facl method eventually. + (facl32): Ditto. + * security.cc (get_nt_object_security): Remove static. + * security.h: Add extern declarations for get_nt_object_security, + aclsort32, acl32, getacl and setacl. + 2004-04-14 Corinna Vinschen * fhandler.cc (fhandler_base::open): Accomodate query_write_control @@ -17,6 +35,9 @@ 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. + * syscalls.cc (chown_worker): Reorganize to call fhandler's fchown + method eventually. + (fchown): Ditto. 2004-04-14 Corinna Vinschen diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index b93102dd1..af9d63313 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -13,6 +13,7 @@ details. */ #include #include #include +#include #include #include "cygerrno.h" #include "perprocess.h" @@ -442,27 +443,28 @@ fhandler_base::open (int flags, mode_t mode) goto done; } - if (query_open ()) - 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) - access = GENERIC_READ; - else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY) - access = GENERIC_WRITE; - else - access = GENERIC_READ | GENERIC_WRITE; + 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) @@ -1429,3 +1431,10 @@ fhandler_base::fchown (__uid32_t uid, __gid32_t gid) /* By default, just succeeds. */ return 0; } + +int +fhandler_base::facl (int cmd, int nentries, __aclent32_t *aclbufp) +{ + /* By default, just succeeds. */ + return 0; +} diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 0ee198c54..3e27b7b8f 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -35,6 +35,7 @@ class fhandler_disk_file; typedef struct __DIR DIR; struct dirent; struct iovec; +struct __acl32; enum conn_state { @@ -245,6 +246,7 @@ class fhandler_base 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 __stdcall facl (int, int, __acl32 *) __attribute__ ((regparm (3))); virtual int ioctl (unsigned int cmd, void *); virtual int fcntl (int cmd, void *); virtual char const *ttyname () { return get_name (); } @@ -571,6 +573,7 @@ class fhandler_disk_file: public fhandler_base 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))); + int __stdcall facl (int, int, __acl32 *) __attribute__ ((regparm (3))); 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); @@ -1105,6 +1108,7 @@ class fhandler_virtual : public fhandler_base 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))); + int __stdcall facl (int, int, __acl32 *) __attribute__ ((regparm (3))); 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 f649d4dbd..b330a96e6 100644 --- a/winsup/cygwin/fhandler_disk_file.cc +++ b/winsup/cygwin/fhandler_disk_file.cc @@ -12,6 +12,7 @@ details. */ #include #include #include +#include #include #include "cygerrno.h" #include "perprocess.h" @@ -445,6 +446,83 @@ fhandler_disk_file::fchown (__uid32_t uid, __gid32_t gid) return res; } +int _stdcall +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))) + return -1; + } + + if (!pc.has_acls () || !allow_ntsec) + { + switch (cmd) + { + struct __stat64 st; + + case SETACL: + set_errno (ENOSYS); + break; + case GETACL: + if (!aclbufp) + set_errno(EFAULT); + else if (nentries < MIN_ACL_ENTRIES) + set_errno (ENOSPC); + else 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; + } + } + else + { + switch (cmd) + { + case SETACL: + if (!aclsort32 (nentries, 0, aclbufp)) + res = setacl (get_io_handle (), pc, nentries, aclbufp); + break; + case GETACL: + if (!aclbufp) + set_errno(EFAULT); + else + res = getacl (get_io_handle (), pc, pc, nentries, aclbufp); + break; + case GETACLCNT: + res = getacl (get_io_handle (), pc, pc, 0, NULL); + default: + set_errno (EINVAL); + break; + } + } + + 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 16b83923e..fa3d2ed2e 100644 --- a/winsup/cygwin/fhandler_virtual.cc +++ b/winsup/cygwin/fhandler_virtual.cc @@ -12,6 +12,7 @@ details. */ #include #include #include +#include #include "cygerrno.h" #include "security.h" #include "path.h" @@ -242,3 +243,11 @@ fhandler_virtual::fchown (__uid32_t uid, __gid32_t gid) set_errno (EPERM); return -1; } + +int +fhandler_virtual::facl (int cmd, int nentries, __aclent32_t *aclbufp) +{ + /* Same as on Linux. */ + set_errno (EPERM); + return -1; +} diff --git a/winsup/cygwin/sec_acl.cc b/winsup/cygwin/sec_acl.cc index a8dbe2f90..e5e058983 100644 --- a/winsup/cygwin/sec_acl.cc +++ b/winsup/cygwin/sec_acl.cc @@ -31,9 +31,6 @@ details. */ #include "cygheap.h" #include "pwdgrp.h" -extern "C" int aclsort32 (int nentries, int, __aclent32_t *aclbufp); -extern "C" int acl32 (const char *path, int cmd, int nentries, __aclent32_t *aclbufp); - static int searchace (__aclent32_t *aclp, int nentries, int type, __uid32_t id = ILLEGAL_UID) { @@ -46,12 +43,13 @@ searchace (__aclent32_t *aclp, int nentries, int type, __uid32_t id = ILLEGAL_UI return -1; } -static int -setacl (const char *file, int nentries, __aclent32_t *aclbufp) +int +setacl (HANDLE handle, const char *file, int nentries, __aclent32_t *aclbufp) { security_descriptor sd_ret; - if (read_sd (file, sd_ret) <= 0) + if ((!handle || get_nt_object_security (handle, SE_FILE_OBJECT, sd_ret)) + && read_sd (file, sd_ret) <= 0) { debug_printf ("read_sd %E"); return -1; @@ -223,7 +221,7 @@ setacl (const char *file, int nentries, __aclent32_t *aclbufp) return -1; } debug_printf ("Created SD-Size: %d", sd_ret.size ()); - return write_sd (NULL, file, sd_ret); + return write_sd (handle, file, sd_ret); } /* Temporary access denied bits */ @@ -257,13 +255,15 @@ getace (__aclent32_t &acl, int type, int id, DWORD win_ace_mask, acl.a_perm |= DENY_X; } -static int -getacl (const char *file, DWORD attr, int nentries, __aclent32_t *aclbufp) +int +getacl (HANDLE handle, const char *file, DWORD attr, int nentries, + __aclent32_t *aclbufp) { security_descriptor sd; int ret; - if ((ret = read_sd (file, sd)) <= 0) + if (!handle || get_nt_object_security (handle, SE_FILE_OBJECT, sd) + && (ret = read_sd (file, sd)) <= 0) { debug_printf ("read_sd %E"); return ret; @@ -409,93 +409,33 @@ getacl (const char *file, DWORD attr, int nentries, __aclent32_t *aclbufp) static int acl_worker (const char *path, int cmd, int nentries, __aclent32_t *aclbufp, - int nofollow) + unsigned fmode) { extern suffix_info stat_suffixes[]; - path_conv real_path (path, (nofollow ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW) | PC_FULL, stat_suffixes); - if (real_path.error) + int res = -1; + fhandler_base *fh = build_fh_name (path, NULL, fmode | PC_FULL, + stat_suffixes); + if (fh->error ()) { - set_errno (real_path.error); - syscall_printf ("-1 = acl (%s)", path); - return -1; + debug_printf ("got %d error from build_fh_name", fh->error ()); + set_errno (fh->error ()); } - if (!real_path.has_acls () || !allow_ntsec) - { - struct __stat64 st; - int ret = -1; - - switch (cmd) - { - case SETACL: - set_errno (ENOSYS); - break; - case GETACL: - if (!aclbufp) - set_errno(EFAULT); - else if (nentries < MIN_ACL_ENTRIES) - set_errno (ENOSPC); - else if ((nofollow && !lstat64 (path, &st)) - || (!nofollow && !stat64 (path, &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; - ret = MIN_ACL_ENTRIES; - } - break; - case GETACLCNT: - ret = MIN_ACL_ENTRIES; - break; - } - syscall_printf ("%d = acl (%s)", ret, path); - return ret; - } - switch (cmd) - { - case SETACL: - if (!aclsort32 (nentries, 0, aclbufp)) - return setacl (real_path.get_win32 (), - nentries, aclbufp); - break; - case GETACL: - if (!aclbufp) - set_errno(EFAULT); - else - return getacl (real_path.get_win32 (), - real_path.file_attributes (), - nentries, aclbufp); - break; - case GETACLCNT: - return getacl (real_path.get_win32 (), - real_path.file_attributes (), - 0, NULL); - default: - set_errno (EINVAL); - break; - } - syscall_printf ("-1 = acl (%s)", path); - return -1; + else + res = fh->facl (cmd, nentries, aclbufp); + syscall_printf ("%d = acl (%s)", res, path); + return res; } extern "C" int acl32 (const char *path, int cmd, int nentries, __aclent32_t *aclbufp) { - return acl_worker (path, cmd, nentries, aclbufp, 0); + return acl_worker (path, cmd, nentries, aclbufp, PC_SYM_FOLLOW); } extern "C" int lacl32 (const char *path, int cmd, int nentries, __aclent32_t *aclbufp) { - return acl_worker (path, cmd, nentries, aclbufp, 1); + return acl_worker (path, cmd, nentries, aclbufp, PC_SYM_NOFOLLOW); } extern "C" int @@ -507,15 +447,9 @@ facl32 (int fd, int cmd, int nentries, __aclent32_t *aclbufp) syscall_printf ("-1 = facl (%d)", fd); return -1; } - const char *path = cfd->get_name (); - if (path == NULL) - { - syscall_printf ("-1 = facl (%d) (no name)", fd); - set_errno (ENOSYS); - return -1; - } - syscall_printf ("facl (%d): calling acl (%s)", fd, path); - return acl_worker (path, cmd, nentries, aclbufp, 0); + int res = cfd->facl (cmd, nentries, aclbufp); + syscall_printf ("%d = facl (%s) )", res, cfd->get_name ()); + return res; } extern "C" int diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index 0915a77e6..c0ad954b7 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -1341,7 +1341,7 @@ get_nt_attribute (const char *file, mode_t *attribute, get_info_from_sd (sd, attribute, uidret, gidret); } -static int +int get_nt_object_security (HANDLE handle, SE_OBJECT_TYPE object_type, security_descriptor &sd_ret) { diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h index e81a8d8ae..df78775e5 100644 --- a/winsup/cygwin/security.h +++ b/winsup/cygwin/security.h @@ -253,6 +253,8 @@ 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); int __stdcall set_file_attribute (bool, HANDLE, const char *, __uid32_t, __gid32_t, int); +int __stdcall get_nt_object_security (HANDLE, SE_OBJECT_TYPE, + security_descriptor &); 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); @@ -266,6 +268,13 @@ void set_security_attribute (int attribute, PSECURITY_ATTRIBUTES psa, bool get_sids_info (cygpsid, cygpsid, __uid32_t * , __gid32_t *); +/* sec_acl.cc */ +struct __acl32; +extern "C" int aclsort32 (int, int, __acl32 *); +extern "C" int acl32 (const char *, int, int, __acl32 *); +int getacl (HANDLE, const char *, DWORD, int, __acl32 *); +int setacl (HANDLE, const char *, int, __acl32 *); + /* Try a subauthentication. */ HANDLE subauth (struct passwd *pw); /* Try creating a token directly. */ diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 237e5375c..5f1b58ecb 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -823,50 +823,20 @@ done: static int chown_worker (const char *name, unsigned fmode, __uid32_t uid, __gid32_t gid) { - int res; - - if (check_null_empty_str_errno (name)) - return -1; - if (!wincap.has_security ()) // real chown only works on NT - res = 0; // return zero (and do nothing) under Windows 9x - else + return 0; // return zero (and do nothing) under Windows 9x + + int res = -1; + fhandler_base *fh = build_fh_name (name, NULL, fmode | PC_FULL, + stat_suffixes); + if (fh->error ()) { - /* we need Win32 path names because of usage of Win32 API functions */ - path_conv win32_path (PC_NONULLEMPTY, name, fmode); - - if (win32_path.error) - { - set_errno (win32_path.error); - res = -1; - goto done; - } - - /* FIXME: This makes chown on a device succeed always. Someday we'll want - to actually allow chown to work properly on devices. */ - if (win32_path.is_auto_device () && !win32_path.issocket ()) - { - res = 0; - goto done; - } - - mode_t attrib = 0; - if (win32_path.isdir ()) - attrib |= S_IFDIR; - res = get_file_attribute (win32_path.has_acls (), NULL, - win32_path.get_win32 (), &attrib); - if (!res) - res = set_file_attribute (win32_path.has_acls (), NULL, win32_path, - uid, gid, attrib); - if (res != 0 && (!win32_path.has_acls () || !allow_ntsec)) - { - /* fake - if not supported, pretend we're like win95 - where it just works */ - res = 0; - } + debug_printf ("got %d error from build_fh_name", fh->error ()); + set_errno (fh->error ()); } + else + res = fh->fchown (uid, gid); -done: syscall_printf ("%d = %schown (%s,...)", res, (fmode & PC_SYM_NOFOLLOW) ? "l" : "", name); return res; @@ -908,18 +878,10 @@ fchown32 (int fd, __uid32_t uid, __gid32_t gid) return -1; } - const char *path = cfd->get_name (); + int res = cfd->fchown (uid, gid); - if (path == NULL) - { - syscall_printf ("-1 = fchown (%d,...) (no name)", fd); - set_errno (ENOSYS); - return -1; - } - - syscall_printf ("fchown (%d,...): calling chown_worker (%s,FOLLOW,...)", - fd, path); - return chown_worker (path, PC_SYM_FOLLOW, uid, gid); + syscall_printf ("%d = fchown (%s,...)", res, cfd->get_name ()); + return res; } extern "C" int