/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-06-03 17:27:03 UTC
  • Revision ID: teddy@recompile.se-20160603172703-mc6tjor6rhq4xy74
mandos: Bug fix: Do multiprocessing cleanup correctly on exit

* mandos (main): Save module "multiprocessing" and open file "wnull"
                 as scope variables accessible by function cleanup(),
                 since the module and global variable may not be
                 accessible when the cleanup() function is run as
                 scheduled by atexit().

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
37
37
#include <sys/select.h>         /* fd_set, select(), FD_ZERO(),
38
38
                                   FD_SET(), FD_ISSET(), FD_CLR */
39
39
#include <sys/wait.h>           /* wait(), waitpid(), WIFEXITED(),
40
 
                                   WEXITSTATUS(), WTERMSIG(),
41
 
                                   WCOREDUMP() */
 
40
                                   WEXITSTATUS(), WTERMSIG() */
42
41
#include <sys/stat.h>           /* struct stat, fstat(), S_ISREG() */
43
42
#include <iso646.h>             /* and, or, not */
44
43
#include <dirent.h>             /* struct dirent, scandirat() */
701
700
        custom_argc += 1;
702
701
        {
703
702
          char **new_argv = realloc(custom_argv, sizeof(char *)
704
 
                                    * ((unsigned int)
705
 
                                       custom_argc + 1));
 
703
                                    * ((size_t)custom_argc + 1));
706
704
          if(new_argv == NULL){
707
705
            error(0, errno, "realloc");
708
706
            exitstatus = EX_OSERR;
827
825
          }
828
826
        }
829
827
      }
830
 
      TEMP_FAILURE_RETRY(close(plugindir_fd));
 
828
      close(plugindir_fd);
831
829
    }
832
830
  }
833
831
  
892
890
    return 1;
893
891
  }
894
892
  
895
 
#ifdef __GLIBC__
896
 
#if __GLIBC_PREREQ(2, 15)
897
893
  int numplugins = scandirat(dir_fd, ".", &direntries, good_name,
898
894
                             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
895
  if(numplugins == -1){
908
896
    error(0, errno, "Could not scan plugin dir");
909
897
    direntries = NULL;
925
913
    ret = (int)TEMP_FAILURE_RETRY(fstat(plugin_fd, &st));
926
914
    if(ret == -1){
927
915
      error(0, errno, "stat");
928
 
      TEMP_FAILURE_RETRY(close(plugin_fd));
 
916
      close(plugin_fd);
929
917
      free(direntries[i]);
930
918
      continue;
931
919
    }
940
928
                plugindir != NULL ? plugindir : PDIR,
941
929
                direntries[i]->d_name);
942
930
      }
943
 
      TEMP_FAILURE_RETRY(close(plugin_fd));
 
931
      close(plugin_fd);
944
932
      free(direntries[i]);
945
933
      continue;
946
934
    }
948
936
    plugin *p = getplugin(direntries[i]->d_name);
949
937
    if(p == NULL){
950
938
      error(0, errno, "getplugin");
951
 
      TEMP_FAILURE_RETRY(close(plugin_fd));
 
939
      close(plugin_fd);
952
940
      free(direntries[i]);
953
941
      continue;
954
942
    }
957
945
        fprintf(stderr, "Ignoring disabled plugin \"%s\"\n",
958
946
                direntries[i]->d_name);
959
947
      }
960
 
      TEMP_FAILURE_RETRY(close(plugin_fd));
 
948
      close(plugin_fd);
961
949
      free(direntries[i]);
962
950
      continue;
963
951
    }
