All of lore.kernel.org
 help / color / mirror / Atom feed
* [patch] updated chcon.c
@ 2003-07-14  2:47 Colin Walters
  2003-07-15 21:08 ` Stephen Smalley
  0 siblings, 1 reply; 2+ messages in thread
From: Colin Walters @ 2003-07-14  2:47 UTC (permalink / raw)
  To: selinux

[-- Attachment #1: Type: text/plain, Size: 242 bytes --]

Hi,

Per our previous discussion, I've updated my previous patch for chcon to
the new 2.5 API.  I tried to minimize the number of places which had
knowledge of the components of the security context.

Tested on my Debian SELinux 2.5 system.


[-- Attachment #2: chcon.patch --]
[-- Type: text/plain, Size: 9668 bytes --]

--- chcon.c~	2003-07-13 22:42:47.000000000 -0400
+++ chcon.c	2003-07-13 22:33:06.000000000 -0400
@@ -1,11 +1,15 @@
 /* chcontext -- change security context of a pathname */
 
+/* Added the ability to specify individual components of
+   a security context. -- Colin Walters <walters@debian.org> */
+
 #include <config.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <grp.h>
 #include <getopt.h>
 #include <selinux/selinux.h>
+#include <selinux/context.h>
 
 #include "system.h"
 #include "error.h"
@@ -31,8 +35,7 @@
   V_off
 };
 
-static int change_dir_context PARAMS ((const char *dir, security_context_t context,
-				       const struct stat *statp));
+static int change_dir_context PARAMS ((const char *dir, const struct stat *statp));
 
 /* The name the program was run with. */
 char *program_name;
@@ -51,7 +54,13 @@
 static enum Verbosity verbosity = V_off;
 
 /* The name of the context file is being given. */
-static const char *contextname;
+static const char *specified_context;
+
+/* Specific components of the context */
+static const char *specified_user;
+static const char *specified_role;
+static const char *specified_range;
+static const char *specified_type;
 
 /* The argument to the --reference option.  Use the context of this file.
    This file must exist.  */
@@ -72,6 +81,10 @@
   {"quiet", no_argument, 0, 'f'},
   {"reference", required_argument, 0, CHAR_MAX + 1},
   {"context", required_argument, 0, CHAR_MAX + 2},
+  {"user", required_argument, 0, 'u'},
+  {"role", required_argument, 0, 'r'},      
+  {"type", required_argument, 0, 't'},
+  {"range", required_argument, 0, 'l'},   
   {"verbose", no_argument, 0, 'v'},
   {"help", no_argument, &show_help, 1},
   {"version", no_argument, &show_version, 1},
@@ -82,7 +95,7 @@
    CHANGED describes what (if anything) has happened. */
 
 static void
-describe_change (const char *file, enum Change_status changed)
+describe_change (const char *file, security_context_t newcontext, enum Change_status changed)
 {
   const char *fmt;
   switch (changed)
@@ -99,71 +112,128 @@
     default:
       abort ();
     }
-  printf (fmt, file, contextname);
+  printf (fmt, file, newcontext);
+}
+
+static int
+compute_context_from_mask (security_context_t context, context_t *ret)
+{
+  context_t newcontext = context_new (context);
+  if (!newcontext)
+    return 1;
+#define SETCOMPONENT(comp) \
+  do { \
+    if (specified_ ## comp) \
+      if (context_ ## comp ## _set (newcontext, specified_ ## comp)) \
+        goto lose; \
+  } while (0)
+      
+  SETCOMPONENT(user);
+  SETCOMPONENT(range);
+  SETCOMPONENT(role);
+  SETCOMPONENT(type);
+#undef SETCOMPONENT
+  
+  *ret = newcontext;
+  return 0;
+ lose:
+  context_free (newcontext);
+  return 1;
 }
 
-/* Change the context of FILE to CONTEXT.
+/* Change the context of FILE, using specified components.
    If it is a directory and -R is given, recurse.
    Return 0 if successful, 1 if errors occurred. */
 
 static int
-change_file_context (const char *file, security_context_t context)
+change_file_context (const char *file)
 {
   struct stat file_stats;
   security_context_t file_context=NULL;
+  context_t context;
+  security_context_t context_string;
   int errors = 0;
 
   if ((lgetfilecon(file, &file_context)<0) && (errno != ENODATA))
-
     {
       if (force_silent == 0)
 	error (0, errno, "%s", file);
       return 1;
     }
 
-  if ((file_context==NULL) || strcmp(context,file_context)!=0)
+  /* This is kind of a gross hack.  But if the file doesn't have a
+     context, and we're not setting all of the context components,
+     there isn't really a sensible default.  Thus, we just get the
+     process context, and hope for the best. */
+  if (file_context == NULL && specified_context == NULL)
+    if (getcon (&file_context) < 0)
+      {
+	if (force_silent == 0)
+	  error (0, errno, _("couldn't get default context"));
+	return 1;
+      }
+
+  if (specified_context == NULL)
+    {
+      if (compute_context_from_mask (file_context, &context))
+	{
+	  error (0, 0, _("couldn't compute security context from %s"), file_context);
+	      return 1;
+	}
+    }
+  else
+    {
+      context = context_new (specified_context);
+      if (!context)
+	error (1, 0, _("virtual memory exhausted"));	    
+    }
+
+  context_string = context_str (context);
+      
+  if (strcmp(context_string,file_context)!=0)
     {
       int fail;
 
       if (change_symlinks)
-      	fail = lsetfilecon (file, context);
+      	fail = lsetfilecon (file, context_string);
       else
-      	fail = setfilecon (file, context);
+      	fail = setfilecon (file, context_string);
 
       if (verbosity == V_high || (verbosity == V_changes_only && !fail))
-	describe_change (file, (fail ? CH_FAILED : CH_SUCCEEDED));
+	describe_change (file, context_string, (fail ? CH_FAILED : CH_SUCCEEDED));
 
       if (fail)
 	{
 	  errors = 1;
 	  if (force_silent == 0)
 	    {
-	      error (0, errno, "%s", file);
+	      error (0, errno, _("failed to change context of %s to %s"), file, context_string);
 	    }
 	}
     }
   else if (verbosity == V_high)
     {
-      describe_change (file, CH_NO_CHANGE_REQUESTED);
+      describe_change (file, context_string, CH_NO_CHANGE_REQUESTED);
     }
 
+  context_free(context);
   freecon(file_context);
 
   if (recurse) {
     if (lstat(file, &file_stats)==0)
       if (S_ISDIR (file_stats.st_mode))
-		 errors |= change_dir_context (file, context, &file_stats);
+		 errors |= change_dir_context (file, &file_stats);
   }
   return errors;
 }
 
 /* Recursively change context of the files in directory DIR
-   to CONTEXT CONTEXT.
+   using specified context components.
    STATP points to the results of lstat on DIR.
    Return 0 if successful, 1 if errors occurred. */
 
 static int
-change_dir_context (const char *dir, security_context_t context, const struct stat *statp)
+change_dir_context (const char *dir, const struct stat *statp)
 {
   char *name_space, *namep;
   char *path;			/* Full path of each entry to process. */
@@ -202,7 +272,7 @@
 	  path = xrealloc (path, pathlength);
 	}
       strcpy (path + dirlength, namep);
-      errors |= change_file_context (path, context);
+      errors |= change_file_context (path);
     }
   free (path);
   free (name_space);
@@ -219,6 +289,7 @@
     {
       printf (_("\
 Usage: %s [OPTION]... CONTEXT FILE...\n\
+  or:  %s [OPTION]... [-u USER] [-r ROLE] [-l RANGE] [-t TYPE] FILE...\n\
   or:  %s [OPTION]... --reference=RFILE FILE...\n\
 "),
 	program_name, program_name, program_name);
@@ -230,6 +301,10 @@
                          (available only on systems with lchown system call)\n\
   -f, --silent, --quiet  suppress most error messages\n\
       --reference=RFILE  use RFILE's group instead of using a CONTEXT value\n\
+  -u, --user=USER        set user USER in the target security context\n\
+  -r, --role=ROLE        set role ROLE in the target security context\n\
+  -t, --type=TYPE        set type TYPE in the target security context\n\
+  -l, --range=RANGE      set range RANGE in the target security context\n\
   -R, --recursive        change files and directories recursively\n\
   -v, --verbose          output a diagnostic for every file processed\n\
       --help             display this help and exit\n\
@@ -243,10 +318,10 @@
 int
 main (int argc, char **argv)
 {
-  security_context_t context = NULL;
   security_context_t ref_context = NULL;
   int errors = 0;
   int optc;
+  int component_specified = 0;
   
   program_name = argv[0];
   setlocale (LC_ALL, "");
@@ -255,12 +330,28 @@
 
   recurse = force_silent = 0;
   
-  while ((optc = getopt_long (argc, argv, "Rcfhv", long_options, NULL)) != -1)
+  while ((optc = getopt_long (argc, argv, "Rcfhvu:r:t:l:", long_options, NULL)) != -1)
   {
 	  switch (optc)
 	  {
 	  case 0:
-		  break;
+	    break;
+	  case 'u':
+	    specified_user = optarg;
+	    component_specified = 1;
+	    break;
+	  case 'r':
+	    specified_role = optarg;
+	    component_specified = 1;
+	    break;
+	  case 't':
+	    specified_type = optarg;
+	    component_specified = 1;
+	    break;
+	  case 'l':
+	    specified_range = optarg;
+	    component_specified = 1;
+	    break;
 	  case CHAR_MAX + 1:
 		  reference_file = optarg;
 		  break;
@@ -294,24 +385,33 @@
   if (show_help)
     usage (0);
 
-  if (argc - optind + ( (reference_file || ( context > 0 ) ) ? 1 : 0) <= 1)
-  {
-     error (0, 0, _("too few arguments"));
-     usage (1);
-  }
+  
+  if (reference_file && component_specified)
+    {
+      error (0, 0, _("conflicting security context specifiers given"));
+      usage (1);
+    }
+
+  if (!(((reference_file || component_specified)
+	 && (argc - optind > 0))
+	|| (argc - optind > 1)))
+    {
+      error (0, 0, _("too few arguments"));
+      usage (1);
+    }
   
   if (reference_file)
     {
       if (getfilecon (reference_file, &ref_context)<0)
 	error (1, errno, "%s", reference_file);
-
-      context = ref_context;
+      
+      specified_context = ref_context;
     }
-  else {
-     context = argv[optind++];
+  else if (!component_specified) {
+    specified_context = argv[optind++];
   }
   for (; optind < argc; ++optind)
-     errors |= change_file_context (argv[optind], context);
+     errors |= change_file_context (argv[optind]);
 
   if (verbosity != V_off)
     close_stdout ();

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [patch] updated chcon.c
  2003-07-14  2:47 [patch] updated chcon.c Colin Walters
@ 2003-07-15 21:08 ` Stephen Smalley
  0 siblings, 0 replies; 2+ messages in thread
From: Stephen Smalley @ 2003-07-15 21:08 UTC (permalink / raw)
  To: Colin Walters; +Cc: selinux

On Sun, 2003-07-13 at 22:47, Colin Walters wrote:
> Per our previous discussion, I've updated my previous patch for chcon to
> the new 2.5 API.  I tried to minimize the number of places which had
> knowledge of the components of the security context.
> 
> Tested on my Debian SELinux 2.5 system.

The coreutils-selinux.patch in the sourceforge CVS tree has been updated
to include the modified chcon.c.

-- 
Stephen Smalley <sds@epoch.ncsc.mil>
National Security Agency


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@tycho.nsa.gov with
the words "unsubscribe selinux" without quotes as the message.

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2003-07-15 21:08 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-07-14  2:47 [patch] updated chcon.c Colin Walters
2003-07-15 21:08 ` Stephen Smalley

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.