Exemplo n.º 1
0
static int
getqctrl(caddr_t data)
{
	au_kcontext_t	*kctx = GET_KCTX_PZ;
	STRUCT_DECL(au_qctrl, qctrl);
	STRUCT_INIT(qctrl, get_udatamodel());

	mutex_enter(&(kctx->auk_queue.lock));
	STRUCT_FSET(qctrl, aq_hiwater, kctx->auk_queue.hiwater);
	STRUCT_FSET(qctrl, aq_lowater, kctx->auk_queue.lowater);
	STRUCT_FSET(qctrl, aq_bufsz, kctx->auk_queue.bufsz);
	STRUCT_FSET(qctrl, aq_delay, kctx->auk_queue.delay);
	mutex_exit(&(kctx->auk_queue.lock));

	if (copyout(STRUCT_BUF(qctrl), data, STRUCT_SIZE(qctrl)))
		return (EFAULT);

	return (0);
}
Exemplo n.º 2
0
/* ARGSUSED */
static int
get_soft_list(dev_t dev, caddr_t arg, int mode, int *rval)
{
	STRUCT_DECL(crypto_get_soft_list, soft_list);
	char *names;
	size_t len;
	uint_t count;

	STRUCT_INIT(soft_list, mode);

	if (copyin(arg, STRUCT_BUF(soft_list), STRUCT_SIZE(soft_list)) != 0)
		return (EFAULT);

	/* get the list from the core module */
	if (crypto_get_soft_list(&count, &names, &len) != 0) {
		STRUCT_FSET(soft_list, sl_return_value, CRYPTO_FAILED);
		if (copyout(STRUCT_BUF(soft_list), arg,
		    STRUCT_SIZE(soft_list)) != 0) {
			return (EFAULT);
		}
		return (0);
	}

	/* check if buffer is too small */
	if (len > STRUCT_FGET(soft_list, sl_soft_len)) {
		STRUCT_FSET(soft_list, sl_soft_count, count);
		STRUCT_FSET(soft_list, sl_soft_len, len);
		STRUCT_FSET(soft_list, sl_return_value,
		    CRYPTO_BUFFER_TOO_SMALL);
		kmem_free(names, len);
		if (copyout(STRUCT_BUF(soft_list), arg,
		    STRUCT_SIZE(soft_list)) != 0) {
			return (EFAULT);
		}
		return (0);
	}

	STRUCT_FSET(soft_list, sl_soft_count, count);
	STRUCT_FSET(soft_list, sl_soft_len, len);
	STRUCT_FSET(soft_list, sl_return_value, CRYPTO_SUCCESS);

	if (count > 0 && copyout(names,
	    STRUCT_FGETP(soft_list, sl_soft_names), len) != 0) {
		kmem_free(names, len);
		return (EFAULT);
	}
	kmem_free(names, len);

	if (copyout(STRUCT_BUF(soft_list), arg, STRUCT_SIZE(soft_list)) != 0) {
		return (EFAULT);
	}

	return (0);
}
Exemplo n.º 3
0
/*ARGSUSED*/
static int
cpuid_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rval)
{
	char areq[16];
	void *ustr;

	switch (cmd) {
	case CPUID_GET_HWCAP: {
		STRUCT_DECL(cpuid_get_hwcap, h);

		STRUCT_INIT(h, mode);
		if (ddi_copyin((void *)arg,
		    STRUCT_BUF(h), STRUCT_SIZE(h), mode))
			return (EFAULT);
		if ((ustr = STRUCT_FGETP(h, cgh_archname)) != NULL &&
		    copyinstr(ustr, areq, sizeof (areq), NULL) != 0)
			return (EFAULT);
		areq[sizeof (areq) - 1] = '\0';

		if (strcmp(areq, architecture) == 0)
			STRUCT_FSET(h, cgh_hwcap, auxv_hwcap);
#if defined(_SYSCALL32_IMPL)
		else if (strcmp(areq, architecture_32) == 0)
			STRUCT_FSET(h, cgh_hwcap, auxv_hwcap32);
#endif
		else
			STRUCT_FSET(h, cgh_hwcap, 0);
		if (ddi_copyout(STRUCT_BUF(h),
		    (void *)arg, STRUCT_SIZE(h), mode))
			return (EFAULT);
		return (0);
	}

	default:
		return (ENOTTY);
	}
}
Exemplo n.º 4
0
/*
 * Get the audit state information from the current process.
 * Return EFAULT if copyout fails.
 */
