Index: kernel/generic/src/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision 466e95f7c1e1804072fe2965ba7a828e95259ed5)
+++ kernel/generic/src/mm/as.c	(revision 082b7f1c98926730d2a2ca8eced2348d2d692bc2)
@@ -285,8 +285,9 @@
 /** Check area conflicts with other areas.
  *
- * @param as    Address space.
- * @param addr  Starting virtual address of the area being tested.
- * @param count Number of pages in the area being tested.
- * @param avoid Do not touch this area.
+ * @param as      Address space.
+ * @param addr    Starting virtual address of the area being tested.
+ * @param count   Number of pages in the area being tested.
+ * @param guarded True if the area being tested is protected by guard pages.
+ * @param avoid   Do not touch this area.
  *
  * @return True if there is no conflict, false otherwise.
@@ -294,5 +295,5 @@
  */
 NO_TRACE static bool check_area_conflicts(as_t *as, uintptr_t addr,
-    size_t count, as_area_t *avoid)
+    size_t count, bool guarded, as_area_t *avoid)
 {
 	ASSERT((addr % PAGE_SIZE) == 0);
@@ -304,5 +305,5 @@
 	if (overlaps(addr, P2SZ(count), (uintptr_t) NULL, PAGE_SIZE))
 		return false;
-	
+
 	/*
 	 * The leaf node is found in O(log n), where n is proportional to
@@ -328,6 +329,34 @@
 		if (area != avoid) {
 			mutex_lock(&area->lock);
+
+			/* If at least one of the two areas are protected
+			 * by the AS_AREA_GUARD flag then we must be sure
+			 * that they are separated by at least one unmapped
+			 * page.
+			 */
+			int const gp = (guarded || 
+			    (area->flags & AS_AREA_GUARD)) ? 1 : 0;
 			
 			if (overlaps(addr, P2SZ(count), area->base,
+			    P2SZ(area->pages + gp))) {
+				mutex_unlock(&area->lock);
+				return false;
+			}
+			
+			mutex_unlock(&area->lock);
+		}
+	}
+	
+	node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);
+	if (node) {
+		area = (as_area_t *) node->value[0];
+		
+		if (area != avoid) {
+			mutex_lock(&area->lock);
+
+			int const gp = (guarded ||
+			    (area->flags & AS_AREA_GUARD)) ? 1 : 0;
+			
+			if (overlaps(addr, P2SZ(count + gp), area->base,
 			    P2SZ(area->pages))) {
 				mutex_unlock(&area->lock);
@@ -339,21 +368,4 @@
 	}
 	
-	node = btree_leaf_node_right_neighbour(&as->as_area_btree, leaf);
-	if (node) {
-		area = (as_area_t *) node->value[0];
-		
-		if (area != avoid) {
-			mutex_lock(&area->lock);
-			
-			if (overlaps(addr, P2SZ(count), area->base,
-			    P2SZ(area->pages))) {
-				mutex_unlock(&area->lock);
-				return false;
-			}
-			
-			mutex_unlock(&area->lock);
-		}
-	}
-	
 	/* Second, check the leaf node. */
 	btree_key_t i;
@@ -365,7 +377,10 @@
 		
 		mutex_lock(&area->lock);
-		
-		if (overlaps(addr, P2SZ(count), area->base,
-		    P2SZ(area->pages))) {
+
+		int const gp = (guarded ||
+		    (area->flags & AS_AREA_GUARD)) ? 1 : 0;
+
+		if (overlaps(addr, P2SZ(count + gp), area->base,
+		    P2SZ(area->pages + gp))) {
 			mutex_unlock(&area->lock);
 			return false;
@@ -392,7 +407,8 @@
  * this function.
  *
- * @param as    Address space.
- * @param bound Lowest address bound.
- * @param size  Requested size of the allocation.
+ * @param as      Address space.
+ * @param bound   Lowest address bound.
+ * @param size    Requested size of the allocation.
+ * @param guarded True if the allocation must be protected by guard pages.
  *
  * @return Address of the beginning of unmapped address space area.
@@ -401,5 +417,5 @@
  */
 NO_TRACE static uintptr_t as_get_unmapped_area(as_t *as, uintptr_t bound,
-    size_t size)
+    size_t size, bool guarded)
 {
 	ASSERT(mutex_locked(&as->lock));
@@ -423,7 +439,15 @@
 	/* First check the bound address itself */
 	uintptr_t addr = ALIGN_UP(bound, PAGE_SIZE);
-	if ((addr >= bound) &&
-	    (check_area_conflicts(as, addr, pages, NULL)))
-		return addr;
+	if (addr >= bound) {
+		if (guarded) {
+			/* Leave an unmapped page between the lower
+			 * bound and the area's start address.
+			 */
+			addr += P2SZ(1);
+		}
+
+		if (check_area_conflicts(as, addr, pages, guarded, NULL))
+			return addr;
+	}
 	
 	/* Eventually check the addresses behind each area */
@@ -439,7 +463,15 @@
 			addr =
 			    ALIGN_UP(area->base + P2SZ(area->pages), PAGE_SIZE);
+
+			if (guarded || area->flags & AS_AREA_GUARD) {
+				/* We must leave an unmapped page
+				 * between the two areas.
+				 */
+				addr += P2SZ(1);
+			}
+
 			bool avail =
 			    ((addr >= bound) && (addr >= area->base) &&
-			    (check_area_conflicts(as, addr, pages, area)));
+			    (check_area_conflicts(as, addr, pages, guarded, area)));
 			
 			mutex_unlock(&area->lock);
@@ -487,9 +519,11 @@
 	if ((flags & AS_AREA_EXEC) && (flags & AS_AREA_WRITE))
 		return NULL;
+
+	bool const guarded = flags & AS_AREA_GUARD;
 	
 	mutex_lock(&as->lock);
 	
 	if (*base == (uintptr_t) -1) {
-		*base = as_get_unmapped_area(as, bound, size);
+		*base = as_get_unmapped_area(as, bound, size, guarded);
 		if (*base == (uintptr_t) -1) {
 			mutex_unlock(&as->lock);
@@ -497,6 +531,6 @@
 		}
 	}
-	
-	if (!check_area_conflicts(as, *base, pages, NULL)) {
+
+	if (!check_area_conflicts(as, *base, pages, guarded, NULL)) {
 		mutex_unlock(&as->lock);
 		return NULL;
@@ -778,5 +812,6 @@
 		 * Check for overlaps with other address space areas.
 		 */
-		if (!check_area_conflicts(as, address, pages, area)) {
+		bool const guarded = area->flags & AS_AREA_GUARD;
+		if (!check_area_conflicts(as, address, pages, guarded, area)) {
 			mutex_unlock(&area->lock);
 			mutex_unlock(&as->lock);
