/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 dracut-module/password-agent.c

  • Committer: Teddy Hogeborn
  • Date: 2019-07-30 17:03:57 UTC
  • Revision ID: teddy@recompile.se-20190730170357-jte0piul5mq7j5pr
Server: Reap zombies created by multiprocessing.Process()

When creating checkers as multiprocessing.Process() objects, the
multiprocessing module also creates a parent process (for the
call_pipe() function) to call the actual checker process, but this
parent process is not reaped.  This is not a huge problem, since the
zombie is always reaped automatically the next time the multiprocess
starts a new process, but the zombies can be up to as many as there
have ever been simultaneous checker processes.  To fix this, the
process object must be join():ed when they report completion of the
child checker process.

* mandos (Client): Fix doc string to correctly state that
                   Client.checker is a multiprocess.Process() and not
                   a subprocess.Popen() object.
  (Client.checker_callback): After the returncode of the checker
                             process has been read, wait for the
                             self.checker Process object to finish by
                             calling join() on it.

Reported-by: Peter Palfrader <weasel@debian.org>

Show diffs side-by-side

added added

removed removed

Lines of Context:
431
431
    case EACCES:
432
432
    case ENAMETOOLONG:
433
433
    case ENOENT:
434
 
    case ENOTDIR:
435
434
      return EX_OSFILE;
436
435
    default:
437
436
      return EX_OSERR;
1018
1017
    return false;
1019
1018
  }
1020
1019
 
