Guido Trentalancia | 2 Nov 2009 18:14

Patch for Ticket #1 [1672486] (checkpolicy/checkmodule)

This patch is proposed to solve Ticket #1 [1672486] (command line
binaries should support --version and --help).

It adds handling of -h, -V and the long formats --help and --version to
all binaries (checkpolicy/checkmodule).

It also adds handling of long options for some of the available options.

Manual pages have also been updated accordingly (and a few undocumented
options have been documented).

Guido Trentalancia

diff -pru checkpolicy/checkmodule.8 checkpolicy-new/checkmodule.8
--- checkpolicy/checkmodule.8   2009-11-01 22:23:01.000000000 +0100
+++ checkpolicy-new/checkmodule.8       2009-11-02 17:20:51.000000000
+0100
 <at>  <at>  -21,23 +21,26  <at>  <at>  the module package into the module store

 .SH OPTIONS
 .TP
-.B \-b
+.B \-b,\-\-binary
 Read an existing binary policy module file rather than a source policy
 module file.  This option is a development/debugging aid.
 .TP
 .B \-m
 Generate a non-base policy module.
 .TP
-.B \-M
(Continue reading)

Guido Trentalancia | 2 Nov 2009 18:14

Patch for Ticket #1 [1672486] (policycoreutils)

This patch is proposed to solve Ticket #1 [1672486] (command line
binaries should support --version and --help).

It adds handling of -h, -V and the long formats --help and --version to
all binaries that are produced from C code. It does not tackle the issue
for Python-based tools (e.g. semanage).

Manual pages have also been updated accordingly.

Guido Trentalancia

diff -pru policycoreutils/load_policy/load_policy.8
policycoreutils-new/load_policy/load_policy.8
--- policycoreutils/load_policy/load_policy.8   2009-11-01
22:23:01.000000000 +0100
+++ policycoreutils-new/load_policy/load_policy.8       2009-11-02
00:40:13.000000000 +0100
 <at>  <at>  -15,11 +15,25  <at>  <at>  values in the policy file.
 
 .SH "OPTIONS"
 .TP
+.B \-V
+or
+.B \-\-version
+shows the current version of load_policy
+.TP
+.B \-h
+or
+.B \-\-help
+shows the usage information for load_policy
(Continue reading)

sds | 2 Nov 2009 22:07
Picon

full version OEM soft

 
 


Please do not reply to this e-mail. To contact us, please Click Here
 
We hope you enjoy our surveys and we'll see you online!
 
 

1226 Allandale West, 26th Floor
Kansas 8739

If you no longer wish to receive offers from MyView, please Click Here
 
 
 
Chad Sellers | 2 Nov 2009 23:12
Favicon

Re: [PATCH 1/2] policycoreutils: share setfiles restore function with restorecond

On 10/29/09 10:14 AM, "Daniel J Walsh" <dwalsh@...> wrote:

> Chad, once you have patch 1 in I will send you the restorecond patch, with all
> the missing files.

Sounds good. And this will have split out the refactoring patch from the
functional changes (new options, adding DBUS support), right?

Thanks,
Chad

Chad Sellers | 2 Nov 2009 23:12
Favicon

Re: [PATCH 1/2] policycoreutils: share setfiles restore function with restorecond

On 10/29/09 10:05 AM, "Daniel J Walsh" <dwalsh@...> wrote:

> On 10/28/2009 04:03 PM, Chad Sellers wrote:
>> I've rebased this so that it will apply to current trunk (which is included
>> below). Looks pretty good to me, though I have 2 questions:
>> 
>> 1) Why remove the free() call in remove_exclude()?
> I have no idea why this would be removed.  I think it should be put back in.

OK, I put it back.

>> 2) Why the new check at the beginning of match()?
>> 
> restorecond and setfiles/restorecon should realize when they hit a hardlinked
> file with multiple labels and not label them.

OK, I left this in. I did change the message slightly.

This is now merged upstream with these changes.

Thanks,
Chad Sellers

