]> granicus.if.org Git - sysstat/commitdiff
Fortify use of structures map
authorSebastien GODARD <sysstat@users.noreply.github.com>
Sun, 24 Sep 2017 16:16:35 +0000 (18:16 +0200)
committerSebastien GODARD <sysstat@users.noreply.github.com>
Mon, 25 Sep 2017 15:21:42 +0000 (17:21 +0200)
Add extra checks on *_types_nr[] values read from a file to cope with
possible corrupted files.
*_types_nr[] values give the number of fields of each type (long long,
long, int) composing a structure.

Signed-off-by: Sebastien GODARD <sysstat@users.noreply.github.com>
rd_stats.h
sa.h
sa_common.c
sadf.c
sar.c
svg_stats.c

index f3eda2fbcaffe06dceb90da719839dbc6eb85139..69a9f9065be0ce1e86f4c19cf2b49a1c7ab254bb 100644 (file)
 #define UL_ALIGNMENT_WIDTH     SIZEOF_LONG_64BIT
 #define U_ALIGNMENT_WIDTH      4
 
+#define MAP_SIZE(m)    ((m[0] * ULL_ALIGNMENT_WIDTH) + \
+                        (m[1] * UL_ALIGNMENT_WIDTH) +  \
+                        (m[2] * U_ALIGNMENT_WIDTH))
+
 /*
  * Structure for CPU statistics.
  * In activity buffer: First structure is for global CPU utilisation ("all").
diff --git a/sa.h b/sa.h
index fdb564b4a739fe0f3a7fb0d426c13b859124060d..296ec45fa2c4d89372ab7dec6aeb27f39a973e1f 100644 (file)
--- a/sa.h
+++ b/sa.h
@@ -509,7 +509,7 @@ struct file_activity {
         * Description of the structure containing statistics for the
         * given activity (nr of "long long", nr of "long" and nr of "int").
         */
-       int types_nr[3];
+       unsigned int types_nr[3];
 };
 
 #define FILE_ACTIVITY_SIZE     (sizeof(struct file_activity))