1021
 
  if(inotify_add_watch(fd, dir, IN_CLOSE_WRITE | IN_MOVED_TO
1022
 
                       | IN_MOVED_FROM| IN_DELETE | IN_EXCL_UNLINK
1023
 
                       | IN_ONLYDIR)
 
1020
  if(inotify_add_watch(fd, dir, IN_CLOSE_WRITE
 
1021
                       | IN_MOVED_TO | IN_DELETE)
1024
1022
     == -1){
1025
1023
    error(0, errno, "Failed to create inotify watch on %s", dir);
1026
1024
    return false;
1073
1071
  /* "sufficient to read at least one event." - inotify(7) */
1074
1072
  const size_t ievent_size = (sizeof(struct inotify_event)
1075
1073
                              + NAME_MAX + 1);
1076
 
  struct {
1077
 
    struct inotify_event event;
1078
 
    char name_buffer[NAME_MAX + 1];
1079
 
  } ievent_buffer;
1080
 
  struct inotify_event *const ievent = &ievent_buffer.event;
 
1074
  char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
 
1075
  struct inotify_event *ievent = ((struct inotify_event *)
 
1076
                                  ievent_buffer);
1081
1077
 
1082
1078
  const ssize_t read_length = read(fd, ievent, ievent_size);
1083
1079
  if(read_length == 0){ /* EOF */
1121
1117
             immediately */
1122
1118
          queue->next_run = 1;
1123
1119
        }
1124
 
      } else if(ievent->mask & (IN_MOVED_FROM | IN_DELETE)){
 
1120
      } else if(ievent->mask & IN_DELETE){
1125
1121
        if(not string_set_add(cancelled_filenames,
1126
1122
                              question_filename)){
1127
1123
          error(0, errno, "Could not add question %s to"
3454
3450
  g_assert_cmpuint((unsigned int)queue->length, ==, 0);
3455
3451
}
3456
3452
 
3457
 
static void test_add_inotify_dir_watch_nondir(__attribute__((unused))
3458
 
                                              test_fixture *fixture,
3459
 
                                            __attribute__((unused))
3460
 
                                              gconstpointer
3461
 
                                              user_data){
3462
 
  __attribute__((cleanup(cleanup_close)))
3463
 
    const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
3464
 
  g_assert_cmpint(epoll_fd, >=, 0);
3465
 
  __attribute__((cleanup(cleanup_queue)))
3466
 
    task_queue *queue = create_queue();
3467
 
  g_assert_nonnull(queue);
3468
 
  __attribute__((cleanup(string_set_clear)))
3469
 
    string_set cancelled_filenames = {};
3470
 
  const mono_microsecs current_time = 0;
3471
 
 
3472
 
  bool quit_now = false;
3473
 
  buffer password = {};
3474
 
  bool mandos_client_exited = false;
3475
 
  bool password_is_read = false;
3476
 
 
3477
 
  const char not_a_directory[] = "/dev/tty";
3478
 
 
3479
 
  FILE *real_stderr = stderr;
3480
 
  FILE *devnull = fopen("/dev/null", "we");
3481
 
  g_assert_nonnull(devnull);
3482
 
  stderr = devnull;
3483
 
  g_assert_false(add_inotify_dir_watch(queue, epoll_fd, &quit_now,
3484
 
                                       &password, not_a_directory,
3485
 
                                       &cancelled_filenames,
3486
 
                                       &current_time,
3487
 
                                       &mandos_client_exited,
3488
 
                                       &password_is_read));
3489
 
  stderr = real_stderr;
3490
 
  g_assert_cmpint(fclose(devnull), ==, 0);
3491
 
 
3492
 
  g_assert_cmpuint((unsigned int)queue->length, ==, 0);
3493
 
}
3494
 
 
3495
3453
static void test_add_inotify_dir_watch_EAGAIN(__attribute__((unused))
3496
3454
                                              test_fixture *fixture,
3497
3455
                                              __attribute__((unused))
3712
3670
}
3713
3671
 
3714
3672
static
3715
 
void test_add_inotify_dir_watch_IN_MOVED_FROM(__attribute__((unused))
3716
 
                                              test_fixture *fixture,
3717
 
                                              __attribute__((unused))
3718
 
                                              gconstpointer
3719
 
                                              user_data){
3720
 
  __attribute__((cleanup(cleanup_close)))
3721
 
    const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
3722
 
  g_assert_cmpint(epoll_fd, >=, 0);
3723
 
  __attribute__((cleanup(cleanup_queue)))
3724
 
    task_queue *queue = create_queue();
3725
 
  g_assert_nonnull(queue);
3726
 
  __attribute__((cleanup(string_set_clear)))
3727
 
    string_set cancelled_filenames = {};
3728
 
  const mono_microsecs current_time = 0;
3729
 
 
3730
 
  bool quit_now = false;
3731
 
  buffer password = {};
3732
 
  bool mandos_client_exited = false;
3733
 
  bool password_is_read = false;
3734
 
 
3735
 
  __attribute__((cleanup(cleanup_string)))
3736
 
    char *tempdir = make_temporary_directory();
3737
 
  g_assert_nonnull(tempdir);
3738
 
 
3739
 
  __attribute__((cleanup(cleanup_string)))
3740
 
    char *tempfilename = make_temporary_file_in_directory(tempdir);
3741
 
  g_assert_nonnull(tempfilename);
3742
 
 
3743
 
  __attribute__((cleanup(cleanup_string)))
3744
 
    char *targetdir = make_temporary_directory();
3745
 
  g_assert_nonnull(targetdir);
3746
 
 
3747
 
  __attribute__((cleanup(cleanup_string)))
3748
 
    char *targetfilename = NULL;
3749
 
  g_assert_cmpint(asprintf(&targetfilename, "%s/%s", targetdir,
3750
 
                           basename(tempfilename)), >, 0);
3751
 
  g_assert_nonnull(targetfilename);
3752
 
 
3753
 
  g_assert_true(add_inotify_dir_watch(queue, epoll_fd, &quit_now,
3754
 
                                      &password, tempdir,
3755
 
                                      &cancelled_filenames,
3756
 
                                      &current_time,
3757
 
                                      &mandos_client_exited,
3758
 
                                      &password_is_read));
3759
 
 
3760
 
  g_assert_cmpint(rename(tempfilename, targetfilename), ==, 0);
3761
 
 
3762
 
  const task_context *const added_read_task
3763
 
    = find_matching_task(queue,
3764
 
                         (task_context){ .func=read_inotify_event });
3765
 
  g_assert_nonnull(added_read_task);
3766
 
 
3767
 
  /* "sufficient to read at least one event." - inotify(7) */
3768
 
  const size_t ievent_size = (sizeof(struct inotify_event)
3769
 
                              + NAME_MAX + 1);
3770
 
  struct inotify_event *ievent = malloc(ievent_size);
3771
 
  g_assert_nonnull(ievent);
3772
 
 
3773
 
  ssize_t read_size = read(added_read_task->fd, ievent, ievent_size);
3774
 
 
3775
 
  g_assert_cmpint((int)read_size, >, 0);
3776
 
  g_assert_true(ievent->mask & IN_MOVED_FROM);
3777
 
  g_assert_cmpstr(ievent->name, ==, basename(tempfilename));
3778
 
 
3779
 
  free(ievent);
3780
 
 
3781
 
  g_assert_cmpint(unlink(targetfilename), ==, 0);
3782
 
  g_assert_cmpint(rmdir(targetdir), ==, 0);
3783
 
  g_assert_cmpint(rmdir(tempdir), ==, 0);
3784
 
}
3785
 
 
3786
 
static
3787
3673
void test_add_inotify_dir_watch_IN_DELETE(__attribute__((unused))
3788
3674
                                          test_fixture *fixture,
3789
3675
                                          __attribute__((unused))
3847
3733
  g_assert_cmpint(rmdir(tempdir), ==, 0);
3848
3734
}
3849
3735
 
3850
 
static
3851
 
void test_add_inotify_dir_watch_IN_EXCL_UNLINK(__attribute__((unused))
3852
 
                                               test_fixture *fixture,
3853
 
                                               __attribute__((unused))
3854
 
                                               gconstpointer
3855
 
                                               user_data){
3856
 
  __attribute__((cleanup(cleanup_close)))
3857
 
    const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
3858
 
  g_assert_cmpint(epoll_fd, >=, 0);
3859
 
  __attribute__((cleanup(cleanup_queue)))
3860
 
    task_queue *queue = create_queue();
3861
 
  g_assert_nonnull(queue);
3862
 
  __attribute__((cleanup(string_set_clear)))
3863
 
    string_set cancelled_filenames = {};
3864
 
  const mono_microsecs current_time = 0;
3865
 
 
3866
 
  bool quit_now = false;
3867
 
  buffer password = {};
3868
 
  bool mandos_client_exited = false;
3869
 
  bool password_is_read = false;
3870
 
 
3871
 
  __attribute__((cleanup(cleanup_string)))
3872
 
    char *tempdir = make_temporary_directory();
3873
 
  g_assert_nonnull(tempdir);
3874
 
 
3875
 
  __attribute__((cleanup(cleanup_string)))
3876
 
    char *tempfile = make_temporary_file_in_directory(tempdir);
3877
 
  g_assert_nonnull(tempfile);
3878
 
  int tempfile_fd = open(tempfile, O_WRONLY | O_CLOEXEC | O_NOCTTY
3879
 
                         | O_NOFOLLOW);
3880
 
  g_assert_cmpint(tempfile_fd, >, 2);
3881
 
 
3882
 
  g_assert_true(add_inotify_dir_watch(queue, epoll_fd, &quit_now,
3883
 
                                      &password, tempdir,
3884
 
                                      &cancelled_filenames,
3885
 
                                      &current_time,
3886
 
                                      &mandos_client_exited,
3887
 
                                      &password_is_read));
3888
 
  g_assert_cmpint(unlink(tempfile), ==, 0);
3889
 
 
3890
 
  g_assert_cmpuint((unsigned int)queue->length, >, 0);
3891
 
 
3892
 
  const task_context *const added_read_task
3893
 
    = find_matching_task(queue,
3894
 
                         (task_context){ .func=read_inotify_event });
3895
 
  g_assert_nonnull(added_read_task);
3896
 
 
3897
 
  g_assert_cmpint(added_read_task->fd, >, 2);
3898
 
  g_assert_true(fd_has_cloexec_and_nonblock(added_read_task->fd));
3899
 
 
3900
 
  /* "sufficient to read at least one event." - inotify(7) */
3901
 
  const size_t ievent_size = (sizeof(struct inotify_event)
3902
 
                              + NAME_MAX + 1);
3903
 
  struct inotify_event *ievent = malloc(ievent_size);
3904
 
  g_assert_nonnull(ievent);
3905
 
 
3906
 
  ssize_t read_size = 0;
3907
 
  read_size = read(added_read_task->fd, ievent, ievent_size);
3908
 
 
3909
 
  g_assert_cmpint((int)read_size, >, 0);
3910
 
  g_assert_true(ievent->mask & IN_DELETE);
3911
 
  g_assert_cmpstr(ievent->name, ==, basename(tempfile));
3912
 
 
3913
 
  g_assert_cmpint(close(tempfile_fd), ==, 0);
3914
 
 
3915
 
  /* IN_EXCL_UNLINK should make the closing of the previously unlinked
3916
 
     file not appear as an ievent, so we should not see it now. */
3917
 
  read_size = read(added_read_task->fd, ievent, ievent_size);
3918
 
  g_assert_cmpint((int)read_size, ==, -1);
3919
 
  g_assert_true(errno == EAGAIN);
3920
 
 
3921
 
  free(ievent);
3922
 
 
3923
 
  g_assert_cmpint(rmdir(tempdir), ==, 0);
3924
 
}
3925
 
 
3926
3736
static void test_read_inotify_event_readerror(__attribute__((unused))
3927
3737
                                              test_fixture *fixture,
3928
3738
                                              __attribute__((unused))
4119
3929
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4120
3930
                                  + NAME_MAX + 1);
4121
3931
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4122
 
  struct {
4123
 
    struct inotify_event event;
4124
 
    char name_buffer[NAME_MAX + 1];
4125
 
  } ievent_buffer;
4126
 
  struct inotify_event *const ievent = &ievent_buffer.event;
 
3932
  char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
 
3933
  struct inotify_event *ievent = ((struct inotify_event *)
 
3934
                                  ievent_buffer);
4127
3935
 
4128
3936
  const char dummy_file_name[] = "ask.dummy_file_name";
4129
3937
  ievent->mask = IN_CLOSE_WRITE;
4131
3939
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4132
3940
  const size_t ievent_size = (sizeof(struct inotify_event)
4133
3941
                              + sizeof(dummy_file_name));
4134
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
 
3942
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4135
3943
                  ==, ievent_size);
4136
3944
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4137
3945
 
4214
4022
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4215
4023
                                  + NAME_MAX + 1);
4216
4024
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4217
 
  struct {
4218
 
    struct inotify_event event;
4219
 
    char name_buffer[NAME_MAX + 1];
4220
 
  } ievent_buffer;
4221
 
  struct inotify_event *const ievent = &ievent_buffer.event;
 
4025
  char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
 
4026
  struct inotify_event *ievent = ((struct inotify_event *)
 
4027
                                  ievent_buffer);
4222
4028
 
4223
4029
  const char dummy_file_name[] = "ask.dummy_file_name";
4224
4030
  ievent->mask = IN_MOVED_TO;
4226
4032
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4227
4033
  const size_t ievent_size = (sizeof(struct inotify_event)
4228
4034
                              + sizeof(dummy_file_name));
4229
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
 
4035
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4230
4036
                  ==, ievent_size);
