Exemple #1
0
int
do_setresgid(struct lwp *l, gid_t r, gid_t e, gid_t sv, u_int flags)
{
	struct proc *p = l->l_proc;
	kauth_cred_t cred, ncred;

	ncred = kauth_cred_alloc();

	/* Get a write lock on the process credential. */
	proc_crmod_enter();
	cred = p->p_cred;

	/*
	 * check new value is one of the allowed existing values.
	 * otherwise, check if we have root privilege.
	 */
	if ((r != -1
	    && !((flags & ID_R_EQ_R) && r == kauth_cred_getgid(cred))
	    && !((flags & ID_R_EQ_E) && r == kauth_cred_getegid(cred))
	    && !((flags & ID_R_EQ_S) && r == kauth_cred_getsvgid(cred))) ||
	    (e != -1
	    && !((flags & ID_E_EQ_R) && e == kauth_cred_getgid(cred))
	    && !((flags & ID_E_EQ_E) && e == kauth_cred_getegid(cred))
	    && !((flags & ID_E_EQ_S) && e == kauth_cred_getsvgid(cred))) ||
	    (sv != -1
	    && !((flags & ID_S_EQ_R) && sv == kauth_cred_getgid(cred))
	    && !((flags & ID_S_EQ_E) && sv == kauth_cred_getegid(cred))
	    && !((flags & ID_S_EQ_S) && sv == kauth_cred_getsvgid(cred)))) {
		int error;

		error = kauth_authorize_process(cred, KAUTH_PROCESS_SETID,
		    p, NULL, NULL, NULL);
		if (error != 0) {
		 	proc_crmod_leave(cred, ncred, false);
			return error;
		}
	}

	/* If nothing has changed, short circuit the request */
	if ((r == -1 || r == kauth_cred_getgid(cred))
	    && (e == -1 || e == kauth_cred_getegid(cred))
	    && (sv == -1 || sv == kauth_cred_getsvgid(cred))) {
	 	proc_crmod_leave(cred, ncred, false);
		return 0;
	}

	kauth_cred_clone(cred, ncred);

	if (r != -1)
		kauth_cred_setgid(ncred, r);
	if (sv != -1)
		kauth_cred_setsvgid(ncred, sv);
	if (e != -1)
		kauth_cred_setegid(ncred, e);

	/* Broadcast our credentials to the process and other LWPs. */
 	proc_crmod_leave(ncred, cred, true);

	return 0;
}
static int
sysvipc_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie,
    void *arg0, void *arg1, void *arg2, void *arg3)
{
	mode_t mask;
	int ismember = 0;
	struct ipc_perm *perm;
	int mode;
	enum kauth_system_req req;

	req = (enum kauth_system_req)arg0;

	if (!(action == KAUTH_SYSTEM_SYSVIPC &&
	      req == KAUTH_REQ_SYSTEM_SYSVIPC_BYPASS))
		return KAUTH_RESULT_DEFER;

	perm = arg1;
	mode = (int)(uintptr_t)arg2;

	if (mode == IPC_M) {
		if (kauth_cred_geteuid(cred) == perm->uid ||
		    kauth_cred_geteuid(cred) == perm->cuid)
			return (KAUTH_RESULT_ALLOW);
		return (KAUTH_RESULT_DEFER); /* EPERM */
	}

	mask = 0;

	if (kauth_cred_geteuid(cred) == perm->uid ||
	    kauth_cred_geteuid(cred) == perm->cuid) {
		if (mode & IPC_R)
			mask |= S_IRUSR;
		if (mode & IPC_W)
			mask |= S_IWUSR;
		return ((perm->mode & mask) == mask ? KAUTH_RESULT_ALLOW : KAUTH_RESULT_DEFER /* EACCES */);
	}

	if (kauth_cred_getegid(cred) == perm->gid ||
	    (kauth_cred_ismember_gid(cred, perm->gid, &ismember) == 0 && ismember) ||
	    kauth_cred_getegid(cred) == perm->cgid ||
	    (kauth_cred_ismember_gid(cred, perm->cgid, &ismember) == 0 && ismember)) {
		if (mode & IPC_R)
			mask |= S_IRGRP;
		if (mode & IPC_W)
			mask |= S_IWGRP;
		return ((perm->mode & mask) == mask ? KAUTH_RESULT_ALLOW : KAUTH_RESULT_DEFER /* EACCES */);
	}

	if (mode & IPC_R)
		mask |= S_IROTH;
	if (mode & IPC_W)
		mask |= S_IWOTH;
	return ((perm->mode & mask) == mask ? KAUTH_RESULT_ALLOW : KAUTH_RESULT_DEFER /* EACCES */);
}
Exemple #3
0
/* ARGSUSED */
int
sys_getegid(struct lwp *l, const void *v, register_t *retval)
{

	*retval = kauth_cred_getegid(l->l_cred);
	return (0);
}
Exemple #4
0
/*
 * Perform chown operation on inode ip;
 * inode must be locked prior to call.
 */
static int
ptyfs_chown(struct vnode *vp, uid_t uid, gid_t gid, kauth_cred_t cred,
    struct lwp *l)
{
	struct ptyfsnode *ptyfs = VTOPTYFS(vp);
	int		error, ismember = 0;

