Blame hurd/hurdauth.c

Packit Service 82fcde
/* Copyright (C) 1991-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <hurd.h>
Packit Service 82fcde
#include <hurd/msg_server.h>
Packit Service 82fcde
#include <hurd/id.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
Packit Service 82fcde
int
Packit Service 82fcde
_hurd_refport_secure_p (mach_port_t ref)
Packit Service 82fcde
{
Packit Service 82fcde
  if (ref == __mach_task_self ())
Packit Service 82fcde
    return 1;
Packit Service 82fcde
  if (__USEPORT (AUTH, ref == port))
Packit Service 82fcde
    return 1;
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
kern_return_t
Packit Service 82fcde
_S_msg_add_auth (mach_port_t me,
Packit Service 82fcde
		 auth_t addauth)
Packit Service 82fcde
{
Packit Service 82fcde
  error_t err;
Packit Service 82fcde
  auth_t newauth;
Packit Service 82fcde
  uid_t *genuids, *gengids, *auxuids, *auxgids;
Packit Service 82fcde
  mach_msg_type_number_t ngenuids, ngengids, nauxuids, nauxgids;
Packit Service 82fcde
  uid_t *newgenuids, *newgengids, *newauxuids, *newauxgids;
Packit Service 82fcde
  mach_msg_type_number_t nnewgenuids, nnewgengids, nnewauxuids, nnewauxgids;
Packit Service 82fcde
Packit Service 82fcde
  /* Create a list of ids and store it in NEWLISTP, length NEWLISTLEN.
Packit Service 82fcde
     Keep all the ids in EXIST (len NEXIST), adding in those from NEW
Packit Service 82fcde
     (len NNEW) which are not already there.  */
Packit Service 82fcde
  error_t make_list (uid_t **newlistp, mach_msg_type_number_t *newlistlen,
Packit Service 82fcde
		     uid_t *exist, mach_msg_type_number_t nexist,
Packit Service 82fcde
		     uid_t *new, mach_msg_type_number_t nnew)
