Blame hurd/hurdauth.c

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