Another bootstrap kludge.
[coreutils/ericb.git] / src / runcon.c
blob1d79ef6ffad4514fdfa84f217f87af94b4f44094
1 /*
2 * runcon [ context |
3 * ( [ -c ] [ -r role ] [-t type] [ -u user ] [ -l levelrange ] )
4 * command [arg1 [arg2 ...] ]
6 * attempt to run the specified command with the specified context.
8 * -r role : use the current context with the specified role
9 * -t type : use the current context with the specified type
10 * -u user : use the current context with the specified user
11 * -l level : use the current context with the specified level range
12 * -c : compute process transition context before modifying
14 * Contexts are interpreted as follows:
16 * Number of MLS
17 * components system?
19 * 1 - type
20 * 2 - role:type
21 * 3 Y role:type:range
22 * 3 N user:role:type
23 * 4 Y user:role:type:range
24 * 4 N error
27 #include <config.h>
28 #include <stdio.h>
29 #include <getopt.h>
30 #include <selinux/selinux.h>
31 #include <selinux/context.h>
32 #ifdef HAVE_SELINUX_FLASK_H
33 # include <selinux/flask.h>
34 #else
35 # define SECCLASS_PROCESS 0
36 #endif
37 #include <sys/types.h>
38 #include "system.h"
39 #include "error.h"
40 #include "quote.h"
41 #include "quotearg.h"
43 /* The official name of this program (e.g., no `g' prefix). */
44 #define PROGRAM_NAME "runcon"
46 #define AUTHORS "Russell Coker"
48 static struct option long_options[] = {
49 {"role", required_argument, NULL, 'r'},
50 {"type", required_argument, NULL, 't'},
51 {"user", required_argument, NULL, 'u'},
52 {"range", required_argument, NULL, 'l'},
53 {"compute", no_argument, NULL, 'c'},
54 {GETOPT_HELP_OPTION_DECL},
55 {GETOPT_VERSION_OPTION_DECL},
56 {NULL, 0, NULL, 0}
59 /* The name the program was run with. */
60 char *program_name;
62 void
63 usage (int status)
65 if (status != EXIT_SUCCESS)
66 fprintf (stderr, _("Try `%s --help' for more information.\n"),
67 program_name);
68 else
70 printf (_("\
71 Usage: %s CONTEXT COMMAND [args]\n\
72 or: %s [ -c ] [-u USER] [-r ROLE] [-t TYPE] [-l RANGE] COMMAND [args]\n\
73 "), program_name, program_name);
74 fputs (_("\
75 Run a program in a different security context.\n\
76 With neither CONTEXT nor COMMAND, print the current security context.\n\
77 \n\
78 CONTEXT Complete security context\n\
79 -c, --compute compute process transition context before modifying\n\
80 -t, --type=TYPE type (for same role as parent)\n\
81 -u, --user=USER user identity\n\
82 -r, --role=ROLE role\n\
83 -l, --range=RANGE levelrange\n\
84 \n\
85 "), stdout);
86 fputs (HELP_OPTION_DESCRIPTION, stdout);
87 fputs (VERSION_OPTION_DESCRIPTION, stdout);
89 exit (status);
92 int
93 main (int argc, char **argv, char **envp)
95 char *role = NULL;
96 char *range = NULL;
97 char *user = NULL;
98 char *type = NULL;
99 char *context = NULL;
100 security_context_t cur_context = NULL;
101 security_context_t file_context = NULL;
102 security_context_t new_context = NULL;
103 bool compute_trans = false;
105 context_t con;
107 initialize_main (&argc, &argv);
108 program_name = argv[0];
109 setlocale (LC_ALL, "");
110 bindtextdomain (PACKAGE, LOCALEDIR);
111 textdomain (PACKAGE);
113 atexit (close_stdout);
115 while (1)
117 int option_index = 0;
118 int c = getopt_long (argc, argv, "+r:t:u:l:c", long_options,
119 &option_index);
120 if (c == -1)
121 break;
122 switch (c)
124 case 'r':
125 if (role)
126 error (EXIT_FAILURE, 0, _("multiple roles"));
127 role = optarg;
128 break;
129 case 't':
130 if (type)
131 error (EXIT_FAILURE, 0, _("multiple types"));
132 type = optarg;
133 break;
134 case 'u':
135 if (user)
136 error (EXIT_FAILURE, 0, _("multiple users"));
137 user = optarg;
138 break;
139 case 'l':
140 if (range)
141 error (EXIT_FAILURE, 0, _("multiple levelranges"));
142 range = optarg;
143 break;
144 case 'c':
145 compute_trans = true;
146 break;
148 case_GETOPT_HELP_CHAR;
149 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
150 default:
151 usage (EXIT_FAILURE);
152 break;
156 if (argc - optind == 0)
158 if (getcon (&cur_context) < 0)
159 error (EXIT_FAILURE, errno, _("failed to get current context"));
160 fputs (cur_context, stdout);
161 fputc ('\n', stdout);
162 exit (EXIT_SUCCESS);
165 if (!(user || role || type || range || compute_trans))
167 if (optind >= argc)
169 error (0, 0, _("you must specify -c, -t, -u, -l, -r, or context"));
170 usage (1);
172 context = argv[optind++];
175 if (optind >= argc)
177 error (0, 0, _("no command specified"));
178 usage (1);
181 if (is_selinux_enabled () != 1)
182 error (EXIT_FAILURE, 0,
183 _("runcon may be used only on a SELinux kernel"));
185 if (context)
187 con = context_new (context);
188 if (!con)
189 error (EXIT_FAILURE, errno, _("failed to create security context: %s"),
190 quotearg_colon (context));
192 else
194 if (getcon (&cur_context) < 0)
195 error (EXIT_FAILURE, errno, _("failed to get current context"));
197 /* We will generate context based on process transition */
198 if (compute_trans)
200 /* Get context of file to be executed */
201 if (getfilecon (argv[optind], &file_context) == -1)
202 error (EXIT_FAILURE, errno,
203 _("failed to get security context of %s"),
204 quote (argv[optind]));
205 /* compute result of process transition */
206 if (security_compute_create (cur_context, file_context,
207 SECCLASS_PROCESS, &new_context) != 0)
208 error (EXIT_FAILURE, errno,
209 _("failed to compute a new context"));
210 /* free contexts */
211 freecon (file_context);
212 freecon (cur_context);
214 /* set cur_context equal to new_context */
215 cur_context = new_context;
218 con = context_new (cur_context);
219 if (!con)
220 error (EXIT_FAILURE, errno, _("failed to create security context: %s"),
221 quotearg_colon (cur_context));
222 if (user && context_user_set (con, user))
223 error (EXIT_FAILURE, errno, _("failed to set new user %s"), user);
224 if (type && context_type_set (con, type))
225 error (EXIT_FAILURE, errno, _("failed to set new type %s"), type);
226 if (range && context_range_set (con, range))
227 error (EXIT_FAILURE, errno, _("failed to set new range %s"), range);
228 if (role && context_role_set (con, role))
229 error (EXIT_FAILURE, errno, _("failed to set new role %s"), role);
232 if (security_check_context (context_str (con)) < 0)
233 error (EXIT_FAILURE, errno, _("invalid context: %s"),
234 quotearg_colon (context_str (con)));
236 if (setexeccon (context_str (con)) != 0)
237 error (EXIT_FAILURE, errno, _("unable to set security context %s"),
238 quote (context_str (con)));
239 if (cur_context != NULL)
240 freecon (cur_context);
242 execvp (argv[optind], argv + optind);
245 int exit_status = (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
246 error (0, errno, "%s", argv[optind]);
247 exit (exit_status);