(root)/
glibc-2.38/
sysdeps/
mach/
hurd/
faccessat.c
       1  /* Test for access to file, relative to open directory.  Hurd version.
       2     Copyright (C) 2006-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <errno.h>
      20  #include <fcntl.h>
      21  #include <stddef.h>
      22  #include <unistd.h>
      23  #include <sys/types.h>
      24  #include <hurd.h>
      25  #include <hurd/fd.h>
      26  #include <hurd/port.h>
      27  #include <hurd/id.h>
      28  #include <hurd/lookup.h>
      29  
      30  static int
      31  hurd_fail_seterrno (error_t err)
      32  {
      33    return __hurd_fail (err);
      34  }
      35  
      36  static int
      37  hurd_fail_noerrno (error_t err)
      38  {
      39    return -1;
      40  }
      41  
      42  static int
      43  __faccessat_common (int fd, const char *file, int type, int at_flags,
      44                      int (*errfunc) (error_t))
      45  {
      46    error_t err;
      47    file_t rcrdir, rcwdir, io;
      48    int flags, allowed;
      49  
      50    if ((at_flags & AT_EACCESS) == AT_EACCESS)
      51      {
      52        /* Use effective permissions.  */
      53        io = __file_name_lookup_at (fd, at_flags &~ AT_EACCESS, file, 0, 0);
      54        if (io == MACH_PORT_NULL)
      55  	return -1;
      56      }
      57    else
      58      {
      59        /* We have to use real permissions instead of the
      60           usual effective permissions.  */
      61  
      62        int hurd_flags = 0;
      63        err = __hurd_at_flags (&at_flags, &hurd_flags);
      64        if (err)
      65  	return errfunc (err);
      66  
      67        error_t reauthenticate_cwdir_at (file_t *result)
      68  	{
      69  	  /* Get a port to the FD directory, authenticated with the real IDs.  */
      70  	  error_t err;
      71  	  mach_port_t ref;
      72  	  ref = __mach_reply_port ();
      73  	  err = HURD_DPORT_USE
      74  	    (fd,
      75  	     ({
      76  	       err = __io_reauthenticate (port, ref, MACH_MSG_TYPE_MAKE_SEND);
      77  	       if (!err)
      78  		 err = __auth_user_authenticate (_hurd_id.rid_auth,
      79  						 ref, MACH_MSG_TYPE_MAKE_SEND,
      80  						 result);
      81  	       err;
      82  	     }));
      83  	  __mach_port_destroy (__mach_task_self (), ref);
      84  	  return err;
      85  	}
      86  
      87        error_t reauthenticate (int which, file_t *result)
      88  	{
      89  	  /* Get a port to our root directory, authenticated with the real IDs.  */
      90  	  error_t err;
      91  	  mach_port_t ref;
      92  	  ref = __mach_reply_port ();
      93  	  err = HURD_PORT_USE
      94  	    (&_hurd_ports[which],
      95  	     ({
      96  	       err = __io_reauthenticate (port, ref, MACH_MSG_TYPE_MAKE_SEND);
      97  	       if (!err)
      98  		 err = __auth_user_authenticate (_hurd_id.rid_auth,
      99  						 ref, MACH_MSG_TYPE_MAKE_SEND,
     100  						 result);
     101  	       err;
     102  	     }));
     103  	  __mach_port_destroy (__mach_task_self (), ref);
     104  	  return err;
     105  	}
     106  
     107        error_t init_port (int which, error_t (*operate) (mach_port_t))
     108  	{
     109  	  switch (which)
     110  	    {
     111  	    case INIT_PORT_AUTH:
     112  	      return (*operate) (_hurd_id.rid_auth);
     113  	    case INIT_PORT_CRDIR:
     114  	      return (reauthenticate (INIT_PORT_CRDIR, &rcrdir) ?:
     115  		      (*operate) (rcrdir));
     116  	    case INIT_PORT_CWDIR:
     117  	      if (fd == AT_FDCWD || file[0] == '/')
     118  		return (reauthenticate (INIT_PORT_CWDIR, &rcwdir) ?:
     119  			(*operate) (rcwdir));
     120  	      else
     121  		return (reauthenticate_cwdir_at (&rcwdir) ?:
     122  			(*operate) (rcwdir));
     123  	    default:
     124  	      return _hurd_ports_use (which, operate);
     125  	    }
     126  	}
     127  
     128        rcrdir = rcwdir = MACH_PORT_NULL;
     129  
     130       retry:
     131        HURD_CRITICAL_BEGIN;
     132  
     133        __mutex_lock (&_hurd_id.lock);
     134        /* Get _hurd_id up to date.  */
     135        if (err = _hurd_check_ids ())
     136  	goto lose;
     137  
     138        if (_hurd_id.rid_auth == MACH_PORT_NULL)
     139  	{
     140  	  /* Set up _hurd_id.rid_auth.  This is a special auth server port
     141  	     which uses the real uid and gid (the first aux uid and gid) as
     142  	     the only effective uid and gid.  */
     143  
     144  	  if (_hurd_id.aux.nuids < 1 || _hurd_id.aux.ngids < 1)
     145  	    {
     146  	      /* We do not have a real UID and GID.  Lose, lose, lose!  */
     147  	      err = EGRATUITOUS;
     148  	      goto lose;
     149  	    }
     150  
     151  	  /* Create a new auth port using our real UID and GID (the first
     152  	     auxiliary UID and GID) as the only effective IDs.  */
     153  	  if (err = __USEPORT (AUTH,
     154  			       __auth_makeauth (port,
     155  						NULL, MACH_MSG_TYPE_COPY_SEND, 0,
     156  						_hurd_id.aux.uids, 1,
     157  						_hurd_id.aux.uids,
     158  						_hurd_id.aux.nuids,
     159  						_hurd_id.aux.gids, 1,
     160  						_hurd_id.aux.gids,
     161  						_hurd_id.aux.ngids,
     162  						&_hurd_id.rid_auth)))
     163  	    goto lose;
     164  	}
     165  
     166        if (!err)
     167  	/* Look up the file name using the modified init ports.  */
     168  	err = __hurd_file_name_lookup (&init_port, &__getdport, 0,
     169  				       file, hurd_flags, 0, &io);
     170  
     171        /* We are done with _hurd_id.rid_auth now.  */
     172       lose:
     173        __mutex_unlock (&_hurd_id.lock);
     174  
     175        HURD_CRITICAL_END;
     176        if (err == EINTR)
     177  	/* Got a signal while inside an RPC of the critical section, retry again */
     178  	goto retry;
     179  
     180        if (rcrdir != MACH_PORT_NULL)
     181  	__mach_port_deallocate (__mach_task_self (), rcrdir);
     182        if (rcwdir != MACH_PORT_NULL)
     183  	__mach_port_deallocate (__mach_task_self (), rcwdir);
     184        if (err)
     185  	return errfunc (err);
     186      }
     187  
     188    /* Find out what types of access we are allowed to this file.  */
     189    err = __file_check_access (io, &allowed);
     190    __mach_port_deallocate (__mach_task_self (), io);
     191    if (err)
     192      return errfunc (err);
     193  
     194    flags = 0;
     195    if (type & R_OK)
     196      flags |= O_READ;
     197    if (type & W_OK)
     198      flags |= O_WRITE;
     199    if (type & X_OK)
     200      flags |= O_EXEC;
     201  
     202    if (flags & ~allowed)
     203      /* We are not allowed all the requested types of access.  */
     204      return errfunc (EACCES);
     205  
     206    return 0;
     207  }
     208  
     209  int
     210  __faccessat_noerrno (int fd, const char *file, int type, int at_flags)
     211  {
     212    return __faccessat_common (fd, file, type, at_flags, hurd_fail_noerrno);
     213  }
     214  
     215  int
     216  __faccessat (int fd, const char *file, int type, int at_flags)
     217  {
     218    return __faccessat_common (fd, file, type, at_flags, hurd_fail_seterrno);
     219  }
     220  weak_alias (__faccessat, faccessat)