> I actually think the code should check every file and if it has hard links,
> not relabel the link until it finishes the search.  Then check all the links
> and see if they all have the same label.  Then set the label.
>> Other than that, let me know if anyone spots a rebasing error.
>> 
>> Rebased patch:
>> 
>> This is the first of two patches.
>> 
>> This patch splits all of the restore functionality in setfiles
>> into another two files, restore.c and restore.h.
>> 
>> The reason for this is shown in the next patch, which patches
>> restorecond to share this code.
>> 
>> To use it, instantiate a restore_opts struct with the proper options
>> and then pass a pointer to it into restore_init, and call restore_destroy
>> later.
>> 
>> Signed-off-by: Thomas Liu <tliu@...>
>> Signed-off-by: Dan Walsh <dwalsh@...>
>> 
>> ---
>>  policycoreutils/setfiles/Makefile   |    4 +-
>>  policycoreutils/setfiles/restore.c  |  605 ++++++++++++++++++++++++++++
>>  policycoreutils/setfiles/restore.h  |   50 +++
>>  policycoreutils/setfiles/setfiles.c |  741
>> ++++-------------------------------
>>  4 files changed, 735 insertions(+), 665 deletions(-)
>>  create mode 100644 policycoreutils/setfiles/restore.c
>>  create mode 100644 policycoreutils/setfiles/restore.h
>> 
>> diff --git a/policycoreutils/setfiles/Makefile
>> b/policycoreutils/setfiles/Makefile
>> index 8600f58..26a965f 100644
>> --- a/policycoreutils/setfiles/Makefile
>> +++ b/policycoreutils/setfiles/Makefile
>>  <at>  <at>  -5,7 +5,7  <at>  <at>  MANDIR = $(PREFIX)/share/man
>>  LIBDIR ?= $(PREFIX)/lib
>>  AUDITH = $(shell ls /usr/include/libaudit.h 2>/dev/null)
>>  
>> -CFLAGS = -Werror -Wall -W
>> +CFLAGS = -g -Werror -Wall -W
>>  override CFLAGS += -I$(PREFIX)/include
>>  LDLIBS = -lselinux -lsepol -L$(LIBDIR)
>>  
>>  <at>  <at>  -16,7 +16,7  <at>  <at>  endif
>>  
>>  all: setfiles restorecon
>>  
>> -setfiles:  setfiles.o
>> +setfiles:  setfiles.o restore.o
>>  
>>  restorecon: setfiles
>> ln -sf setfiles restorecon
>> diff --git a/policycoreutils/setfiles/restore.c
>> b/policycoreutils/setfiles/restore.c
>> new file mode 100644
>> index 0000000..d37fe22
>> --- /dev/null
>> +++ b/policycoreutils/setfiles/restore.c
>>  <at>  <at>  -0,0 +1,605  <at>  <at> 
>> +#include "restore.h"
>> +
>> +#define SKIP -2
>> +#define ERR -1
>> +#define MAX_EXCLUDES 1000
>> +
>> +/*
>> + * The hash table of associations, hashed by inode number.
>> + * Chaining is used for collisions, with elements ordered
>> + * by inode number in each bucket.  Each hash bucket has a dummy
>> + * header.
>> + */
>> +#define HASH_BITS 16
>> +#define HASH_BUCKETS (1 << HASH_BITS)
>> +#define HASH_MASK (HASH_BUCKETS-1)
>> +
>> +/*
>> + * An association between an inode and a context.
>> + */
>> +typedef struct file_spec {
>> + ino_t ino;  /* inode number */
>> + char *con;  /* matched context */
>> + char *file;  /* full pathname */
>> + struct file_spec *next; /* next association in hash bucket chain */
>> +} file_spec_t;
>> +
>> +struct edir {
>> + char *directory;
>> + size_t size;
>> +};
>> +
>> +
>> +static file_spec_t *fl_head;
>> +static int exclude(const char *file);
>> +static int filespec_add(ino_t ino, const security_context_t con, const char
>> *file);
>> +static int only_changed_user(const char *a, const char *b);
>> +struct restore_opts *r_opts = NULL;
>> +static void filespec_destroy(void);
>> +static void filespec_eval(void);
>> +static int excludeCtr = 0;
>> +static struct edir excludeArray[MAX_EXCLUDES];
>> +
>> +void remove_exclude(const char *directory)
>> +{
>> + int i = 0;
>> + for (i = 0; i < excludeCtr; i++) {
>> +  if (strcmp(directory, excludeArray[i].directory) == 0) {
>> +   if (i != excludeCtr-1)
>> +    excludeArray[i] = excludeArray[excludeCtr-1];
>> +   excludeCtr--;
>> +   return;
>> +  }
>> + }
>> + return;
>> +
>> +}
>> +
>> +void restore_init(struct restore_opts *opts)
>> +{ 
>> + r_opts = opts;
>> + struct selinux_opt selinux_opts[] = {
>> +  { SELABEL_OPT_VALIDATE, r_opts->selabel_opt_validate },
>> +  { SELABEL_OPT_PATH, r_opts->selabel_opt_path }
>> + };
>> + r_opts->hnd = selabel_open(SELABEL_CTX_FILE, selinux_opts, 2);
>> + if (!r_opts->hnd) {
>> +  perror(r_opts->selabel_opt_path);
>> +  exit(1);
>> + } 
>> +}
>> +
>> +void restore_finish()
>> +{
>> + int i;
>> + for (i = 0; i < excludeCtr; i++) {
>> +  free(excludeArray[i].directory);
>> + }
>> +}
>> +
>> +static int match(const char *name, struct stat *sb, char **con)
>> +{
>> + if (!(r_opts->hard_links) && !S_ISDIR(sb->st_mode) && (sb->st_nlink > 1)) {
>> +  fprintf(stderr, "Warning! %s refers to a hard link, not fixing hard
>> links.\n",
>> +     name);
>> +  return -1;
>> + }
>> + 
>> + if (NULL != r_opts->rootpath) {
>> +  if (0 != strncmp(r_opts->rootpath, name, r_opts->rootpathlen)) {
>> +   fprintf(stderr, "%s:  %s is not located in %s\n",
>> +    r_opts->progname, name, r_opts->rootpath);
>> +   return -1;
>> +  }
>> +  name += r_opts->rootpathlen;
>> + }
>> +
>> + if (r_opts->rootpath != NULL && name[0] == '\0')
>> +  /* this is actually the root dir of the alt root */
>> +  return selabel_lookup_raw(r_opts->hnd, con, "/", sb->st_mode);
>> + else
>> +  return selabel_lookup_raw(r_opts->hnd, con, name, sb->st_mode);
>> +}
>> +static int restore(FTSENT *ftsent)
>> +{
>> + char *my_file = strdupa(ftsent->fts_path);
>> + int ret;
>> + char *context, *newcon;
>> + int user_only_changed = 0;
>> +
>> + if (match(my_file, ftsent->fts_statp, &newcon) < 0)
>> +  /* Check for no matching specification. */
>> +  return (errno == ENOENT) ? 0 : -1;
>> +
>> + if (r_opts->progress) {
>> +  r_opts->count++;
>> +  if (r_opts->count % (80 * STAR_COUNT) == 0) {
>> +   fprintf(stdout, "\n");
>> +   fflush(stdout);
>> +  }
>> +  if (r_opts->count % STAR_COUNT == 0) {
>> +   fprintf(stdout, "*");
>> +   fflush(stdout);
>> +  }
>> + }
>> +
>> + /*
>> +  * Try to add an association between this inode and
>> +  * this specification.  If there is already an association
>> +  * for this inode and it conflicts with this specification,
>> +  * then use the last matching specification.
>> +  */
>> + if (r_opts->add_assoc) {
>> +  ret = filespec_add(ftsent->fts_statp->st_ino, newcon, my_file);
>> +  if (ret < 0)
>> +   goto err;
>> +
>> +  if (ret > 0)
>> +   /* There was already an association and it took precedence. */
>> +   goto out;
>> + }
>> +
>> + if (r_opts->debug) {
>> +  printf("%s:  %s matched by %s\n", r_opts->progname, my_file, newcon);
>> + }
>> +
>> + /* Get the current context of the file. */
>> + ret = lgetfilecon_raw(ftsent->fts_accpath, &context);
>> + if (ret < 0) {
>> +  if (errno == ENODATA) {
>> +   context = NULL;
>> +  } else {
>> +   fprintf(stderr, "%s get context on %s failed: '%s'\n",
>> +    r_opts->progname, my_file, strerror(errno));
>> +   goto err;
>> +  }
>> +  user_only_changed = 0;
>> + } else
>> +  user_only_changed = only_changed_user(context, newcon);
>> + /* lgetfilecon returns number of characters and ret needs to be reset
>> +  * to 0.
>> +  */
>> + ret = 0;
>> +
>> + /*
>> +  * Do not relabel the file if the matching specification is
>> +  * <<none>> or the file is already labeled according to the
>> +  * specification.
>> +  */
>> + if ((strcmp(newcon, "<<none>>") == 0) ||
>> +     (context && (strcmp(context, newcon) == 0))) {
>> +  freecon(context);
>> +  goto out;
>> + }
>> +
>> + if (!r_opts->force && context && (is_context_customizable(context) > 0)) {
>> +  if (r_opts->verbose > 1) {
>> +   fprintf(stderr,
>> +    "%s: %s not reset customized by admin to %s\n",
>> +    r_opts->progname, my_file, context);
>> +  }
>> +  freecon(context);
>> +  goto out;
>> + }
>> +
>> + if (r_opts->verbose) {
>> +  /* If we're just doing "-v", trim out any relabels where
>> +   * the user has r_opts->changed but the role and type are the
>> +   * same.  For "-vv", emit everything. */
>> +  if (r_opts->verbose > 1 || !user_only_changed) {
>> +   printf("%s reset %s context %s->%s\n",
>> +          r_opts->progname, my_file, context ?: "", newcon);
>> +  }
>> + }
>> +
>> + if (r_opts->logging && !user_only_changed) {
>> +  if (context)
>> +   syslog(LOG_INFO, "relabeling %s from %s to %s\n",
>> +          my_file, context, newcon);
>> +  else
>> +   syslog(LOG_INFO, "labeling %s to %s\n",
>> +          my_file, newcon);
>> + }
>> +
>> + if (r_opts->outfile && !user_only_changed)
>> +  fprintf(r_opts->outfile, "%s\n", my_file);
>> +
>> + if (context)
>> +  freecon(context);
>> +
>> + /*
>> +  * Do not relabel the file if -n was used.
>> +  */
>> + if (!r_opts->change || user_only_changed)
>> +  goto out;
>> +
>> + /*
>> +  * Relabel the file to the specified context.
>> +  */
>> + ret = lsetfilecon(ftsent->fts_accpath, newcon);
>> + if (ret) {
>> +  fprintf(stderr, "%s set context %s->%s failed:'%s'\n",
>> +   r_opts->progname, my_file, newcon, strerror(errno));
>> +  goto skip;
>> + }
>> + ret = 1;
>> +out:
>> + freecon(newcon);
>> + return ret;
>> +skip:
>> + freecon(newcon);
>> + return SKIP;
>> +err:
>> + freecon(newcon);
>> + return ERR;
>> +}
>> +/*
>> + * Apply the last matching specification to a file.
>> + * This function is called by fts on each file during
>> + * the directory traversal.
>> + */
>> +static int apply_spec(FTSENT *ftsent)
>> +{
>> + if (ftsent->fts_info == FTS_DNR) {
>> +  fprintf(stderr, "%s:  unable to read directory %s\n",
>> +   r_opts->progname, ftsent->fts_path);
>> +  return SKIP;
>> + }
>> + 
>> + int rc = restore(ftsent);
>> + if (rc == ERR) {
>> +  if (!r_opts->abort_on_error)
>> +   return SKIP;
>> + }
>> + return rc;
>> +}
>> +
>> +static int symlink_realpath(char *name, char *path)
>> +{
>> + char *p = NULL, *file_sep;
>> + char *tmp_path = strdupa(name);
>> + size_t len = 0;
>> +
>> + if (!tmp_path) {
>> +  fprintf(stderr, "strdupa on %s failed:  %s\n", name,
>> +   strerror(errno));
>> +  return -1;
>> + }
>> + file_sep = strrchr(tmp_path, '/');
>> + if (file_sep == tmp_path) {
>> +  file_sep++;
>> +  p = strcpy(path, "");
>> + } else if (file_sep) {
>> +  *file_sep = 0;
>> +  file_sep++;
>> +  p = realpath(tmp_path, path);
>> + } else {
>> +  file_sep = tmp_path;
>> +  p = realpath("./", path);
>> + }
>> + if (p)
>> +  len = strlen(p);
>> + if (!p || len + strlen(file_sep) + 2 > PATH_MAX) {
>> +  fprintf(stderr, "symlink_realpath(%s) failed %s\n", name,
>> +   strerror(errno));
>> +  return -1;
>> + }
>> + p += len;
>> + /* ensure trailing slash of directory name */
>> + if (len == 0 || *(p - 1) != '/') {
>> +  *p = '/';
>> +  p++;
>> + }
>> + strcpy(p, file_sep);
>> + return 0;
>> +}
>> +
>> +static int process_one(char *name, int recurse_this_path)
>> +{
>> + int rc = 0;
>> + const char *namelist[2] = {name, NULL};
>> + dev_t dev_num = 0;
>> + FTS *fts_handle;
>> + FTSENT *ftsent;
>> +
>> + fts_handle = fts_open((char **)namelist, r_opts->fts_flags, NULL);
>> + if (fts_handle  == NULL) {
>> +  fprintf(stderr,
>> +   "%s: error while labeling %s:  %s\n",
>> +   r_opts->progname, namelist[0], strerror(errno));
>> +  goto err;
>> + }
>> +
>> +
>> + ftsent = fts_read(fts_handle);
>> + if (ftsent != NULL) {
>> +  /* Keep the inode of the first one. */
>> +  dev_num = ftsent->fts_statp->st_dev;
>> + }
>> +
>> + do {
>> +  rc = 0;
>> +  /* Skip the post order nodes. */
>> +  if (ftsent->fts_info == FTS_DP)
>> +   continue;
>> +  /* If the XDEV flag is set and the device is different */
>> +  if (ftsent->fts_statp->st_dev != dev_num &&
>> +      FTS_XDEV == (r_opts->fts_flags & FTS_XDEV))
>> +   continue;
>> +  if (excludeCtr > 0) {
>> +   if (exclude(ftsent->fts_path)) {
>> +    fts_set(fts_handle, ftsent, FTS_SKIP);
>> +    continue;
>> +   }
>> +  }
>> +  rc = apply_spec(ftsent);
>> +  if (rc == SKIP)
>> +   fts_set(fts_handle, ftsent, FTS_SKIP);
>> +  if (rc == ERR)
>> +   goto err;
>> +  if (!recurse_this_path)
>> +   break;
>> + } while ((ftsent = fts_read(fts_handle)) != NULL);
>> +
>> +out:
>> + if (r_opts->add_assoc) {
>> +  if (!r_opts->quiet)
>> +   filespec_eval();
>> +  filespec_destroy();
>> + }
>> + if (fts_handle)
>> +  fts_close(fts_handle);
>> + return rc;
>> +
>> +err:
>> + rc = -1;
>> + goto out;
>> +}
>> +
>> +int process_one_realpath(char *name, int recurse)
>> +{
>> + int rc = 0;
>> + char *p;
>> + struct stat sb;
>> +
>> + if (r_opts == NULL){
>> +  fprintf(stderr,
>> +   "Must call initialize first!");
>> +  return -1;
>> + }
>> +
>> + if (!r_opts->expand_realpath) {
>> +  return process_one(name, recurse);
>> + } else {
>> +  rc = lstat(name, &sb);
>> +  if (rc < 0) {
>> +   fprintf(stderr, "%s:  lstat(%s) failed:  %s\n",
>> +    r_opts->progname, name, strerror(errno));
>> +   return -1;
>> +  }
>> +
>> +  if (S_ISLNK(sb.st_mode)) {
>> +   char path[PATH_MAX + 1];
>> +
>> +   rc = symlink_realpath(name, path);
>> +   if (rc < 0)
>> +    return rc;
>> +   rc = process_one(path, 0);
>> +   if (rc < 0)
>> +    return rc;
>> +
>> +   p = realpath(name, NULL);
>> +   if (p) {
>> +    rc = process_one(p, recurse);
>> +    free(p);
>> +   }
>> +   return rc;
>> +  } else {
>> +   p = realpath(name, NULL);
>> +   if (!p) {
>> +    fprintf(stderr, "realpath(%s) failed %s\n", name,
>> +     strerror(errno));
>> +    return -1;
>> +   }
>> +   rc = process_one(p, recurse);
>> +   free(p);
>> +   return rc;
>> +  }
>> + }
>> +}
>> +
>> +static int exclude(const char *file)
>> +{
>> + int i = 0;
>> + for (i = 0; i < excludeCtr; i++) {
>> +  if (strncmp
>> +      (file, excludeArray[i].directory,
>> +       excludeArray[i].size) == 0) {
>> +   if (file[excludeArray[i].size] == 0
>> +       || file[excludeArray[i].size] == '/') {
>> +    return 1;
>> +   }
>> +  }
>> + }
>> + return 0;
>> +}
>> +
>> +int add_exclude(const char *directory)
>> +{
>> + size_t len = 0;
>> +
>> + if (directory == NULL || directory[0] != '/') {
>> +  fprintf(stderr, "Full path required for exclude: %s.\n",
>> +   directory);
>> +  return 1;
>> + }
>> + if (excludeCtr == MAX_EXCLUDES) {
>> +  fprintf(stderr, "Maximum excludes %d exceeded.\n",
>> +   MAX_EXCLUDES);
>> +  return 1;
>> + }
>> +
>> + len = strlen(directory);
>> + while (len > 1 && directory[len - 1] == '/') {
>> +  len--;
>> + }
>> + excludeArray[excludeCtr].directory = strndup(directory, len);
>> +
>> + if (excludeArray[excludeCtr].directory == NULL) {
>> +  fprintf(stderr, "Out of memory.\n");
>> +  return 1;
>> + }
>> + excludeArray[excludeCtr++].size = len;
>> +
>> + return 0;
>> +}
>> +
>> +/* Compare two contexts to see if their differences are "significant",
>> + * or whether the only difference is in the user. */
>> +static int only_changed_user(const char *a, const char *b)
>> +{
>> + char *rest_a, *rest_b; /* Rest of the context after the user */
>> + if (r_opts->force)
>> +  return 0;
>> + if (!a || !b)
>> +  return 0;
>> + rest_a = strchr(a, ':');
>> + rest_b = strchr(b, ':');
>> + if (!rest_a || !rest_b)
>> +  return 0;
>> + return (strcmp(rest_a, rest_b) == 0);
>> +}
>> +
>> +/*
>> + * Evaluate the association hash table distribution.
>> + */
>> +static void filespec_eval(void)
>> +{
>> + file_spec_t *fl;
>> + int h, used, nel, len, longest;
>> +
>> + if (!fl_head)
>> +  return;
>> +
>> + used = 0;
>> + longest = 0;
>> + nel = 0;
>> + for (h = 0; h < HASH_BUCKETS; h++) {
>> +  len = 0;
>> +  for (fl = fl_head[h].next; fl; fl = fl->next) {
>> +   len++;
>> +  }
>> +  if (len)
>> +   used++;
>> +  if (len > longest)
>> +   longest = len;
>> +  nel += len;
>> + }
>> +
>> + if (r_opts->verbose > 1)
>> +  printf
>> +      ("%s:  hash table stats: %d elements, %d/%d buckets used, longest
>> chain length %d\n",
>> +       __FUNCTION__, nel, used, HASH_BUCKETS, longest);
>> +}
>> +
>> +/*
>> + * Destroy the association hash table.
>> + */
>> +static void filespec_destroy(void)
>> +{
>> + file_spec_t *fl, *tmp;
>> + int h;
>> +
>> + if (!fl_head)
>> +  return;
>> +
>> + for (h = 0; h < HASH_BUCKETS; h++) {
>> +  fl = fl_head[h].next;
>> +  while (fl) {
>> +   tmp = fl;
>> +   fl = fl->next;
>> +   freecon(tmp->con);
>> +   free(tmp->file);
>> +   free(tmp);
>> +  }
>> +  fl_head[h].next = NULL;
>> + }
>> + free(fl_head);
>> + fl_head = NULL;
>> +}
>> +/*
>> + * Try to add an association between an inode and a context.
>> + * If there is a different context that matched the inode,
>> + * then use the first context that matched.
>> + */
>> +static int filespec_add(ino_t ino, const security_context_t con, const char
>> *file)
>> +{
>> + file_spec_t *prevfl, *fl;
>> + int h, ret;
>> + struct stat sb;
>> +
>> + if (!fl_head) {
>> +  fl_head = malloc(sizeof(file_spec_t) * HASH_BUCKETS);
>> +  if (!fl_head)
>> +   goto oom;
>> +  memset(fl_head, 0, sizeof(file_spec_t) * HASH_BUCKETS);
>> + }
>> +
>> + h = (ino + (ino >> HASH_BITS)) & HASH_MASK;
>> + for (prevfl = &fl_head[h], fl = fl_head[h].next; fl;
>> +      prevfl = fl, fl = fl->next) {
>> +  if (ino == fl->ino) {
>> +   ret = lstat(fl->file, &sb);
>> +   if (ret < 0 || sb.st_ino != ino) {
>> +    freecon(fl->con);
>> +    free(fl->file);
>> +    fl->file = strdup(file);
>> +    if (!fl->file)
>> +     goto oom;
>> +    fl->con = strdup(con);
>> +    if (!fl->con)
>> +     goto oom;
>> +    return 1;
>> +   }
>> +
>> +   if (strcmp(fl->con, con) == 0)
>> +    return 1;
>> +
>> +   fprintf(stderr,
>> +    "%s:  conflicting specifications for %s and %s, using %s.\n",
>> +    __FUNCTION__, file, fl->file, fl->con);
>> +   free(fl->file);
>> +   fl->file = strdup(file);
>> +   if (!fl->file)
>> +    goto oom;
>> +   return 1;
>> +  }
>> +
>> +  if (ino > fl->ino)
>> +   break;
>> + }
>> +
>> + fl = malloc(sizeof(file_spec_t));
>> + if (!fl)
>> +  goto oom;
>> + fl->ino = ino;
>> + fl->con = strdup(con);
>> + if (!fl->con)
>> +  goto oom_freefl;
>> + fl->file = strdup(file);
>> + if (!fl->file)
>> +  goto oom_freefl;
>> + fl->next = prevfl->next;
>> + prevfl->next = fl;
>> + return 0;
>> +      oom_freefl:
>> + free(fl);
>> +      oom:
>> + fprintf(stderr,
>> +  "%s:  insufficient memory for file label entry for %s\n",
>> +  __FUNCTION__, file);
>> + return -1;
>> +}
>> +
>> +
>> +
>> diff --git a/policycoreutils/setfiles/restore.h
>> b/policycoreutils/setfiles/restore.h
>> new file mode 100644
>> index 0000000..03b82e8
>> --- /dev/null
>> +++ b/policycoreutils/setfiles/restore.h
>>  <at>  <at>  -0,0 +1,50  <at>  <at> 
>> +#ifndef RESTORE_H
>> +#define RESTORE_H
>> +#ifndef _GNU_SOURCE
>> +#define _GNU_SOURCE
>> +#endif
>> +#include <fts.h>
>> +#include <errno.h>
>> +#include <string.h>
>> +#include <stdio.h>
>> +#include <syslog.h>
>> +#include <sys/stat.h>
>> +#include <sepol/sepol.h>
>> +#include <selinux/selinux.h>
>> +#include <selinux/label.h>
>> +#include <stdlib.h>
>> +#include <limits.h>
>> +
>> +#define STAR_COUNT 1000
>> +
>> +/* Things that need to be init'd */
>> +struct restore_opts {
>> + int add_assoc; /* Track inode associations for conflict detection. */
>> + int progress;
>> + unsigned long long count;
>> + int debug;
>> + int change;
>> + int hard_links;
>> + int verbose;
>> + int logging;
>> + char *rootpath;
>> + int rootpathlen;
>> + char *progname;
>> + FILE *outfile;
>> + int force;
>> + struct selabel_handle *hnd;
>> + int expand_realpath;  /* Expand paths via realpath. */
>> + int abort_on_error; /* Abort the file tree walk upon an error. */
>> + int quiet;
>> + int fts_flags; /* Flags to fts, e.g. follow links, follow mounts */
>> + const char *selabel_opt_validate;
>> + const char *selabel_opt_path;
>> +};
>> +
>> +void restore_init(struct restore_opts *opts);
>> +void restore_finish();
>> +int add_exclude(const char *directory);
>> +void remove_exclude(const char *directory);
>> +int process_one_realpath(char *name, int recurse);
>> +
>> +#endif
>> diff --git a/policycoreutils/setfiles/setfiles.c
>> b/policycoreutils/setfiles/setfiles.c
>> index db2857f..8f4f663 100644
>> --- a/policycoreutils/setfiles/setfiles.c
>> +++ b/policycoreutils/setfiles/setfiles.c
>>  <at>  <at>  -1,26 +1,12  <at>  <at> 
>> -#ifndef _GNU_SOURCE
>> -#define _GNU_SOURCE
>> -#endif
>> +#include "restore.h"
>>  #include <unistd.h>
>> -#include <stdlib.h>
>>  #include <fcntl.h>
>> -#include <stdio.h>
>>  #include <stdio_ext.h>
>> -#include <string.h>
>> -#include <errno.h>
>>  #include <ctype.h>
>>  #include <regex.h>
>>  #include <sys/vfs.h>
>>  #include <sys/utsname.h>
>>  #define __USE_XOPEN_EXTENDED 1 /* nftw */
>> -#define SKIP -2
>> -#define ERR -1
>> -#include <fts.h>
>> -#include <limits.h>
>> -#include <sepol/sepol.h>
>> -#include <selinux/selinux.h>
>> -#include <selinux/label.h>
>> -#include <syslog.h>
>>  #include <libgen.h>
>>  #ifdef USE_AUDIT
>>  #include <libaudit.h>
>>  <at>  <at>  -32,287 +18,28  <at>  <at> 
>>  static int mass_relabel;
>>  static int mass_relabel_errs;
>>  
>> -#define STAR_COUNT 1000
>> -
>> -static FILE *outfile = NULL;
>> -static int force = 0;
>> -#define STAT_BLOCK_SIZE 1
>> -static int progress = 0;
>> -static unsigned long long count = 0;
>>  
>> -#define MAX_EXCLUDES 1000
>> -static int excludeCtr = 0;
>> -struct edir {
>> - char *directory;
>> - size_t size;
>> -};
>> -static struct edir excludeArray[MAX_EXCLUDES];
>> +/* cmdline opts*/
>>  
>> -/*
>> - * Command-line options.
>> - */
>>  static char *policyfile = NULL;
>> -static int debug = 0;
>> -static int change = 1;
>> -static int quiet = 0;
>> -static int ignore_enoent;
>> -static int verbose = 0;
>> -static int logging = 0;
>>  static int warn_no_match = 0;
>>  static int null_terminated = 0;
>> -static char *rootpath = NULL;
>> -static int rootpathlen = 0;
>> -static int recurse; /* Recursive descent. */
>>  static int errors;
>> +static int ignore_enoent;
>> +static struct restore_opts r_opts;
>> +
>> +#define STAT_BLOCK_SIZE 1
>> +
>>  
>> -static char *progname;
>>  
>>  #define SETFILES "setfiles"
>>  #define RESTORECON "restorecon"
>>  static int iamrestorecon;
>>  
>>  /* Behavior flags determined based on setfiles vs. restorecon */
>> -static int expand_realpath;  /* Expand paths via realpath. */
>> -static int abort_on_error; /* Abort the file tree walk upon an error. */
>> -static int add_assoc; /* Track inode associations for conflict detection. */
>> -static int fts_flags; /* Flags to fts, e.g. follow links, follow mounts */
>>  static int ctx_validate; /* Validate contexts */
>>  static const char *altpath; /* Alternate path to file_contexts */
>>  
>> -/* Label interface handle */
>> -static struct selabel_handle *hnd;
>> -
>> -/*
>> - * An association between an inode and a context.
>> - */
>> -typedef struct file_spec {
>> - ino_t ino;  /* inode number */
>> - char *con;  /* matched context */
>> - char *file;  /* full pathname */
>> - struct file_spec *next; /* next association in hash bucket chain */
>> -} file_spec_t;
>> -
>> -/*
>> - * The hash table of associations, hashed by inode number.
>> - * Chaining is used for collisions, with elements ordered
>> - * by inode number in each bucket.  Each hash bucket has a dummy
>> - * header.
>> - */
>> -#define HASH_BITS 16
>> -#define HASH_BUCKETS (1 << HASH_BITS)
>> -#define HASH_MASK (HASH_BUCKETS-1)
>> -static file_spec_t *fl_head;
>> -
>> -/*
>> - * Try to add an association between an inode and a context.
>> - * If there is a different context that matched the inode,
>> - * then use the first context that matched.
>> - */
>> -int filespec_add(ino_t ino, const security_context_t con, const char *file)
>> -{
>> - file_spec_t *prevfl, *fl;
>> - int h, ret;
>> - struct stat sb;
>> -
>> - if (!fl_head) {
>> -  fl_head = malloc(sizeof(file_spec_t) * HASH_BUCKETS);
>> -  if (!fl_head)
>> -   goto oom;
>> -  memset(fl_head, 0, sizeof(file_spec_t) * HASH_BUCKETS);
>> - }
>> -
>> - h = (ino + (ino >> HASH_BITS)) & HASH_MASK;
>> - for (prevfl = &fl_head[h], fl = fl_head[h].next; fl;
>> -      prevfl = fl, fl = fl->next) {
>> -  if (ino == fl->ino) {
>> -   ret = lstat(fl->file, &sb);
>> -   if (ret < 0 || sb.st_ino != ino) {
>> -    freecon(fl->con);
>> -    free(fl->file);
>> -    fl->file = strdup(file);
>> -    if (!fl->file)
>> -     goto oom;
>> -    fl->con = strdup(con);
>> -    if (!fl->con)
>> -     goto oom;
>> -    return 1;
>> -   }
>> -
>> -   if (strcmp(fl->con, con) == 0)
>> -    return 1;
>> -
>> -   fprintf(stderr,
>> -    "%s:  conflicting specifications for %s and %s, using %s.\n",
>> -    __FUNCTION__, file, fl->file, fl->con);
>> -   free(fl->file);
>> -   fl->file = strdup(file);
>> -   if (!fl->file)
>> -    goto oom;
>> -   return 1;
>> -  }
>> -
>> -  if (ino > fl->ino)
>> -   break;
>> - }
>> -
>> - fl = malloc(sizeof(file_spec_t));
>> - if (!fl)
>> -  goto oom;
>> - fl->ino = ino;
>> - fl->con = strdup(con);
>> - if (!fl->con)
>> -  goto oom_freefl;
>> - fl->file = strdup(file);
>> - if (!fl->file)
>> -  goto oom_freefl;
>> - fl->next = prevfl->next;
>> - prevfl->next = fl;
>> - return 0;
>> -      oom_freefl:
>> - free(fl);
>> -      oom:
>> - fprintf(stderr,
>> -  "%s:  insufficient memory for file label entry for %s\n",
>> -  __FUNCTION__, file);
>> - return -1;
>> -}
>> -
>> -/*
>> - * Evaluate the association hash table distribution.
>> - */
>> -void filespec_eval(void)
>> -{
>> - file_spec_t *fl;
>> - int h, used, nel, len, longest;
>> -
>> - if (!fl_head)
>> -  return;
>> -
>> - used = 0;
>> - longest = 0;
>> - nel = 0;
>> - for (h = 0; h < HASH_BUCKETS; h++) {
>> -  len = 0;
>> -  for (fl = fl_head[h].next; fl; fl = fl->next) {
>> -   len++;
>> -  }
>> -  if (len)
>> -   used++;
>> -  if (len > longest)
>> -   longest = len;
>> -  nel += len;
>> - }
>> -
>> - printf
>> -     ("%s:  hash table stats: %d elements, %d/%d buckets used, longest chain
>> length %d\n",
>> -      __FUNCTION__, nel, used, HASH_BUCKETS, longest);
>> -}
>> -
>> -/*
>> - * Destroy the association hash table.
>> - */
>> -void filespec_destroy(void)
>> -{
>> - file_spec_t *fl, *tmp;
>> - int h;
>> -
>> - if (!fl_head)
>> -  return;
>> -
>> - for (h = 0; h < HASH_BUCKETS; h++) {
>> -  fl = fl_head[h].next;
>> -  while (fl) {
>> -   tmp = fl;
>> -   fl = fl->next;
>> -   freecon(tmp->con);
>> -   free(tmp->file);
>> -   free(tmp);
>> -  }
>> -  fl_head[h].next = NULL;
>> - }
>> - free(fl_head);
>> - fl_head = NULL;
>> -}
>> -
>> -static int add_exclude(const char *directory)
>> -{
>> - size_t len = 0;
>> -
>> - if (directory == NULL || directory[0] != '/') {
>> -  fprintf(stderr, "Full path required for exclude: %s.\n",
>> -   directory);
>> -  return 1;
>> - }
>> - if (excludeCtr == MAX_EXCLUDES) {
>> -  fprintf(stderr, "Maximum excludes %d exceeded.\n",
>> -   MAX_EXCLUDES);
>> -  return 1;
>> - }
>> -
>> - len = strlen(directory);
>> - while (len > 1 && directory[len - 1] == '/') {
>> -  len--;
>> - }
>> - excludeArray[excludeCtr].directory = strndup(directory, len);
>> -
>> - if (excludeArray[excludeCtr].directory == NULL) {
>> -  fprintf(stderr, "Out of memory.\n");
>> -  return 1;
>> - }
>> - excludeArray[excludeCtr++].size = len;
>> -
>> - return 0;
>> -}
>> -
>> -static void remove_exclude(const char *directory)
>> -{
>> - int i = 0;
>> - for (i = 0; i < excludeCtr; i++) {
>> -  if (strcmp(directory, excludeArray[i].directory) == 0) {
>> -   free(excludeArray[i].directory);
>> -   if (i != excludeCtr-1)
>> -    excludeArray[i] = excludeArray[excludeCtr-1];
>> -   excludeCtr--;
>> -   return;
>> -  }
>> - }
>> - return;
>> -}
>> -
>> -static int exclude(const char *file)
>> -{
>> - int i = 0;
>> - for (i = 0; i < excludeCtr; i++) {
>> -  if (strncmp
>> -      (file, excludeArray[i].directory,
>> -       excludeArray[i].size) == 0) {
>> -   if (file[excludeArray[i].size] == 0
>> -       || file[excludeArray[i].size] == '/') {
>> -    return 1;
>> -   }
>> -  }
>> - }
>> - return 0;
>> -}
>> -
>> -int match(const char *name, struct stat *sb, char **con)
>> -{
>> - if (NULL != rootpath) {
>> -  if (0 != strncmp(rootpath, name, rootpathlen)) {
>> -   fprintf(stderr, "%s:  %s is not located in %s\n",
>> -    progname, name, rootpath);
>> -   return -1;
>> -  }
>> -  name += rootpathlen;
>> - }
>> -
>> - if (rootpath != NULL && name[0] == '\0')
>> -  /* this is actually the root dir of the alt root */
>> -  return selabel_lookup_raw(hnd, con, "/", sb->st_mode);
>> - else
>> -  return selabel_lookup_raw(hnd, con, name, sb->st_mode);
>> -}
>> -
>>  void usage(const char *const name)
>>  {
>> if (iamrestorecon) {
>>  <at>  <at>  -334,194 +61,30  <at>  <at>  static int nerr = 0;
>>  void inc_err()
>>  {
>> nerr++;
>> - if (nerr > 9 && !debug) {
>> + if (nerr > 9 && !r_opts.debug) {
>> fprintf(stderr, "Exiting after 10 errors.\n");
>> exit(1);
>> }
>>  }
>>  
>> -/* Compare two contexts to see if their differences are "significant",
>> - * or whether the only difference is in the user. */
>> -static int only_changed_user(const char *a, const char *b)
>> -{
>> - char *rest_a, *rest_b; /* Rest of the context after the user */
>> - if (force)
>> -  return 0;
>> - if (!a || !b)
>> -  return 0;
>> - rest_a = strchr(a, ':');
>> - rest_b = strchr(b, ':');
>> - if (!rest_a || !rest_b)
>> -  return 0;
>> - return (strcmp(rest_a, rest_b) == 0);
>> -}
>> -
>> -static int restore(FTSENT *ftsent)
>> -{
>> - char *my_file = strdupa(ftsent->fts_path);
>> - int ret;
>> - char *context, *newcon;
>> - int user_only_changed = 0;
>> -
>> - if (match(my_file, ftsent->fts_statp, &newcon) < 0)
>> -  /* Check for no matching specification. */
>> -  return (errno == ENOENT) ? 0 : -1;
>> -
>> - if (progress) {
>> -  count++;
>> -  if (count % (80 * STAR_COUNT) == 0) {
>> -   fprintf(stdout, "\n");
>> -   fflush(stdout);
>> -  }
>> -  if (count % STAR_COUNT == 0) {
>> -   fprintf(stdout, "*");
>> -   fflush(stdout);
>> -  }
>> - }
>> -
>> - /*
>> -  * Try to add an association between this inode and
>> -  * this specification.  If there is already an association
>> -  * for this inode and it conflicts with this specification,
>> -  * then use the last matching specification.
>> -  */
>> - if (add_assoc) {
>> -  ret = filespec_add(ftsent->fts_statp->st_ino, newcon, my_file);
>> -  if (ret < 0)
>> -   goto err;
>> -
>> -  if (ret > 0)
>> -   /* There was already an association and it took precedence. */
>> -   goto out;
>> - }
>> -
>> - if (debug) {
>> -  printf("%s:  %s matched by %s\n", progname, my_file, newcon);
>> - }
>> -
>> - /* Get the current context of the file. */
>> - ret = lgetfilecon_raw(ftsent->fts_accpath, &context);
>> - if (ret < 0) {
>> -  if (errno == ENODATA) {
>> -   context = NULL;
>> -  } else {
>> -   fprintf(stderr, "%s get context on %s failed: '%s'\n",
>> -    progname, my_file, strerror(errno));
>> -   goto err;
>> -  }
>> -  user_only_changed = 0;
>> - } else
>> -  user_only_changed = only_changed_user(context, newcon);
>> -
>> - /*
>> -  * Do not relabel the file if the matching specification is
>> -  * <<none>> or the file is already labeled according to the
>> -  * specification.
>> -  */
>> - if ((strcmp(newcon, "<<none>>") == 0) ||
>> -     (context && (strcmp(context, newcon) == 0))) {
>> -  freecon(context);
>> -  goto out;
>> - }
>> -
>> - if (!force && context && (is_context_customizable(context) > 0)) {
>> -  if (verbose > 1) {
>> -   fprintf(stderr,
>> -    "%s: %s not reset customized by admin to %s\n",
>> -    progname, my_file, context);
>> -  }
>> -  freecon(context);
>> -  goto out;
>> - }
>> -
>> - if (verbose) {
>> -  /* If we're just doing "-v", trim out any relabels where
>> -   * the user has changed but the role and type are the
>> -   * same.  For "-vv", emit everything. */
>> -  if (verbose > 1 || !user_only_changed) {
>> -   printf("%s reset %s context %s->%s\n",
>> -          progname, my_file, context ?: "", newcon);
>> -  }
>> - }
>> -
>> - if (logging && !user_only_changed) {
>> -  if (context)
>> -   syslog(LOG_INFO, "relabeling %s from %s to %s\n",
>> -          my_file, context, newcon);
>> -  else
>> -   syslog(LOG_INFO, "labeling %s to %s\n",
>> -          my_file, newcon);
>> - }
>> -
>> - if (outfile && !user_only_changed)
>> -  fprintf(outfile, "%s\n", my_file);
>> -
>> - if (context)
>> -  freecon(context);
>> -
>> - /*
>> -  * Do not relabel the file if -n was used.
>> -  */
>> - if (!change || user_only_changed)
>> -  goto out;
>> -
>> - /*
>> -  * Relabel the file to the specified context.
>> -  */
>> - ret = lsetfilecon(ftsent->fts_accpath, newcon);
>> - if (ret) {
>> -  fprintf(stderr, "%s set context %s->%s failed:'%s'\n",
>> -   progname, my_file, newcon, strerror(errno));
>> -  goto skip;
>> - }
>> -out:
>> - freecon(newcon);
>> - return 0;
>> -skip:
>> - freecon(newcon);
>> - return SKIP;
>> -err:
>> - freecon(newcon);
>> - return ERR;
>> -}
>> -
>> -/*
>> - * Apply the last matching specification to a file.
>> - * This function is called by fts on each file during
>> - * the directory traversal.
>> - */
>> -static int apply_spec(FTSENT *ftsent)
>> -{
>> - if (ftsent->fts_info == FTS_DNR) {
>> -  fprintf(stderr, "%s:  unable to read directory %s\n",
>> -   progname, ftsent->fts_path);
>> -  return SKIP;
>> - }
>>  
>> - int rc = restore(ftsent);
>> - if (rc == ERR) {
>> -  if (!abort_on_error)
>> -   return SKIP;
>> - }
>> - return rc;
>> -}
>>  
>>  void set_rootpath(const char *arg)
>>  {
>> int len;
>>  
>> - rootpath = strdup(arg);
>> - if (NULL == rootpath) {
>> -  fprintf(stderr, "%s:  insufficient memory for rootpath\n",
>> -   progname);
>> + r_opts.rootpath = strdup(arg);
>> + if (NULL == r_opts.rootpath) {
>> +  fprintf(stderr, "%s:  insufficient memory for r_opts.rootpath\n",
>> +   r_opts.progname);
>> exit(1);
>> }
>>  
>> /* trim trailing /, if present */
>> - len = strlen(rootpath);
>> - while (len && ('/' == rootpath[len - 1]))
>> -  rootpath[--len] = 0;
>> - rootpathlen = len;
>> + len = strlen(r_opts.rootpath);
>> + while (len && ('/' == r_opts.rootpath[len - 1]))
>> +  r_opts.rootpath[--len] = 0;
>> + r_opts.rootpathlen = len;
>>  }
>>  
>>  int canoncon(char **contextp)
>>  <at>  <at>  -545,163 +108,6  <at>  <at>  int canoncon(char **contextp)
>> return rc;
>>  }
>>  
>> -static int symlink_realpath(char *name, char *path)
>> -{
>> - char *p = NULL, *file_sep;
>> - char *tmp_path = strdupa(name);
>> - size_t len = 0;
>> -
>> - if (!tmp_path) {
>> -  fprintf(stderr, "strdupa on %s failed:  %s\n", name,
>> -   strerror(errno));
>> -  return -1;
>> - }
>> - file_sep = strrchr(tmp_path, '/');
>> - if (file_sep == tmp_path) {
>> -  file_sep++;
>> -  p = strcpy(path, "");
>> - } else if (file_sep) {
>> -  *file_sep = 0;
>> -  file_sep++;
>> -  p = realpath(tmp_path, path);
>> - } else {
>> -  file_sep = tmp_path;
>> -  p = realpath("./", path);
>> - }
>> - if (p)
>> -  len = strlen(p);
>> - if (!p || len + strlen(file_sep) + 2 > PATH_MAX) {
>> -  fprintf(stderr, "symlink_realpath(%s) failed %s\n", name,
>> -   strerror(errno));
>> -  return -1;
>> - }
>> - p += len;
>> - /* ensure trailing slash of directory name */
>> - if (len == 0 || *(p - 1) != '/') {
>> -  *p = '/';
>> -  p++;
>> - }
>> - strcpy(p, file_sep);
>> - return 0;
>> -}
>> -
>> -static int process_one(char *name, int recurse_this_path)
>> -{
>> - int rc = 0;
>> - const char *namelist[2];
>> - dev_t dev_num = 0;
>> - FTS *fts_handle;
>> - FTSENT *ftsent;
>> -
>> - if (!strcmp(name, "/"))
>> -  mass_relabel = 1;
>> -
>> - namelist[0] = name;
>> - namelist[1] = NULL;
>> - fts_handle = fts_open((char **)namelist, fts_flags, NULL);
>> - if (fts_handle  == NULL) {
>> -  fprintf(stderr,
>> -   "%s: error while labeling %s:  %s\n",
>> -   progname, namelist[0], strerror(errno));
>> -  goto err;
>> - }
>> -
>> -
>> - ftsent = fts_read(fts_handle);
>> - if (ftsent != NULL) {
>> -  /* Keep the inode of the first one. */
>> -  dev_num = ftsent->fts_statp->st_dev;
>> - }
>> -
>> - do {
>> -  /* Skip the post order nodes. */
>> -  if (ftsent->fts_info == FTS_DP)
>> -   continue;
>> -  /* If the XDEV flag is set and the device is different */
>> -  if (ftsent->fts_statp->st_dev != dev_num &&
>> -      FTS_XDEV == (fts_flags & FTS_XDEV))
>> -   continue;
>> -  if (excludeCtr > 0) {
>> -   if (exclude(ftsent->fts_path)) {
>> -    fts_set(fts_handle, ftsent, FTS_SKIP);
>> -    continue;
>> -   }
>> -  }
>> -  int rc = apply_spec(ftsent);
>> -  if (rc == SKIP)
>> -   fts_set(fts_handle, ftsent, FTS_SKIP);
>> -  if (rc == ERR)
>> -   goto err;
>> -  if (!recurse_this_path)
>> -   break;
>> - } while ((ftsent = fts_read(fts_handle)) != NULL);
>> -
>> - if (!strcmp(name, "/"))
>> -  mass_relabel_errs = 0;
>> -
>> -out:
>> - if (add_assoc) {
>> -  if (!quiet)
>> -   filespec_eval();
>> -  filespec_destroy();
>> - }
>> - if (fts_handle)
>> -  fts_close(fts_handle);
>> - return rc;
>> -
>> -err:
>> - if (!strcmp(name, "/"))
>> -  mass_relabel_errs = 1;
>> - rc = -1;
>> - goto out;
>> -}
>> -
>> -static int process_one_realpath(char *name)
>> -{
>> - int rc = 0;
>> - char *p;
>> - struct stat sb;
>> -
>> - if (!expand_realpath) {
>> -  return process_one(name, recurse);
>> - } else {
>> -  rc = lstat(name, &sb);
>> -  if (rc < 0) {
>> -   fprintf(stderr, "%s:  lstat(%s) failed:  %s\n",
>> -    progname, name, strerror(errno));
>> -   return -1;
>> -  }
>> -
>> -  if (S_ISLNK(sb.st_mode)) {
>> -   char path[PATH_MAX + 1];
>> -
>> -   rc = symlink_realpath(name, path);
>> -   if (rc < 0)
>> -    return rc;
>> -   rc = process_one(path, 0);
>> -   if (rc < 0)
>> -    return rc;
>> -
>> -   p = realpath(name, NULL);
>> -   if (p) {
>> -    rc = process_one(p, recurse);
>> -    free(p);
>> -   }
>> -   return rc;
>> -  } else {
>> -   p = realpath(name, NULL);
>> -   if (!p) {
>> -    fprintf(stderr, "realpath(%s) failed %s\n", name,
>> -     strerror(errno));
>> -    return -1;
>> -   }
>> -   rc = process_one(p, recurse);
>> -   free(p);
>> -   return rc;
>> -  }
>> - }
>> -}
>> -
>>  #ifndef USE_AUDIT
>>  static void maybe_audit_mass_relabel(void)
>>  {
>>  <at>  <at>  -803,21 +209,32  <at>  <at>  int main(int argc, char **argv)
>> int use_input_file = 0;
>> char *buf = NULL;
>> size_t buf_len;
>> + int recurse; /* Recursive descent. */
>> char *base;
>> - struct selinux_opt opts[] = {
>> -  { SELABEL_OPT_VALIDATE, NULL },
>> -  { SELABEL_OPT_PATH, NULL }
>> - };
>> + 
>> + memset(&r_opts, 0, sizeof(r_opts));
>> +
>> + /* Initialize variables */
>> + r_opts.progress = 0;
>> + r_opts.count = 0;
>> + r_opts.debug = 0;
>> + r_opts.change = 1;
>> + r_opts.verbose = 0;
>> + r_opts.logging = 0;
>> + r_opts.rootpath = NULL;
>> + r_opts.rootpathlen = 0;
>> + r_opts.outfile = NULL;
>> + r_opts.force = 0;
>> + r_opts.hard_links = 1;
>>  
>> - memset(excludeArray, 0, sizeof(excludeArray));
>> altpath = NULL;
>>  
>> - progname = strdup(argv[0]);
>> - if (!progname) {
>> + r_opts.progname = strdup(argv[0]);
>> + if (!r_opts.progname) {
>> fprintf(stderr, "%s:  Out of memory!\n", argv[0]);
>> exit(1);
>> }
>> - base = basename(progname);
>> + base = basename(r_opts.progname);
>> 
>> if (!strcmp(base, SETFILES)) {
>> /* 
>>  <at>  <at>  -831,10 +248,10  <at>  <at>  int main(int argc, char **argv)
>> */
>> iamrestorecon = 0;
>> recurse = 1;
>> -  expand_realpath = 0;
>> -  abort_on_error = 1;
>> -  add_assoc = 1;
>> -  fts_flags = FTS_PHYSICAL | FTS_XDEV;
>> +  r_opts.expand_realpath = 0;
>> +  r_opts.abort_on_error = 1;
>> +  r_opts.add_assoc = 1;
>> +  r_opts.fts_flags = FTS_PHYSICAL | FTS_XDEV;
>> ctx_validate = 1;
>> } else {
>> /*
>>  <at>  <at>  -846,14 +263,14  <at>  <at>  int main(int argc, char **argv)
>> * Follows mounts,
>> * Does lazy validation of contexts upon use. 
>> */
>> -  if (strcmp(base, RESTORECON) && !quiet) 
>> +  if (strcmp(base, RESTORECON) && !r_opts.quiet) 
>> printf("Executed with an unrecognized name (%s), defaulting to %s 
>> behavior.\n", base, RESTORECON);
>> iamrestorecon = 1;
>> recurse = 0;
>> -  expand_realpath = 1;
>> -  abort_on_error = 0;
>> -  add_assoc = 0;
>> -  fts_flags = FTS_PHYSICAL;
>> +  r_opts.expand_realpath = 1;
>> +  r_opts.abort_on_error = 0;
>> +  r_opts.add_assoc = 0;
>> +  r_opts.fts_flags = FTS_PHYSICAL;
>> ctx_validate = 0;
>>  
>> /* restorecon only:  silent exit if no SELinux.
>>  <at>  <at>  -915,37 +332,37  <at>  <at>  int main(int argc, char **argv)
>> input_filename = optarg;
>> break;   
>> case 'd':
>> -   debug = 1;
>> +   r_opts.debug = 1;
>> break;
>> case 'i':
>> ignore_enoent = 1;
>> break;
>> case 'l':
>> -   logging = 1;
>> +   r_opts.logging = 1;
>> break;
>> case 'F':
>> -   force = 1;
>> +   r_opts.force = 1;
>> break;
>> case 'n':
>> -   change = 0;
>> +   r_opts.change = 0;
>> break;
>> case 'o':
>> if (strcmp(optarg, "-") == 0) {
>> -    outfile = stdout;
>> +    r_opts.outfile = stdout;
>> break;
>> }
>>  
>> -   outfile = fopen(optarg, "w");
>> -   if (!outfile) {
>> +   r_opts.outfile = fopen(optarg, "w");
>> +   if (!r_opts.outfile) {
>> fprintf(stderr, "Error opening %s: %s\n",
>> optarg, strerror(errno));
>>  
>> usage(argv[0]);
>> }
>> -   __fsetlocking(outfile, FSETLOCKING_BYCALLER);
>> +   __fsetlocking(r_opts.outfile, FSETLOCKING_BYCALLER);
>> break;
>> case 'q':
>> -   quiet = 1;
>> +   r_opts.quiet = 1;
>> break;
>> case 'R':
>> case 'r':
>>  <at>  <at>  -954,11 +371,11  <at>  <at>  int main(int argc, char **argv)
>> break;
>> }
>> if (optind + 1 >= argc) {
>> -    fprintf(stderr, "usage:  %s -r rootpath\n",
>> +    fprintf(stderr, "usage:  %s -r r_opts.rootpath\n",
>> argv[0]);
>> exit(1);
>> }
>> -   if (NULL != rootpath) {
>> +   if (NULL != r_opts.rootpath) {
>> fprintf(stderr,
>> "%s: only one -r can be specified\n",
>> argv[0]);
>>  <at>  <at>  -969,23 +386,23  <at>  <at>  int main(int argc, char **argv)
>> case 's':
>> use_input_file = 1;
>> input_filename = "-";
>> -   add_assoc = 0;
>> +   r_opts.add_assoc = 0;
>> break;
>> case 'v':
>> -   if (progress) {
>> +   if (r_opts.progress) {
>> fprintf(stderr,
>> "Progress and Verbose mutually exclusive\n");
>> exit(1);
>> }
>> -   verbose++;
>> +   r_opts.verbose++;
>> break;
>> case 'p':
>> -   if (verbose) {
>> +   if (r_opts.verbose) {
>> fprintf(stderr,
>> "Progress and Verbose mutually exclusive\n");
>> usage(argv[0]);
>> }
>> -   progress = 1;
>> +   r_opts.progress = 1;
>> break;
>> case 'W':
>> warn_no_match = 1;
>>  <at>  <at>  -1033,18 +450,13  <at>  <at>  int main(int argc, char **argv)
>> }
>>  
>> /* Load the file contexts configuration and check it. */
>> - opts[0].value = (ctx_validate ? (char*)1 : NULL);
>> - opts[1].value = altpath;
>> -
>> - hnd = selabel_open(SELABEL_CTX_FILE, opts, 2);
>> - if (!hnd) {
>> -  perror(altpath);
>> -  exit(1);
>> - }
>> + r_opts.selabel_opt_validate = (ctx_validate ? (char *)1 : NULL);
>> + r_opts.selabel_opt_path = altpath;
>>  
>> if (nerr)
>> exit(1);
>>  
>> + restore_init(&r_opts);
>> if (use_input_file) {
>> FILE *f = stdin;
>> ssize_t len;
>>  <at>  <at>  -1061,31 +473,34  <at>  <at>  int main(int argc, char **argv)
>> delim = (null_terminated != 0) ? '\0' : '\n';
>> while ((len = getdelim(&buf, &buf_len, delim, f)) > 0) {
>> buf[len - 1] = 0;
>> -   errors |= process_one_realpath(buf);
>> +   if (!strcmp(buf, "/"))
>> +    mass_relabel = 1;
>> +   errors |= process_one_realpath(buf, recurse) < 0;
>> }
>> if (strcmp(input_filename, "-") != 0)
>> fclose(f);
>> } else {
>> for (i = optind; i < argc; i++) {
>> -   errors |= process_one_realpath(argv[i]);
>> +   if (!strcmp(argv[i], "/"))
>> +    mass_relabel = 1;
>> +   errors |= process_one_realpath(argv[i], recurse) < 0;
>> }
>> }
>> -
>> + 
>> + if (mass_relabel)
>> +  mass_relabel_errs = errors;
>> maybe_audit_mass_relabel();
>>  
>> if (warn_no_match)
>> -  selabel_stats(hnd);
>> +  selabel_stats(r_opts.hnd);
>>  
>> - selabel_close(hnd);
>> + selabel_close(r_opts.hnd);
>> + restore_finish();
>>  
>> - if (outfile)
>> -  fclose(outfile);
>> -
>> - for (i = 0; i < excludeCtr; i++) {
>> -  free(excludeArray[i].directory);
>> - }
>> + if (r_opts.outfile)
>> +  fclose(r_opts.outfile);
>>  
>> -       if (progress && count >= STAR_COUNT)
>> +       if (r_opts.progress && r_opts.count >= STAR_COUNT)
>>                 printf("\n");
>> exit(errors);
>>  }
> 

Libby Duke | 3 Nov 2009 00:26
Picon

Save REAL money with OEM soft

 


Please do not reply to this e-mail. To contact us, please Click Here
We hope you enjoy our surveys and we'll see you online!

320 South, 02th Floor
Delaware 858

If you no longer wish to receive offers from MyView, please Click Here
 
Guido Trentalancia | 2 Nov 2009 23:43

selinux_check_passwd_access() behaviour when passwd class does not exist

Hello !

The current behaviour of selinux_check_passwd_access() is to succeed
even if the "passwd" class does not exist (see checkAccess.c:21). Is
this really the intended behaviour ??

It would make more sense if it failed in such case (as in
mapping.c:66)... Or am I wrong ?

Guido Trentalancia

Guido Trentalancia | 3 Nov 2009 00:57

Contributed manual pages for libselinux

Hello !

I found from http://userspace.selinuxproject.org/trac/wiki/Todo that the
following manual pages were missing for libselinux:

* matchpathcon_checkmatches
* matchpathcon_filespec_add
* matchpathcon_filespec_destroy
* matchpathcon_filespec_eval
* matchpathcon_index
* matchpathcon_init_prefix
* print_access_vector
security_canonicalize_context
* security_disable
* security_set_boolean_list
* selinux_check_passwd_access
selinux_customizable_types_path
selinux_get_callback
* selinux_init_load_policy
* selinux_lsetfilecon_default
* selinux_mkload_policy
selinux_raw_to_trans_context
selinux_trans_to_raw_context
selinux_translations_path
selinux_users_path
* set_selinuxmnt

So, I have contributed the ones marked with a "*" in the attached patch.
I might do the rest at a later time, if possible (and if needed).

Guido Trentalancia

diff -pruN libselinux/man/man3/fini_selinuxmnt.3
libselinux-new/man/man3/fini_selinuxmnt.3
--- libselinux/man/man3/fini_selinuxmnt.3	1970-01-01 01:00:00.000000000
+0100
+++ libselinux-new/man/man3/fini_selinuxmnt.3	2009-11-03
00:09:04.000000000 +0100
 <at>  <at>  -0,0 +1  <at>  <at> 
+.so man3/init_selinuxmnt.3
diff -pruN libselinux/man/man3/init_selinuxmnt.3
libselinux-new/man/man3/init_selinuxmnt.3
--- libselinux/man/man3/init_selinuxmnt.3	1970-01-01 01:00:00.000000000
+0100
+++ libselinux-new/man/man3/init_selinuxmnt.3	2009-11-03
00:30:08.000000000 +0100
 <at>  <at>  -0,0 +1,31  <at>  <at> 
+.\" Hey Emacs! This file is -*- nroff -*- source.
+.\"
+.\" Author: Guido Trentalancia (guido@...) 2009
+.TH "init_selinuxmnt" "3" "02 Nov 2009" "" "SELinux API documentation"
+.SH "NAME"
+init_selinuxmnt \- initialize the global variable selinux_mnt.
+
+.SH "SYNOPSIS"
+.BI "static void init_selinuxmnt(void);"
+.sp
+.BI "static void fini_selinuxmnt(void);"
+.sp
+.BI "void set_selinuxmnt(char *" mnt ");"
+
+.SH "DESCRIPTION"
+.B init_selinuxmnt 
+initializes the global variable selinux_mnt to the selinuxfs
mountpoint.
+
+.B fini_selinuxmnt
+deinitializes the global variable selinux_mnt that stores the selinuxfs
+mountpoint.
+
+.B set_selinuxmnt
+changes the selinuxfs mountpoint to
+.I mnt. 
+
+.SH "AUTHOR"
+This manual page has been written by Guido Trentalancia
<guido@...>
+
+.SH "SEE ALSO"
+.BR selinux (8),
diff -pruN libselinux/man/man3/matchpathcon.3
libselinux-new/man/man3/matchpathcon.3
--- libselinux/man/man3/matchpathcon.3	2009-11-01 22:23:01.000000000
+0100
+++ libselinux-new/man/man3/matchpathcon.3	2009-11-03 00:44:53.000000000
+0100
 <at>  <at>  -7,21 +7,35  <at>  <at>  matchpathcon \- get the default SELinux 
 .sp
 .BI "int matchpathcon_init(const char *" path ");"

+.BI "int matchpathcon_init_prefix(const char *" path ", const char *"
subset ");"
+
 .BI "int matchpathcon_fini(void);"

-.BI "int matchpathcon(const char *" path ", mode_t " mode ",
security_context_t *" con);
+.BI "int matchpathcon(const char *" path ", mode_t " mode ",
security_context_t *" con ");
+.sp
+
+.BI "int matchpathcon_index(const char *" name ", mode_t " mode ",
security_context_t * " con ");"
+
+.BI "int matchpathcon_filespec_add(ino_t " ino ", int " specind ",
const char *" file ");"
+
+.BI "void matchpathcon_filespec_destroy(void);"
+
+.BI "void matchpathcon_filespec_eval(void);"
+
+.BI "void matchpathcon_checkmatches(char *" str ");"
 .sp

 .BI "void set_matchpathcon_printf(void (*" f ")(const char *" fmt
", ...));"

-.BI "void set_matchpathcon_invalidcon(int (*" f ")(const char *"path ",
unsigned " lineno ", char * " context "));"
+.BI "void set_matchpathcon_invalidcon(int (*" f ")(const char *" path
", unsigned " lineno ", char * " context "));"

 .BI "void set_matchpathcon_flags(unsigned int " flags ");"

-.BI "int selinux_file_context_cmp(const security_context_t a,
-				     const security_context_t b);"
+.BI "int selinux_file_context_cmp(const security_context_t " a ", const
security_context_t " b ");"

