]> granicus.if.org Git - imagemagick/commitdiff
Support max-request-limit security policy
authorCristy <urban-warrior@imagemagick.org>
Thu, 13 Jul 2017 14:57:35 +0000 (10:57 -0400)
committerCristy <urban-warrior@imagemagick.org>
Thu, 13 Jul 2017 14:57:35 +0000 (10:57 -0400)
MagickCore/memory.c
config/policy.xml

index c49428d8e094acef7535e75850f9b0f6c44e26c7..70197953421ac80e9975700a5fdd74233b882f1f 100644 (file)
@@ -64,6 +64,7 @@
 #include "MagickCore/resource_.h"
 #include "MagickCore/semaphore.h"
 #include "MagickCore/string_.h"
+#include "MagickCore/string-private.h"
 #include "MagickCore/utility-private.h"
 \f
 /*
@@ -547,8 +548,9 @@ MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
 %                                                                             %
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 %
-%  AcquireVirtualMemory() allocates a pointer to a block of memory at least size
-%  bytes suitably aligned for any use.
+%  AcquireVirtualMemory() allocates a pointer to a block of memory at least
+%  size bytes suitably aligned for any use. In addition to heap, it also
+%  supports memory-mapped and file-based memory-mapped memory requests.
 %
 %  The format of the AcquireVirtualMemory method is:
 %
@@ -561,117 +563,119 @@ MagickExport void *AcquireQuantumMemory(const size_t count,const size_t quantum)
 %    o quantum: the number of bytes in each quantum.
 %
 */
