]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Fix a bug that Clang Static Analyzer claimed it is potential insecure
authorMichihiro NAKAJIMA <ggcueroad@gmail.com>
Wed, 12 Sep 2012 05:32:06 +0000 (14:32 +0900)
committerMichihiro NAKAJIMA <ggcueroad@gmail.com>
Tue, 2 Oct 2012 22:46:57 +0000 (07:46 +0900)
implementation-specific behavior in call 'vfork' and recommended the
use of posix_spawn instead of vfork.

CMakeLists.txt
build/cmake/config.h.in
configure.ac
libarchive/filter_fork.c

index 662de0c4cc32c82a83a5fa7c5ed3c3f724f95f24..04b8234953e9d76a3701df81eef0272c47ed92f4 100644 (file)
@@ -414,6 +414,7 @@ LA_CHECK_INCLUDE_FILE("process.h" HAVE_PROCESS_H)
 LA_CHECK_INCLUDE_FILE("pwd.h" HAVE_PWD_H)
 LA_CHECK_INCLUDE_FILE("regex.h" HAVE_REGEX_H)
 LA_CHECK_INCLUDE_FILE("signal.h" HAVE_SIGNAL_H)
+LA_CHECK_INCLUDE_FILE("spawn.h" HAVE_SPAWN_H)
 LA_CHECK_INCLUDE_FILE("stdarg.h" HAVE_STDARG_H)
 LA_CHECK_INCLUDE_FILE("stdint.h" HAVE_STDINT_H)
 LA_CHECK_INCLUDE_FILE("stdlib.h" HAVE_STDLIB_H)
@@ -945,6 +946,7 @@ CHECK_FUNCTION_EXISTS_GLIBC(nl_langinfo HAVE_NL_LANGINFO)
 CHECK_FUNCTION_EXISTS_GLIBC(openat HAVE_OPENAT)
 CHECK_FUNCTION_EXISTS_GLIBC(pipe HAVE_PIPE)
 CHECK_FUNCTION_EXISTS_GLIBC(poll HAVE_POLL)
+CHECK_FUNCTION_EXISTS_GLIBC(posix_spawnp HAVE_POSIX_SPAWNP)
 CHECK_FUNCTION_EXISTS_GLIBC(readlink HAVE_READLINK)
 CHECK_FUNCTION_EXISTS_GLIBC(select HAVE_SELECT)
 CHECK_FUNCTION_EXISTS_GLIBC(setenv HAVE_SETENV)
index d1e92a35bd6be51e444f5c80c1c50689897dad91..8c40654e5ce5ec53aea026c33dcc6f2cffc45512 100644 (file)
@@ -706,6 +706,9 @@ typedef uint64_t uintmax_t;
 /* Define to 1 if you have the <poll.h> header file. */
 #cmakedefine HAVE_POLL_H 1
 
+/* Define to 1 if you have the `posix_spawnp' function. */
+#cmakedefine HAVE_POSIX_SPAWNP 1
+
 /* Define to 1 if you have the <process.h> header file. */
 #cmakedefine HAVE_PROCESS_H 1
 
@@ -739,6 +742,9 @@ typedef uint64_t uintmax_t;
 /* Define to 1 if you have the <signal.h> header file. */
 #cmakedefine HAVE_SIGNAL_H 1
 
+/* Define to 1 if you have the <spawn.h> header file. */
+#cmakedefine HAVE_SPAWN_H 1
+
 /* Define to 1 if you have the `statfs' function. */
 #cmakedefine HAVE_STATFS 1
 
