Fix faccessat(,0) and access() semantics.

* 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.
* spawn.cc (find_exec, fixup): Likewise.
This commit is contained in:
Eric Blake 2009-09-25 13:44:45 +00:00
parent 5386cd8ecc
commit 3dbe243afa
7 changed files with 38 additions and 25 deletions

View File

@ -1,3 +1,14 @@
2009-09-25 Eric Blake <ebb9@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.
* spawn.cc (find_exec, fixup): Likewise.
2009-09-24 Corinna Vinschen <corinna@vinschen.de> 2009-09-24 Corinna Vinschen <corinna@vinschen.de>
* posix_ipc.cc (mq_open): Avoid closing the same descriptor twice in * posix_ipc.cc (mq_open): Avoid closing the same descriptor twice in

View File

@ -344,11 +344,11 @@ fhandler_base::device_access_denied (int flags)
if (!mode) if (!mode)
mode |= R_OK; mode |= R_OK;
return fhaccess (mode); return fhaccess (mode, true);
} }
int int
fhandler_base::fhaccess (int flags) fhandler_base::fhaccess (int flags, bool effective)
{ {
int res = -1; int res = -1;
if (error ()) if (error ())
@ -373,12 +373,12 @@ fhandler_base::fhaccess (int flags)
goto eaccess_done; goto eaccess_done;
else if (has_acls ()) else if (has_acls ())
{ {
res = check_file_access (pc, flags); res = check_file_access (pc, flags, effective);
goto done; goto done;
} }
else if (get_device () == FH_REGISTRY && open (O_RDONLY, 0) && get_handle ()) 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 (); close ();
return res; return res;
} }
@ -389,12 +389,12 @@ fhandler_base::fhaccess (int flags)
if (flags & R_OK) 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)) if (!(st.st_mode & S_IRUSR))
goto eaccess_done; 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)) if (!(st.st_mode & S_IRGRP))
goto eaccess_done; goto eaccess_done;
@ -405,12 +405,12 @@ fhandler_base::fhaccess (int flags)
if (flags & W_OK) 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)) if (!(st.st_mode & S_IWUSR))
goto eaccess_done; 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)) if (!(st.st_mode & S_IWGRP))
goto eaccess_done; goto eaccess_done;
@ -421,12 +421,12 @@ fhandler_base::fhaccess (int flags)
if (flags & X_OK) 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)) if (!(st.st_mode & S_IXUSR))
goto eaccess_done; 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)) if (!(st.st_mode & S_IXGRP))
goto eaccess_done; goto eaccess_done;

View File

@ -392,7 +392,7 @@ class fhandler_base
bool is_fs_special () {return pc.is_fs_special ();} bool is_fs_special () {return pc.is_fs_special ();}
bool issymlink () {return pc.issymlink ();} bool issymlink () {return pc.issymlink ();}
bool device_access_denied (int) __attribute__ ((regparm (2))); 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 class fhandler_mailslot : public fhandler_base

View File

