diff options
Diffstat (limited to 'sysdeps/mach/hurd/faccessat.c')
-rw-r--r-- | sysdeps/mach/hurd/faccessat.c | 181 |
1 files changed, 165 insertions, 16 deletions
diff --git a/sysdeps/mach/hurd/faccessat.c b/sysdeps/mach/hurd/faccessat.c index 260060639f..d9bceaada7 100644 --- a/sysdeps/mach/hurd/faccessat.c +++ b/sysdeps/mach/hurd/faccessat.c @@ -23,31 +23,167 @@ #include <sys/types.h> #include <hurd.h> #include <hurd/fd.h> +#include <hurd/port.h> +#include <hurd/id.h> +#include <hurd/lookup.h> -int -faccessat (int fd, const char *file, int type, int flag) +static int +hurd_fail_seterrno (error_t err) +{ + return __hurd_fail (err); +} + +static int +hurd_fail_noerrno (error_t err) +{ + return -1; +} + +static int +__faccessat_common (int fd, const char *file, int type, int at_flags, + int (*errfunc) (error_t)) { error_t err; - file_t port; - int allowed, flags; + file_t rcrdir, rcwdir, io; + int flags, allowed; - if ((flag & AT_EACCESS) == 0) + if ((at_flags & AT_EACCESS) == AT_EACCESS) { - if (fd == AT_FDCWD || file[0] == '/') - return __access (file, type); - __set_errno (ENOTSUP); /* XXX later */ - return -1; + /* Use effective permissions. */ + io = __file_name_lookup_at (fd, at_flags &~ AT_EACCESS, file, 0, 0); + if (io == MACH_PORT_NULL) + return -1; } + else + { + /* We have to use real permissions instead of the + usual effective permissions. */ + + int hurd_flags = 0; + __hurd_at_flags (&at_flags, &hurd_flags); + + error_t reauthenticate_cwdir_at (file_t *result) + { + /* Get a port to the FD directory, authenticated with the real IDs. */ + error_t err; + mach_port_t ref; + ref = __mach_reply_port (); + err = HURD_DPORT_USE + (fd, + ({ + err = __io_reauthenticate (port, ref, MACH_MSG_TYPE_MAKE_SEND); + if (!err) + err = __auth_user_authenticate (_hurd_id.rid_auth, + ref, MACH_MSG_TYPE_MAKE_SEND, + result); + err; + })); + __mach_port_destroy (__mach_task_self (), ref); + return err; + } + + error_t reauthenticate (int which, file_t *result) + { + /* Get a port to our root directory, authenticated with the real IDs. */ + error_t err; + mach_port_t ref; + ref = __mach_reply_port (); + err = HURD_PORT_USE + (&_hurd_ports[which], + ({ + err = __io_reauthenticate (port, ref, MACH_MSG_TYPE_MAKE_SEND); + if (!err) + err = __auth_user_authenticate (_hurd_id.rid_auth, + ref, MACH_MSG_TYPE_MAKE_SEND, + result); + err; + })); + __mach_port_destroy (__mach_task_self (), ref); + return err; + } + + error_t init_port (int which, error_t (*operate) (mach_port_t)) + { + switch (which) + { + case INIT_PORT_AUTH: + return (*operate) (_hurd_id.rid_auth); + case INIT_PORT_CRDIR: + return (reauthenticate (INIT_PORT_CRDIR, &rcrdir) ?: + (*operate) (rcrdir)); + case INIT_PORT_CWDIR: + if (fd == AT_FDCWD || file[0] == '/') + return (reauthenticate (INIT_PORT_CWDIR, &rcwdir) ?: + (*operate) (rcwdir)); + else + return (reauthenticate_cwdir_at (&rcwdir) ?: + (*operate) (rcwdir)); + default: + return _hurd_ports_use (which, operate); + } + } + + rcrdir = rcwdir = MACH_PORT_NULL; + + HURD_CRITICAL_BEGIN; + + __mutex_lock (&_hurd_id.lock); + /* Get _hurd_id up to date. */ + if (err = _hurd_check_ids ()) + goto lose; - port = __file_name_lookup_at (fd, flag &~ AT_EACCESS, file, 0, 0); - if (port == MACH_PORT_NULL) - return -1; + if (_hurd_id.rid_auth == MACH_PORT_NULL) + { + /* Set up _hurd_id.rid_auth. This is a special auth server port + which uses the real uid and gid (the first aux uid and gid) as + the only effective uid and gid. */ + + if (_hurd_id.aux.nuids < 1 || _hurd_id.aux.ngids < 1) + { + /* We do not have a real UID and GID. Lose, lose, lose! */ + err = EGRATUITOUS; + goto lose; + } + + /* Create a new auth port using our real UID and GID (the first + auxiliary UID and GID) as the only effective IDs. */ + if (err = __USEPORT (AUTH, + __auth_makeauth (port, + NULL, MACH_MSG_TYPE_COPY_SEND, 0, + _hurd_id.aux.uids, 1, + _hurd_id.aux.uids, + _hurd_id.aux.nuids, + _hurd_id.aux.gids, 1, + _hurd_id.aux.gids, + _hurd_id.aux.ngids, + &_hurd_id.rid_auth))) + goto lose; + } + + if (!err) + /* Look up the file name using the modified init ports. */ + err = __hurd_file_name_lookup (&init_port, &__getdport, 0, + file, hurd_flags, 0, &io); + + /* We are done with _hurd_id.rid_auth now. */ + lose: + __mutex_unlock (&_hurd_id.lock); + + HURD_CRITICAL_END; + + if (rcrdir != MACH_PORT_NULL) + __mach_port_deallocate (__mach_task_self (), rcrdir); + if (rcwdir != MACH_PORT_NULL) + __mach_port_deallocate (__mach_task_self (), rcwdir); + if (err) + return errfunc (err); + } /* Find out what types of access we are allowed to this file. */ - err = __file_check_access (port, &allowed); - __mach_port_deallocate (__mach_task_self (), port); + err = __file_check_access (io, &allowed); + __mach_port_deallocate (__mach_task_self (), io); if (err) - return __hurd_fail (err); + return errfunc (err); flags = 0; if (type & R_OK) @@ -59,7 +195,20 @@ faccessat (int fd, const char *file, int type, int flag) if (flags & ~allowed) /* We are not allowed all the requested types of access. */ - return __hurd_fail (EACCES); + return errfunc (EACCES); return 0; } + +int +__faccessat_noerrno (int fd, const char *file, int type, int at_flags) +{ + return __faccessat_common (fd, file, type, at_flags, hurd_fail_noerrno); +} + +int +__faccessat (int fd, const char *file, int type, int at_flags) +{ + return __faccessat_common (fd, file, type, at_flags, hurd_fail_seterrno); +} +weak_alias (__faccessat, faccessat) |