-.BI "int selinux_file_context_verify(const char *path, mode_t mode);"
+.BI "int selinux_file_context_verify(const char *" path ", mode_t "
mode ");"
+
+.BI "int selinux_lsetfilecon_default(const char *" path ");"

 .SH "DESCRIPTION"
 .B matchpathcon_init
 <at>  <at>  -44,7 +58,16  <at>  <at>  and
 .B .local
 suffix are also looked up and loaded if present.  These files provide
 dynamically generated entries for user home directories and for local
-customizations.
+customizations. Returns zero on success or \-1 on error.
+
+.sp
+.B matchpathcon_init_prefix
+is the same as
+.B matchpathcon_init
+but only loads entries with regexes that have stems that are prefixes
+of
+.I prefix.
+Returns zero on success or \-1 on error.

 .sp
 .B matchpathcon_fini
 <at>  <at>  -78,6 +101,43  <at>  <at>  its first invocation with a NULL
 defaulting to the active file contexts configuration.
 .sp

+.B matchpathcon_index
+is the same as
+.B matchpathcon
+but returns a specification index that can be used later in a
+.B matchpathcon_filespec_add
+call.
+.sp
+
+.B matchpathcon_filespec_add
+maintains an association between an inode
+.I ino
+and a specification index
+.I specind,
+and checks whether a conflicting specification is already associated
+with the same inode (e.g. due to multiple hard links). If so, then
+it uses the latter of the two specifications based on their order in
the 
+.I file
+context configuration. Returns the specification index used or \-1 on
+error.
+.sp
+
+.B matchpathcon_filespec_destroy
+destroys any inode associations that have been added, e.g. to restart
+for a new filesystem.
+.sp
+
+.B matchpathcon_filespec_eval
+displays statistics on the hash table usage for the inode associations.
+.sp
+
+.B matchpathcon_checkmatches
+checks whether any specification has no matches and reports them.
+The
+.I str
+argument is used as a prefix for any warning messages.
+.sp
+
 .B set_matchpathcon_printf
 sets the function used by 
 .B matchpathcon_init
 <at>  <at>  -98,7 +158,7  <at>  <at>  This can be set to instead perform check
 e.g. using 
 .B sepol_check_context(3),
 as is done by 
