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 */); }
/* ARGSUSED */ int sys_getegid(struct lwp *l, const void *v, register_t *retval) { *retval = kauth_cred_getegid(l->l_cred); return (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; }
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; }
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); }
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; }
/* 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); }
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; }
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; }
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; }
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; }
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; }
/* * 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); }