summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>2014-02-07 21:34:06 +0000
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>2014-02-07 21:34:06 +0000
commitc82f05eadbc1e63c258313eda5ec7b0c571f7c93 (patch)
tree80babf2a20ad11383a2b8b48fd7811b51e349aab
parent7e86f2f686334cb3db458b4585dfce9c1b712bc4 (diff)
downloadcups-c82f05eadbc1e63c258313eda5ec7b0c571f7c93.tar.gz
<rdar://problem/15958253> 14A125b: cupsd console output when launching AddPrinter
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
-rw-r--r--config-scripts/cups-common.m43
-rw-r--r--config.h.in7
-rw-r--r--scheduler/cups-exec.c64
-rw-r--r--scheduler/process.c115
-rw-r--r--xcode/config.h7
5 files changed, 165 insertions, 31 deletions
diff --git a/config-scripts/cups-common.m4 b/config-scripts/cups-common.m4
index 52e995011..0b66ac467 100644
--- a/config-scripts/cups-common.m4
+++ b/config-scripts/cups-common.m4
@@ -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;
diff --git a/config.h.in b/config.h.in
index 463b572f2..863c66757 100644
--- a/config.h.in
+++ b/config.h.in
@@ -132,6 +132,13 @@
/*
+ * Do we have posix_spawn?
+ */
+
+#undef HAVE_POSIX_SPAWN
+
+
+/*
* Do we have ZLIB?
*/
diff --git a/scheduler/cups-exec.c b/scheduler/cups-exec.c
index ee5981751..0d8a764d7 100644
--- a/scheduler/cups-exec.c
+++ b/scheduler/cups-exec.c
@@ -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...
@@ -75,10 +82,35 @@ 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...
diff --git a/scheduler/process.c b/scheduler/process.c
index 44ebf7324..97da1eaa2 100644
--- a/scheduler/process.c
+++ b/scheduler/process.c
@@ -22,6 +22,10 @@
#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, "
diff --git a/xcode/config.h b/xcode/config.h
index 10996f3de..00b369141 100644
--- a/xcode/config.h
+++ b/xcode/config.h
@@ -132,6 +132,13 @@
/*
+ * Do we have posix_spawn?
+ */
+
+#define HAVE_POSIX_SPAWN 1
+
+
+/*
* Do we have ZLIB?
*/