Browse Source

Ticket 47499 - if nsslapd-cachememsize set to the number larger than
the RAM available, should result in proper error message.

Bug Description: The server allows any value to be set for all the cache sizes. If
this value is too large it will basically crash the server.

Fix Description: Do a value verification before allowing the change. Report an
error 53 and a descriptive error string if the value is too large.

https://fedorahosted.org/389/ticket/47499

Reviewed by: nhosoi(Thanks!!)

Mark Reynolds 12 years ago
parent
commit
1e035d1111

+ 1 - 1
ldap/servers/slapd/back-ldbm/dblayer.c

@@ -1112,7 +1112,7 @@ int dblayer_is_cachesize_sane(size_t *cachesize)
      * after the current working set size for this process has been subtracted,
      * then we say that's insane and try to correct.
      */
-    issane = (int)(*cachesize / pagesize) <= (pages - procpages);
+    issane = (int)((*cachesize / pagesize) <= (pages - procpages));
     if (!issane) {
         *cachesize = (size_t)((pages - procpages) * pagesize);
     }

+ 39 - 11
ldap/servers/slapd/back-ldbm/ldbm_config.c

@@ -430,25 +430,31 @@ static int ldbm_config_dbcachesize_set(void *arg, void *value, char *errorbuf, i
 {
     struct ldbminfo *li = (struct ldbminfo *) arg;
     int retval = LDAP_SUCCESS;
-    size_t val = (size_t) value;
+    size_t val = (size_t)value;
 
     if (apply) {
         /* Stop the user configuring a stupidly small cache */
         /* min: 8KB (page size) * def thrd cnts (threadnumber==20). */
 #define DBDEFMINSIZ     500000
         if (val < DBDEFMINSIZ) {
-            LDAPDebug( LDAP_DEBUG_ANY,"WARNING: cache too small, increasing to %dK bytes\n", DBDEFMINSIZ/1000, 0, 0);
+            LDAPDebug( LDAP_DEBUG_ANY,"WARNING: cache too small, increasing to %dK bytes\n",
+                    DBDEFMINSIZ/1000, 0, 0);
             val = DBDEFMINSIZ;
-        } 
-        
+        } else if (!dblayer_is_cachesize_sane(&val)){
+            PR_snprintf(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
+                    "Error: dbcachememsize value is too large.");
+            LDAPDebug( LDAP_DEBUG_ANY,"Error: dbcachememsize value is too large.\n",
+                    0, 0, 0);
+            return LDAP_UNWILLING_TO_PERFORM;
+        }
         if (CONFIG_PHASE_RUNNING == phase) {
             li->li_new_dbcachesize = val;
-            LDAPDebug(LDAP_DEBUG_ANY, "New db cache size will not take affect until the server is restarted\n", 0, 0, 0);
+            LDAPDebug(LDAP_DEBUG_ANY, "New db cache size will not take affect until the server is restarted\n",
+                    0, 0, 0);
         } else {
             li->li_new_dbcachesize = val;
             li->li_dbcachesize = val;
         }
-        
     }
     
     return retval;
@@ -491,13 +497,20 @@ static int ldbm_config_dbncache_set(void *arg, void *value, char *errorbuf, int
 {
     struct ldbminfo *li = (struct ldbminfo *) arg;
     int retval = LDAP_SUCCESS;
-    int val = (int) ((uintptr_t)value);
+    size_t val = (size_t) ((uintptr_t)value);
     
     if (apply) {
         if (val < 0) {
             LDAPDebug( LDAP_DEBUG_ANY,"WARNING: ncache will not take negative value\n", 0, 0, 0);
             val = 0;
         } 
+        if (!dblayer_is_cachesize_sane(&val)){
+            PR_snprintf(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
+                    "Error: dbncache size value is too large.");
+            LDAPDebug( LDAP_DEBUG_ANY,"Error: dbncache size value is too large.\n",
+                    val, 0, 0);
+            return LDAP_UNWILLING_TO_PERFORM;
+        }
         
         if (CONFIG_PHASE_RUNNING == phase) {
             li->li_new_dbncache = val;
@@ -1056,9 +1069,16 @@ static int ldbm_config_db_cache_set(void *arg, void *value, char *errorbuf, int
 {
     struct ldbminfo *li = (struct ldbminfo *) arg;
     int retval = LDAP_SUCCESS;
-    int val = (int) ((uintptr_t)value);
+    size_t val = (size_t) ((uintptr_t)value);
     
     if (apply) {
+        if (!dblayer_is_cachesize_sane(&val)){
+            PR_snprintf(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
+                    "Error: db cachesize value is too large");
+            LDAPDebug( LDAP_DEBUG_ANY,"Error: db cachesize value is too large.\n",
+                    val, 0, 0);
+            return LDAP_UNWILLING_TO_PERFORM;
+        }
         li->li_dblayer_private->dblayer_cache_config = val;
     }
     
@@ -1170,9 +1190,17 @@ static int ldbm_config_import_cachesize_set(void *arg, void *value, char *errorb
                                      int phase, int apply)
 {
     struct ldbminfo *li = (struct ldbminfo *)arg;
-
-    if (apply)
-        li->li_import_cachesize = (size_t)value;
+    size_t val = (size_t)value;
+    if (apply){
+        if (!dblayer_is_cachesize_sane(&val)){
+            PR_snprintf(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
+                    "Error: import cachesize value is too large.");
+            LDAPDebug( LDAP_DEBUG_ANY,"Error: import cachesize value is too large.\n",
+                    0, 0, 0);
+            return LDAP_UNWILLING_TO_PERFORM;
+        }
+        li->li_import_cachesize = val;
+    }
     return LDAP_SUCCESS;
 }
 

+ 15 - 1
ldap/servers/slapd/back-ldbm/ldbm_instance_config.c

@@ -125,6 +125,13 @@ ldbm_instance_config_cachememsize_set(void *arg, void *value, char *errorbuf, in
     /* Do whatever we can to make sure the data is ok. */
 
     if (apply) {
+        if (!dblayer_is_cachesize_sane(&val)){
+            PR_snprintf(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
+                    "Error: cachememsize value is too large.");
+            LDAPDebug( LDAP_DEBUG_ANY,"Error: cachememsize value is too large.\n",
+                    0, 0, 0);
+            return LDAP_UNWILLING_TO_PERFORM;
+        }
         cache_set_max_size(&(inst->inst_cache), val, CACHE_TYPE_ENTRY);
     }
 
@@ -144,11 +151,18 @@ ldbm_instance_config_dncachememsize_set(void *arg, void *value, char *errorbuf,
 {
     ldbm_instance *inst = (ldbm_instance *) arg;
     int retval = LDAP_SUCCESS;
-    size_t val = (size_t) value;
+    size_t val = (size_t)value;
 
     /* Do whatever we can to make sure the data is ok. */
 
     if (apply) {
+        if (!dblayer_is_cachesize_sane(&val)){
+            PR_snprintf(errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
+                    "Error: dncachememsize value is too large.");
+            LDAPDebug( LDAP_DEBUG_ANY,"Error: dncachememsize value is too large.\n",
+                    0, 0, 0);
+            return LDAP_UNWILLING_TO_PERFORM;
+        }
         cache_set_max_size(&(inst->inst_dncache), val, CACHE_TYPE_DN);
     }