int vmfree(void *addr, unsigned long size, int type) { struct filemap *fm = NULL; int pages = PAGES(size); int i, rc; char *vaddr; if (size == 0) return 0; addr = (void *) PAGEADDR(addr); if (!valid_range(addr, size)) return -EINVAL; if (type & (MEM_DECOMMIT | MEM_RELEASE)) { vaddr = (char *) addr; for (i = 0; i < pages; i++) { if (page_directory_mapped(vaddr)) { pte_t flags = get_page_flags(vaddr); unsigned long pfn = BTOP(virt2phys(vaddr)); if (flags & PT_FILE) { handle_t h = (flags & PT_PRESENT) ? pfdb[pfn].owner : pfn; struct filemap *newfm = (struct filemap *) hlookup(h); if (newfm != fm) { if (fm) { if (fm->pages == 0) { rc = free_filemap(fm); } else { rc = unlock_filemap(fm); } if (rc < 0) return rc; } fm = newfm; rc = wait_for_object(fm, INFINITE); if (rc < 0) return rc; } fm->pages--; unmap_page(vaddr); if (flags & PT_PRESENT) free_pageframe(pfn); } else if (flags & PT_PRESENT) { unmap_page(vaddr); free_pageframe(pfn); } } vaddr += PAGESIZE; } } if (fm) { if (fm->pages == 0) { rc = free_filemap(fm); } else { rc = unlock_filemap(fm); } if (rc < 0) return rc; } else if (type & MEM_RELEASE) { rmap_free(vmap, BTOP(addr), pages); } return 0; }
int vmsync(void *addr, unsigned long size) { struct filemap *fm = NULL; int pages = PAGES(size); int i, rc; char *vaddr; if (size == 0) return 0; addr = (void *) PAGEADDR(addr); if (!valid_range(addr, size)) return -EINVAL; vaddr = (char *) addr; for (i = 0; i < pages; i++) { if (page_directory_mapped(vaddr)) { pte_t flags = get_page_flags(vaddr); if ((flags & (PT_FILE | PT_PRESENT | PT_DIRTY)) == (PT_FILE | PT_PRESENT | PT_DIRTY)) { unsigned long pfn = BTOP(virt2phys(vaddr)); struct filemap *newfm = (struct filemap *) hlookup(pfdb[pfn].owner); if (newfm != fm) { if (fm) { rc = unlock_filemap(fm); if (rc < 0) return rc; } fm = newfm; rc = wait_for_object(fm, INFINITE); if (rc < 0) return rc; } rc = save_file_page(fm, vaddr); if (rc < 0) return rc; } } vaddr += PAGESIZE; } if (fm) { rc = unlock_filemap(fm); if (rc < 0) return rc; } return 0; }
int vmprotect(void *addr, unsigned long size, int protect) { int pages = PAGES(size); int i; char *vaddr; unsigned long flags; if (size == 0) return 0; addr = (void *) PAGEADDR(addr); if (!valid_range(addr, size)) return -EINVAL; flags = pte_flags_from_protect(protect); if (flags == 0xFFFFFFFF) return -EINVAL; vaddr = (char *) addr; for (i = 0; i < pages; i++) { if (page_mapped(vaddr)) { set_page_flags(vaddr, (get_page_flags(vaddr) & ~PT_PROTECTMASK) | flags); } vaddr += PAGESIZE; } return 0; }
static bool validate_request (struct connection *conn, uint16_t cmd, uint16_t flags, uint64_t offset, uint32_t count, uint32_t *error) { /* Readonly connection? */ if (conn->readonly && (cmd == NBD_CMD_WRITE || cmd == NBD_CMD_TRIM || cmd == NBD_CMD_WRITE_ZEROES)) { nbdkit_error ("invalid request: %s: write request on readonly connection", name_of_nbd_cmd (cmd)); *error = EROFS; return false; } /* Validate cmd, offset, count. */ switch (cmd) { case NBD_CMD_READ: case NBD_CMD_CACHE: case NBD_CMD_WRITE: case NBD_CMD_TRIM: case NBD_CMD_WRITE_ZEROES: case NBD_CMD_BLOCK_STATUS: if (!valid_range (conn, offset, count)) { /* XXX Allow writes to extend the disk? */ nbdkit_error ("invalid request: %s: offset and count are out of range: " "offset=%" PRIu64 " count=%" PRIu32, name_of_nbd_cmd (cmd), offset, count); *error = (cmd == NBD_CMD_WRITE || cmd == NBD_CMD_WRITE_ZEROES) ? ENOSPC : EINVAL; return false; } break; case NBD_CMD_FLUSH: if (offset != 0 || count != 0) { nbdkit_error ("invalid request: %s: expecting offset and count = 0", name_of_nbd_cmd (cmd)); *error = EINVAL; return false; } break; default: nbdkit_error ("invalid request: unknown command (%" PRIu32 ") ignored", cmd); *error = EINVAL; return false; } /* Validate flags */ if (flags & ~(NBD_CMD_FLAG_FUA | NBD_CMD_FLAG_NO_HOLE | NBD_CMD_FLAG_DF | NBD_CMD_FLAG_REQ_ONE)) { nbdkit_error ("invalid request: unknown flag (0x%x)", flags); *error = EINVAL; return false; } if ((flags & NBD_CMD_FLAG_NO_HOLE) && cmd != NBD_CMD_WRITE_ZEROES) { nbdkit_error ("invalid request: NO_HOLE flag needs WRITE_ZEROES request"); *error = EINVAL; return false; } if (flags & NBD_CMD_FLAG_DF) { if (cmd != NBD_CMD_READ) { nbdkit_error ("invalid request: DF flag needs READ request"); *error = EINVAL; return false; } if (!conn->structured_replies) { nbdkit_error ("invalid request: " "%s: structured replies was not negotiated", name_of_nbd_cmd (cmd)); *error = EINVAL; return false; } } if ((flags & NBD_CMD_FLAG_REQ_ONE) && cmd != NBD_CMD_BLOCK_STATUS) { nbdkit_error ("invalid request: REQ_ONE flag needs BLOCK_STATUS request"); *error = EINVAL; return false; } if (!conn->can_fua && (flags & NBD_CMD_FLAG_FUA)) { nbdkit_error ("invalid request: FUA flag not supported"); *error = EINVAL; return false; } /* Refuse over-large read and write requests. */ if ((cmd == NBD_CMD_WRITE || cmd == NBD_CMD_READ) && count > MAX_REQUEST_SIZE) { nbdkit_error ("invalid request: %s: data request is too large (%" PRIu32 " > %d)", name_of_nbd_cmd (cmd), count, MAX_REQUEST_SIZE); *error = ENOMEM; return false; } /* Flush allowed? */ if (!conn->can_flush && cmd == NBD_CMD_FLUSH) { nbdkit_error ("invalid request: %s: flush operation not supported", name_of_nbd_cmd (cmd)); *error = EINVAL; return false; } /* Trim allowed? */ if (!conn->can_trim && cmd == NBD_CMD_TRIM) { nbdkit_error ("invalid request: %s: trim operation not supported", name_of_nbd_cmd (cmd)); *error = EINVAL; return false; } /* Zero allowed? */ if (!conn->can_zero && cmd == NBD_CMD_WRITE_ZEROES) { nbdkit_error ("invalid request: %s: write zeroes operation not supported", name_of_nbd_cmd (cmd)); *error = EINVAL; return false; } /* Cache allowed? */ if (!conn->can_cache && cmd == NBD_CMD_CACHE) { nbdkit_error ("invalid request: %s: cache operation not supported", name_of_nbd_cmd (cmd)); *error = EINVAL; return false; } /* Block status allowed? */ if (cmd == NBD_CMD_BLOCK_STATUS) { if (!conn->structured_replies) { nbdkit_error ("invalid request: " "%s: structured replies was not negotiated", name_of_nbd_cmd (cmd)); *error = EINVAL; return false; } if (!conn->meta_context_base_allocation) { nbdkit_error ("invalid request: " "%s: base:allocation was not negotiated", name_of_nbd_cmd (cmd)); *error = EINVAL; return false; } } return true; /* Command validates. */ }
int gmatch(const char *s, const char *p) { const char *olds; wchar_t scc, c; int n; wchar_t cl; olds = s; n = mbtowc(&cl, s, MB_LEN_MAX); if (n <= 0) { s++; scc = n; } else { scc = cl; s += n; } n = mbtowc(&cl, p, MB_LEN_MAX); if (n < 0) return (0); if (n == 0) return (scc == 0); p += n; c = cl; switch (c) { case '[': if (scc <= 0) return (0); { int ok; wchar_t lc = 0; int notflag = 0; ok = 0; if (*p == '!') { notflag = 1; p++; } Popwchar(p, c); do { if (c == '-' && lc && *p != ']') { Popwchar(p, c); if (c == '\\') { Popwchar(p, c); } if (notflag) { if (!multibyte || valid_range(lc, c)) { if (scc < lc || scc > c) ok++; else return (0); } } else { if (!multibyte || valid_range(lc, c)) if (lc <= scc && scc <= c) ok++; } } else if (c == '\\') { /* skip to quoted character */ Popwchar(p, c); } lc = c; if (notflag) { if (scc != lc) ok++; else return (0); } else { if (scc == lc) ok++; } Popwchar(p, c); } while (c != ']'); return (ok ? gmatch(s, p) : 0); } case '\\': /* skip to quoted character and see if it matches */ Popwchar(p, c); default: if (c != scc) return (0); /*FALLTHRU*/ case '?': return (scc > 0 ? gmatch(s, p) : 0); case '*': while (*p == '*') p++; if (*p == 0) return (1); s = olds; while (*s) { if (gmatch(s, p)) return (1); n = mbtowc(&cl, s, MB_LEN_MAX); if (n < 0) /* skip past illegal byte sequence */ s++; else s += n; } return (0); } }
void *vmalloc(void *addr, unsigned long size, int type, int protect, unsigned long tag, int *rc) { int pages = PAGES(size); unsigned long flags = pte_flags_from_protect(protect); int i; if (rc) *rc = 0; if (size == 0) { if (rc) *rc = -EINVAL; return NULL; } if ((type & MEM_COMMIT) != 0 && flags == 0xFFFFFFFF) { if (rc) *rc = -EINVAL; return NULL; } addr = (void *) PAGEADDR(addr); if (!addr && (type & MEM_COMMIT) != 0) type |= MEM_RESERVE; if (!tag) tag = 'VM'; if (type & MEM_RESERVE) { if (addr == NULL) { if (type & MEM_ALIGN64K) { addr = (void *) PTOB(rmap_alloc_align(vmap, pages, 64 * 1024 / PAGESIZE)); } else { addr = (void *) PTOB(rmap_alloc(vmap, pages)); } if (addr == NULL) { if (rc) *rc = -ENOMEM; return NULL; } } else { if (rmap_reserve(vmap, BTOP(addr), pages)) { if (rc) *rc = -ENOMEM; return NULL; } } } else { if (!valid_range(addr, size)) { if (rc) *rc = -EFAULT; return NULL; } } if (type & MEM_COMMIT) { char *vaddr; unsigned long pfn; vaddr = (char *) addr; for (i = 0; i < pages; i++) { if (page_mapped(vaddr)) { set_page_flags(vaddr, flags | PT_PRESENT); } else { pfn = alloc_pageframe(tag); if (pfn == 0xFFFFFFFF) { if (rc) *rc = -ENOMEM; return NULL; } map_page(vaddr, pfn, flags | PT_PRESENT); memset(vaddr, 0, PAGESIZE); } vaddr += PAGESIZE; } } return addr; }
char * _compile(const char *sp, char *ep, char *endbuf, int viflag) { wchar_t c; int n; wchar_t d; const char *oldsp; char *lastep; int cclcnt; char bracket[NBRA], *bracketp; int closed; int neg; int alloc; wchar_t lc, cl; int i, cflg; char *expbuf = ep; char *start; regerrno = 0; reglength = 0; lastep = 0; bracketp = bracket; closed = 0; alloc = 0; oldsp = sp; if ((c = *sp++) == '\0') { if (ep == (char *)0 || ep[1] == 0) ERROR(41); goto out; } nbra = 0; if (ep == (char *)0) { /* malloc space */ const char *startsp = oldsp; n = 0; while ((d = *startsp++) != NULL) { if (d == '[') n += 33; /* add room for bitmaps */ } n += 2 * (startsp - oldsp) + 3; if ((ep = malloc(n)) == (char *)0) ERROR(50); expbuf = ep; alloc = 1; endbuf = ep + n; } if (c == '^') *ep++ = 1; else { *ep++ = 0; sp--; } endbuf--; /* avoid extra check for overflow */ for (;;) { if (ep >= endbuf) ERROR(50); Popwchar if (c != '*' && ((c != '\\') || (PEEKC() != '{'))) lastep = ep; if (c == '\0') { *ep++ = CCEOF; if (bracketp != bracket) ERROR(42); goto out; } switch (c) { case '.': *ep++ = CDOT; continue; case '*': if (lastep == 0 || *lastep == CBRA ||*lastep == CKET || *lastep == CBRC || *lastep == CLET) goto defchar; *lastep |= STAR; continue; case '$': /* look one character ahead to see if $ means */ /* to anchor match at end of line */ if ((d = PEEKC()) != '\0') goto defchar; *ep++ = CDOL; continue; case '[': start = ep + 34; if (start > endbuf) ERROR(50); *ep++ = CCL; lc = 0; for (i = 0; i < 32; i++) ep[i] = 0; neg = 0; Popwchar if (c == '^') { neg = 1; Popwchar } if (multibyte) { if (neg) { /* do not negate bitmap for */ /* for multibyte characters */ neg = 0; ep[-1] = NMCCL; /* turn off null byte */ ep[0] |= 01; } else ep[-1] = MCCL; } do { if (c == '\0') ERROR(49); if (c == '-' && lc != 0) { Popwchar if (c == '\0') ERROR(49); if (c == ']') { PLACE('-'); break; } /* * ranges do not span code sets */ if (!multibyte || c <= 0177) while (lc < c) { PLACE(lc); lc++; } else if (valid_range(lc, c) && lc < c) /* insert '-' for range */ *start++ = '-'; if (viflag & 1) lc = 0; else lc = c; } else if (c == '\\' && (viflag & 1) && strchr("\\^-]", PEEKC())) { c = GETC(); lc = c; } else lc = c; /* put eight bit characters into bitmap */ if (!multibyte || c <= 0177 || c <= 0377 && iscntrl((int)c)) PLACE(c); else { /* * insert individual bytes of * multibyte characters after * bitmap */ if (start + n > endbuf) ERROR(50); while (n--) *start++ = *oldsp++; } Popwchar } while (c != ']'); if (neg) { for (cclcnt = 0; cclcnt < 32; cclcnt++) ep[cclcnt] ^= 0377; ep[0] &= 0376; } ep += 32; if (multibyte) { /* * Only allow 256 bytes to * represent multibyte characters * character class */ if (start - ep > MBYTE_SIZE) ERROR(50); *ep = (char)(start - ep); ep = start; } continue; case '\\': Popwchar switch (c) { case '(': if (nbra >= NBRA) ERROR(43); *bracketp++ = nbra; *ep++ = CBRA; *ep++ = nbra++; continue; case ')': if (bracketp <= bracket) ERROR(42); *ep++ = CKET; *ep++ = *--bracketp; closed++; continue; case '{': if (lastep == (char *)0) goto defchar; *lastep |= RNGE; cflg = 0; c = GETC(); nlim: i = 0; do { if ('0' <= c && c <= '9') i = 10 * i + (int)c - '0'; else ERROR(16); } while (((c = GETC()) != '\\') && (c != ',')); if (i > MBYTE_SIZE) ERROR(11); *ep++ = (char)i; if (c == ',') { if (cflg++) ERROR(44); if ((c = GETC()) == '\\') *ep++ = (char)MBYTE_SIZE; else goto nlim; /* get 2'nd number */ } if (GETC() != '}') ERROR(45); if (!cflg) /* one number */ *ep++ = (char)i; else if ((int)(unsigned char)ep[-1] < (int)(unsigned char)ep[-2]) ERROR(46); continue; case 'n': c = '\n'; goto defchar; case '<': *ep++ = CBRC; continue; case '>': *ep++ = CLET; continue; default: if (c >= '1' && c <= '9') { if ((c -= '1') >= closed) ERROR(25); *ep++ = CBACK; *ep++ = (char)c; continue; } } /* Drop through to default to use \ to turn off special chars */ defchar: default: lastep = ep; if (!multibyte || c <= 0177) { /* 8-bit character */ *ep++ = CCHR; *ep++ = (char)c; } else { /* multibyte character */ *ep++ = MCCHR; if (ep + n > endbuf) ERROR(50); while (n--) *ep++ = *oldsp++; } }