convert the rest to use proper_name -- manually
[coreutils.git] / src / runcon.c
blob3c45c6fec8bd0215ea0b4963221c7fc0bbc79272
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 proper_name ("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);
88 emit_bug_reporting_address ();
90 exit (status);
93 int
94 main (int argc, char **argv)
96 char *role = NULL;
97 char *range = NULL;
98 char *user = NULL;
99 char *type = NULL;
100 char *context = NULL;
101 security_context_t cur_context = NULL;
102 security_context_t file_context = NULL;
103 security_context_t new_context = NULL;
104 bool compute_trans = false;
106 context_t con;
108 initialize_main (&argc, &argv);
109 program_name = argv[0];
110 setlocale (LC_ALL, "");
111 bindtextdomain (PACKAGE, LOCALEDIR);
112 textdomain (PACKAGE);
114 atexit (close_stdout);
116 while (1)
118 int option_index = 0;
119 int c = getopt_long (argc, argv, "+r:t:u:l:c", long_options,
120 &option_index);
121 if (c == -1)
122 break;
123 switch (c)
125 case 'r':
126 if (role)
127 error (EXIT_FAILURE, 0, _("multiple roles"));
128 role = optarg;
129 break;
130 case 't':
131 if (type)
132 error (EXIT_FAILURE, 0, _("multiple types"));
133 type = optarg;
134 break;
135 case 'u':
136 if (user)
137 error (EXIT_FAILURE, 0, _("multiple users"));
138 user = optarg;
139 break;
140 case 'l':
141 if (range)
142 error (EXIT_FAILURE, 0, _("multiple levelranges"));
143 range = optarg;
144 break;
145 case 'c':
146 compute_trans = true;
147 break;
149 case_GETOPT_HELP_CHAR;
150 case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
151 default:
152 usage (EXIT_FAILURE);
153 break;
157 if (argc - optind == 0)
159 if (getcon (&cur_context) < 0)
160 error (EXIT_FAILURE, errno, _("failed to get current context"));
161 fputs (cur_context, stdout);
162 fputc ('\n', stdout);
163 exit (EXIT_SUCCESS);
166 if (!(user || role || type || range || compute_trans))
168 if (optind >= argc)
170 error (0, 0, _("you must specify -c, -t, -u, -l, -r, or context"));
171 usage (1);
173 context = argv[optind++];
176 if (optind >= argc)
178 error (0, 0, _("no command specified"));
179 usage (1);
182 if (is_selinux_enabled () != 1)
183 error (EXIT_FAILURE, 0,
184 _("runcon may be used only on a SELinux kernel"));
186 if (context)
188 con = context_new (context);
189 if (!con)
190 error (EXIT_FAILURE, errno, _("failed to create security context: %s"),
191 quotearg_colon (context));
193 else
195 if (getcon (&cur_context) < 0)
196 error (EXIT_FAILURE, errno, _("failed to get current context"));
198 /* We will generate context based on process transition */
199 if (compute_trans)
201 /* Get context of file to be executed */
202 if (getfilecon (argv[optind], &file_context) == -1)
203 error (EXIT_FAILURE, errno,
204 _("failed to get security context of %s"),
205 quote (argv[optind]));
206 /* compute result of process transition */
207 if (security_compute_create (cur_context, file_context,
208 SECCLASS_PROCESS, &new_context) != 0)
209 error (EXIT_FAILURE, errno,
210 _("failed to compute a new context"));
211 /* free contexts */
212 freecon (file_context);
213 freecon (cur_context);
215 /* set cur_context equal to new_context */
216 cur_context = new_context;
219 con = context_new (cur_context);
220 if (!con)
221 error (EXIT_FAILURE, errno, _("failed to create security context: %s"),
222 quotearg_colon (cur_context));
223 if (user && context_user_set (con, user))
224 error (EXIT_FAILURE, errno, _("failed to set new user %s"), user);
225 if (type && context_type_set (con, type))
226 error (EXIT_FAILURE, errno, _("failed to set new type %s"), type);
227 if (range && context_range_set (con, range))
228 error (EXIT_FAILURE, errno, _("failed to set new range %s"), range);
229 if (role && context_role_set (con, role))
230 error (EXIT_FAILURE, errno, _("failed to set new role %s"), role);
233 if (security_check_context (context_str (con)) < 0)
234 error (EXIT_FAILURE, errno, _("invalid context: %s"),
235 quotearg_colon (context_str (con)));
237 if (setexeccon (context_str (con)) != 0)
238 error (EXIT_FAILURE, errno, _("unable to set security context %s"),
239 quote (context_str (con)));
240 if (cur_context != NULL)
241 freecon (cur_context);
243 execvp (argv[optind], argv + optind);
246 int exit_status = (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
247 error (0, errno, "%s", argv[optind]);
248 exit (exit_status);