	if (uid == (uid_t)VNOVAL)
		uid = ptyfs->ptyfs_uid;
	if (gid == (gid_t)VNOVAL)
		gid = ptyfs->ptyfs_gid;
	/*
	 * If we don't own the file, are trying to change the owner
	 * of the file, or are not a member of the target group,
	 * the caller's credentials must imply super-user privilege
	 * or the call fails.
	 */
	if ((kauth_cred_geteuid(cred) != ptyfs->ptyfs_uid || uid != ptyfs->ptyfs_uid ||
	    (gid != ptyfs->ptyfs_gid &&
	    !(kauth_cred_getegid(cred) == gid ||
	    (kauth_cred_ismember_gid(cred, gid, &ismember) == 0 && ismember)))) &&
	    ((error = kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
	    NULL)) != 0))
		return error;

	ptyfs->ptyfs_gid = gid;
	ptyfs->ptyfs_uid = uid;
	return 0;
}
Exemple #5
0
static int
tap_fops_stat(file_t *fp, struct stat *st)
{
	int error = 0;
	struct tap_softc *sc;
	int unit = fp->f_devunit;

	(void)memset(st, 0, sizeof(*st));

	KERNEL_LOCK(1, NULL);
	sc = device_lookup_private(&tap_cd, unit);
	if (sc == NULL) {
		error = ENXIO;
		goto out;
	}

	st->st_dev = makedev(cdevsw_lookup_major(&tap_cdevsw), unit);
	st->st_atimespec = sc->sc_atime;
	st->st_mtimespec = sc->sc_mtime;
	st->st_ctimespec = st->st_birthtimespec = sc->sc_btime;
	st->st_uid = kauth_cred_geteuid(fp->f_cred);
	st->st_gid = kauth_cred_getegid(fp->f_cred);
out:
	KERNEL_UNLOCK_ONE(NULL);
	return error;
}
Exemple #6
0
int
sys_setregid(struct lwp *l, const struct sys_setregid_args *uap, register_t *retval)
{
	/* {
		syscallarg(gid_t) rgid;
		syscallarg(gid_t) egid;
	} */
	kauth_cred_t cred = l->l_cred;
	gid_t rgid, egid, svgid;

	rgid = SCARG(uap, rgid);
	egid = SCARG(uap, egid);

	if (rgid == -1)
		rgid = kauth_cred_getgid(cred);
	if (egid == -1)
		egid = kauth_cred_getegid(cred);

	/* Saved gid is set to the new egid if the rgid changed */
	svgid = rgid == kauth_cred_getgid(cred) ? -1 : egid;

	return do_setresgid(l, rgid, egid, svgid,
			ID_R_EQ_R | ID_R_EQ_E |
			ID_E_EQ_R | ID_E_EQ_E | ID_E_EQ_S |
			ID_S_EQ_R | ID_S_EQ_E | ID_S_EQ_S);
}
Exemple #7
0
int
v7fs_symlink(void *v)
{
	struct vop_symlink_v3_args /* {
				   struct vnode		*a_dvp;
				   struct vnode		**a_vpp;
				   struct componentname	*a_cnp;
				   struct vattr		*a_vap;
				   char			*a_target;
				   } */ *a = v;
	struct v7fs_node *parent_node = a->a_dvp->v_data;
	struct v7fs_mount *v7fsmount = parent_node->v7fsmount;
	struct v7fs_self *fs = v7fsmount->core;
	struct vattr *va = a->a_vap;
	kauth_cred_t cr = a->a_cnp->cn_cred;
	struct componentname *cnp = a->a_cnp;
	struct v7fs_fileattr attr;
	v7fs_ino_t ino;
	const char *from = a->a_target;
	const char *to = cnp->cn_nameptr;
	size_t len = strlen(from) + 1;
	int error = 0;

	if (len > V7FS_BSIZE) { /* limited to 512byte pathname */
		DPRINTF("too long pathname.");
		return ENAMETOOLONG;
	}

	memset(&attr, 0, sizeof(attr));
	attr.uid = kauth_cred_geteuid(cr);
	attr.gid = kauth_cred_getegid(cr);
	attr.mode = va->va_mode | vtype_to_v7fs_mode(va->va_type);

	if ((error = v7fs_file_allocate
		(fs, &parent_node->inode, to, &attr, &ino))) {
		return error;
	}
	/* Sync dirent size change. */
	uvm_vnp_setsize(a->a_dvp, v7fs_inode_filesize(&parent_node->inode));

	/* Get myself vnode. */
	if ((error = v7fs_vget(v7fsmount->mountp, ino, a->a_vpp))) {
		DPRINTF("can't get vnode.\n");
	}

	struct v7fs_node *newnode = (*a->a_vpp)->v_data;
	struct v7fs_inode *p = &newnode->inode;
	v7fs_file_symlink(fs, p, from);
	uvm_vnp_setsize(*a->a_vpp, v7fs_inode_filesize(p));

	newnode->update_ctime = true;
	newnode->update_mtime = true;
	newnode->update_atime = true;

	if (error == 0)
		VOP_UNLOCK(*a->a_vpp);

	return error;
}
Exemple #8
0
/* ARGSUSED */
int
sys_getgid_with_egid(struct lwp *l, const void *v, register_t *retval)
{

	retval[0] = kauth_cred_getgid(l->l_cred);
	retval[1] = kauth_cred_getegid(l->l_cred);
	return (0);
}
Exemple #9
0
int
v7fs_create(void *v)
{
	struct vop_create_v3_args /* {
				  struct vnode *a_dvp;
				  struct vnode **a_vpp;
				  struct componentname *a_cnp;
				  struct vattr *a_vap;
				  } */ *a = v;
	struct v7fs_node *parent_node = a->a_dvp->v_data;
	struct v7fs_mount *v7fsmount = parent_node->v7fsmount;
	struct v7fs_self *fs = v7fsmount->core;
	struct mount *mp = v7fsmount->mountp;
	struct v7fs_fileattr attr;
	struct vattr *va = a->a_vap;
	kauth_cred_t cr = a->a_cnp->cn_cred;
	v7fs_ino_t ino;
	int error = 0;

	DPRINTF("%s parent#%d\n", a->a_cnp->cn_nameptr,
	    parent_node->inode.inode_number);
	KDASSERT((va->va_type == VREG) || (va->va_type == VSOCK));

	memset(&attr, 0, sizeof(attr));
	attr.uid = kauth_cred_geteuid(cr);
	attr.gid = kauth_cred_getegid(cr);
	attr.mode = va->va_mode | vtype_to_v7fs_mode (va->va_type);
	attr.device = 0;

	/* Allocate disk entry. and register its entry to parent directory. */
	if ((error = v7fs_file_allocate(fs, &parent_node->inode,
		    a->a_cnp->cn_nameptr, &attr, &ino))) {
		DPRINTF("v7fs_file_allocate failed.\n");
		return error;
	}
	/* Sync dirent size change. */
	uvm_vnp_setsize(a->a_dvp, v7fs_inode_filesize(&parent_node->inode));

	/* Get myself vnode. */
	*a->a_vpp = 0;
	if ((error = v7fs_vget(mp, ino, a->a_vpp))) {
		DPRINTF("v7fs_vget failed.\n");
		return error;
	}

	/* Scheduling update time. real update by v7fs_update */
	struct v7fs_node *newnode = (*a->a_vpp)->v_data;
	newnode->update_ctime = true;
	newnode->update_mtime = true;
	newnode->update_atime = true;
	DPRINTF("allocated %s->#%d\n", a->a_cnp->cn_nameptr, ino);

	if (error == 0)
		VOP_UNLOCK(*a->a_vpp);

	return error;
}
Exemple #10
0
int
v7fs_mknod(void *v)
{
	struct vop_mknod_v3_args /* {
				 struct vnode		*a_dvp;
				 struct vnode		**a_vpp;
				 struct componentname	*a_cnp;
				 struct vattr		*a_vap;
				 } */ *a = v;
	struct componentname *cnp = a->a_cnp;
	kauth_cred_t cr = cnp->cn_cred;
	struct vnode *dvp = a->a_dvp;
	struct vattr *va = a->a_vap;
	struct v7fs_node *parent_node = dvp->v_data;
	struct v7fs_mount *v7fsmount = parent_node->v7fsmount;
	struct v7fs_self *fs = v7fsmount->core;
	struct mount *mp = v7fsmount->mountp;
	struct v7fs_fileattr attr;

	v7fs_ino_t ino;
	int error = 0;

	DPRINTF("%s %06o %lx %d\n", cnp->cn_nameptr, va->va_mode,
	    (long)va->va_rdev, va->va_type);
	memset(&attr, 0, sizeof(attr));
	attr.uid = kauth_cred_geteuid(cr);
	attr.gid = kauth_cred_getegid(cr);
	attr.mode = va->va_mode | vtype_to_v7fs_mode(va->va_type);
	attr.device = va->va_rdev;

	if ((error = v7fs_file_allocate(fs, &parent_node->inode,
	    cnp->cn_nameptr, &attr, &ino)))
		return error;
	/* Sync dirent size change. */
	uvm_vnp_setsize(dvp, v7fs_inode_filesize(&parent_node->inode));

	if ((error = v7fs_vget(mp, ino, a->a_vpp))) {
		DPRINTF("can't get vnode.\n");
		return error;
	}
	struct v7fs_node *newnode = (*a->a_vpp)->v_data;
	newnode->update_ctime = true;
	newnode->update_mtime = true;
	newnode->update_atime = true;

	if (error == 0)
		VOP_UNLOCK(*a->a_vpp);

	return error;
}
Exemple #11
0
int
sysvbfs_create(void *arg)
{
	struct vop_create_args /* {
		struct vnode *a_dvp;
		struct vnode **a_vpp;
		struct componentname *a_cnp;
		struct vattr *a_vap;
	} */ *a = arg;
	struct sysvbfs_node *bnode = a->a_dvp->v_data;
	struct sysvbfs_mount *bmp = bnode->bmp;
	struct bfs *bfs = bmp->bfs;
	struct mount *mp = bmp->mountp;
	struct bfs_dirent *dirent;
	struct bfs_fileattr attr;
	struct vattr *va = a->a_vap;
	kauth_cred_t cr = a->a_cnp->cn_cred;
	int err = 0;

	DPRINTF("%s: %s\n", __func__, a->a_cnp->cn_nameptr);
	KDASSERT(a->a_vap->va_type == VREG);
	attr.uid = kauth_cred_geteuid(cr);
	attr.gid = kauth_cred_getegid(cr);
	attr.mode = va->va_mode;

	if ((err = bfs_file_create(bfs, a->a_cnp->cn_nameptr, 0, 0, &attr))
	    != 0) {
		DPRINTF("%s: bfs_file_create failed.\n", __func__);
		goto unlock_exit;
	}

	if (!bfs_dirent_lookup_by_name(bfs, a->a_cnp->cn_nameptr, &dirent))
		panic("no dirent for created file.");

	if ((err = sysvbfs_vget(mp, dirent->inode, a->a_vpp)) != 0) {
		DPRINTF("%s: sysvbfs_vget failed.\n", __func__);
		goto unlock_exit;
	}
	bnode = (*a->a_vpp)->v_data;
	bnode->update_ctime = true;
	bnode->update_mtime = true;
	bnode->update_atime = true;

 unlock_exit:
	/* unlock parent directory */
	vput(a->a_dvp);	/* locked at sysvbfs_lookup(); */

	return err;
}
static int
rnd_stat(struct file *fp, struct stat *st)
{
	struct rnd_ctx *const ctx = fp->f_data;

	/* XXX lock, if cprng allocated?  why? */
	memset(st, 0, sizeof(*st));
	st->st_dev = makedev(cdevsw_lookup_major(&rnd_cdevsw),
	    (ctx->rc_hard? RND_DEV_RANDOM : RND_DEV_URANDOM));
	/* XXX leave atimespect, mtimespec, ctimespec = 0? */

	st->st_uid = kauth_cred_geteuid(fp->f_cred);
	st->st_gid = kauth_cred_getegid(fp->f_cred);
	st->st_mode = S_IFCHR;
	return 0;
}
Exemple #13
0
struct mbuf *
compat_70_unp_addsockcred(struct lwp *l, struct mbuf *control)
{
	struct sockcred70 *sc;
	struct mbuf *m;
	void *p;

	m = sbcreatecontrol1(&p, SOCKCRED70SIZE(kauth_cred_ngroups(l->l_cred)),
		SCM_OCREDS, SOL_SOCKET, M_WAITOK);
	if (m == NULL)
		return control;

	sc = p;
	sc->sc_uid = kauth_cred_getuid(l->l_cred);
	sc->sc_euid = kauth_cred_geteuid(l->l_cred);
	sc->sc_gid = kauth_cred_getgid(l->l_cred);
	sc->sc_egid = kauth_cred_getegid(l->l_cred);
	sc->sc_ngroups = kauth_cred_ngroups(l->l_cred);

	for (int i = 0; i < sc->sc_ngroups; i++)
		sc->sc_groups[i] = kauth_cred_group(l->l_cred, i);

	return m_add(control, m);
}
/*
 * Copy arguments onto the stack in the normal way, but add some
 * extra information in case of dynamic binding.
 */