int
getaudit(caddr_t info_p)
{
	STRUCT_DECL(auditinfo, info);
	const auditinfo_addr_t	*ainfo;
	model_t	model;

	if (secpolicy_audit_getattr(CRED(), B_FALSE) != 0)
		return (EPERM);

	model = get_udatamodel();
	STRUCT_INIT(info, model);

	ainfo = crgetauinfo(CRED());
	if (ainfo == NULL)
		return (EINVAL);

	/* trying to read a process with an IPv6 address? */
	if (ainfo->ai_termid.at_type == AU_IPv6)
		return (EOVERFLOW);

	STRUCT_FSET(info, ai_auid, ainfo->ai_auid);
	STRUCT_FSET(info, ai_mask, ainfo->ai_mask);
#ifdef _LP64
	if (model == DATAMODEL_ILP32) {
		dev32_t dev;
		/* convert internal 64 bit form to 32 bit version */
		if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) {
			return (EOVERFLOW);
		}
		STRUCT_FSET(info, ai_termid.port, dev);
	} else
		STRUCT_FSET(info, ai_termid.port, ainfo->ai_termid.at_port);
#else
	STRUCT_FSET(info, ai_termid.port, ainfo->ai_termid.at_port);
#endif
	STRUCT_FSET(info, ai_termid.machine, ainfo->ai_termid.at_addr[0]);
	STRUCT_FSET(info, ai_asid, ainfo->ai_asid);

	if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info)))
		return (EFAULT);

	return (0);
}
Exemplo n.º 5
0
static int
getkaudit(caddr_t info_p, int len)
{
	STRUCT_DECL(auditinfo_addr, info);
	model_t model;
	au_kcontext_t	*kctx = GET_KCTX_PZ;

	model = get_udatamodel();
	STRUCT_INIT(info, model);

	if (len < STRUCT_SIZE(info))
		return (EOVERFLOW);

	STRUCT_FSET(info, ai_auid, kctx->auk_info.ai_auid);
	STRUCT_FSET(info, ai_mask, kctx->auk_info.ai_namask);
#ifdef _LP64
	if (model == DATAMODEL_ILP32) {
		dev32_t dev;
		/* convert internal 64 bit form to 32 bit version */
		if (cmpldev(&dev, kctx->auk_info.ai_termid.at_port) == 0) {
			return (EOVERFLOW);
		}
		STRUCT_FSET(info, ai_termid.at_port, dev);
	} else {
		STRUCT_FSET(info, ai_termid.at_port,
		    kctx->auk_info.ai_termid.at_port);
	}
#else
	STRUCT_FSET(info, ai_termid.at_port,
	    kctx->auk_info.ai_termid.at_port);
#endif
	STRUCT_FSET(info, ai_termid.at_type,
	    kctx->auk_info.ai_termid.at_type);
	STRUCT_FSET(info, ai_termid.at_addr[0],
	    kctx->auk_info.ai_termid.at_addr[0]);
	STRUCT_FSET(info, ai_termid.at_addr[1],
	    kctx->auk_info.ai_termid.at_addr[1]);
	STRUCT_FSET(info, ai_termid.at_addr[2],
	    kctx->auk_info.ai_termid.at_addr[2]);
	STRUCT_FSET(info, ai_termid.at_addr[3],
	    kctx->auk_info.ai_termid.at_addr[3]);
	STRUCT_FSET(info, ai_asid, kctx->auk_info.ai_asid);

	if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info)))
		return (EFAULT);

	return (0);
}
Exemplo n.º 6
0
static int
getpinfo_addr(caddr_t data, int len)
{
	STRUCT_DECL(auditpinfo_addr, apinfo);
	proc_t *proc;
	const auditinfo_addr_t	*ainfo;
	model_t	model;
	cred_t	*cr, *newcred;

	model = get_udatamodel();
	STRUCT_INIT(apinfo, model);

	if (len < STRUCT_SIZE(apinfo))
		return (EOVERFLOW);

	if (copyin(data, STRUCT_BUF(apinfo), STRUCT_SIZE(apinfo)))
		return (EFAULT);

	newcred = cralloc();

	mutex_enter(&pidlock);
	if ((proc = prfind(STRUCT_FGET(apinfo, ap_pid))) == NULL) {
		mutex_exit(&pidlock);
		crfree(newcred);
		return (ESRCH);
	}
	mutex_enter(&proc->p_lock);	/* so process doesn't go away */
	mutex_exit(&pidlock);

	audit_update_context(proc, newcred);	/* make sure it's up-to-date */

	mutex_enter(&proc->p_crlock);
	crhold(cr = proc->p_cred);
	mutex_exit(&proc->p_crlock);
	mutex_exit(&proc->p_lock);

	ainfo = crgetauinfo(cr);
	if (ainfo == NULL) {
		crfree(cr);
		return (EINVAL);
	}

	STRUCT_FSET(apinfo, ap_auid, ainfo->ai_auid);
	STRUCT_FSET(apinfo, ap_asid, ainfo->ai_asid);
#ifdef _LP64
	if (model == DATAMODEL_ILP32) {
		dev32_t dev;
		/* convert internal 64 bit form to 32 bit version */
		if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) {
			crfree(cr);
			return (EOVERFLOW);
		}
		STRUCT_FSET(apinfo, ap_termid.at_port, dev);
	} else
		STRUCT_FSET(apinfo, ap_termid.at_port,
		    ainfo->ai_termid.at_port);
