Пример #1
0
/* Check to see whether USER should be considered the owner of the
   file identified by ST.  If so, return zero; otherwise return an
   appropriate error code. */
error_t
fshelp_isowner (struct stat *st, struct iouser *user)
{
  /* Permitted if the user has the owner UID, the superuser UID, or if
     the user is in the group of the file and has the group ID as
     their user ID.  */
  if (idvec_contains (user->uids, st->st_uid)
      || idvec_contains (user->uids, 0)
      || (idvec_contains (user->gids, st->st_gid)
	  && idvec_contains (user->uids, st->st_gid)))
    return 0;
  else
    return EPERM;
}
Пример #2
0
/* Return an NFS file handle for CRED in FH & FN_LEN.  */
error_t
diskfs_S_file_getfh (struct protid *cred, char **fh, size_t *fh_len)
{
  struct node *node;
  union diskfs_fhandle *f;

  if (! cred)
    return EOPNOTSUPP;

  if (! idvec_contains (cred->user->uids, 0))
    return EPERM;

  assert (sizeof *f == sizeof f->bytes);

  node = cred->po->np;

  pthread_mutex_lock (&node->lock);

  if (*fh_len < sizeof (union diskfs_fhandle))
    *fh = mmap (0, sizeof (union diskfs_fhandle), PROT_READ|PROT_WRITE,
		MAP_ANON, 0, 0);
  *fh_len = sizeof *f;

  f = (union diskfs_fhandle *) *fh;

  memset (f, 0, sizeof *f);
  f->data.cache_id = node->cache_id;
  f->data.gen = node->dn_stat.st_gen;

  pthread_mutex_unlock (&node->lock);

  return 0;
}
Пример #3
0
/* If IDVEC doesn't contain ID, add it onto the end, returning ENOMEM if
   there's not enough memory; otherwise, do nothing.  */
error_t
idvec_add_new (struct idvec *idvec, uid_t id)
{
  if (idvec_contains (idvec, id))
    return 0;
  else
    return idvec_add (idvec, id);
}
Пример #4
0
error_t
iohelp_restrict_iouser (struct iouser **new_user,
			const struct iouser *old_user,
			const uid_t *uids, int nuids,
			const gid_t *gids, int ngids)
{
  if (idvec_contains (old_user->uids, 0))
    /* OLD_USER has root access, and so may use any ids.  */
    return iohelp_create_complex_iouser (new_user, uids, nuids, gids, ngids);
  else
    {
      struct idvec *uvec, *gvec;
      int i;
      error_t err;

      uvec = make_idvec ();
      if (! uvec)
        return ENOMEM;

      gvec = make_idvec ();
      if (! gvec)
        {
	  idvec_free (uvec);
	  return ENOMEM;
	}

      /* Otherwise, use any of the requested ids that OLD_USER already has.  */
      for (i = 0; i < old_user->uids->num; i++)
	if (listmember (uids, old_user->uids->ids[i], nuids))
	  {
	    err = idvec_add (uvec, old_user->uids->ids[i]);
	    if (err)
	      goto out;
	  }
      for (i = 0; i < old_user->gids->num; i++)
	if (listmember (gids, old_user->gids->ids[i], ngids))
	  {
	    err = idvec_add (gvec, old_user->gids->ids[i]);
	    if (err)
	      goto out;
	  }

      err = iohelp_create_iouser (new_user, uvec, gvec);

      if (err)
        {
        out:
	  idvec_free (uvec);
	  idvec_free (gvec);
	}
      return err;
    }
}
kern_return_t
trivfs_S_io_restrict_auth (struct trivfs_protid *cred,
			   mach_port_t reply,
			   mach_msg_type_name_t replytype,
			   mach_port_t *newport,
			   mach_msg_type_name_t *newporttype,
			   uid_t *uids, size_t nuids,
			   uid_t *gids, size_t ngids)
{
  int i;
  error_t err;
  struct trivfs_protid *newcred;
  struct idvec *uvec, *gvec;
  struct iouser *user;

  if (!cred)
    return EOPNOTSUPP;

  if (cred->isroot)
    /* CRED has root access, and so may use any ids.  */
    {
      err = iohelp_create_complex_iouser (&user, uids, nuids, gids, ngids);
      if (err)
        return err;
    }
  else
    {
      uvec = make_idvec ();
      if (! uvec)
        return ENOMEM;

      gvec = make_idvec ();
      if (! gvec)
        {
	  idvec_free (uvec);
	  return ENOMEM;
	}

      /* Otherwise, use any of the requested ids that CRED already has.  */
      for (i = 0; i < cred->user->uids->num; i++)
	if (listmember (uids, cred->user->uids->ids[i], nuids))
	  {
	    err = idvec_add (uvec, cred->user->uids->ids[i]);
	    if (err)
	      goto out;
	  }

      for (i = 0; i < cred->user->gids->num; i++)
	if (listmember (gids, cred->user->gids->ids[i], ngids))
	  {
	    err = idvec_add (gvec, cred->user->gids->ids[i]);
	    if (err)
	      goto out;
	  }

      err = iohelp_create_iouser (&user, uvec, gvec);
      if (err)
        {
	out:
	  idvec_free (uvec);
	  idvec_free (gvec);
	  return err;
	}
    }

  err = ports_create_port (cred->po->cntl->protid_class,
			   cred->po->cntl->protid_bucket,
			   sizeof (struct trivfs_protid),
			   &newcred);
  if (err)
    {
      iohelp_free_iouser (user);
      return err;
    }

  newcred->isroot = 0;
  mutex_lock (&cred->po->cntl->lock);
  newcred->po = cred->po;
  newcred->po->refcnt++;
  mutex_unlock (&cred->po->cntl->lock);
  if (cred->isroot && idvec_contains (user->uids, 0))
    newcred->isroot = 1;
  newcred->user = user;
  newcred->hook = cred->hook;

  err = io_restrict_auth (cred->realnode, &newcred->realnode,
			  user->uids->ids, user->uids->num,
			  user->gids->ids, user->gids->num);
  if (!err && trivfs_protid_create_hook)
    {
      err = (*trivfs_protid_create_hook) (newcred);
      if (err)
	mach_port_deallocate (mach_task_self (), newcred->realnode);
    }

  if (err)
    /* Signal that the user destroy hook shouldn't be called on NEWCRED.  */
    newcred->realnode = MACH_PORT_NULL;
  else
    {
      *newport = ports_get_right (newcred);
      *newporttype = MACH_MSG_TYPE_MAKE_SEND;
    }

  /* This will destroy NEWCRED if we got an error and didn't do the
     ports_get_right above.  */
  ports_port_deref (newcred);

  return 0;
}