tests: cleanup trapping of signal names
[coreutils.git] / src / runcon.c
blob95b434a45e1b5bfe07bc81ef245630673a2d1bc7
1 /* runcon -- run command with specified security context
2 Copyright (C) 2005-2015 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
18 * runcon [ context
19 * | ( [ -c ] [ -r role ] [-t type] [ -u user ] [ -l levelrange ] )
20 * command [arg1 [arg2 ...] ]
22 * attempt to run the specified command with the specified context.
24 * -r role : use the current context with the specified role
25 * -t type : use the current context with the specified type
26 * -u user : use the current context with the specified user
27 * -l level : use the current context with the specified level range
28 * -c : compute process transition context before modifying
30 * Contexts are interpreted as follows:
32 * Number of MLS
33 * components system?
35 * 1 - type
36 * 2 - role:type
37 * 3 Y role:type:range
38 * 3 N user:role:type
39 * 4 Y user:role:type:range
40 * 4 N error
43 #include <config.h>
44 #include <stdio.h>
45 #include <getopt.h>
46 #include <selinux/selinux.h>
47 #include <selinux/context.h>
48 #include <sys/types.h>
49 #include "system.h"
50 #include "error.h"
51 #include "quote.h"
53 /* The official name of this program (e.g., no 'g' prefix). */
54 #define PROGRAM_NAME "runcon"
56 #define AUTHORS proper_name ("Russell Coker")
58 static struct option const long_options[] =
60 {"role", required_argument, NULL, 'r'},
61 {"type", required_argument, NULL, 't'},
62 {"user", required_argument, NULL, 'u'},
63 {"range", required_argument, NULL, 'l'},
64 {"compute", no_argument, NULL, 'c'},
65 {GETOPT_HELP_OPTION_DECL},
66 {GETOPT_VERSION_OPTION_DECL},
67 {NULL, 0, NULL, 0}
70 void
71 usage (int status)
73 if (status != EXIT_SUCCESS)
74 emit_try_help ();
75 else
77 printf (_("\
78 Usage: %s CONTEXT COMMAND [args]\n\
79 or: %s [ -c ] [-u USER] [-r ROLE] [-t TYPE] [-l RANGE] COMMAND [args]\n\
80 "), program_name, program_name);
81 fputs (_("\
82 Run a program in a different SELinux security context.\n\
83 With neither CONTEXT nor COMMAND, print the current security context.\n\
84 "), stdout);
86 emit_mandatory_arg_note ();
88 fputs (_("\
89 CONTEXT Complete security context\n\
90 -c, --compute compute process transition context before modifying\n\
91 -t, --type=TYPE type (for same role as parent)\n\
92 -u, --user=USER user identity\n\
93 -r, --role=ROLE role\n\
94 -l, --range=RANGE levelrange\n\
95 \n\
96 "), stdout);
97 fputs (HELP_OPTION_DESCRIPTION, stdout);
98 fputs (VERSION_OPTION_DESCRIPTION, stdout);
99 emit_ancillary_info (PROGRAM_NAME);
101 exit (status);
105 main (int argc, char **argv)
107 char *role = NULL;
108 char *range = NULL;
109 char *user = NULL;
110 char *type = NULL;
111 char *context = NULL;
112 char *cur_context = NULL;
113 char *file_context = NULL;
114 char *new_context = NULL;
115 bool compute_trans = false;
117 context_t con;
119 initialize_main (&argc, &argv);
120 set_program_name (argv[0]);
121 setlocale (LC_ALL, "");
122 bindtextdomain (PACKAGE, LOCALEDIR);
123 textdomain (PACKAGE);
125 atexit (close_stdout);
127 while (1)
129 int option_index = 0;
130 int c = getopt_long (argc, argv, "+r:t:u:l:c", long_options,
131 &option_index);
132 if (c == -1)
133 break;
134 switch (c)
136 case 'r':
137 if (role)
138 error (EXIT_FAILURE, 0, _("multiple roles"));
139 role = optarg;
140 break;
141 case 't':
142 if (type)
143 error (EXIT_FAILURE, 0, _("multiple types"));
144 type = optarg;
145 break;
146 case 'u':
147 if (user)
148 error (EXIT_FAILURE, 0, _("multiple users"));
149 user = optarg;
150 break;
151 case 'l':
152 if (range)
153 error (EXIT_FAILURE, 0, _("multiple levelranges"));
154 range = optarg;
155 break;
156 case 'c':
157 compute_trans = true;
158 break;
160 case_GETOPT_HELP_CHAR;
161 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
162 default:
163 usage (EXIT_FAILURE);
164 break;
168 if (argc - optind == 0)
170 if (getcon (&cur_context) < 0)
171 error (EXIT_FAILURE, errno, _("failed to get current context"));
172 fputs (cur_context, stdout);
173 fputc ('\n', stdout);
174 return EXIT_SUCCESS;
177 if (!(user || role || type || range || compute_trans))
179 if (optind >= argc)
181 error (0, 0, _("you must specify -c, -t, -u, -l, -r, or context"));
182 usage (EXIT_FAILURE);
184 context = argv[optind++];
187 if (optind >= argc)
189 error (0, 0, _("no command specified"));
190 usage (EXIT_FAILURE);
193 if (is_selinux_enabled () != 1)
194 error (EXIT_FAILURE, 0, _("%s may be used only on a SELinux kernel"),
195 program_name);
197 if (context)
199 con = context_new (context);
200 if (!con)
201 error (EXIT_FAILURE, errno, _("failed to create security context: %s"),
202 quote (context));
204 else
206 if (getcon (&cur_context) < 0)
207 error (EXIT_FAILURE, errno, _("failed to get current context"));
209 /* We will generate context based on process transition */
210 if (compute_trans)
212 /* Get context of file to be executed */
213 if (getfilecon (argv[optind], &file_context) == -1)
214 error (EXIT_FAILURE, errno,
215 _("failed to get security context of %s"),
216 quoteaf (argv[optind]));
217 /* compute result of process transition */
218 if (security_compute_create (cur_context, file_context,
219 string_to_security_class ("process"),
220 &new_context) != 0)
221 error (EXIT_FAILURE, errno, _("failed to compute a new context"));
222 /* free contexts */
223 freecon (file_context);
224 freecon (cur_context);
226 /* set cur_context equal to new_context */
227 cur_context = new_context;
230 con = context_new (cur_context);
231 if (!con)
232 error (EXIT_FAILURE, errno, _("failed to create security context: %s"),
233 quote (cur_context));
234 if (user && context_user_set (con, user))
235 error (EXIT_FAILURE, errno, _("failed to set new user: %s"),
236 quote (user));
237 if (type && context_type_set (con, type))
238 error (EXIT_FAILURE, errno, _("failed to set new type: %s"),
239 quote (type));
240 if (range && context_range_set (con, range))
241 error (EXIT_FAILURE, errno, _("failed to set new range: %s"),
242 quote (range));
243 if (role && context_role_set (con, role))
244 error (EXIT_FAILURE, errno, _("failed to set new role: %s"),
245 quote (role));
248 if (security_check_context (context_str (con)) < 0)
249 error (EXIT_FAILURE, errno, _("invalid context: %s"),
250 quote (context_str (con)));
252 if (setexeccon (context_str (con)) != 0)
253 error (EXIT_FAILURE, errno, _("unable to set security context %s"),
254 quote (context_str (con)));
255 if (cur_context != NULL)
256 freecon (cur_context);
258 execvp (argv[optind], argv + optind);
260 int exit_status = errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE;
261 error (0, errno, "%s", quote (argv[optind]));
262 return exit_status;