int
netbsd32_elf32_copyargs(struct lwp *l, struct exec_package *pack,
    struct ps_strings *arginfo, char **stackp, void *argp)
{
	size_t len;
	AuxInfo ai[ELF_AUX_ENTRIES], *a;
	struct elf_args *ap;
	int error;

	if ((error = netbsd32_copyargs(l, pack, arginfo, stackp, argp)) != 0)
		return error;

	a = ai;

	/*
	 * Push extra arguments on the stack needed by dynamically
	 * linked binaries
	 */
	if ((ap = (struct elf_args *)pack->ep_emul_arg)) {

		a->a_type = AT_PHDR;
		a->a_v = ap->arg_phaddr;
		a++;

		a->a_type = AT_PHENT;
		a->a_v = ap->arg_phentsize;
		a++;

		a->a_type = AT_PHNUM;
		a->a_v = ap->arg_phnum;
		a++;

		a->a_type = AT_PAGESZ;
		a->a_v = PAGE_SIZE;
		a++;

		a->a_type = AT_BASE;
		a->a_v = ap->arg_interp;
		a++;

		a->a_type = AT_FLAGS;
		a->a_v = 0;
		a++;

		a->a_type = AT_ENTRY;
		a->a_v = ap->arg_entry;
		a++;

		a->a_type = AT_EUID;
		a->a_v = kauth_cred_geteuid(l->l_cred);
		a++;

		a->a_type = AT_RUID;
		a->a_v = kauth_cred_getuid(l->l_cred);
		a++;

		a->a_type = AT_EGID;
		a->a_v = kauth_cred_getegid(l->l_cred);
		a++;

		a->a_type = AT_RGID;
		a->a_v = kauth_cred_getgid(l->l_cred);
		a++;

		exec_free_emul_arg(pack);
	}

