LCOV - code coverage report
Current view: top level - src - runcon.c (source / functions) Hit Total Coverage
Test: coreutils.info Lines: 64 108 59.3 %
Date: 2018-01-30 Functions: 2 2 100.0 %

          Line data    Source code
       1             : /*
       2             :  * runcon [ context |
       3             :  *         ( [ -c ] [ -r role ] [-t type] [ -u user ] [ -l levelrange ] )
       4             :  *         command [arg1 [arg2 ...] ]
       5             :  *
       6             :  * attempt to run the specified command with the specified context.
       7             :  *
       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
      13             :  *
      14             :  * Contexts are interpreted as follows:
      15             :  *
      16             :  * Number of       MLS
      17             :  * components    system?
      18             :  *
      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
      25             :  */
      26             : 
      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"
      42             : 
      43             : /* The official name of this program (e.g., no `g' prefix).  */
      44             : #define PROGRAM_NAME "runcon"
      45             : 
      46             : #define AUTHORS "Russell Coker"
      47             : 
      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}
      57             : };
      58             : 
      59             : /* The name the program was run with. */
      60             : char *program_name;
      61             : 
      62             : void
      63          15 : usage (int status)
      64             : {
      65          15 :   if (status != EXIT_SUCCESS)
      66          14 :     fprintf (stderr, _("Try `%s --help' for more information.\n"),
      67             :              program_name);
      68             :   else
      69             :     {
      70           1 :       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           1 :       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           1 :       fputs (HELP_OPTION_DESCRIPTION, stdout);
      87           1 :       fputs (VERSION_OPTION_DESCRIPTION, stdout);
      88             :     }
      89          15 :   exit (status);
      90             : }
      91             : 
      92             : int
      93          34 : main (int argc, char **argv)
      94             : {
      95          34 :   char *role = NULL;
      96          34 :   char *range = NULL;
      97          34 :   char *user = NULL;
      98          34 :   char *type = NULL;
      99          34 :   char *context = NULL;
     100          34 :   security_context_t cur_context = NULL;
     101          34 :   security_context_t file_context = NULL;
     102          34 :   security_context_t new_context = NULL;
     103          34 :   bool compute_trans = false;
     104             : 
     105             :   context_t con;
     106             : 
     107             :   initialize_main (&argc, &argv);
     108          34 :   program_name = argv[0];
     109          34 :   setlocale (LC_ALL, "");
     110             :   bindtextdomain (PACKAGE, LOCALEDIR);
     111             :   textdomain (PACKAGE);
     112             : 
     113          34 :   atexit (close_stdout);
     114             : 
     115             :   while (1)
     116          16 :     {
     117          50 :       int option_index = 0;
     118          50 :       int c = getopt_long (argc, argv, "+r:t:u:l:c", long_options,
     119             :                            &option_index);
     120          50 :       if (c == -1)
     121          16 :         break;
     122          34 :       switch (c)
     123             :         {
     124           4 :         case 'r':
     125           4 :           if (role)
     126           1 :             error (EXIT_FAILURE, 0, _("multiple roles"));
     127           3 :           role = optarg;
     128           3 :           break;
     129           7 :         case 't':
     130           7 :           if (type)
     131           1 :             error (EXIT_FAILURE, 0, _("multiple types"));
     132           6 :           type = optarg;
     133           6 :           break;
     134           3 :         case 'u':
     135           3 :           if (user)
     136           1 :             error (EXIT_FAILURE, 0, _("multiple users"));
     137           2 :           user = optarg;
     138           2 :           break;
     139           3 :         case 'l':
     140           3 :           if (range)
     141           1 :             error (EXIT_FAILURE, 0, _("multiple levelranges"));
     142           2 :           range = optarg;
     143           2 :           break;
     144           3 :         case 'c':
     145           3 :           compute_trans = true;
     146           3 :           break;
     147             : 
     148           1 :         case_GETOPT_HELP_CHAR;
     149           1 :         case_GETOPT_VERSION_CHAR (PROGRAM_NAME, AUTHORS);
     150          12 :         default:
     151          12 :           usage (EXIT_FAILURE);
     152           0 :           break;
     153             :         }
     154             :     }
     155             : 
     156          16 :   if (argc - optind == 0)
     157             :     {
     158           9 :       if (getcon (&cur_context) < 0)
     159           9 :         error (EXIT_FAILURE, errno, _("failed to get current context"));
     160           0 :       fputs (cur_context, stdout);
     161           0 :       fputc ('\n', stdout);
     162           0 :       exit (EXIT_SUCCESS);
     163             :     }
     164             : 
     165           7 :   if (!(user || role || type || range || compute_trans))
     166             :     {
     167           5 :       if (optind >= argc)
     168             :         {
     169           0 :           error (0, 0, _("you must specify -c, -t, -u, -l, -r, or context"));
     170           0 :           usage (1);
     171             :         }
     172           5 :       context = argv[optind++];
     173             :     }
     174             : 
     175           7 :   if (optind >= argc)
     176             :     {
     177           2 :       error (0, 0, _("no command specified"));
     178           2 :       usage (1);
     179             :     }
     180             : 
     181             :   if (is_selinux_enabled () != 1)
     182           5 :     error (EXIT_FAILURE, 0,
     183             :            _("runcon may be used only on a SELinux kernel"));
     184             : 
     185           0 :   if (context)
     186             :     {
     187           0 :       con = context_new (context);
     188           0 :       if (!con)
     189           0 :         error (EXIT_FAILURE, errno, _("failed to create security context: %s"),
     190             :                quotearg_colon (context));
     191             :     }
     192             :   else
     193             :     {
     194           0 :       if (getcon (&cur_context) < 0)
     195           0 :         error (EXIT_FAILURE, errno, _("failed to get current context"));
     196             : 
     197             :       /* We will generate context based on process transition */
     198           0 :       if (compute_trans)
     199             :         {
     200             :           /* Get context of file to be executed */
     201           0 :           if (getfilecon (argv[optind], &file_context) == -1)
     202           0 :             error (EXIT_FAILURE, errno,
     203             :                    _("failed to get security context of %s"),
     204           0 :                    quote (argv[optind]));
     205             :           /* compute result of process transition */
     206           0 :           if (security_compute_create (cur_context, file_context,
     207             :                                        SECCLASS_PROCESS, &new_context) != 0)
     208           0 :             error (EXIT_FAILURE, errno,
     209             :                    _("failed to compute a new context"));
     210             :           /* free contexts */
     211           0 :           freecon (file_context);
     212           0 :           freecon (cur_context);
     213             : 
     214             :           /* set cur_context equal to new_context */
     215           0 :           cur_context = new_context;
     216             :         }
     217             : 
     218           0 :       con = context_new (cur_context);
     219           0 :       if (!con)
     220           0 :         error (EXIT_FAILURE, errno, _("failed to create security context: %s"),
     221             :                quotearg_colon (cur_context));
     222           0 :       if (user && context_user_set (con, user))
     223           0 :         error (EXIT_FAILURE, errno, _("failed to set new user %s"), user);
     224           0 :       if (type && context_type_set (con, type))
     225           0 :         error (EXIT_FAILURE, errno, _("failed to set new type %s"), type);
     226           0 :       if (range && context_range_set (con, range))
     227           0 :         error (EXIT_FAILURE, errno, _("failed to set new range %s"), range);
     228           0 :       if (role && context_role_set (con, role))
     229           0 :         error (EXIT_FAILURE, errno, _("failed to set new role %s"), role);
     230             :     }
     231             : 
     232           0 :   if (security_check_context (context_str (con)) < 0)
     233           0 :     error (EXIT_FAILURE, errno, _("invalid context: %s"),
     234           0 :            quotearg_colon (context_str (con)));
     235             : 
     236           0 :   if (setexeccon (context_str (con)) != 0)
     237           0 :     error (EXIT_FAILURE, errno, _("unable to set security context %s"),
     238           0 :            quote (context_str (con)));
     239           0 :   if (cur_context != NULL)
     240           0 :     freecon (cur_context);
     241             : 
     242           0 :   execvp (argv[optind], argv + optind);
     243             : 
     244             :   {
     245           0 :     int exit_status = (errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE);
     246           0 :     error (0, errno, "%s", argv[optind]);
     247           0 :     exit (exit_status);
     248             :   }
     249             : }

Generated by: LCOV version 1.10