/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to plugin-runner.c

  • Committer: Teddy Hogeborn
  • Date: 2016-03-17 20:40:55 UTC
  • Revision ID: teddy@recompile.se-20160317204055-bhsh5xsidq7w5cxu
Client: Fix plymouth agent; broken since 1.7.2.

Fix an very old memory bug in the plymouth agent (which has been
present since its apperance in version 1.2), but which was only
recently detected at run time due to the new -fsanitize=address
compile- time flag, which has been used since version 1.7.2.  This
detection of a memory access violation causes the program to abort,
making the Plymouth graphical boot system unable to accept interactive
input of passwords when using the Mandos client.

* plugins.d/plymouth.c (exec_and_wait): Fix memory allocation bug when
  allocating new_argv.  Also tolerate a zero-length argv.

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
/*
3
3
 * Mandos plugin runner - Run Mandos plugins
4
4
 *
5
 
 * Copyright © 2008-2014 Teddy Hogeborn
6
 
 * Copyright © 2008-2014 Björn Påhlsson
 
5
 * Copyright © 2008-2016 Teddy Hogeborn
 
6
 * Copyright © 2008-2016 Björn Påhlsson
7
7
 * 
8
8
 * This program is free software: you can redistribute it and/or
9
9
 * modify it under the terms of the GNU General Public License as
701
701
        custom_argc += 1;
702
702
        {
703
703
          char **new_argv = realloc(custom_argv, sizeof(char *)
704
 
                                    * ((unsigned int)
705
 
                                       custom_argc + 1));
 
704
                                    * ((size_t)custom_argc + 1));
706
705
          if(new_argv == NULL){
707
706
            error(0, errno, "realloc");
708
707
            exitstatus = EX_OSERR;
827
826
          }
828
827
        }
829
828
      }
830
 
      TEMP_FAILURE_RETRY(close(plugindir_fd));
 
829
      close(plugindir_fd);
831
830
    }
832
831
  }
833
832
  
892
891
    return 1;
893
892
  }
894
893
  
895
 
#ifdef __GLIBC__
896
 
#if __GLIBC_PREREQ(2, 15)
897
894
  int numplugins = scandirat(dir_fd, ".", &direntries, good_name,
898
895
                             alphasort);
899
 
#else  /* not __GLIBC_PREREQ(2, 15) */
900
 
  int numplugins = scandir(plugindir != NULL ? plugindir : PDIR,
901
 
                           &direntries, good_name, alphasort);
902
 
#endif  /* not __GLIBC_PREREQ(2, 15) */
903
 
#else   /* not __GLIBC__ */
904
 
  int numplugins = scandir(plugindir != NULL ? plugindir : PDIR,
905
 
                           &direntries, good_name, alphasort);
906
 
#endif  /* not __GLIBC__ */
907
896
  if(numplugins == -1){
908
897
    error(0, errno, "Could not scan plugin dir");
909
898
    direntries = NULL;
925
914
    ret = (int)TEMP_FAILURE_RETRY(fstat(plugin_fd, &st));
926
915
    if(ret == -1){
927
916
      error(0, errno, "stat");
928
 
      TEMP_FAILURE_RETRY(close(plugin_fd));
 
917
      close(plugin_fd);
929
918
      free(direntries[i]);
930
919
      continue;
931
920
    }
940
929
                plugindir != NULL ? plugindir : PDIR,
941
930
                direntries[i]->d_name);
942
931
      }
943
 
      TEMP_FAILURE_RETRY(close(plugin_fd));
 
932
      close(plugin_fd);
944
933
      free(direntries[i]);
945
934
      continue;
946
935
    }
948
937
    plugin *p = getplugin(direntries[i]->d_name);
949
938
    if(p == NULL){
950
939
      error(0, errno, "getplugin");
951
 
      TEMP_FAILURE_RETRY(close(plugin_fd));
 
940
      close(plugin_fd);
952
941
      free(direntries[i]);
953
942
      continue;
954
943
    }
957
946
        fprintf(stderr, "Ignoring disabled plugin \"%s\"\n",
958
947
                direntries[i]->d_name);
959
948
      }
960
 
      TEMP_FAILURE_RETRY(close(plugin_fd));
 
949
      close(plugin_fd);
961
950
      free(direntries[i]);
962
951
      continue;
963
952
    }
