* 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
return socket connection state.

View File

@ -270,7 +270,8 @@ public:
void erase (int i);
void erase ();
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 ()
@ -323,13 +324,24 @@ list::match (_off64_t off, DWORD len)
/* Used in munmap() */
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)
if (addr >= recs[i].get_address ()
&& addr + len <= recs[i].get_address ()
+ (PAGE_CNT (recs[i].get_size ()) * getpagesize ()))
{
low = (addr >= recs[i].get_address ()) ? addr : recs[i].get_address ();
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 -1;
}
@ -486,6 +498,16 @@ mmap64 (caddr_t addr, size_t len, int prot, int flags, int fd, _off64_t off)
DWORD high;
DWORD low = GetFileSize (fh->get_handle (), &high);
_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;
if (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);
}
/* munmap () removes an mmapped area. It insists that base area
requested is the same as that mmapped, error if not. */
/* munmap () removes all mmapped pages between addr and addr+len. */
extern "C" int
munmap (caddr_t addr, size_t len)
{
syscall_printf ("munmap (addr %x, len %d)", addr, len);
/* Error conditions according to SUSv2 */
if (((DWORD)addr % getpagesize ()) || !len)
/* Error conditions according to SUSv3 */
if (!addr || ((DWORD)addr % getpagesize ()) || !len
|| IsBadReadPtr (addr, len))
{
set_errno (EINVAL);
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");
/* Check if a mmap'ed area was ever created */
if (mmapped_areas == NULL)
{
syscall_printf ("-1 = munmap(): mmapped_areas == NULL");
set_errno (EINVAL);
ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "munmap");
return -1;
return 0;
}
/* Iterate through the map, looking for the mmapped area.
Error if not found. */
/* Iterate through the map, unmap pages between addr and addr+len
in all maps. */
for (int it = 0; it < mmapped_areas->nlists; ++it)
{
@ -626,10 +646,13 @@ munmap (caddr_t addr, size_t len)
if (map_list)
{
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;
if (rec->unmap_map (addr, len))
if (rec->unmap_map (u_addr, u_len))
{
fhandler_base *fh = rec->alloc_fh ();
fh->munmap (rec->get_handle (), addr, len);
@ -638,19 +661,14 @@ munmap (caddr_t addr, size_t len)
/* Delete the entry. */
map_list->erase (li);
}
}
}
}
ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "munmap");
syscall_printf ("0 = munmap(): %x", addr);
ReleaseResourceLock (LOCK_MMAP_LIST, WRITE_LOCK | READ_LOCK, "munmap");
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. */