-.B setfiles -c.
+.B setfiles \-c.
 The function is also responsible for reporting any such error, and
 may include the 
 .I path
 <at>  <at>  -122,10 +182,13  <at>  <at>  compares two file contexts to see if the
 .sp
 .B selinux_file_context_verify
 compares the file context on disk to the system default.
+.sp
+.B selinux_lsetfilecon_default
+sets the file context to the system defaults.

 .sp
 .SH "RETURN VALUE"
-Returns 0 on success or -1 otherwise.
+Returns zero on success or \-1 otherwise.

 .SH "SEE ALSO"
 .BR selinux "(8), " freecon "(3), " setfilecon "(3), " setfscreatecon
"(3)"
diff -pruN libselinux/man/man3/matchpathcon_checkmatches.3
libselinux-new/man/man3/matchpathcon_checkmatches.3
--- libselinux/man/man3/matchpathcon_checkmatches.3	1970-01-01
01:00:00.000000000 +0100
+++ libselinux-new/man/man3/matchpathcon_checkmatches.3	2009-11-02
17:54:56.000000000 +0100
 <at>  <at>  -0,0 +1  <at>  <at> 
+.so man3/matchpathcon.3
diff -pruN libselinux/man/man3/print_access_vector.3
libselinux-new/man/man3/print_access_vector.3
--- libselinux/man/man3/print_access_vector.3	1970-01-01
01:00:00.000000000 +0100
+++ libselinux-new/man/man3/print_access_vector.3	2009-11-02
19:34:40.000000000 +0100
 <at>  <at>  -0,0 +1  <at>  <at> 