#else
	STRUCT_FSET(apinfo, ap_termid.at_port, ainfo->ai_termid.at_port);
#endif
	STRUCT_FSET(apinfo, ap_termid.at_type, ainfo->ai_termid.at_type);
	STRUCT_FSET(apinfo, ap_termid.at_addr[0], ainfo->ai_termid.at_addr[0]);
	STRUCT_FSET(apinfo, ap_termid.at_addr[1], ainfo->ai_termid.at_addr[1]);
	STRUCT_FSET(apinfo, ap_termid.at_addr[2], ainfo->ai_termid.at_addr[2]);
	STRUCT_FSET(apinfo, ap_termid.at_addr[3], ainfo->ai_termid.at_addr[3]);
	STRUCT_FSET(apinfo, ap_mask, ainfo->ai_mask);

	crfree(cr);

	if (copyout(STRUCT_BUF(apinfo), data, STRUCT_SIZE(apinfo)))
		return (EFAULT);

	return (0);
}
Exemplo n.º 7
0
/*
 * msgctl system call.
 *
 * gets q lock (via ipc_lookup), releases before return.
 * may call users of msg_lock
 */
static int
msgctl(int msgid, int cmd, void *arg)
{
    STRUCT_DECL(msqid_ds, ds);		/* SVR4 queue work area */
    kmsqid_t		*qp;		/* ptr to associated q */
    int			error;
    struct	cred		*cr;
    model_t	mdl = get_udatamodel();
    struct msqid_ds64	ds64;
    kmutex_t		*lock;
    proc_t			*pp = curproc;

    STRUCT_INIT(ds, mdl);
    cr = CRED();

    /*
     * Perform pre- or non-lookup actions (e.g. copyins, RMID).
     */
    switch (cmd) {
    case IPC_SET:
        if (copyin(arg, STRUCT_BUF(ds), STRUCT_SIZE(ds)))
            return (set_errno(EFAULT));
        break;

    case IPC_SET64:
        if (copyin(arg, &ds64, sizeof (struct msqid_ds64)))
            return (set_errno(EFAULT));
        break;

    case IPC_RMID:
        if (error = ipc_rmid(msq_svc, msgid, cr))
            return (set_errno(error));
        return (0);
    }

    /*
     * get msqid_ds for this msgid
     */
    if ((lock = ipc_lookup(msq_svc, msgid, (kipc_perm_t **)&qp)) == NULL)
        return (set_errno(EINVAL));

    switch (cmd) {
    case IPC_SET:
        if (STRUCT_FGET(ds, msg_qbytes) > qp->msg_qbytes &&
                secpolicy_ipc_config(cr) != 0) {
            mutex_exit(lock);
            return (set_errno(EPERM));
        }
        if (error = ipcperm_set(msq_svc, cr, &qp->msg_perm,
                                &STRUCT_BUF(ds)->msg_perm, mdl)) {
            mutex_exit(lock);
            return (set_errno(error));
        }
        qp->msg_qbytes = STRUCT_FGET(ds, msg_qbytes);
        qp->msg_ctime = gethrestime_sec();
        break;

    case IPC_STAT:
        if (error = ipcperm_access(&qp->msg_perm, MSG_R, cr)) {
            mutex_exit(lock);
            return (set_errno(error));
        }

        if (qp->msg_rcv_cnt)
            qp->msg_perm.ipc_mode |= MSG_RWAIT;
        if (qp->msg_snd_cnt)
            qp->msg_perm.ipc_mode |= MSG_WWAIT;
        ipcperm_stat(&STRUCT_BUF(ds)->msg_perm, &qp->msg_perm, mdl);
        qp->msg_perm.ipc_mode &= ~(MSG_RWAIT|MSG_WWAIT);
        STRUCT_FSETP(ds, msg_first, NULL); 	/* kernel addr */
        STRUCT_FSETP(ds, msg_last, NULL);
        STRUCT_FSET(ds, msg_cbytes, qp->msg_cbytes);
        STRUCT_FSET(ds, msg_qnum, qp->msg_qnum);
        STRUCT_FSET(ds, msg_qbytes, qp->msg_qbytes);
        STRUCT_FSET(ds, msg_lspid, qp->msg_lspid);
        STRUCT_FSET(ds, msg_lrpid, qp->msg_lrpid);
        STRUCT_FSET(ds, msg_stime, qp->msg_stime);
        STRUCT_FSET(ds, msg_rtime, qp->msg_rtime);
        STRUCT_FSET(ds, msg_ctime, qp->msg_ctime);
        break;

    case IPC_SET64:
        mutex_enter(&pp->p_lock);
        if ((ds64.msgx_qbytes > qp->msg_qbytes) &&
                secpolicy_ipc_config(cr) != 0 &&
                rctl_test(rc_process_msgmnb, pp->p_rctls, pp,
                          ds64.msgx_qbytes, RCA_SAFE) & RCT_DENY) {
            mutex_exit(&pp->p_lock);
            mutex_exit(lock);
            return (set_errno(EPERM));
        }
        mutex_exit(&pp->p_lock);
        if (error = ipcperm_set64(msq_svc, cr, &qp->msg_perm,
                                  &ds64.msgx_perm)) {
            mutex_exit(lock);
            return (set_errno(error));
        }
        qp->msg_qbytes = ds64.msgx_qbytes;
        qp->msg_ctime = gethrestime_sec();
        break;

    case IPC_STAT64:
        if (qp->msg_rcv_cnt)
            qp->msg_perm.ipc_mode |= MSG_RWAIT;
        if (qp->msg_snd_cnt)
            qp->msg_perm.ipc_mode |= MSG_WWAIT;
        ipcperm_stat64(&ds64.msgx_perm, &qp->msg_perm);
        qp->msg_perm.ipc_mode &= ~(MSG_RWAIT|MSG_WWAIT);
        ds64.msgx_cbytes = qp->msg_cbytes;
        ds64.msgx_qnum = qp->msg_qnum;
        ds64.msgx_qbytes = qp->msg_qbytes;
        ds64.msgx_lspid = qp->msg_lspid;
        ds64.msgx_lrpid = qp->msg_lrpid;
        ds64.msgx_stime = qp->msg_stime;
        ds64.msgx_rtime = qp->msg_rtime;
        ds64.msgx_ctime = qp->msg_ctime;
        break;

    default:
        mutex_exit(lock);
        return (set_errno(EINVAL));
    }

    mutex_exit(lock);

    /*
     * Do copyout last (after releasing mutex).
     */
    switch (cmd) {
    case IPC_STAT:
        if (copyout(STRUCT_BUF(ds), arg, STRUCT_SIZE(ds)))
            return (set_errno(EFAULT));
        break;

    case IPC_STAT64:
        if (copyout(&ds64, arg, sizeof (struct msqid_ds64)))
            return (set_errno(EFAULT));
        break;
    }

    return (0);
}
Exemplo n.º 8
0
/*
 * semctl - Semctl system call.
 */
