Merge remote-tracking branch 'aosp/upstream-master' into mymerge

Change-Id: Ib31d805f4abcc7bebc923a5d9fa35ce7aa6e29b4
This commit is contained in:
Nick Kralevich 2015-05-06 10:15:39 -07:00
commit e39c09f418
16 changed files with 808 additions and 71 deletions

View file

@ -1,3 +1,4 @@
* Add selabel partial and best match APIs, from Richard Haines.
* Use os.walk() instead of the deprecated os.path.walk(), from Petr
Lautrbach & Miro Hrončok
* is_selinux_enabled(): drop no-policy-loaded test, from Stephen Smalley.

View file

@ -6,6 +6,7 @@
#ifndef _SELABEL_H_
#define _SELABEL_H_
#include <stdbool.h>
#include <sys/types.h>
#include <selinux/selinux.h>
@ -97,6 +98,13 @@ int selabel_lookup(struct selabel_handle *handle, char **con,
int selabel_lookup_raw(struct selabel_handle *handle, char **con,
const char *key, int type);
bool selabel_partial_match(struct selabel_handle *handle, const char *key);
int selabel_lookup_best_match(struct selabel_handle *rec, char **con,
const char *key, const char **aliases, int type);
int selabel_lookup_best_match_raw(struct selabel_handle *rec, char **con,
const char *key, const char **aliases, int type);
/**
* selabel_stats - log labeling operation statistics.
* @handle: specifies backend instance to query

View file

@ -0,0 +1,100 @@
.TH "selabel_lookup_best_match" "3" "05 May 2015" "Security Enhanced Linux" "SELinux API documentation"
.SH "NAME"
selabel_lookup_best_match \- obtain a best match SELinux security
context \- Only supported on file backend.
.
.SH "SYNOPSIS"
.B #include <selinux/selinux.h>
.br
.B #include <selinux/label.h>
.sp
.BI "int selabel_lookup_best_match(struct selabel_handle *" hnd ,
.in +\w'int selabel_lookup_best_match('u
.BI "char **" context ,
.br
.BI "const char *" key ,
.br
.BI "const char **" links ,
.br
.BI "int " type ");"
.in
.sp
.BI "int selabel_lookup_best_match_raw(struct selabel_handle *" hnd ,
.in +\w'int selabel_lookup_best_match_raw('u
.BI "char **" context ,
.br
.BI "const char *" key ,
.br
.BI "const char **" links ,
.br
.BI "int " type ");"
.in
.
.SH "DESCRIPTION"
.BR selabel_lookup_best_match ()
performs a best match lookup operation on the handle
.IR hnd ,
returning the result in the memory pointed to by
.IR context ,
which must be freed by the caller using
.BR freecon (3).
The \fIkey\fR parameter is a file path to check for best match using zero or
more \fIlink\fR (aliases) parameters. The order of precedence for best match is:
.RS
.IP "1." 4
An exact match for the real path (\fIkey\fR) or
.IP "2." 4
An exact match for any of the \fIlink\fRs (aliases), or
.IP "3." 4
The longest fixed prefix match.
.RE
.sp
The \fItype\fR parameter is an optional file \fImode\fR argument that should
be set to the mode bits of the file, as determined by \fBlstat\fR(2).
\fImode\fR may be zero, however full matching may not occur.
.BR selabel_lookup_best_match_raw ()
behaves identically to
.BR selabel_lookup_best_match ()
but does not perform context translation.
.
.SH "RETURN VALUE"
On success, zero is returned. On error, \-1 is returned and
.I errno
is set appropriately.
.
.SH "ERRORS"
.TP
.B ENOENT
No context corresponding to the input
.I key
and
.I type
was found.
.TP
.B EINVAL
The
.I key
and/or
.I type
inputs are invalid, or the context being returned failed validation.
.TP
.B ENOMEM
An attempt to allocate memory failed.
.sp
.SH "NOTES"
Example usage - When a service creates a device node, it may also create one
or more symlinks to the device node. These symlinks may be the only stable
name for the device, e.g. if the partition is dynamically assigned.
The file label backend supports this by looking up the "best match"
for a device node based on its real path (\fIkey\fR) and any \fIlink\fRs to it
(aliases). The order of precedence for best match is described above.
.sp
.SH "SEE ALSO"
.BR selabel_open (3),
.BR selabel_stats (3),
.BR selinux_set_callback (3),
.BR selinux (8),
.BR lstat (2),
.BR selabel_file (5)

View file

@ -0,0 +1 @@
.so man3/selabel_lookup_best_match.3

View file

@ -0,0 +1,34 @@
.TH "selabel_partial_match" "3" "05 May 2015" "Security Enhanced Linux" "SELinux API documentation"
.SH "NAME"
selabel_partial_match \- determine whether a direct or partial match is
possible on a file path \- Only supported on file backend.
.
.SH "SYNOPSIS"
.B #include <stdbool.h>
.br
.B #include <selinux/selinux.h>
.br
.B #include <selinux/label.h>
.sp
.BI "bool selabel_partial_match(struct selabel_handle *" hnd ,
.in +\w'int selabel_partial_match('u
.BI "const char *" key ");"
.in
.
.SH "DESCRIPTION"
.BR selabel_partial_match ()
performs a partial match operation on the handle
.IR hnd ,
returning TRUE or FALSE.
The \fIkey\fR parameter is a file path to check for a direct or partial match.
.sp
.SH "RETURN VALUE"
TRUE is returned if a direct or partial match is found, FALSE if not.
.sp
.SH "SEE ALSO"
.BR selabel_open (3),
.BR selabel_stats (3),
.BR selinux_set_callback (3),
.BR selinux (8),
.BR selabel_file (5)

View file

@ -154,6 +154,98 @@ out:
return rc;
}
/* Public API helpers */
static char *selabel_sub_key(struct selabel_handle *rec, const char *key)
{
char *ptr = NULL;
char *dptr = NULL;
ptr = selabel_sub(rec->subs, key);
if (ptr) {
dptr = selabel_sub(rec->dist_subs, ptr);
if (dptr) {
free(ptr);
ptr = dptr;
}
} else {
ptr = selabel_sub(rec->dist_subs, key);
}
if (ptr)
return ptr;
return NULL;
}
static int selabel_fini(struct selabel_handle *rec,
struct selabel_lookup_rec *lr,
int translating)
{
if (compat_validate(rec, lr, rec->spec_file, 0))
return -1;
if (translating && !lr->ctx_trans &&
selinux_raw_to_trans_context(lr->ctx_raw, &lr->ctx_trans))
return -1;
return 0;
}
static struct selabel_lookup_rec *
selabel_lookup_common(struct selabel_handle *rec, int translating,
const char *key, int type)
{
struct selabel_lookup_rec *lr;
char *ptr = NULL;
if (key == NULL) {
errno = EINVAL;
return NULL;
}
ptr = selabel_sub_key(rec, key);
if (ptr) {
lr = rec->func_lookup(rec, ptr, type);
free(ptr);
} else {
lr = rec->func_lookup(rec, key, type);
}
if (!lr)
return NULL;
if (selabel_fini(rec, lr, translating))
return NULL;
return lr;
}
static struct selabel_lookup_rec *
selabel_lookup_bm_common(struct selabel_handle *rec, int translating,
const char *key, int type, const char **aliases)
{
struct selabel_lookup_rec *lr;
char *ptr = NULL;
if (key == NULL) {
errno = EINVAL;
return NULL;
}
ptr = selabel_sub_key(rec, key);
if (ptr) {
lr = rec->func_lookup_best_match(rec, ptr, aliases, type);
free(ptr);
} else {
lr = rec->func_lookup_best_match(rec, key, aliases, type);
}
if (!lr)
return NULL;
if (selabel_fini(rec, lr, translating))
return NULL;
return lr;
}
/*
* Public API
*/
@ -188,48 +280,6 @@ out:
return rec;
}
static struct selabel_lookup_rec *
selabel_lookup_common(struct selabel_handle *rec, int translating,
const char *key, int type)
{
struct selabel_lookup_rec *lr;
char *ptr = NULL;
char *dptr = NULL;
if (key == NULL) {
errno = EINVAL;
return NULL;
}
ptr = selabel_sub(rec->subs, key);
if (ptr) {
dptr = selabel_sub(rec->dist_subs, ptr);
if (dptr) {
free(ptr);
ptr = dptr;
}
} else {
ptr = selabel_sub(rec->dist_subs, key);
}
if (ptr) {
lr = rec->func_lookup(rec, ptr, type);
free(ptr);
} else {
lr = rec->func_lookup(rec, key, type);
}
if (!lr)
return NULL;
if (compat_validate(rec, lr, rec->spec_file, 0))
return NULL;
if (translating && !lr->ctx_trans &&
selinux_raw_to_trans_context(lr->ctx_raw, &lr->ctx_trans))
return NULL;
return lr;
}
int selabel_lookup(struct selabel_handle *rec, char **con,
const char *key, int type)
{
@ -256,6 +306,66 @@ int selabel_lookup_raw(struct selabel_handle *rec, char **con,
return *con ? 0 : -1;
}
bool selabel_partial_match(struct selabel_handle *rec, const char *key)
{
char *ptr;
bool ret;
if (!rec->func_partial_match) {
/*
* If the label backend does not support partial matching,
* then assume a match is possible.
*/
return true;
}
ptr = selabel_sub_key(rec, key);
if (ptr) {
ret = rec->func_partial_match(rec, ptr);
free(ptr);
} else {
ret = rec->func_partial_match(rec, key);
}
return ret;
}
int selabel_lookup_best_match(struct selabel_handle *rec, char **con,
const char *key, const char **aliases, int type)
{
struct selabel_lookup_rec *lr;
if (!rec->func_lookup_best_match) {
errno = ENOTSUP;
return -1;
}
lr = selabel_lookup_bm_common(rec, 1, key, type, aliases);
if (!lr)
return -1;
*con = strdup(lr->ctx_trans);
return *con ? 0 : -1;
}
int selabel_lookup_best_match_raw(struct selabel_handle *rec, char **con,
const char *key, const char **aliases, int type)
{
struct selabel_lookup_rec *lr;
if (!rec->func_lookup_best_match) {
errno = ENOTSUP;
return -1;
}
lr = selabel_lookup_bm_common(rec, 0, key, type, aliases);
if (!lr)
return -1;
*con = strdup(lr->ctx_raw);
return *con ? 0 : -1;
}
void selabel_close(struct selabel_handle *rec)
{
selabel_subs_fini(rec->subs);

View file

@ -601,15 +601,17 @@ static void closef(struct selabel_handle *rec)
free(data);
}
static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
const char *key, int type)
static struct spec *lookup_common(struct selabel_handle *rec,
const char *key,
int type,
bool partial)
{
struct saved_data *data = (struct saved_data *)rec->data;
struct spec *spec_arr = data->spec_arr;
int i, rc, file_stem;
int i, rc, file_stem, pcre_options = 0;
mode_t mode = (mode_t)type;
const char *buf;
struct selabel_lookup_rec *ret = NULL;
struct spec *ret = NULL;
char *clean_key = NULL;
const char *prev_slash, *next_slash;
unsigned int sofar = 0;
@ -621,7 +623,7 @@ static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
/* Remove duplicate slashes */
if ((next_slash = strstr(key, "//"))) {
clean_key = malloc(strlen(key) + 1);
clean_key = (char *) malloc(strlen(key) + 1);
if (!clean_key)
goto finish;
prev_slash = key;
@ -639,6 +641,9 @@ static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
file_stem = find_stem_from_file(data, &buf);
mode &= S_IFMT;
if (partial)
pcre_options |= PCRE_PARTIAL_SOFT;
/*
* Check for matching specifications in reverse order, so that
* the last matching specification is used.
@ -654,14 +659,22 @@ static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
if (compile_regex(data, spec, NULL) < 0)
goto finish;
if (spec->stem_id == -1)
rc = pcre_exec(spec->regex, get_pcre_extra(spec), key, strlen(key), 0, 0, NULL, 0);
rc = pcre_exec(spec->regex,
get_pcre_extra(spec),
key, strlen(key), 0,
pcre_options, NULL, 0);
else
rc = pcre_exec(spec->regex, get_pcre_extra(spec), buf, strlen(buf), 0, 0, NULL, 0);
rc = pcre_exec(spec->regex,
get_pcre_extra(spec),
buf, strlen(buf), 0,
pcre_options, NULL, 0);
if (rc == 0) {
spec->matches++;
break;
} else if (rc == PCRE_ERROR_NOMATCH)
} else if (partial && rc == PCRE_ERROR_PARTIAL)
break;
if (rc == PCRE_ERROR_NOMATCH)
continue;
errno = ENOENT;
@ -677,13 +690,87 @@ static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
}
errno = 0;
ret = &spec_arr[i].lr;
ret = &spec_arr[i];
finish:
free(clean_key);
return ret;
}
static struct selabel_lookup_rec *lookup(struct selabel_handle *rec,
const char *key, int type)
{
struct spec *spec;
spec = lookup_common(rec, key, type, false);
if (spec)
return &spec->lr;
return NULL;
}
static bool partial_match(struct selabel_handle *rec, const char *key)
{
return lookup_common(rec, key, 0, true) ? true : false;
}
static struct selabel_lookup_rec *lookup_best_match(struct selabel_handle *rec,
const char *key,
const char **aliases,
int type)
{
size_t n, i;
int best = -1;
struct spec **specs;
size_t prefix_len = 0;
struct selabel_lookup_rec *lr = NULL;
if (!aliases || !aliases[0])
return lookup(rec, key, type);
for (n = 0; aliases[n]; n++)
;
specs = calloc(n+1, sizeof(struct spec *));
if (!specs)
return NULL;
specs[0] = lookup_common(rec, key, type, false);
if (specs[0]) {
if (!specs[0]->hasMetaChars) {
/* exact match on key */
lr = &specs[0]->lr;
goto out;
}
best = 0;
prefix_len = specs[0]->prefix_len;
}
for (i = 1; i <= n; i++) {
specs[i] = lookup_common(rec, aliases[i-1], type, false);
if (specs[i]) {
if (!specs[i]->hasMetaChars) {
/* exact match on alias */
lr = &specs[i]->lr;
goto out;
}
if (specs[i]->prefix_len > prefix_len) {
best = i;
prefix_len = specs[i]->prefix_len;
}
}
}
if (best >= 0) {
/* longest fixed prefix match on key or alias */
lr = &specs[best]->lr;
} else {
errno = ENOENT;
}
out:
free(specs);
return lr;
}
static void stats(struct selabel_handle *rec)
{
struct saved_data *data = (struct saved_data *)rec->data;
@ -722,6 +809,8 @@ int selabel_file_init(struct selabel_handle *rec, struct selinux_opt *opts,
rec->func_close = &closef;
rec->func_stats = &stats;
rec->func_lookup = &lookup;
rec->func_partial_match = &partial_match;
rec->func_lookup_best_match = &lookup_best_match;
return init(rec, opts, nopts);
}

View file

@ -31,6 +31,7 @@ struct spec {
char hasMetaChars; /* regular expression has meta-chars */
char regcomp; /* regex_str has been compiled to regex */
char from_mmap; /* this spec is from an mmap of the data */
size_t prefix_len; /* length of fixed path prefix */
};
/* A regular expression stem */

View file

@ -57,6 +57,12 @@ struct selabel_handle {
const char *key, int type);
void (*func_close) (struct selabel_handle *h);
void (*func_stats) (struct selabel_handle *h);
bool (*func_partial_match) (struct selabel_handle *h, const char *key);
struct selabel_lookup_rec *(*func_lookup_best_match)
(struct selabel_handle *h,
const char *key,
const char **aliases,
int type);
/* supports backend-specific state information */
void *data;

View file

@ -0,0 +1,126 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <errno.h>
#include <selinux/selinux.h>
#include <selinux/label.h>
static void usage(const char *progname)
{
fprintf(stderr,
"usage: %s -b backend [-v] [-r] -k key [-t type] [-f file]\n\n"
"Where:\n\t"
"-b The backend - \"file\", \"media\", \"x\", \"db\" or "
"\"prop\"\n\t"
"-v Validate entries against loaded policy.\n\t"
"-r Use \"raw\" function.\n\t"
"-k Lookup key - Depends on backend.\n\t"
"-t Lookup type - Optional as depends on backend.\n\t"
"-f Optional file containing the specs (defaults to\n\t"
" those used by loaded policy).\n\n"
"Examples:\n\t"
"%s -v -b file -k /run -t 0\n\t"
" lookup with validation against the loaded policy, the\n\t"
" \"file\" backend for path \"/run\" with mode = 0\n\t"
"%s -r -b x -t 4 -k X11:ButtonPress\n\t"
" lookup_raw the \"X\" backend for type SELABEL_X_EVENT\n\t"
" using key \"X11:ButtonPress\"\n\n",
progname, progname, progname);
exit(1);
}
int main(int argc, char **argv)
{
int raw = 0, type = 0, backend = 0, rc, opt;
char *validate = NULL, *key = NULL, *context = NULL, *file = NULL;
struct selabel_handle *hnd;
struct selinux_opt selabel_option[] = {
{ SELABEL_OPT_PATH, file },
{ SELABEL_OPT_VALIDATE, validate }
};
if (argc < 3)
usage(argv[0]);
while ((opt = getopt(argc, argv, "b:f:vrk:t:")) > 0) {
switch (opt) {
case 'b':
if (!strcasecmp(optarg, "file")) {
backend = SELABEL_CTX_FILE;
} else if (!strcmp(optarg, "media")) {
backend = SELABEL_CTX_MEDIA;
} else if (!strcmp(optarg, "x")) {
backend = SELABEL_CTX_X;
} else if (!strcmp(optarg, "db")) {
backend = SELABEL_CTX_DB;
} else if (!strcmp(optarg, "prop")) {
backend = SELABEL_CTX_ANDROID_PROP;
} else {
fprintf(stderr, "Unknown backend: %s\n",
optarg);
usage(argv[0]);
}
break;
case 'f':
file = optarg;
break;
case 'v':
validate = (char *)1;
break;
case 'r':
raw = 1;
break;
case 'k':
key = optarg;
break;
case 't':
type = atoi(optarg);
break;
default:
usage(argv[0]);
}
}
selabel_option[0].value = file;
selabel_option[1].value = validate;
hnd = selabel_open(backend, selabel_option, 2);
if (!hnd) {
fprintf(stderr, "ERROR: selabel_open - Could not obtain "
"handle.\n");
return -1;
}
switch (raw) {
case 1:
rc = selabel_lookup_raw(hnd, &context, key, type);
break;
default:
rc = selabel_lookup(hnd, &context, key, type);
}
selabel_close(hnd);
if (rc) {
switch (errno) {
case ENOENT:
fprintf(stderr, "ERROR: selabel_lookup failed to "
"find a valid context.\n");
break;
case EINVAL:
fprintf(stderr, "ERROR: selabel_lookup failed to "
"validate context, or key / type are "
"invalid.\n");
break;
default:
fprintf(stderr, "selabel_lookup ERROR: %s\n",
strerror(errno));
}
} else {
printf("Default context: %s\n", context);
freecon(context);
}
return rc;
}

View file

@ -0,0 +1,164 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <errno.h>
#include <sys/stat.h>
#include <selinux/selinux.h>
#include <selinux/label.h>
static void usage(const char *progname)
{
fprintf(stderr,
"usage: %s [-v] [-r] -p path [-m mode] [-f file] [link...]\n\n"
"Where:\n\t"
"-v Validate file_contxts entries against loaded policy.\n\t"
"-r Use \"raw\" function.\n\t"
"-p Path to check for best match using the link(s) provided.\n\t"
"-m Optional mode (b, c, d, p, l, s or f) Defaults to 0.\n\t"
"-f Optional file containing the specs (defaults to\n\t"
" those used by loaded policy).\n\t"
"link Zero or more links to check against, the order of\n\t"
" precedence for best match is:\n\t\t"
" 1) An exact match for the real path (if no links), or\n\t\t"
" 2) An exact match for any of the links (aliases), or\n\t\t"
" 3) The longest fixed prefix match.\n\n"
"Example:\n\t"
"%s -p /dev/initctl /run/systemd/initctl/fifo\n\t"
" Find best matching context for the specified path using one link.\n\n",
progname, progname);
exit(1);
}
static mode_t string_to_mode(char *s)
{
switch (s[0]) {
case 'b':
return S_IFBLK;
case 'c':
return S_IFCHR;
case 'd':
return S_IFDIR;
case 'p':
return S_IFIFO;
case 'l':
return S_IFLNK;
case 's':
return S_IFSOCK;
case 'f':
return S_IFREG;
};
return 0;
}
int main(int argc, char **argv)
{
int raw = 0, mode = 0, rc, opt, i, num_links, string_size;
char *validate = NULL, *path = NULL, *context = NULL, *file = NULL;
char **links = NULL;
struct selabel_handle *hnd;
struct selinux_opt options[] = {
{ SELABEL_OPT_PATH, file },
{ SELABEL_OPT_VALIDATE, validate }
};
if (argc < 3)
usage(argv[0]);
while ((opt = getopt(argc, argv, "f:vrp:m:")) > 0) {
switch (opt) {
case 'f':
file = optarg;
break;
case 'v':
validate = (char *)1;
break;
case 'r':
raw = 1;
break;
case 'p':
path = optarg;
break;
case 'm':
mode = string_to_mode(optarg);
break;
default:
usage(argv[0]);
}
}
/* Count links */
for (i = optind, num_links = 0; i < argc; i++, num_links++)
;
if (num_links != 0) {
links = malloc(sizeof(char *) * num_links);
if (links == NULL) {
fprintf(stderr, "ERROR: malloc failed.");
exit(1);
}
for (i = optind, num_links = 0; i < argc; i++, num_links++) {
string_size = strlen(argv[i]) + 1;
links[num_links] = malloc(string_size);
if (links[num_links] == NULL) {
fprintf(stderr, "ERROR: malloc failed.");
exit(1);
}
strcpy(links[num_links], argv[i]);
}
}
options[0].value = file;
options[1].value = validate;
hnd = selabel_open(SELABEL_CTX_FILE, options, 2);
if (!hnd) {
fprintf(stderr, "ERROR: selabel_open - Could not obtain "
"handle.\n");
rc = -1;
goto out;
}
switch (raw) {
case 1:
rc = selabel_lookup_best_match_raw(hnd, &context, path,
(const char **)links, mode);
break;
default:
rc = selabel_lookup_best_match(hnd, &context, path,
(const char **)links, mode);
}
selabel_close(hnd);
if (rc) {
switch (errno) {
case ENOENT:
fprintf(stderr, "ERROR: selabel_lookup_best_match "
"failed to find a valid context.\n");
break;
case EINVAL:
fprintf(stderr, "ERROR: selabel_lookup_best_match "
"failed to validate context, or path / mode "
"are invalid.\n");
break;
default:
fprintf(stderr, "selabel_lookup_best_match ERROR: "
"%s\n", strerror(errno));
}
} else {
printf("Best match context: %s\n", context);
freecon(context);
}
out:
if (num_links != 0) {
for (i = 0; i < num_links; i++)
free(links[i]);
free(links);
}
return rc;
}

View file

@ -0,0 +1,75 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <errno.h>
#include <stdbool.h>
#include <selinux/selinux.h>
#include <selinux/label.h>
static void usage(const char *progname)
{
fprintf(stderr,
"usage: %s [-v] -p <path> [-f file]\n\n"
"Where:\n\t"
"-v Validate file_contxts entries against loaded policy.\n\t"
"-p Path to check if a match or partial match is possible\n\t"
" against a regex entry in the file_contexts file.\n\t"
"-f Optional file_contexts file (defaults to current policy).\n\n"
"Example:\n\t"
"%s -p /sys/devices/system/cpu/online\n\t"
" Check if a match or partial match is possible against\n\t"
" the path \"/sys/devices/system/cpu/online\", returning\n\t"
" TRUE or FALSE.\n\n", progname, progname);
exit(1);
}
int main(int argc, char **argv)
{
int opt;
bool partial_match;
char *validate = NULL, *path = NULL, *file = NULL;
struct selabel_handle *hnd;
struct selinux_opt selabel_option[] = {
{ SELABEL_OPT_PATH, file },
{ SELABEL_OPT_VALIDATE, validate }
};
if (argc < 2)
usage(argv[0]);
while ((opt = getopt(argc, argv, "f:vp:")) > 0) {
switch (opt) {
case 'f':
file = optarg;
break;
case 'v':
validate = (char *)1;
break;
case 'p':
path = optarg;
break;
default:
usage(argv[0]);
}
}
selabel_option[0].value = file;
selabel_option[1].value = validate;
hnd = selabel_open(SELABEL_CTX_FILE, selabel_option, 2);
if (!hnd) {
fprintf(stderr, "ERROR: selabel_open - Could not obtain "
"handle.\n");
return -1;
}
partial_match = selabel_partial_match(hnd, path);
printf("Match or Partial match: %s\n",
partial_match == 1 ? "TRUE" : "FALSE");
selabel_close(hnd);
return partial_match;
}

View file

@ -1,3 +1,4 @@
* Verify users prior to evaluating users in cil, from Yuli Khodorkovskiy.
* Binary modules do not support ioctl rules, from Stephen Smalley.
* Add support for ioctl command whitelisting, from Jeff Vander Stoep.
* Don't use symbol versioning for static object files, from Yuli Khodorkovskiy.

View file

@ -1691,12 +1691,30 @@ exit:
return rc;
}
static int cil_pre_verify(struct cil_db *db)
{
int rc = SEPOL_ERR;
struct cil_args_verify extra_args;
extra_args.db = db;
rc = cil_tree_walk(db->ast->root, __cil_pre_verify_helper, NULL, NULL, &extra_args);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to verify cil database\n");
goto exit;
}
exit:
return rc;
}
int cil_post_process(struct cil_db *db)
{
int rc = SEPOL_ERR;
rc = cil_verify_no_classperms_loop(db);
rc = cil_pre_verify(db);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to verify cil database\n");
goto exit;
}