+.so man3/security_class_to_string.3
diff -pruN libselinux/man/man3/security_class_to_string.3
libselinux-new/man/man3/security_class_to_string.3
--- libselinux/man/man3/security_class_to_string.3	2009-11-01
22:23:01.000000000 +0100
+++ libselinux-new/man/man3/security_class_to_string.3	2009-11-03
00:23:55.000000000 +0100
 <at>  <at>  -6,6 +6,8  <at>  <at> 
 security_class_to_string, security_av_perm_to_string,
string_to_security_class, string_to_av_perm, security_av_string \-
convert
 between SELinux class and permission values and string names.

+print_access_vector \- display an access vector in human-readable
form. 
+
 .SH "SYNOPSIS"
 .B #include <selinux/selinux.h>

 <at>  <at>  -20,6 +22,8  <at>  <at>  between SELinux class and permission val
 .BI "security_class_t string_to_security_class(const char *" name ");"
 .sp
 .BI "access_vector_t string_to_av_perm(security_class_t " tclass ",
const char *" name ");"
+.sp
+.BI "void print_access_vector(security_class_t " tclass ",
access_vector_t " av ");"

 .SH "DESCRIPTION"
 .B security_class_to_string
 <at>  <at>  -56,11 +60,17  <at>  <at>  and security class
 .IR tclass ,
 or zero if no such value exists.