static int
semctl(int semid, uint_t semnum, int cmd, uintptr_t arg)
{
    ksemid_t		*sp;	/* ptr to semaphore header */
    struct sem		*p;	/* ptr to semaphore */
    unsigned int		i;	/* loop control */
    ushort_t		*vals, *vp;
    size_t			vsize = 0;
    int			error = 0;
    int			retval = 0;
    struct cred		*cr;
    kmutex_t		*lock;
    model_t			mdl = get_udatamodel();
    STRUCT_DECL(semid_ds, sid);
    struct semid_ds64	ds64;

    STRUCT_INIT(sid, mdl);
    cr = CRED();

    /*
     * Perform pre- or non-lookup actions (e.g. copyins, RMID).
     */
    switch (cmd) {
    case IPC_SET:
        if (copyin((void *)arg, STRUCT_BUF(sid), STRUCT_SIZE(sid)))
            return (set_errno(EFAULT));
        break;

    case IPC_SET64:
        if (copyin((void *)arg, &ds64, sizeof (struct semid_ds64)))
            return (set_errno(EFAULT));
        break;

    case SETALL:
        if ((lock = ipc_lookup(sem_svc, semid,
                               (kipc_perm_t **)&sp)) == NULL)
            return (set_errno(EINVAL));
        vsize = sp->sem_nsems * sizeof (*vals);
        mutex_exit(lock);

        /* allocate space to hold all semaphore values */
        vals = kmem_alloc(vsize, KM_SLEEP);

        if (copyin((void *)arg, vals, vsize)) {
            kmem_free(vals, vsize);
            return (set_errno(EFAULT));
        }
        break;

    case IPC_RMID:
        if (error = ipc_rmid(sem_svc, semid, cr))
            return (set_errno(error));
        return (0);
    }

    if ((lock = ipc_lookup(sem_svc, semid, (kipc_perm_t **)&sp)) == NULL) {
        if (vsize != 0)
            kmem_free(vals, vsize);
        return (set_errno(EINVAL));
    }
    switch (cmd) {
    /* Set ownership and permissions. */
    case IPC_SET:

        if (error = ipcperm_set(sem_svc, cr, &sp->sem_perm,
                                &STRUCT_BUF(sid)->sem_perm, mdl)) {
            mutex_exit(lock);
            return (set_errno(error));
        }
        sp->sem_ctime = gethrestime_sec();
        mutex_exit(lock);
        return (0);

    /* Get semaphore data structure. */
    case IPC_STAT:

        if (error = ipcperm_access(&sp->sem_perm, SEM_R, cr)) {
            mutex_exit(lock);
            return (set_errno(error));
        }

        ipcperm_stat(&STRUCT_BUF(sid)->sem_perm, &sp->sem_perm, mdl);
        STRUCT_FSETP(sid, sem_base, NULL);	/* kernel addr */
        STRUCT_FSET(sid, sem_nsems, sp->sem_nsems);
        STRUCT_FSET(sid, sem_otime, sp->sem_otime);
        STRUCT_FSET(sid, sem_ctime, sp->sem_ctime);
        STRUCT_FSET(sid, sem_binary, sp->sem_binary);
        mutex_exit(lock);

        if (copyout(STRUCT_BUF(sid), (void *)arg, STRUCT_SIZE(sid)))
            return (set_errno(EFAULT));
        return (0);

    case IPC_SET64:

        if (error = ipcperm_set64(sem_svc, cr, &sp->sem_perm,
                                  &ds64.semx_perm)) {
            mutex_exit(lock);
            return (set_errno(error));
        }
        sp->sem_ctime = gethrestime_sec();
        mutex_exit(lock);
        return (0);

    case IPC_STAT64:

        ipcperm_stat64(&ds64.semx_perm, &sp->sem_perm);
        ds64.semx_nsems = sp->sem_nsems;
        ds64.semx_otime = sp->sem_otime;
        ds64.semx_ctime = sp->sem_ctime;

        mutex_exit(lock);
        if (copyout(&ds64, (void *)arg, sizeof (struct semid_ds64)))
            return (set_errno(EFAULT));

        return (0);

    /* Get # of processes sleeping for greater semval. */
    case GETNCNT:
        if (error = ipcperm_access(&sp->sem_perm, SEM_R, cr)) {
            mutex_exit(lock);
            return (set_errno(error));
        }
        if (semnum >= sp->sem_nsems) {
            mutex_exit(lock);
            return (set_errno(EINVAL));
        }
        retval = sp->sem_base[semnum].semncnt;
        mutex_exit(lock);
        return (retval);

    /* Get pid of last process to operate on semaphore. */
    case GETPID:
        if (error = ipcperm_access(&sp->sem_perm, SEM_R, cr)) {
            mutex_exit(lock);
            return (set_errno(error));
        }
        if (semnum >= sp->sem_nsems) {
            mutex_exit(lock);
            return (set_errno(EINVAL));
        }
        retval = sp->sem_base[semnum].sempid;
        mutex_exit(lock);
        return (retval);

    /* Get semval of one semaphore. */
    case GETVAL:
        if (error = ipcperm_access(&sp->sem_perm, SEM_R, cr)) {
            mutex_exit(lock);
            return (set_errno(error));
        }
        if (semnum >= sp->sem_nsems) {
            mutex_exit(lock);
            return (set_errno(EINVAL));
        }
        retval = sp->sem_base[semnum].semval;
        mutex_exit(lock);
        return (retval);

    /* Get all semvals in set. */
    case GETALL:
        if (error = ipcperm_access(&sp->sem_perm, SEM_R, cr)) {
            mutex_exit(lock);
            return (set_errno(error));
        }

        /* allocate space to hold all semaphore values */
        vsize = sp->sem_nsems * sizeof (*vals);
        vals = vp = kmem_alloc(vsize, KM_SLEEP);

        for (i = sp->sem_nsems, p = sp->sem_base; i--; p++, vp++)
            bcopy(&p->semval, vp, sizeof (p->semval));

        mutex_exit(lock);

        if (copyout((void *)vals, (void *)arg, vsize)) {
            kmem_free(vals, vsize);
            return (set_errno(EFAULT));
        }

        kmem_free(vals, vsize);
        return (0);

    /* Get # of processes sleeping for semval to become zero. */
    case GETZCNT:
        if (error = ipcperm_access(&sp->sem_perm, SEM_R, cr)) {
            mutex_exit(lock);
            return (set_errno(error));
        }
        if (semnum >= sp->sem_nsems) {
            mutex_exit(lock);
            return (set_errno(EINVAL));
        }
        retval = sp->sem_base[semnum].semzcnt;
        mutex_exit(lock);
        return (retval);

    /* Set semval of one semaphore. */
    case SETVAL:
        if (error = ipcperm_access(&sp->sem_perm, SEM_A, cr)) {
            mutex_exit(lock);
            return (set_errno(error));
        }
        if (semnum >= sp->sem_nsems) {
            mutex_exit(lock);
            return (set_errno(EINVAL));
        }
        if ((uint_t)arg > USHRT_MAX) {
            mutex_exit(lock);
            return (set_errno(ERANGE));
        }
        p = &sp->sem_base[semnum];
        if ((p->semval = (ushort_t)arg) != 0) {
            if (p->semncnt) {
                cv_broadcast(&p->semncnt_cv);
            }
        } else if (p->semzcnt) {
            cv_broadcast(&p->semzcnt_cv);
        }
        p->sempid = curproc->p_pid;
        sem_undo_clear(sp, (ushort_t)semnum, (ushort_t)semnum);
        mutex_exit(lock);
        return (0);

    /* Set semvals of all semaphores in set. */
    case SETALL:
        /* Check if semaphore set has been deleted and reallocated. */
        if (sp->sem_nsems * sizeof (*vals) != vsize) {
            error = set_errno(EINVAL);
            goto seterr;
        }
        if (error = ipcperm_access(&sp->sem_perm, SEM_A, cr)) {
            error = set_errno(error);
            goto seterr;
        }
        sem_undo_clear(sp, 0, sp->sem_nsems - 1);
        for (i = 0, p = sp->sem_base; i < sp->sem_nsems;
                (p++)->sempid = curproc->p_pid) {
            if ((p->semval = vals[i++]) != 0) {
                if (p->semncnt) {
                    cv_broadcast(&p->semncnt_cv);
                }
            } else if (p->semzcnt) {
                cv_broadcast(&p->semzcnt_cv);
            }
        }
seterr:
        mutex_exit(lock);
        kmem_free(vals, vsize);
        return (error);

    default:
        mutex_exit(lock);
        return (set_errno(EINVAL));
    }

    /* NOTREACHED */
}
/*
 * Get the audit state information from the current process.
 * Return EFAULT if copyout fails.
 */