@@ -756,13 +756,13 @@ struct activity {
         * gives the number of "long long" fields composing the structure, then the number
         * of "long" fields, then the number of "int" fields.
         */
-       int gtypes_nr[3];
+       unsigned int gtypes_nr[3];
        /*
         * This array has the same meaning as @gtypes_nr[] above, but the values are those
         * read from current data file. They may be different from those of @gtypes_nr[]
         * because we can read data from a different sysstat version (older or newer).
         */
-       int ftypes_nr[3];
+       unsigned int ftypes_nr[3];
        /*
         * Number of SVG graphs for this activity. The total number of graphs for
         * the activity can be greater though if flag AO_GRAPH_PER_ITEM is set, in
index 5a7493a41553313e3a94e640c95c562306e07f37..2b84e4ba3a626b334676b695f7f4765ec48a3316 100644 (file)
@@ -50,8 +50,8 @@
 int default_file_used = FALSE;
 extern struct act_bitmap cpu_bitmap;
 
-int hdr_types_nr[] = {FILE_HEADER_ULL_NR, FILE_HEADER_UL_NR, FILE_HEADER_U_NR};
-int act_types_nr[] = {FILE_ACTIVITY_ULL_NR, FILE_ACTIVITY_UL_NR, FILE_ACTIVITY_U_NR};
+unsigned int hdr_types_nr[] = {FILE_HEADER_ULL_NR, FILE_HEADER_UL_NR, FILE_HEADER_U_NR};
+unsigned int act_types_nr[] = {FILE_ACTIVITY_ULL_NR, FILE_ACTIVITY_UL_NR, FILE_ACTIVITY_U_NR};
 
 /*
  ***************************************************************************
@@ -993,7 +993,7 @@ void select_default_activity(struct activity *act[])
  * @is64bit    TRUE if data come from a 64-bit machine.
  ***************************************************************************
  */
-void swap_struct(int types_nr[], void *ps, int is64bit)
+void swap_struct(unsigned int types_nr[], void *ps, int is64bit)
 {
        int i;
        uint64_t *x;
@@ -1049,10 +1049,15 @@ void swap_struct(int types_nr[], void *ps, int is64bit)
  *             structure expected by current sysstat version).
  ***************************************************************************
  */
-void remap_struct(int gtypes_nr[], int ftypes_nr[], void *ps, int st_size)
+void remap_struct(unsigned int gtypes_nr[], unsigned int ftypes_nr[],
+                 void *ps, unsigned int st_size)
 {
        int d;
 
+       /* Sanity check */
+       if (MAP_SIZE(ftypes_nr) > st_size)
+               return;
+
        /* Remap [unsigned] long fields */
        d = gtypes_nr[0] - ftypes_nr[0];
        if (d) {
@@ -1521,6 +1526,9 @@ void check_file_actlst(int *ifd, char *dfile, struct activity *act[],
                     (fal->types_nr[2] <= act[p]->gtypes_nr[2])))) {
                        handle_invalid_sa_file(ifd, file_magic, dfile, 0);
                }
+               if (MAP_SIZE(fal->types_nr) > fal->size) {
+                       handle_invalid_sa_file(ifd, file_magic, dfile, 0);
+               }
                for (k = 0; k < 3; k++) {
                        act[p]->ftypes_nr[k] = fal->types_nr[k];
                }
diff --git a/sadf.c b/sadf.c
index 3de2f701225257e193b7990fa363b50b1c7e0787..473e1558286f0243b8e5d78a86743dc96c86699b 100644 (file)
--- a/sadf.c
+++ b/sadf.c
@@ -53,7 +53,7 @@ int endian_mismatch = FALSE;
 /* TRUE if file's data come from a 64 bit machine */
 int arch_64 = FALSE;
 
-int rec_types_nr[] = {RECORD_HEADER_ULL_NR, RECORD_HEADER_UL_NR, RECORD_HEADER_U_NR};
+unsigned int rec_types_nr[] = {RECORD_HEADER_ULL_NR, RECORD_HEADER_UL_NR, RECORD_HEADER_U_NR};
 
 unsigned int flags = 0;
 unsigned int dm_major;         /* Device-mapper major number */
diff --git a/sar.c b/sar.c
index fb42b0fbbd6abdca71ccb950e280a5351e4e9f20..a110a51360c597a0645b25feb6cd712adbbf9912 100644 (file)
--- a/sar.c
+++ b/sar.c
@@ -61,7 +61,7 @@ unsigned int flags = 0;
 unsigned int dm_major; /* Device-mapper major number */
 
 char timestamp[2][TIMESTAMP_LEN];
-int rec_types_nr[] = {RECORD_HEADER_ULL_NR, RECORD_HEADER_UL_NR, RECORD_HEADER_U_NR};
+unsigned int rec_types_nr[] = {RECORD_HEADER_ULL_NR, RECORD_HEADER_UL_NR, RECORD_HEADER_U_NR};
 
 unsigned long avg_count = 0;
 
index d89733b613f27a83b353cf845081b24bbb9ec0f6..2444ed1ac3e02b959de8ab52afa84c470068d636 100644 (file)
@@ -75,7 +75,7 @@ unsigned int svg_colors[] = {0x00cc00, 0xff00bf, 0x00ffff, 0xff0000,
  * @spmax      Array containg the possible new max values for current activity.
  ***************************************************************************
  */
-void save_extrema(int types_nr[], void *cs, void *ps, unsigned long long itv,
+void save_extrema(unsigned int types_nr[], void *cs, void *ps, unsigned long long itv,
                  double *spmin, double *spmax, int g_fields[])
 {
        unsigned long long *lluc, *llup;
@@ -1966,7 +1966,7 @@ __print_funct_t svg_print_disk_stats(struct activity *a, int curr, int action, s
                           "await", "svctm",
                           "%util"};
        int g_fields[] = {0, 1, 2};
-       int local_types_nr[] = {1, 0, 0};
+       unsigned int local_types_nr[] = {1, 0, 0};
        static double *spmin, *spmax;
        static char **out;
        static int *outsize;
@@ -2218,7 +2218,7 @@ __print_funct_t svg_print_net_dev_stats(struct activity *a, int curr, int action
                           "rxcmp/s", "txcmp/s", "rxmcst/s",
                           "%ifutil"};
        int g_fields[] = {0, 1, 2, 3, 4, 5, 6};
-       int local_types_nr[] = {7, 0, 0};
+       unsigned int local_types_nr[] = {7, 0, 0};
        static double *spmin, *spmax;
        static char **out;
        static int *outsize;
@@ -4432,7 +4432,7 @@ __print_funct_t svg_print_huge_stats(struct activity *a, int curr, int action, s
        char *g_title[] = {"~kbhugfree", "~kbhugused",
                           "%hugused"};
        int g_fields[] = {0};
-       int local_types_nr[] = {0, 1, 0};
+       unsigned int local_types_nr[] = {0, 1, 0};
        static double *spmin, *spmax;
        static char **out;
        static int *outsize;