	a->a_type = AT_NULL;
	a->a_v = 0;
	a++;

	len = (a - ai) * sizeof(AuxInfo);
	if ((error = copyout(ai, *stackp, len)) != 0)
		return error;
	*stackp += len;

	return 0;
}
int
ELFNAME2(linux,copyargs)(struct lwp *l, struct exec_package *pack,
	struct ps_strings *arginfo, char **stackp, void *argp)
{
	struct linux_extra_stack_data64 *esdp, esd;
	struct elf_args *ap;
	struct vattr *vap;
	Elf_Ehdr *eh;
	Elf_Phdr *ph;
	u_long phsize;
	Elf_Addr phdr = 0;
	int error;
	int i;

	if ((error = copyargs(l, pack, arginfo, stackp, argp)) != 0)
		return error;

	/*
	 * Push extra arguments on the stack needed by dynamically
	 * linked binaries and static binaries as well.
	 */
	memset(&esd, 0, sizeof(esd));
	esdp = (struct linux_extra_stack_data64 *)(*stackp);
	ap = (struct elf_args *)pack->ep_emul_arg;
	vap = pack->ep_vap;
	eh = (Elf_Ehdr *)pack->ep_hdr;

	/*
	 * We forgot this, so we need to reload it now. XXX keep track of it?
	 */
	if (ap == NULL) {
		phsize = eh->e_phnum * sizeof(Elf_Phdr);
		ph = (Elf_Phdr *)kmem_alloc(phsize, KM_SLEEP);
		error = exec_read_from(l, pack->ep_vp, eh->e_phoff, ph, phsize);
		if (error != 0) {
			for (i = 0; i < eh->e_phnum; i++) {
				if (ph[i].p_type == PT_PHDR) {
					phdr = ph[i].p_vaddr;
					break;
				}
			}
		}
		kmem_free(ph, phsize);
	}


	/*
	 * The exec_package doesn't have a proc pointer and it's not
	 * exactly trivial to add one since the credentials are
	 * changing. XXX Linux uses curlwp's credentials.
	 * Why can't we use them too?
	 */

	i = 0;
	esd.ai[i].a_type = LINUX_AT_HWCAP;
	esd.ai[i++].a_v = rcr4();

	esd.ai[i].a_type = AT_PAGESZ;
	esd.ai[i++].a_v = PAGE_SIZE;

	esd.ai[i].a_type = LINUX_AT_CLKTCK;
	esd.ai[i++].a_v = hz;

	esd.ai[i].a_type = AT_PHDR;
	esd.ai[i++].a_v = (ap ? ap->arg_phaddr: phdr);

	esd.ai[i].a_type = AT_PHENT;
	esd.ai[i++].a_v = (ap ? ap->arg_phentsize : eh->e_phentsize);

	esd.ai[i].a_type = AT_PHNUM;
	esd.ai[i++].a_v = (ap ? ap->arg_phnum : eh->e_phnum);

	esd.ai[i].a_type = AT_BASE;
	esd.ai[i++].a_v = (ap ? ap->arg_interp : 0);

	esd.ai[i].a_type = AT_FLAGS;
	esd.ai[i++].a_v = 0;

	esd.ai[i].a_type = AT_ENTRY;
	esd.ai[i++].a_v = (ap ? ap->arg_entry : eh->e_entry);