static int
getaudit_addr(caddr_t info_p, int len)
{
	STRUCT_DECL(auditinfo_addr, info);
	const auditinfo_addr_t	*ainfo;
	model_t	model;

	if (secpolicy_audit_getattr(CRED()) != 0)
		return (EPERM);

	model = get_udatamodel();
	STRUCT_INIT(info, model);

	if (len < STRUCT_SIZE(info))
		return (EOVERFLOW);

	ainfo = crgetauinfo(CRED());

	if (ainfo == NULL)
		return (EINVAL);

	STRUCT_FSET(info, ai_auid, ainfo->ai_auid);
	STRUCT_FSET(info, ai_mask, ainfo->ai_mask);
#ifdef _LP64
	if (model == DATAMODEL_ILP32) {
		dev32_t dev;
		/* convert internal 64 bit form to 32 bit version */
		if (cmpldev(&dev, ainfo->ai_termid.at_port) == 0) {
			return (EOVERFLOW);
		}
		STRUCT_FSET(info, ai_termid.at_port, dev);
	} else
		STRUCT_FSET(info, ai_termid.at_port, ainfo->ai_termid.at_port);
#else
	STRUCT_FSET(info, ai_termid.at_port, ainfo->ai_termid.at_port);
#endif
	STRUCT_FSET(info, ai_termid.at_type, ainfo->ai_termid.at_type);
	STRUCT_FSET(info, ai_termid.at_addr[0], ainfo->ai_termid.at_addr[0]);
	STRUCT_FSET(info, ai_termid.at_addr[1], ainfo->ai_termid.at_addr[1]);
	STRUCT_FSET(info, ai_termid.at_addr[2], ainfo->ai_termid.at_addr[2]);
	STRUCT_FSET(info, ai_termid.at_addr[3], ainfo->ai_termid.at_addr[3]);
	STRUCT_FSET(info, ai_asid, ainfo->ai_asid);

	if (copyout(STRUCT_BUF(info), info_p, STRUCT_SIZE(info)))
		return (EFAULT);

	return (0);
}