1003
992
    if(pipefd[0] >= FD_SETSIZE){
1004
993
      fprintf(stderr, "pipe()[0] (%d) >= FD_SETSIZE (%d)", pipefd[0],
1005
994
              FD_SETSIZE);
1006
 
      TEMP_FAILURE_RETRY(close(pipefd[0]));
1007
 
      TEMP_FAILURE_RETRY(close(pipefd[1]));
 
995
      close(pipefd[0]);
 
996
      close(pipefd[1]);
1008
997
      exitstatus = EX_OSERR;
1009
998
      free(direntries[i]);
1010
999
      goto fallback;
1014
1003
    ret = set_cloexec_flag(pipefd[0]);
1015
1004
    if(ret < 0){
1016
1005
      error(0, errno, "set_cloexec_flag");
1017
 
      TEMP_FAILURE_RETRY(close(pipefd[0]));
1018
 
      TEMP_FAILURE_RETRY(close(pipefd[1]));
 
1006
      close(pipefd[0]);
 
1007
      close(pipefd[1]);
1019
1008
      exitstatus = EX_OSERR;
1020
1009
      free(direntries[i]);
1021
1010
      goto fallback;
1023
1012
    ret = set_cloexec_flag(pipefd[1]);
1024
1013
    if(ret < 0){
1025
1014
      error(0, errno, "set_cloexec_flag");
1026
 
      TEMP_FAILURE_RETRY(close(pipefd[0]));
1027
 
      TEMP_FAILURE_RETRY(close(pipefd[1]));
 
1015
      close(pipefd[0]);
 
1016
      close(pipefd[1]);
1028
1017
      exitstatus = EX_OSERR;
1029
1018
      free(direntries[i]);
1030
1019
      goto fallback;
1049
1038
      error(0, errno, "fork");
1050
1039
      TEMP_FAILURE_RETRY(sigprocmask(SIG_UNBLOCK,
1051
1040
                                     &sigchld_action.sa_mask, NULL));
1052
 
      TEMP_FAILURE_RETRY(close(pipefd[0]));
1053
 
      TEMP_FAILURE_RETRY(close(pipefd[1]));
 
1041
      close(pipefd[0]);
 
1042
      close(pipefd[1]);
1054
1043
      exitstatus = EX_OSERR;
1055
1044
      free(direntries[i]);
1056
1045
      goto fallback;
1084
1073
      /* no return */
1085
1074
    }
1086
1075
    /* Parent process */
1087
 
    TEMP_FAILURE_RETRY(close(pipefd[1])); /* Close unused write end of
1088
 
                                             pipe */
1089
 
    TEMP_FAILURE_RETRY(close(plugin_fd));
 
1076
    close(pipefd[1]);           /* Close unused write end of pipe */
 
1077
    close(plugin_fd);
1090
1078
    plugin *new_plugin = getplugin(direntries[i]->d_name);
1091
1079
    if(new_plugin == NULL){
1092
1080
      error(0, errno, "getplugin");
1116
1104
      goto fallback;
1117
1105
    }
1118
1106
    
1119
 
#if defined (__GNUC__) and defined (__GLIBC__)
1120
 
#if not __GLIBC_PREREQ(2, 16)
1121
 
#pragma GCC diagnostic push
1122
 
#pragma GCC diagnostic ignored "-Wsign-conversion"
1123
 
#endif
1124
 
#endif
1125
 
    FD_SET(new_plugin->fd, &rfds_all); /* Spurious warning from
1126
 
                                          -Wconversion in GNU libc
1127
 
                                          before 2.16 */
1128
 
#if defined (__GNUC__) and defined (__GLIBC__)
1129
 
#if not __GLIBC_PREREQ(2, 16)
1130
 
#pragma GCC diagnostic pop
1131
 
#endif
1132
 
#endif
 
1107
    FD_SET(new_plugin->fd, &rfds_all);
1133
1108
    
1134
1109
    if(maxfd < new_plugin->fd){
1135
1110
      maxfd = new_plugin->fd;
1138
1113
  
1139
1114
  free(direntries);
1140
1115
  direntries = NULL;
1141
 
  TEMP_FAILURE_RETRY(close(dir_fd));
 
1116
  close(dir_fd);
1142
1117
  dir_fd = -1;
1143
1118
  free_plugin(getplugin(NULL));
1144
1119
  
1191
1166
          }
1192
1167
          
1193
1168
          /* Remove the plugin */
1194
 
#if defined (__GNUC__) and defined (__GLIBC__)
1195
 
#if not __GLIBC_PREREQ(2, 16)
1196
 
#pragma GCC diagnostic push
1197
 
#pragma GCC diagnostic ignored "-Wsign-conversion"
1198
 
#endif
1199
 
#endif
1200
 
          FD_CLR(proc->fd, &rfds_all); /* Spurious warning from
1201
 
                                          -Wconversion in GNU libc
1202
 
                                          before 2.16 */
1203
 
#if defined (__GNUC__) and defined (__GLIBC__)
1204
 
#if not __GLIBC_PREREQ(2, 16)
1205
 
#pragma GCC diagnostic pop
1206
 
#endif
1207
 
#endif
 
1169
          FD_CLR(proc->fd, &rfds_all);
1208
1170
          
1209
1171
          /* Block signal while modifying process_list */
1210
1172
          ret = (int)TEMP_FAILURE_RETRY(sigprocmask
1250
1212
      }
1251
1213
      
1252
1214
      /* This process has not completed.  Does it have any output? */
1253
 
#if defined (__GNUC__) and defined (__GLIBC__)
1254
 
#if not __GLIBC_PREREQ(2, 16)
1255
 
#pragma GCC diagnostic push
1256
 
#pragma GCC diagnostic ignored "-Wsign-conversion"
1257
 
#endif
1258
 
#endif
1259
 
      if(proc->eof or not FD_ISSET(proc->fd, &rfds)){ /* Spurious
1260
 
                                                         warning from
1261
 
                                                         -Wconversion
1262
 
                                                         in GNU libc
1263
 
                                                         before
1264
 
                                                         2.16 */
1265
 
#if defined (__GNUC__) and defined (__GLIBC__)
1266
 
#if not __GLIBC_PREREQ(2, 16)
1267
 
#pragma GCC diagnostic pop
1268
 
#endif
1269
 
#endif
 
1215
      if(proc->eof or not FD_ISSET(proc->fd, &rfds)){
1270
1216
        /* This process had nothing to say at this time */
1271
1217
        proc = proc->next;
1272
1218
        continue;
1342
1288
  free(direntries);
1343
1289
  
1344
1290
  if(dir_fd != -1){
1345
 
    TEMP_FAILURE_RETRY(close(dir_fd));
 
1291
    close(dir_fd);
1346
1292
  }
1347
1293
  
1348
1294
  /* Kill the processes */