	esd.ai[i].a_type = LINUX_AT_EGID;
	esd.ai[i++].a_v = ((vap->va_mode & S_ISGID) ?
	    vap->va_gid : kauth_cred_getegid(l->l_cred));

	esd.ai[i].a_type = LINUX_AT_GID;
	esd.ai[i++].a_v = kauth_cred_getgid(l->l_cred);

	esd.ai[i].a_type = LINUX_AT_EUID;
	esd.ai[i++].a_v = ((vap->va_mode & S_ISUID) ? 
	    vap->va_uid : kauth_cred_geteuid(l->l_cred));

	esd.ai[i].a_type = LINUX_AT_UID;
	esd.ai[i++].a_v = kauth_cred_getuid(l->l_cred);

	esd.ai[i].a_type = LINUX_AT_SECURE;
	esd.ai[i++].a_v = 0;

	esd.ai[i].a_type = LINUX_AT_PLATFORM;
	esd.ai[i++].a_v = (Elf_Addr)&esdp->hw_platform[0];

	esd.ai[i].a_type = AT_NULL;
	esd.ai[i++].a_v = 0;

#ifdef DEBUG_LINUX
	if (i != LINUX_ELF_AUX_ENTRIES) {
		printf("linux_elf64_copyargs: %d Aux entries\n", i);
		return EINVAL;
	}
#endif
		
	strcpy(esd.hw_platform, LINUX_PLATFORM); 

	exec_free_emul_arg(pack);

	/*
	 * Copy out the ELF auxiliary table and hw platform name
	 */
	if ((error = copyout(&esd, esdp, sizeof(esd))) != 0)
		return error;
	*stackp += sizeof(esd);

	return 0;
}
Exemple #16
0
int
sys_semget(struct lwp *l, const struct sys_semget_args *uap, register_t *retval)
{
	/* {
		syscallarg(key_t) key;
		syscallarg(int) nsems;
		syscallarg(int) semflg;
	} */
	int semid, error = 0;
	int key = SCARG(uap, key);
	int nsems = SCARG(uap, nsems);
	int semflg = SCARG(uap, semflg);
	kauth_cred_t cred = l->l_cred;

	SEM_PRINTF(("semget(0x%x, %d, 0%o)\n", key, nsems, semflg));

	mutex_enter(&semlock);

	if (key != IPC_PRIVATE) {
		for (semid = 0; semid < seminfo.semmni; semid++) {
			if ((sema[semid].sem_perm.mode & SEM_ALLOC) &&
			    sema[semid].sem_perm._key == key)
				break;
		}
		if (semid < seminfo.semmni) {
			SEM_PRINTF(("found public key\n"));
			if ((error = ipcperm(cred, &sema[semid].sem_perm,
			    semflg & 0700)))
			    	goto out;
			if (nsems > 0 && sema[semid].sem_nsems < nsems) {
				SEM_PRINTF(("too small\n"));
				error = EINVAL;
				goto out;
			}
			if ((semflg & IPC_CREAT) && (semflg & IPC_EXCL)) {
				SEM_PRINTF(("not exclusive\n"));
				error = EEXIST;
				goto out;
			}
			goto found;
		}
	}

	SEM_PRINTF(("need to allocate the semid_ds\n"));
	if (key == IPC_PRIVATE || (semflg & IPC_CREAT)) {
		if (nsems <= 0 || nsems > seminfo.semmsl) {
			SEM_PRINTF(("nsems out of range (0<%d<=%d)\n", nsems,
			    seminfo.semmsl));
			error = EINVAL;
			goto out;
		}
		if (nsems > seminfo.semmns - semtot) {
			SEM_PRINTF(("not enough semaphores left "
			    "(need %d, got %d)\n",
			    nsems, seminfo.semmns - semtot));
			error = ENOSPC;
			goto out;
		}
		for (semid = 0; semid < seminfo.semmni; semid++) {
			if ((sema[semid].sem_perm.mode & SEM_ALLOC) == 0)
				break;
		}
		if (semid == seminfo.semmni) {
			SEM_PRINTF(("no more semid_ds's available\n"));
			error = ENOSPC;
			goto out;
		}
		SEM_PRINTF(("semid %d is available\n", semid));
		sema[semid].sem_perm._key = key;
		sema[semid].sem_perm.cuid = kauth_cred_geteuid(cred);
		sema[semid].sem_perm.uid = kauth_cred_geteuid(cred);
		sema[semid].sem_perm.cgid = kauth_cred_getegid(cred);
		sema[semid].sem_perm.gid = kauth_cred_getegid(cred);
		sema[semid].sem_perm.mode = (semflg & 0777) | SEM_ALLOC;
		sema[semid].sem_perm._seq =
		    (sema[semid].sem_perm._seq + 1) & 0x7fff;
		sema[semid].sem_nsems = nsems;
		sema[semid].sem_otime = 0;
		sema[semid].sem_ctime = time_second;
		sema[semid]._sem_base = &sem[semtot];
		semtot += nsems;
		memset(sema[semid]._sem_base, 0,
		    sizeof(sema[semid]._sem_base[0]) * nsems);
		SEM_PRINTF(("sembase = %p, next = %p\n", sema[semid]._sem_base,
		    &sem[semtot]));
	} else {
		SEM_PRINTF(("didn't find it and wasn't asked to create it\n"));
		error = ENOENT;
		goto out;
	}

 found:
	*retval = IXSEQ_TO_IPCID(semid, sema[semid].sem_perm);
 out:
	mutex_exit(&semlock);
	return (error);
}
/*
 * Copy arguments onto the stack in the normal way, but add some
 * extra information in case of dynamic binding.
 */
int
ELFNAME2(linux,copyargs)(struct lwp *l, struct exec_package *pack,
                         struct ps_strings *arginfo, char **stackp, void *argp)
{
    size_t len;
    AuxInfo ai[LINUX_ELF_AUX_ENTRIES], *a;
    struct elf_args *ap;
    int error;
    struct vattr *vap;

