klpd.c revision ddf7fe95b8ad67aa16deb427a0b78f4dd4ff22b1
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/cred_impl.h>
#include <sys/sysmacros.h>
#include <sys/pathname.h>
static kmutex_t klpd_mutex;
typedef struct klpd_reg {
int klpd_indel; /* Disabled */
} klpd_reg_t;
/*
* This data structure hangs off the credential of a process; the
* credential is finalized and cannot be changed; but this structure
* can be changed when a new door server for the particular group
* needs to be registered. It is refcounted and shared between
* processes with common ancestry.
*
* The reference count is atomically updated.
*
* But the registration probably needs to be updated under a lock.
*/
typedef struct credklpd {
} credklpd_t;
static void klpd_unlink(klpd_reg_t *);
static int klpd_unreg_dh(door_handle_t);
static credklpd_t *crklpd_alloc(void);
extern size_t max_vnode_path;
void
klpd_rele(klpd_reg_t *p)
{
klpd_unlink(p);
door_ki_rele(p->klpd_door);
kmem_free(p, sizeof (*p));
}
}
/*
* In order to be able to walk the lists, we can't unlink the entry
* until the reference count drops to 0. If we remove it too soon,
* list walkers will terminate when they happen to call a now orphaned
* entry.
*/
static klpd_reg_t *
{
klpd_reg_t *r = p->klpd_next;
klpd_rele(p);
return (r);
}
static void
klpd_hold(klpd_reg_t *p)
{
}
/*
* Remove registration from where it is registered. Returns next in list.
*/
static void
{
}
/*
* Remove the head of the klpd list and decrement its refcnt.
* The lock guarding the list should be held; this function is
* called when we are sure we want to remove the entry from the
* list but not so sure that the reference count has dropped back to
* 1 and is specifically intended to remove the non-list variants.
*/
void
{
klpd_reg_t *p = *pp;
if (p == NULL)
return;
klpd_unlink(p);
klpd_rele(p);
}
/*
* Link new entry in list. The Boolean argument specifies whether this
* list can contain only a single item or multiple items.
* Returns the entry which needs to be released if single is B_TRUE.
*/
static klpd_reg_t *
{
*listp = p;
if (single) {
return (old);
} else
}
return (NULL);
}
/*
* The typical call consists of:
* - priv_set_t
* - some integer data (type, value)
* for now, it's just one bit.
*/
static klpd_head_t *
{
char *comp;
int proto;
switch (type) {
case KLPDARG_NOMORE:
khp->klh_argoff = 0;
break;
case KLPDARG_VNODE:
return (NULL);
else
clen = 0;
return (NULL);
}
if (clen != 0) {
return (NULL);
}
/* Don't make root into a double "/" */
if (plen <= 2)
plen = 0;
}
break;
case KLPDARG_PORT:
switch (proto) {
break;
break;
break;
break;
}
/* FALLTHROUGH */
case KLPDARG_INT:
case KLPDARG_TCPPORT:
case KLPDARG_UDPPORT:
case KLPDARG_SCTPPORT:
case KLPDARG_SDPPORT:
break;
default:
return (NULL);
}
}
return (khp);
}
static int
{
int res;
int dres;
return (-1);
return (-1);
switch (dres) {
case EAGAIN:
delay(1);
continue;
case EINVAL:
case EBADF:
/* Bad door, don't call it again. */
(void) klpd_unreg_dh(p->klpd_door);
/* FALLTHROUGH */
case EINTR:
/* Pending signal, nothing we can do. */
/* FALLTHROUGH */
default:
return (-1);
}
}
/* Bogus return value, must be a failure */
return (-1);
}
return (res);
}
int
{
klpd_reg_t *p;
int rv = -1;
/*
* These locks must not be held when this code is called;
* callbacks to userland with these locks held will result
* in issues. That said, the code at the call sides was
* restructured not to call with any of the locks held and
* no policies operate by default on most processes.
*/
return (-1);
}
/*
* Enforce the limit set for the call process (still).
*/
return (-1);
/* Try 1: get the credential specific klpd */
p->klpd_indel == 0 &&
klpd_hold(p);
klpd_rele(p);
if (rv != -1)
return (rv == 0 ? 0 : -1);
} else {
}
}
/* Try 2: get the project specific klpd */
klpd_hold(p);
if (p->klpd_indel == 0 &&
}
klpd_rele(p);
if (rv != -1)
return (rv == 0 ? 0 : -1);
} else {
}
/* Try 3: get the global klpd list */
p->klpd_indel == 0 &&
klpd_hold(p);
p = klpd_rele_next(p);
if (rv != -1)
break;
} else {
p = p->klpd_next;
}
}
return (rv == 0 ? 0 : -1);
}
/*
* Register the klpd.
* If the pid_t passed in is positive, update the registration for
* the specific process; that is only possible if the process already
* has a registration on it. This change of registration will affect
* all processes which share common ancestry.
*
* MY_PID (pid 0) can be used to create or change the context for
* the current process, typically done after fork().
*
* A negative value can be used to register a klpd globally.
*
* The per-credential klpd needs to be cleaned up when entering
* a zone or unsetting the flag.
*/
int
{
switch (type) {
case P_PID:
ckp = crklpd_alloc();
break;
case P_PROJID:
break;
default:
}
/*
* Verify the door passed in; it must be a door and we won't
* allow processes to be called on their own behalf.
*/
}
}
} else if ((int)pid < 0) {
/* Global daemon */
/* No need to lock, sole reference to ckp */
mutex_enter(&p->p_crlock);
mutex_exit(&p->p_crlock);
} else {
proc_t *p;
}
mutex_enter(&p->p_crlock);
mutex_exit(&p->p_crlock);
/*
* We're going to update the credential's ckp in place;
* this requires that it exists.
*/
}
}
return (0);
}
static int
{
klpd_reg_t *p;
break;
}
if (p == NULL) {
return (EINVAL);
}
if (p->klpd_indel != 0) {
return (EAGAIN);
}
p->klpd_indel = 1;
klpd_rele(p);
return (0);
}
int
{
int res = 0;
proc_t *p;
switch (type) {
case P_PID:
break;
case P_PROJID:
break;
default:
}
}
else
goto out;
} else if ((int)pid > 0) {
if (p == NULL) {
}
mutex_enter(&p->p_crlock);
} else if (pid == 0) {
p = curproc;
mutex_enter(&p->p_crlock);
} else {
goto out;
}
} else {
}
mutex_exit(&p->p_crlock);
out:
if (res != 0)
return (0);
}
void
{
}
void
{
}
}
static credklpd_t *
crklpd_alloc(void)
{
return (res);
}
void
{
} else {
}
}