@ -1,7 +1,7 @@
/* security.cc: NT file access control functions /* security.cc: NT file access control functions
Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, Copyright 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007 Red Hat, Inc. 2006, 2007, 2008, 2009 Red Hat, Inc.
Originaly written by Gunther Ebert, gunther.ebert@ixos-leipzig.de Originaly written by Gunther Ebert, gunther.ebert@ixos-leipzig.de
Completely rewritten by Corinna Vinschen <corinna@vinschen.de> Completely rewritten by Corinna Vinschen <corinna@vinschen.de>
@ -725,15 +725,16 @@ set_file_attribute (HANDLE handle, path_conv &pc,
static int static int
check_access (security_descriptor &sd, GENERIC_MAPPING &mapping, check_access (security_descriptor &sd, GENERIC_MAPPING &mapping,
DWORD desired, int flags) DWORD desired, int flags, bool effective)
{ {
int ret = -1; int ret = -1;
BOOL status; BOOL status;
DWORD granted; DWORD granted;
DWORD plen = sizeof (PRIVILEGE_SET) + 3 * sizeof (LUID_AND_ATTRIBUTES); DWORD plen = sizeof (PRIVILEGE_SET) + 3 * sizeof (LUID_AND_ATTRIBUTES);
PPRIVILEGE_SET pset = (PPRIVILEGE_SET) alloca (plen); PPRIVILEGE_SET pset = (PPRIVILEGE_SET) alloca (plen);
HANDLE tok = cygheap->user.issetuid () ? cygheap->user.imp_token () HANDLE tok = ((effective && cygheap->user.issetuid ())
: hProcImpToken; ? cygheap->user.imp_token ()
: hProcImpToken);
if (!tok && !DuplicateTokenEx (hProcToken, MAXIMUM_ALLOWED, NULL, if (!tok && !DuplicateTokenEx (hProcToken, MAXIMUM_ALLOWED, NULL,
SecurityImpersonation, TokenImpersonation, SecurityImpersonation, TokenImpersonation,
@ -794,7 +795,7 @@ check_access (security_descriptor &sd, GENERIC_MAPPING &mapping,
} }
int int
check_file_access (path_conv &pc, int flags) check_file_access (path_conv &pc, int flags, bool effective)
{ {
security_descriptor sd; security_descriptor sd;
int ret = -1; int ret = -1;
@ -810,13 +811,13 @@ check_file_access (path_conv &pc, int flags)
if (flags & X_OK) if (flags & X_OK)
desired |= FILE_EXECUTE; desired |= FILE_EXECUTE;
if (!get_file_sd (NULL, pc, sd)) 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); debug_printf ("flags %x, ret %d", flags, ret);
return ret; return ret;
} }
int int
check_registry_access (HANDLE hdl, int flags) check_registry_access (HANDLE hdl, int flags, bool effective)
{ {
security_descriptor sd; security_descriptor sd;
int ret = -1; int ret = -1;
@ -832,7 +833,7 @@ check_registry_access (HANDLE hdl, int flags)
if (flags & X_OK) if (flags & X_OK)
desired |= KEY_QUERY_VALUE; desired |= KEY_QUERY_VALUE;
if (!get_reg_sd (hdl, sd)) 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... */ /* As long as we can't write the registry... */
if (flags & W_OK) if (flags & W_OK)
{ {

View File

@ -350,8 +350,8 @@ LONG __stdcall set_file_sd (HANDLE fh, path_conv &, security_descriptor &sd,
bool is_chown); 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_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); 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_file_access (path_conv &, int, bool);
int __stdcall check_registry_access (HANDLE, int); int __stdcall check_registry_access (HANDLE, int, bool);
void set_security_attribute (path_conv &pc, int attribute, void set_security_attribute (path_conv &pc, int attribute,
PSECURITY_ATTRIBUTES psa, PSECURITY_ATTRIBUTES psa,

View File

@ -169,7 +169,7 @@ find_exec (const char *name, path_conv& buf, const char *mywinenv,
if ((suffix = perhaps_suffix (tmp, buf, err, opt)) != NULL) if ((suffix = perhaps_suffix (tmp, buf, err, opt)) != NULL)
{ {
if (buf.has_acls () && check_file_access (buf, X_OK)) if (buf.has_acls () && check_file_access (buf, X_OK, true))
continue; continue;
if (posix == tmp) if (posix == tmp)
@ -1083,7 +1083,8 @@ just_shell:
/* Check if script is executable. Otherwise we start non-executable /* Check if script is executable. Otherwise we start non-executable
scripts successfully, which is incorrect behaviour. */ scripts successfully, which is incorrect behaviour. */
if (real_path.has_acls () && check_file_access (real_path, X_OK) < 0) if (real_path.has_acls ()
&& check_file_access (real_path, X_OK, true) < 0)
return -1; /* errno is already set. */ return -1; /* errno is already set. */
/* Replace argv[0] with the full path to the script if this is the /* Replace argv[0] with the full path to the script if this is the

View File

@ -1572,7 +1572,7 @@ access (const char *fn, int flags)
fhandler_base *fh = build_fh_name (fn, NULL, PC_SYM_FOLLOW, stat_suffixes); fhandler_base *fh = build_fh_name (fn, NULL, PC_SYM_FOLLOW, stat_suffixes);
if (fh) if (fh)
{ {
res = fh->fhaccess (flags); res = fh->fhaccess (flags, false);
delete fh; delete fh;
} }
} }
@ -3862,7 +3862,7 @@ faccessat (int dirfd, const char *pathname, int mode, int flags)
stat_suffixes); stat_suffixes);
if (fh) if (fh)
{ {
res = fh->fhaccess (mode); res = fh->fhaccess (mode, flags & AT_EACCESS);
delete fh; delete fh;
} }
} }