+.B print_access_vector
+displays an access vector in human-readable form on the standard output
+stream.
+
 .SH "RETURN VALUE"
 .B security_av_string
-returns returns zero on success or \-1 on error with
+returns zero on success or \-1 on error with
 .I errno
-set appropriately.  All other functions return zero or NULL on error.
+set appropriately.
+.B print_access_vector
+does not return a value. All other functions return zero or NULL on
error.

 .SH "ERRORS"
 .TP
diff -pruN libselinux/man/man3/security_compute_av.3
libselinux-new/man/man3/security_compute_av.3
--- libselinux/man/man3/security_compute_av.3	2009-11-01
22:23:01.000000000 +0100
+++ libselinux-new/man/man3/security_compute_av.3	2009-11-02
23:34:49.000000000 +0100
 <at>  <at>  -24,6 +24,8  <at>  <at>  the SELinux policy database in the kerne
 .BI "int security_get_initial_context(const char *" name ",
security_context_t
 "con );
 .sp
+.BI "int selinux_check_passwd_access(access_vector_t " requested );
+.sp
 .BI "int checkPasswdAccess(access_vector_t " requested );

 .SH "DESCRIPTION"
 <at>  <at>  -65,18 +67,29  <at>  <at>  instance.

 .B security_compute_user
 is used to determine the set of user contexts that can be reached from
