X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=scheduler%2Fprocess.c;h=3c1c6ba4f9d49fcc3ebb82dd5e446f902ad2e636;hb=86206ccf13c909e67fdbe0a4ddba0152a571cd9d;hp=a036dfa075a0501c72d8adaec63b2cffdea53843;hpb=6e4925fbe63edc68e0e9aaf443b00ef949d32950;p=thirdparty%2Fcups.git diff --git a/scheduler/process.c b/scheduler/process.c index a036dfa07..3c1c6ba4f 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -1,16 +1,10 @@ /* - * "$Id$" - * * Process management routines for the CUPS scheduler. * - * Copyright 2007-2014 by Apple Inc. + * Copyright 2007-2017 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * - * 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/". + * Licensed under Apache License v2.0. See the file "LICENSE" for more information. */ /* @@ -25,6 +19,18 @@ #ifdef HAVE_POSIX_SPAWN # include extern char **environ; +/* Don't use posix_spawn on systems with bugs in their implementations... */ +# if defined(OpenBSD) && OpenBSD < 201505 +# define USE_POSIX_SPAWN 0 +# elif defined(__UCLIBC__) && __UCLIBC_MAJOR__ == 1 && __UCLIBC_MINOR__ == 0 && __UCLIBC_SUBLEVEL__ < 27 +# define USE_POSIX_SPAWN 0 +# elif defined(__UCLIBC__) && __UCLIBC_MAJOR__ < 1 +# define USE_POSIX_SPAWN 0 +# else /* All other platforms */ +# define USE_POSIX_SPAWN 1 +# endif /* ... */ +#else +# define USE_POSIX_SPAWN 0 #endif /* HAVE_POSIX_SPAWN */ @@ -73,6 +79,7 @@ cupsdCreateProfile(int job_id, /* I - Job ID or 0 for none */ 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 */ @@ -91,9 +98,13 @@ cupsdCreateProfile(int job_id, /* I - Job ID or 0 for none */ if ((fp = cupsTempFile2(profile, sizeof(profile))) == NULL) { + /* + * This should never happen, and is fatal when sandboxing is enabled. + */ + cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCreateProfile(job_id=%d, allow_networking=%d) = NULL", job_id, allow_networking); - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create security profile: %s", - strerror(errno)); + cupsdLogMessage(CUPSD_LOG_EMERG, "Unable to create security profile: %s", strerror(errno)); + kill(getpid(), SIGTERM); return (NULL); } @@ -104,6 +115,7 @@ cupsdCreateProfile(int job_id, /* I - Job ID or 0 for none */ 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)" : ""; @@ -116,19 +128,13 @@ cupsdCreateProfile(int job_id, /* I - Job ID or 0 for none */ if (LogLevel >= CUPSD_LOG_DEBUG) cupsFilePuts(fp, "(debug deny)\n"); cupsFilePuts(fp, "(import \"system.sb\")\n"); + cupsFilePuts(fp, "(import \"com.apple.corefoundation.sb\")\n"); cupsFilePuts(fp, "(system-network)\n"); cupsFilePuts(fp, "(allow mach-per-user-lookup)\n"); cupsFilePuts(fp, "(allow ipc-posix-sem)\n"); 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" @@ -163,6 +169,31 @@ cupsdCreateProfile(int job_id, /* I - Job ID or 0 for none */ "))\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" @@ -170,19 +201,6 @@ cupsdCreateProfile(int job_id, /* I - Job ID or 0 for none */ " #\"^%s/\"" /* TempDir/... */ " #\"^%s$\"" /* CacheDir */ " #\"^%s/\"" /* CacheDir/... */ - " #\"^/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", temp, temp, cache, cache); /* Read common folders */ @@ -206,6 +224,8 @@ cupsdCreateProfile(int job_id, /* I - Job ID or 0 for none */ " #\"^/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 */ @@ -214,29 +234,20 @@ cupsdCreateProfile(int job_id, /* I - Job ID or 0 for none */ " #\"^/usr/libexec/fax/\"" /* /usr/libexec/fax/... */ " #\"^/usr/sbin$\"" /* /usr/sbin */ " #\"^/usr/sbin/\"" /* /usr/sbin/... */ - " #\"^/Library/Application Support$\"" - " #\"^/Library/Application Support/\"" - " #\"^/Library/Caches$\"" - " #\"^/Library/Fonts$\"" - " #\"^/Library/Fonts/\"" - " #\"^/Library/Frameworks$\"" - " #\"^/Library/Frameworks/\"" - " #\"^/Library/Keychains$\"" - " #\"^/Library/Keychains/\"" - " #\"^/Library/Logs$\"" - " #\"^/Library/Printers$\"" - " #\"^/Library/Printers/\"" - " #\"^/Library/Security$\"" - " #\"^/Library/Security/\"" - " #\"^/Library/WebServer$\"" + " #\"^/Library$\"" /* /Library */ + " #\"^/Library/\"" /* /Library/... */ + " #\"^/System$\"" /* /System */ + " #\"^/System/\"" /* /System/... */ " #\"^%s/Library$\"" /* RequestRoot/Library */ " #\"^%s/Library/\"" /* RequestRoot/Library/... */ " #\"^%s$\"" /* ServerBin */ " #\"^%s/\"" /* ServerBin/... */ " #\"^%s$\"" /* ServerRoot */ " #\"^%s/\"" /* ServerRoot/... */ + " #\"^%s$\"" /* StateDir */ + " #\"^%s/\"" /* StateDir/... */ "))\n", - request, request, bin, bin, root, root); + request, request, bin, bin, root, root, state, state); if (Sandboxing == CUPSD_SANDBOXING_RELAXED) { /* Limited write access to /Library/Printers/... */ @@ -254,21 +265,9 @@ cupsdCreateProfile(int job_id, /* I - Job ID or 0 for none */ " #\"^/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/libexec/fax/\"" /* /usr/libexec/fax/... */ - " #\"^/usr/sbin/\"" /* /usr/sbin/... */ - " #\"^%s/\"" /* ServerBin/... */ - " #\"^/Library/Printers/.*/\"" - " #\"^/System/Library/Frameworks/Python.framework/\"" - "))\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 */ @@ -289,11 +288,8 @@ cupsdCreateProfile(int job_id, /* I - Job ID or 0 for none */ " #\"^%s/\"" /* CUPS_TESTROOT/... */ "))\n", testroot); + cupsFilePrintf(fp, "(allow sysctl*)\n"); } - cupsFilePrintf(fp, - "(deny file-write* file-read-data file-read-metadata\n" - " (regex #\"^%s$\" #\"^%s/\"))\n", - request, request); if (job_id) { /* Allow job filters to read the current job files... */ @@ -310,9 +306,12 @@ cupsdCreateProfile(int job_id, /* I - Job ID or 0 for none */ " (literal \"/usr/sbin/sendmail\")\n" " (with no-sandbox))\n"); } + /* 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 (regex #\"^/private/var/run/\" #\"^/private/tmp/\")"); + "\n (regex #\"^/private/var/run/\" #\"^/private/tmp/\" #\"^/private/var/tmp/\")"); for (lis = (cupsd_listener_t *)cupsArrayFirst(Listeners); lis; lis = (cupsd_listener_t *)cupsArrayNext(Listeners)) @@ -332,21 +331,22 @@ cupsdCreateProfile(int job_id, /* I - Job ID or 0 for none */ " (local udp \"*:*\")\n" " (remote udp \"*:*\"))\n"); - /* Also allow access to Bluetooth, USB, device files, etc. */ - cupsFilePuts(fp, "(allow iokit*)\n"); + /* Also allow access to device files... */ cupsFilePuts(fp, "(allow file-write* file-read-data file-read-metadata file-ioctl\n" " (regex #\"^/dev/\"))\n"); - cupsFilePuts(fp, "(allow distributed-notification-post)\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"); - cupsFilePuts(fp, "(deny iokit* (with no-report))\n"); } cupsFileClose(fp); @@ -473,18 +473,19 @@ cupsdStartProcess( int i; /* Looping var */ const char *exec_path = command; /* Command to be exec'd */ char *real_argv[110], /* Real command-line arguments */ - cups_exec[1024]; /* Path to "cups-exec" program */ + 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 */ + sigset_t defsignals; /* Default signals */ #elif defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* POSIX signal handler */ -#endif /* HAVE_POSIX_SPAWN */ +#endif /* USE_POSIX_SPAWN */ #if defined(__APPLE__) char processPath[1024], /* CFProcessPath environment variable */ linkpath[1024]; /* Link path for symlinks... */ @@ -517,7 +518,7 @@ cupsdStartProcess( 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... */ @@ -548,9 +549,9 @@ cupsdStartProcess( * 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); @@ -586,21 +587,28 @@ cupsdStartProcess( 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); } @@ -802,7 +810,7 @@ cupsdStartProcess( } cupsdReleaseSignals(); -#endif /* HAVE_POSIX_SPAWN */ +#endif /* USE_POSIX_SPAWN */ if (*pid) { @@ -870,7 +878,7 @@ cupsd_requote(char *dst, /* I - Destination buffer */ if (ch == '/' && !*src) break; /* Don't add trailing slash */ - if (strchr(".?*()[]^$\\", ch)) + if (strchr(".?*()[]^$\\\"", ch)) *dstptr++ = '\\'; *dstptr++ = (char)ch; @@ -881,8 +889,3 @@ cupsd_requote(char *dst, /* I - Destination buffer */ return (dst); } #endif /* HAVE_SANDBOX_H */ - - -/* - * End of "$Id$". - */