* mmap.cc (list::match): Add parameters to return valid address and

length back to munmap().  Evaluate intersection between given
	area and mapped area and return it, if any.
	(mmap64): On regular files, don't allow mappings beginning beyond
	EOF.  Return with errno set to ENXIO instead.
	(munmap): Rewrite SUSv3 conformant.  Check if given memory area is
	valid.  Unmap all maps inside given memory area.  Don't return error
	if no mapping has been unmapped.
This commit is contained in:
Corinna Vinschen 2003-07-05 18:59:35 +00:00
parent 4b2cbaeefd
commit f2d3c47b14
2 changed files with 54 additions and 25 deletions

View File

@ -1,4 +1,15 @@
2003-07-04 N Stephens <nigel@mips.com> 2003-07-05 Corinna Vinschen <corinna@vinschen.de>
* mmap.cc (list::match): Add parameters to return valid address and
length back to munmap(). Evaluate intersection between given
area and mapped area and return it, if any.
(mmap64): On regular files, don't allow mappings beginning beyond
EOF. Return with errno set to ENXIO instead.
(munmap): Rewrite SUSv3 conformant. Check if given memory area is
valid. Unmap all maps inside given memory area. Don't return error
if no mapping has been unmapped.
2003-07-05 N Stephens <nigel@mips.com>
* fhandler.h (fhandler_socket::get_connect_state): New method to * fhandler.h (fhandler_socket::get_connect_state): New method to
return socket connection state. return socket connection state.

View File

@ -270,7 +270,8 @@ public:
void erase (int i); void erase (int i);
void erase (); void erase ();
mmap_record *match (_off64_t off, DWORD len); mmap_record *match (_off64_t off, DWORD len);
long match (caddr_t addr, DWORD len, long start); long match (caddr_t addr, DWORD len, caddr_t &m_addr, DWORD &m_len,
long start);
}; };
list::list () list::list ()
@ -323,13 +324,24 @@ list::match (_off64_t off, DWORD len)
/* Used in munmap() */ /* Used in munmap() */
long long
list::match (caddr_t addr, DWORD len, _off_t start) list::match (caddr_t addr, DWORD len, caddr_t &m_addr, DWORD &m_len,
_off_t start)
{ {
caddr_t low, high;
for (int i = start + 1; i < nrecs; ++i) for (int i = start + 1; i < nrecs; ++i)
if (addr >= recs[i].get_address () {
&& addr + len <= recs[i].get_address () low = (addr >= recs[i].get_address ()) ? addr : recs[i].get_address ();
+ (PAGE_CNT (recs[i].get_size ()) * getpagesize ())) high = recs[i].get_address ()
+ (PAGE_CNT (recs[i].get_size ()) * getpagesize ());
high = (addr + len < high) ? addr + len : high;
if (low < high)
{
m_addr = low;
m_len = high - low;
return i; return i;
}
}
return -1; return -1;
} }
@ -486,6 +498,16 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off)
DWORD high; DWORD high;
DWORD low = GetFileSize (fh->get_handle (), &high); DWORD low = GetFileSize (fh->get_handle (), &high);
_off64_t fsiz = ((_off64_t)high << 32) + low; _off64_t fsiz = ((_off64_t)high << 32) + low;
/* Don't allow mappings beginning beyond EOF since Windows can't
handle that POSIX like. FIXME: Still looking for a good idea
to allow that nevertheless. */
if (gran_off >= fsiz)
{
set_errno (ENXIO);
ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK,
"mmap");
return MAP_FAILED;
}
fsiz -= gran_off; fsiz -= gran_off;
if (gran_len > fsiz) if (gran_len > fsiz)
gran_len = fsiz; gran_len = fsiz;
@ -591,16 +613,16 @@ mmap (caddr_t addr, size_t len, int prot, int flags, int fd, _off_t off)
return mmap64 (addr, len, prot, flags, fd, (_off64_t)off); return mmap64 (addr, len, prot, flags, fd, (_off64_t)off);
} }
/* munmap () removes an mmapped area. It insists that base area /* munmap () removes all mmapped pages between addr and addr+len. */
requested is the same as that mmapped, error if not. */
extern "C" int extern "C" int
munmap (caddr_t addr, size_t len) munmap (caddr_t addr, size_t len)
{ {
syscall_printf ("munmap (addr %x, len %d)", addr, len); syscall_printf ("munmap (addr %x, len %d)", addr, len);
/* Error conditions according to SUSv2 */ /* Error conditions according to SUSv3 */
if (((DWORD)addr % getpagesize ()) || !len) if (!addr || ((DWORD)addr % getpagesize ()) || !len
|| IsBadReadPtr (addr, len))
{ {
set_errno (EINVAL); set_errno (EINVAL);
syscall_printf ("-1 = munmap(): Invalid parameters"); syscall_printf ("-1 = munmap(): Invalid parameters");
@ -608,17 +630,15 @@ munmap (caddr_t addr, size_t len)
} }
SetResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "munmap"); SetResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "munmap");
/* Check if a mmap'ed area was ever created */
if (mmapped_areas == NULL) if (mmapped_areas == NULL)
{ {
syscall_printf ("-1 = munmap(): mmapped_areas == NULL"); syscall_printf ("-1 = munmap(): mmapped_areas == NULL");
set_errno (EINVAL);
ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "munmap"); ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "munmap");
return -1; return 0;
} }
/* Iterate through the map, looking for the mmapped area. /* Iterate through the map, unmap pages between addr and addr+len
Error if not found. */ in all maps. */
for (int it = 0; it < mmapped_areas->nlists; ++it) for (int it = 0; it < mmapped_areas->nlists; ++it)
{ {
@ -626,10 +646,13 @@ munmap (caddr_t addr, size_t len)
if (map_list) if (map_list)
{ {
long li = -1; long li = -1;
if ((li = map_list->match(addr, len, li)) >= 0) caddr_t u_addr;
DWORD u_len;
while ((li = map_list->match(addr, len, u_addr, u_len, li)) >= 0)
{ {
mmap_record *rec = map_list->recs + li; mmap_record *rec = map_list->recs + li;
if (rec->unmap_map (addr, len)) if (rec->unmap_map (u_addr, u_len))
{ {
fhandler_base *fh = rec->alloc_fh (); fhandler_base *fh = rec->alloc_fh ();
fh->munmap (rec->get_handle (), addr, len); fh->munmap (rec->get_handle (), addr, len);
@ -638,18 +661,13 @@ munmap (caddr_t addr, size_t len)
/* Delete the entry. */ /* Delete the entry. */
map_list->erase (li); map_list->erase (li);
} }
}
}
}
ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "munmap");
syscall_printf ("0 = munmap(): %x", addr); syscall_printf ("0 = munmap(): %x", addr);
ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "munmap");
return 0; return 0;
}
}
}
set_errno (EINVAL);
syscall_printf ("-1 = munmap(): EINVAL");
ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "munmap");
return -1;
} }
/* Sync file with memory. Ignore flags for now. */ /* Sync file with memory. Ignore flags for now. */