/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-08-03 11:39:38 UTC
  • Revision ID: teddy@recompile.se-20190803113938-httj8rqsnct08txx
dracut-module/password-agent.c: Bug fix: Ignore deleted files

If a question file ("ask.*") is opened, deleted, and then closed, we
still get an IN_CLOSE_WRITE ievent after the IN_DELETE ievent.  We
should pass the IN_EXCL_UNLINK flag to inotify_add_watch() to avoid
this.

* dracut-module/password-agent.c (add_inotify_dir_watch): Add
  "IN_EXCL_UNLINK" flag to inotify_add_watch().
  (test_add_inotify_dir_watch_IN_EXCL_UNLINK): New test.
  (run_tests): Add new test.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1018
1018
  }
1019
1019
 
1020
1020
  if(inotify_add_watch(fd, dir, IN_CLOSE_WRITE | IN_MOVED_TO
1021
 
                       | IN_MOVED_FROM| IN_DELETE)
 
1021
                       | IN_MOVED_FROM| IN_DELETE | IN_EXCL_UNLINK)
1022
1022
     == -1){
1023
1023
    error(0, errno, "Failed to create inotify watch on %s", dir);
1024
1024
    return false;
3807
3807
  g_assert_cmpint(rmdir(tempdir), ==, 0);
3808
3808
}
3809
3809
 
 
3810
static
 
3811
void test_add_inotify_dir_watch_IN_EXCL_UNLINK(__attribute__((unused))
 
3812
                                               test_fixture *fixture,
 
3813
                                               __attribute__((unused))
 
3814
                                               gconstpointer
 
3815
                                               user_data){
 
3816
  __attribute__((cleanup(cleanup_close)))
 
3817
    const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
 
3818
  g_assert_cmpint(epoll_fd, >=, 0);
 
3819
  __attribute__((cleanup(cleanup_queue)))
 
3820
    task_queue *queue = create_queue();
 
3821
  g_assert_nonnull(queue);
 
3822
  __attribute__((cleanup(string_set_clear)))
 
3823
    string_set cancelled_filenames = {};
 
3824
  const mono_microsecs current_time = 0;
 
3825
 
 
3826
  bool quit_now = false;
 
3827
  buffer password = {};
 
3828
  bool mandos_client_exited = false;
 
3829
  bool password_is_read = false;
 
3830
 
 
3831
  __attribute__((cleanup(cleanup_string)))
 
3832
    char *tempdir = make_temporary_directory();
 
3833
  g_assert_nonnull(tempdir);
 
3834
 
 
3835
  __attribute__((cleanup(cleanup_string)))
 
3836
    char *tempfile = make_temporary_file_in_directory(tempdir);
 
3837
  g_assert_nonnull(tempfile);
 
3838
  int tempfile_fd = open(tempfile, O_WRONLY | O_CLOEXEC | O_NOCTTY
 
3839
                         | O_NOFOLLOW);
 
3840
  g_assert_cmpint(tempfile_fd, >, 2);
 
3841
 
 
3842
  g_assert_true(add_inotify_dir_watch(queue, epoll_fd, &quit_now,
 
3843
                                      &password, tempdir,
 
3844
                                      &cancelled_filenames,
 
3845
                                      &current_time,
 
3846
                                      &mandos_client_exited,
 
3847
                                      &password_is_read));
 
3848
  g_assert_cmpint(unlink(tempfile), ==, 0);
 
3849
 
 
3850
  g_assert_cmpuint((unsigned int)queue->length, >, 0);
 
3851
 
 
3852
  const task_context *const added_read_task
 
3853
    = find_matching_task(queue,
 
3854
                         (task_context){ .func=read_inotify_event });
 
3855
  g_assert_nonnull(added_read_task);
 
3856
 
 
3857
  g_assert_cmpint(added_read_task->fd, >, 2);
 
3858
  g_assert_true(fd_has_cloexec_and_nonblock(added_read_task->fd));
 
3859
 
 
3860
  /* "sufficient to read at least one event." - inotify(7) */
 
3861
  const size_t ievent_size = (sizeof(struct inotify_event)
 
3862
                              + NAME_MAX + 1);
 
3863
  struct inotify_event *ievent = malloc(ievent_size);
 
3864
  g_assert_nonnull(ievent);
 
3865
 
 
3866
  ssize_t read_size = 0;
 
3867
  read_size = read(added_read_task->fd, ievent, ievent_size);
 
3868
 
 
3869
  g_assert_cmpint((int)read_size, >, 0);
 
3870
  g_assert_true(ievent->mask & IN_DELETE);
 
3871
  g_assert_cmpstr(ievent->name, ==, basename(tempfile));
 
3872
 
 
3873
  g_assert_cmpint(close(tempfile_fd), ==, 0);
 
3874
 
 
3875
  /* IN_EXCL_UNLINK should make the closing of the previously unlinked
 
3876
     file not appear as an ievent, so we should not see it now. */
 
3877
  read_size = read(added_read_task->fd, ievent, ievent_size);
 
3878
  g_assert_cmpint((int)read_size, ==, -1);
 
3879
  g_assert_true(errno == EAGAIN);
 
3880
 
 
3881
  free(ievent);
 
3882
 
 
3883
  g_assert_cmpint(rmdir(tempdir), ==, 0);
 
3884
}
 
3885
 
3810
3886
static void test_read_inotify_event_readerror(__attribute__((unused))
3811
3887
                                              test_fixture *fixture,
3812
3888
                                              __attribute__((unused))
7837
7913
              test_add_inotify_dir_watch_IN_MOVED_TO);
7838
7914
  test_add_st("/task-creators/add_inotify_dir_watch/IN_MOVED_FROM",
7839
7915
              test_add_inotify_dir_watch_IN_MOVED_FROM);
 
7916
  test_add_st("/task-creators/add_inotify_dir_watch/IN_EXCL_UNLINK",
 
7917
              test_add_inotify_dir_watch_IN_EXCL_UNLINK);
7840
7918
  test_add_st("/task-creators/add_inotify_dir_watch/IN_DELETE",
7841
7919
              test_add_inotify_dir_watch_IN_DELETE);
7842
7920
  test_add_st("/task/read_inotify_event/readerror",