View file

@ -601,7 +601,7 @@ exit:
return rc;
}
int __cil_verify_user(struct cil_db *db, struct cil_tree_node *node)
static int __cil_verify_user_pre_eval(struct cil_tree_node *node)
{
int rc = SEPOL_ERR;
struct cil_user *user = node->data;
@ -635,6 +635,17 @@ int __cil_verify_user(struct cil_db *db, struct cil_tree_node *node)
}
}
return SEPOL_OK;
exit:
cil_log(CIL_ERR, "Invalid user at line %d of %s\n", node->line, node->path);
return rc;
}
static int __cil_verify_user_post_eval(struct cil_db *db, struct cil_tree_node *node)
{
int rc = SEPOL_ERR;
struct cil_user *user = node->data;
/* Verify user range only if anonymous */
if (user->range->datum.name == NULL) {
rc = __cil_verify_levelrange(db, user->range);
@ -1318,7 +1329,7 @@ int __cil_verify_helper(struct cil_tree_node *node, uint32_t *finished, void *ex
case 0: {
switch (node->flavor) {
case CIL_USER:
rc = __cil_verify_user(db, node);
rc = __cil_verify_user_post_eval(db, node);
break;
case CIL_SELINUXUSERDEFAULT:
(*nseuserdflt)++;
@ -1531,7 +1542,7 @@ static int __cil_verify_map_class(struct cil_tree_node *node)
return SEPOL_OK;
}
static int __cil_verify_no_classperms_loop_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args)
int __cil_pre_verify_helper(struct cil_tree_node *node, uint32_t *finished, __attribute__((unused)) void *extra_args)
{
int rc = SEPOL_ERR;
@ -1549,6 +1560,12 @@ static int __cil_verify_no_classperms_loop_helper(struct cil_tree_node *node, ui
}
switch (node->flavor) {
case CIL_USER:
rc = __cil_verify_user_pre_eval(node);
if (rc != SEPOL_OK) {
goto exit;
}
break;
case CIL_MAP_CLASS:
rc = __cil_verify_map_class(node);
break;
@ -1563,17 +1580,3 @@ static int __cil_verify_no_classperms_loop_helper(struct cil_tree_node *node, ui
exit:
return rc;
}
int cil_verify_no_classperms_loop(struct cil_db *db)
{
int rc = SEPOL_ERR;
rc = cil_tree_walk(db->ast->root, __cil_verify_no_classperms_loop_helper, NULL, NULL, NULL);
if (rc != SEPOL_OK) {
cil_log(CIL_ERR, "Failed to verify no loops in class permissions\n");
goto exit;
}
exit:
return rc;
}

View file

@ -68,6 +68,6 @@ int __cil_verify_ordered(struct cil_tree_node *current, enum cil_flavor flavor);
int __cil_verify_initsids(struct cil_list *sids);
int __cil_verify_senscat(struct cil_sens *sens, struct cil_cat *cat);
int __cil_verify_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args);
int cil_verify_no_classperms_loop(struct cil_db *db);
int __cil_pre_verify_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args);
#endif