4231
4037
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4232
4038
 
4292
4098
      }));
4293
4099
}
4294
4100
 
4295
 
static
4296
 
void test_read_inotify_event_IN_MOVED_FROM(__attribute__((unused))
4297
 
                                           test_fixture *fixture,
4298
 
                                           __attribute__((unused))
4299
 
                                           gconstpointer user_data){
4300
 
  __attribute__((cleanup(cleanup_close)))
4301
 
    const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
4302
 
  g_assert_cmpint(epoll_fd, >=, 0);
4303
 
  __attribute__((cleanup(string_set_clear)))
4304
 
    string_set cancelled_filenames = {};
4305
 
  const mono_microsecs current_time = 0;
4306
 
 
4307
 
  int pipefds[2];
4308
 
  g_assert_cmpint(pipe2(pipefds, O_CLOEXEC | O_NONBLOCK), ==, 0);
4309
 
 
4310
 
  /* "sufficient to read at least one event." - inotify(7) */
4311
 
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4312
 
                                  + NAME_MAX + 1);
4313
 
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4314
 
  struct {
4315
 
    struct inotify_event event;
4316
 
    char name_buffer[NAME_MAX + 1];
4317
 
  } ievent_buffer;
4318
 
  struct inotify_event *const ievent = &ievent_buffer.event;
