]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
<rdar://problem/15958253> 14A125b: cupsd console output when launching AddPrinter
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Fri, 7 Feb 2014 21:34:06 +0000 (21:34 +0000)
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Fri, 7 Feb 2014 21:34:06 +0000 (21:34 +0000)
Use posix_spawn and move all of the setuid/setgid/setgroups/nice stuff to
cups-exec.

git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@11564 a1ca3aef-8c08-0410-bb20-df032aa958be

config-scripts/cups-common.m4
config.h.in
scheduler/cups-exec.c
scheduler/process.c
xcode/config.h

index 52e995011a65bdad43d3e0ba4d4106ff6d135ea8..0b66ac467628fc80053e53d79462f9d64008a6a5 100644 (file)
@@ -200,6 +200,9 @@ AC_CHECK_FUNCS(sigaction)
 dnl Checks for wait functions.
 AC_CHECK_FUNCS(waitpid wait3)
 
+dnl Check for posix_spawn
+AC_CHECK_FUNCS(posix_spawn)
+
 dnl See if the tm structure has the tm_gmtoff member...
 AC_MSG_CHECKING(for tm_gmtoff member in tm structure)
 AC_TRY_COMPILE([#include <time.h>],[struct tm t;
index 463b572f2304b30c4e4d50c9b12792208b32b99f..863c667574b03390c50c223eb0ca0c06e499dfac 100644 (file)
 #define CUPS_STATEDIR  "/var/run/cups"
 
 
+/*
+ * Do we have posix_spawn?
+ */
+
+#undef HAVE_POSIX_SPAWN
+
+
 /*
  * Do we have ZLIB?
  */
index ee5981751888ed0ab6c5cb9ed03dbcc05f0abb0b..0d8a764d78f78d77358019d2b6f3720b0cc0cf8a 100644 (file)
@@ -1,23 +1,19 @@
 /*
  * "$Id$"
  *
- *   Sandbox helper for CUPS.
+ * Sandbox helper for CUPS.
  *
- *   Copyright 2007-2013 by Apple Inc.
+ * Copyright 2007-2014 by Apple Inc.
  *
- *   These coded instructions, statements, and computer programs are the
- *   property of Apple Inc. and are protected by Federal copyright
- *   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
- *   which should have been included with this file.  If this file is
- *   file is missing or damaged, see the license at "http://www.cups.org/".
+ * These coded instructions, statements, and computer programs are the
+ * property of Apple Inc. and are protected by Federal copyright
+ * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
+ * which should have been included with this file.  If this file is
+ * file is missing or damaged, see the license at "http://www.cups.org/".
  *
  * Usage:
  *
- *     cups-exec /path/to/profile /path/to/program argv0 argv1 ... argvN
- *
- * Contents:
- *
- *   main() - Apply sandbox profile and execute program.
+ *     cups-exec /path/to/profile UID GID NICE /path/to/program argv0 argv1 ... argvN
  */
 
 /*
@@ -26,6 +22,8 @@
 
 #include <cups/string-private.h>
 #include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
 #ifdef HAVE_SANDBOX_H
 #  include <sandbox.h>
 #  ifndef SANDBOX_NAMED_EXTERNAL
@@ -43,6 +41,9 @@ int                                   /* O - Exit status */
 main(int  argc,                                /* I - Number of command-line args */
      char *argv[])                     /* I - Command-line arguments */
 {
+  uid_t        uid;                            /* UID */
+  gid_t        gid;                            /* GID */
+  int  niceval;                        /* Nice value */
 #ifdef HAVE_SANDBOX_H
   char *sandbox_error = NULL;          /* Sandbox error, if any */
 #endif /* HAVE_SANDBOX_H */
@@ -52,13 +53,19 @@ main(int  argc,                             /* I - Number of command-line args */
   * Check that we have enough arguments...
   */
 
-  if (argc < 4)
+  if (argc < 7)
   {
-    puts("Usage: cups-exec /path/to/profile /path/to/program argv0 argv1 ... "
-         "argvN");
+    puts("Usage: cups-exec /path/to/profile UID GID NICE /path/to/program argv0 argv1 ... argvN");
     return (1);
   }
 
+ /*
+  * Make sure side and back channel FDs are non-blocking...
+  */
+
+  fcntl(3, F_SETFL, O_NDELAY);
+  fcntl(4, F_SETFL, O_NDELAY);
+
 #ifdef HAVE_SANDBOX_H
  /*
   * Run in a separate security profile...
@@ -74,11 +81,36 @@ main(int  argc,                             /* I - Number of command-line args */
   }
 #endif /* HAVE_SANDBOX_H */
 
+ /*
+  * Change UID, GID, and nice value...
+  */
+
+  uid     = (uid_t)atoi(argv[2]);
+  gid     = (gid_t)atoi(argv[3]);
+  niceval = atoi(argv[4]);
+
+  if (uid)
+    nice(niceval);
+
+  if (!getuid())
+  {
+    if (setgid(gid))
+      exit(errno + 100);
+
+    if (setgroups(1, &gid))
+      exit(errno + 100);
+
+    if (uid && setuid(uid))
+      exit(errno + 100);
+  }
+
+  umask(077);
+
  /*
   * Execute the program...
   */
 
-  execv(argv[2], argv + 3);
+  execv(argv[5], argv + 6);
 
  /*
   * If we get here, execv() failed...
index 44ebf7324f80f8f8d7bb30e896a5a19c80c47625..97da1eaa231987e65d0f10e8f67b6faba63e54fc 100644 (file)
 #ifdef __APPLE__
 #  include <libgen.h>
 #endif /* __APPLE__ */
+#ifdef HAVE_POSIX_SPAWN
+#  include <spawn.h>
+extern char **environ;
+#endif /* HAVE_POSIX_SPAWN */
 
 
 /*
@@ -316,10 +320,17 @@ cupsdStartProcess(
 {
   int          i;                      /* Looping var */
   const char   *exec_path = command;   /* Command to be exec'd */
-  char         *real_argv[103],        /* Real command-line arguments */
+  char         *real_argv[107],        /* Real command-line arguments */
                cups_exec[1024];        /* Path to "cups-exec" program */
   uid_t                user;                   /* Command UID */
   cupsd_proc_t *proc;                  /* New process record */
+#ifdef HAVE_POSIX_SPAWN
+  posix_spawn_file_actions_t actions;  /* Spawn file actions */
+  posix_spawnattr_t attrs;             /* Spawn attributes */
+  char         user_str[16],           /* User string */
+               group_str[16],          /* Group string */
+               nice_str[16];           /* FilterNice string */
+#endif /* HAVE_POSIX_SPAWN */
 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
   struct sigaction action;             /* POSIX signal handler */
 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
@@ -386,25 +397,97 @@ cupsdStartProcess(
   * Use helper program when we have a sandbox profile...
   */
 
+#ifndef HAVE_POSIX_SPAWN
   if (profile)
+#endif /* !HAVE_POSIX_SPAWN */
   {
     snprintf(cups_exec, sizeof(cups_exec), "%s/daemon/cups-exec", ServerBin);
+    snprintf(user_str, sizeof(user_str), "%d", User);
+    snprintf(group_str, sizeof(group_str), "%d", Group);
+    snprintf(nice_str, sizeof(nice_str), "%d", FilterNice);
 
     real_argv[0] = cups_exec;
     real_argv[1] = profile;
-    real_argv[2] = (char *)command;
+    real_argv[2] = user_str;
+    real_argv[3] = group_str;
+    real_argv[4] = nice_str;
+    real_argv[5] = (char *)command;
 
     for (i = 0;
-         i < (int)(sizeof(real_argv) / sizeof(real_argv[0]) - 4) && argv[i];
+         i < (int)(sizeof(real_argv) / sizeof(real_argv[0]) - 7) && argv[i];
         i ++)
-      real_argv[i + 3] = argv[i];
+      real_argv[i + 6] = argv[i];
 
-    real_argv[i + 3] = NULL;
+    real_argv[i + 6] = NULL;
 
     argv      = real_argv;
     exec_path = cups_exec;
   }
 
+  if (LogLevel == CUPSD_LOG_DEBUG2)
+  {
+    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Preparing to start \"%s\", arguments:", command);
+
+    for (i = 0; argv[i]; i ++)
+      cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: argv[%d] = \"%s\"", i, argv[i]);
+  }
+
+#ifdef HAVE_POSIX_SPAWN
+ /*
+  * Setup attributes and file actions for the spawn...
+  */
+
+  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Setting spawn attributes.");
+  posix_spawnattr_init(&attrs);
+  posix_spawnattr_setflags(&attrs, POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_SETSIGDEF);
+
+  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Setting file actions.");
+  posix_spawn_file_actions_init(&actions);
+  if (infd != 0)
+  {
+    if (infd < 0)
+      posix_spawn_file_actions_addopen(&actions, 0, "/dev/null", O_WRONLY, 0);
+    else
+      posix_spawn_file_actions_adddup2(&actions, infd, 0);
+  }
+
+  if (outfd != 1)
+  {
+    if (outfd < 0)
+      posix_spawn_file_actions_addopen(&actions, 1, "/dev/null", O_WRONLY, 0);
+    else
+      posix_spawn_file_actions_adddup2(&actions, outfd, 1);
+  }
+
+  if (errfd != 2)
+  {
+    if (errfd < 0)
+      posix_spawn_file_actions_addopen(&actions, 2, "/dev/null", O_WRONLY, 0);
+    else
+      posix_spawn_file_actions_adddup2(&actions, errfd, 2);
+  }
+
+  if (backfd != 3 && backfd >= 0)
+    posix_spawn_file_actions_adddup2(&actions, backfd, 3);
+
+  if (sidefd != 4 && sidefd >= 0)
+    posix_spawn_file_actions_adddup2(&actions, sidefd, 4);
+
+  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Calling posix_spawn.");
+
+  if (posix_spawn(pid, exec_path, &actions, &attrs, argv, envp ? envp : environ))
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to fork %s - %s.", command, strerror(errno));
+
+    *pid = 0;
+  }
+  else
+    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: pid=%d", (int)*pid);
+
+  posix_spawn_file_actions_destroy(&actions);
+  posix_spawnattr_destroy(&attrs);
+
+#else
  /*
   * Block signals before forking...
   */
@@ -434,13 +517,13 @@ cupsdStartProcess(
     * processes it creates.
     */
 
-#ifdef HAVE_SETPGID
+#  ifdef HAVE_SETPGID
     if (!RunUser && setpgid(0, 0))
       exit(errno + 100);
-#else
+#  else
     if (!RunUser && setpgrp())
       exit(errno + 100);
-#endif /* HAVE_SETPGID */
+#  endif /* HAVE_SETPGID */
 
    /*
     * Update the remaining file descriptors as needed...
@@ -519,11 +602,11 @@ cupsdStartProcess(
     * Unblock signals before doing the exec...
     */
 
-#ifdef HAVE_SIGSET
+#  ifdef HAVE_SIGSET
     sigset(SIGTERM, SIG_DFL);
     sigset(SIGCHLD, SIG_DFL);
     sigset(SIGPIPE, SIG_DFL);
-#elif defined(HAVE_SIGACTION)
+#  elif defined(HAVE_SIGACTION)
     memset(&action, 0, sizeof(action));
 
     sigemptyset(&action.sa_mask);
@@ -532,11 +615,11 @@ cupsdStartProcess(
     sigaction(SIGTERM, &action, NULL);
     sigaction(SIGCHLD, &action, NULL);
     sigaction(SIGPIPE, &action, NULL);
-#else
+#  else
     signal(SIGTERM, SIG_DFL);
     signal(SIGCHLD, SIG_DFL);
     signal(SIGPIPE, SIG_DFL);
-#endif /* HAVE_SIGSET */
+#  endif /* HAVE_SIGSET */
 
     cupsdReleaseSignals();
 
@@ -563,7 +646,11 @@ cupsdStartProcess(
 
     *pid = 0;
   }
-  else
+
+  cupsdReleaseSignals();
+#endif /* HAVE_POSIX_SPAWN */
+
+  if (*pid)
   {
     if (!process_array)
       process_array = cupsArrayNew((cups_array_func_t)compare_procs, NULL);
@@ -581,8 +668,6 @@ cupsdStartProcess(
     }
   }
 
-  cupsdReleaseSignals();
-
   cupsdLogMessage(CUPSD_LOG_DEBUG2,
                  "cupsdStartProcess(command=\"%s\", argv=%p, envp=%p, "
                  "infd=%d, outfd=%d, errfd=%d, backfd=%d, sidefd=%d, root=%d, "
index 10996f3de1632e2129a5e0139ff6255e72f909d2..00b369141872d217a1f45a867ec9459c1d2dfb9f 100644 (file)
 #define CUPS_STATEDIR "/private/etc/cups"
 
 
+/*
+ * Do we have posix_spawn?
+ */
+
+#define HAVE_POSIX_SPAWN 1
+
+
 /*
  * Do we have ZLIB?
  */