    if ((error = copyargs(l, pack, arginfo, stackp, argp)) != 0)
        return error;

    a = ai;

    /*
     * Push extra arguments used by glibc on the stack.
     */

    a->a_type = AT_PAGESZ;
    a->a_v = PAGE_SIZE;
    a++;

    if ((ap = (struct elf_args *)pack->ep_emul_arg)) {

        a->a_type = AT_PHDR;
        a->a_v = ap->arg_phaddr;
        a++;

        a->a_type = AT_PHENT;
        a->a_v = ap->arg_phentsize;
        a++;

        a->a_type = AT_PHNUM;
        a->a_v = ap->arg_phnum;
        a++;

        a->a_type = AT_BASE;
        a->a_v = ap->arg_interp;
        a++;

        a->a_type = AT_FLAGS;
        a->a_v = 0;
        a++;

        a->a_type = AT_ENTRY;
        a->a_v = ap->arg_entry;
        a++;

        exec_free_emul_arg(pack);
    }

    /* Linux-specific items */
    a->a_type = LINUX_AT_CLKTCK;
    a->a_v = hz;
    a++;

    vap = pack->ep_vap;

    a->a_type = LINUX_AT_UID;
    a->a_v = kauth_cred_getuid(l->l_cred);
    a++;

    a->a_type = LINUX_AT_EUID;
    if (vap->va_mode & S_ISUID)
        a->a_v = vap->va_uid;
    else
        a->a_v = kauth_cred_geteuid(l->l_cred);
    a++;

    a->a_type = LINUX_AT_GID;
    a->a_v = kauth_cred_getgid(l->l_cred);
    a++;

    a->a_type = LINUX_AT_EGID;
    if (vap->va_mode & S_ISGID)
        a->a_v = vap->va_gid;
    else
        a->a_v = kauth_cred_getegid(l->l_cred);
    a++;

    a->a_type = AT_NULL;
    a->a_v = 0;
    a++;

    len = (a - ai) * sizeof(AuxInfo);
    if ((error = copyout(ai, *stackp, len)) != 0)
        return error;
    *stackp += len;

    return 0;
}
int
svr4_32_copyargs(struct lwp *l, struct exec_package *pack, struct ps_strings *arginfo, char **stackp, void *argp)
{
	size_t len;
	AuxInfo ai[SVR4_32_AUX_ARGSIZ], *a, *platform=NULL, *exec=NULL;
	struct elf_args *ap;
	extern char machine_model[];
	int error;

	if ((error = netbsd32_copyargs(l, pack, arginfo, stackp, argp)) != 0)
		return error;

	a = ai;

	memset(ai, 0, sizeof(ai));

	/*
	 * Push extra arguments on the stack needed by dynamically
	 * linked binaries
	 */
	if ((ap = (struct elf_args *)pack->ep_emul_arg)) {
		struct proc *p = curproc; /* XXXXX */

		a->a_type = AT_SUN_PLATFORM;
		platform = a; /* Patch this later. */
		a++;

		a->a_type = AT_SUN_EXECNAME;
		exec = a; /* Patch this later. */
		a++;

		a->a_type = AT_PHDR;
		a->a_v = ap->arg_phaddr;
		a++;

		a->a_type = AT_PHENT;
		a->a_v = ap->arg_phentsize;
		a++;

		a->a_type = AT_PHNUM;
		a->a_v = ap->arg_phnum;
		a++;

		a->a_type = AT_ENTRY;
		a->a_v = ap->arg_entry;
		a++;

		a->a_type = AT_BASE;
		a->a_v = ap->arg_interp;
		a++;

		if (sun_flags) {
			a->a_type = AT_FLAGS;
			a->a_v = sun_flags;
			a++;
		}

		a->a_type = AT_PAGESZ;
		a->a_v = PAGE_SIZE;
		a++;

		a->a_type = AT_EUID;
		a->a_v = kauth_cred_geteuid(l->l_cred);
		a++;

		a->a_type = AT_RUID;
		a->a_v = kauth_cred_getuid(l->l_cred);
		a++;

		a->a_type = AT_EGID;
		a->a_v = kauth_cred_getegid(l->l_cred);
		a++;

		a->a_type = AT_RGID;
		a->a_v = kauth_cred_getgid(l->l_cred);
		a++;

		if (sun_hwcap) {
			a->a_type = AT_SUN_HWCAP;
			a->a_v = sun_hwcap;
			a++;
		}

		exec_free_emul_arg(pack);
	}

	a->a_type = AT_NULL;
	a->a_v = 0;
	a++;

	len = (a - ai) * sizeof(AuxInfo);

	if (platform) {
		char *ptr = (char *)a;
		const char *path = NULL;

		/* Copy out the platform name. */
		platform->a_v = (u_long)(*stackp) + len;
		/* XXXX extremely inefficient.... */
		strcpy(ptr, machine_model);
		ptr += strlen(machine_model) + 1;
		len += strlen(machine_model) + 1;

		if (exec) {
			path = pack->ep_resolvedname;

			/* Copy out the file we're executing. */
			exec->a_v = (u_long)(*stackp) + len;
			strcpy(ptr, path);
			len += strlen(ptr)+1;
		}

		/* Round to 32-bits */
		len = (len+7)&~0x7L;
	}
	if ((error = copyout(ai, *stackp, len)) != 0)
		return error;
	*stackp += len;

	return error;
}
Exemple #19
0
/*
 * This is the 08-June-1999 bypass routine.
 * See layer_vnops.c:layer_bypass for more details.
 */