4319
 
 
4320
 
  const char dummy_file_name[] = "ask.dummy_file_name";
4321
 
  ievent->mask = IN_MOVED_FROM;
4322
 
  ievent->len = sizeof(dummy_file_name);
4323
 
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4324
 
  const size_t ievent_size = (sizeof(struct inotify_event)
4325
 
                              + sizeof(dummy_file_name));
4326
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4327
 
                  ==, ievent_size);
4328
 
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4329
 
 
4330
 
  bool quit_now = false;
4331
 
  buffer password = {};
4332
 
  bool mandos_client_exited = false;
4333
 
  bool password_is_read = false;
4334
 
  __attribute__((cleanup(cleanup_queue)))
4335
 
    task_queue *queue = create_queue();
4336
 
  g_assert_nonnull(queue);
4337
 
 
4338
 
  task_context task = {
4339
 
    .func=read_inotify_event,
4340
 
    .epoll_fd=epoll_fd,
4341
 
    .fd=pipefds[0],
4342
 
    .quit_now=&quit_now,
4343
 
    .password=&password,
4344
 
    .filename=strdup("/nonexistent"),
4345
 
    .cancelled_filenames=&cancelled_filenames,
4346
 
    .current_time=&current_time,
4347
 
    .mandos_client_exited=&mandos_client_exited,
4348
 
    .password_is_read=&password_is_read,
4349
 
  };
