Browse Source

Fix different kinds of issues with string buffers and pointers

- Use NAME_MAX and PATH_MAX instead of hardcoded values
- Allow paths to be longer than 256 chars
- Check pointers everywhere
- Use strncpy/snprintf instead of strcpy/sprintf
- Validate controllers' name (-s flag + a very long name -> bad things happening)
- Get rid of globals for dir iteration
Abdullah ibn Nadjo 7 years ago
parent
commit
f62503b299
2 changed files with 141 additions and 83 deletions
  1. 6
    10
      include/light.h
  2. 135
    73
      src/light.c

+ 6
- 10
include/light.h View File

@@ -5,6 +5,7 @@
5 5
 
6 6
 #include <sys/types.h>
7 7
 #include <dirent.h>
8
+#include <linux/limits.h>
8 9
 
9 10
 #define LIGHT_VER_MAJOR 0
10 11
 #define LIGHT_VER_MINOR 9
@@ -64,7 +65,7 @@ typedef enum LIGHT_VAL_MODE {
64 65
 typedef struct light_runtimeArguments_s {
65 66
   /* Which controller to use */
66 67
   LIGHT_CTRL_MODE controllerMode;
67
-  char            specifiedController[256];
68
+  char            specifiedController[NAME_MAX + 1];
68 69
 
69 70
   /* What to do with the controller */
70 71
   LIGHT_OP_MODE   operationMode;
@@ -81,11 +82,6 @@ typedef struct light_runtimeArguments_s {
81 82
 
82 83
 } light_runtimeArguments, *light_runtimeArguments_p;
83 84
 
84
-/* -- Global variables that handles iterating controllers -- */
85
-struct dirent *light_iterator;
86
-DIR           *light_iteratorDir;
87
-char          light_currentController[256];
88
-
89 85
 /* -- Global variable holding the settings for the current run -- */
90 86
 light_runtimeArguments light_Configuration;
91 87
 
@@ -116,9 +112,11 @@ void light_free();
116 112
 /* SECTION: Controller functionality */
117 113
 
118 114
 /* WARNING: `buffer` HAS to be freed by the user if not null once returned!
119
- * Size is always 256 */
115
+ * Size is always NAME_MAX + 1 */
120 116
 LIGHT_BOOL light_genPath(char const *controller, LIGHT_TARGET target, LIGHT_FIELD type, char **buffer);
121 117
 
118
+LIGHT_BOOL light_validControllerName(char const *controller);
119
+
122 120
 LIGHT_BOOL light_getBrightness(char const *controller, unsigned long *v);
123 121
 
124 122
 LIGHT_BOOL light_getMaxBrightness(char const *controller, unsigned long *v);
@@ -127,9 +125,7 @@ LIGHT_BOOL light_setBrightness(char const *controller, unsigned long v);
127 125
 
128 126
 LIGHT_BOOL light_controllerAccessible(char const *controller);
129 127
 
130
-LIGHT_BOOL light_iterateControllers(void);
131
-
132
-/* WARNING: `controller` HAS to be at least 256 bytes */
128
+/* WARNING: `controller` HAS to be at most NAME_MAX, otherwise fails */
133 129
 LIGHT_BOOL light_getBestController(char *controller);
134 130
 
135 131
 LIGHT_BOOL light_getMinCap(char const *controller, LIGHT_BOOL *hasMinCap, unsigned long *minCap);

+ 135
- 73
src/light.c View File

@@ -11,7 +11,7 @@
11 11
 void light_defaultConfig()
12 12
 {
13 13
   light_Configuration.controllerMode         = LIGHT_AUTO;
14
-  memset(&light_Configuration.specifiedController, '\0', 256);
14
+  memset(&light_Configuration.specifiedController, '\0', NAME_MAX + 1);
15 15
   light_Configuration.operationMode          = LIGHT_GET;
16 16
   light_Configuration.valueMode              = LIGHT_PERCENT;
17 17
   light_Configuration.specifiedValueRaw      = 0;
@@ -74,8 +74,6 @@ LIGHT_BOOL light_parseArguments(int argc, char** argv)
74 74
   LIGHT_BOOL ctrlSet = FALSE;
75 75
   LIGHT_BOOL valSet = FALSE;
76 76
 
77
-  unsigned long specLen = 0;
78
-
79 77
   while((currFlag = getopt(argc, argv, "HhVGSAULIObmclkas:prv:")) != -1)
80 78
   {
81 79
     switch(currFlag)
@@ -157,15 +155,13 @@ LIGHT_BOOL light_parseArguments(int argc, char** argv)
157 155
           light_printHelp();
158 156
         }
159 157
 
160
-        specLen = strlen(optarg);
161
-        if(specLen > 255)
158
+        if(!light_validControllerName(optarg))
162 159
         {
163
-          specLen = 255;
160
+          fprintf(stderr, "can't handle controller '%s'\n", optarg);
161
+          return FALSE;
164 162
         }
165
-
166
-        strncpy(light_Configuration.specifiedController, optarg, specLen);
167
-
168
-        light_Configuration.specifiedController[255] = '\0';
163
+        strncpy(light_Configuration.specifiedController, optarg, NAME_MAX);
164
+        light_Configuration.specifiedController[NAME_MAX] = '\0';
169 165
         break;
170 166
       /* -- Value modes -- */
171 167
       case 'p':
@@ -573,58 +569,92 @@ void light_free()
573 569
 
574 570
 }
575 571
 
572
+LIGHT_BOOL light_validControllerName(char const *controller)
573
+{
574
+  if(!controller)
575
+  {
576
+    return FALSE;
577
+  }
578
+
579
+  if(strlen(controller) > NAME_MAX)
580
+  {
581
+    LIGHT_WARN_FMT("controller \"%s\"'s name is too long", controller);
582
+    return FALSE;
583
+  }
584
+  return TRUE;
585
+}
586
+
576 587
 LIGHT_BOOL light_genPath(char const *controller, LIGHT_TARGET target, LIGHT_FIELD type, char **buffer)
577 588
 {
578
-  char* returner = malloc(256);
589
+  char* returner;
579 590
   int spfVal = -1;
580 591
 
581
-  if(returner == NULL)
592
+  if(!light_validControllerName(controller))
593
+  {
594
+    LIGHT_ERR("invalid controller, couldn't generate path");
595
+    return FALSE;
596
+  }
597
+
598
+  if(!buffer)
599
+  {
600
+    LIGHT_ERR("a valid buffer is required");
601
+    return FALSE;
602
+  }
603
+  *buffer = NULL;
604
+
605
+  /* PATH_MAX define includes the '\0' character, so no + 1 here*/
606
+  if((returner = malloc(PATH_MAX)) == NULL)
582 607
   {
583 608
     LIGHT_MEMERR();
584
-    buffer = NULL;
585 609
     return FALSE;
586 610
   }
587 611
 
588
-  memset(returner, '\0', 256);
589 612
   if(target == LIGHT_BACKLIGHT)
590 613
   {
591 614
     switch(type)
592 615
     {
593 616
       case LIGHT_BRIGHTNESS:
594
-        spfVal = sprintf(returner, "/sys/class/backlight/%s/brightness", controller);
617
+        spfVal = snprintf(returner, PATH_MAX, "/sys/class/backlight/%s/brightness", controller);
595 618
         break;
596 619
       case LIGHT_MAX_BRIGHTNESS:
597
-        spfVal = sprintf(returner, "/sys/class/backlight/%s/max_brightness", controller);
620
+        spfVal = snprintf(returner, PATH_MAX, "/sys/class/backlight/%s/max_brightness", controller);
598 621
         break;
599 622
       case LIGHT_MIN_CAP:
600
-        spfVal = sprintf(returner, "/etc/light/mincap/%s", controller);
623
+        spfVal = snprintf(returner, PATH_MAX, "/etc/light/mincap/%s", controller);
601 624
         break;
602 625
       case LIGHT_SAVERESTORE:
603
-        spfVal = sprintf(returner, "/etc/light/save/%s", controller);
626
+        spfVal = snprintf(returner, PATH_MAX, "/etc/light/save/%s", controller);
604 627
         break;
605 628
     }
606 629
   }else{
607 630
     switch(type)
608 631
     {
609 632
       case LIGHT_BRIGHTNESS:
610
-        spfVal = sprintf(returner, "/sys/class/leds/%s/brightness", controller);
633
+        spfVal = snprintf(returner, PATH_MAX, "/sys/class/leds/%s/brightness", controller);
611 634
         break;
612 635
       case LIGHT_MAX_BRIGHTNESS:
613
-        spfVal = sprintf(returner, "/sys/class/leds/%s/max_brightness", controller);
636
+        spfVal = snprintf(returner, PATH_MAX, "/sys/class/leds/%s/max_brightness", controller);
614 637
         break;
615 638
       case LIGHT_MIN_CAP:
616
-        spfVal = sprintf(returner, "/etc/light/mincap/kbd/%s", controller);
639
+        spfVal = snprintf(returner, PATH_MAX, "/etc/light/mincap/kbd/%s", controller);
617 640
         break;
618 641
       case LIGHT_SAVERESTORE:
619
-        spfVal = sprintf(returner, "/etc/light/save/kbd/%s", controller);
642
+        spfVal = snprintf(returner, PATH_MAX, "/etc/light/save/kbd/%s", controller);
620 643
         break;
621 644
     }
622 645
   }
646
+
623 647
   if(spfVal < 0)
624 648
   {
625
-    LIGHT_ERR("sprintf failed");
649
+    LIGHT_ERR("snprintf failed");
626 650
     free(returner);
627
-    buffer = NULL;
651
+    return FALSE;
652
+  }
653
+
654
+  /* PATH_MAX define includes the '\0' character, so - 1 here*/
655
+  if(spfVal > PATH_MAX - 1)
656
+  {
657
+    LIGHT_ERR("generated path is too long to be handled");
628 658
     return FALSE;
629 659
   }
630 660
 
@@ -769,77 +799,103 @@ LIGHT_BOOL light_controllerAccessible(char const *controller)
769 799
   return TRUE;
770 800
 }
771 801
 
772
-LIGHT_BOOL light_iterateControllers()
802
+LIGHT_BOOL light_prepareControllerIteration(DIR **dir)
773 803
 {
774
-  LIGHT_BOOL dotsKilled = FALSE;
804
+  if(!dir)
805
+  {
806
+    LIGHT_ERR("specified dir was NULL");
807
+    return FALSE;
808
+  }
775 809
 
776
-  if(light_iteratorDir == NULL)
810
+  if(light_Configuration.target == LIGHT_KEYBOARD)
777 811
   {
778
-    if(light_Configuration.target == LIGHT_KEYBOARD)
779
-    {
780
-      light_iteratorDir = opendir("/sys/class/leds");
781
-    }
782
-    else
783
-    {
784
-      light_iteratorDir = opendir("/sys/class/backlight");
785
-    }
786
-    if(light_iteratorDir == NULL)
787
-    {
788
-      LIGHT_ERR("could not open backlight or leds directory in /sys/class");
789
-      return FALSE;
790
-    }
812
+    *dir = opendir("/sys/class/leds");
813
+  }
814
+  else
815
+  {
816
+    *dir = opendir("/sys/class/backlight");
817
+  }
818
+  if(dir == NULL)
819
+  {
820
+    LIGHT_ERR("could not open backlight or leds directory in /sys/class");
821
+    return FALSE;
822
+  }
823
+  return TRUE;
824
+}
825
+
826
+LIGHT_BOOL light_iterateControllers(DIR *dir, char *currentController)
827
+{
828
+  struct dirent *file;
829
+  LIGHT_BOOL controllerFound = FALSE;
830
+
831
+  if(!dir || !currentController)
832
+  {
833
+    LIGHT_ERR("one of the arguments was NULL");
834
+    return FALSE;
791 835
   }
792 836
 
793
-  while(!dotsKilled)
837
+  while(!controllerFound)
794 838
   {
795
-    light_iterator = readdir(light_iteratorDir);
796
-    if(light_iterator == NULL)
839
+    file = readdir(dir);
840
+    if(file == NULL)
797 841
     {
798
-      if(light_iteratorDir != NULL)
799
-      {
800
-        closedir(light_iteratorDir);
801
-        light_iteratorDir = NULL;
802
-      }
803 842
       return FALSE;
804 843
     }
805 844
 
806
-    if(light_iterator->d_name[0] != '.')
845
+    if(file->d_name[0] != '.')
807 846
     {
808
-      dotsKilled = TRUE;
847
+      if(!light_validControllerName(file->d_name))
848
+      {
849
+        LIGHT_WARN_FMT("invalid controller '%s' found, continuing...", file->d_name);
850
+        continue;
851
+      }
852
+      controllerFound = TRUE;
809 853
     }
810 854
   }
811 855
 
812
-  strcpy(light_currentController, light_iterator->d_name);
813
-
856
+  strncpy(currentController, file->d_name, NAME_MAX);
857
+  currentController[NAME_MAX] = '\0';
814 858
   return TRUE;
815 859
 }
816 860
 
817 861
 LIGHT_BOOL light_getBestController(char *controller)
818 862
 {
819
-  char bestYet[256];
863
+  DIR *dir;
820 864
   unsigned long bestValYet = 0;
821 865
   LIGHT_BOOL foundOkController = FALSE;
866
+  char bestYet[NAME_MAX + 1];
867
+  char currentController[NAME_MAX + 1];
822 868
 
823
-  memset(bestYet, '\0', 256);
869
+  if(!controller)
870
+  {
871
+    LIGHT_ERR("controller buffer was NULL");
872
+    return FALSE;
873
+  }
874
+
875
+  if(!light_prepareControllerIteration(&dir))
876
+  {
877
+    LIGHT_ERR("can't list controllers");
878
+    return FALSE;
879
+  }
824 880
 
825
-  while(light_iterateControllers())
881
+  while(light_iterateControllers(dir, currentController))
826 882
   {
827 883
     unsigned long currVal = 0;
828 884
 
829
-    LIGHT_NOTE_FMT("found '%s' controller", light_currentController);
830
-    if(light_controllerAccessible(light_currentController))
885
+    LIGHT_NOTE_FMT("found '%s' controller", currentController);
886
+    if(light_controllerAccessible(currentController))
831 887
     {
832 888
 
833
-      if(light_getMaxBrightness(light_currentController, &currVal))
889
+      if(light_getMaxBrightness(currentController, &currVal))
834 890
       {
835 891
         if(currVal > bestValYet)
836 892
         {
837
-        foundOkController = TRUE;
838
-        bestValYet = currVal;
839
-        memset(bestYet, '\0', 256);
840
-        strcpy(bestYet, light_currentController);
841
-        light_Configuration.hasCachedMaxBrightness = TRUE;
842
-        light_Configuration.cachedMaxBrightness = currVal;
893
+          foundOkController = TRUE;
894
+          bestValYet = currVal;
895
+          strncpy(bestYet, currentController, NAME_MAX);
896
+          bestYet[NAME_MAX] = '\0';
897
+          light_Configuration.hasCachedMaxBrightness = TRUE;
898
+          light_Configuration.cachedMaxBrightness = currVal;
843 899
         }else{
844 900
           LIGHT_NOTE("ignoring controller as better one already found");
845 901
         }
@@ -851,6 +907,8 @@ LIGHT_BOOL light_getBestController(char *controller)
851 907
     }
852 908
   }
853 909
 
910
+  closedir(dir);
911
+
854 912
   if(!foundOkController)
855 913
   {
856 914
     LIGHT_ERR("could not find an accessible controller");
@@ -863,9 +921,8 @@ LIGHT_BOOL light_getBestController(char *controller)
863 921
     return FALSE;
864 922
   }
865 923
 
866
-  memset(controller, '\0', 256);
867
-  strcpy(controller, bestYet);
868
-
924
+  strncpy(controller, bestYet, NAME_MAX);
925
+  controller[NAME_MAX] = '\0';
869 926
   return TRUE;
870 927
 }
871 928
 
@@ -923,16 +980,20 @@ LIGHT_BOOL light_setMinCap(char const * controller, unsigned long v)
923 980
 
924 981
 LIGHT_BOOL light_listControllers()
925 982
 {
983
+  DIR *dir;
984
+  char controller[NAME_MAX + 1];
926 985
   LIGHT_BOOL foundController = FALSE;
927 986
 
928
-  while(light_iterateControllers())
987
+  if(!light_prepareControllerIteration(&dir))
929 988
   {
930
-    if(!foundController)
931
-    {
932
-      foundController = TRUE;
933
-    }
989
+    LIGHT_ERR("can't list controllers");
990
+    return FALSE;
991
+  }
934 992
 
935
-    printf("%s\n", light_currentController);
993
+  while(light_iterateControllers(dir, controller))
994
+  {
995
+    printf("%s\n", controller);
996
+    foundController = TRUE;
936 997
   }
937 998
 
938 999
   if(!foundController)
@@ -946,6 +1007,7 @@ LIGHT_BOOL light_listControllers()
946 1007
 
947 1008
 LIGHT_BOOL light_saveBrightness(char const *controller, unsigned long v){
948 1009
   char *savePath = NULL;
1010
+
949 1011
   if(!light_genPath(controller, light_Configuration.target, LIGHT_SAVERESTORE, &savePath))
950 1012
   {
951 1013
     LIGHT_ERR("could not generate path to save/restore file");