From c82f05eadbc1e63c258313eda5ec7b0c571f7c93 Mon Sep 17 00:00:00 2001 From: msweet Date: Fri, 7 Feb 2014 21:34:06 +0000 Subject: [PATCH] 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 --- config-scripts/cups-common.m4 | 3 + config.h.in | 7 +++ scheduler/cups-exec.c | 64 ++++++++++++++----- scheduler/process.c | 115 +++++++++++++++++++++++++++++----- xcode/config.h | 7 +++ 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 ],[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 @@ -131,6 +131,13 @@ #define CUPS_STATEDIR "/var/run/cups" +/* + * 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 #include +#include +#include #ifdef HAVE_SANDBOX_H # include # 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... 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 #endif /* __APPLE__ */ +#ifdef HAVE_POSIX_SPAWN +# include +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 @@ -131,6 +131,13 @@ #define CUPS_STATEDIR "/private/etc/cups" +/* + * Do we have posix_spawn? + */ + +#define HAVE_POSIX_SPAWN 1 + + /* * Do we have ZLIB? */ -- 2.39.5