4350
 
  task.func(task, queue);
4351
 
  g_assert_false(quit_now);
4352
 
  g_assert_true(queue->next_run == 0);
4353
 
  g_assert_cmpuint((unsigned int)queue->length, ==, 1);
4354
 
 
4355
 
  g_assert_nonnull(find_matching_task(queue, (task_context){
4356
 
        .func=read_inotify_event,
4357
 
        .epoll_fd=epoll_fd,
4358
 
        .fd=pipefds[0],
4359
 
        .quit_now=&quit_now,
4360
 
        .password=&password,
4361
 
        .filename=task.filename,
4362
 
        .cancelled_filenames=&cancelled_filenames,
4363
 
        .current_time=&current_time,
4364
 
        .mandos_client_exited=&mandos_client_exited,
4365
 
        .password_is_read=&password_is_read,
4366
 
      }));
4367
 
 
4368
 
  g_assert_true(epoll_set_contains(epoll_fd, pipefds[0],
4369
 
                                   EPOLLIN | EPOLLRDHUP));
4370
 
 
4371
 
  __attribute__((cleanup(cleanup_string)))
4372
 
    char *filename = NULL;
4373
 
  g_assert_cmpint(asprintf(&filename, "%s/%s", task.filename,
4374
 
                           dummy_file_name), >, 0);
4375
 
  g_assert_nonnull(filename);
4376
 
  g_assert_true(string_set_contains(*task.cancelled_filenames,
4377
 
                                    filename));
