From: msweet Date: Wed, 12 Feb 2014 01:27:42 +0000 (+0000) Subject: Improve CUPS sandboxing X-Git-Tag: v2.2b1~763 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=28c194b081332386a28b4c7ea4cd74167bf6af71;p=thirdparty%2Fcups.git Improve CUPS sandboxing Fix a bug in cups-exec where (for some reason) the call to execv was missing... Update cups-exec to take real options (-u uid, -g gid, -n nice-value) so that existing applications that use cups-exec won't need changes. This will also allow for future changes without breaking things. git-svn-id: svn+ssh://src.apple.com/svn/cups/cups.org/trunk@11578 a1ca3aef-8c08-0410-bb20-df032aa958be --- diff --git a/CHANGES.txt b/CHANGES.txt index a39bbfc81e..33442d28ae 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,4 +1,4 @@ -CHANGES.txt - 2.0b1 - 2014-01-21 +CHANGES.txt - 2.0b1 - 2014-02-11 -------------------------------- CHANGES IN CUPS V2.0b1 @@ -13,3 +13,5 @@ CHANGES IN CUPS V2.0b1 () - cupsRasterInterpretPPD now supports the Orientation header in order to support long-edge feed raster printers () + - The filter/backend sandbox on OS X now defaults to a more strict + whitelist () \ No newline at end of file diff --git a/scheduler/cups-exec.c b/scheduler/cups-exec.c index ecbc6bbc64..1111f7d07a 100644 --- a/scheduler/cups-exec.c +++ b/scheduler/cups-exec.c @@ -34,6 +34,13 @@ #endif /* HAVE_SANDBOX_H */ +/* + * Local functions... + */ + +static void usage(void) __attribute__((noreturn)); + + /* * 'main()' - Apply sandbox profile and execute program. */ @@ -42,22 +49,70 @@ 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 */ + int i; /* Looping var */ + const char *opt; /* Current option character */ + uid_t uid = getuid(); /* UID */ + gid_t gid = getgid(); /* GID */ + int niceval = 0; /* Nice value */ #ifdef HAVE_SANDBOX_H - char *sandbox_error = NULL; /* Sandbox error, if any */ + char *sandbox_error = NULL; /* Sandbox error, if any */ #endif /* HAVE_SANDBOX_H */ + /* + * Parse command-line... + */ + + for (i = 1; i < argc; i ++) + { + if (argv[i][0] == '-') + { + for (opt = argv[i] + 1; *opt; opt ++) + { + switch (*opt) + { + case 'g' : /* -g gid */ + i ++; + if (i >= argc) + usage(); + + gid = (gid_t)atoi(argv[i]); + break; + + case 'n' : /* -n nice-value */ + i ++; + if (i >= argc) + usage(); + + niceval = atoi(argv[i]); + break; + + case 'u' : /* -g gid */ + i ++; + if (i >= argc) + usage(); + + uid = (uid_t)atoi(argv[i]); + break; + + default : + fprintf(stderr, "cups-exec: Unknown option '-%c'.\n", *opt); + usage(); + } + } + } + else + break; + } + /* * Check that we have enough arguments... */ - if (argc < 7) + if ((i + 3) > argc) { - puts("Usage: cups-exec /path/to/profile UID GID NICE /path/to/program argv0 argv1 ... argvN"); - return (1); + fputs("cups-exec: Insufficient arguments.\n", stderr); + usage(); } /* @@ -71,10 +126,6 @@ main(int argc, /* I - Number of command-line args */ * 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); @@ -97,8 +148,8 @@ main(int argc, /* I - Number of command-line args */ * Run in a separate security profile... */ - if (strcmp(argv[1], "none") && - sandbox_init(argv[1], SANDBOX_NAMED_EXTERNAL, &sandbox_error)) + if (strcmp(argv[i], "none") && + sandbox_init(argv[i], SANDBOX_NAMED_EXTERNAL, &sandbox_error)) { cups_file_t *fp; /* File */ char line[1024]; /* Line from file */ @@ -108,7 +159,7 @@ main(int argc, /* I - Number of command-line args */ strerror(errno)); sandbox_free_error(sandbox_error); - if ((fp = cupsFileOpen(argv[1], "r")) != NULL) + if ((fp = cupsFileOpen(argv[i], "r")) != NULL) { while (cupsFileGets(fp, line, sizeof(line))) { @@ -122,6 +173,12 @@ main(int argc, /* I - Number of command-line args */ } #endif /* HAVE_SANDBOX_H */ + /* + * Execute the program... + */ + + execv(argv[i + 1], argv + i + 2); + /* * If we get here, execv() failed... */ @@ -131,6 +188,18 @@ main(int argc, /* I - Number of command-line args */ } +/* + * 'usage()' - Show program usage. + */ + +static void +usage(void) +{ + fputs("Usage: cups-exec [-g gid] [-n nice-value] [-u uid] /path/to/profile /path/to/program argv0 argv1 ... argvN\n", stderr); + exit(1); +} + + /* * End of "$Id$". */ diff --git a/scheduler/process.c b/scheduler/process.c index 4276dbff4d..6afb5926cf 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -427,7 +427,7 @@ cupsdStartProcess( { int i; /* Looping var */ const char *exec_path = command; /* Command to be exec'd */ - char *real_argv[107], /* Real command-line arguments */ + char *real_argv[110], /* Real command-line arguments */ cups_exec[1024]; /* Path to "cups-exec" program */ uid_t user; /* Command UID */ cupsd_proc_t *proc; /* New process record */ @@ -514,18 +514,21 @@ cupsdStartProcess( 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; + 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;