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:
parent
5386cd8ecc
commit
3dbe243afa
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue