Go to:
Gentoo Home
Documentation
Forums
Lists
Bugs
Planet
Store
Wiki
Get Gentoo!
Gentoo's Bugzilla – Attachment 58369 Details for
Bug 91921
setfiles segfaults (problem in libselinux?)
Home
|
New
–
[Ex]
|
Browse
|
Search
|
Privacy Policy
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
My setfiles.c with patch + printf
setfiles-patched.c (text/plain), 13.61 KB, created by
Daniel Thaler
on 2005-05-08 10:37:06 UTC
(
hide
)
Description:
My setfiles.c with patch + printf
Filename:
MIME Type:
Creator:
Daniel Thaler
Created:
2005-05-08 10:37:06 UTC
Size:
13.61 KB
patch
obsolete
>/* > * setfiles > * > * AUTHOR: Stephen Smalley <sds@epoch.ncsc.mil> > * This program was derived in part from the setfiles.pl script > * developed by Secure Computing Corporation. > * > * PURPOSE: > * This program reads a set of file security context specifications > * based on pathname regular expressions and labels files > * accordingly, traversing a set of file systems specified by > * the user. The program does not cross file system boundaries. > * > * USAGE: > * setfiles [-dnpqsvW] [-e directory ] [-c policy] [-o filename ] spec_file pathname... > * > * -e Specify directory to exclude > * -F Force reset of context to match file_context for customizable files > * -c Verify the specification file using a binary policy > * -d Show what specification matched each file. > * -l Log changes in files labels to syslog. > * -n Do not change any file labels. > * -q Be quiet (suppress non-error output). > * -r Use an alternate root path > * -s Use stdin for a list of files instead of searching a partition. > * -v Show changes in file labels. > * -W Warn about entries that have no matching file. > * -o filename write out file names with wrong context. > * > * spec_file The specification file. > * pathname... The file systems to label (omit if using -s). > * > * EXAMPLE USAGE: > * ./setfiles -v file_contexts `mount | awk '/ext3/{print $3}'` > * > * SPECIFICATION FILE: > * Each specification has the form: > * regexp [ -type ] ( context | <<none>> ) > * > * By default, the regexp is an anchored match on both ends (i.e. a > * caret (^) is prepended and a dollar sign ($) is appended automatically). > * This default may be overridden by using .* at the beginning and/or > * end of the regular expression. > * > * The optional type field specifies the file type as shown in the mode > * field by ls, e.g. use -d to match only directories or -- to match only > * regular files. > * > * The value of <<none> may be used to indicate that matching files > * should not be relabeled. > * > * The last matching specification is used. > * > * If there are multiple hard links to a file that match > * different specifications and those specifications indicate > * different security contexts, then a warning is displayed > * but the file is still labeled based on the last matching > * specification other than <<none>>. > */ > >#include <unistd.h> >#include <stdlib.h> >#include <fcntl.h> >#include <stdio.h> >#include <string.h> >#include <errno.h> >#include <ctype.h> >#include <regex.h> >#include <sys/vfs.h> >#define __USE_XOPEN_EXTENDED 1 /* nftw */ >#include <ftw.h> >#include <limits.h> >#include <sepol/sepol.h> >#include <selinux/selinux.h> >#include <syslog.h> >#include <libgen.h> > >static int add_assoc = 1; >static FILE *outfile=NULL; >static int force=0; > >#define MAX_EXCLUDES 100 >static int excludeCtr=0; >struct edir { > char *directory; > size_t size; >}; >static struct edir excludeArray[MAX_EXCLUDES]; > >/* > * Command-line options. > */ >static char *policyfile = NULL; >static int debug = 0; >static int change = 1; >static int quiet = 0; >static int use_stdin = 0; >static int verbose = 0; >static int log = 0; >static int warn_no_match = 0; >static char *rootpath = NULL; >static int rootpathlen = 0; > >static char *progname; > >static void >#ifdef __GNUC__ >__attribute__ ((format (printf, 1, 2))) >#endif >qprintf(const char *fmt, ...) >{ > va_list ap; > va_start(ap, fmt); > if (!quiet) > vfprintf(stdout, fmt, ap); > va_end(ap); >} > >static int add_exclude(const char *directory) { > struct stat sb; > if(directory == NULL || directory[0] != '/') { > fprintf(stderr, "Full path required for exclude: %s.\n", > directory); > return 1; > } > if(lstat(directory, &sb)) { > fprintf(stderr, "Directory \"%s\" not found, ignoring.\n", directory); > return 0; > } > if ((sb.st_mode & S_IFDIR) == 0 ) { > fprintf(stderr, "\"%s\" is not a Directory: mode %o, ignoring\n", directory,sb.st_mode); > return 0; > } > > if (excludeCtr == MAX_EXCLUDES) { > fprintf(stderr, "Maximum excludes %d exceeded.\n", MAX_EXCLUDES); > return 1; > } > > excludeArray[excludeCtr].directory = strdup(directory); > if (!excludeArray[excludeCtr].directory) { > fprintf(stderr, "Out of memory.\n"); > return 1; > } > excludeArray[excludeCtr++].size = strlen(directory); > > return 0; >} > >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) >{ > int ret; > const char *fullname = name; > > /* fullname will be the real file that gets labeled > * name will be what is matched in the policy */ > 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 (excludeCtr > 0) { > if (exclude(fullname)) { > return -1; > } > } > ret = lstat(fullname, sb); > if (ret) { > fprintf(stderr, "%s: unable to stat file %s\n", progname, > fullname); > return -1; > } > > if(rootpath != NULL && name[0]=='\0') > /* this is actually the root dir of the alt root */ > return matchpathcon_index("/", sb->st_mode, con); > else > return matchpathcon_index(name, sb->st_mode, con); > >} > >void usage(const char * const name) >{ > fprintf(stderr, > "usage: %s [-dnqvW] [-o filename] spec_file pathname...\n" > "usage: %s [-c policyfile] spec_file\n" > "usage: %s -s [-dnqvW] [-o filename ] spec_file\n", name, name, name); > exit(1); >} > >static int nerr = 0; > >void inc_err() >{ > nerr++; > if(nerr > 9 && !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); >} > >/* > * Apply the last matching specification to a file. > * This function is called by nftw on each file during > * the directory traversal. > */ >static int apply_spec(const char *file, > const struct stat *sb_unused __attribute__((unused)), > int flag, > struct FTW *s_unused __attribute__((unused))) >{ > const char *my_file; > struct stat my_sb; > int i, j, ret; > char *context, *newcon; > int user_only_changed=0; > > /* Skip the extra slash at the beginning, if present. */ > if (file[0] == '/' && file[1] == '/') > my_file = &file[1]; > else > my_file = file; > > if (flag == FTW_DNR) { > fprintf(stderr, "%s: unable to read directory %s\n", > progname, my_file); > return 0; > } > > i = match(my_file, &my_sb, &newcon); > if (i < 0) > /* No matching specification. */ > return 0; > > /* > * 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) { > j = matchpathcon_filespec_add(my_sb.st_ino, i, my_file); > if (j < 0) > goto err; > > if (j != i) { > /* 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(my_file, &context); > if (ret < 0) { > if (errno == ENODATA) { > context = malloc(10); > strcpy(context, "<<none>>"); > } else { > perror(my_file); > fprintf(stderr, "%s: unable to obtain attribute for file %s\n", > progname, my_file); > goto err; > } > } > > 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) || > (strcmp(context,newcon) == 0)) { > freecon(context); > goto out; > } > > if (! force && > ( is_context_customizable(context)>0 )) { > if (verbose > 1) { > fprintf(stderr,"%s: %s not reset customized by admin to %s\n", > progname, my_file, 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: relabeling %s from %s to %s\n", progname, > my_file, context, newcon); > } > } > > if ( log && !user_only_changed ) { > syslog(LOG_INFO, "relabeling %s from %s to %s\n", > my_file, context, newcon); > } > > if (outfile && !user_only_changed) > fprintf(outfile, "%s\n", my_file); > > 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(my_file, newcon); > if (ret) { > perror(my_file); > fprintf(stderr, "%s: unable to relabel %s to %s\n", > progname, my_file, newcon); > goto out; > } >out: > freecon(newcon); > return 0; >err: > freecon(newcon); > return -1; >} > >void set_rootpath(const char *arg) >{ > int len; > > rootpath = strdup(arg); > if (NULL == rootpath) { > fprintf(stderr, "%s: insufficient memory for rootpath\n", > progname); > exit(1); > } > > /* trim trailing /, if present */ > len = strlen(rootpath); > while ('/' == rootpath[len - 1]) > rootpath[--len] = 0; > rootpathlen = len; >} > >int invalidcon(const char *path, unsigned lineno, char *context) >{ > int valid = 1; > > if (policyfile) { > valid = (sepol_check_context ((char *) context) >= 0); > } else if (security_check_context((char *) context) < 0 && errno != ENOENT) { > valid = 0; > inc_err(); > } > > if (!valid) { > fprintf(stderr, "%s: line %u has invalid context %s\n", > path, lineno, context); > > /* Exit immediately if we're in checking mode. */ > if (policyfile) > exit(1); > } > > return !valid; >} > >int main(int argc, char **argv) >{ > int opt, rc, i; > > memset(excludeArray,0, sizeof(excludeArray)); > > /* Process any options. */ > while ((opt = getopt(argc, argv, "Fc:dlnqrsvWe:o:")) > 0) { > switch (opt) { > case 'c': > { > FILE *policystream; > > policyfile = optarg; > > policystream = fopen(policyfile,"r"); > if (!policystream) { > fprintf(stderr, "Error opening %s: %s\n", > policyfile, strerror(errno)); > exit(1); > } > > if (sepol_set_policydb_from_file(policystream) < 0) { > fprintf(stderr, "Error reading policy %s: %s\n", policyfile, > strerror(errno)); > exit(1); > } > fclose(policystream); > > break; > } > case 'e': > if ( add_exclude(optarg) ) exit(1); > break; > > case 'd': > debug = 1; > break; > case 'l': > log = 1; > break; > case 'F': > force = 1; > break; > case 'n': > change = 0; > break; > case 'o': > outfile = fopen(optarg,"w"); > if (!outfile) { > fprintf(stderr, "Error opening %s: %s\n", > optarg, strerror(errno)); > > usage(argv[0]); > } > break; > case 'q': > quiet = 1; > break; > case 'r': > if (optind + 1 >= argc) { > fprintf(stderr, "usage: %s -r rootpath\n", > argv[0]); > exit(1); > } > if (NULL != rootpath) { > fprintf(stderr, > "%s: only one -r can be specified\n", > argv[0]); > exit(1); > } > set_rootpath(argv[optind++]); > break; > case 's': > use_stdin = 1; > add_assoc = 0; > break; > case 'v': > verbose++; > break; > case 'W': > warn_no_match = 1; > break; > case '?': > usage(argv[0]); > } > } > > if (policyfile) { > if (optind != (argc - 1)) > usage(argv[0]); > } else if (use_stdin) { > if (optind != (argc - 1)) { > /* Cannot mix with pathname arguments. */ > usage(argv[0]); > } > } else { > if (optind > (argc - 2)) > usage(argv[0]); > } > > /* Use our own invalid context checking function so that > we can support either checking against the active policy or > checking against a binary policy file. */ > set_matchpathcon_invalidcon(&invalidcon); > > /* Load the file contexts configuration and check it. */ > rc = matchpathcon_init(argv[optind]); > if (rc < 0) { > perror(argv[optind]); > exit(1); > } > > optind++; > > if (nerr) > exit(1); > > /* > * Apply the specifications to the file systems. > */ > progname = argv[0]; > if(use_stdin) > { > char buf[PATH_MAX]; > while(fgets(buf, sizeof(buf), stdin)) > { > struct stat sb; > strtok(buf, "\n"); > if(buf[0] != '\n') > { > if(lstat(buf, &sb)) > fprintf(stderr, "File \"%s\" not found.\n", buf); > else > { > int flag; > switch(sb.st_mode) > { > case S_IFDIR: > flag = FTW_D; > break; > case S_IFLNK: > flag = FTW_SL; > break; > default: > flag = FTW_F; > } > apply_spec(buf, &sb, flag, NULL); > } > } > } > } > else for (; optind < argc; optind++) > { > if (NULL != rootpath) { > qprintf("%s: labeling files, pretending %s is /\n", > argv[0], rootpath); > } > > qprintf("%s: labeling files under %s\n", argv[0], > argv[optind]); > > /* Walk the file tree, calling apply_spec on each file. */ > if (nftw > (argv[optind], apply_spec, 1024, > FTW_PHYS | FTW_MOUNT)) { > fprintf(stderr, > "%s: error while labeling files under %s\n", > argv[0], argv[optind]); > exit(1); > } > > /* > * Evaluate the association hash table distribution for the > * directory tree just traversed. > */ > set_matchpathcon_printf(&qprintf); > matchpathcon_filespec_eval(); > set_matchpathcon_printf(NULL); > > /* Reset the association hash table for the next directory tree. */ > printf("1\n"); > matchpathcon_filespec_destroy(); > printf("2\n"); > } > > if (warn_no_match) > matchpathcon_checkmatches(argv[0]); > > if (outfile) > fclose(outfile); > > for(i=0; i < excludeCtr; i++) { > free(excludeArray[i].directory); > } > > qprintf("%s: Done.\n", argv[0]); > > exit(0); >}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Raw
Actions:
View
Attachments on
bug 91921
: 58369