int lookupname(char *dirname, enum uio_seg seg, vnode_t **dirvpp, vnode_t **compvpp) { struct nameidata nd; int error; error = 0; KASSERT(dirvpp == NULL); error = namei_simple_kernel(dirname, NSM_FOLLOW_NOEMULROOT, compvpp); return error; }
void emul_find_root(struct lwp *l, struct exec_package *epp) { struct vnode *vp; const char *emul_path; if (epp->ep_emul_root != NULL) /* We've already found it */ return; emul_path = epp->ep_esch->es_emul->e_path; if (emul_path == NULL) /* Emulation doesn't have a root */ return; if (namei_simple_kernel(emul_path, NSM_FOLLOW_NOEMULROOT, &vp) != 0) /* emulation root doesn't exist */ return; epp->ep_emul_root = vp; }
/* * Look for native NetBSD compatibility libraries, usually interp-ABI. * It returns 0 if it changed the interpreter, otherwise it returns * the error from namei(). Callers should not try any more processing * if this returns 0, and probably should just ignore the return value. */ int compat_elf_check_interp(struct exec_package *epp, char *interp, const char *interp_suffix) { int error = 0; /* * Don't look for something else, if someone has already found and * setup the ep_interp already. */ if (interp && epp->ep_interp == NULL) { /* * If the path is exactly "/usr/libexec/ld.elf_so", first * try to see if "/usr/libexec/ld.elf_so-<abi>" exists * and if so, use that instead. */ if (strcmp(interp, "/usr/libexec/ld.elf_so") == 0 || strcmp(interp, "/libexec/ld.elf_so") == 0) { struct vnode *vp; char *path; path = PNBUF_GET(); snprintf(path, MAXPATHLEN, "%s-%s", interp, interp_suffix); error = namei_simple_kernel(path, NSM_FOLLOW_NOEMULROOT, &vp); /* * If that worked, replace interpreter in case we * actually need to load it. */ if (error == 0) { epp->ep_interp = vp; snprintf(interp, MAXPATHLEN, "%s", path); } PNBUF_PUT(path); } } return error; }
/*ARGSUSED*/ int coda_mount(struct mount *vfsp, /* Allocated and initialized by mount(2) */ const char *path, /* path covered: ignored by the fs-layer */ void *data, /* Need to define a data type for this in netbsd? */ size_t *data_len) { struct lwp *l = curlwp; struct vnode *dvp; struct cnode *cp; dev_t dev; struct coda_mntinfo *mi; struct vnode *rtvp; const struct cdevsw *cdev; CodaFid rootfid = INVAL_FID; CodaFid ctlfid = CTL_FID; int error; if (data == NULL) return EINVAL; if (vfsp->mnt_flag & MNT_GETARGS) return EINVAL; ENTRY; coda_vfsopstats_init(); coda_vnodeopstats_init(); MARK_ENTRY(CODA_MOUNT_STATS); if (CODA_MOUNTED(vfsp)) { MARK_INT_FAIL(CODA_MOUNT_STATS); return(EBUSY); } /* Validate mount device. Similar to getmdev(). */ /* * XXX: coda passes the mount device as the entire mount args, * All other fs pass a structure contining a pointer. * In order to get sys_mount() to do the copyin() we've set a * fixed default size for the filename buffer. */ /* Ensure that namei() doesn't run off the filename buffer */ ((char *)data)[*data_len - 1] = 0; error = namei_simple_kernel((char *)data, NSM_FOLLOW_NOEMULROOT, &dvp); if (error) { MARK_INT_FAIL(CODA_MOUNT_STATS); return (error); } if (dvp->v_type != VCHR) { MARK_INT_FAIL(CODA_MOUNT_STATS); vrele(dvp); return(ENXIO); } dev = dvp->v_rdev; vrele(dvp); cdev = cdevsw_lookup(dev); if (cdev == NULL) { MARK_INT_FAIL(CODA_MOUNT_STATS); return(ENXIO); } /* * See if the device table matches our expectations. */ if (cdev != &vcoda_cdevsw) { MARK_INT_FAIL(CODA_MOUNT_STATS); return(ENXIO); } if (minor(dev) >= NVCODA) { MARK_INT_FAIL(CODA_MOUNT_STATS); return(ENXIO); } /* * Initialize the mount record and link it to the vfs struct */ mi = &coda_mnttbl[minor(dev)]; if (!VC_OPEN(&mi->mi_vcomm)) { MARK_INT_FAIL(CODA_MOUNT_STATS); return(ENODEV); } /* No initialization (here) of mi_vcomm! */ vfsp->mnt_data = mi; vfsp->mnt_stat.f_fsidx.__fsid_val[0] = 0; vfsp->mnt_stat.f_fsidx.__fsid_val[1] = makefstype(MOUNT_CODA); vfsp->mnt_stat.f_fsid = vfsp->mnt_stat.f_fsidx.__fsid_val[0]; vfsp->mnt_stat.f_namemax = CODA_MAXNAMLEN; mi->mi_vfsp = vfsp; /* * Make a root vnode to placate the Vnode interface, but don't * actually make the CODA_ROOT call to venus until the first call * to coda_root in case a server is down while venus is starting. */ cp = make_coda_node(&rootfid, vfsp, VDIR); rtvp = CTOV(cp); rtvp->v_vflag |= VV_ROOT; cp = make_coda_node(&ctlfid, vfsp, VCHR); coda_ctlvp = CTOV(cp); /* Add vfs and rootvp to chain of vfs hanging off mntinfo */ mi->mi_vfsp = vfsp; mi->mi_rootvp = rtvp; /* set filesystem block size */ vfsp->mnt_stat.f_bsize = 8192; /* XXX -JJK */ vfsp->mnt_stat.f_frsize = 8192; /* XXX -JJK */ /* error is currently guaranteed to be zero, but in case some code changes... */ CODADEBUG(1, myprintf(("coda_mount returned %d\n",error)););
/* * Dump core, into a file named "progname.core" or "core" (depending on the * value of shortcorename), unless the process was setuid/setgid. */ static int coredump(struct lwp *l, const char *pattern) { struct vnode *vp; struct proc *p; struct vmspace *vm; kauth_cred_t cred; struct pathbuf *pb; struct nameidata nd; struct vattr vattr; struct coredump_iostate io; struct plimit *lim; int error, error1; char *name, *lastslash; name = PNBUF_GET(); p = l->l_proc; vm = p->p_vmspace; mutex_enter(proc_lock); /* p_session */ mutex_enter(p->p_lock); /* * Refuse to core if the data + stack + user size is larger than * the core dump limit. XXX THIS IS WRONG, because of mapped * data. */ if (USPACE + ctob(vm->vm_dsize + vm->vm_ssize) >= p->p_rlimit[RLIMIT_CORE].rlim_cur) { error = EFBIG; /* better error code? */ mutex_exit(p->p_lock); mutex_exit(proc_lock); goto done; } /* * It may well not be curproc, so grab a reference to its current * credentials. */ kauth_cred_hold(p->p_cred); cred = p->p_cred; /* * Make sure the process has not set-id, to prevent data leaks, * unless it was specifically requested to allow set-id coredumps. */ if (p->p_flag & PK_SUGID) { if (!security_setidcore_dump) { error = EPERM; mutex_exit(p->p_lock); mutex_exit(proc_lock); goto done; } pattern = security_setidcore_path; } /* Lock, as p_limit and pl_corename might change. */ lim = p->p_limit; mutex_enter(&lim->pl_lock); if (pattern == NULL) { pattern = lim->pl_corename; } error = coredump_buildname(p, name, pattern, MAXPATHLEN); mutex_exit(&lim->pl_lock); if (error) { mutex_exit(p->p_lock); mutex_exit(proc_lock); goto done; } /* * On a simple filename, see if the filesystem allow us to write * core dumps there. */ lastslash = strrchr(name, '/'); if (!lastslash) { vp = p->p_cwdi->cwdi_cdir; if (vp->v_mount == NULL || (vp->v_mount->mnt_flag & MNT_NOCOREDUMP) != 0) error = EPERM; } mutex_exit(p->p_lock); mutex_exit(proc_lock); if (error) goto done; /* * On a complex filename, see if the filesystem allow us to write * core dumps there. * * XXX: We should have an API that avoids double lookups */ if (lastslash) { char c[2]; if (lastslash - name >= MAXPATHLEN - 2) { error = EPERM; goto done; } c[0] = lastslash[1]; c[1] = lastslash[2]; lastslash[1] = '.'; lastslash[2] = '\0'; error = namei_simple_kernel(name, NSM_FOLLOW_NOEMULROOT, &vp); if (error) goto done; if (vp->v_mount == NULL || (vp->v_mount->mnt_flag & MNT_NOCOREDUMP) != 0) error = EPERM; vrele(vp); if (error) goto done; lastslash[1] = c[0]; lastslash[2] = c[1]; } pb = pathbuf_create(name); if (pb == NULL) { error = ENOMEM; goto done; } NDINIT(&nd, LOOKUP, NOFOLLOW, pb); if ((error = vn_open(&nd, O_CREAT | O_NOFOLLOW | FWRITE, S_IRUSR | S_IWUSR)) != 0) { pathbuf_destroy(pb); goto done; } vp = nd.ni_vp; pathbuf_destroy(pb); /* * Don't dump to: * - non-regular files * - files with links * - files we don't own */ if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred) || vattr.va_nlink != 1 || vattr.va_uid != kauth_cred_geteuid(cred)) { error = EACCES; goto out; } vattr_null(&vattr); vattr.va_size = 0; if ((p->p_flag & PK_SUGID) && security_setidcore_dump) { vattr.va_uid = security_setidcore_owner; vattr.va_gid = security_setidcore_group; vattr.va_mode = security_setidcore_mode; } VOP_SETATTR(vp, &vattr, cred); p->p_acflag |= ACORE; io.io_lwp = l; io.io_vp = vp; io.io_cred = cred; io.io_offset = 0; /* Now dump the actual core file. */ error = (*p->p_execsw->es_coredump)(l, &io); out: VOP_UNLOCK(vp); error1 = vn_close(vp, FWRITE, cred); if (error == 0) error = error1; done: if (name != NULL) PNBUF_PUT(name); return error; }