/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 at recompile
  • Date: 2020-04-05 21:30:59 UTC
  • Revision ID: teddy@recompile.se-20200405213059-fb2a61ckqynrmatk
Fix file descriptor leak in mandos-client

When the local network has Mandos servers announcing themselves using
real, globally reachable, IPv6 addresses (i.e. not link-local
addresses), but there is no router on the local network providing IPv6
RA (Router Advertisement) packets, the client cannot reach the server
by normal means, since the client only has a link-local IPv6 address,
and has no usable route to reach the server's global IPv6 address.
(This is not a common situation, and usually only happens when the
router itself reboots and runs a Mandos client, since it cannot then
give RA packets to itself.)  The client code has a solution for
this, which consists of adding a temporary local route to reach the
address of the server during communication, and removing this
temporary route afterwards.

This solution with a temporary route works, but has a file descriptor
leak; it leaks one file descriptor for each addition and for each
removal of a route.  If one server requiring an added route is present
on the network, but no servers gives a password, making the client
retry after the default ten seconds, and we furthermore assume a
default 1024 open files limit, the client runs out of file descriptors
after about 90 minutes, after which time the client process will be
useless and fail to retrieve any passwords, necessitating manual
password entry via the keyboard.

Fix this by eliminating the file descriptor leak in the client.

* plugins.d/mandos-client.c (add_delete_local_route): Do
  close(devnull) also in parent process, also if fork() fails, and on
  any failure in child process.

Show diffs side-by-side

added added

removed removed

Lines of Context:
868
868
  }
869
869
  close(pipefds[1]);
870
870
 
 
871
  if(pid == -1){
 
872
    error(0, errno, "Failed to fork()");
 
873
    close(pipefds[0]);
 
874
    return false;
 
875
  }
 
876
 
871
877
  if(not add_to_queue(queue, (task_context){
872
878
        .func=wait_for_mandos_client_exit,
873
879
        .pid=pid,
2190
2196
    }
2191
2197
    exit(EXIT_SUCCESS);
2192
2198
  }
 
2199
  if(pid == -1){
 
2200
    error(EXIT_FAILURE, errno, "Failed to fork()");
 
2201
  }
 
2202
 
2193
2203
  int status;
2194
2204
  waitpid(pid, &status, 0);
2195
2205
  if(WIFEXITED(status) and (WEXITSTATUS(status) == EXIT_SUCCESS)){
5948
5958
                                           test_fixture *fixture,
5949
5959
                                           __attribute__((unused))
5950
5960
                                           gconstpointer user_data){
 
5961
#ifndef __amd64__
 
5962
  g_test_skip("Skipping EMSGSIZE test on non-AMD64 platform");
 
5963
#else
5951
5964
  __attribute__((cleanup(cleanup_close)))
5952
5965
    const int epoll_fd = epoll_create1(EPOLL_CLOEXEC);
5953
5966
  g_assert_cmpint(epoll_fd, >=, 0);
6006
6019
  g_assert_cmpuint((unsigned int)queue->length, ==, 0);
6007
6020
  g_assert_true(string_set_contains(cancelled_filenames,
6008
6021
                                    question_filename));
 
6022
#endif
6009
6023
}
6010
6024
 
6011
6025
static void test_send_password_to_socket_retry(__attribute__((unused))