Exemple #1
0
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;
}
Exemple #2
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;
}
Exemple #3
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;
}
Exemple #4
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. */
}
Exemple #5
0
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);
	}
}
Exemple #6
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;
}
Exemple #7
0
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++;
			}
		}