static int strategy(void *devdata, int rw, daddr32_t blk, size_t size, void *buf, size_t *rsize) { struct of_dev *dev = devdata; u_quad_t pos; int n; if (rw != F_READ) return EPERM; if (dev->type != OFDEV_DISK) panic("strategy"); DNPRINTF(BOOT_D_OFDEV, "strategy: block %lx, partition offset %lx, " "blksz %lx\n", (long)blk, (long)dev->partoff, (long)dev->bsize); DNPRINTF(BOOT_D_OFDEV, "strategy: seek position should be: %lx\n", (long)((blk + dev->partoff) * dev->bsize)); pos = (u_quad_t)(blk + dev->partoff) * dev->bsize; for (;;) { DNPRINTF(BOOT_D_OFDEV, "strategy: seeking to %lx\n", (long)pos); if (OF_seek(dev->handle, pos) < 0) break; DNPRINTF(BOOT_D_OFDEV, "strategy: reading %lx at %p\n", (long)size, buf); n = OF_read(dev->handle, buf, size); if (n == -2) continue; if (n < 0) break; *rsize = n; return 0; } return EIO; }
int load_disklabel(struct of_dev *ofdev, struct disklabel *label) { char buf[DEV_BSIZE]; size_t read; int error = 0; char *errmsg = NULL; /* First try to find a disklabel without MBR partitions */ DNPRINTF(BOOT_D_OFDEV, "load_disklabel: trying to read disklabel\n"); if (strategy(ofdev, F_READ, LABELSECTOR, DEV_BSIZE, buf, &read) != 0 || read != DEV_BSIZE || (errmsg = getdisklabel(buf, label))) { #ifdef BOOT_DEBUG if (errmsg) DNPRINTF(BOOT_D_OFDEV, "load_disklabel: getdisklabel says %s\n", errmsg); #endif /* Else try MBR partitions */ errmsg = search_label(ofdev, LABELSECTOR, buf, label, 0); if (errmsg) { printf("load_disklabel: search_label says %s\n", errmsg); error = ERDLAB; } } return (error); }
int spec_open_clone(struct vop_open_args *ap) { struct vnode *cvp, *vp = ap->a_vp; struct cloneinfo *cip; int error, i; DNPRINTF("cloning vnode\n"); if (minor(vp->v_rdev) >= (1 << CLONE_SHIFT)) return (ENXIO); for (i = 1; i < sizeof(vp->v_specbitmap) * NBBY; i++) if (isclr(vp->v_specbitmap, i)) { setbit(vp->v_specbitmap, i); break; } if (i == sizeof(vp->v_specbitmap) * NBBY) return (EBUSY); /* too many open instances */ error = cdevvp(makedev(major(vp->v_rdev), (i << CLONE_SHIFT) | minor(vp->v_rdev)), &cvp); if (error) { clrbit(vp->v_specbitmap, i); return (error); /* out of vnodes */ } VOP_UNLOCK(vp, 0, ap->a_p); error = cdevsw[major(vp->v_rdev)].d_open(cvp->v_rdev, ap->a_mode, S_IFCHR, ap->a_p); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, ap->a_p); if (error) { vput(cvp); clrbit(vp->v_specbitmap, i); return (error); /* device open failed */ } cvp->v_flag |= VCLONE; cip = malloc(sizeof(struct cloneinfo), M_TEMP, M_WAITOK); cip->ci_data = vp->v_data; cip->ci_vp = cvp; cvp->v_specparent = vp; vp->v_flag |= VCLONED; vp->v_data = cip; DNPRINTF("clone of vnode %p is vnode %p\n", vp, cvp); return (0); /* device cloned */ }
/* * Find a valid disklabel. */ static char * search_label(struct of_dev *devp, u_long off, char *buf, struct disklabel *lp, u_long off0) { size_t read; struct mbr_partition *p; int i; u_long poff; static int recursion; struct disklabel *dlp; struct sun_disklabel *slp; int error; /* minimal requirements for archetypal disk label */ if (lp->d_secperunit == 0) lp->d_secperunit = 0x1fffffff; lp->d_npartitions = MAXPARTITIONS; if (lp->d_partitions[0].p_size == 0) lp->d_partitions[0].p_size = 0x1fffffff; lp->d_partitions[0].p_offset = 0; if (strategy(devp, F_READ, off, DEV_BSIZE, buf, &read) || read != DEV_BSIZE) return ("Cannot read label"); /* Check for a disk label. */ dlp = (struct disklabel *) (buf + LABELOFFSET); if (dlp->d_magic == DISKMAGIC) { if (dkcksum(dlp)) return ("corrupt disk label"); *lp = *dlp; DNPRINTF(BOOT_D_OFDEV, "search_label: found disk label\n"); return (NULL); } /* Check for a Sun disk label (for PROM compatibility). */ slp = (struct sun_disklabel *)buf; if (slp->sl_magic == SUN_DKMAGIC) { if (disklabel_sun_to_bsd(slp, lp) != 0) return ("corrupt disk label"); DNPRINTF(BOOT_D_OFDEV, "search_label: found disk label\n"); return (NULL); } bzero(buf, sizeof(buf)); return ("no disk label"); }
int vndclose(dev_t dev, int flags, int mode, struct proc *p) { int unit = DISKUNIT(dev); struct vnd_softc *sc; int part; DNPRINTF(VDB_FOLLOW, "vndclose(%x, %x, %x, %p)\n", dev, flags, mode, p); if (unit >= numvnd) return (ENXIO); sc = &vnd_softc[unit]; disk_lock_nointr(&sc->sc_dk); part = DISKPART(dev); disk_closepart(&sc->sc_dk, part, mode); #if 0 if (sc->sc_dk.dk_openmask == 0) sc->sc_flags &= ~VNF_HAVELABEL; #endif disk_unlock(&sc->sc_dk); return (0); }
static char * filename(char *str, char *ppart) { char *cp, *lp; char savec; int dhandle; char devtype[16]; lp = str; devtype[0] = 0; *ppart = 0; for (cp = str; *cp; lp = cp) { /* For each component of the path name... */ while (*++cp && *cp != '/'); savec = *cp; *cp = 0; /* ...look whether there is a device with this name */ dhandle = OF_finddevice(str); DNPRINTF(BOOT_D_OFDEV, "filename: OF_finddevice(%s) says %x\n", str, dhandle); *cp = savec; if (dhandle == -1) { /* if not, lp is the delimiter between device and path */ /* if the last component was a block device... */ if (!strcmp(devtype, "block")) { /* search for arguments */ DNPRINTF(BOOT_D_OFDEV, "filename: hunting for " "arguments in %s\n", str); for (cp = lp; --cp >= str && *cp != '/' && *cp != '-';); if (cp >= str && *cp == '-') { /* found arguments, make firmware ignore them */ *cp = 0; for (cp = lp; *--cp && *cp != ',';); if (*++cp >= 'a' && *cp <= 'a' + MAXPARTITIONS) *ppart = *cp; } } DNPRINTF(BOOT_D_OFDEV, "filename: found %s\n", lp); return lp; } else if (OF_getprop(dhandle, "device_type", devtype, sizeof devtype) < 0) devtype[0] = 0; } DNPRINTF(BOOT_D_OFDEV, "filename: not found\n", lp); return 0; }
/* * cancel, remove, etc. downloads */ void xtp_handle_dl(struct tab *t, uint8_t cmd, int id) { struct download find, *d = NULL; DNPRINTF(XT_D_DOWNLOAD, "download control: cmd %d, id %d\n", cmd, id); /* some commands require a valid download id */ if (cmd != XT_XTP_DL_LIST) { /* lookup download in question */ find.id = id; d = RB_FIND(download_list, &downloads, &find); if (d == NULL) { show_oops(t, "%s: no such download", __func__); return; } } /* decide what to do */ switch (cmd) { case XT_XTP_DL_START: /* our downloads always needs to be * restarted if called from here */ download_start(t, d, XT_DL_RESTART); break; case XT_XTP_DL_CANCEL: webkit_download_cancel(d->download); g_object_unref(d->download); RB_REMOVE(download_list, &downloads, d); break; case XT_XTP_DL_UNLINK: #ifdef __MINGW32__ unlink(webkit_download_get_destination_uri(d->download)); #else unlink(webkit_download_get_destination_uri(d->download) + strlen("file://")); #endif /* FALLTHROUGH */ case XT_XTP_DL_REMOVE: webkit_download_cancel(d->download); /* just incase */ g_object_unref(d->download); RB_REMOVE(download_list, &downloads, d); break; case XT_XTP_DL_LIST: /* Nothing */ break; default: show_oops(t, "%s: unknown command", __func__); break; }; xtp_page_dl(t, NULL); }
int strategy(void *devdata, int rw, daddr32_t blk, size_t size, void *buf, size_t *rsize) { struct of_dev *dev = devdata; u_quad_t pos; int n; if (rw != F_READ) return EPERM; #ifdef SOFTRAID /* Intercept strategy for softraid volumes. */ if (dev->type == OFDEV_SOFTRAID) return sr_strategy(bootdev_dip->sr_vol, rw, blk, size, buf, rsize); #endif if (dev->type != OFDEV_DISK) panic("strategy"); DNPRINTF(BOOT_D_OFDEV, "strategy: block %lx, partition offset %lx, " "blksz %lx\n", (long)blk, (long)dev->partoff, (long)dev->bsize); DNPRINTF(BOOT_D_OFDEV, "strategy: seek position should be: %lx\n", (long)((blk + dev->partoff) * dev->bsize)); pos = (u_quad_t)(blk + dev->partoff) * dev->bsize; for (;;) { DNPRINTF(BOOT_D_OFDEV, "strategy: seeking to %lx\n", (long)pos); if (OF_seek(dev->handle, pos) < 0) break; DNPRINTF(BOOT_D_OFDEV, "strategy: reading %lx at %p\n", (long)size, buf); n = OF_read(dev->handle, buf, size); if (n == -2) continue; if (n < 0) break; *rsize = n; return 0; } return EIO; }
void print_cookie(char *msg, SoupCookie *c) { if (c == NULL) return; if (msg) { DNPRINTF(XT_D_COOKIE, "%s\n", msg); } DNPRINTF(XT_D_COOKIE, "name : %s\n", c->name); DNPRINTF(XT_D_COOKIE, "value : %s\n", c->value); DNPRINTF(XT_D_COOKIE, "domain : %s\n", c->domain); DNPRINTF(XT_D_COOKIE, "path : %s\n", c->path); DNPRINTF(XT_D_COOKIE, "expires : %s\n", c->expires ? soup_date_to_string(c->expires, SOUP_DATE_HTTP) : ""); DNPRINTF(XT_D_COOKIE, "secure : %d\n", c->secure); DNPRINTF(XT_D_COOKIE, "http_only: %d\n", c->http_only); DNPRINTF(XT_D_COOKIE, "====================================\n"); }
int mfi_pci_find_device(void *aux) { struct pci_attach_args *pa = aux; int i; for (i = 0; mfi_pci_devices[i].mpd_vendor; i++) { if (mfi_pci_devices[i].mpd_vendor == PCI_VENDOR(pa->pa_id) && mfi_pci_devices[i].mpd_product == PCI_PRODUCT(pa->pa_id)) { DNPRINTF(MFI_D_MISC, "mfi_pci_find_device: %i\n", i); return (i); } } return (-1); }
int mfi_pci_match(struct device *parent, void *match, void *aux) { int i; if ((i = mfi_pci_find_device(aux)) != -1) { DNPRINTF(MFI_D_MISC, "mfi_pci_match: vendor: %04x product: %04x\n", mfi_pci_devices[i].mpd_vendor, mfi_pci_devices[i].mpd_product); return (1); } return (0); }
/* * generate a session key to secure xtp commands. * pass in a ptr to the key in question and it will * be modified in place. */ void generate_xtp_session_key(char **key) { uint8_t rand_bytes[XT_XTP_SES_KEY_SZ]; /* free old key */ if (*key) g_free(*key); /* make a new one */ arc4random_buf(rand_bytes, XT_XTP_SES_KEY_SZ); *key = g_strdup_printf(XT_XTP_SES_KEY_HEX_FMT, rand_bytes[0], rand_bytes[1], rand_bytes[2], rand_bytes[3], rand_bytes[4], rand_bytes[5], rand_bytes[6], rand_bytes[7]); DNPRINTF(XT_D_DOWNLOAD, "%s: new session key '%s'\n", __func__, *key); }
size_t vndbdevsize(struct vnode *vp, struct proc *p) { struct partinfo pi; struct bdevsw *bsw; dev_t dev; dev = vp->v_rdev; bsw = bdevsw_lookup(dev); if (bsw->d_ioctl == NULL) return (0); if (bsw->d_ioctl(dev, DIOCGPART, (caddr_t)&pi, FREAD, p)) return (0); DNPRINTF(VDB_INIT, "vndbdevsize: size %llu secsize %u\n", DL_GETPSIZE(pi.part), pi.disklab->d_secsize); return (DL_GETPSIZE(pi.part)); }
void vndclear(struct vnd_softc *sc) { struct vnode *vp = sc->sc_vp; struct proc *p = curproc; /* XXX */ DNPRINTF(VDB_FOLLOW, "vndclear(%p): vp %p\n", sc, vp); if (vp == NULL) panic("vndioctl: null vp"); (void) vn_close(vp, VNDRW(sc), sc->sc_cred, p); crfree(sc->sc_cred); sc->sc_flags = 0; sc->sc_vp = NULL; sc->sc_cred = NULL; sc->sc_size = 0; memset(sc->sc_file, 0, sizeof(sc->sc_file)); }
int vndopen(dev_t dev, int flags, int mode, struct proc *p) { int unit = DISKUNIT(dev); struct vnd_softc *sc; int error = 0, part; DNPRINTF(VDB_FOLLOW, "vndopen(%x, %x, %x, %p)\n", dev, flags, mode, p); if (unit >= numvnd) return (ENXIO); sc = &vnd_softc[unit]; if ((error = disk_lock(&sc->sc_dk)) != 0) return (error); if ((flags & FWRITE) && (sc->sc_flags & VNF_READONLY)) { error = EROFS; goto bad; } if ((sc->sc_flags & VNF_INITED) && (sc->sc_flags & VNF_HAVELABEL) == 0 && sc->sc_dk.dk_openmask == 0) { sc->sc_flags |= VNF_HAVELABEL; vndgetdisklabel(dev, sc, sc->sc_dk.dk_label, 0); } part = DISKPART(dev); error = disk_openpart(&sc->sc_dk, part, mode, (sc->sc_flags & VNF_HAVELABEL) != 0); bad: disk_unlock(&sc->sc_dk); return (error); }
/* * Given a SunOS disk label, set lp to a BSD disk label. * The BSD label is cleared out before this is called. */ static int disklabel_sun_to_bsd(struct sun_disklabel *sl, struct disklabel *lp) { struct sun_preamble *preamble = (struct sun_preamble *)sl; struct sun_partinfo *ppp; struct sun_dkpart *spp; struct partition *npp; u_short cksum = 0, *sp1, *sp2; int i, secpercyl; /* Verify the XOR check. */ sp1 = (u_short *)sl; sp2 = (u_short *)(sl + 1); while (sp1 < sp2) cksum ^= *sp1++; if (cksum != 0) return (EINVAL); /* SunOS disk label, bad checksum */ /* Format conversion. */ lp->d_magic = DISKMAGIC; lp->d_magic2 = DISKMAGIC; lp->d_flags = D_VENDOR; memcpy(lp->d_packname, sl->sl_text, sizeof(lp->d_packname)); lp->d_secsize = DEV_BSIZE; lp->d_nsectors = sl->sl_nsectors; lp->d_ntracks = sl->sl_ntracks; lp->d_ncylinders = sl->sl_ncylinders; secpercyl = sl->sl_nsectors * sl->sl_ntracks; lp->d_secpercyl = secpercyl; if (DL_GETDSIZE(lp) == 0) DL_SETDSIZE(lp, (u_int64_t)secpercyl * sl->sl_ncylinders); lp->d_version = 1; memcpy(&lp->d_uid, &sl->sl_uid, sizeof(lp->d_uid)); lp->d_acylinders = sl->sl_acylinders; lp->d_npartitions = MAXPARTITIONS; /* These are as defined in <ufs/ffs/fs.h> */ lp->d_bbsize = 8192; /* XXX */ lp->d_sbsize = 8192; /* XXX */ for (i = 0; i < 8; i++) { spp = &sl->sl_part[i]; npp = &lp->d_partitions[i]; DL_SETPOFFSET(npp, spp->sdkp_cyloffset * secpercyl); DL_SETPSIZE(npp, spp->sdkp_nsectors); if (DL_GETPSIZE(npp) == 0) { npp->p_fstype = FS_UNUSED; } else { npp->p_fstype = sun_fstypes[i]; if (npp->p_fstype == FS_BSDFFS) { /* * The sun label does not store the FFS fields, * so just set them with default values here. */ npp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(2048, 8); npp->p_cpg = 16; } } } /* Clear "extended" partition info, tentatively */ for (i = 0; i < SUNXPART; i++) { npp = &lp->d_partitions[i+8]; DL_SETPOFFSET(npp, 0); DL_SETPSIZE(npp, 0); npp->p_fstype = FS_UNUSED; } /* Check to see if there's an "extended" partition table * SL_XPMAG partitions had checksums up to just before the * (new) sl_types variable, while SL_XPMAGTYP partitions have * checksums up to the just before the (new) sl_xxx1 variable. * Also, disklabels created prior to the addition of sl_uid will * have a checksum to just before the sl_uid variable. */ if ((sl->sl_xpmag == SL_XPMAG && sun_extended_sum(sl, &sl->sl_types) == sl->sl_xpsum) || (sl->sl_xpmag == SL_XPMAGTYP && sun_extended_sum(sl, &sl->sl_uid) == sl->sl_xpsum) || (sl->sl_xpmag == SL_XPMAGTYP && sun_extended_sum(sl, &sl->sl_xxx1) == sl->sl_xpsum)) { /* * There is. Copy over the "extended" partitions. * This code parallels the loop for partitions a-h. */ for (i = 0; i < SUNXPART; i++) { spp = &sl->sl_xpart[i]; npp = &lp->d_partitions[i+8]; DL_SETPOFFSET(npp, spp->sdkp_cyloffset * secpercyl); DL_SETPSIZE(npp, spp->sdkp_nsectors); if (DL_GETPSIZE(npp) == 0) { npp->p_fstype = FS_UNUSED; continue; } npp->p_fstype = FS_BSDFFS; npp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(2048, 8); npp->p_cpg = 16; } if (sl->sl_xpmag == SL_XPMAGTYP) { for (i = 0; i < MAXPARTITIONS; i++) { npp = &lp->d_partitions[i]; npp->p_fstype = sl->sl_types[i]; npp->p_fragblock = sl->sl_fragblock[i]; npp->p_cpg = sl->sl_cpg[i]; } } } else if (preamble->sl_nparts <= 8) { /* * A more traditional Sun label. Recognise certain filesystem * types from it, if they are available. */ i = preamble->sl_nparts; if (i == 0) i = 8; npp = &lp->d_partitions[i-1]; ppp = &preamble->sl_part[i-1]; for (; i > 0; i--, npp--, ppp--) { if (npp->p_size == 0) continue; if ((ppp->spi_tag == 0) && (ppp->spi_flag == 0)) continue; switch (ppp->spi_tag) { case SPTAG_SUNOS_ROOT: case SPTAG_SUNOS_USR: case SPTAG_SUNOS_VAR: case SPTAG_SUNOS_HOME: npp->p_fstype = FS_BSDFFS; npp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(2048, 8); npp->p_cpg = 16; break; case SPTAG_LINUX_EXT2: npp->p_fstype = FS_EXT2FS; break; default: /* FS_SWAP for _SUNOS_SWAP and _LINUX_SWAP? */ npp->p_fstype = FS_UNUSED; break; } } } lp->d_checksum = 0; lp->d_checksum = dkcksum(lp); DNPRINTF(BOOT_D_OFDEV, "disklabel_sun_to_bsd: success!\n"); return (0); }
int devopen(struct open_file *of, const char *name, char **file) { char *cp; char partition; char fname[256]; char buf[DEV_BSIZE]; struct disklabel label; int handle, part; size_t read; char *errmsg = NULL; int error = 0; if (ofdev.handle != -1) panic("devopen"); if (of->f_flags != F_READ) return EPERM; DNPRINTF(BOOT_D_OFDEV, "devopen: you want %s\n", name); strlcpy(fname, name, sizeof fname); cp = filename(fname, &partition); if (cp) { strlcpy(buf, cp, sizeof buf); *cp = 0; } if (!cp || !*buf) strlcpy(buf, DEFAULT_KERNEL, sizeof buf); if (!*fname) strlcpy(fname, bootdev, sizeof fname); strlcpy(opened_name, fname, sizeof opened_name); if (partition) { cp = opened_name + strlen(opened_name); *cp++ = ':'; *cp++ = partition; *cp = 0; } if (*buf != '/') strlcat(opened_name, "/", sizeof opened_name); strlcat(opened_name, buf, sizeof opened_name); *file = opened_name + strlen(fname) + 1; DNPRINTF(BOOT_D_OFDEV, "devopen: trying %s\n", fname); if ((handle = OF_finddevice(fname)) == -1) return ENOENT; DNPRINTF(BOOT_D_OFDEV, "devopen: found %s\n", fname); if (OF_getprop(handle, "name", buf, sizeof buf) < 0) return ENXIO; DNPRINTF(BOOT_D_OFDEV, "devopen: %s is called %s\n", fname, buf); if (OF_getprop(handle, "device_type", buf, sizeof buf) < 0) return ENXIO; DNPRINTF(BOOT_D_OFDEV, "devopen: %s is a %s device\n", fname, buf); DNPRINTF(BOOT_D_OFDEV, "devopen: opening %s\n", fname); if ((handle = OF_open(fname)) == -1) { DNPRINTF(BOOT_D_OFDEV, "devopen: open of %s failed\n", fname); return ENXIO; } DNPRINTF(BOOT_D_OFDEV, "devopen: %s is now open\n", fname); bzero(&ofdev, sizeof ofdev); ofdev.handle = handle; if (!strcmp(buf, "block")) { ofdev.type = OFDEV_DISK; ofdev.bsize = DEV_BSIZE; /* First try to find a disklabel without MBR partitions */ DNPRINTF(BOOT_D_OFDEV, "devopen: trying to read disklabel\n"); if (strategy(&ofdev, F_READ, LABELSECTOR, DEV_BSIZE, buf, &read) != 0 || read != DEV_BSIZE || (errmsg = getdisklabel(buf, &label))) { #ifdef BOOT_DEBUG if (errmsg) DNPRINTF(BOOT_D_OFDEV, "devopen: getdisklabel says %s\n", errmsg); #endif /* Else try MBR partitions */ errmsg = search_label(&ofdev, LABELSECTOR, buf, &label, 0); if (errmsg) { printf("devopen: search_label says %s\n", errmsg); error = ERDLAB; } if (error && error != ERDLAB) goto bad; } if (error == ERDLAB) { if (partition) /* User specified a parititon, but there is none */ goto bad; /* No, label, just use complete disk */ ofdev.partoff = 0; } else { part = partition ? partition - 'a' : 0; ofdev.partoff = label.d_partitions[part].p_offset; DNPRINTF(BOOT_D_OFDEV, "devopen: setting partition %d " "offset %x\n", part, ofdev.partoff); } of->f_dev = devsw; of->f_devdata = &ofdev; #ifdef SPARC_BOOT_UFS bcopy(&file_system_ufs, &file_system[nfsys++], sizeof file_system[0]); #endif #ifdef SPARC_BOOT_HSFS bcopy(&file_system_cd9660, &file_system[nfsys++], sizeof file_system[0]); #endif DNPRINTF(BOOT_D_OFDEV, "devopen: return 0\n"); return 0; } #ifdef NETBOOT if (!strcmp(buf, "network")) { ofdev.type = OFDEV_NET; of->f_dev = devsw; of->f_devdata = &ofdev; bcopy(&file_system_nfs, file_system, sizeof file_system[0]); nfsys = 1; if (error = net_open(&ofdev)) goto bad; return 0; } #endif error = EFTYPE; bad: DNPRINTF(BOOT_D_OFDEV, "devopen: error %d, cannot open device\n", error); OF_close(handle); ofdev.handle = -1; return error; }
void sr_raid1_set_chunk_state(struct sr_discipline *sd, int c, int new_state) { int old_state, s; DNPRINTF(SR_D_STATE, "%s: %s: %s: sr_raid_set_chunk_state %d -> %d\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, sd->sd_vol.sv_chunks[c]->src_meta.scmi.scm_devname, c, new_state); /* ok to go to splbio since this only happens in error path */ s = splbio(); old_state = sd->sd_vol.sv_chunks[c]->src_meta.scm_status; /* multiple IOs to the same chunk that fail will come through here */ if (old_state == new_state) goto done; switch (old_state) { case BIOC_SDONLINE: switch (new_state) { case BIOC_SDOFFLINE: case BIOC_SDSCRUB: break; default: goto die; } break; case BIOC_SDOFFLINE: switch (new_state) { case BIOC_SDREBUILD: case BIOC_SDHOTSPARE: break; default: goto die; } break; case BIOC_SDSCRUB: if (new_state == BIOC_SDONLINE) { ; } else goto die; break; case BIOC_SDREBUILD: switch (new_state) { case BIOC_SDONLINE: break; case BIOC_SDOFFLINE: /* Abort rebuild since the rebuild chunk disappeared. */ sd->sd_reb_abort = 1; break; default: goto die; } break; case BIOC_SDHOTSPARE: switch (new_state) { case BIOC_SDOFFLINE: case BIOC_SDREBUILD: break; default: goto die; } break; default: die: splx(s); /* XXX */ panic("%s: %s: %s: invalid chunk state transition " "%d -> %d\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, sd->sd_vol.sv_chunks[c]->src_meta.scmi.scm_devname, old_state, new_state); /* NOTREACHED */ } sd->sd_vol.sv_chunks[c]->src_meta.scm_status = new_state; sd->sd_set_vol_state(sd); sd->sd_must_flush = 1; workq_add_task(NULL, 0, sr_meta_save_callback, sd, NULL); done: splx(s); }
/* * is the url xtp protocol? (xxxt://) * if so, parse and despatch correct bahvior */ int parse_xtp_url(struct tab *t, const char *url) { char *dup = NULL, *p, *last = NULL; uint8_t n_tokens = 0; char *tokens[4] = {NULL, NULL, NULL, ""}; struct xtp_despatch *dsp, *dsp_match = NULL; uint8_t req_class; int ret = FALSE; /* * tokens array meaning: * tokens[0] = class * tokens[1] = session key * tokens[2] = action * tokens[3] = optional argument */ DNPRINTF(XT_D_URL, "%s: url %s\n", __func__, url); if (strncmp(url, XT_XTP_STR, strlen(XT_XTP_STR))) goto clean; dup = g_strdup(url + strlen(XT_XTP_STR)); /* split out the url */ for ((p = strtok_r(dup, "/", &last)); p; (p = strtok_r(NULL, "/", &last))) { if (n_tokens < 4) tokens[n_tokens++] = p; } /* should be atleast three fields 'class/seskey/command/arg' */ if (n_tokens < 3) goto clean; dsp = xtp_despatches; req_class = atoi(tokens[0]); while (dsp->xtp_class) { if (dsp->xtp_class == req_class) { dsp_match = dsp; break; } dsp++; } /* did we find one atall? */ if (dsp_match == NULL) { show_oops(t, "%s: no matching xtp despatch found", __func__); goto clean; } /* check session key and call despatch function */ if (validate_xtp_session_key(t, *(dsp_match->session_key), tokens[1])) { ret = TRUE; /* all is well, this was a valid xtp request */ dsp_match->handle_func(t, atoi(tokens[2]), atoi(tokens[3])); } clean: if (dup) g_free(dup); return (ret); }
/* ARGSUSED */ int vndioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { int unit = DISKUNIT(dev); struct disklabel *lp; struct vnd_softc *sc; struct vnd_ioctl *vio; struct vnd_user *vnu; struct vattr vattr; struct nameidata nd; int error, part, pmask; DNPRINTF(VDB_FOLLOW, "vndioctl(%x, %lx, %p, %x, %p): unit %d\n", dev, cmd, addr, flag, p, unit); error = suser(p, 0); if (error) return (error); if (unit >= numvnd) return (ENXIO); sc = &vnd_softc[unit]; vio = (struct vnd_ioctl *)addr; switch (cmd) { case VNDIOCSET: if (sc->sc_flags & VNF_INITED) return (EBUSY); /* Geometry eventually has to fit into label fields */ if (vio->vnd_secsize > UINT_MAX || vio->vnd_ntracks > UINT_MAX || vio->vnd_nsectors > UINT_MAX) return (EINVAL); if ((error = disk_lock(&sc->sc_dk)) != 0) return (error); if ((error = copyinstr(vio->vnd_file, sc->sc_file, sizeof(sc->sc_file), NULL))) { disk_unlock(&sc->sc_dk); return (error); } /* Set geometry for device. */ sc->sc_secsize = vio->vnd_secsize; sc->sc_ntracks = vio->vnd_ntracks; sc->sc_nsectors = vio->vnd_nsectors; /* * Open for read and write first. This lets vn_open() weed out * directories, sockets, etc. so we don't have to worry about * them. */ NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, vio->vnd_file, p); sc->sc_flags &= ~VNF_READONLY; error = vn_open(&nd, FREAD|FWRITE, 0); if (error == EROFS) { sc->sc_flags |= VNF_READONLY; error = vn_open(&nd, FREAD, 0); } if (error) { disk_unlock(&sc->sc_dk); return (error); } if (nd.ni_vp->v_type == VBLK) sc->sc_size = vndbdevsize(nd.ni_vp, p); else { error = VOP_GETATTR(nd.ni_vp, &vattr, p->p_ucred, p); if (error) { VOP_UNLOCK(nd.ni_vp, 0, p); vn_close(nd.ni_vp, VNDRW(sc), p->p_ucred, p); disk_unlock(&sc->sc_dk); return (error); } sc->sc_size = vattr.va_size / sc->sc_secsize; } VOP_UNLOCK(nd.ni_vp, 0, p); sc->sc_vp = nd.ni_vp; if ((error = vndsetcred(sc, p->p_ucred)) != 0) { (void) vn_close(nd.ni_vp, VNDRW(sc), p->p_ucred, p); disk_unlock(&sc->sc_dk); return (error); } if (vio->vnd_keylen > 0) { char key[BLF_MAXUTILIZED]; if (vio->vnd_keylen > sizeof(key)) vio->vnd_keylen = sizeof(key); if ((error = copyin(vio->vnd_key, key, vio->vnd_keylen)) != 0) { (void) vn_close(nd.ni_vp, VNDRW(sc), p->p_ucred, p); disk_unlock(&sc->sc_dk); return (error); } sc->sc_keyctx = malloc(sizeof(*sc->sc_keyctx), M_DEVBUF, M_WAITOK); blf_key(sc->sc_keyctx, key, vio->vnd_keylen); explicit_bzero(key, vio->vnd_keylen); } else sc->sc_keyctx = NULL; vio->vnd_size = sc->sc_size * sc->sc_secsize; sc->sc_flags |= VNF_INITED; DNPRINTF(VDB_INIT, "vndioctl: SET vp %p size %llx\n", sc->sc_vp, (unsigned long long)sc->sc_size); /* Attach the disk. */ sc->sc_dk.dk_name = sc->sc_dev.dv_xname; disk_attach(&sc->sc_dev, &sc->sc_dk); disk_unlock(&sc->sc_dk); break; case VNDIOCCLR: if ((sc->sc_flags & VNF_INITED) == 0) return (ENXIO); if ((error = disk_lock(&sc->sc_dk)) != 0) return (error); /* * Don't unconfigure if any other partitions are open * or if both the character and block flavors of this * partition are open. */ part = DISKPART(dev); pmask = (1 << part); if ((sc->sc_dk.dk_openmask & ~pmask) || ((sc->sc_dk.dk_bopenmask & pmask) && (sc->sc_dk.dk_copenmask & pmask))) { disk_unlock(&sc->sc_dk); return (EBUSY); } vndclear(sc); DNPRINTF(VDB_INIT, "vndioctl: CLRed\n"); /* Free crypto key */ if (sc->sc_keyctx) { explicit_bzero(sc->sc_keyctx, sizeof(*sc->sc_keyctx)); free(sc->sc_keyctx, M_DEVBUF, sizeof(*sc->sc_keyctx)); } /* Detach the disk. */ disk_detach(&sc->sc_dk); disk_unlock(&sc->sc_dk); break; case VNDIOCGET: vnu = (struct vnd_user *)addr; if (vnu->vnu_unit == -1) vnu->vnu_unit = unit; if (vnu->vnu_unit >= numvnd) return (ENXIO); if (vnu->vnu_unit < 0) return (EINVAL); sc = &vnd_softc[vnu->vnu_unit]; if (sc->sc_flags & VNF_INITED) { error = VOP_GETATTR(sc->sc_vp, &vattr, p->p_ucred, p); if (error) return (error); strlcpy(vnu->vnu_file, sc->sc_file, sizeof(vnu->vnu_file)); vnu->vnu_dev = vattr.va_fsid; vnu->vnu_ino = vattr.va_fileid; } else { vnu->vnu_dev = 0; vnu->vnu_ino = 0; } break; case DIOCRLDINFO: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK); vndgetdisklabel(dev, sc, lp, 0); *(sc->sc_dk.dk_label) = *lp; free(lp, M_TEMP, sizeof(*lp)); return (0); case DIOCGPDINFO: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); vndgetdisklabel(dev, sc, (struct disklabel *)addr, 1); return (0); case DIOCGDINFO: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); *(struct disklabel *)addr = *(sc->sc_dk.dk_label); return (0); case DIOCGPART: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); ((struct partinfo *)addr)->disklab = sc->sc_dk.dk_label; ((struct partinfo *)addr)->part = &sc->sc_dk.dk_label->d_partitions[DISKPART(dev)]; return (0); case DIOCWDINFO: case DIOCSDINFO: if ((sc->sc_flags & VNF_HAVELABEL) == 0) return (ENOTTY); if ((flag & FWRITE) == 0) return (EBADF); if ((error = disk_lock(&sc->sc_dk)) != 0) return (error); error = setdisklabel(sc->sc_dk.dk_label, (struct disklabel *)addr, /* sc->sc_dk.dk_openmask */ 0); if (error == 0) { if (cmd == DIOCWDINFO) error = writedisklabel(DISKLABELDEV(dev), vndstrategy, sc->sc_dk.dk_label); } disk_unlock(&sc->sc_dk); return (error); default: return (ENOTTY); } return (0); }
void vndstrategy(struct buf *bp) { int unit = DISKUNIT(bp->b_dev); struct vnd_softc *sc; struct partition *p; off_t off; long origbcount; int s; DNPRINTF(VDB_FOLLOW, "vndstrategy(%p): unit %d\n", bp, unit); if (unit >= numvnd) { bp->b_error = ENXIO; goto bad; } sc = &vnd_softc[unit]; if ((sc->sc_flags & VNF_HAVELABEL) == 0) { bp->b_error = ENXIO; goto bad; } /* * Many of the distrib scripts assume they can issue arbitrary * sized requests to raw vnd devices irrespective of the * emulated disk geometry. * * To continue supporting this, round the block count up to a * multiple of d_secsize for bounds_check_with_label(), and * then restore afterwards. * * We only do this for non-encrypted vnd, because encryption * requires operating on blocks at a time. */ origbcount = bp->b_bcount; if (sc->sc_keyctx == NULL) { u_int32_t secsize = sc->sc_dk.dk_label->d_secsize; bp->b_bcount = ((origbcount + secsize - 1) & ~(secsize - 1)); #ifdef DIAGNOSTIC if (bp->b_bcount != origbcount) { struct proc *pr = curproc; printf("%s: sloppy %s from proc %d (%s): " "blkno %lld bcount %ld\n", sc->sc_dev.dv_xname, (bp->b_flags & B_READ) ? "read" : "write", pr->p_pid, pr->p_comm, (long long)bp->b_blkno, origbcount); } #endif } if (bounds_check_with_label(bp, sc->sc_dk.dk_label) == -1) { bp->b_resid = bp->b_bcount = origbcount; goto done; } if (origbcount < bp->b_bcount) bp->b_bcount = origbcount; p = &sc->sc_dk.dk_label->d_partitions[DISKPART(bp->b_dev)]; off = DL_GETPOFFSET(p) * sc->sc_dk.dk_label->d_secsize + (u_int64_t)bp->b_blkno * DEV_BSIZE; if (sc->sc_keyctx && !(bp->b_flags & B_READ)) vndencryptbuf(sc, bp, 1); /* * Use IO_NOLIMIT because upper layer has already checked I/O * for limits, so there is no need to do it again. */ bp->b_error = vn_rdwr((bp->b_flags & B_READ) ? UIO_READ : UIO_WRITE, sc->sc_vp, bp->b_data, bp->b_bcount, off, UIO_SYSSPACE, IO_NOLIMIT, sc->sc_cred, &bp->b_resid, curproc); if (bp->b_error) bp->b_flags |= B_ERROR; /* Data in buffer cache needs to be in clear */ if (sc->sc_keyctx) vndencryptbuf(sc, bp, 0); goto done; bad: bp->b_flags |= B_ERROR; bp->b_resid = bp->b_bcount; done: s = splbio(); biodone(bp); splx(s); }
int sr_concat_rw(struct sr_workunit *wu) { struct sr_discipline *sd = wu->swu_dis; struct scsi_xfer *xs = wu->swu_xs; struct sr_ccb *ccb; struct sr_chunk *scp; daddr_t blkno; int64_t lbaoffs, offset; int64_t no_chunk, chunkend, chunk, chunksize; int64_t length, leftover; u_int8_t *data; /* blkno and scsi error will be handled by sr_validate_io */ if (sr_validate_io(wu, &blkno, "sr_concat_rw")) goto bad; no_chunk = sd->sd_meta->ssdi.ssd_chunk_no; DNPRINTF(SR_D_DIS, "%s: %s: front end io: blkno %lld size %d\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, (long long)blkno, xs->datalen); /* All offsets are in bytes. */ lbaoffs = blkno << DEV_BSHIFT; leftover = xs->datalen; data = xs->data; for (;;) { chunkend = 0; offset = lbaoffs; for (chunk = 0; chunk < no_chunk; chunk++) { chunksize = sd->sd_vol.sv_chunks[chunk]->src_size << DEV_BSHIFT; chunkend += chunksize; if (lbaoffs < chunkend) break; offset -= chunksize; } if (lbaoffs > chunkend) goto bad; length = MIN(MIN(leftover, chunkend - lbaoffs), MAXPHYS); /* make sure chunk is online */ scp = sd->sd_vol.sv_chunks[chunk]; if (scp->src_meta.scm_status != BIOC_SDONLINE) goto bad; DNPRINTF(SR_D_DIS, "%s: %s %s io lbaoffs %lld " "chunk %lld chunkend %lld offset %lld length %lld " "leftover %lld data %p\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, sd->sd_name, lbaoffs, chunk, chunkend, offset, length, leftover, data); blkno = offset >> DEV_BSHIFT; ccb = sr_ccb_rw(sd, chunk, blkno, length, data, xs->flags, 0); if (!ccb) { /* should never happen but handle more gracefully */ printf("%s: %s: too many ccbs queued\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname); goto bad; } sr_wu_enqueue_ccb(wu, ccb); leftover -= length; if (leftover == 0) break; data += length; lbaoffs += length; } sr_schedule_wu(wu); return (0); bad: /* wu is unwound by sr_wu_put */ return (1); }
int devopen(struct open_file *of, const char *name, char **file) { char *cp; char partition; char fname[256]; char buf[DEV_BSIZE]; struct disklabel label; int handle, part; int error = 0; #ifdef SOFTRAID char volno; #endif if (ofdev.handle != -1) panic("devopen"); if (of->f_flags != F_READ) return EPERM; DNPRINTF(BOOT_D_OFDEV, "devopen: you want %s\n", name); if (strlcpy(fname, name, sizeof fname) >= sizeof fname) return ENAMETOOLONG; #ifdef SOFTRAID if (bootdev_dip) { if (fname[0] == 's' && fname[1] == 'r' && '0' <= fname[2] && fname[2] <= '9') { volno = fname[2]; if ('a' <= fname[3] && fname[3] <= 'a' + MAXPARTITIONS) { partition = fname[3]; if (fname[4] == ':') cp = &fname[5]; else cp = &fname[4]; } else { partition = 'a'; cp = &fname[3]; } } else { volno = '0'; partition = 'a'; cp = &fname[0]; } snprintf(buf, sizeof buf, "sr%c:%c", volno, partition); if (strlcpy(opened_name, buf, sizeof opened_name) >= sizeof opened_name) return ENAMETOOLONG; *file = opened_name + strlen(opened_name); if (!*cp) { if (strlcpy(buf, DEFAULT_KERNEL, sizeof buf) >= sizeof buf) return ENAMETOOLONG; } else { if (snprintf(buf, sizeof buf, "%s%s", *cp == '/' ? "" : "/", cp) >= sizeof buf) return ENAMETOOLONG; } if (strlcat(opened_name, buf, sizeof opened_name) >= sizeof opened_name) return ENAMETOOLONG; } else { #endif cp = filename(fname, &partition); if (cp) { if (strlcpy(buf, cp, sizeof buf) >= sizeof buf) return ENAMETOOLONG; *cp = 0; } if (!cp || !*buf) { if (strlcpy(buf, DEFAULT_KERNEL, sizeof buf) >= sizeof buf) return ENAMETOOLONG; } if (!*fname) { if (strlcpy(fname, bootdev, sizeof fname) >= sizeof fname) return ENAMETOOLONG; } if (strlcpy(opened_name, fname, partition ? (sizeof opened_name) - 2 : sizeof opened_name) >= sizeof opened_name) return ENAMETOOLONG; if (partition) { cp = opened_name + strlen(opened_name); *cp++ = ':'; *cp++ = partition; *cp = 0; } if (*buf != '/') { if (strlcat(opened_name, "/", sizeof opened_name) >= sizeof opened_name) return ENAMETOOLONG; } if (strlcat(opened_name, buf, sizeof opened_name) >= sizeof opened_name) return ENAMETOOLONG; *file = opened_name + strlen(fname) + 1; #ifdef SOFTRAID } #endif DNPRINTF(BOOT_D_OFDEV, "devopen: trying %s\n", fname); #ifdef SOFTRAID if (bootdev_dip) { /* Redirect to the softraid boot volume. */ struct partition *pp; bzero(&ofdev, sizeof ofdev); ofdev.type = OFDEV_SOFTRAID; if (partition) { if (partition < 'a' || partition >= 'a' + MAXPARTITIONS) { printf("invalid partition '%c'\n", partition); return EINVAL; } part = partition - 'a'; pp = &bootdev_dip->disklabel.d_partitions[part]; if (pp->p_fstype == FS_UNUSED || pp->p_size == 0) { printf("invalid partition '%c'\n", partition); return EINVAL; } bootdev_dip->sr_vol->sbv_part = partition; } else bootdev_dip->sr_vol->sbv_part = 'a'; of->f_dev = devsw; of->f_devdata = &ofdev; #ifdef SPARC_BOOT_UFS bcopy(&file_system_ufs, &file_system[nfsys++], sizeof file_system[0]); #else #error "-DSOFTRAID requires -DSPARC_BOOT_UFS" #endif return 0; } #endif if ((handle = OF_finddevice(fname)) == -1) return ENOENT; DNPRINTF(BOOT_D_OFDEV, "devopen: found %s\n", fname); if (OF_getprop(handle, "name", buf, sizeof buf) < 0) return ENXIO; DNPRINTF(BOOT_D_OFDEV, "devopen: %s is called %s\n", fname, buf); if (OF_getprop(handle, "device_type", buf, sizeof buf) < 0) return ENXIO; DNPRINTF(BOOT_D_OFDEV, "devopen: %s is a %s device\n", fname, buf); DNPRINTF(BOOT_D_OFDEV, "devopen: opening %s\n", fname); if ((handle = OF_open(fname)) == -1) { DNPRINTF(BOOT_D_OFDEV, "devopen: open of %s failed\n", fname); return ENXIO; } DNPRINTF(BOOT_D_OFDEV, "devopen: %s is now open\n", fname); bzero(&ofdev, sizeof ofdev); ofdev.handle = handle; ofdev.type = OFDEV_DISK; ofdev.bsize = DEV_BSIZE; if (!strcmp(buf, "block")) { error = load_disklabel(&ofdev, &label); if (error && error != ERDLAB) goto bad; else if (error == ERDLAB) { if (partition) /* User specified a parititon, but there is none */ goto bad; /* No, label, just use complete disk */ ofdev.partoff = 0; } else { part = partition ? partition - 'a' : 0; ofdev.partoff = label.d_partitions[part].p_offset; DNPRINTF(BOOT_D_OFDEV, "devopen: setting partition %d " "offset %x\n", part, ofdev.partoff); } of->f_dev = devsw; of->f_devdata = &ofdev; #ifdef SPARC_BOOT_UFS bcopy(&file_system_ufs, &file_system[nfsys++], sizeof file_system[0]); #endif #ifdef SPARC_BOOT_HSFS bcopy(&file_system_cd9660, &file_system[nfsys++], sizeof file_system[0]); #endif DNPRINTF(BOOT_D_OFDEV, "devopen: return 0\n"); return 0; } #ifdef NETBOOT if (!strcmp(buf, "network")) { ofdev.type = OFDEV_NET; of->f_dev = devsw; of->f_devdata = &ofdev; bcopy(&file_system_nfs, file_system, sizeof file_system[0]); nfsys = 1; if (error = net_open(&ofdev)) goto bad; return 0; } #endif error = EFTYPE; bad: DNPRINTF(BOOT_D_OFDEV, "devopen: error %d, cannot open device\n", error); OF_close(handle); ofdev.handle = -1; return error; }
int sys_pledge(struct proc *p, void *v, register_t *retval) { struct sys_pledge_args /* { syscallarg(const char *)request; syscallarg(const char **)paths; } */ *uap = v; uint64_t flags = 0; int error; if (SCARG(uap, request)) { size_t rbuflen; char *rbuf, *rp, *pn; uint64_t f; rbuf = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); error = copyinstr(SCARG(uap, request), rbuf, MAXPATHLEN, &rbuflen); if (error) { free(rbuf, M_TEMP, MAXPATHLEN); return (error); } #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrstruct(p, "pledgereq", rbuf, rbuflen-1); #endif for (rp = rbuf; rp && *rp && error == 0; rp = pn) { pn = strchr(rp, ' '); /* find terminator */ if (pn) { while (*pn == ' ') *pn++ = '\0'; } if ((f = pledgereq_flags(rp)) == 0) { free(rbuf, M_TEMP, MAXPATHLEN); return (EINVAL); } flags |= f; } free(rbuf, M_TEMP, MAXPATHLEN); /* * if we are already pledged, allow only promises reductions. * flags doesn't contain flags outside _USERSET: they will be * relearned. */ if (ISSET(p->p_p->ps_flags, PS_PLEDGE) && (((flags | p->p_p->ps_pledge) != p->p_p->ps_pledge))) return (EPERM); } if (SCARG(uap, paths)) { #if 1 return (EINVAL); #else const char **u = SCARG(uap, paths), *sp; struct whitepaths *wl; char *path, *rdir = NULL, *cwd = NULL; size_t pathlen, rdirlen, cwdlen; size_t maxargs = 0; int i, error; if (p->p_p->ps_pledgepaths) return (EPERM); /* Count paths */ for (i = 0; i < PLEDGE_MAXPATHS; i++) { if ((error = copyin(u + i, &sp, sizeof(sp))) != 0) return (error); if (sp == NULL) break; } if (i == PLEDGE_MAXPATHS) return (E2BIG); wl = malloc(sizeof *wl + sizeof(struct whitepath) * (i+1), M_TEMP, M_WAITOK | M_ZERO); wl->wl_size = sizeof *wl + sizeof(struct whitepath) * (i+1); wl->wl_count = i; wl->wl_ref = 1; path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); /* Copy in */ for (i = 0; i < wl->wl_count; i++) { char *resolved = NULL; size_t resolvedlen; if ((error = copyin(u + i, &sp, sizeof(sp))) != 0) break; if (sp == NULL) break; if ((error = copyinstr(sp, path, MAXPATHLEN, &pathlen)) != 0) break; #ifdef KTRACE if (KTRPOINT(p, KTR_STRUCT)) ktrstruct(p, "pledgepath", path, pathlen-1); #endif error = resolvpath(p, &rdir, &rdirlen, &cwd, &cwdlen, path, pathlen, &resolved, &resolvedlen); if (error != 0) /* resolved is allocated only if !error */ break; maxargs += resolvedlen; if (maxargs > ARG_MAX) { error = E2BIG; free(resolved, M_TEMP, resolvedlen); break; } wl->wl_paths[i].name = resolved; wl->wl_paths[i].len = resolvedlen; } free(rdir, M_TEMP, rdirlen); free(cwd, M_TEMP, cwdlen); free(path, M_TEMP, MAXPATHLEN); if (error) { for (i = 0; i < wl->wl_count; i++) free(wl->wl_paths[i].name, M_TEMP, wl->wl_paths[i].len); free(wl, M_TEMP, wl->wl_size); return (error); } p->p_p->ps_pledgepaths = wl; #ifdef DEBUG_PLEDGE /* print paths registered as whilelisted (viewed as without chroot) */ DNPRINTF(1, "pledge: %s(%d): paths loaded:\n", p->p_comm, p->p_pid); for (i = 0; i < wl->wl_count; i++) if (wl->wl_paths[i].name) DNPRINTF(1, "pledge: %d=\"%s\" [%lld]\n", i, wl->wl_paths[i].name, (long long)wl->wl_paths[i].len); #endif #endif } if (SCARG(uap, request)) { p->p_p->ps_pledge = flags; p->p_p->ps_flags |= PS_PLEDGE; } return (0); }
void soup_cookie_jar_add_cookie(SoupCookieJar *jar, SoupCookie *cookie) { struct wl_entry *w = NULL; SoupCookie *c; FILE *r_cookie_f; char *public_suffix; DNPRINTF(XT_D_COOKIE, "soup_cookie_jar_add_cookie: %p %p %p\n", jar, p_cookiejar, s_cookiejar); if (cookies_enabled == 0) return; /* see if we are up and running */ if (p_cookiejar == NULL) { _soup_cookie_jar_add_cookie(jar, cookie); return; } /* disallow p_cookiejar adds, shouldn't happen */ if (jar == p_cookiejar) return; /* sanity */ if (jar == NULL || cookie == NULL) return; /* check if domain is valid */ public_suffix = tld_get_suffix(cookie->domain[0] == '.' ? cookie->domain + 1 : cookie->domain); if (public_suffix == NULL || (enable_cookie_whitelist && (w = wl_find(cookie->domain, &c_wl)) == NULL)) { blocked_cookies++; DNPRINTF(XT_D_COOKIE, "soup_cookie_jar_add_cookie: reject %s\n", cookie->domain); if (save_rejected_cookies) { if ((r_cookie_f = fopen(rc_fname, "a+")) == NULL) { show_oops(NULL, "can't open reject cookie file"); return; } fseek(r_cookie_f, 0, SEEK_END); fprintf(r_cookie_f, "%s%s\t%s\t%s\t%s\t%lu\t%s\t%s\n", cookie->http_only ? "#HttpOnly_" : "", cookie->domain, *cookie->domain == '.' ? "TRUE" : "FALSE", cookie->path, cookie->secure ? "TRUE" : "FALSE", cookie->expires ? (gulong)soup_date_to_time_t(cookie->expires) : 0, cookie->name, cookie->value); fflush(r_cookie_f); fclose(r_cookie_f); } if (!allow_volatile_cookies) return; } if (cookie->expires == NULL && session_timeout) { soup_cookie_set_expires(cookie, soup_date_new_from_now(session_timeout)); print_cookie("modified add cookie", cookie); } /* see if we are white listed for persistence */ if ((w && w->handy) || (enable_cookie_whitelist == 0)) { /* add to persistent jar */ c = soup_cookie_copy(cookie); print_cookie("soup_cookie_jar_add_cookie p_cookiejar", c); _soup_cookie_jar_add_cookie(p_cookiejar, c); } /* add to session jar */ print_cookie("soup_cookie_jar_add_cookie s_cookiejar", cookie); _soup_cookie_jar_add_cookie(s_cookiejar, cookie); }
/* * wlpath lookup - only done after namei lookup has succeeded on the last compoent of * a namei lookup, with a possibly non-canonicalized path given in "origpath" from namei. */ int pledge_namei_wlpath(struct proc *p, struct nameidata *ni) { struct whitepaths *wl = p->p_p->ps_pledgepaths; char *rdir = NULL, *cwd = NULL, *resolved = NULL; size_t rdirlen, cwdlen, resolvedlen; int i, error, pardir_found; /* * If a whitelist is set, compare canonical paths. Anything * not on the whitelist gets ENOENT. */ if (ni->ni_p_path == NULL) return(0); KASSERT(p->p_p->ps_pledgepaths); // XXX change later or more help from namei? error = resolvpath(p, &rdir, &rdirlen, &cwd, &cwdlen, ni->ni_p_path, ni->ni_p_length+1, &resolved, &resolvedlen); free(rdir, M_TEMP, rdirlen); free(cwd, M_TEMP, cwdlen); if (error != 0) /* resolved is allocated only if !error */ return (error); /* print resolved path (viewed as without chroot) */ DNPRINTF(2, "pledge_namei: resolved=\"%s\" [%lld] strlen=%lld\n", resolved, (long long)resolvedlen, (long long)strlen(resolved)); error = ENOENT; pardir_found = 0; for (i = 0; i < wl->wl_count && wl->wl_paths[i].name && error; i++) { int substr = substrcmp(wl->wl_paths[i].name, wl->wl_paths[i].len - 1, resolved, resolvedlen - 1); /* print check between registered wl_path and resolved */ DNPRINTF(3, "pledge: check: \"%s\" (%ld) \"%s\" (%ld) = %d\n", wl->wl_paths[i].name, wl->wl_paths[i].len - 1, resolved, resolvedlen - 1, substr); /* wl_paths[i].name is a substring of resolved */ if (substr == 1) { u_char term = resolved[wl->wl_paths[i].len - 1]; if (term == '\0' || term == '/' || wl->wl_paths[i].name[1] == '\0') error = 0; /* resolved is a substring of wl_paths[i].name */ } else if (substr == 2) { u_char term = wl->wl_paths[i].name[resolvedlen - 1]; if (resolved[1] == '\0' || term == '/') pardir_found = 1; } } if (pardir_found) switch (p->p_pledge_syscall) { case SYS_stat: case SYS_lstat: case SYS_fstatat: case SYS_fstat: ni->ni_pledge |= PLEDGE_STATLIE; error = 0; } #ifdef DEBUG_PLEDGE if (error == ENOENT) /* print the path that is reported as ENOENT */ DNPRINTF(1, "pledge: %s(%d): wl_path ENOENT: \"%s\"\n", p->p_comm, p->p_pid, resolved); #endif free(resolved, M_TEMP, resolvedlen); return (error); /* Don't hint why it failed */ }
int sr_raid0_rw(struct sr_workunit *wu) { struct sr_discipline *sd = wu->swu_dis; struct scsi_xfer *xs = wu->swu_xs; struct sr_ccb *ccb; struct sr_chunk *scp; daddr_t blkno; int64_t chunkoffs, lbaoffs, offset, stripoffs; int64_t strip_bits, strip_no, strip_size; int64_t chunk, no_chunk; int64_t length, leftover; u_int8_t *data; /* blkno and scsi error will be handled by sr_validate_io */ if (sr_validate_io(wu, &blkno, "sr_raid0_rw")) goto bad; strip_size = sd->sd_meta->ssdi.ssd_strip_size; strip_bits = sd->mds.mdd_raid0.sr0_strip_bits; no_chunk = sd->sd_meta->ssdi.ssd_chunk_no; DNPRINTF(SR_D_DIS, "%s: %s: front end io: blkno %lld size %d\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, (long long)blkno, xs->datalen); /* all offs are in bytes */ lbaoffs = blkno << DEV_BSHIFT; strip_no = lbaoffs >> strip_bits; chunk = strip_no % no_chunk; stripoffs = lbaoffs & (strip_size - 1); chunkoffs = (strip_no / no_chunk) << strip_bits; offset = chunkoffs + stripoffs; length = MIN(xs->datalen, strip_size - stripoffs); leftover = xs->datalen; data = xs->data; for (;;) { /* make sure chunk is online */ scp = sd->sd_vol.sv_chunks[chunk]; if (scp->src_meta.scm_status != BIOC_SDONLINE) goto bad; DNPRINTF(SR_D_DIS, "%s: %s %s io lbaoffs %lld " "strip_no %lld chunk %lld stripoffs %lld " "chunkoffs %lld offset %lld length %lld " "leftover %lld data %p\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, sd->sd_name, lbaoffs, strip_no, chunk, stripoffs, chunkoffs, offset, length, leftover, data); blkno = offset >> DEV_BSHIFT; ccb = sr_ccb_rw(sd, chunk, blkno, length, data, xs->flags, 0); if (!ccb) { /* should never happen but handle more gracefully */ printf("%s: %s: too many ccbs queued\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname); goto bad; } sr_wu_enqueue_ccb(wu, ccb); leftover -= length; if (leftover == 0) break; data += length; if (++chunk > no_chunk - 1) { chunk = 0; offset += length; } else if (wu->swu_io_count == 1) offset -= stripoffs; length = MIN(leftover,strip_size); } sr_schedule_wu(wu); return (0); bad: /* wu is unwound by sr_wu_put */ return (1); }
void sr_raid1_set_vol_state(struct sr_discipline *sd) { int states[SR_MAX_STATES]; int new_state, i, s, nd; int old_state = sd->sd_vol_status; DNPRINTF(SR_D_STATE, "%s: %s: sr_raid_set_vol_state\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname); nd = sd->sd_meta->ssdi.ssd_chunk_no; #ifdef SR_DEBUG for (i = 0; i < nd; i++) DNPRINTF(SR_D_STATE, "%s: chunk %d status = %u\n", DEVNAME(sd->sd_sc), i, sd->sd_vol.sv_chunks[i]->src_meta.scm_status); #endif for (i = 0; i < SR_MAX_STATES; i++) states[i] = 0; for (i = 0; i < nd; i++) { s = sd->sd_vol.sv_chunks[i]->src_meta.scm_status; if (s >= SR_MAX_STATES) panic("%s: %s: %s: invalid chunk state", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, sd->sd_vol.sv_chunks[i]->src_meta.scmi.scm_devname); states[s]++; } if (states[BIOC_SDONLINE] == nd) new_state = BIOC_SVONLINE; else if (states[BIOC_SDONLINE] == 0) new_state = BIOC_SVOFFLINE; else if (states[BIOC_SDSCRUB] != 0) new_state = BIOC_SVSCRUB; else if (states[BIOC_SDREBUILD] != 0) new_state = BIOC_SVREBUILD; else if (states[BIOC_SDOFFLINE] != 0) new_state = BIOC_SVDEGRADED; else { DNPRINTF(SR_D_STATE, "%s: invalid volume state, old state " "was %d\n", DEVNAME(sd->sd_sc), old_state); panic("invalid volume state"); } DNPRINTF(SR_D_STATE, "%s: %s: sr_raid1_set_vol_state %d -> %d\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, old_state, new_state); switch (old_state) { case BIOC_SVONLINE: switch (new_state) { case BIOC_SVONLINE: /* can go to same state */ case BIOC_SVOFFLINE: case BIOC_SVDEGRADED: case BIOC_SVREBUILD: /* happens on boot */ break; default: goto die; } break; case BIOC_SVOFFLINE: /* XXX this might be a little too much */ goto die; case BIOC_SVSCRUB: switch (new_state) { case BIOC_SVONLINE: case BIOC_SVOFFLINE: case BIOC_SVDEGRADED: case BIOC_SVSCRUB: /* can go to same state */ break; default: goto die; } break; case BIOC_SVBUILDING: switch (new_state) { case BIOC_SVONLINE: case BIOC_SVOFFLINE: case BIOC_SVBUILDING: /* can go to the same state */ break; default: goto die; } break; case BIOC_SVREBUILD: switch (new_state) { case BIOC_SVONLINE: case BIOC_SVOFFLINE: case BIOC_SVDEGRADED: case BIOC_SVREBUILD: /* can go to the same state */ break; default: goto die; } break; case BIOC_SVDEGRADED: switch (new_state) { case BIOC_SVOFFLINE: case BIOC_SVREBUILD: case BIOC_SVDEGRADED: /* can go to the same state */ break; default: goto die; } break; default: die: panic("%s: %s: invalid volume state transition " "%d -> %d\n", DEVNAME(sd->sd_sc), sd->sd_meta->ssd_devname, old_state, new_state); /* NOTREACHED */ } sd->sd_vol_status = new_state; /* If we have just become degraded, look for a hotspare. */ if (new_state == BIOC_SVDEGRADED) workq_add_task(NULL, 0, sr_hotspare_rebuild_callback, sd, NULL); }