From b94cb20ff990d26ec931c373344c9a8b1dbcc4da Mon Sep 17 00:00:00 2001
From: Mark Reynolds <mreynolds@redhat.com>
Date: Wed, 10 Jul 2013 15:41:47 -0400
Subject: [PATCH] Ticket 47427 - Overflow in nsslapd-disk-monitoring-threshold

Bug Description:  The threshold setting was being stored as an "int" instead
                  of a PRUint64.  Config setting validation was also incomplete.

Fix Description:  Changed the data type to PRUint64 from int, and improved the config
                  validation, and logging.

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

Reviewed by: ?
---
 ldap/servers/slapd/daemon.c     |   48 +++++++++++++++++++-------------------
 ldap/servers/slapd/libglobs.c   |   12 +++++----
 ldap/servers/slapd/proto-slap.h |    2 +-
 ldap/servers/slapd/slap.h       |    2 +-
 4 files changed, 33 insertions(+), 31 deletions(-)

diff --git a/ldap/servers/slapd/daemon.c b/ldap/servers/slapd/daemon.c
index 817fea7..a14cf35 100644
--- a/ldap/servers/slapd/daemon.c
+++ b/ldap/servers/slapd/daemon.c
@@ -641,16 +641,16 @@ disk_mon_get_dirs(char ***list, int logs_critical){
  *  directory.
  */
 char *
-disk_mon_check_diskspace(char **dirs, PRInt64 threshold, PRInt64 *disk_space)
+disk_mon_check_diskspace(char **dirs, PRUint64 threshold, PRUint64 *disk_space)
 {
 #ifdef LINUX
     struct statfs buf;
 #else
     struct statvfs buf;
 #endif
-    PRInt64 worst_disk_space = threshold;
-    PRInt64 freeBytes = 0;
-    PRInt64 blockSize = 0;
+    PRUint64 worst_disk_space = threshold;
+    PRUint64 freeBytes = 0;
+    PRUint64 blockSize = 0;
     char *worst_dir = NULL;
     int hit_threshold = 0;
     int i = 0;
@@ -707,10 +707,10 @@ disk_monitoring_thread(void *nothing)
     char errorbuf[BUFSIZ];
     char **dirs = NULL;
     char *dirstr = NULL;
-    PRInt64 previous_mark = 0;
-    PRInt64 disk_space = 0;
-    PRInt64 threshold = 0;
-    PRInt64 halfway = 0;
+    PRUint64 previous_mark = 0;
+    PRUint64 disk_space = 0;
+    PRUint64 threshold = 0;
+    PRUint64 halfway = 0;
     time_t start = 0;
     time_t now = 0;
     int deleted_rotated_logs = 0;
@@ -792,7 +792,7 @@ disk_monitoring_thread(void *nothing)
          *  Check if we are already critical
          */
         if(disk_space < 4096){ /* 4 k */
-            LDAPDebug(LDAP_DEBUG_ANY, "Disk space is critically low on disk (%s), remaining space: %d Kb.  "
+            LDAPDebug(LDAP_DEBUG_ANY, "Disk space is critically low on disk (%s), remaining space: %" NSPRIu64 " Kb.  "
                 "Signaling slapd for shutdown...\n", dirstr , (disk_space / 1024), 0);
             g_set_shutdown( SLAPI_SHUTDOWN_EXIT );
             return;
@@ -802,7 +802,7 @@ disk_monitoring_thread(void *nothing)
          *  if logging is not critical
          */
         if(verbose_logging != 0 && verbose_logging != LDAP_DEBUG_ANY){
-            LDAPDebug(LDAP_DEBUG_ANY, "Disk space is low on disk (%s), remaining space: %d Kb, "
+            LDAPDebug(LDAP_DEBUG_ANY, "Disk space is low on disk (%s), remaining space: %" NSPRIu64 " Kb, "
                 "temporarily setting error loglevel to zero.\n", dirstr,
                 (disk_space / 1024), 0);
             /* Setting the log level back to zero, actually sets the value to LDAP_DEBUG_ANY */
@@ -814,11 +814,11 @@ disk_monitoring_thread(void *nothing)
          *  access/audit logs, log another error, and continue.
          */
         if(!logs_disabled && !logging_critical){
-                LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb, "
-                    "disabling access and audit logging.\n", dirstr, (disk_space / 1024), 0);
-                config_set_accesslog_enabled(LOGGING_OFF);
-                config_set_auditlog_enabled(LOGGING_OFF);
-                logs_disabled = 1;
+            LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %" NSPRIu64 " Kb, "
+                "disabling access and audit logging.\n", dirstr, (disk_space / 1024), 0);
+            config_set_accesslog_enabled(LOGGING_OFF);
+            config_set_auditlog_enabled(LOGGING_OFF);
+            logs_disabled = 1;
             continue;
         }
         /*
@@ -826,17 +826,17 @@ disk_monitoring_thread(void *nothing)
          *  access/audit logging, then delete the rotated logs, log another error, and continue.
          */
         if(!deleted_rotated_logs && !logging_critical){
-                LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb, "
-                    "deleting rotated logs.\n", dirstr, (disk_space / 1024), 0);
-                log__delete_rotated_logs();
-                deleted_rotated_logs = 1;
+            LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %" NSPRIu64 " Kb, "
+                "deleting rotated logs.\n", dirstr, (disk_space / 1024), 0);
+            log__delete_rotated_logs();
+            deleted_rotated_logs = 1;
             continue;
         }
         /*
          *  Ok, we've done what we can, log a message if we continue to lose available disk space
          */
         if(disk_space < previous_mark){
-            LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %d Kb\n",
+            LDAPDebug(LDAP_DEBUG_ANY, "Disk space is too low on disk (%s), remaining space: %" NSPRIu64 " Kb\n",
                 dirstr, (disk_space / 1024), 0);
         }
         /*
@@ -848,7 +848,7 @@ disk_monitoring_thread(void *nothing)
          *
          */
         if(disk_space < halfway){
-            LDAPDebug(LDAP_DEBUG_ANY, "Disk space on (%s) is too far below the threshold(%d bytes).  "
+            LDAPDebug(LDAP_DEBUG_ANY, "Disk space on (%s) is too far below the threshold(%" NSPRIu64 " bytes).  "
                 "Waiting %d minutes for disk space to be cleaned up before shutting slapd down...\n",
                 dirstr, threshold, (grace_period / 60));
             time(&start);
@@ -870,7 +870,7 @@ disk_monitoring_thread(void *nothing)
                     /*
                      *  Excellent, we are back to acceptable levels, reset everything...
                      */
-                    LDAPDebug(LDAP_DEBUG_ANY, "Available disk space is now acceptable (%d bytes).  Aborting"
+                    LDAPDebug(LDAP_DEBUG_ANY, "Available disk space is now acceptable (%" NSPRIu64 " bytes).  Aborting"
                                               " shutdown, and restoring the log settings.\n",disk_space,0,0);
                     if(logs_disabled && using_accesslog){
                         config_set_accesslog_enabled(LOGGING_ON);
@@ -890,7 +890,7 @@ disk_monitoring_thread(void *nothing)
                     /*
                      *  Disk space is critical, log an error, and shut it down now!
                      */
-                    LDAPDebug(LDAP_DEBUG_ANY, "Disk space is critically low on disk (%s), remaining space: %d Kb."
+                    LDAPDebug(LDAP_DEBUG_ANY, "Disk space is critically low on disk (%s), remaining space: %" NSPRIu64 " Kb."
                         "  Signaling slapd for shutdown...\n", dirstr, (disk_space / 1024), 0);
                     g_set_shutdown( SLAPI_SHUTDOWN_DISKFULL );
                     return;
@@ -907,7 +907,7 @@ disk_monitoring_thread(void *nothing)
             /*
              *  If disk space was freed up we would of detected in the above while loop.  So shut it down.
              */
-            LDAPDebug(LDAP_DEBUG_ANY, "Disk space is still too low (%d Kb).  Signaling slapd for shutdown...\n",
+            LDAPDebug(LDAP_DEBUG_ANY, "Disk space is still too low (%" NSPRIu64 " Kb).  Signaling slapd for shutdown...\n",
                 (disk_space / 1024), 0, 0);
             g_set_shutdown( SLAPI_SHUTDOWN_DISKFULL );
 
diff --git a/ldap/servers/slapd/libglobs.c b/ldap/servers/slapd/libglobs.c
index 12a1e03..c1f92ee 100644
--- a/ldap/servers/slapd/libglobs.c
+++ b/ldap/servers/slapd/libglobs.c
@@ -1667,17 +1667,19 @@ config_set_disk_threshold( const char *attrname, char *value, char *errorbuf, in
 {
     slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
     int retVal = LDAP_SUCCESS;
-    long threshold = 0;
+    PRUint64 threshold = 0;
     char *endp = NULL;
 
     if ( config_value_is_null( attrname, value, errorbuf, 0 )) {
         return LDAP_OPERATIONS_ERROR;
     }
 
-    threshold = strtol(value, &endp, 10);
+    errno = 0;
+    threshold = strtoll(value, &endp, 10);
 
-    if ( *endp != '\0' || threshold < 2048 ) {
-        PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE, "%s: \"%s\" is invalid, threshold must be greater than 2048 and less then %ld",
+    if ( *endp != '\0' || threshold <= 4096 || errno == ERANGE ) {
+        PR_snprintf ( errorbuf, SLAPI_DSE_RETURNTEXT_SIZE,
+            "%s: \"%s\" is invalid, threshold must be greater than 4096 and less then %llu",
             attrname, value, LONG_MAX );
         retVal = LDAP_OPERATIONS_ERROR;
         return retVal;
@@ -4370,7 +4372,7 @@ config_get_disk_grace_period(){
     return retVal;
 }
 
-long
+PRUint64
 config_get_disk_threshold(){
     slapdFrontendConfig_t *slapdFrontendConfig = getFrontendConfig();
     long retVal;
diff --git a/ldap/servers/slapd/proto-slap.h b/ldap/servers/slapd/proto-slap.h
index 447d7d5..25663d2 100644
--- a/ldap/servers/slapd/proto-slap.h
+++ b/ldap/servers/slapd/proto-slap.h
@@ -554,7 +554,7 @@ void config_set_accesslog_enabled(int value);
 void config_set_auditlog_enabled(int value);
 int config_get_accesslog_logging_enabled();
 int config_get_disk_monitoring();
-long config_get_disk_threshold();
+PRUint64 config_get_disk_threshold();
 int config_get_disk_grace_period();
 int config_get_disk_logging_critical();
 int config_get_ndn_cache_count();
diff --git a/ldap/servers/slapd/slap.h b/ldap/servers/slapd/slap.h
index f836b16..fff4646 100644
--- a/ldap/servers/slapd/slap.h
+++ b/ldap/servers/slapd/slap.h
@@ -2327,7 +2327,7 @@ typedef struct _slapdFrontendConfig {
 
   /* disk monitoring */
   slapi_onoff_t disk_monitoring;
-  int disk_threshold;
+  PRUint64 disk_threshold;
   int disk_grace_period;
   slapi_onoff_t disk_logging_critical;
 
-- 
1.7.1