4378
 
}
4379
 
 
4380
4101
static void test_read_inotify_event_IN_DELETE(__attribute__((unused))
4381
4102
                                              test_fixture *fixture,
4382
4103
                                              __attribute__((unused))
4396
4117
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4397
4118
                                  + NAME_MAX + 1);
4398
4119
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4399
 
  struct {
4400
 
    struct inotify_event event;
4401
 
    char name_buffer[NAME_MAX + 1];
4402
 
  } ievent_buffer;
4403
 
  struct inotify_event *const ievent = &ievent_buffer.event;
 
4120
  char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
 
4121
  struct inotify_event *ievent = ((struct inotify_event *)
 
4122
                                  ievent_buffer);
4404
4123
 
4405
4124
  const char dummy_file_name[] = "ask.dummy_file_name";
4406
4125
  ievent->mask = IN_DELETE;
4408
4127
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4409
4128
  const size_t ievent_size = (sizeof(struct inotify_event)
4410
4129
                              + sizeof(dummy_file_name));
4411
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
 
4130
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4412
4131
                  ==, ievent_size);
4413
4132
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4414
4133
 
4480
4199
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4481
4200
                                  + NAME_MAX + 1);
4482
4201
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4483
 
  struct {
4484
 
    struct inotify_event event;
4485
 
    char name_buffer[NAME_MAX + 1];
4486
 
  } ievent_buffer;
4487
 
  struct inotify_event *const ievent = &ievent_buffer.event;
 
4202
  char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
 
4203
  struct inotify_event *ievent = ((struct inotify_event *)
 
4204
                                  ievent_buffer);
4488
4205
 
4489
4206
  const char dummy_file_name[] = "ignored.dummy_file_name";
4490
4207
  ievent->mask = IN_CLOSE_WRITE;
4492
4209
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4493
4210
  const size_t ievent_size = (sizeof(struct inotify_event)
4494
4211
                              + sizeof(dummy_file_name));
4495
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
 
4212
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4496
4213
                  ==, ievent_size);
4497
4214
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4498
4215
 
4556
4273
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4557
4274
                                  + NAME_MAX + 1);
4558
4275
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4559
 
  struct {
4560
 
    struct inotify_event event;
4561
 
    char name_buffer[NAME_MAX + 1];
4562
 
  } ievent_buffer;
4563
 
  struct inotify_event *const ievent = &ievent_buffer.event;
 
4276
  char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
 
4277
  struct inotify_event *ievent = ((struct inotify_event *)
 
4278
                                  ievent_buffer);
4564
4279
 
4565
4280
  const char dummy_file_name[] = "ignored.dummy_file_name";
4566
4281
  ievent->mask = IN_MOVED_TO;
4568
4283
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4569
4284
  const size_t ievent_size = (sizeof(struct inotify_event)
4570
4285
                              + sizeof(dummy_file_name));
4571
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
 
4286
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4572
4287
                  ==, ievent_size);
4573
4288
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4574
4289
 
4615
4330
                                   EPOLLIN | EPOLLRDHUP));
4616
4331
}
4617
4332
 
4618
 
static void
4619
 
test_read_inotify_event_IN_MOVED_FROM_badname(__attribute__((unused))
4620
 
                                              test_fixture *fixture,
4621
 
                                              __attribute__((unused))
4622
 
                                              gconstpointer
4623
 
                                              user_data){
4624
 
  __attribute__((cleanup(cleanup_close)))
4625
 
    const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
4626
 
  g_assert_cmpint(epoll_fd, >=, 0);
4627
 
  __attribute__((cleanup(string_set_clear)))
4628
 
    string_set cancelled_filenames = {};
4629
 
  const mono_microsecs current_time = 0;
4630
 
 
4631
 
  int pipefds[2];
4632
 
  g_assert_cmpint(pipe2(pipefds, O_CLOEXEC | O_NONBLOCK), ==, 0);
4633
 
 
4634
 
  /* "sufficient to read at least one event." - inotify(7) */
4635
 
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4636
 
                                  + NAME_MAX + 1);
