Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2003-07-05 22:59:35 +0400
committerCorinna Vinschen <corinna@vinschen.de>2003-07-05 22:59:35 +0400
commitf2d3c47b14afcfc782e8e8ce88e2ab624e87b264 (patch)
tree58e33f7e7127a1d75c83225124c23140f3fc70b6 /winsup/cygwin
parent4b2cbaeefd38dc562dc4ee362033ee2edad06659 (diff)
* 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.
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog13
-rw-r--r--winsup/cygwin/mmap.cc66
2 files changed, 54 insertions, 25 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index fd982faa0..0bc113e5d 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -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.
diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc
index cd974bed1..00ef3e6bc 100644
--- a/winsup/cygwin/mmap.cc
+++ b/winsup/cygwin/mmap.cc
@@ -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 ()))
- return i;
+ {
+ 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,18 +661,13 @@ munmap (caddr_t addr, size_t len)
/* Delete the entry. */
map_list->erase (li);
}
- 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;
+ syscall_printf ("0 = munmap(): %x", addr);
+ return 0;
}
/* Sync file with memory. Ignore flags for now. */