-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 According to Eric Blake on 9/3/2009 9:58 AM: > Second, it is not performing the proper checks when AT_EACCESS is set and the > applications' effective id differs from the real id (to fix this would > require > adding a parameter to fhandler_base::fhaccess).
Actually, faccessat(,AT_EACCESS) was right, but access() and faccessat(,0) were doing the wrong thing (using effective id instead of real id when doing the permission check). I think I got it all right, but please double-check me. 2009-09-24 Eric Blake <e...@byu.net> * fhandler.h (fhandler_base::fhaccess): Add parameter. * security.h (check_file_access, check_registry_access): Likewise. * security.cc (check_file_access, check_registry_access) (check_access): Implement new parameter. * fhandler.cc (fhandler_base::fhaccess): Likewise. (device_access_denied): Update caller. * syscalls.cc (access, faccessat): Update callers. - -- Don't work too hard, make some time for fun as well! Eric Blake e...@byu.net -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (Cygwin) Comment: Public key at home.comcast.net/~ericblake/eblake.gpg Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/ iEYEARECAAYFAkq8OmQACgkQ84KuGfSFAYD5ggCglYCjeUDkJF30Bn455/MoEkrn ynkAn29rXYxx0RV47hEXpAqkVoFijiz2 =mWIO -----END PGP SIGNATURE-----
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc index 44311ca..7a7d801 100644 --- a/winsup/cygwin/fhandler.cc +++ b/winsup/cygwin/fhandler.cc @@ -344,11 +344,11 @@ fhandler_base::device_access_denied (int flags) if (!mode) mode |= R_OK; - return fhaccess (mode); + return fhaccess (mode, true); } int -fhandler_base::fhaccess (int flags) +fhandler_base::fhaccess (int flags, bool effective) { int res = -1; if (error ()) @@ -373,12 +373,12 @@ fhandler_base::fhaccess (int flags) goto eaccess_done; else if (has_acls ()) { - res = check_file_access (pc, flags); + res = check_file_access (pc, flags, effective); goto done; } else if (get_device () == FH_REGISTRY && open (O_RDONLY, 0) && get_handle ()) { - res = check_registry_access (get_handle (), flags); + res = check_registry_access (get_handle (), flags, effective); close (); return res; } @@ -389,12 +389,12 @@ fhandler_base::fhaccess (int flags) if (flags & R_OK) { - if (st.st_uid == myself->uid) + if (st.st_uid == (effective ? myself->uid : cygheap->user.real_uid)) { if (!(st.st_mode & S_IRUSR)) goto eaccess_done; } - else if (st.st_gid == myself->gid) + else if (st.st_gid == (effective ? myself->gid : cygheap->user.real_gid)) { if (!(st.st_mode & S_IRGRP)) goto eaccess_done; @@ -405,12 +405,12 @@ fhandler_base::fhaccess (int flags) if (flags & W_OK) { - if (st.st_uid == myself->uid) + if (st.st_uid == (effective ? myself->uid : cygheap->user.real_uid)) { if (!(st.st_mode & S_IWUSR)) goto eaccess_done; } - else if (st.st_gid == myself->gid) + else if (st.st_gid == (effective ? myself->gid : cygheap->user.real_gid)) { if (!(st.st_mode & S_IWGRP)) goto eaccess_done; @@ -421,12 +421,12 @@ fhandler_base::fhaccess (int flags) if (flags & X_OK) { - if (st.st_uid == myself->uid) + if (st.st_uid == (effective ? myself->uid : cygheap->user.real_uid)) { if (!(st.st_mode & S_IXUSR)) goto eaccess_done; } - else if (st.st_gid == myself->gid) + else if (st.st_gid == (effective ? myself->gid : cygheap->user.real_gid)) { if (!(st.st_mode & S_IXGRP)) goto eaccess_done; diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 1544cc6..dd9b591 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -392,7 +392,7 @@ class fhandler_base bool is_fs_special () {return pc.is_fs_special ();} bool issymlink () {return pc.issymlink ();} bool device_access_denied (int) __attribute__ ((regparm (2))); - int fhaccess (int flags) __attribute__ ((regparm (2))); + int fhaccess (int flags, bool) __attribute__ ((regparm (3))); }; class fhandler_mailslot : public fhandler_base diff --git a/winsup/cygwin/security.cc b/winsup/cygwin/security.cc index 00a8c32..8c67fc9 100644 --- a/winsup/cygwin/security.cc +++ b/winsup/cygwin/security.cc @@ -1,7 +1,7 @@ /* security.cc: NT file access control functions Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007 Red Hat, Inc. + 2006, 2007, 2009 Red Hat, Inc. Originaly written by Gunther Ebert, gunther.eb...@ixos-leipzig.de Completely rewritten by Corinna Vinschen <cori...@vinschen.de> @@ -725,15 +725,16 @@ set_file_attribute (HANDLE handle, path_conv &pc, static int check_access (security_descriptor &sd, GENERIC_MAPPING &mapping, - DWORD desired, int flags) + DWORD desired, int flags, bool effective) { int ret = -1; BOOL status; DWORD granted; DWORD plen = sizeof (PRIVILEGE_SET) + 3 * sizeof (LUID_AND_ATTRIBUTES); PPRIVILEGE_SET pset = (PPRIVILEGE_SET) alloca (plen); - HANDLE tok = cygheap->user.issetuid () ? cygheap->user.imp_token () - : hProcImpToken; + HANDLE tok = ((cygheap->user.issetuid () && effective) + ? cygheap->user.imp_token () + : hProcImpToken); if (!tok && !DuplicateTokenEx (hProcToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenImpersonation, @@ -794,7 +795,7 @@ check_access (security_descriptor &sd, GENERIC_MAPPING &mapping, } int -check_file_access (path_conv &pc, int flags) +check_file_access (path_conv &pc, int flags, bool effective) { security_descriptor sd; int ret = -1; @@ -810,13 +811,13 @@ check_file_access (path_conv &pc, int flags) if (flags & X_OK) desired |= FILE_EXECUTE; if (!get_file_sd (NULL, pc, sd)) - ret = check_access (sd, mapping, desired, flags); + ret = check_access (sd, mapping, desired, flags, effective); debug_printf ("flags %x, ret %d", flags, ret); return ret; } int -check_registry_access (HANDLE hdl, int flags) +check_registry_access (HANDLE hdl, int flags, bool effective) { security_descriptor sd; int ret = -1; @@ -832,7 +833,7 @@ check_registry_access (HANDLE hdl, int flags) if (flags & X_OK) desired |= KEY_QUERY_VALUE; if (!get_reg_sd (hdl, sd)) - ret = check_access (sd, mapping, desired, flags); + ret = check_access (sd, mapping, desired, flags, effective); /* As long as we can't write the registry... */ if (flags & W_OK) { diff --git a/winsup/cygwin/security.h b/winsup/cygwin/security.h index 7b09bc0..be0ebd4 100644 --- a/winsup/cygwin/security.h +++ b/winsup/cygwin/security.h @@ -350,8 +350,8 @@ LONG __stdcall set_file_sd (HANDLE fh, path_conv &, security_descriptor &sd, bool is_chown); 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 (path_conv &, int); -int __stdcall check_registry_access (HANDLE, int); +int __stdcall check_file_access (path_conv &, int, bool effective = true); +int __stdcall check_registry_access (HANDLE, int, bool effective = true); void set_security_attribute (path_conv &pc, int attribute, PSECURITY_ATTRIBUTES psa, diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index b00404d..15dbc87 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -1569,7 +1569,7 @@ access (const char *fn, int flags) fhandler_base *fh = build_fh_name (fn, NULL, PC_SYM_FOLLOW, stat_suffixes); if (fh) { - res = fh->fhaccess (flags); + res = fh->fhaccess (flags, false); delete fh; } } @@ -3864,7 +3864,7 @@ faccessat (int dirfd, const char *pathname, int mode, int flags) stat_suffixes); if (fh) { - res = fh->fhaccess (mode); + res = fh->fhaccess (mode, flags & AT_EACCESS); delete fh; } } -- 1.6.5.rc1