int
umap_bypass(void *v)
{
	struct vop_generic_args /* {
		struct vnodeop_desc *a_desc;
		<other random data follows, presumably>
	} */ *ap = v;
	int (**our_vnodeop_p)(void *);
	kauth_cred_t *credpp = NULL, credp = 0;
	kauth_cred_t savecredp = 0, savecompcredp = 0;
	kauth_cred_t compcredp = 0;
	struct vnode **this_vp_p;
	int error;
	struct vnode *old_vps[VDESC_MAX_VPS], *vp0;
	struct vnode **vps_p[VDESC_MAX_VPS];
	struct vnode ***vppp;
	struct vnodeop_desc *descp = ap->a_desc;
	int reles, i, flags;
	struct componentname **compnamepp = 0;

#ifdef DIAGNOSTIC
	/*
	 * We require at least one vp.
	 */
	if (descp->vdesc_vp_offsets == NULL ||
	    descp->vdesc_vp_offsets[0] == VDESC_NO_OFFSET)
		panic("%s: no vp's in map.\n", __func__);
#endif

	vps_p[0] =
	    VOPARG_OFFSETTO(struct vnode**, descp->vdesc_vp_offsets[0], ap);
	vp0 = *vps_p[0];
	flags = MOUNTTOUMAPMOUNT(vp0->v_mount)->umapm_flags;
	our_vnodeop_p = vp0->v_op;

	if (flags & LAYERFS_MBYPASSDEBUG)
		printf("%s: %s\n", __func__, descp->vdesc_name);

	/*
	 * Map the vnodes going in.
	 * Later, we'll invoke the operation based on
	 * the first mapped vnode's operation vector.
	 */
	reles = descp->vdesc_flags;
	for (i = 0; i < VDESC_MAX_VPS; reles >>= 1, i++) {
		if (descp->vdesc_vp_offsets[i] == VDESC_NO_OFFSET)
			break;   /* bail out at end of list */
		vps_p[i] = this_vp_p =
		    VOPARG_OFFSETTO(struct vnode**, descp->vdesc_vp_offsets[i],
		    ap);
		/*
		 * We're not guaranteed that any but the first vnode
		 * are of our type.  Check for and don't map any
		 * that aren't.  (We must always map first vp or vclean fails.)
		 */
		if (i && (*this_vp_p == NULL ||
		    (*this_vp_p)->v_op != our_vnodeop_p)) {
			old_vps[i] = NULL;
		} else {
			old_vps[i] = *this_vp_p;
			*(vps_p[i]) = UMAPVPTOLOWERVP(*this_vp_p);
			/*
			 * XXX - Several operations have the side effect
			 * of vrele'ing their vp's.  We must account for
			 * that.  (This should go away in the future.)
			 */
			if (reles & VDESC_VP0_WILLRELE)
				vref(*this_vp_p);
		}

	}

	/*
	 * Fix the credentials.  (That's the purpose of this layer.)
	 */

	if (descp->vdesc_cred_offset != VDESC_NO_OFFSET) {

		credpp = VOPARG_OFFSETTO(kauth_cred_t*,
		    descp->vdesc_cred_offset, ap);

		/* Save old values */

		savecredp = *credpp;
		if (savecredp != NOCRED && savecredp != FSCRED)
			*credpp = kauth_cred_dup(savecredp);
		credp = *credpp;

		if ((flags & LAYERFS_MBYPASSDEBUG) &&
		    kauth_cred_geteuid(credp) != 0)
			printf("umap_bypass: user was %d, group %d\n",
			    kauth_cred_geteuid(credp), kauth_cred_getegid(credp));

		/* Map all ids in the credential structure. */

		umap_mapids(vp0->v_mount, credp);

		if ((flags & LAYERFS_MBYPASSDEBUG) &&
		    kauth_cred_geteuid(credp) != 0)
			printf("umap_bypass: user now %d, group %d\n",
			    kauth_cred_geteuid(credp), kauth_cred_getegid(credp));
	}
/*
 * Copy arguments onto the stack in the normal way, but add some
 * extra information in case of dynamic binding.
 */
int
linux32_elf32_copyargs(struct lwp *l, struct exec_package *pack,
    struct ps_strings *arginfo, char **stackp, void *argp)
{
	Aux32Info ai[LINUX32_ELF_AUX_ENTRIES], *a;
	uint32_t randbytes[4];
	struct elf_args *ap;
	struct vattr *vap;
	size_t len;
	int error;

	if ((error = netbsd32_copyargs(l, pack, arginfo, stackp, argp)) != 0)
		return error;

	a = ai;

	memset(ai, 0, sizeof(ai));

	/*
	 * Push extra arguments on the stack needed by dynamically
	 * linked binaries and static binaries as well.
	 */

	a->a_type = AT_PAGESZ;
	a->a_v = PAGE_SIZE;
	a++;

	if ((ap = (struct elf_args *)pack->ep_emul_arg)) {

		a->a_type = AT_PHDR;
		a->a_v = ap->arg_phaddr;
		a++;

		a->a_type = AT_PHENT;
		a->a_v = ap->arg_phentsize;
		a++;

		a->a_type = AT_PHNUM;
		a->a_v = ap->arg_phnum;
		a++;

		a->a_type = AT_BASE;
		a->a_v = ap->arg_interp;
		a++;

		a->a_type = AT_FLAGS;
		a->a_v = 0;
		a++;

		a->a_type = AT_ENTRY;
		a->a_v = ap->arg_entry;
		a++;

		exec_free_emul_arg(pack);
	}

	/* Linux-specific items */
	a->a_type = LINUX_AT_CLKTCK;
	a->a_v = hz;
	a++;

	vap = pack->ep_vap;

	a->a_type = LINUX_AT_UID;
	a->a_v = kauth_cred_getuid(l->l_cred);
	a++;

	a->a_type = LINUX_AT_EUID;
	a->a_v = ((vap->va_mode & S_ISUID) ?
	    vap->va_uid : kauth_cred_geteuid(l->l_cred));
	a++;

	a->a_type = LINUX_AT_GID;
	a->a_v = kauth_cred_getgid(l->l_cred);
	a++;

	a->a_type = LINUX_AT_EGID;
	a->a_v = ((vap->va_mode & S_ISGID) ?
	    vap->va_gid : kauth_cred_getegid(l->l_cred));
	a++;

	a->a_type = LINUX_AT_SECURE;
	a->a_v = 0;
	a++;

	a->a_type = LINUX_AT_RANDOM;
	a->a_v = NETBSD32PTR32I(*stackp);
	a++;

#if 0
	/* XXX: increase LINUX32_ELF_AUX_ENTRIES if we enable those things */

	a->a_type = LINUX_AT_SYSINFO;
	a->a_v = NETBSD32PTR32I(&esdp->kernel_vsyscall[0]);
	a++;

	a->a_type = LINUX_AT_SYSINFO_EHDR;
	a->a_v = NETBSD32PTR32I(&esdp->elfhdr);
	a++;

	a->a_type = LINUX_AT_HWCAP;
	a->a_v = LINUX32_CPUCAP;
	a++;

	a->a_type = LINUX_AT_PLATFORM;
	a->a_v = NETBSD32PTR32I(&esdp->hw_platform[0]);
	a++;
#endif

	a->a_type = AT_NULL;
	a->a_v = 0;
	a++;

	randbytes[0] = cprng_strong32();
	randbytes[1] = cprng_strong32();
	randbytes[2] = cprng_strong32();
	randbytes[3] = cprng_strong32();

	len = sizeof(randbytes);
	if ((error = copyout(randbytes, *stackp, len)) != 0)
		return error;
	*stackp += len;

#if 0
	memcpy(esd.kernel_vsyscall, linux32_kernel_vsyscall,
	    sizeof(linux32_kernel_vsyscall));

	memcpy(&esd.elfhdr, eh, sizeof(*eh));

	strcpy(esd.hw_platform, LINUX32_PLATFORM);
	
	/*
	 * Copy out the ELF auxiliary table and hw platform name
	 */
	if ((error = copyout(&esd, esdp, sizeof(esd))) != 0)
		return error;
	*stackp += sizeof(esd);
#endif

	len = (a - ai) * sizeof(Aux32Info);
	KASSERT(len <= LINUX32_ELF_AUX_ENTRIES * sizeof(Aux32Info));
	if ((error = copyout(ai, *stackp, len)) != 0)
		return error;
	*stackp += len;

	return 0;
}
int
sys_msgget(struct lwp *l, const struct sys_msgget_args *uap, register_t *retval)
{
	/* {
		syscallarg(key_t) key;
		syscallarg(int) msgflg;
	} */
	int msqid, error = 0;
	int key = SCARG(uap, key);
	int msgflg = SCARG(uap, msgflg);
	kauth_cred_t cred = l->l_cred;
	struct msqid_ds *msqptr = NULL;
	kmsq_t *msq;

	mutex_enter(&msgmutex);

	MSG_PRINTF(("msgget(0x%x, 0%o)\n", key, msgflg));

	if (key != IPC_PRIVATE) {
		for (msqid = 0; msqid < msginfo.msgmni; msqid++) {
			msq = &msqs[msqid];
			msqptr = &msq->msq_u;
			if (msqptr->msg_qbytes != 0 &&
			    msqptr->msg_perm._key == key)
				break;
		}
		if (msqid < msginfo.msgmni) {
			MSG_PRINTF(("found public key\n"));
			if ((msgflg & IPC_CREAT) && (msgflg & IPC_EXCL)) {
				MSG_PRINTF(("not exclusive\n"));
				error = EEXIST;
				goto unlock;
			}
			if ((error = ipcperm(cred, &msqptr->msg_perm,
			    msgflg & 0700 ))) {
				MSG_PRINTF(("requester doesn't have 0%o access\n",
				    msgflg & 0700));
				goto unlock;
			}
			goto found;
		}
	}

	MSG_PRINTF(("need to allocate the msqid_ds\n"));
	if (key == IPC_PRIVATE || (msgflg & IPC_CREAT)) {
		for (msqid = 0; msqid < msginfo.msgmni; msqid++) {
			/*
			 * Look for an unallocated and unlocked msqid_ds.
			 * msqid_ds's can be locked by msgsnd or msgrcv while
			 * they are copying the message in/out.  We can't
			 * re-use the entry until they release it.
			 */
			msq = &msqs[msqid];
			msqptr = &msq->msq_u;
			if (msqptr->msg_qbytes == 0 &&
			    (msqptr->msg_perm.mode & MSG_LOCKED) == 0)
				break;
		}
		if (msqid == msginfo.msgmni) {
			MSG_PRINTF(("no more msqid_ds's available\n"));
			error = ENOSPC;
			goto unlock;
		}
		MSG_PRINTF(("msqid %d is available\n", msqid));
		msqptr->msg_perm._key = key;
		msqptr->msg_perm.cuid = kauth_cred_geteuid(cred);
		msqptr->msg_perm.uid = kauth_cred_geteuid(cred);
		msqptr->msg_perm.cgid = kauth_cred_getegid(cred);
		msqptr->msg_perm.gid = kauth_cred_getegid(cred);
		msqptr->msg_perm.mode = (msgflg & 0777);
		/* Make sure that the returned msqid is unique */
		msqptr->msg_perm._seq++;
		msqptr->_msg_first = NULL;
		msqptr->_msg_last = NULL;
		msqptr->_msg_cbytes = 0;
		msqptr->msg_qnum = 0;
		msqptr->msg_qbytes = msginfo.msgmnb;
		msqptr->msg_lspid = 0;
		msqptr->msg_lrpid = 0;
		msqptr->msg_stime = 0;
		msqptr->msg_rtime = 0;
		msqptr->msg_ctime = time_second;
	} else {
		MSG_PRINTF(("didn't find it and wasn't asked to create it\n"));
		error = ENOENT;
		goto unlock;
	}

found:
	/* Construct the unique msqid */
	*retval = IXSEQ_TO_IPCID(msqid, msqptr->msg_perm);

unlock:
	mutex_exit(&msgmutex);
	return (error);
}