s4-process_model: Do not close random fds while forking.
authorAndreas Schneider <asn@samba.org>
Thu, 26 Mar 2015 09:48:31 +0000 (10:48 +0100)
committerAndreas Schneider <asn@samba.org>
Thu, 26 Mar 2015 16:41:32 +0000 (17:41 +0100)
BUG: https://bugzilla.samba.org/show_bug.cgi?id=11180

The issue has been found with nss_wrapper debug output running:
    samba4.ntvfs.cifs.krb5.base.lock

In the case here, we fork a child and close the fd without resetting
the pipe fd variable. Then the fd was used to open the nss_wrapper
hosts file which got the same fd. We forked again in the process model
called close() on the re-used fd (of the pipe variable) again without
nss_wrapper noticing.  Now Samba opened the secrets tdb and got
the same fd as nss_wrapper was using for the hosts file and next
nss_wrapper tried to parse a TDB ...

Pair-Programmed-With: Michael Adam <obnox@samba.org>
Signed-off-by: Andreas Schneider <asn@samba.org>
Signed-off-by: Michael Adam <obnox@samba.org>
Reviewed-by: Stefan Metzmacher <metze@samba.org>
source4/smbd/process_standard.c

index d3622f9..e68dbb1 100644 (file)
@@ -42,7 +42,7 @@ NTSTATUS process_model_standard_init(void);
 /* we hold a pipe open in the parent, and the any child
    processes wait for EOF on that pipe. This ensures that
    children die when the parent dies */
-static int child_pipe[2];
+static int child_pipe[2] = { -1, -1 };
 
 /*
   called when the process model is selected
@@ -266,7 +266,10 @@ static void standard_accept_connection(struct tevent_context *ev,
 
        tevent_add_fd(ev, ev, child_pipe[0], TEVENT_FD_READ,
                      standard_pipe_handler, NULL);
-       close(child_pipe[1]);
+       if (child_pipe[1] != -1) {
+               close(child_pipe[1]);
+               child_pipe[1] = -1;
+       }
 
        /* Ensure that the forked children do not expose identical random streams */
        set_need_random_reseed();
@@ -342,7 +345,10 @@ static void standard_new_task(struct tevent_context *ev,
 
        tevent_add_fd(ev, ev, child_pipe[0], TEVENT_FD_READ,
                      standard_pipe_handler, NULL);
-       close(child_pipe[1]);
+       if (child_pipe[1] != -1) {
+               close(child_pipe[1]);
+               child_pipe[1] = -1;
+       }
 
        /* Ensure that the forked children do not expose identical random streams */
        set_need_random_reseed();