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>
* 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)
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;

View File

@ -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

View File

@ -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, 2008, 2009 Red Hat, Inc.
Originaly written by Gunther Ebert, gunther.ebert@ixos-leipzig.de
Completely rewritten by Corinna Vinschen <corinna@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 = ((effective && cygheap->user.issetuid ())
? 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)
{

View File

@ -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);
int __stdcall check_registry_access (HANDLE, int, bool);
void set_security_attribute (path_conv &pc, int attribute,
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 (buf.has_acls () && check_file_access (buf, X_OK))
if (buf.has_acls () && check_file_access (buf, X_OK, true))
continue;
if (posix == tmp)
@ -1083,7 +1083,8 @@ just_shell:
/* Check if script is executable. Otherwise we start non-executable
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. */
/* 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);
if (fh)
{
res = fh->fhaccess (flags);
res = fh->fhaccess (flags, false);
delete fh;
}
}
@ -3862,7 +3862,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;
}
}