From: Colin Walters <walters@verbum.org>
To: selinux@tycho.nsa.gov
Subject: [patch] updated chcon.c
Date: 13 Jul 2003 22:47:56 -0400 [thread overview]
Message-ID: <1058150876.4130.21.camel@columbia> (raw)
[-- 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 ();
next reply other threads:[~2003-07-14 2:50 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-07-14 2:47 Colin Walters [this message]
2003-07-15 21:08 ` [patch] updated chcon.c Stephen Smalley
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1058150876.4130.21.camel@columbia \
--to=walters@verbum.org \
--cc=selinux@tycho.nsa.gov \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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.