+
+static inline size_t StringToSizeType(const char *string,const double interval)
+{
+  double
+    value;
+
+  value=SiPrefixToDoubleInterval(string,interval);
+  if (value >= (double) MagickULLConstant(~0))
+    return((size_t) MagickULLConstant(~0));
+  return((size_t) value);
+}
+
 MagickExport MemoryInfo *AcquireVirtualMemory(const size_t count,
   const size_t quantum)
 {
+  char
+    *value;
+
   MemoryInfo
     *memory_info;
 
   size_t
     extent;
 
-  static ssize_t
-    virtual_anonymous_memory = (-1);
+  static size_t
+    max_memory_request = 0,
+    virtual_anonymous_memory = 0;
 
   if (HeapOverflowSanityCheck(count,quantum) != MagickFalse)
     return((MemoryInfo *) NULL);
-  memory_info=(MemoryInfo *) MagickAssumeAligned(AcquireAlignedMemory(1,
-    sizeof(*memory_info)));
-  if (memory_info == (MemoryInfo *) NULL)
-    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
-  (void) ResetMagickMemory(memory_info,0,sizeof(*memory_info));
-  extent=count*quantum;
-  memory_info->length=extent;
-  memory_info->signature=MagickCoreSignature;
-  if (virtual_anonymous_memory < 0)
+  if (max_memory_request == 0)
     {
-      char
-        *value;
-
-      /*
-        Does the security policy require anonymous mapping for pixel cache?
-      */
-      virtual_anonymous_memory=0;
+      max_memory_request=(size_t) MagickULLConstant(~0);
+      value=GetPolicyValue("system:max-memory-request");
+      if (value != (char *) NULL)
+        {
+          /*
+            The security policy sets a max memory request limit.
+          */
+          max_memory_request=StringToSizeType(value,100.0);
+          value=DestroyString(value);
+        }
+    }
+  if ((count*quantum) > (size_t) max_memory_request)
+    return((MemoryInfo *) NULL);
+  if (virtual_anonymous_memory == 0)
+    {
+      virtual_anonymous_memory=1;
       value=GetPolicyValue("system:memory-map");
       if (LocaleCompare(value,"anonymous") == 0)
         {
+          /*
+            The security policy sets anonymous mapping for the memory request.
+          */
 #if defined(MAGICKCORE_HAVE_MMAP) && defined(MAP_ANONYMOUS)
-          virtual_anonymous_memory=1;
+          virtual_anonymous_memory=2;
 #endif
         }
       value=DestroyString(value);
     }
-  if (virtual_anonymous_memory <= 0)
+  memory_info=(MemoryInfo *) MagickAssumeAligned(AcquireAlignedMemory(1,
+    sizeof(*memory_info)));
+  if (memory_info == (MemoryInfo *) NULL)
+    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
+  (void) ResetMagickMemory(memory_info,0,sizeof(*memory_info));
+  extent=count*quantum;
+  memory_info->length=extent;
+  memory_info->signature=MagickCoreSignature;
+  if (virtual_anonymous_memory == 1)
     {
-      if (AcquireMagickResource(MemoryResource,extent) != MagickFalse)
-        {
-          memory_info->blob=AcquireAlignedMemory(1,extent);
-          if (memory_info->blob != NULL)
-            {
-              memory_info->type=AlignedVirtualMemory;
-              return(memory_info);
-            }
-        }
-      RelinquishMagickResource(MemoryResource,extent);
+      memory_info->blob=AcquireAlignedMemory(1,extent);
+      if (memory_info->blob != NULL)
+        memory_info->type=AlignedVirtualMemory;
     }
   else
     {
-      if (AcquireMagickResource(MapResource,extent) != MagickFalse)
+      /*
+        Acquire anonymous memory map.
+      */
+      memory_info->blob=MapBlob(-1,IOMode,0,extent);
+      if (memory_info->blob != NULL)
+        memory_info->type=MapVirtualMemory;
+      else
         {
+          int
+            file;
+
           /*
-            Acquire anonymous memory map.
+            Anonymous memory mapping failed, try file-backed memory mapping.
           */
-          memory_info->blob=MapBlob(-1,IOMode,0,extent);
-          if (memory_info->blob != NULL)
-            {
-              memory_info->type=MapVirtualMemory;
-              return(memory_info);
-            }
-          if (AcquireMagickResource(DiskResource,extent) != MagickFalse)
+          file=AcquireUniqueFileResource(memory_info->filename);
+          if (file != -1)
             {
-              int
-                file;
-
-              /*
-                Anonymous memory mapping failed, try file-backed memory mapping.
-                If the MapResource request failed, there is no point in trying
-                file-backed memory mapping.
-              */
-              file=AcquireUniqueFileResource(memory_info->filename);
-              if (file != -1)
-                {
-                  MagickOffsetType
-                    offset;
+              MagickOffsetType
+                offset;
 
-                  offset=(MagickOffsetType) lseek(file,extent-1,SEEK_SET);
-                  if ((offset == (MagickOffsetType) (extent-1)) &&
-                      (write(file,"",1) == 1))
+              offset=(MagickOffsetType) lseek(file,extent-1,SEEK_SET);
+              (void) close(file);
+              if ((offset == (MagickOffsetType) (extent-1)) &&
+                  (write(file,"",1) == 1))
+                {
+                  memory_info->blob=MapBlob(file,IOMode,0,extent);
+                  if (memory_info->blob != NULL)
+                    memory_info->type=MapVirtualMemory;
+                  else
                     {
-                      memory_info->blob=MapBlob(file,IOMode,0,extent);
-                      if (memory_info->blob != NULL)
-                        {
-                          (void) close(file);
-                          memory_info->type=MapVirtualMemory;
-                          return(memory_info);
-                        }
+                      (void) RelinquishUniqueFileResource(
+                        memory_info->filename);
+                      *memory_info->filename='\0';
                     }
-                  /*
-                    File-backed memory mapping fail, delete the temporary file.
-                  */
-                  (void) close(file);
-                  (void) RelinquishUniqueFileResource(memory_info->filename);
-                  *memory_info->filename = '\0';
                 }
             }
-          RelinquishMagickResource(DiskResource,extent);
         }
-      RelinquishMagickResource(MapResource,extent);
-    }
-  if (memory_info->blob == NULL)
-    {
-      memory_info->blob=AcquireMagickMemory(extent);
-      if (memory_info->blob != NULL)
-        memory_info->type=UnalignedVirtualMemory;
     }
   if (memory_info->blob == NULL)
     memory_info=RelinquishVirtualMemory(memory_info);
index 7ee2f2663e2b203ed8f7322be8187afdd33c7c6c..6330084a5ab033ddb328f6fee150a618d040c245 100644 (file)
@@ -58,6 +58,7 @@
   <!-- <policy domain="system" name="shred" value="2"/> -->
   <!-- <policy domain="system" name="precision" value="6"/> -->
   <!-- <policy domain="system" name="memory-map" value="anonymous"/> -->
+  <!-- <policy domain="system" name="max-memory-request" value="256MiB"/> -->
   <!-- <policy domain="resource" name="temporary-path" value="/tmp"/> -->
   <!-- <policy domain="resource" name="memory" value="2GiB"/> -->
   <!-- <policy domain="resource" name="map" value="4GiB"/> -->