(root)/
glibc-2.38/
hurd/
hurdauth.c
       1  /* Copyright (C) 1991-2023 Free Software Foundation, Inc.
       2     This file is part of the GNU C Library.
       3  
       4     The GNU C Library is free software; you can redistribute it and/or
       5     modify it under the terms of the GNU Lesser General Public
       6     License as published by the Free Software Foundation; either
       7     version 2.1 of the License, or (at your option) any later version.
       8  
       9     The GNU C Library is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12     Lesser General Public License for more details.
      13  
      14     You should have received a copy of the GNU Lesser General Public
      15     License along with the GNU C Library; if not, see
      16     <https://www.gnu.org/licenses/>.  */
      17  
      18  #include <hurd.h>
      19  #include <hurd/msg_server.h>
      20  #include <hurd/id.h>
      21  #include <string.h>
      22  
      23  int
      24  _hurd_refport_secure_p (mach_port_t ref)
      25  {
      26    if (ref == __mach_task_self ())
      27      return 1;
      28    if (__USEPORT (AUTH, ref == port))
      29      return 1;
      30    return 0;
      31  }
      32  
      33  kern_return_t
      34  _S_msg_add_auth (mach_port_t me,
      35  		 auth_t addauth)
      36  {
      37    error_t err;
      38    auth_t newauth;
      39    uid_t *genuids, *gengids, *auxuids, *auxgids;
      40    mach_msg_type_number_t ngenuids, ngengids, nauxuids, nauxgids;
      41    uid_t *newgenuids, *newgengids, *newauxuids, *newauxgids;
      42    mach_msg_type_number_t nnewgenuids, nnewgengids, nnewauxuids, nnewauxgids;
      43  
      44    /* Create a list of ids and store it in NEWLISTP, length NEWLISTLEN.
      45       Keep all the ids in EXIST (len NEXIST), adding in those from NEW
      46       (len NNEW) which are not already there.  */
      47    error_t make_list (uid_t **newlistp, mach_msg_type_number_t *newlistlen,
      48  		     uid_t *exist, mach_msg_type_number_t nexist,
      49  		     uid_t *new, mach_msg_type_number_t nnew)
      50      {
      51        error_t urp;
      52        int i, j, k;
      53        vm_size_t offset;
      54  
      55        urp = __vm_allocate (mach_task_self (), (vm_address_t *) newlistp,
      56  			   nexist + nnew * sizeof (uid_t), 1);
      57        if (urp)
      58  	return urp;
      59  
      60        j = 0;
      61        for (i = 0; i < nexist; i++)
      62  	(*newlistp)[j++] = exist[i];
      63  
      64        for (i = 0; i < nnew; i++)
      65  	{
      66  	  for (k = 0; k < nexist; k++)
      67  	    if (exist[k] == new[i])
      68  	      break;
      69  	  if (k < nexist)
      70  	    continue;
      71  
      72  	  (*newlistp)[j++] = new[i];
      73  	}
      74  
      75        offset = (round_page (nexist + nnew * sizeof (uid_t))
      76  		- round_page (j * sizeof (uid_t)));
      77        if (offset)
      78  	__vm_deallocate (mach_task_self (),
      79  		         (vm_address_t) (*newlistp
      80  				         + (nexist + nnew * sizeof (uid_t))),
      81  		         offset);
      82        *newlistlen = j;
      83        return 0;
      84      }
      85  
      86    /* Find out what ids ADDAUTH refers to */
      87  
      88    genuids = gengids = auxuids = auxgids = 0;
      89    ngenuids = ngengids = nauxuids = nauxgids = 0;
      90    err = __auth_getids (addauth,
      91  		       &genuids, &ngenuids,
      92  		       &auxuids, &nauxuids,
      93  		       &gengids, &ngengids,
      94  		       &auxgids, &nauxgids);
      95    if (err)
      96      return err;
      97  
      98    /* OR in these ids to what we already have, creating a new list. */
      99  
     100    HURD_CRITICAL_BEGIN;
     101    __mutex_lock (&_hurd_id.lock);
     102    _hurd_check_ids ();
     103  
     104  #define MAKE(genaux,uidgid) ({						    \
     105    new ## genaux ## uidgid ## s = 0;					    \
     106    nnew ## genaux ## uidgid ## s = 0;					    \
     107    make_list (&new ## genaux ## uidgid ## s,				    \
     108  	     &nnew ## genaux ## uidgid ## s,				    \
     109  	     _hurd_id.genaux.uidgid ## s,				    \
     110  	     _hurd_id.genaux.n ## uidgid ## s,				    \
     111  	     genaux ## uidgid ## s,					    \
     112  	     n ## genaux ## uidgid ## s);				    \
     113  })
     114  
     115    err = MAKE (gen, uid);
     116    if (!err)
     117      err = MAKE (aux, uid);
     118    if (!err)
     119      err = MAKE (gen, gid);
     120    if (!err)
     121      err = MAKE (aux, gid);
     122  #undef MAKE
     123  
     124    __mutex_unlock (&_hurd_id.lock);
     125    HURD_CRITICAL_END;
     126  
     127  
     128    /* Create the new auth port */
     129  
     130    if (!err)
     131      err = __USEPORT (AUTH,
     132  		     __auth_makeauth (port,
     133  				      &addauth, MACH_MSG_TYPE_MOVE_SEND, 1,
     134  				      newgenuids, nnewgenuids,
     135  				      newauxuids, nnewauxuids,
     136  				      newgengids, nnewgengids,
     137  				      newauxgids, nnewauxgids,
     138  				      &newauth));
     139  
     140  #define freeup(array, len) \
     141    if (array) \
     142      __vm_deallocate (mach_task_self (), (vm_address_t) array, \
     143  		     len * sizeof (uid_t));
     144  
     145    freeup (genuids, ngenuids);
     146    freeup (auxuids, nauxuids);
     147    freeup (gengids, ngengids);
     148    freeup (auxgids, nauxgids);
     149    freeup (newgenuids, nnewgenuids);
     150    freeup (newauxuids, nnewauxuids);
     151    freeup (newgengids, nnewgengids);
     152    freeup (newauxgids, nnewauxgids);
     153  #undef freeup
     154  
     155    if (err)
     156      return err;
     157  
     158    /* And install it. */
     159  
     160    err = __setauth (newauth);
     161    __mach_port_deallocate (__mach_task_self (), newauth);
     162    if (err)
     163      return errno;
     164  
     165    return 0;
     166  }
     167  
     168  kern_return_t
     169  _S_msg_del_auth (mach_port_t me,
     170  		 task_t task,
     171  		 const_intarray_t uids, mach_msg_type_number_t nuids,
     172  		 const_intarray_t gids, mach_msg_type_number_t ngids)
     173  {
     174    error_t err;
     175    auth_t newauth;
     176  
     177    if (!_hurd_refport_secure_p (task))
     178      return EPERM;
     179  
     180    HURD_CRITICAL_BEGIN;
     181    __mutex_lock (&_hurd_id.lock);
     182    err = _hurd_check_ids ();
     183  
     184    if (!err)
     185      {
     186        size_t i, j;
     187        size_t nu = _hurd_id.gen.nuids, ng = _hurd_id.gen.ngids;
     188        uid_t newu[nu];
     189        gid_t newg[ng];
     190  
     191        memcpy (newu, _hurd_id.gen.uids, nu * sizeof (uid_t));
     192        memcpy (newg, _hurd_id.gen.gids, ng * sizeof (gid_t));
     193  
     194        for (j = 0; j < nuids; ++j)
     195  	{
     196  	  const uid_t uid = uids[j];
     197  	  for (i = 0; i < nu; ++i)
     198  	    if (newu[i] == uid)
     199  	      /* Move the last uid into this slot, and decrease the
     200  		 number of uids so the last slot is no longer used.  */
     201  	      newu[i] = newu[--nu];
     202  	}
     203        __vm_deallocate (__mach_task_self (),
     204  		       (vm_address_t) uids, nuids * sizeof (uid_t));
     205  
     206        for (j = 0; j < ngids; ++j)
     207  	{
     208  	  const gid_t gid = gids[j];
     209  	  for (i = 0; i < nu; ++i)
     210  	    if (newu[i] == gid)
     211  	      /* Move the last gid into this slot, and decrease the
     212  		 number of gids so the last slot is no longer used.  */
     213  	      newu[i] = newu[--nu];
     214  	}
     215        __vm_deallocate (__mach_task_self (),
     216  		       (vm_address_t) gids, ngids * sizeof (gid_t));
     217  
     218        err = __USEPORT (AUTH, __auth_makeauth
     219  		       (port,
     220  			NULL, MACH_MSG_TYPE_COPY_SEND, 0,
     221  			newu, nu,
     222  			_hurd_id.aux.uids, _hurd_id.aux.nuids,
     223  			newg, ng,
     224  			_hurd_id.aux.uids, _hurd_id.aux.ngids,
     225  			&newauth));
     226      }
     227    __mutex_unlock (&_hurd_id.lock);
     228    HURD_CRITICAL_END;
     229  
     230    if (err)
     231      return err;
     232  
     233    err = __setauth (newauth);
     234    __mach_port_deallocate (__mach_task_self (), newauth);
     235    if (err)
     236      return errno;
     237  
     238    return 0;
     239  }