a
-source context. Is mainly used by
+source context. It is mainly used by
 .B get_ordered_context_list.

 .B security_get_initial_context
 is used to get the context of a kernel initial security identifier
specified by 
 .I name

+.B selinux_check_passwd_access
+is used to check for a permission in the
+.I passwd
+class.
+.B selinux_check_passwd_access
+uses getprevcon() for the source and target security contexts.
+
+.B checkPasswdAccess
+is a helper function that allows you to check for a permission in the
+.I passwd
+class.
 .B checkPasswdAccess
-This functions is a helper functions that allows you to check for a
permission in the passwd class. checkPasswdAccess uses getprevcon() for
the source and target security contexts.
+uses getprevcon() for the source and target security contexts.

 .SH "RETURN VALUE"
-0 for success and on error -1 is returned.
+0 for success and on error \-1 is returned.

 .SH "SEE ALSO"
 .BR selinux "(8), " getcon "(3), " getfilecon "(3), "
get_ordered_context_list "(3)"
diff -pruN libselinux/man/man3/security_disable.3
libselinux-new/man/man3/security_disable.3
--- libselinux/man/man3/security_disable.3	1970-01-01 01:00:00.000000000
+0100
+++ libselinux-new/man/man3/security_disable.3	2009-11-03
00:30:18.000000000 +0100
 <at>  <at>  -0,0 +1,26  <at>  <at> 
