/*
- * "$Id$"
- *
* Process management routines for the CUPS scheduler.
*
- * Copyright 2007-2014 by Apple Inc.
+ * Copyright 2007-2015 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
# include <spawn.h>
extern char **environ;
#endif /* HAVE_POSIX_SPAWN */
+#ifdef HAVE_POSIX_SPAWN
+# if !defined(__OpenBSD__) || OpenBSD >= 201505
+# define USE_POSIX_SPAWN 1
+# else
+# define USE_POSIX_SPAWN 0
+# endif /* !__OpenBSD__ || */
+#else
+# define USE_POSIX_SPAWN 0
+#endif /* HAVE_POSIX_SPAWN */
/*
domain[1024], /* Domain socket, if any */
request[1024], /* Quoted RequestRoot */
root[1024], /* Quoted ServerRoot */
+ state[1024], /* Quoted StateDir */
temp[1024]; /* Quoted TempDir */
const char *nodebug; /* " (with no-log)" for no debug */
cupsd_listener_t *lis; /* Current listening socket */
cupsd_requote(cache, CacheDir, sizeof(cache));
cupsd_requote(request, RequestRoot, sizeof(request));
cupsd_requote(root, ServerRoot, sizeof(root));
+ cupsd_requote(state, StateDir, sizeof(state));
cupsd_requote(temp, TempDir, sizeof(temp));
nodebug = LogLevel < CUPSD_LOG_DEBUG ? " (with no-log)" : "";
cupsFilePuts(fp, "(allow ipc-posix-shm)\n");
cupsFilePuts(fp, "(allow ipc-sysv-shm)\n");
cupsFilePuts(fp, "(allow mach-lookup)\n");
- cupsFilePrintf(fp,
- "(deny file-write* file-read-data file-read-metadata\n"
- " (regex"
- " #\"^%s$\"" /* RequestRoot */
- " #\"^%s/\"" /* RequestRoot/... */
- ")%s)\n",
- request, request, nodebug);
if (!RunUser)
cupsFilePrintf(fp,
"(deny file-write* file-read-data file-read-metadata\n"
"))\n",
request);
/* Read and write TempDir, CacheDir, and other common folders */
+ cupsFilePuts(fp,
+ "(allow file-write* file-read-data file-read-metadata\n"
+ " (regex"
+ " #\"^/private/var/db/\""
+ " #\"^/private/var/folders/\""
+ " #\"^/private/var/lib/\""
+ " #\"^/private/var/log/\""
+ " #\"^/private/var/mysql/\""
+ " #\"^/private/var/run/\""
+ " #\"^/private/var/spool/\""
+ " #\"^/Library/Application Support/\""
+ " #\"^/Library/Caches/\""
+ " #\"^/Library/Logs/\""
+ " #\"^/Library/Preferences/\""
+ " #\"^/Library/WebServer/\""
+ " #\"^/Users/Shared/\""
+ "))\n");
+ cupsFilePrintf(fp,
+ "(deny file-write*\n"
+ " (regex #\"^%s$\")%s)\n",
+ request, nodebug);
+ cupsFilePrintf(fp,
+ "(deny file-write* file-read-data file-read-metadata\n"
+ " (regex #\"^%s/\")%s)\n",
+ request, nodebug);
cupsFilePrintf(fp,
"(allow file-write* file-read-data file-read-metadata\n"
" (regex"
" #\"^%s/\"" /* TempDir/... */
" #\"^%s$\"" /* CacheDir */
" #\"^%s/\"" /* CacheDir/... */
- " #\"^/private/var/folders/\""
- " #\"^/Library/Application Support/\""
- " #\"^/Library/Caches/\""
- " #\"^/Library/Preferences/\""
- " #\"^/Users/Shared/\""
+ " #\"^%s$\"" /* StateDir */
+ " #\"^%s/\"" /* StateDir/... */
"))\n",
- temp, temp, cache, cache);
+ temp, temp, cache, cache, state, state);
/* Read common folders */
cupsFilePrintf(fp,
"(allow file-read-data file-read-metadata\n"
- " (literal \"/private/etc/services\")\n"
" (regex"
+ " #\"^/AppleInternal$\""
+ " #\"^/AppleInternal/\""
" #\"^/bin$\"" /* /bin */
" #\"^/bin/\"" /* /bin/... */
+ " #\"^/private$\""
+ " #\"^/private/etc$\""
+ " #\"^/private/etc/\""
+ " #\"^/private/tmp$\""
+ " #\"^/private/tmp/\""
+ " #\"^/private/var$\""
+ " #\"^/private/var/db$\""
+ " #\"^/private/var/folders$\""
+ " #\"^/private/var/lib$\""
+ " #\"^/private/var/log$\""
+ " #\"^/private/var/mysql$\""
+ " #\"^/private/var/run$\""
+ " #\"^/private/var/spool$\""
+ " #\"^/private/var/tmp$\""
+ " #\"^/private/var/tmp/\""
" #\"^/usr/bin$\"" /* /usr/bin */
" #\"^/usr/bin/\"" /* /usr/bin/... */
" #\"^/usr/libexec/cups$\"" /* /usr/libexec/cups */
" #\"^/usr/libexec/cups/\"" /* /usr/libexec/cups/... */
+ " #\"^/usr/libexec/fax$\"" /* /usr/libexec/fax */
+ " #\"^/usr/libexec/fax/\"" /* /usr/libexec/fax/... */
" #\"^/usr/sbin$\"" /* /usr/sbin */
" #\"^/usr/sbin/\"" /* /usr/sbin/... */
- " #\"^/Library/Caches$\""
- " #\"^/Library/Fonts$\""
- " #\"^/Library/Fonts/\""
- " #\"^/Library/Printers$\""
- " #\"^/Library/Printers/.*$\""
+ " #\"^/Library$\"" /* /Library */
+ " #\"^/Library/\"" /* /Library/... */
+ " #\"^/System$\"" /* /System */
+ " #\"^/System/\"" /* /System/... */
" #\"^%s/Library$\"" /* RequestRoot/Library */
" #\"^%s/Library/\"" /* RequestRoot/Library/... */
" #\"^%s$\"" /* ServerBin */
" #\"^/Library/Printers/PPD Plugins/\""
")%s)\n", nodebug);
}
- /* Allow execution of child processes */
- cupsFilePuts(fp, "(allow process-fork)\n");
- cupsFilePrintf(fp,
- "(allow process-exec\n"
- " (regex"
- " #\"^/bin/\"" /* /bin/... */
- " #\"^/usr/bin/\"" /* /usr/bin/... */
- " #\"^/usr/libexec/cups/\"" /* /usr/libexec/cups/... */
- " #\"^/usr/sbin/\"" /* /usr/sbin/... */
- " #\"^%s/\"" /* ServerBin/... */
- " #\"^/Library/Printers/.*/\""
- "))\n",
- bin);
+ /* Allow execution of child processes as long as the programs are not in a user directory */
+ cupsFilePuts(fp, "(allow process*)\n");
+ cupsFilePuts(fp, "(deny process-exec (regex #\"^/Users/\"))\n");
if (RunUser && getenv("CUPS_TESTROOT"))
{
/* Allow source directory access in "make test" environment */
" #\"^%s/\"" /* CUPS_TESTROOT/... */
"))\n",
testroot);
+ cupsFilePrintf(fp, "(allow sysctl*)\n");
}
if (job_id)
{
/* Allow job filters to read the current job files... */
cupsFilePrintf(fp,
"(allow file-read-data file-read-metadata\n"
- " (regex #\"^%s/([ac]%05d|d%05d-[0-9][0-9][0-9])$\"))\n",
+ " (regex #\"^%s/([ac]%05d|d%05d-[0-9][0-9][0-9])$\"))\n",
request, job_id, job_id);
}
else
" (literal \"/usr/sbin/sendmail\")\n"
" (with no-sandbox))\n");
}
- /* Allow outbound networking to local mDNSResponder and cupsd */
+ /* Allow access to Bluetooth, USB, and notify_post. */
+ cupsFilePuts(fp, "(allow iokit*)\n");
+ cupsFilePuts(fp, "(allow distributed-notification-post)\n");
+ /* Allow outbound networking to local services */
cupsFilePuts(fp, "(allow network-outbound"
- "\n (literal \"/private/var/run/mDNSResponder\")");
+ "\n (regex #\"^/private/var/run/\" #\"^/private/tmp/\" #\"^/private/var/tmp/\")");
for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners);
lis;
lis = (cupsd_listener_t *)cupsArrayNext(Listeners))
{
/* Allow TCP and UDP networking off the machine... */
cupsFilePuts(fp, "\n (remote tcp))\n");
+ cupsFilePuts(fp, "(allow network-bind)\n"); /* for LPD resvport */
cupsFilePuts(fp, "(allow network*\n"
" (local udp \"*:*\")\n"
" (remote udp \"*:*\"))\n");
+
+ /* Also allow access to device files... */
+ cupsFilePuts(fp, "(allow file-write* file-read-data file-read-metadata file-ioctl\n"
+ " (regex #\"^/dev/\"))\n");
+
+ /* And allow kernel extensions to be loaded, e.g., SMB */
+ cupsFilePuts(fp, "(allow system-kext-load)\n");
}
else
{
- /* Only allow SNMP (UDP) off the machine... */
+ /* Only allow SNMP (UDP) and LPD (TCP) off the machine... */
cupsFilePuts(fp, ")\n");
cupsFilePuts(fp, "(allow network-outbound\n"
- " (remote udp \"*:161\"))\n");
+ " (remote udp \"*:161\")\n"
+ " (remote tcp \"*:515\"))\n");
cupsFilePuts(fp, "(allow network-inbound\n"
" (local udp \"localhost:*\"))\n");
}
*/
const char * /* O - Process name */
-cupsdFinishProcess(int pid, /* I - Process ID */
- char *name, /* I - Name buffer */
- int namelen, /* I - Size of name buffer */
- int *job_id) /* O - Job ID pointer or NULL */
+cupsdFinishProcess(int pid, /* I - Process ID */
+ char *name, /* I - Name buffer */
+ size_t namelen, /* I - Size of name buffer */
+ int *job_id) /* O - Job ID pointer or NULL */
{
cupsd_proc_t key, /* Search key */
*proc; /* Matching process */
strlcpy(name, "unknown", namelen);
}
- cupsdLogMessage(CUPSD_LOG_DEBUG2,
- "cupsdFinishProcess(pid=%d, name=%p, namelen=%d, "
- "job_id=%p(%d)) = \"%s\"", pid, name, namelen, job_id,
- job_id ? *job_id : 0, name);
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdFinishProcess(pid=%d, name=%p, namelen=" CUPS_LLFMT ", job_id=%p(%d)) = \"%s\"", pid, name, CUPS_LLCAST namelen, job_id, job_id ? *job_id : 0, name);
return (name);
}
{
int i; /* Looping var */
const char *exec_path = command; /* Command to be exec'd */
- char *real_argv[107], /* Real command-line arguments */
- cups_exec[1024]; /* Path to "cups-exec" program */
+ char *real_argv[110], /* Real command-line arguments */
+ cups_exec[1024], /* Path to "cups-exec" program */
+ user_str[16], /* User string */
+ group_str[16], /* Group string */
+ nice_str[16]; /* FilterNice string */
uid_t user; /* Command UID */
cupsd_proc_t *proc; /* New process record */
-#ifdef HAVE_POSIX_SPAWN
+#if USE_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)
+ sigset_t defsignals; /* Default signals */
+#elif defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
struct sigaction action; /* POSIX signal handler */
-#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
+#endif /* USE_POSIX_SPAWN */
#if defined(__APPLE__)
char processPath[1024], /* CFProcessPath environment variable */
linkpath[1024]; /* Link path for symlinks... */
if (envp)
{
/*
- * Add special voodoo magic for OS X - this allows OS X programs to access
+ * Add special voodoo magic for macOS - this allows macOS programs to access
* their bundle resources properly...
*/
* Use helper program when we have a sandbox profile...
*/
-#ifndef HAVE_POSIX_SPAWN
+#if !USE_POSIX_SPAWN
if (profile)
-#endif /* !HAVE_POSIX_SPAWN */
+#endif /* !USE_POSIX_SPAWN */
{
snprintf(cups_exec, sizeof(cups_exec), "%s/daemon/cups-exec", ServerBin);
snprintf(user_str, sizeof(user_str), "%d", user);
snprintf(nice_str, sizeof(nice_str), "%d", FilterNice);
real_argv[0] = cups_exec;
- real_argv[1] = profile;
- real_argv[2] = user_str;
- real_argv[3] = group_str;
+ real_argv[1] = (char *)"-g";
+ real_argv[2] = group_str;
+ real_argv[3] = (char *)"-n";
real_argv[4] = nice_str;
- real_argv[5] = (char *)command;
+ real_argv[5] = (char *)"-u";
+ real_argv[6] = user_str;
+ real_argv[7] = profile ? profile : "none";
+ real_argv[8] = (char *)command;
for (i = 0;
- i < (int)(sizeof(real_argv) / sizeof(real_argv[0]) - 7) && argv[i];
+ i < (int)(sizeof(real_argv) / sizeof(real_argv[0]) - 10) && argv[i];
i ++)
- real_argv[i + 6] = argv[i];
+ real_argv[i + 9] = argv[i];
- real_argv[i + 6] = NULL;
+ real_argv[i + 9] = NULL;
argv = real_argv;
exec_path = cups_exec;
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: argv[%d] = \"%s\"", i, argv[i]);
}
-#ifdef HAVE_POSIX_SPAWN
+#if USE_POSIX_SPAWN
/*
* Setup attributes and file actions for the spawn...
*/
cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdStartProcess: Setting spawn attributes.");
+ sigemptyset(&defsignals);
+ sigaddset(&defsignals, SIGTERM);
+ sigaddset(&defsignals, SIGCHLD);
+ sigaddset(&defsignals, SIGPIPE);
+
posix_spawnattr_init(&attrs);
posix_spawnattr_setflags(&attrs, POSIX_SPAWN_SETPGROUP | POSIX_SPAWN_SETSIGDEF);
+ posix_spawnattr_setpgroup(&attrs, 0);
+ posix_spawnattr_setsigdefault(&attrs, &defsignals);
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);
+ posix_spawn_file_actions_addopen(&actions, 0, "/dev/null", O_RDONLY, 0);
else
posix_spawn_file_actions_adddup2(&actions, infd, 0);
}
}
cupsdReleaseSignals();
-#endif /* HAVE_POSIX_SPAWN */
+#endif /* USE_POSIX_SPAWN */
if (*pid)
{
return (dst);
}
#endif /* HAVE_SANDBOX_H */
-
-
-/*
- * End of "$Id$".
- */