Print this page
6452 ilbd leaks lmalloc() memory due to posix_spawn() sloppiness
Reviewed by: Albert Lee <trisk@omniti.com>


   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  * Copyright 2012 Milan Jurik. All rights reserved.

  26  */
  27 
  28 #include <sys/types.h>
  29 #include <sys/socket.h>
  30 #include <sys/list.h>
  31 #include <sys/stropts.h>
  32 #include <sys/siginfo.h>
  33 #include <sys/wait.h>
  34 #include <arpa/inet.h>
  35 #include <netinet/in.h>
  36 #include <stdlib.h>
  37 #include <stdio.h>
  38 #include <strings.h>
  39 #include <stddef.h>
  40 #include <unistd.h>
  41 #include <libilb.h>
  42 #include <port.h>
  43 #include <time.h>
  44 #include <signal.h>
  45 #include <assert.h>


1271         pid_t                           pid;
1272         char                            *child_argv[HC_PROBE_ARGC];
1273         ilbd_hc_probe_event_t           *probe_ev;
1274         char                            *probe_name;
1275 
1276         bzero(child_argv, HC_PROBE_ARGC * sizeof (char *));
1277         if ((probe_ev = calloc(1, sizeof (*probe_ev))) == NULL) {
1278                 logdebug("ilbd_run_probe: calloc");
1279                 return (B_FALSE);
1280         }
1281 
1282         /* Set up a pipe to get output from probe command. */
1283         if (pipe(fds) < 0) {
1284                 logdebug("ilbd_run_probe: cannot create pipe");
1285                 free(probe_ev);
1286                 return (B_FALSE);
1287         }
1288         /* Set our side of the pipe to be non-blocking */
1289         if ((fdflags = fcntl(fds[0], F_GETFL, 0)) == -1) {
1290                 logdebug("ilbd_run_probe: fcntl(F_GETFL)");
1291                 goto cleanup;
1292         }
1293         if (fcntl(fds[0], F_SETFL, fdflags | O_NONBLOCK) == -1) {
1294                 logdebug("ilbd_run_probe: fcntl(F_SETFL)");
1295                 goto cleanup;
1296         }
1297 
1298         if (posix_spawn_file_actions_init(&fd_actions) != 0) {
1299                 logdebug("ilbd_run_probe: posix_spawn_file_actions_init");
1300                 goto cleanup;
1301         }
1302         if (posix_spawnattr_init(&attr) != 0) {
1303                 logdebug("ilbd_run_probe: posix_spawnattr_init");
1304                 goto cleanup;
1305         }
1306         if (posix_spawn_file_actions_addclose(&fd_actions, fds[0]) != 0) {
1307                 logdebug("ilbd_run_probe: posix_spawn_file_actions_addclose");
1308                 goto cleanup;
1309         }
1310         if (posix_spawn_file_actions_adddup2(&fd_actions, fds[1],
1311             STDOUT_FILENO) != 0) {
1312                 logdebug("ilbd_run_probe: posix_spawn_file_actions_dup2");
1313                 goto cleanup;
1314         }
1315         if (posix_spawn_file_actions_addclose(&fd_actions, fds[1]) != 0) {
1316                 logdebug("ilbd_run_probe: posix_spawn_file_actions_addclose");
1317                 goto cleanup;
1318         }
1319 
1320         /* Reset all signal handling of the child to default. */
1321         (void) sigfillset(&child_sigset);
1322         if (posix_spawnattr_setsigdefault(&attr, &child_sigset) != 0) {
1323                 logdebug("ilbd_run_probe: posix_spawnattr_setsigdefault");
1324                 goto cleanup;


1338         /*
1339          * If we are doing default pinging or not using a user supplied
1340          * probe, we should execute our standard supplied probe.  The
1341          * supplied probe command handles all types of probes.  And the
1342          * type used depends on argv[0], as filled in by create_argv().
1343          */
1344         if (srv->shc_state == ilbd_hc_def_pinging ||
1345             srv->shc_hc->ihc_test_type != ILBD_HC_USER) {
1346                 probe_name = ILB_PROBE_PROTO;
1347         } else {
1348                 probe_name = srv->shc_hc->ihc_test;
1349         }
1350         if (posix_spawn(&pid, probe_name, &fd_actions, &attr, child_argv,
1351             NULL) != 0) {
1352                 logerr("%s: posix_spawn: %s for server %s: %s", __func__,
1353                     srv->shc_hc->ihc_test, srv->shc_sg_srv->sgs_srvID,
1354                     strerror(errno));
1355                 goto cleanup;
1356         }
1357 


1358         (void) close(fds[1]);
1359         destroy_argv(child_argv);
1360         srv->shc_child_pid = pid;
1361         srv->shc_child_fd = fds[0];
1362         srv->shc_ev = probe_ev;
1363 
1364         probe_ev->ihp_ev = ILBD_EVENT_PROBE;
1365         probe_ev->ihp_srv = srv;
1366         probe_ev->ihp_pid = pid;
1367         if (port_associate(srv->shc_ev_port, PORT_SOURCE_FD, fds[0],
1368             POLLRDNORM, probe_ev) != 0) {
1369                 /*
1370                  * Need to kill the child.  It will free the srv->shc_ev,
1371                  * which is probe_ev.  So set probe_ev to NULL.
1372                  */
1373                 ilbd_hc_kill_probe(srv);
1374                 probe_ev = NULL;
1375                 goto cleanup;

1376         }

1377 
1378         return (B_TRUE);
1379 
1380 cleanup:




1381         (void) close(fds[0]);
1382         (void) close(fds[1]);
1383         destroy_argv(child_argv);
1384         if (probe_ev != NULL)
1385                 free(probe_ev);
1386         return (B_FALSE);
1387 }
1388 
1389 /*
1390  * Called by ild_hc_probe_return() to re-associate the fd to a child to
1391  * the event port.
1392  */
1393 static void
1394 reassociate_port(int ev_port, int fd, ilbd_hc_probe_event_t *ev)
1395 {
1396         if (port_associate(ev_port, PORT_SOURCE_FD, fd,
1397             POLLRDNORM, ev) != 0) {
1398                 /*
1399                  * If we cannot reassociate with the port, the only
1400                  * thing we can do now is to kill the child and




   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  * Copyright 2012 Milan Jurik. All rights reserved.
  26  * Copyright 2015 OmniTI Computer Consulting, Inc. All rights reserved.
  27  */
  28 
  29 #include <sys/types.h>
  30 #include <sys/socket.h>
  31 #include <sys/list.h>
  32 #include <sys/stropts.h>
  33 #include <sys/siginfo.h>
  34 #include <sys/wait.h>
  35 #include <arpa/inet.h>
  36 #include <netinet/in.h>
  37 #include <stdlib.h>
  38 #include <stdio.h>
  39 #include <strings.h>
  40 #include <stddef.h>
  41 #include <unistd.h>
  42 #include <libilb.h>
  43 #include <port.h>
  44 #include <time.h>
  45 #include <signal.h>
  46 #include <assert.h>


1272         pid_t                           pid;
1273         char                            *child_argv[HC_PROBE_ARGC];
1274         ilbd_hc_probe_event_t           *probe_ev;
1275         char                            *probe_name;
1276 
1277         bzero(child_argv, HC_PROBE_ARGC * sizeof (char *));
1278         if ((probe_ev = calloc(1, sizeof (*probe_ev))) == NULL) {
1279                 logdebug("ilbd_run_probe: calloc");
1280                 return (B_FALSE);
1281         }
1282 
1283         /* Set up a pipe to get output from probe command. */
1284         if (pipe(fds) < 0) {
1285                 logdebug("ilbd_run_probe: cannot create pipe");
1286                 free(probe_ev);
1287                 return (B_FALSE);
1288         }
1289         /* Set our side of the pipe to be non-blocking */
1290         if ((fdflags = fcntl(fds[0], F_GETFL, 0)) == -1) {
1291                 logdebug("ilbd_run_probe: fcntl(F_GETFL)");
1292                 goto cleanup_noactions;
1293         }
1294         if (fcntl(fds[0], F_SETFL, fdflags | O_NONBLOCK) == -1) {
1295                 logdebug("ilbd_run_probe: fcntl(F_SETFL)");
1296                 goto cleanup_noactions;
1297         }
1298 
1299         if (posix_spawn_file_actions_init(&fd_actions) != 0) {
1300                 logdebug("ilbd_run_probe: posix_spawn_file_actions_init");
1301                 goto cleanup_noactions;
1302         }
1303         if (posix_spawnattr_init(&attr) != 0) {
1304                 logdebug("ilbd_run_probe: posix_spawnattr_init");
1305                 goto cleanup_noattr;
1306         }
1307         if (posix_spawn_file_actions_addclose(&fd_actions, fds[0]) != 0) {
1308                 logdebug("ilbd_run_probe: posix_spawn_file_actions_addclose");
1309                 goto cleanup;
1310         }
1311         if (posix_spawn_file_actions_adddup2(&fd_actions, fds[1],
1312             STDOUT_FILENO) != 0) {
1313                 logdebug("ilbd_run_probe: posix_spawn_file_actions_dup2");
1314                 goto cleanup;
1315         }
1316         if (posix_spawn_file_actions_addclose(&fd_actions, fds[1]) != 0) {
1317                 logdebug("ilbd_run_probe: posix_spawn_file_actions_addclose");
1318                 goto cleanup;
1319         }
1320 
1321         /* Reset all signal handling of the child to default. */
1322         (void) sigfillset(&child_sigset);
1323         if (posix_spawnattr_setsigdefault(&attr, &child_sigset) != 0) {
1324                 logdebug("ilbd_run_probe: posix_spawnattr_setsigdefault");
1325                 goto cleanup;


1339         /*
1340          * If we are doing default pinging or not using a user supplied
1341          * probe, we should execute our standard supplied probe.  The
1342          * supplied probe command handles all types of probes.  And the
1343          * type used depends on argv[0], as filled in by create_argv().
1344          */
1345         if (srv->shc_state == ilbd_hc_def_pinging ||
1346             srv->shc_hc->ihc_test_type != ILBD_HC_USER) {
1347                 probe_name = ILB_PROBE_PROTO;
1348         } else {
1349                 probe_name = srv->shc_hc->ihc_test;
1350         }
1351         if (posix_spawn(&pid, probe_name, &fd_actions, &attr, child_argv,
1352             NULL) != 0) {
1353                 logerr("%s: posix_spawn: %s for server %s: %s", __func__,
1354                     srv->shc_hc->ihc_test, srv->shc_sg_srv->sgs_srvID,
1355                     strerror(errno));
1356                 goto cleanup;
1357         }
1358 
1359         (void) posix_spawnattr_destroy(&attr);
1360         (void) posix_spawn_file_actions_destroy(&fd_actions);
1361         (void) close(fds[1]);

1362         srv->shc_child_pid = pid;
1363         srv->shc_child_fd = fds[0];
1364         srv->shc_ev = probe_ev;
1365 
1366         probe_ev->ihp_ev = ILBD_EVENT_PROBE;
1367         probe_ev->ihp_srv = srv;
1368         probe_ev->ihp_pid = pid;
1369         if (port_associate(srv->shc_ev_port, PORT_SOURCE_FD, fds[0],
1370             POLLRDNORM, probe_ev) != 0) {
1371                 /*
1372                  * Need to kill the child.  It will free the srv->shc_ev,
1373                  * which is probe_ev.  So set probe_ev to NULL.
1374                  */
1375                 ilbd_hc_kill_probe(srv);
1376                 probe_ev = NULL;
1377                 /* posix_spawn attrs & actions already destroyed. */
1378                 goto cleanup_noactions;
1379         }
1380         destroy_argv(child_argv);
1381 
1382         return (B_TRUE);
1383 
1384 cleanup:
1385         (void) posix_spawnattr_destroy(&attr);
1386 cleanup_noattr:
1387         (void) posix_spawn_file_actions_destroy(&fd_actions);
1388 cleanup_noactions:
1389         (void) close(fds[0]);
1390         (void) close(fds[1]);
1391         destroy_argv(child_argv);
1392         if (probe_ev != NULL)
1393                 free(probe_ev);
1394         return (B_FALSE);
1395 }
1396 
1397 /*
1398  * Called by ild_hc_probe_return() to re-associate the fd to a child to
1399  * the event port.
1400  */
1401 static void
1402 reassociate_port(int ev_port, int fd, ilbd_hc_probe_event_t *ev)
1403 {
1404         if (port_associate(ev_port, PORT_SOURCE_FD, fd,
1405             POLLRDNORM, ev) != 0) {
1406                 /*
1407                  * If we cannot reassociate with the port, the only
1408                  * thing we can do now is to kill the child and