Packit Service 82fcde
    {
Packit Service 82fcde
      error_t urp;
Packit Service 82fcde
      int i, j, k;
Packit Service 82fcde
      vm_size_t offset;
Packit Service 82fcde
Packit Service 82fcde
      urp = __vm_allocate (mach_task_self (), (vm_address_t *) newlistp,
Packit Service 82fcde
			   nexist + nnew * sizeof (uid_t), 1);
Packit Service 82fcde
      if (urp)
Packit Service 82fcde
	return urp;
Packit Service 82fcde
Packit Service 82fcde
      j = 0;
Packit Service 82fcde
      for (i = 0; i < nexist; i++)
Packit Service 82fcde
	(*newlistp)[j++] = exist[i];
Packit Service 82fcde
Packit Service 82fcde
      for (i = 0; i < nnew; i++)
Packit Service 82fcde
	{
Packit Service 82fcde
	  for (k = 0; k < nexist; k++)
Packit Service 82fcde
	    if (exist[k] == new[i])
Packit Service 82fcde
	      break;
Packit Service 82fcde
	  if (k < nexist)
Packit Service 82fcde
	    continue;
Packit Service 82fcde
Packit Service 82fcde
	  (*newlistp)[j++] = new[i];
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      offset = (round_page (nexist + nnew * sizeof (uid_t))
Packit Service 82fcde
		- round_page (j * sizeof (uid_t)));
Packit Service 82fcde
      if (offset)
Packit Service 82fcde
	__vm_deallocate (mach_task_self (),
Packit Service 82fcde
		         (vm_address_t) (*newlistp
Packit Service 82fcde
				         + (nexist + nnew * sizeof (uid_t))),
Packit Service 82fcde
		         offset);
Packit Service 82fcde
      *newlistlen = j;
Packit Service 82fcde
      return 0;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Find out what ids ADDAUTH refers to */
Packit Service 82fcde
Packit Service 82fcde
  genuids = gengids = auxuids = auxgids = 0;
Packit Service 82fcde
  ngenuids = ngengids = nauxuids = nauxgids = 0;
Packit Service 82fcde
  err = __auth_getids (addauth,
Packit Service 82fcde
		       &genuids, &ngenuids,
Packit Service 82fcde
		       &auxuids, &nauxuids,
Packit Service 82fcde
		       &gengids, &ngengids,
Packit Service 82fcde
		       &auxgids, &nauxgids);
Packit Service 82fcde
  if (err)
Packit Service 82fcde
    return err;
Packit Service 82fcde
Packit Service 82fcde
  /* OR in these ids to what we already have, creating a new list. */
Packit Service 82fcde
Packit Service 82fcde
  HURD_CRITICAL_BEGIN;
Packit Service 82fcde
  __mutex_lock (&_hurd_id.lock);
Packit Service 82fcde
  _hurd_check_ids ();
Packit Service 82fcde
Packit Service 82fcde
#define MAKE(genaux,uidgid) 						    \
Packit Service 82fcde
  make_list (&new ## genaux ## uidgid ## s, 				    \
Packit Service 82fcde
	     &nnew ## genaux ## uidgid ## s,				    \
Packit Service 82fcde
	     _hurd_id.genaux.uidgid ## s,				    \
Packit Service 82fcde
	     _hurd_id.genaux.n ## uidgid ## s,				    \
Packit Service 82fcde
	     genaux ## uidgid ## s,					    \
Packit Service 82fcde
	     n ## genaux ## uidgid ## s)
Packit Service 82fcde
Packit Service 82fcde
  err = MAKE (gen, uid);
Packit Service 82fcde
  if (!err)
Packit Service 82fcde
    MAKE (aux, uid);
Packit Service 82fcde
  if (!err)
Packit Service 82fcde
    MAKE (gen, gid);
Packit Service 82fcde
  if (!err)
Packit Service 82fcde
    MAKE (aux, gid);
Packit Service 82fcde
#undef MAKE
Packit Service 82fcde
Packit Service 82fcde
  __mutex_unlock (&_hurd_id.lock);
Packit Service 82fcde
  HURD_CRITICAL_END;
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
  /* Create the new auth port */
Packit Service 82fcde
Packit Service 82fcde
  if (!err)
Packit Service 82fcde
    err = __USEPORT (AUTH,
Packit Service 82fcde
		     __auth_makeauth (port,
Packit Service 82fcde
				      &addauth, MACH_MSG_TYPE_MOVE_SEND, 1,
Packit Service 82fcde
				      newgenuids, nnewgenuids,
Packit Service 82fcde
				      newauxuids, nnewauxuids,
Packit Service 82fcde
				      newgengids, nnewgengids,
Packit Service 82fcde
				      newauxgids, nnewauxgids,
Packit Service 82fcde
				      &newauth));
Packit Service 82fcde
Packit Service 82fcde
#define freeup(array, len) \
Packit Service 82fcde
  if (array) \
Packit Service 82fcde
    __vm_deallocate (mach_task_self (), (vm_address_t) array, \
Packit Service 82fcde
		     len * sizeof (uid_t));
Packit Service 82fcde
Packit Service 82fcde
  freeup (genuids, ngenuids);
Packit Service 82fcde
  freeup (auxuids, nauxuids);
Packit Service 82fcde
  freeup (gengids, ngengids);
Packit Service 82fcde
  freeup (auxgids, nauxgids);
Packit Service 82fcde
  freeup (newgenuids, nnewgenuids);
Packit Service 82fcde
  freeup (newauxuids, nnewauxuids);
Packit Service 82fcde
  freeup (newgengids, nnewgengids);
Packit Service 82fcde
  freeup (newauxgids, nnewauxgids);
Packit Service 82fcde
#undef freeup
Packit Service 82fcde
Packit Service 82fcde
  if (err)
Packit Service 82fcde
    return err;
Packit Service 82fcde
Packit Service 82fcde
  /* And install it. */
Packit Service 82fcde
Packit Service 82fcde
  err = __setauth (newauth);
Packit Service 82fcde
  __mach_port_deallocate (__mach_task_self (), newauth);
Packit Service 82fcde
  if (err)
Packit Service 82fcde
    return errno;
Packit Service 82fcde
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
kern_return_t
Packit Service 82fcde
_S_msg_del_auth (mach_port_t me,
Packit Service 82fcde
		 task_t task,
Packit Service 82fcde
		 intarray_t uids, mach_msg_type_number_t nuids,
Packit Service 82fcde
		 intarray_t gids, mach_msg_type_number_t ngids)
Packit Service 82fcde
{
Packit Service 82fcde
  error_t err;
Packit Service 82fcde
  auth_t newauth;
Packit Service 82fcde
Packit Service 82fcde
  if (!_hurd_refport_secure_p (task))
Packit Service 82fcde
    return EPERM;
Packit Service 82fcde
Packit Service 82fcde
  HURD_CRITICAL_BEGIN;
Packit Service 82fcde
  __mutex_lock (&_hurd_id.lock);
Packit Service 82fcde
  err = _hurd_check_ids ();
Packit Service 82fcde
Packit Service 82fcde
  if (!err)
Packit Service 82fcde
    {
Packit Service 82fcde
      size_t i, j;
Packit Service 82fcde
      size_t nu = _hurd_id.gen.nuids, ng = _hurd_id.gen.ngids;
Packit Service 82fcde
      uid_t newu[nu];
Packit Service 82fcde
      gid_t newg[ng];
Packit Service 82fcde
Packit Service 82fcde
      memcpy (newu, _hurd_id.gen.uids, nu * sizeof (uid_t));
Packit Service 82fcde
      memcpy (newg, _hurd_id.gen.gids, ng * sizeof (gid_t));
Packit Service 82fcde
Packit Service 82fcde
      for (j = 0; j < nuids; ++j)
Packit Service 82fcde
	{
Packit Service 82fcde
	  const uid_t uid = uids[j];
Packit Service 82fcde
	  for (i = 0; i < nu; ++i)
Packit Service 82fcde
	    if (newu[i] == uid)
Packit Service 82fcde
	      /* Move the last uid into this slot, and decrease the
Packit Service 82fcde
		 number of uids so the last slot is no longer used.  */
Packit Service 82fcde
	      newu[i] = newu[--nu];
Packit Service 82fcde
	}
Packit Service 82fcde
      __vm_deallocate (__mach_task_self (),
Packit Service 82fcde
		       (vm_address_t) uids, nuids * sizeof (uid_t));
Packit Service 82fcde
Packit Service 82fcde
      for (j = 0; j < ngids; ++j)
Packit Service 82fcde
	{
Packit Service 82fcde
	  const gid_t gid = gids[j];
Packit Service 82fcde
	  for (i = 0; i < nu; ++i)
Packit Service 82fcde
	    if (newu[i] == gid)
Packit Service 82fcde
	      /* Move the last gid into this slot, and decrease the
Packit Service 82fcde
		 number of gids so the last slot is no longer used.  */
Packit Service 82fcde
	      newu[i] = newu[--nu];
Packit Service 82fcde
	}
Packit Service 82fcde
      __vm_deallocate (__mach_task_self (),
Packit Service 82fcde
		       (vm_address_t) gids, ngids * sizeof (gid_t));
Packit Service 82fcde
Packit Service 82fcde
      err = __USEPORT (AUTH, __auth_makeauth
Packit Service 82fcde
		       (port,
Packit Service 82fcde
			NULL, MACH_MSG_TYPE_COPY_SEND, 0,
Packit Service 82fcde
			newu, nu,
Packit Service 82fcde
			_hurd_id.aux.uids, _hurd_id.aux.nuids,
Packit Service 82fcde
			newg, ng,
Packit Service 82fcde
			_hurd_id.aux.uids, _hurd_id.aux.ngids,
Packit Service 82fcde
			&newauth));
Packit Service 82fcde
    }
Packit Service 82fcde
  __mutex_unlock (&_hurd_id.lock);
Packit Service 82fcde
  HURD_CRITICAL_END;
Packit Service 82fcde
Packit Service 82fcde
  if (err)
Packit Service 82fcde
    return err;
Packit Service 82fcde
Packit Service 82fcde
  err = __setauth (newauth);
Packit Service 82fcde
  __mach_port_deallocate (__mach_task_self (), newauth);
Packit Service 82fcde
  if (err)
Packit Service 82fcde
    return errno;
Packit Service 82fcde
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}