1003
991
    if(pipefd[0] >= FD_SETSIZE){
1004
992
      fprintf(stderr, "pipe()[0] (%d) >= FD_SETSIZE (%d)", pipefd[0],
1005
993
              FD_SETSIZE);
1006
 
      TEMP_FAILURE_RETRY(close(pipefd[0]));
1007
 
      TEMP_FAILURE_RETRY(close(pipefd[1]));
 
994
      close(pipefd[0]);
 
995
      close(pipefd[1]);
1008
996
      exitstatus = EX_OSERR;
1009
997
      free(direntries[i]);
1010
998
      goto fallback;
1014
1002
    ret = set_cloexec_flag(pipefd[0]);
1015
1003
    if(ret < 0){
1016
1004
      error(0, errno, "set_cloexec_flag");
1017
 
      TEMP_FAILURE_RETRY(close(pipefd[0]));
1018
 
      TEMP_FAILURE_RETRY(close(pipefd[1]));
 
1005
      close(pipefd[0]);
 
1006
      close(pipefd[1]);
1019
1007
      exitstatus = EX_OSERR;
1020
1008
      free(direntries[i]);
1021
1009
      goto fallback;
1023
1011
    ret = set_cloexec_flag(pipefd[1]);
1024
1012
    if(ret < 0){
1025
1013
      error(0, errno, "set_cloexec_flag");
1026
 
      TEMP_FAILURE_RETRY(close(pipefd[0]));
1027
 
      TEMP_FAILURE_RETRY(close(pipefd[1]));
 
1014
      close(pipefd[0]);
 
1015
      close(pipefd[1]);
1028
1016
      exitstatus = EX_OSERR;
1029
1017
      free(direntries[i]);
1030
1018
      goto fallback;
1049
1037
      error(0, errno, "fork");
1050
1038
      TEMP_FAILURE_RETRY(sigprocmask(SIG_UNBLOCK,
1051
1039
                                     &sigchld_action.sa_mask, NULL));
1052
 
      TEMP_FAILURE_RETRY(close(pipefd[0]));
1053
 
      TEMP_FAILURE_RETRY(close(pipefd[1]));
 
1040
      close(pipefd[0]);
 
1041
      close(pipefd[1]);
1054
1042
      exitstatus = EX_OSERR;
1055
1043
      free(direntries[i]);
1056
1044
      goto fallback;
1084
1072
      /* no return */
1085
1073
    }
1086
1074
    /* Parent process */
1087
 
    TEMP_FAILURE_RETRY(close(pipefd[1])); /* Close unused write end of
1088
 
                                             pipe */
1089
 
    TEMP_FAILURE_RETRY(close(plugin_fd));
 
1075
    close(pipefd[1]);           /* Close unused write end of pipe */
 
1076
    close(plugin_fd);
1090
1077
    plugin *new_plugin = getplugin(direntries[i]->d_name);
1091
1078
    if(new_plugin == NULL){
1092
1079
      error(0, errno, "getplugin");
1116
1103
      goto fallback;
1117
1104
    }
1118
1105
    
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
 
1106
    FD_SET(new_plugin->fd, &rfds_all);
1133
1107
    
1134
1108
    if(maxfd < new_plugin->fd){
1135
1109
      maxfd = new_plugin->fd;
1138
1112
  
1139
1113
  free(direntries);
1140
1114
  direntries = NULL;
1141
 
  TEMP_FAILURE_RETRY(close(dir_fd));
 
1115
  close(dir_fd);
1142
1116
  dir_fd = -1;
1143
1117
  free_plugin(getplugin(NULL));
1144
1118
  
1184
1158
                      (intmax_t) (proc->pid),
1185
1159
                      WTERMSIG(proc->status),
1186
1160
                      strsignal(WTERMSIG(proc->status)));
1187
 
            } else if(WCOREDUMP(proc->status)){
1188
 
              fprintf(stderr, "Plugin %s [%" PRIdMAX "] dumped"
1189
 
                      " core\n", proc->name, (intmax_t) (proc->pid));
1190
1161
            }
1191
1162
          }
1192
1163
          
1193
1164
          /* 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
 
1165
          FD_CLR(proc->fd, &rfds_all);
1208
1166
          
1209
1167
          /* Block signal while modifying process_list */
1210
1168
          ret = (int)TEMP_FAILURE_RETRY(sigprocmask
1250
1208
      }
1251
1209
      
1252
1210
      /* 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
 
1211
      if(proc->eof or not FD_ISSET(proc->fd, &rfds)){
1270
1212
        /* This process had nothing to say at this time */
1271
1213
        proc = proc->next;
1272
1214
        continue;
1342
1284
  free(direntries);
1343
1285
  
1344
1286
  if(dir_fd != -1){
1345
 
    TEMP_FAILURE_RETRY(close(dir_fd));
 
1287
    close(dir_fd);
1346
1288
  }
1347
1289
  
1348
1290
  /* Kill the processes */