4637
 
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4638
 
  struct {
4639
 
    struct inotify_event event;
4640
 
    char name_buffer[NAME_MAX + 1];
4641
 
  } ievent_buffer;
4642
 
  struct inotify_event *const ievent = &ievent_buffer.event;
4643
 
 
4644
 
  const char dummy_file_name[] = "ignored.dummy_file_name";
4645
 
  ievent->mask = IN_MOVED_FROM;
4646
 
  ievent->len = sizeof(dummy_file_name);
4647
 
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4648
 
  const size_t ievent_size = (sizeof(struct inotify_event)
4649
 
                              + sizeof(dummy_file_name));
4650
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
4651
 
                  ==, ievent_size);
4652
 
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4653
 
 
4654
 
  bool quit_now = false;
4655
 
  buffer password = {};
4656
 
  bool mandos_client_exited = false;
4657
 
  bool password_is_read = false;
4658
 
  __attribute__((cleanup(cleanup_queue)))
4659
 
    task_queue *queue = create_queue();
4660
 
  g_assert_nonnull(queue);
4661
 
 
4662
 
  task_context task = {
4663
 
    .func=read_inotify_event,
4664
 
    .epoll_fd=epoll_fd,
4665
 
    .fd=pipefds[0],
4666
 
    .quit_now=&quit_now,
4667
 
    .password=&password,
4668
 
    .filename=strdup("/nonexistent"),
4669
 
    .cancelled_filenames=&cancelled_filenames,
4670
 
    .current_time=&current_time,
4671
 
    .mandos_client_exited=&mandos_client_exited,
4672
 
    .password_is_read=&password_is_read,
4673
 
  };
4674
 
  task.func(task, queue);
4675
 
  g_assert_false(quit_now);
4676
 
  g_assert_true(queue->next_run == 0);
4677
 
  g_assert_cmpuint((unsigned int)queue->length, ==, 1);
4678
 
 
4679
 
  g_assert_nonnull(find_matching_task(queue, (task_context){
4680
 
        .func=read_inotify_event,
4681
 
        .epoll_fd=epoll_fd,
4682
 
        .fd=pipefds[0],
4683
 
        .quit_now=&quit_now,
4684
 
        .password=&password,
4685
 
        .filename=task.filename,
4686
 
        .cancelled_filenames=&cancelled_filenames,
4687
 
        .current_time=&current_time,
4688
 
        .mandos_client_exited=&mandos_client_exited,
4689
 
        .password_is_read=&password_is_read,
4690
 
      }));
4691
 
 
4692
 
  g_assert_true(epoll_set_contains(epoll_fd, pipefds[0],
4693
 
                                   EPOLLIN | EPOLLRDHUP));
4694
 
 
4695
 
  __attribute__((cleanup(cleanup_string)))
4696
 
    char *filename = NULL;
4697
 
  g_assert_cmpint(asprintf(&filename, "%s/%s", task.filename,
4698
 
                           dummy_file_name), >, 0);
4699
 
  g_assert_nonnull(filename);
4700
 
  g_assert_false(string_set_contains(cancelled_filenames, filename));