+.\" Hey Emacs! This file is -*- nroff -*- source.
+.\"
+.\" Author: Guido Trentalancia (guido@...) 2009
+.TH "security_disable" "3" "02 Nov 2009" "" "SELinux API documentation"
+.SH "NAME"
+security_disable \- disable the SELinux kernel code at runtime.
+
+.SH "SYNOPSIS"
+.B #include <selinux/selinux.h>
+.sp
+.BI "int security_disable(void);"
+
+.SH "DESCRIPTION"
+.B security_disable
+disables the SELinux kernel code, unregisters selinuxfs
from /proc/filesystems,
+and then umounts /selinux.
+
+.SH "RETURN VALUE"
+.B security_disable
+returns returns zero on success or \-1 on error.
+
+.SH "AUTHOR"
+This manual page has been written by Guido Trentalancia
<guido@...>
+
+.SH "SEE ALSO"
+.BR selinux (8),
diff -pruN libselinux/man/man3/security_load_booleans.3
libselinux-new/man/man3/security_load_booleans.3
--- libselinux/man/man3/security_load_booleans.3	2009-11-01
22:23:01.000000000 +0100
+++ libselinux-new/man/man3/security_load_booleans.3	2009-11-02
20:23:28.000000000 +0100
 <at>  <at>  -6,17 +6,19  <at>  <at>  security_get_boolean_pending \- routines
 .SH "SYNOPSIS"
 .B #include <selinux/selinux.h>
 .sp
-extern int security_load_booleans(char *path);
-
-extern int security_get_boolean_names(char ***names, int *len);
-
-extern int security_get_boolean_pending(const char *name);
-
-extern int security_get_boolean_active(const char *name);
-
-extern int security_set_boolean(const char *name, int value);
-
-extern int security_commit_booleans(void);
+.BI "int security_load_booleans(char *" path ");"
+.sp 
+.BI "int security_get_boolean_names(char ***" names ", int *" len ");"
+.sp
+.BI "int security_get_boolean_pending(const char *" name ");"
+.sp
+.BI "int security_get_boolean_active(const char *" name ");"
+.sp
+.BI "int security_set_boolean(const char *" name ", int " value ");"
+.sp
+.BI "int security_set_boolean_list(size_t " boolcnt ", SELboolean *"
boollist ", int " permanent ");"
+.sp
+.BI "int security_commit_booleans(void);"

 
 .SH "DESCRIPTION"
 <at>  <at>  -26,31 +28,37  <at>  <at>  disabled based on the current values of 
 These policy booleans allow runtime modification of the security
 policy without having to load a new policy.  

-The SELinux API allows for a transaction based update.  So you can set
several boolean values and the commit them all at once.
+The SELinux API allows for a transaction based update. So you can
+set several boolean values and then commit them all at once.
+
+.B security_load_booleans
+
+loads policy boolean settings. Path may be NULL, in which case the
+booleans are loaded from the active policy boolean configuration file.

-security_load_booleans
+.B security_get_boolean_names

-Load policy boolean settings. Path may be NULL, in which case the
booleans are loaded from the active policy boolean configuration file.
+returns a list of boolean names, currently supported by the loaded
policy.

-security_get_boolean_names
+.B security_get_boolean_pending

-Returns a list of boolean names, currently supported by the loaded
policy.
+returns pending value for boolean

-security_set_boolean 
+.B security_get_boolean_active

-Sets the pending value for boolean 
+returns active value for boolean

-security_get_boolean_pending
+.B security_set_boolean 

-Return pending value for boolean
+sets the pending value for boolean 

-security_get_boolean_active
+.B security_set_boolean_list

-Return active value for boolean
+saves a list of booleans in a single transaction.

-security_commit_booleans
+.B security_commit_booleans

-Commit all pending values for the booleans.
+commits all pending values for the booleans.

 .SH AUTHOR	
 This manual page was written by Dan Walsh <dwalsh@...>.
diff -pruN libselinux/man/man3/security_load_policy.3
libselinux-new/man/man3/security_load_policy.3
--- libselinux/man/man3/security_load_policy.3	2009-11-01
22:23:01.000000000 +0100
+++ libselinux-new/man/man3/security_load_policy.3	2009-11-03
00:30:45.000000000 +0100
 <at>  <at>  -1,14 +1,46  <at>  <at> 
-.TH "security_load_policy" "3" "1 January 2004" "russell@..."
"SELinux API documentation"
+.TH "security_load_policy" "3" "3 November 2009"
"guido@..." "SELinux API documentation"
 .SH "NAME"
 security_load_policy \- load a new SELinux policy
 .SH "SYNOPSIS"
 .B #include <selinux/selinux.h>
 .sp
 .BI "int security_load_policy(void *" data ", size_t "len );
+.sp
+.BI "int selinux_mkload_policy(int " preservebools ");"
+.sp
+.BI "int selinux_init_load_policy(int *" enforce ");"

 .SH "DESCRIPTION"
 .B security_load_policy
-loads a new policy, returns 0 for success and -1 for error.
+loads a new policy, returns 0 for success and \-1 for error.
+
+.B selinux_mkload_policy
+makes a policy image and loads it. This function provides a higher
level
+interface for loading policy than
+.B security_load_policy,
+internally determining the right policy version, locating and opening
+the policy file, mapping it into memory, manipulating it as needed for
+current boolean settings and/or local definitions, and then calling
+security_load_policy to load it.
+.I preservebools
+is a boolean flag indicating whether current policy boolean values
should
+be preserved into the new policy (if 1) or reset to the saved policy
+settings (if 0). The former case is the default for policy reloads,
while
+the latter case is an option for policy reloads but is primarily used
for
+the initial policy load.
+.B selinux_init_load_policy
+performs the initial policy load. This function determines the desired
+enforcing mode, sets the
+.I enforce
+argument accordingly for the caller to use, sets the SELinux kernel
+enforcing status to match it, and loads the policy. It also internally
+handles the initial selinuxfs mount required to perform these actions.
+
+.SH "RETURN VALUE"
+returns zero on success or \-1 on error.
+
+.SH "AUTHOR"
+This manual page has been written by Guido Trentalancia
<guido@...>

 .SH "SEE ALSO"
 .BR selinux "(8)"
diff -pruN libselinux/man/man3/security_mkload_policy.3
libselinux-new/man/man3/security_mkload_policy.3
--- libselinux/man/man3/security_mkload_policy.3	1970-01-01
01:00:00.000000000 +0100
+++ libselinux-new/man/man3/security_mkload_policy.3	2009-11-03
00:21:00.000000000 +0100
 <at>  <at>  -0,0 +1  <at>  <at> 
+.so man3/security_load_policy.3
diff -pruN libselinux/man/man3/selinux_lsetfilecon_default.3
libselinux-new/man/man3/selinux_lsetfilecon_default.3
--- libselinux/man/man3/selinux_lsetfilecon_default.3	1970-01-01
01:00:00.000000000 +0100
+++ libselinux-new/man/man3/selinux_lsetfilecon_default.3	2009-11-03
00:45:13.000000000 +0100
 <at>  <at>  -0,0 +1  <at>  <at> 
+.so man3/matchpathcon.3
diff -pruN libselinux/man/man3/set_selinuxmnt.3
libselinux-new/man/man3/set_selinuxmnt.3
--- libselinux/man/man3/set_selinuxmnt.3	1970-01-01 01:00:00.000000000
+0100
+++ libselinux-new/man/man3/set_selinuxmnt.3	2009-11-03
00:08:40.000000000 +0100
 <at>  <at>  -0,0 +1  <at>  <at> 
+.so man3/init_selinuxmnt.3
Attachment (new-manpages.patch): text/x-patch, 16 KiB
Michal Svoboda | 3 Nov 2009 12:45
Picon
Picon
Favicon

MCS read only cats

Hello,

I have been thinking of how to best implement a feature called read only
categories. That is, if we have a file with say c2, then c2 folks would
have full access (given by TE rules), but also there would be a category
called r2 (or c512+2 = c514 or whatever), that would be given read only
access to the file.

It seems to me that an implementation would ideally deal with a simple
MLS constrain or constrain relaxation. The reference policy constrains
file reading thus:

mlsconstrain file { read ioctl lock execute execute_no_trans }
        (( h1 dom h2 ) or ( t1 == mcsreadall ) or ( t2 == domain ));

How would one say 'also allow rN if file is cN'? So far I only came up
with an enumeration like so:

           (h1 dom r0 and h2 == c0)
	or (h1 dom r1 and h2 == c1)
	or (...1022 more)

Which seems ugly and perhaps such a mammoth expression would hog the
system too much. Moreover it seems it would be very difficult to
accomodate this enumeration for h2 == { c0, c1 } and beyond.

Does anyone have any better tips?

Michal Svoboda

Daniel J Walsh | 3 Nov 2009 14:13
Picon
Favicon
Gravatar

Re: selinux_check_passwd_access() behaviour when passwd class does not exist

On 11/02/2009 05:43 PM, Guido Trentalancia wrote:
> Hello !
> 
> The current behaviour of selinux_check_passwd_access() is to succeed
> even if the "passwd" class does not exist (see checkAccess.c:21). Is
> this really the intended behaviour ??
> 
> It would make more sense if it failed in such case (as in
> mapping.c:66)... Or am I wrong ?
> 
> Guido Trentalancia
> 
> 
> 
> --
> This message was distributed to subscribers of the selinux mailing list.
> If you no longer wish to subscribe, send mail to majordomo@... with
> the words "unsubscribe selinux" without quotes as the message.
I am not sure,  I think it could be argued that this function should not be in libselinux at all, since it hard
codes policy into the library.

I think you need to start setting the errno if you are going to change the function ENOSUPP for this error
versus EPERM for the other error, and then all users (passwd?) of the function need to change to look at the errno.


Gmane