xref: /aosp_15_r20/external/libcups/scheduler/cups-exec.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * Sandbox helper for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright 2007-2014 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker  *
6*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more information.
7*5e7646d2SAndroid Build Coastguard Worker  *
8*5e7646d2SAndroid Build Coastguard Worker  * Usage:
9*5e7646d2SAndroid Build Coastguard Worker  *
10*5e7646d2SAndroid Build Coastguard Worker  *     cups-exec /path/to/profile [-u UID] [-g GID] [-n NICE] /path/to/program argv0 argv1 ... argvN
11*5e7646d2SAndroid Build Coastguard Worker  */
12*5e7646d2SAndroid Build Coastguard Worker 
13*5e7646d2SAndroid Build Coastguard Worker /*
14*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers...
15*5e7646d2SAndroid Build Coastguard Worker  */
16*5e7646d2SAndroid Build Coastguard Worker 
17*5e7646d2SAndroid Build Coastguard Worker #include <cups/string-private.h>
18*5e7646d2SAndroid Build Coastguard Worker #include <cups/file.h>
19*5e7646d2SAndroid Build Coastguard Worker #include <unistd.h>
20*5e7646d2SAndroid Build Coastguard Worker #include <fcntl.h>
21*5e7646d2SAndroid Build Coastguard Worker #include <grp.h>
22*5e7646d2SAndroid Build Coastguard Worker #include <sys/stat.h>
23*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_SANDBOX_H
24*5e7646d2SAndroid Build Coastguard Worker #  include <sandbox.h>
25*5e7646d2SAndroid Build Coastguard Worker #  ifndef SANDBOX_NAMED_EXTERNAL
26*5e7646d2SAndroid Build Coastguard Worker #    define SANDBOX_NAMED_EXTERNAL  0x0003
27*5e7646d2SAndroid Build Coastguard Worker #  endif /* !SANDBOX_NAMED_EXTERNAL */
28*5e7646d2SAndroid Build Coastguard Worker #  pragma GCC diagnostic ignored "-Wdeprecated-declarations"
29*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SANDBOX_H */
30*5e7646d2SAndroid Build Coastguard Worker 
31*5e7646d2SAndroid Build Coastguard Worker 
32*5e7646d2SAndroid Build Coastguard Worker /*
33*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
34*5e7646d2SAndroid Build Coastguard Worker  */
35*5e7646d2SAndroid Build Coastguard Worker 
36*5e7646d2SAndroid Build Coastguard Worker static void	usage(void) _CUPS_NORETURN;
37*5e7646d2SAndroid Build Coastguard Worker 
38*5e7646d2SAndroid Build Coastguard Worker 
39*5e7646d2SAndroid Build Coastguard Worker /*
40*5e7646d2SAndroid Build Coastguard Worker  * 'main()' - Apply sandbox profile and execute program.
41*5e7646d2SAndroid Build Coastguard Worker  */
42*5e7646d2SAndroid Build Coastguard Worker 
43*5e7646d2SAndroid Build Coastguard Worker int					/* O - Exit status */
main(int argc,char * argv[])44*5e7646d2SAndroid Build Coastguard Worker main(int  argc,				/* I - Number of command-line args */
45*5e7646d2SAndroid Build Coastguard Worker      char *argv[])			/* I - Command-line arguments */
46*5e7646d2SAndroid Build Coastguard Worker {
47*5e7646d2SAndroid Build Coastguard Worker   int		i;			/* Looping var */
48*5e7646d2SAndroid Build Coastguard Worker   const char	*opt;			/* Current option character */
49*5e7646d2SAndroid Build Coastguard Worker   uid_t		uid = getuid();		/* UID */
50*5e7646d2SAndroid Build Coastguard Worker   gid_t		gid = getgid();		/* GID */
51*5e7646d2SAndroid Build Coastguard Worker   int		niceval = 0;		/* Nice value */
52*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_SANDBOX_H
53*5e7646d2SAndroid Build Coastguard Worker   char		*sandbox_error = NULL;	/* Sandbox error, if any */
54*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SANDBOX_H */
55*5e7646d2SAndroid Build Coastguard Worker 
56*5e7646d2SAndroid Build Coastguard Worker 
57*5e7646d2SAndroid Build Coastguard Worker  /*
58*5e7646d2SAndroid Build Coastguard Worker   * Parse command-line...
59*5e7646d2SAndroid Build Coastguard Worker   */
60*5e7646d2SAndroid Build Coastguard Worker 
61*5e7646d2SAndroid Build Coastguard Worker   for (i = 1; i < argc; i ++)
62*5e7646d2SAndroid Build Coastguard Worker   {
63*5e7646d2SAndroid Build Coastguard Worker     if (argv[i][0] == '-')
64*5e7646d2SAndroid Build Coastguard Worker     {
65*5e7646d2SAndroid Build Coastguard Worker       for (opt = argv[i] + 1; *opt; opt ++)
66*5e7646d2SAndroid Build Coastguard Worker       {
67*5e7646d2SAndroid Build Coastguard Worker         switch (*opt)
68*5e7646d2SAndroid Build Coastguard Worker         {
69*5e7646d2SAndroid Build Coastguard Worker           case 'g' : /* -g gid */
70*5e7646d2SAndroid Build Coastguard Worker               i ++;
71*5e7646d2SAndroid Build Coastguard Worker               if (i >= argc)
72*5e7646d2SAndroid Build Coastguard Worker                 usage();
73*5e7646d2SAndroid Build Coastguard Worker 
74*5e7646d2SAndroid Build Coastguard Worker               gid = (gid_t)atoi(argv[i]);
75*5e7646d2SAndroid Build Coastguard Worker               break;
76*5e7646d2SAndroid Build Coastguard Worker 
77*5e7646d2SAndroid Build Coastguard Worker           case 'n' : /* -n nice-value */
78*5e7646d2SAndroid Build Coastguard Worker               i ++;
79*5e7646d2SAndroid Build Coastguard Worker               if (i >= argc)
80*5e7646d2SAndroid Build Coastguard Worker                 usage();
81*5e7646d2SAndroid Build Coastguard Worker 
82*5e7646d2SAndroid Build Coastguard Worker               niceval = atoi(argv[i]);
83*5e7646d2SAndroid Build Coastguard Worker               break;
84*5e7646d2SAndroid Build Coastguard Worker 
85*5e7646d2SAndroid Build Coastguard Worker           case 'u' : /* -g gid */
86*5e7646d2SAndroid Build Coastguard Worker               i ++;
87*5e7646d2SAndroid Build Coastguard Worker               if (i >= argc)
88*5e7646d2SAndroid Build Coastguard Worker                 usage();
89*5e7646d2SAndroid Build Coastguard Worker 
90*5e7646d2SAndroid Build Coastguard Worker               uid = (uid_t)atoi(argv[i]);
91*5e7646d2SAndroid Build Coastguard Worker               break;
92*5e7646d2SAndroid Build Coastguard Worker 
93*5e7646d2SAndroid Build Coastguard Worker 	  default :
94*5e7646d2SAndroid Build Coastguard Worker 	      fprintf(stderr, "cups-exec: Unknown option '-%c'.\n", *opt);
95*5e7646d2SAndroid Build Coastguard Worker 	      usage();
96*5e7646d2SAndroid Build Coastguard Worker         }
97*5e7646d2SAndroid Build Coastguard Worker       }
98*5e7646d2SAndroid Build Coastguard Worker     }
99*5e7646d2SAndroid Build Coastguard Worker     else
100*5e7646d2SAndroid Build Coastguard Worker       break;
101*5e7646d2SAndroid Build Coastguard Worker   }
102*5e7646d2SAndroid Build Coastguard Worker 
103*5e7646d2SAndroid Build Coastguard Worker  /*
104*5e7646d2SAndroid Build Coastguard Worker   * Check that we have enough arguments...
105*5e7646d2SAndroid Build Coastguard Worker   */
106*5e7646d2SAndroid Build Coastguard Worker 
107*5e7646d2SAndroid Build Coastguard Worker   if ((i + 3) > argc)
108*5e7646d2SAndroid Build Coastguard Worker   {
109*5e7646d2SAndroid Build Coastguard Worker     fputs("cups-exec: Insufficient arguments.\n", stderr);
110*5e7646d2SAndroid Build Coastguard Worker     usage();
111*5e7646d2SAndroid Build Coastguard Worker   }
112*5e7646d2SAndroid Build Coastguard Worker 
113*5e7646d2SAndroid Build Coastguard Worker  /*
114*5e7646d2SAndroid Build Coastguard Worker   * Make sure side and back channel FDs are non-blocking...
115*5e7646d2SAndroid Build Coastguard Worker   */
116*5e7646d2SAndroid Build Coastguard Worker 
117*5e7646d2SAndroid Build Coastguard Worker   fcntl(3, F_SETFL, O_NDELAY);
118*5e7646d2SAndroid Build Coastguard Worker   fcntl(4, F_SETFL, O_NDELAY);
119*5e7646d2SAndroid Build Coastguard Worker 
120*5e7646d2SAndroid Build Coastguard Worker  /*
121*5e7646d2SAndroid Build Coastguard Worker   * Change UID, GID, and nice value...
122*5e7646d2SAndroid Build Coastguard Worker   */
123*5e7646d2SAndroid Build Coastguard Worker 
124*5e7646d2SAndroid Build Coastguard Worker   if (uid)
125*5e7646d2SAndroid Build Coastguard Worker     nice(niceval);
126*5e7646d2SAndroid Build Coastguard Worker 
127*5e7646d2SAndroid Build Coastguard Worker   if (!getuid())
128*5e7646d2SAndroid Build Coastguard Worker   {
129*5e7646d2SAndroid Build Coastguard Worker     if (setgid(gid))
130*5e7646d2SAndroid Build Coastguard Worker       exit(errno + 100);
131*5e7646d2SAndroid Build Coastguard Worker 
132*5e7646d2SAndroid Build Coastguard Worker     if (setgroups(1, &gid))
133*5e7646d2SAndroid Build Coastguard Worker       exit(errno + 100);
134*5e7646d2SAndroid Build Coastguard Worker 
135*5e7646d2SAndroid Build Coastguard Worker     if (uid && setuid(uid))
136*5e7646d2SAndroid Build Coastguard Worker       exit(errno + 100);
137*5e7646d2SAndroid Build Coastguard Worker   }
138*5e7646d2SAndroid Build Coastguard Worker 
139*5e7646d2SAndroid Build Coastguard Worker   umask(077);
140*5e7646d2SAndroid Build Coastguard Worker 
141*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_SANDBOX_H
142*5e7646d2SAndroid Build Coastguard Worker  /*
143*5e7646d2SAndroid Build Coastguard Worker   * Run in a separate security profile...
144*5e7646d2SAndroid Build Coastguard Worker   */
145*5e7646d2SAndroid Build Coastguard Worker 
146*5e7646d2SAndroid Build Coastguard Worker   if (strcmp(argv[i], "none") &&
147*5e7646d2SAndroid Build Coastguard Worker       sandbox_init(argv[i], SANDBOX_NAMED_EXTERNAL, &sandbox_error))
148*5e7646d2SAndroid Build Coastguard Worker   {
149*5e7646d2SAndroid Build Coastguard Worker     cups_file_t	*fp;			/* File */
150*5e7646d2SAndroid Build Coastguard Worker     char	line[1024];		/* Line from file */
151*5e7646d2SAndroid Build Coastguard Worker     int		linenum = 0;		/* Line number in file */
152*5e7646d2SAndroid Build Coastguard Worker 
153*5e7646d2SAndroid Build Coastguard Worker     fprintf(stderr, "DEBUG: sandbox_init failed: %s (%s)\n", sandbox_error,
154*5e7646d2SAndroid Build Coastguard Worker 	    strerror(errno));
155*5e7646d2SAndroid Build Coastguard Worker     sandbox_free_error(sandbox_error);
156*5e7646d2SAndroid Build Coastguard Worker 
157*5e7646d2SAndroid Build Coastguard Worker     if ((fp = cupsFileOpen(argv[i], "r")) != NULL)
158*5e7646d2SAndroid Build Coastguard Worker     {
159*5e7646d2SAndroid Build Coastguard Worker       while (cupsFileGets(fp, line, sizeof(line)))
160*5e7646d2SAndroid Build Coastguard Worker       {
161*5e7646d2SAndroid Build Coastguard Worker         linenum ++;
162*5e7646d2SAndroid Build Coastguard Worker         fprintf(stderr, "DEBUG: %4d  %s\n", linenum, line);
163*5e7646d2SAndroid Build Coastguard Worker       }
164*5e7646d2SAndroid Build Coastguard Worker       cupsFileClose(fp);
165*5e7646d2SAndroid Build Coastguard Worker     }
166*5e7646d2SAndroid Build Coastguard Worker 
167*5e7646d2SAndroid Build Coastguard Worker     return (100 + EINVAL);
168*5e7646d2SAndroid Build Coastguard Worker   }
169*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_SANDBOX_H */
170*5e7646d2SAndroid Build Coastguard Worker 
171*5e7646d2SAndroid Build Coastguard Worker  /*
172*5e7646d2SAndroid Build Coastguard Worker   * Execute the program...
173*5e7646d2SAndroid Build Coastguard Worker   */
174*5e7646d2SAndroid Build Coastguard Worker 
175*5e7646d2SAndroid Build Coastguard Worker   execv(argv[i + 1], argv + i + 2);
176*5e7646d2SAndroid Build Coastguard Worker 
177*5e7646d2SAndroid Build Coastguard Worker  /*
178*5e7646d2SAndroid Build Coastguard Worker   * If we get here, execv() failed...
179*5e7646d2SAndroid Build Coastguard Worker   */
180*5e7646d2SAndroid Build Coastguard Worker 
181*5e7646d2SAndroid Build Coastguard Worker   fprintf(stderr, "DEBUG: execv failed: %s\n", strerror(errno));
182*5e7646d2SAndroid Build Coastguard Worker   return (errno + 100);
183*5e7646d2SAndroid Build Coastguard Worker }
184*5e7646d2SAndroid Build Coastguard Worker 
185*5e7646d2SAndroid Build Coastguard Worker 
186*5e7646d2SAndroid Build Coastguard Worker /*
187*5e7646d2SAndroid Build Coastguard Worker  * 'usage()' - Show program usage.
188*5e7646d2SAndroid Build Coastguard Worker  */
189*5e7646d2SAndroid Build Coastguard Worker 
190*5e7646d2SAndroid Build Coastguard Worker static void
usage(void)191*5e7646d2SAndroid Build Coastguard Worker usage(void)
192*5e7646d2SAndroid Build Coastguard Worker {
193*5e7646d2SAndroid Build Coastguard Worker   fputs("Usage: cups-exec [-g gid] [-n nice-value] [-u uid] /path/to/profile /path/to/program argv0 argv1 ... argvN\n", stderr);
194*5e7646d2SAndroid Build Coastguard Worker   exit(1);
195*5e7646d2SAndroid Build Coastguard Worker }
196