4701
 
}
4702
 
 
4703
4333
static
4704
4334
void test_read_inotify_event_IN_DELETE_badname(__attribute__((unused))
4705
4335
                                               test_fixture *fixture,
4720
4350
  const size_t ievent_max_size = (sizeof(struct inotify_event)
4721
4351
                                  + NAME_MAX + 1);
4722
4352
  g_assert_cmpint(ievent_max_size, <=, PIPE_BUF);
4723
 
  struct {
4724
 
    struct inotify_event event;
4725
 
    char name_buffer[NAME_MAX + 1];
4726
 
  } ievent_buffer;
4727
 
  struct inotify_event *const ievent = &ievent_buffer.event;
 
4353
  char ievent_buffer[sizeof(struct inotify_event) + NAME_MAX + 1];
 
4354
  struct inotify_event *ievent = ((struct inotify_event *)
 
4355
                                  ievent_buffer);
4728
4356
 
4729
4357
  const char dummy_file_name[] = "ignored.dummy_file_name";
4730
4358
  ievent->mask = IN_DELETE;
4732
4360
  memcpy(ievent->name, dummy_file_name, sizeof(dummy_file_name));
4733
4361
  const size_t ievent_size = (sizeof(struct inotify_event)
4734
4362
                              + sizeof(dummy_file_name));
4735
 
  g_assert_cmpint(write(pipefds[1], (char *)ievent, ievent_size),
 
4363
  g_assert_cmpint(write(pipefds[1], ievent_buffer, ievent_size),
4736
4364
                  ==, ievent_size);
4737
4365
  g_assert_cmpint(close(pipefds[1]), ==, 0);
4738
4366
 
7945
7573
              test_add_inotify_dir_watch);
7946
7574
  test_add_st("/task-creators/add_inotify_dir_watch/fail",
7947
7575
              test_add_inotify_dir_watch_fail);
7948
 
  test_add_st("/task-creators/add_inotify_dir_watch/not-a-directory",
7949
 
              test_add_inotify_dir_watch_nondir);
7950
7576
  test_add_st("/task-creators/add_inotify_dir_watch/EAGAIN",
7951
7577
              test_add_inotify_dir_watch_EAGAIN);
7952
7578
  test_add_st("/task-creators/add_inotify_dir_watch/IN_CLOSE_WRITE",
7953
7579
              test_add_inotify_dir_watch_IN_CLOSE_WRITE);
7954
7580
  test_add_st("/task-creators/add_inotify_dir_watch/IN_MOVED_TO",
7955
7581
              test_add_inotify_dir_watch_IN_MOVED_TO);
7956
 
  test_add_st("/task-creators/add_inotify_dir_watch/IN_MOVED_FROM",
7957
 
              test_add_inotify_dir_watch_IN_MOVED_FROM);
7958
 
  test_add_st("/task-creators/add_inotify_dir_watch/IN_EXCL_UNLINK",
7959
 
              test_add_inotify_dir_watch_IN_EXCL_UNLINK);
7960
7582
  test_add_st("/task-creators/add_inotify_dir_watch/IN_DELETE",
7961
7583
              test_add_inotify_dir_watch_IN_DELETE);
7962
7584
  test_add_st("/task/read_inotify_event/readerror",
7971
7593
              test_read_inotify_event_IN_CLOSE_WRITE);
7972
7594
  test_add_st("/task/read_inotify_event/IN_MOVED_TO",
7973
7595
              test_read_inotify_event_IN_MOVED_TO);
7974
 
  test_add_st("/task/read_inotify_event/IN_MOVED_FROM",
7975
 
              test_read_inotify_event_IN_MOVED_FROM);
7976
7596
  test_add_st("/task/read_inotify_event/IN_DELETE",
7977
7597
              test_read_inotify_event_IN_DELETE);
7978
7598
  test_add_st("/task/read_inotify_event/IN_CLOSE_WRITE/badname",
7979
7599
              test_read_inotify_event_IN_CLOSE_WRITE_badname);
7980
7600
  test_add_st("/task/read_inotify_event/IN_MOVED_TO/badname",
7981
7601
              test_read_inotify_event_IN_MOVED_TO_badname);
7982
 
  test_add_st("/task/read_inotify_event/IN_MOVED_FROM/badname",
7983
 
              test_read_inotify_event_IN_MOVED_FROM_badname);
7984
7602
  test_add_st("/task/read_inotify_event/IN_DELETE/badname",
7985
7603
              test_read_inotify_event_IN_DELETE_badname);
7986
7604
  test_add_st("/task/open_and_parse_question/ENOENT",