From 7961bb65b63e82045f7fdafcedbf6340a470e17a Mon Sep 17 00:00:00 2001 From: jbj Date: Sun, 21 Dec 2003 15:21:41 +0000 Subject: [PATCH] Create file security context container. CVS patchset: 6986 CVS date: 2003/12/21 15:21:41 --- lib/Makefile.am | 26 +++++---- lib/rpmsx.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/rpmsx.h | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ lib/setfiles.c | 129 +++++++++++++++------------------------------ 4 files changed, 362 insertions(+), 98 deletions(-) create mode 100644 lib/rpmsx.c create mode 100644 lib/rpmsx.h diff --git a/lib/Makefile.am b/lib/Makefile.am index 4f21df6..820beb0 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -18,7 +18,7 @@ EXTRA_DIST = getdate.y pkgincdir = $(pkgincludedir) pkginc_HEADERS = \ misc.h rpmcli.h rpmlib.h \ - rpmal.h rpmds.h rpmfi.h rpmps.h rpmte.h rpmts.h stringbuf.h + rpmal.h rpmds.h rpmfi.h rpmps.h rpmsx.h rpmte.h rpmts.h stringbuf.h noinst_HEADERS = \ cpio.h fsm.h manifest.h psm.h rpmlead.h signature.h @@ -34,8 +34,8 @@ librpm_la_SOURCES = \ manifest.c misc.c package.c \ poptALL.c poptI.c poptQV.c psm.c query.c \ rpmal.c rpmchecksig.c rpmds.c rpmfi.c rpminstall.c \ - rpmlead.c rpmlibprov.c rpmps.c rpmrc.c rpmte.c rpmts.c rpmvercmp.c \ - signature.c stringbuf.c transaction.c \ + rpmlead.c rpmlibprov.c rpmps.c rpmrc.c rpmsx.c rpmte.c rpmts.c \ + rpmvercmp.c signature.c stringbuf.c transaction.c \ verify.c librpm_la_LDFLAGS = -release 4.3 $(LDFLAGS) \ $(top_builddir)/rpmdb/librpmdb.la \ @@ -77,10 +77,6 @@ BUILT_SOURCES = getdate.c # rpmlib.lcd #tds_SOURCES = tds.c #tds_LDFLAGS = @LDFLAGS_STATIC@ ./librpm.la -noinst_PROGRAMS = setfiles -setfiles_SOURCES = setfiles.c -setfiles_LDFLAGS = @LDFLAGS_STATIC@ -lselinux $(top_builddir)/popt/libpopt.la # ./librpm.la - rpmlib.lcd: Makefile.am ${librpm_la_SOURCES} ${pkginc_HEADERS} ${noinst_HEADERS} -lclint ${DEFS} ${INCLUDES} ${librpm_la_SOURCES} -dump $@ 2>/dev/null @@ -92,12 +88,14 @@ sources: lint: $(LINT) $(DEFS) $(INCLUDES) $(librpm_la_SOURCES) -th: th.c librpm.la - $(CC) $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< $(mylibs) - +setfiles: setfiles.o + $(LINK) @LDFLAGS_STATIC@ $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< \ + -lselinux \ + $(top_builddir)/rpmio/librpmio.la \ + $(top_builddir)/popt/libpopt.la + #tds: tds.c librpm.la # $(CC) $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< $(mylibs) -# trb: trb.o librpm.la $(LINK) @LDFLAGS_STATIC@ $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< $(mylibs) @@ -108,6 +106,12 @@ tthread: tthread.o librpm.la tsystem: tsystem.o $(top_builddir)/popt/libpopt.la $(LINK) $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< $(top_builddir)/rpmio/librpmio.la $(top_builddir)/popt/libpopt.la +tre: tre.o + $(LINK) @LDFLAGS_STATIC@ $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< \ + -lselinux \ + $(top_builddir)/rpmio/librpmio.la \ + $(top_builddir)/popt/libpopt.la + tcpu: tcpu.o librpm.la $(LINK) @LDFLAGS_STATIC@ $(CFLAGS) $(DEFS) $(INCLUDES) -o $@ $< $(mylibs) diff --git a/lib/rpmsx.c b/lib/rpmsx.c new file mode 100644 index 0000000..1fe2e93 --- /dev/null +++ b/lib/rpmsx.c @@ -0,0 +1,144 @@ +/** \ingroup rpmdep + * \file lib/rpmsx.c + */ +#include "system.h" + +#include + +#define _RPMSX_INTERNAL +#include "rpmsx.h" + +#include "debug.h" + +/*@unchecked@*/ +int _rpmsx_debug = 0; + +rpmsx XrpmsxUnlink(rpmsx sx, const char * msg, const char * fn, unsigned ln) +{ + if (sx == NULL) return NULL; +/*@-modfilesys@*/ +if (_rpmsx_debug && msg != NULL) +fprintf(stderr, "--> sx %p -- %d %s at %s:%u\n", sx, sx->nrefs, msg, fn, ln); +/*@=modfilesys@*/ + sx->nrefs--; + return NULL; +} + +rpmsx XrpmsxLink(rpmsx sx, const char * msg, const char * fn, unsigned ln) +{ + if (sx == NULL) return NULL; + sx->nrefs++; + +/*@-modfilesys@*/ +if (_rpmsx_debug && msg != NULL) +fprintf(stderr, "--> sx %p ++ %d %s at %s:%u\n", sx, sx->nrefs, msg, fn, ln); +/*@=modfilesys@*/ + + /*@-refcounttrans@*/ return sx; /*@=refcounttrans@*/ +} + +rpmsx rpmsxFree(rpmsx sx) +{ + int i; + + if (sx == NULL) + return NULL; + + if (sx->nrefs > 1) + return rpmsxUnlink(sx, __func__); + +/*@-modfilesys@*/ +if (_rpmsx_debug < 0) +fprintf(stderr, "*** sx %p\t%s[%d]\n", sx, __func__, sx->Count); +/*@=modfilesys@*/ + + /*@-branchstate@*/ + if (sx->Count > 0) + for (i = 0; i < sx->Count; i++) { + rpmsxp sxp = sx->sxp + i; + sxp->pattern = _free(sxp->pattern); + sxp->type = _free(sxp->type); + sxp->context = _free(sxp->context); + } + /*@=branchstate@*/ + + sx->sxp = _free(sx->sxp); + + (void) rpmsxUnlink(sx, __func__); + /*@-refcounttrans -usereleased@*/ +/*@-bounsxwrite@*/ + memset(sx, 0, sizeof(*sx)); /* XXX trash and burn */ +/*@=bounsxwrite@*/ + sx = _free(sx); + /*@=refcounttrans =usereleased@*/ + return NULL; +} + +rpmsx rpmsxNew(const char * fn) +{ + rpmsx sx; + + sx = xcalloc(1, sizeof(*sx)); + sx->Count = 0; + sx->i = -1; + sx->sxp = NULL; + +/*@-modfilesys@*/ +if (_rpmsx_debug < 0) +fprintf(stderr, "*** sx %p\t%s[%d]\n", sx, __func__, sx->Count); +/*@=modfilesys@*/ + + return rpmsxLink(sx, (sx ? __func__ : NULL)); +} + +int rpmsxCount(const rpmsx sx) +{ + return (sx != NULL ? sx->Count : 0); +} + +int rpmsxIx(const rpmsx sx) +{ + return (sx != NULL ? sx->i : -1); +} + +int rpmsxSetIx(rpmsx sx, int ix) +{ + int i = -1; + + if (sx != NULL) { + i = sx->i; + sx->i = ix; + } + return i; +} + +int rpmsxNext(/*@null@*/ rpmsx sx) + /*@modifies sx @*/ +{ + int i = -1; + + if (sx != NULL && ++sx->i >= 0) { + if (sx->i < sx->Count) { + i = sx->i; + } else + sx->i = -1; + +/*@-modfilesys @*/ +if (_rpmsx_debug < 0 && i != -1) +fprintf(stderr, "*** sx %p\t%s[%d]\n", sx, __func__, i); +/*@=modfilesys @*/ + + } + + return i; +} + +rpmsx rpmsxInit(/*@null@*/ rpmsx sx) + /*@modifies sx @*/ +{ + if (sx != NULL) + sx->i = -1; + /*@-refcounttrans@*/ + return sx; + /*@=refcounttrans@*/ +} diff --git a/lib/rpmsx.h b/lib/rpmsx.h new file mode 100644 index 0000000..7570b1c --- /dev/null +++ b/lib/rpmsx.h @@ -0,0 +1,161 @@ +#ifndef H_RPMSX +#define H_RPMSX + +/** \ingroup rpmdep rpmtrans + * \file lib/rpmsx.h + * Structure(s) used for file security context pattern handling + */ + +#include + +/** + */ +/*@-exportlocal@*/ +/*@unchecked@*/ +extern int _rpmsx_debug; +/*@=exportlocal@*/ + +/** + */ +/*@-exportlocal@*/ +/*@unchecked@*/ +extern int _rpmsx_nopromote; +/*@=exportlocal@*/ + +typedef struct rpmsxp_s * rpmsxp; +typedef struct rpmsx_s * rpmsx; + +#if defined(_RPMSX_INTERNAL) +/** + * File security context regex pattern. + */ +struct rpmsxp_s { +/*@only@*/ /*@null@*/ + const char * pattern; /*!< File path regex pattern. */ +/*@only@*/ /*@null@*/ + const char * type; /*!< File type. */ +/*@only@*/ /*@null@*/ + const char * context; /*!< Security context. */ +/*@only@*/ /*@null@*/ + regex_t * preg; /*!< Compiled regex. */ +}; + +/** + * File security context patterns container. + */ +struct rpmsx_s { + int Count; /*!< No. of elements */ + int i; /*!< Current element index. */ +/*@only@*/ /*@null@*/ + rpmsxp sxp; /*!< File context patterns. */ + int nrefs; /*!< Reference count. */ +}; +#endif /* defined(_RPMSX_INTERNAL) */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Unreference a security context patterns instance. + * @param sx security context patterns + * @param msg + * @return NULL always + */ +/*@unused@*/ /*@null@*/ +rpmsx rpmsxUnlink (/*@killref@*/ /*@only@*/ /*@null@*/ rpmsx sx, + /*@null@*/ const char * msg) + /*@modifies sx @*/; + +/** @todo Remove debugging entry from the ABI. */ +/*@-exportlocal@*/ +/*@null@*/ +rpmsx XrpmsxUnlink (/*@killref@*/ /*@only@*/ /*@null@*/ rpmsx sx, + /*@null@*/ const char * msg, const char * fn, unsigned ln) + /*@modifies sx @*/; +/*@=exportlocal@*/ +#define rpmsxUnlink(_sx, _msg) XrpmsxUnlink(_sx, _msg, __FILE__, __LINE__) + +/** + * Reference a security context patterns instance. + * @param sx security context patterns + * @param msg + * @return new security context patterns reference + */ +/*@unused@*/ /*@newref@*/ /*@null@*/ +rpmsx rpmsxLink (/*@null@*/ rpmsx sx, /*@null@*/ const char * msg) + /*@modifies sx @*/; + +/** @todo Remove debugging entry from the ABI. */ +/*@newref@*/ /*@null@*/ +rpmsx XrpmsxLink (/*@null@*/ rpmsx sx, /*@null@*/ const char * msg, + const char * fn, unsigned ln) + /*@modifies sx @*/; +#define rpmsxLink(_sx, _msg) XrpmsxLink(_sx, _msg, __FILE__, __LINE__) + +/** + * Destroy a security context patterns. + * @param sx security context patterns + * @return NULL always + */ +/*@null@*/ +rpmsx rpmsxFree(/*@killref@*/ /*@only@*/ /*@null@*/ rpmsx sx) + /*@modifies sx@*/; +/** + * Create and load security context patterns. + * @param fn header + * @param tagN type of dependency + * @param scareMem Use pointers to refcounted header memory? + * @return new security context patterns + */ +/*@null@*/ +rpmsx rpmsxNew(const char * fn) + /*@*/; + +/** + * Return security context patterns count. + * @param sx security context patterns + * @return current count + */ +int rpmsxCount(/*@null@*/ const rpmsx sx) + /*@*/; + +/** + * Return security context patterns index. + * @param sx security context patterns + * @return current index + */ +int rpmsxIx(/*@null@*/ const rpmsx sx) + /*@*/; + +/** + * Set security context patterns index. + * @param sx security context patterns + * @param ix new index + * @return current index + */ +int rpmsxSetIx(/*@null@*/ rpmsx sx, int ix) + /*@modifies sx @*/; + +/** + * Return next security context patterns iterator index. + * @param sx security context patterns + * @return security context patterns iterator index, -1 on termination + */ +int rpmsxNext(/*@null@*/ rpmsx sx) + /*@modifies sx @*/; + +/** + * Initialize security context patterns iterator. + * @param sx security context patterns + * @return security context patterns + */ +/*@null@*/ +rpmsx rpmsxInit(/*@null@*/ rpmsx sx) + /*@modifies sx @*/; + +#ifdef __cplusplus +} +#endif + +#endif /* H_RPMSX */ diff --git a/lib/setfiles.c b/lib/setfiles.c index aa99037..ac155c0 100644 --- a/lib/setfiles.c +++ b/lib/setfiles.c @@ -84,10 +84,14 @@ static int rootpathlen = 0; * A file security context specification. */ typedef struct spec { - char *regex_str; /* regular expession string for diagnostic messages */ +/*@only@*/ + char *pattern; /* regular expession string for diagnostic messages */ +/*@only@*/ char *type_str; /* type string for diagnostic messages */ +/*@only@*/ char *context; /* context string */ - regex_t regex; /* compiled regular expression */ +/*@only@*/ + regex_t * preg; /* compiled regular expression */ mode_t mode; /* mode format value */ int matches; /* number of matching pathnames */ int hasMetaChars; /* indicates whether the RE has @@ -119,7 +123,7 @@ static int get_stem_from_spec(const char * const buf) if (!tmp) return 0; - for(ind = buf + 1; ind < tmp; ind++) { + for (ind = buf + 1; ind < tmp; ind++) { if (strchr(regex_chars, (int)*ind)) return 0; } @@ -147,7 +151,7 @@ static int find_stem_from_spec(const char **buf) if (!stem_len) return -1; - for(i = 0; i < num_stems; i++) { + for (i = 0; i < num_stems; i++) { if (stem_len != stem_arr[i].len) continue; if (strncmp(*buf, stem_arr[i].buf, stem_len)) @@ -158,18 +162,10 @@ static int find_stem_from_spec(const char **buf) if (num_stems == alloc_stems) { alloc_stems = alloc_stems * 2 + 16; - stem_arr = realloc(stem_arr, sizeof(*stem_arr) * alloc_stems); - if (!stem_arr) { - fprintf(stderr, "Unable to grow stem array to %d entries: out of memory.\n", alloc_stems); - exit(1); - } + stem_arr = xrealloc(stem_arr, sizeof(*stem_arr) * alloc_stems); } stem_arr[num_stems].len = stem_len; - stem_arr[num_stems].buf = malloc(stem_len + 1); - if (!stem_arr[num_stems].buf) { - fprintf(stderr, "Unable to allocate new stem of length %d: out of memory.\n", stem_len+1); - exit(1); - } + stem_arr[num_stems].buf = xmalloc(stem_len + 1); memcpy(stem_arr[num_stems].buf, *buf, stem_len); stem_arr[num_stems].buf[stem_len] = '\0'; num_stems++; @@ -186,7 +182,7 @@ static int find_stem_from_file(const char **buf) int i; if (stem_len) - for(i = 0; i < num_stems; i++) { + for (i = 0; i < num_stems; i++) { if (stem_len != stem_arr[i].len) continue; if (strncmp(*buf, stem_arr[i].buf, stem_len)) @@ -252,14 +248,7 @@ static file_spec_t file_spec_add(ino_t ino, int specind, const char *file) if (ret < 0 || sb.st_ino != ino) { fl->specind = specind; free(fl->file); - fl->file = malloc(strlen(file) + 1); - if (!fl->file) { - fprintf(stderr, - "%s: insufficient memory for file label entry for %s\n", - __progname, file); - return NULL; - } - strcpy(fl->file, file); + fl->file = xstrdup(file); return fl; } @@ -275,14 +264,7 @@ static file_spec_t file_spec_add(ino_t ino, int specind, const char *file) fl->specind = (specind > fl->specind) ? specind : fl->specind; free(fl->file); - fl->file = malloc(strlen(file) + 1); - if (!fl->file) { - fprintf(stderr, - "%s: insufficient memory for file label entry for %s\n", - __progname, file); - return NULL; - } - strcpy(fl->file, file); + fl->file = xstrdup(file); return fl; } @@ -290,21 +272,10 @@ static file_spec_t file_spec_add(ino_t ino, int specind, const char *file) break; } - fl = malloc(sizeof(*fl)); - if (!fl) { - fprintf(stderr, "%s: insufficient memory for file label entry for %s\n", - __progname, file); - return NULL; - } + fl = xmalloc(sizeof(*fl)); fl->ino = ino; fl->specind = specind; - fl->file = malloc(strlen(file) + 1); - if (!fl->file) { - fprintf(stderr, "%s: insufficient memory for file label entry for %s\n", - __progname, file); - return NULL; - } - strcpy(fl->file, file); + fl->file = xstrdup(file); fl->next = prevfl->next; prevfl->next = fl; return fl; @@ -406,9 +377,9 @@ static int match(const char *name, struct stat *sb) continue; if (sp->stem_id == -1) - ret = regexec(&sp->regex, name, 0, NULL, 0); + ret = regexec(sp->preg, name, 0, NULL, 0); else - ret = regexec(&sp->regex, buf, 0, NULL, 0); + ret = regexec(sp->preg, buf, 0, NULL, 0); if (ret == 0) break; @@ -416,9 +387,9 @@ static int match(const char *name, struct stat *sb) continue; /* else it's an error */ - regerror(ret, &sp->regex, errbuf, sizeof errbuf); + regerror(ret, sp->preg, errbuf, sizeof errbuf); fprintf(stderr, "%s: unable to match %s against %s: %s\n", - __progname, name, sp->regex_str, errbuf); + __progname, name, sp->pattern, errbuf); return -1; } @@ -454,7 +425,7 @@ static int nodups_specs(void) spec_t sjp = spec_arr + j; /* Check if same RE string */ - if (strcmp(sjp->regex_str, sip->regex_str)) + if (strcmp(sjp->pattern, sip->pattern)) continue; if (sjp->mode && sip->mode && sjp->mode != sip->mode) continue; @@ -464,12 +435,12 @@ static int nodups_specs(void) /* If different contexts, give warning */ fprintf(stderr, "ERROR: Multiple different specifications for %s (%s and %s).\n", - sip->regex_str, sjp->context, sip->context); + sip->pattern, sjp->context, sip->context); } else { /* If same contexts give warning */ fprintf(stderr, "WARNING: Multiple same specifications for %s.\n", - sip->regex_str); + sip->pattern); } } } @@ -486,17 +457,13 @@ static void usage(const char * const name, poptContext optCon) } /* Determine if the regular expression specification has any meta characters. */ -static void spec_hasMetaChars(spec_t spec) +static void spec_hasMetaChars(spec_t sp) { - char *c; - int len; - char *end; + char * c = sp->pattern; + int len = strlen(c); + char * end = c + len; - c = spec->regex_str; - len = strlen(spec->regex_str); - end = c + len; - - spec->hasMetaChars = 0; + sp->hasMetaChars = 0; /* Look at each character in the RE specification string for a * meta character. Return when any meta character reached. */ @@ -512,7 +479,7 @@ static void spec_hasMetaChars(spec_t spec) case '[': case '(': case '{': - spec->hasMetaChars = 1; + sp->hasMetaChars = 1; return; break; case '\\': /* skip the next character */ @@ -535,11 +502,11 @@ static void spec_hasMetaChars(spec_t spec) static int apply_spec(const char *file, const struct stat *sb_unused, int flag, struct FTW *s_unused) { - const char *my_file; + const char * my_file; file_spec_t fl; struct stat my_sb; int i, ret; - char *context; + char * context; spec_t sp; /* Skip the extra slash at the beginning, if present. */ @@ -580,11 +547,11 @@ static int apply_spec(const char *file, if (debug) { if (sp->type_str) { printf("%s: %s matched by (%s,%s,%s)\n", __progname, - my_file, sp->regex_str, + my_file, sp->pattern, sp->type_str, sp->context); } else { printf("%s: %s matched by (%s,%s)\n", __progname, - my_file, sp->regex_str, sp->context); + my_file, sp->pattern, sp->context); } } @@ -592,8 +559,7 @@ static int apply_spec(const char *file, ret = lgetfilecon(my_file, &context); if (ret < 0) { if (errno == ENODATA) { - context = malloc(10); - strcpy(context, "<>"); + context = xstrdup("<>"); } else { perror(my_file); fprintf(stderr, "%s: unable to obtain attribute for file %s\n", @@ -684,6 +650,7 @@ int parseREContexts(const char *fn) */ for (pass = 0; pass < 2; pass++) { spec_t sp; + lineno = 0; nspec = 0; sp = spec_arr; @@ -724,25 +691,19 @@ int parseREContexts(const char *fn) /* On the second pass, compile and store the specification in spec. */ const char *reg_buf = regex; sp->stem_id = find_stem_from_spec(®_buf); - sp->regex_str = regex; + sp->pattern = regex; /* Anchor the regular expression. */ len = strlen(reg_buf); - anchored_regex = malloc(len + 3); - if (!anchored_regex) { - fprintf(stderr, - "%s: insufficient memory for anchored regexp on line %d\n", - fn, lineno); - return -1; - } + anchored_regex = xmalloc(len + 3); sprintf(anchored_regex, "^%s$", reg_buf); /* Compile the regular expression. */ - regerr = regcomp(&sp->regex, anchored_regex, + sp->preg = xcalloc(1, sizeof(*sp->preg)); + regerr = regcomp(sp->preg, anchored_regex, REG_EXTENDED | REG_NOSUB); if (regerr < 0) { - regerror(regerr, &sp->regex, - errbuf, sizeof errbuf); + regerror(regerr, sp->preg, errbuf, sizeof errbuf); fprintf(stderr, "%s: unable to compile regular expression %s on line number %d: %s\n", fn, regex, lineno, @@ -828,12 +789,7 @@ int parseREContexts(const char *fn) QPRINTF("%s: read %d specifications\n", fn, nspec); if (nspec == 0) return 0; - if ((spec_arr = malloc(sizeof(*spec_arr) * nspec)) == NULL) { - fprintf(stderr, "%s: insufficient memory for specifications\n", - fn); - return -1; - } - memset(spec_arr, 0, sizeof(*spec_arr) * nspec); + spec_arr = xcalloc(nspec, sizeof(*spec_arr)); rewind(fp); } } @@ -1008,12 +964,11 @@ int main(int argc, char **argv) continue; if (sp->type_str) { printf("%s: Warning! No matches for (%s, %s, %s)\n", - __progname, sp->regex_str, + __progname, sp->pattern, sp->type_str, sp->context); } else { printf("%s: Warning! No matches for (%s, %s)\n", - __progname, sp->regex_str, - sp->context); + __progname, sp->pattern, sp->context); } } } -- 2.7.4