index 0e2e0fd882512cbbb5afef320e251d9f0c0b1ab7..ce356eef8d1ebdeedfeaebab849e2998571fdaa0 100644 (file)
@@ -218,8 +218,8 @@ AS_VAR_IF([ac_cv_have_decl_EXT2_IOC_GETFLAGS], [yes],
 
 AC_CHECK_HEADERS([inttypes.h io.h langinfo.h limits.h])
 AC_CHECK_HEADERS([linux/fiemap.h linux/fs.h linux/magic.h linux/types.h])
-AC_CHECK_HEADERS([locale.h paths.h poll.h pwd.h regex.h signal.h stdarg.h])
-AC_CHECK_HEADERS([stdint.h stdlib.h string.h])
+AC_CHECK_HEADERS([locale.h paths.h poll.h pwd.h regex.h signal.h spawn.h])
+AC_CHECK_HEADERS([stdarg.h stdint.h stdlib.h string.h])
 AC_CHECK_HEADERS([sys/acl.h sys/cdefs.h sys/extattr.h sys/ioctl.h])
 AC_CHECK_HEADERS([sys/mkdev.h sys/mount.h])
 AC_CHECK_HEADERS([sys/param.h sys/poll.h sys/select.h sys/statfs.h sys/statvfs.h])
@@ -442,7 +442,7 @@ AC_CHECK_FUNCS([getpwnam_r getpwuid_r getvfsbyname gmtime_r])
 AC_CHECK_FUNCS([lchflags lchmod lchown link localtime_r lstat lutimes])
 AC_CHECK_FUNCS([mbrtowc memmove memset])
 AC_CHECK_FUNCS([mkdir mkfifo mknod mkstemp])
-AC_CHECK_FUNCS([nl_langinfo openat pipe poll readlink readlinkat])
+AC_CHECK_FUNCS([nl_langinfo openat pipe poll posix_spawnp readlink readlinkat])
 AC_CHECK_FUNCS([select setenv setlocale sigaction statfs statvfs])
 AC_CHECK_FUNCS([strchr strdup strerror strncpy_s strrchr symlink timegm])
 AC_CHECK_FUNCS([tzset unsetenv utime utimensat utimes vfork])
index d160524b097c1cd049bd1304aedfcb20b90e22a7..95796ac2b1c805e64e0ae8defdb8398a8e4f3226 100644 (file)
@@ -1,5 +1,6 @@
 /*-
  * Copyright (c) 2007 Joerg Sonnenberger
+ * Copyright (c) 2012 Michihiro NAKAJIMA 
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 
 /* This capability is only available on POSIX systems. */
 #if defined(HAVE_PIPE) && defined(HAVE_FCNTL) && \
-    (defined(HAVE_FORK) || defined(HAVE_VFORK))
+    (defined(HAVE_FORK) || defined(HAVE_VFORK) || defined(HAVE_POSIX_SPAWNP))
 
 __FBSDID("$FreeBSD: head/lib/libarchive/filter_fork.c 182958 2008-09-12 05:33:00Z kientzle $");
 
+#if defined(HAVE_SYS_TYPES_H)
+#  include <sys/types.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#  include <errno.h>
+#endif
+#ifdef HAVE_STRING_H
+#  include <string.h>
+#endif
 #if defined(HAVE_POLL) && (defined(HAVE_POLL_H) || defined(HAVE_SYS_POLL_H))
 #  if defined(HAVE_POLL_H)
 #    include <poll.h>
@@ -47,6 +57,12 @@ __FBSDID("$FreeBSD: head/lib/libarchive/filter_fork.c 182958 2008-09-12 05:33:00
 #ifdef HAVE_FCNTL_H
 #  include <fcntl.h>
 #endif
+#ifdef HAVE_SPAWN_H
+#  include <spawn.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#  include <stdlib.h>
+#endif
 #ifdef HAVE_UNISTD_H
 #  include <unistd.h>
 #endif
@@ -58,6 +74,11 @@ __archive_create_child(const char *path, int *child_stdin, int *child_stdout)
 {
        pid_t child;
        int stdin_pipe[2], stdout_pipe[2], tmp;
+#if HAVE_POSIX_SPAWNP
+       posix_spawn_file_actions_t actions;
+       char *argv[2];
+       int r;
+#endif
 
        if (pipe(stdin_pipe) == -1)
                goto state_allocated;
@@ -76,14 +97,58 @@ __archive_create_child(const char *path, int *child_stdin, int *child_stdout)
                stdout_pipe[1] = tmp;
        }
 
+#if HAVE_POSIX_SPAWNP
+
+       r = posix_spawn_file_actions_init(&actions);
+       if (r != 0) {
+               errno = r;
+               goto stdout_opened;
+       }
+       r = posix_spawn_file_actions_addclose(&actions, stdin_pipe[1]);
+       if (r != 0)
+               goto actions_inited;
+       r = posix_spawn_file_actions_addclose(&actions, stdout_pipe[0]);
+       if (r != 0)
+               goto actions_inited;
+       /* Setup for stdin. */
+       r = posix_spawn_file_actions_adddup2(&actions, stdin_pipe[0], 0);
+       if (r != 0)
+               goto actions_inited;
+       if (stdin_pipe[0] != 0 /* stdin */) {
+               r = posix_spawn_file_actions_addclose(&actions, stdin_pipe[0]);
+               if (r != 0)
+                       goto actions_inited;
+       }
+       /* Setup for stdout. */
+       r = posix_spawn_file_actions_adddup2(&actions, stdout_pipe[1], 1);
+       if (r != 0)
+               goto actions_inited;
+       if (stdout_pipe[1] != 1 /* stdout */) {
+               r = posix_spawn_file_actions_addclose(&actions, stdout_pipe[1]);
+               if (r != 0)
+                       goto actions_inited;
+       }
+       argv[0] = strdup(path);
+       if (argv[0] == NULL)
+               goto actions_inited2;
+       argv[1] = NULL;
+       r = posix_spawnp(&child, path, &actions, NULL,
+               (char ** const)argv, NULL);
+       free(argv[0]);
+       if (r != 0)
+               goto actions_inited;
+       posix_spawn_file_actions_destroy(&actions);
+
+#else /* HAVE_POSIX_SPAWNP */
+
 #if HAVE_VFORK
-       switch ((child = vfork())) {
+       child = vfork();
 #else
-       switch ((child = fork())) {
+       child = fork();
 #endif
-       case -1:
+       if (child == -1)
                goto stdout_opened;
-       case 0:
+       if (child == 0) {
                close(stdin_pipe[1]);
                close(stdout_pipe[0]);
                if (dup2(stdin_pipe[0], 0 /* stdin */) == -1)
@@ -96,18 +161,25 @@ __archive_create_child(const char *path, int *child_stdin, int *child_stdout)
                        close(stdout_pipe[1]);
                execlp(path, path, (char *)NULL);
                _exit(254);
-       default:
-               close(stdin_pipe[0]);
-               close(stdout_pipe[1]);
-
-               *child_stdin = stdin_pipe[1];
-               fcntl(*child_stdin, F_SETFL, O_NONBLOCK);
-               *child_stdout = stdout_pipe[0];
-               fcntl(*child_stdout, F_SETFL, O_NONBLOCK);
        }
+#endif /* HAVE_POSIX_SPAWNP */
+
+       close(stdin_pipe[0]);
+       close(stdout_pipe[1]);
+
+       *child_stdin = stdin_pipe[1];
+       fcntl(*child_stdin, F_SETFL, O_NONBLOCK);
+       *child_stdout = stdout_pipe[0];
+       fcntl(*child_stdout, F_SETFL, O_NONBLOCK);
 
        return child;
 
+#if HAVE_POSIX_SPAWNP
+actions_inited:
+       errno = r;
+actions_inited2:
+       posix_spawn_file_actions_destroy(&actions);
+#endif
 stdout_opened:
        close(stdout_pipe[0]);
        close(stdout_pipe[1]);