Merge remote-tracking branch 'aosp/upstream-master' into mymerge
Followed the following steps: # In repo client cd external/selinux repo sync . repo start mymerge . git merge aosp/upstream-master --no-ff # resolve any conflicts repo upload . Test: compiles/boots no problems. Change-Id: I4cd9f73fbbb818ef7fa07ff8dd183f8a7e892345
This commit is contained in:
commit
4d25411b3a
79 changed files with 969 additions and 222 deletions
32
.travis.yml
32
.travis.yml
|
@ -11,29 +11,30 @@ compiler:
|
|||
env:
|
||||
matrix:
|
||||
# Test the last version of Python and Ruby together, with some linkers
|
||||
- PYVER=python3.6 RUBYLIBVER=2.4
|
||||
- PYVER=python3.6 RUBYLIBVER=2.4 TEST_FLAGS_OVERRIDE=1
|
||||
- PYVER=python3.6 RUBYLIBVER=2.4 LINKER=gold
|
||||
- PYVER=python3.6 RUBYLIBVER=2.4 LINKER=bfd
|
||||
- PYVER=python3.6 RUBYLIBVER=2.5.1
|
||||
- PYVER=python3.6 RUBYLIBVER=2.5.1 TEST_FLAGS_OVERRIDE=1
|
||||
- PYVER=python3.6 RUBYLIBVER=2.5.1 LINKER=gold
|
||||
- PYVER=python3.6 RUBYLIBVER=2.5.1 LINKER=bfd
|
||||
|
||||
# Test several Python versions
|
||||
- PYVER=python2.7 RUBYLIBVER=2.4
|
||||
- PYVER=python3.3 RUBYLIBVER=2.4
|
||||
- PYVER=python3.4 RUBYLIBVER=2.4
|
||||
- PYVER=python3.5 RUBYLIBVER=2.4
|
||||
- PYVER=pypy RUBYLIBVER=2.4
|
||||
- PYVER=pypy3 RUBYLIBVER=2.4
|
||||
- PYVER=python2.7 RUBYLIBVER=2.5.1
|
||||
- PYVER=python3.3 RUBYLIBVER=2.5.1
|
||||
- PYVER=python3.4 RUBYLIBVER=2.5.1
|
||||
- PYVER=python3.5 RUBYLIBVER=2.5.1
|
||||
- PYVER=pypy RUBYLIBVER=2.5.1
|
||||
- PYVER=pypy3 RUBYLIBVER=2.5.1
|
||||
|
||||
# Test several Ruby versions
|
||||
- PYVER=python3.6 RUBYLIBVER=2.2
|
||||
- PYVER=python3.6 RUBYLIBVER=2.4
|
||||
- PYVER=python3.6 RUBYLIBVER=2.3
|
||||
- PYVER=python3.6 RUBYLIBVER=2.2
|
||||
|
||||
matrix:
|
||||
exclude:
|
||||
- compiler: clang
|
||||
env: PYVER=python3.6 RUBYLIBVER=2.4 LINKER=gold
|
||||
env: PYVER=python3.6 RUBYLIBVER=2.5.1 LINKER=gold
|
||||
- compiler: clang
|
||||
env: PYVER=python3.6 RUBYLIBVER=2.4 LINKER=bfd
|
||||
env: PYVER=python3.6 RUBYLIBVER=2.5.1 LINKER=bfd
|
||||
|
||||
# Use Travis-CI Ubuntu 14.04 Trusty infrastructure, "full image" variant
|
||||
sudo: required
|
||||
|
@ -64,10 +65,10 @@ addons:
|
|||
install:
|
||||
# Download refpolicy Makefile for sepolgen tests
|
||||
- sudo mkdir -p /usr/share/selinux/default
|
||||
- sudo curl --retry 10 -o /usr/share/selinux/default/Makefile 'https://raw.githubusercontent.com/TresysTechnology/refpolicy/RELEASE_2_20170204/support/Makefile.devel'
|
||||
- sudo curl --retry 10 -o /usr/share/selinux/default/Makefile 'https://raw.githubusercontent.com/SELinuxProject/refpolicy/RELEASE_2_20180114/support/Makefile.devel'
|
||||
- sudo sed "s,^PREFIX :=.*,PREFIX := $TRAVIS_BUILD_DIR/installdir/usr," -i /usr/share/selinux/default/Makefile
|
||||
- sudo mkdir -p /usr/share/selinux/refpolicy/include
|
||||
- sudo curl --retry 10 -o /usr/share/selinux/refpolicy/include/build.conf 'https://raw.githubusercontent.com/TresysTechnology/refpolicy/RELEASE_2_20170204/build.conf'
|
||||
- sudo curl --retry 10 -o /usr/share/selinux/refpolicy/include/build.conf 'https://raw.githubusercontent.com/SELinuxProject/refpolicy/RELEASE_2_20180114/build.conf'
|
||||
- sudo mkdir -p /etc/selinux
|
||||
- echo 'SELINUXTYPE=refpolicy' | sudo tee /etc/selinux/config
|
||||
|
||||
|
@ -98,6 +99,7 @@ before_script:
|
|||
- if echo "$PYVER" | grep -q pypy ; then export PYINC=-I$($PYTHON -c 'import sys;print(sys.prefix)')/include PYLIBS= ; fi
|
||||
|
||||
# Find the Ruby executable with version $RUBYLIBVER
|
||||
- rvm reinstall ruby-$RUBYLIBVER --binary
|
||||
- export RUBY="$(ls -d -1 "$HOME/.rvm/rubies/ruby-$RUBYLIBVER"*/bin/ruby | head -n 1)"
|
||||
|
||||
# Set the linker in $CC so that it gets used everywhere
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.7
|
||||
2.8
|
||||
|
|
|
@ -802,6 +802,7 @@ int require_class(int pass)
|
|||
if ((datum = calloc(1, sizeof(*datum))) == NULL ||
|
||||
symtab_init(&datum->permissions, PERM_SYMTAB_SIZE)) {
|
||||
yyerror("Out of memory!");
|
||||
class_datum_destroy(datum);
|
||||
return -1;
|
||||
}
|
||||
ret =
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.7
|
||||
2.8
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.7
|
||||
2.8
|
||||
|
|
|
@ -145,7 +145,7 @@ def html_to_text(html, maxcol=80):
|
|||
|
||||
def html_document(*body_components):
|
||||
'''Wrap the body components in a HTML document structure with a valid header.
|
||||
Accepts a variable number of arguments of of which canb be:
|
||||
Accepts a variable number of arguments of which can be:
|
||||
* string
|
||||
* a sequences of strings (tuple or list).
|
||||
* a callable object taking no parameters and returning a string or sequence of strings.
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.7
|
||||
2.8
|
||||
|
|
|
@ -36,8 +36,8 @@ extern int selinux_restorecon(const char *pathname,
|
|||
*/
|
||||
#define SELINUX_RESTORECON_NOCHANGE 0x0002
|
||||
/*
|
||||
* If set set change file label to that in spec file.
|
||||
* If not only change type component to that in spec file.
|
||||
* If set, change file label to that in spec file.
|
||||
* If not, only change type component to that in spec file.
|
||||
*/
|
||||
#define SELINUX_RESTORECON_SET_SPECFILE_CTX 0x0004
|
||||
/*
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
.TH "selinux_boolean_sub" "3" "11 June 2012" "dwalsh@redhat.com" "SELinux API documentation"
|
||||
.SH "NAME"
|
||||
selinux_boolean_sub \-
|
||||
selinux_boolean_sub \- Search the translated name for a boolean_name record
|
||||
.
|
||||
.SH "SYNOPSIS"
|
||||
.B #include <selinux/selinux.h>
|
||||
|
@ -12,7 +12,7 @@ selinux_boolean_sub \-
|
|||
searches the
|
||||
.I \%/etc/selinux/{POLICYTYPE}/booleans.subs_dist
|
||||
file
|
||||
for a maching boolean_name record. If the record exists the boolean substitution name is returned. If not
|
||||
for a matching boolean_name record. If the record exists the boolean substitution name is returned. If not
|
||||
.BR \%selinux_boolean_sub ()
|
||||
returns the original
|
||||
.IR \%boolean_name .
|
||||
|
|
|
@ -18,7 +18,7 @@ reads the contents of the
|
|||
file to determine which policy files should be used for this machine.
|
||||
.
|
||||
.BR selinux_set_policy_root ()
|
||||
sets up all all policy paths based on the alternate root
|
||||
sets up all policy paths based on the alternate root
|
||||
|
||||
.I /etc/selinux/config
|
||||
file to determine which policy files should be used for this machine.
|
||||
|
|
|
@ -119,7 +119,7 @@ By default
|
|||
.BR selinux_restorecon_xattr (3)
|
||||
will use the default set of specfiles described in
|
||||
.BR files_contexts (5)
|
||||
to calculate the initial SHA1 digest to be used for comparision.
|
||||
to calculate the initial SHA1 digest to be used for comparison.
|
||||
To change this default behavior
|
||||
.BR selabel_open (3)
|
||||
must be called specifying the required
|
||||
|
|
|
@ -92,7 +92,7 @@ The optional local and distribution substitution files that perform any path ali
|
|||
.RE
|
||||
.sp
|
||||
The default file context series of files are:
|
||||
.RS
|
||||
.RS 6
|
||||
.I /etc/selinux/{SELINUXTYPE}/contexts/files/file_contexts
|
||||
.br
|
||||
.I /etc/selinux/{SELINUXTYPE}/contexts/files/file_contexts.local
|
||||
|
|
|
@ -5,7 +5,7 @@ virtual_domain_context \- The SELinux virtual machine domain context configurati
|
|||
.SH "DESCRIPTION"
|
||||
The
|
||||
.I virtual_domain_context
|
||||
file contains a list of domain contexts that are available for use by the SELinux-aware virtulization API libvirt (see \fBlibvirtd\fR(8)).
|
||||
file contains a list of domain contexts that are available for use by the SELinux-aware virtualization API libvirt (see \fBlibvirtd\fR(8)).
|
||||
.sp
|
||||
.BR selinux_virtual_domain_context_path "(3) "
|
||||
will return the active policy path to this file. The default virtual domain context file is:
|
||||
|
|
|
@ -5,7 +5,7 @@ virtual_image_context \- The SELinux virtual machine image context configuration
|
|||
.SH "DESCRIPTION"
|
||||
The
|
||||
.I virtual_image_context
|
||||
file contains a list of image contexts for use by the SELinux-aware virtulization API libvirt (see \fBlibvirtd\fR(8)).
|
||||
file contains a list of image contexts for use by the SELinux-aware virtualization API libvirt (see \fBlibvirtd\fR(8)).
|
||||
.sp
|
||||
.BR selinux_virtual_image_context_path "(3) "
|
||||
will return the active policy path to this file. The default virtual image context file is:
|
||||
|
|
|
@ -98,6 +98,8 @@ LD_SONAME_FLAGS=-install_name,$(LIBSO)
|
|||
endif
|
||||
|
||||
PCRE_LDLIBS ?= -lpcre
|
||||
# override with -lfts when building on Musl libc to use fts-standalone
|
||||
FTS_LDLIBS ?=
|
||||
|
||||
override CFLAGS += -I../include -D_GNU_SOURCE $(DISABLE_FLAGS) $(PCRE_CFLAGS)
|
||||
|
||||
|
@ -149,7 +151,7 @@ $(LIBA): $(OBJS)
|
|||
$(RANLIB) $@
|
||||
|
||||
$(LIBSO): $(LOBJS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ $(PCRE_LDLIBS) -ldl -Wl,$(LD_SONAME_FLAGS)
|
||||
$(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ $(PCRE_LDLIBS) $(FTS_LDLIBS) -ldl -Wl,$(LD_SONAME_FLAGS)
|
||||
ln -sf $@ $(TARGET)
|
||||
|
||||
$(LIBPC): $(LIBPC).in ../VERSION
|
||||
|
|
|
@ -193,7 +193,7 @@ static int __policy_init(const char *init_path)
|
|||
{
|
||||
FILE *fp;
|
||||
char path[PATH_MAX];
|
||||
char errormsg[PATH_MAX];
|
||||
char errormsg[PATH_MAX+1024+20];
|
||||
struct sepol_policy_file *pf = NULL;
|
||||
int rc;
|
||||
unsigned int cnt;
|
||||
|
|
|
@ -416,7 +416,7 @@ static int save_booleans(size_t boolcnt, SELboolean * boollist)
|
|||
ssize_t ret;
|
||||
size_t size = 0;
|
||||
int val;
|
||||
char boolname[BUFSIZ];
|
||||
char boolname[BUFSIZ-3];
|
||||
char *buffer;
|
||||
inbuf = NULL;
|
||||
__fsetlocking(boolf, FSETLOCKING_BYCALLER);
|
||||
|
@ -450,6 +450,7 @@ static int save_booleans(size_t boolcnt, SELboolean * boollist)
|
|||
}
|
||||
}
|
||||
if (i == boolcnt) {
|
||||
val = !!val;
|
||||
snprintf(outbuf, sizeof(outbuf),
|
||||
"%s=%d\n", boolname, val);
|
||||
len = strlen(outbuf);
|
||||
|
@ -505,6 +506,7 @@ int security_set_boolean_list(size_t boolcnt, SELboolean * boollist,
|
|||
|
||||
size_t i;
|
||||
for (i = 0; i < boolcnt; i++) {
|
||||
boollist[i].value = !!boollist[i].value;
|
||||
if (security_set_boolean(boollist[i].name, boollist[i].value)) {
|
||||
rollback(boollist, i);
|
||||
return -1;
|
||||
|
|
|
@ -153,7 +153,7 @@ static int selabel_fini(struct selabel_handle *rec,
|
|||
|
||||
if (rec->spec_files)
|
||||
path = rec->spec_files[0];
|
||||
if (compat_validate(rec, lr, path, 0))
|
||||
if (compat_validate(rec, lr, path, lr->lineno))
|
||||
return -1;
|
||||
|
||||
if (translating && !lr->ctx_trans &&
|
||||
|
|
|
@ -278,12 +278,14 @@ static inline int store_stem(struct saved_data *data, char *buf, int stem_len)
|
|||
|
||||
if (data->alloc_stems == num) {
|
||||
struct stem *tmp_arr;
|
||||
|
||||
data->alloc_stems = data->alloc_stems * 2 + 16;
|
||||
int alloc_stems = data->alloc_stems * 2 + 16;
|
||||
tmp_arr = realloc(data->stem_arr,
|
||||
sizeof(*tmp_arr) * data->alloc_stems);
|
||||
if (!tmp_arr)
|
||||
sizeof(*tmp_arr) * alloc_stems);
|
||||
if (!tmp_arr) {
|
||||
free(buf);
|
||||
return -1;
|
||||
}
|
||||
data->alloc_stems = alloc_stems;
|
||||
data->stem_arr = tmp_arr;
|
||||
}
|
||||
data->stem_arr[num].len = stem_len;
|
||||
|
@ -472,6 +474,7 @@ static inline int process_line(struct selabel_handle *rec,
|
|||
spec_arr[nspec].mode = 0;
|
||||
|
||||
spec_arr[nspec].lr.ctx_raw = context;
|
||||
spec_arr[nspec].lr.lineno = lineno;
|
||||
|
||||
/*
|
||||
* bump data->nspecs to cause closef() to cover it in its free
|
||||
|
|
|
@ -73,6 +73,7 @@ struct selabel_lookup_rec {
|
|||
char * ctx_raw;
|
||||
char * ctx_trans;
|
||||
int validated;
|
||||
unsigned lineno;
|
||||
};
|
||||
|
||||
struct selabel_handle {
|
||||
|
|
|
@ -116,7 +116,7 @@ static pthread_once_t fc_once = PTHREAD_ONCE_INIT;
|
|||
*
|
||||
* check_excluded() - Check if directory/fs is to be excluded when relabeling.
|
||||
*
|
||||
* file_system_count() - Calculates the the number of files to be processed.
|
||||
* file_system_count() - Calculates the number of files to be processed.
|
||||
* The count is only used if SELINUX_RESTORECON_PROGRESS
|
||||
* is set and a mass relabel is requested.
|
||||
*
|
||||
|
|
|
@ -110,7 +110,8 @@ int main(int argc, char **argv)
|
|||
cumulative = 1;
|
||||
break;
|
||||
case 'f':
|
||||
strncpy(avcstatfile, optarg, sizeof avcstatfile);
|
||||
strncpy(avcstatfile, optarg, sizeof(avcstatfile) - 1);
|
||||
avcstatfile[sizeof(avcstatfile)-1] = '\0';
|
||||
break;
|
||||
case 'h':
|
||||
case '-':
|
||||
|
|
|
@ -19,7 +19,7 @@ static __attribute__ ((__noreturn__)) void usage(const char *name, const char *d
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char **list, *usercon = NULL, *cur_context = NULL;
|
||||
char **list, *cur_context = NULL;
|
||||
char *user = NULL, *level = NULL;
|
||||
int ret, i, opt;
|
||||
|
||||
|
@ -40,6 +40,7 @@ int main(int argc, char **argv)
|
|||
if (!is_selinux_enabled()) {
|
||||
fprintf(stderr,
|
||||
"getconlist may be used only on a SELinux kernel.\n");
|
||||
free(level);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -49,6 +50,7 @@ int main(int argc, char **argv)
|
|||
if (((argc - optind) < 2)) {
|
||||
if (getcon(&cur_context) < 0) {
|
||||
fprintf(stderr, "Couldn't get current context.\n");
|
||||
free(level);
|
||||
return 2;
|
||||
}
|
||||
} else
|
||||
|
@ -67,7 +69,7 @@ int main(int argc, char **argv)
|
|||
freeconary(list);
|
||||
}
|
||||
|
||||
free(usercon);
|
||||
free(level);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.7
|
||||
2.8
|
||||
|
|
|
@ -23,7 +23,7 @@ The count function will return the number of all objects in the selected locatio
|
|||
.B Parameters:
|
||||
The
|
||||
.I handle
|
||||
is used to track persistent state across semanage calls, and for error reporting. The number of objects will be stored at the location poined by
|
||||
is used to track persistent state across semanage calls, and for error reporting. The number of objects will be stored at the location pointed by
|
||||
.I response.
|
||||
|
||||
.TP
|
||||
|
|
|
@ -25,7 +25,7 @@ The list function will return an array of all the objects in the selected locati
|
|||
.B Parameters:
|
||||
The
|
||||
.I handle
|
||||
is used to track persistent state across semanage calls, and for error reporting. The function will allocate and populate the the array of objects, and store it at the location pointed by
|
||||
is used to track persistent state across semanage calls, and for error reporting. The function will allocate and populate the array of objects, and store it at the location pointed by
|
||||
.I objects.
|
||||
It will write the number of objects at the location pointed by
|
||||
.I count.
|
||||
|
|
|
@ -1481,7 +1481,7 @@ rebuild:
|
|||
retval = semanage_copy_file(path,
|
||||
semanage_path(SEMANAGE_TMP,
|
||||
SEMANAGE_STORE_SEUSERS),
|
||||
sh->conf->file_mode);
|
||||
0);
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
pseusers->dtable->drop_cache(pseusers->dbase);
|
||||
|
@ -1499,7 +1499,7 @@ rebuild:
|
|||
retval = semanage_copy_file(path,
|
||||
semanage_path(SEMANAGE_TMP,
|
||||
SEMANAGE_USERS_EXTRA),
|
||||
sh->conf->file_mode);
|
||||
0);
|
||||
if (retval < 0)
|
||||
goto cleanup;
|
||||
pusers_extra->dtable->drop_cache(pusers_extra->dbase);
|
||||
|
|
|
@ -972,9 +972,13 @@ static int add_user(genhomedircon_settings_t * s,
|
|||
char uid[11];
|
||||
char gid[11];
|
||||
|
||||
errno = 0;
|
||||
/* Allocate space for the getpwnam_r buffer */
|
||||
rbuflen = sysconf(_SC_GETPW_R_SIZE_MAX);
|
||||
if (rbuflen <= 0)
|
||||
if (rbuflen == -1 && errno == 0)
|
||||
/* sysconf returning -1 with no errno means indeterminate size */
|
||||
rbuflen = 1024;
|
||||
else if (rbuflen <= 0)
|
||||
goto cleanup;
|
||||
rbuf = malloc(rbuflen);
|
||||
if (rbuf == NULL)
|
||||
|
@ -1057,8 +1061,12 @@ static int get_group_users(genhomedircon_settings_t * s,
|
|||
struct group grstorage, *group = NULL;
|
||||
struct passwd *pw = NULL;
|
||||
|
||||
errno = 0;
|
||||
grbuflen = sysconf(_SC_GETGR_R_SIZE_MAX);
|
||||
if (grbuflen <= 0)
|
||||
if (grbuflen == -1 && errno == 0)
|
||||
/* sysconf returning -1 with no errno means indeterminate size */
|
||||
grbuflen = 1024;
|
||||
else if (grbuflen <= 0)
|
||||
goto cleanup;
|
||||
grbuf = malloc(grbuflen);
|
||||
if (grbuf == NULL)
|
||||
|
|
|
@ -1350,6 +1350,8 @@ static char **split_args(const char *arg0, char *arg_string,
|
|||
if (isspace(*s) && !in_quote && !in_dquote) {
|
||||
if (arg != NULL) {
|
||||
rc = append_arg(&argv, &num_args, arg);
|
||||
if (rc)
|
||||
goto cleanup;
|
||||
free(arg);
|
||||
arg = NULL;
|
||||
}
|
||||
|
@ -1366,6 +1368,8 @@ static char **split_args(const char *arg0, char *arg_string,
|
|||
}
|
||||
if (arg != NULL) {
|
||||
rc = append_arg(&argv, &num_args, arg);
|
||||
if (rc)
|
||||
goto cleanup;
|
||||
free(arg);
|
||||
arg = NULL;
|
||||
}
|
||||
|
@ -1593,7 +1597,12 @@ static int semanage_install_final_tmp(semanage_handle_t * sh)
|
|||
/* skip genhomedircon if configured */
|
||||
if (sh->conf->disable_genhomedircon &&
|
||||
i == SEMANAGE_FC_HOMEDIRS) continue;
|
||||
|
||||
|
||||
if (strlen(dst) >= sizeof(fn)) {
|
||||
ERR(sh, "Unable to compose the final paths.");
|
||||
status = -1;
|
||||
goto cleanup;
|
||||
}
|
||||
strcpy(fn, dst);
|
||||
ret = semanage_mkpath(sh, dirname(fn));
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.7
|
||||
2.8
|
||||
|
|
|
@ -2923,7 +2923,7 @@ int cil_resolve_call1(struct cil_tree_node *current, void *extra_args)
|
|||
|
||||
rc = cil_fill_ipaddr(pc->cl_head, ipaddr);
|
||||
if (rc != SEPOL_OK) {
|
||||
cil_log(CIL_ERR, "Failed to create anonymous ip address, rc; %d\n", rc);
|
||||
cil_log(CIL_ERR, "Failed to create anonymous ip address, rc: %d\n", rc);
|
||||
cil_destroy_ipaddr(ipaddr);
|
||||
goto exit;
|
||||
}
|
||||
|
|
|
@ -339,7 +339,7 @@ static int cil_expr_to_string(struct cil_list *expr, char **out)
|
|||
int pos = 0;
|
||||
|
||||
cil_list_for_each(curr, expr) {
|
||||
if (pos > COND_EXPR_MAXDEPTH) {
|
||||
if (pos >= COND_EXPR_MAXDEPTH) {
|
||||
rc = SEPOL_ERR;
|
||||
goto exit;
|
||||
}
|
||||
|
@ -512,7 +512,7 @@ void cil_tree_print_expr(struct cil_list *datum_expr, struct cil_list *str_expr)
|
|||
} else {
|
||||
rc = cil_expr_to_string(str_expr, &expr_str);
|
||||
}
|
||||
if (rc < 0) {
|
||||
if (rc != SEPOL_OK) {
|
||||
cil_log(CIL_INFO, "ERROR)");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -646,9 +646,6 @@ extern int policydb_context_isvalid(const policydb_t * p,
|
|||
|
||||
extern void symtabs_destroy(symtab_t * symtab);
|
||||
extern int scope_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p);
|
||||
typedef void (*hashtab_destroy_func_t) (hashtab_key_t k, hashtab_datum_t d,
|
||||
void *args);
|
||||
extern hashtab_destroy_func_t get_symtab_destroy_func(int sym_num);
|
||||
|
||||
extern void class_perm_node_init(class_perm_node_t * x);
|
||||
extern void type_set_init(type_set_t * x);
|
||||
|
|
|
@ -201,11 +201,11 @@ static int load_users(struct policydb *policydb, const char *path)
|
|||
if (!(*p))
|
||||
BADLINE();
|
||||
q = p;
|
||||
while (*p && strncasecmp(p, "range", 5))
|
||||
while (*p && (!isspace(*p) || strncasecmp(p + 1, "range", 5)))
|
||||
p++;
|
||||
if (!(*p))
|
||||
if (!(*p) || p == q)
|
||||
BADLINE();
|
||||
*--p = 0;
|
||||
*p = 0;
|
||||
p++;
|
||||
|
||||
scontext = malloc(p - q);
|
||||
|
|
|
@ -80,10 +80,13 @@ static char *create_str_helper(const char *fmt, int num, va_list vargs)
|
|||
goto exit;
|
||||
}
|
||||
|
||||
va_end(vargs2);
|
||||
|
||||
return str;
|
||||
|
||||
exit:
|
||||
free(str);
|
||||
va_end(vargs2);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
@ -298,6 +298,8 @@ static int roles_gather_map(char *key, void *data, void *args)
|
|||
role_node->role = role;
|
||||
|
||||
rc = list_prepend((struct list *)args, role_node);
|
||||
if (rc != 0)
|
||||
free(role_node);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -344,6 +346,11 @@ static int typealiases_gather_map(char *key, void *data, void *arg)
|
|||
goto exit;
|
||||
}
|
||||
}
|
||||
/* As typealias_lists[scope_id] does not hold the
|
||||
* ownership of its items (typealias_list_destroy does
|
||||
* not free the list items), "key" does not need to be
|
||||
* strdup'ed before it is inserted in the list.
|
||||
*/
|
||||
list_prepend(typealias_lists[scope_id], key);
|
||||
}
|
||||
}
|
||||
|
@ -1002,6 +1009,12 @@ static int ebitmap_to_names(struct ebitmap *map, char **vals_to_names, char ***n
|
|||
}
|
||||
}
|
||||
|
||||
if (!num) {
|
||||
*names = NULL;
|
||||
*num_names = 0;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
name_arr = malloc(sizeof(*name_arr) * num);
|
||||
if (name_arr == NULL) {
|
||||
log_err("Out of memory");
|
||||
|
@ -1092,7 +1105,6 @@ static int roletype_role_in_ancestor_to_cil(struct policydb *pdb, struct stack *
|
|||
goto exit;
|
||||
}
|
||||
|
||||
curr = role_list->head;
|
||||
for (curr = role_list->head; curr != NULL; curr = curr->next) {
|
||||
role_node = curr->data;
|
||||
if (!is_id_in_ancestor_scope(pdb, decl_stack, role_node->role_name, SYM_ROLES)) {
|
||||
|
@ -1284,7 +1296,6 @@ static int cond_expr_to_cil(int indent, struct policydb *pdb, struct cond_expr *
|
|||
rc = -1;
|
||||
goto exit;
|
||||
}
|
||||
num_params = 0;
|
||||
} else {
|
||||
switch(curr->expr_type) {
|
||||
case COND_NOT: op = "not"; break;
|
||||
|
@ -1824,8 +1835,6 @@ static int constraint_expr_to_string(struct policydb *pdb, struct constraint_exp
|
|||
free(names);
|
||||
names = NULL;
|
||||
}
|
||||
|
||||
num_params = 0;
|
||||
} else {
|
||||
switch (expr->expr_type) {
|
||||
case CEXPR_NOT: op = "not"; break;
|
||||
|
@ -1917,10 +1926,12 @@ exit:
|
|||
free(new_val);
|
||||
free(val1);
|
||||
free(val2);
|
||||
while ((val1 = stack_pop(stack)) != NULL) {
|
||||
free(val1);
|
||||
if (stack != NULL) {
|
||||
while ((val1 = stack_pop(stack)) != NULL) {
|
||||
free(val1);
|
||||
}
|
||||
stack_destroy(&stack);
|
||||
}
|
||||
stack_destroy(&stack);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
@ -4221,7 +4232,6 @@ exit:
|
|||
int sepol_ppfile_to_module_package(FILE *fp, struct sepol_module_package **mod_pkg)
|
||||
{
|
||||
int rc = -1;
|
||||
FILE *f = NULL;
|
||||
struct sepol_policy_file *pf = NULL;
|
||||
struct sepol_module_package *pkg = NULL;
|
||||
char *data = NULL;
|
||||
|
@ -4273,9 +4283,6 @@ exit:
|
|||
free(data);
|
||||
|
||||
sepol_policy_file_free(pf);
|
||||
if (f != NULL) {
|
||||
fclose(f);
|
||||
}
|
||||
|
||||
if (rc != 0) {
|
||||
sepol_module_package_free(pkg);
|
||||
|
|
|
@ -83,7 +83,7 @@ static int node_parse_addr(sepol_handle_t * handle,
|
|||
}
|
||||
|
||||
/* Allocates a sufficiently large buffer (addr, addr_sz)
|
||||
* according the the protocol */
|
||||
* according to the protocol */
|
||||
|
||||
static int node_alloc_addr(sepol_handle_t * handle,
|
||||
int proto, char **addr, size_t * addr_sz)
|
||||
|
|
|
@ -1573,14 +1573,6 @@ int scope_destroy(hashtab_key_t key, hashtab_datum_t datum, void *p
|
|||
return 0;
|
||||
}
|
||||
|
||||
hashtab_destroy_func_t get_symtab_destroy_func(int sym_num)
|
||||
{
|
||||
if (sym_num < 0 || sym_num >= SYM_NUM) {
|
||||
return NULL;
|
||||
}
|
||||
return (hashtab_destroy_func_t) destroy_f[sym_num];
|
||||
}
|
||||
|
||||
/*
|
||||
* Load the initial SIDs specified in a policy database
|
||||
* structure into a SID table.
|
||||
|
|
|
@ -210,7 +210,6 @@ int read_binary_policy(const char *path, policydb_t *p)
|
|||
if ((in_fp = fopen(path, "rb")) == NULL) {
|
||||
fprintf(stderr, "Unable to open %s: %s\n", path,
|
||||
strerror(errno));
|
||||
sepol_handle_destroy(f.handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -220,7 +219,6 @@ int read_binary_policy(const char *path, policydb_t *p)
|
|||
f.fp = in_fp;
|
||||
rc = policydb_read(p, &f, 0);
|
||||
|
||||
sepol_handle_destroy(f.handle);
|
||||
fclose(in_fp);
|
||||
return rc;
|
||||
}
|
||||
|
@ -256,7 +254,7 @@ int write_binary_policy(const char *path, policydb_t *p)
|
|||
if ((out_fp = fopen(path, "w" )) == NULL) {
|
||||
fprintf(stderr, "Unable to open %s: %s\n", path,
|
||||
strerror(errno));
|
||||
sepol_handle_destroy(f.handle);
|
||||
sepol_handle_destroy(handle);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.7
|
||||
2.8
|
||||
|
|
|
@ -59,7 +59,7 @@ defines a translation of s15:c0.c1023 to SystemHigh. c0.c1023 is shorthand for a
|
|||
|
||||
.TP
|
||||
s0\-s15:c0.c1023=SystemLow\-SystemHigh\fR
|
||||
defines a range translation of of s0\-s15:c0.c1023 to SystemLow\-SystemHigh. The two range components are separated by a dash.
|
||||
defines a range translation of s0\-s15:c0.c1023 to SystemLow\-SystemHigh. The two range components are separated by a dash.
|
||||
|
||||
.TP
|
||||
s0:c0=PatientRecord\fR
|
||||
|
|
|
@ -708,6 +708,7 @@ append(affix_t **affixes, const char *val) {
|
|||
|
||||
err:
|
||||
log_error("allocation error %s", strerror(errno));
|
||||
free(affix);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1517,8 +1518,10 @@ trans_context(const security_context_t incon, security_context_t *rcon) {
|
|||
} else {
|
||||
trans = compute_trans_from_raw(range, domain);
|
||||
if (trans)
|
||||
if (add_cache(domain, range, trans) < 0)
|
||||
if (add_cache(domain, range, trans) < 0) {
|
||||
free(range);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (lrange && urange) {
|
||||
|
@ -1526,12 +1529,15 @@ trans_context(const security_context_t incon, security_context_t *rcon) {
|
|||
if (! ltrans) {
|
||||
ltrans = compute_trans_from_raw(lrange, domain);
|
||||
if (ltrans) {
|
||||
if (add_cache(domain, lrange, ltrans) < 0)
|
||||
if (add_cache(domain, lrange, ltrans) < 0) {
|
||||
free(range);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
ltrans = strdup(lrange);
|
||||
if (! ltrans) {
|
||||
log_error("strdup failed %s", strerror(errno));
|
||||
free(range);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -1541,25 +1547,36 @@ trans_context(const security_context_t incon, security_context_t *rcon) {
|
|||
if (! utrans) {
|
||||
utrans = compute_trans_from_raw(urange, domain);
|
||||
if (utrans) {
|
||||
if (add_cache(domain, urange, utrans) < 0)
|
||||
if (add_cache(domain, urange, utrans) < 0) {
|
||||
free(ltrans);
|
||||
free(range);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
utrans = strdup(urange);
|
||||
if (! utrans) {
|
||||
log_error("strdup failed %s", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
free(ltrans);
|
||||
free(range);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(ltrans, utrans) == 0) {
|
||||
if (asprintf(&trans, "%s", ltrans) < 0) {
|
||||
log_error("asprintf failed %s", strerror(errno));
|
||||
free(utrans);
|
||||
free(ltrans);
|
||||
free(range);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (asprintf(&trans, "%s-%s", ltrans, utrans) < 0) {
|
||||
log_error("asprintf failed %s", strerror(errno));
|
||||
free(utrans);
|
||||
free(ltrans);
|
||||
free(range);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -1629,13 +1646,17 @@ untrans_context(const security_context_t incon, security_context_t *rcon) {
|
|||
if (!canonical) {
|
||||
canonical = compute_trans_from_raw(raw, domain);
|
||||
if (canonical && strcmp(canonical, range))
|
||||
if (add_cache(domain, raw, canonical) < 0)
|
||||
if (add_cache(domain, raw, canonical) < 0) {
|
||||
free(range);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (canonical)
|
||||
free(canonical);
|
||||
if (add_cache(domain, raw, range) < 0)
|
||||
if (add_cache(domain, raw, range) < 0) {
|
||||
free(range);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
log_debug("untrans_context unable to compute raw context %s\n", range);
|
||||
}
|
||||
|
@ -1650,17 +1671,24 @@ untrans_context(const security_context_t incon, security_context_t *rcon) {
|
|||
if (!canonical) {
|
||||
canonical = compute_trans_from_raw(lraw, domain);
|
||||
if (canonical)
|
||||
if (add_cache(domain, lraw, canonical) < 0)
|
||||
if (add_cache(domain, lraw, canonical) < 0) {
|
||||
free(lraw);
|
||||
free(range);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (canonical)
|
||||
free(canonical);
|
||||
if (add_cache(domain, lraw, lrange) < 0)
|
||||
if (add_cache(domain, lraw, lrange) < 0) {
|
||||
free(lraw);
|
||||
free(range);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
lraw = strdup(lrange);
|
||||
if (! lraw) {
|
||||
log_error("strdup failed %s", strerror(errno));
|
||||
free(range);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -1674,17 +1702,27 @@ untrans_context(const security_context_t incon, security_context_t *rcon) {
|
|||
if (!canonical) {
|
||||
canonical = compute_trans_from_raw(uraw, domain);
|
||||
if (canonical)
|
||||
if (add_cache(domain, uraw, canonical) < 0)
|
||||
if (add_cache(domain, uraw, canonical) < 0) {
|
||||
free(uraw);
|
||||
free(lraw);
|
||||
free(range);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (canonical)
|
||||
free(canonical);
|
||||
if (add_cache(domain, uraw, urange) < 0)
|
||||
if (add_cache(domain, uraw, urange) < 0) {
|
||||
free(uraw);
|
||||
free(lraw);
|
||||
free(range);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
uraw = strdup(urange);
|
||||
if (! uraw) {
|
||||
log_error("strdup failed %s", strerror(errno));
|
||||
free(lraw);
|
||||
free(range);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
@ -1694,11 +1732,17 @@ untrans_context(const security_context_t incon, security_context_t *rcon) {
|
|||
if (strcmp(lraw, uraw) == 0) {
|
||||
if (asprintf(&raw, "%s", lraw) < 0) {
|
||||
log_error("asprintf failed %s", strerror(errno));
|
||||
free(uraw);
|
||||
free(lraw);
|
||||
free(range);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
if (asprintf(&raw, "%s-%s", lraw, uraw) < 0) {
|
||||
log_error("asprintf failed %s", strerror(errno));
|
||||
free(uraw);
|
||||
free(lraw);
|
||||
free(range);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.7
|
||||
2.8
|
||||
|
|
|
@ -73,7 +73,6 @@ int main(int argc, char **argv)
|
|||
const char *ofile = NULL;
|
||||
FILE *in = NULL;
|
||||
FILE *out = NULL;
|
||||
int outfd = -1;
|
||||
|
||||
// ignore sigpipe so we can check the return code of write, and potentially
|
||||
// return a more helpful error message
|
||||
|
@ -159,12 +158,6 @@ exit:
|
|||
if (out != NULL) {
|
||||
fclose(out);
|
||||
}
|
||||
if (outfd != -1) {
|
||||
close(outfd);
|
||||
if (rc != 0) {
|
||||
unlink(argv[2]);
|
||||
}
|
||||
}
|
||||
sepol_module_package_free(mod_pkg);
|
||||
|
||||
return rc;
|
||||
|
|
|
@ -44,7 +44,7 @@ specified by that range. If the
|
|||
or
|
||||
.B --preserve-environment
|
||||
option is specified, the shell with the new SELinux context will preserve environment variables,
|
||||
otherwise a new minimal enviroment is created.
|
||||
otherwise a new minimal environment is created.
|
||||
.PP
|
||||
Additional arguments
|
||||
.I ARGS
|
||||
|
|
|
@ -309,7 +309,7 @@ case "$1" in
|
|||
usage
|
||||
exit 1
|
||||
fi
|
||||
> /.autorelabel
|
||||
> /.autorelabel || exit $?
|
||||
[ -z "$FORCEFLAG" ] || echo -n "$FORCEFLAG " >> /.autorelabel
|
||||
[ -z "$BOOTTIME" ] || echo -N $BOOTTIME >> /.autorelabel
|
||||
# Force full relabel if / does not have a label on it
|
||||
|
|
|
@ -309,7 +309,7 @@ static void cmd_line(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
if (!done) { /* defualt, if nothing specified */
|
||||
if (!done) { /* default, if nothing specified */
|
||||
opts->disp_user = TRUE;
|
||||
opts->disp_role = TRUE;
|
||||
opts->disp_type = TRUE;
|
||||
|
@ -646,6 +646,7 @@ static void disp_con(security_context_t scon_raw)
|
|||
disp__con_val("clearance", NULL, &color);
|
||||
if (opts->disp_mlsr)
|
||||
disp__con_val("mls-range", NULL, &color);
|
||||
freecon(scon_trans);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <unistd.h>
|
||||
#include <libgen.h>
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
|
||||
#define PROC_BASE "/proc"
|
||||
#define MAX_CHECK 50
|
||||
|
@ -61,6 +62,7 @@ int cmp_cmdline(const char *command, int pid)
|
|||
int pidof(const char *command)
|
||||
{
|
||||
/* inspired by killall5.c from psmisc */
|
||||
char stackpath[PATH_MAX + 1], *p;
|
||||
DIR *dir;
|
||||
struct dirent *de;
|
||||
int pid, ret = -1, self = getpid();
|
||||
|
@ -70,6 +72,11 @@ int pidof(const char *command)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/* Resolve the path if it contains symbolic links */
|
||||
p = realpath(command, stackpath);
|
||||
if (p)
|
||||
command = p;
|
||||
|
||||
while ((de = readdir(dir)) != NULL) {
|
||||
errno = 0;
|
||||
pid = (int)strtol(de->d_name, (char **)NULL, 10);
|
||||
|
@ -430,6 +437,7 @@ int main(int argc, char **argv)
|
|||
printf("%s\n", context);
|
||||
freecon(context);
|
||||
}
|
||||
free(pc[i]);
|
||||
}
|
||||
|
||||
printf("\nFile contexts:\n");
|
||||
|
@ -472,6 +480,7 @@ int main(int argc, char **argv)
|
|||
freecon(context);
|
||||
}
|
||||
}
|
||||
free(fc[i]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -6,6 +6,14 @@
|
|||
#include "restore.h"
|
||||
#include <glob.h>
|
||||
|
||||
#ifndef GLOB_BRACE
|
||||
#define GLOB_BRACE 0
|
||||
#endif
|
||||
|
||||
#ifndef GLOB_TILDE
|
||||
#define GLOB_TILDE 0
|
||||
#endif
|
||||
|
||||
char **exclude_list;
|
||||
int exclude_count;
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.7
|
||||
2.8
|
||||
|
|
|
@ -86,6 +86,8 @@ class AuditToPolicy:
|
|||
dest="type")
|
||||
parser.add_option("--perm-map", dest="perm_map", help="file name of perm map")
|
||||
parser.add_option("--interface-info", dest="interface_info", help="file name of interface information")
|
||||
parser.add_option("-x", "--xperms", action="store_true", dest="xperms",
|
||||
default=False, help="generate extended permission rules")
|
||||
parser.add_option("--debug", dest="debug", action="store_true", default=False,
|
||||
help="leave generated modules for -M")
|
||||
parser.add_option("-w", "--why", dest="audit2why", action="store_true", default=(os.path.basename(sys.argv[0]) == "audit2why"),
|
||||
|
@ -314,6 +316,10 @@ class AuditToPolicy:
|
|||
ifs, perm_maps = self.__load_interface_info()
|
||||
g.set_gen_refpol(ifs, perm_maps)
|
||||
|
||||
# Extended permissions
|
||||
if self.__options.xperms:
|
||||
g.set_gen_xperms(True)
|
||||
|
||||
# Explanation
|
||||
if self.__options.verbose:
|
||||
g.set_gen_explain(policygen.SHORT_EXPLANATION)
|
||||
|
|
|
@ -85,6 +85,9 @@ This is the default behavior.
|
|||
Generate reference policy using installed macros.
|
||||
This attempts to match denials against interfaces and may be inaccurate.
|
||||
.TP
|
||||
.B "\-x" | "\-\-xperms"
|
||||
Generate extended permission access vector rules
|
||||
.TP
|
||||
.B "\-w" | "\-\-why"
|
||||
Translates SELinux audit messages into a description of why the access was denied
|
||||
|
||||
|
|
|
@ -34,3 +34,4 @@ node=mary.example.com type=AVC msg=audit(1166023021.373:910): avc: denied { re
|
|||
node=lilly.example.com type=AVC_PATH msg=audit(1164783469.561:109): path="/linuxtest/LVT/lvt/log.current"
|
||||
node=lilly.example.com type=SYSCALL msg=audit(1164783469.561:109): arch=14 syscall=11 success=yes exit=0 a0=10120520 a1=10120a78 a2=10120970 a3=118 items=0 ppid=8310 pid=8311 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=(none) comm="smbd" exe="/usr/sbin/smbd" subj=root:system_r:smbd_t:s0 key=(null)
|
||||
node=lilly.example.com type=AVC msg=audit(1164783469.561:109): avc: denied { append } for pid=8311 comm="smbd" name="log.current" dev=dm-0 ino=130930 scontext=root:system_r:smbd_t:s0 tcontext=root:object_r:default_t:s0 tclass=dir
|
||||
node=lilly.example.com type=AVC msg=audit(1164783469.561:109): avc: denied { ioctl } for pid=8311 comm="smbd" name="log.current" ioctlcmd=0x2a scontext=root:system_r:smbd_t:s0 tcontext=root:object_r:default_t:s0 tclass=tcp_socket
|
||||
|
|
|
@ -47,5 +47,14 @@ class Audit2allowTests(unittest.TestCase):
|
|||
print(out, err)
|
||||
self.assertSuccess("audit2why", p.returncode, err)
|
||||
|
||||
def test_xperms(self):
|
||||
"Verify that xperms generation works"
|
||||
p = Popen(['python', './audit2allow', "-x", "-i", "test.log"], stdout=PIPE)
|
||||
out, err = p.communicate()
|
||||
if err:
|
||||
print(out, err)
|
||||
self.assertTrue(b"allowxperm" in out)
|
||||
self.assertSuccess("xperms", p.returncode, err)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
|
|
@ -101,6 +101,8 @@ ftype_to_audit = {"": "any",
|
|||
|
||||
try:
|
||||
import audit
|
||||
#test if audit module is enabled
|
||||
audit.audit_close(audit.audit_open())
|
||||
|
||||
class logger:
|
||||
|
||||
|
@ -138,7 +140,7 @@ try:
|
|||
|
||||
self.log_list = []
|
||||
self.log_change_list = []
|
||||
except:
|
||||
except (OSError, ImportError):
|
||||
class logger:
|
||||
|
||||
def __init__(self):
|
||||
|
@ -593,7 +595,6 @@ class loginRecords(semanageRecords):
|
|||
|
||||
semanage_seuser_key_free(k)
|
||||
semanage_seuser_free(u)
|
||||
self.mylog.log("login", name, sename=sename, serange=serange, serole=",".join(serole), oldserole=",".join(oldserole), oldsename=self.oldsename, oldserange=self.oldserange)
|
||||
|
||||
def add(self, name, sename, serange):
|
||||
try:
|
||||
|
@ -601,7 +602,6 @@ class loginRecords(semanageRecords):
|
|||
self.__add(name, sename, serange)
|
||||
self.commit()
|
||||
except ValueError as error:
|
||||
self.mylog.commit(0)
|
||||
raise error
|
||||
|
||||
def __modify(self, name, sename="", serange=""):
|
||||
|
@ -653,7 +653,6 @@ class loginRecords(semanageRecords):
|
|||
|
||||
semanage_seuser_key_free(k)
|
||||
semanage_seuser_free(u)
|
||||
self.mylog.log("login", name, sename=self.sename, serange=self.serange, serole=",".join(serole), oldserole=",".join(oldserole), oldsename=self.oldsename, oldserange=self.oldserange)
|
||||
|
||||
def modify(self, name, sename="", serange=""):
|
||||
try:
|
||||
|
@ -661,7 +660,6 @@ class loginRecords(semanageRecords):
|
|||
self.__modify(name, sename, serange)
|
||||
self.commit()
|
||||
except ValueError as error:
|
||||
self.mylog.commit(0)
|
||||
raise error
|
||||
|
||||
def __delete(self, name):
|
||||
|
@ -694,8 +692,6 @@ class loginRecords(semanageRecords):
|
|||
rec, self.sename, self.serange = selinux.getseuserbyname("__default__")
|
||||
range, (rc, serole) = userrec.get(self.sename)
|
||||
|
||||
self.mylog.log_remove("login", name, sename=self.sename, serange=self.serange, serole=",".join(serole), oldserole=",".join(oldserole), oldsename=self.oldsename, oldserange=self.oldserange)
|
||||
|
||||
def delete(self, name):
|
||||
try:
|
||||
self.begin()
|
||||
|
@ -703,7 +699,6 @@ class loginRecords(semanageRecords):
|
|||
self.commit()
|
||||
|
||||
except ValueError as error:
|
||||
self.mylog.commit(0)
|
||||
raise error
|
||||
|
||||
def deleteall(self):
|
||||
|
@ -717,7 +712,6 @@ class loginRecords(semanageRecords):
|
|||
self.__delete(semanage_seuser_get_name(u))
|
||||
self.commit()
|
||||
except ValueError as error:
|
||||
self.mylog.commit(0)
|
||||
raise error
|
||||
|
||||
def get_all_logins(self):
|
||||
|
@ -2299,7 +2293,7 @@ class fcontextRecords(semanageRecords):
|
|||
raise ValueError(_("Target %s is not valid. Target is not allowed to end with '/'") % target)
|
||||
|
||||
if substitute != "/" and substitute[-1] == "/":
|
||||
raise ValueError(_("Substiture %s is not valid. Substitute is not allowed to end with '/'") % substitute)
|
||||
raise ValueError(_("Substitute %s is not valid. Substitute is not allowed to end with '/'") % substitute)
|
||||
|
||||
if target in self.equiv.keys():
|
||||
raise ValueError(_("Equivalence class for %s already exists") % target)
|
||||
|
@ -2651,7 +2645,7 @@ class booleanRecords(semanageRecords):
|
|||
self.current_booleans = []
|
||||
ptype = None
|
||||
|
||||
if self.store is None or self.store == ptype:
|
||||
if self.store == "" or self.store == ptype:
|
||||
self.modify_local = True
|
||||
else:
|
||||
self.modify_local = False
|
||||
|
|
|
@ -78,6 +78,7 @@ class AccessVector(util.Comparison):
|
|||
.obj_class - The object class to which access is allowed. [String or None]
|
||||
.perms - The permissions allowed to the object class. [IdSet]
|
||||
.audit_msgs - The audit messages that generated this access vector [List of strings]
|
||||
.xperms - Extended permissions attached to the AV. [Dictionary {operation: xperm set}]
|
||||
"""
|
||||
def __init__(self, init_list=None):
|
||||
if init_list:
|
||||
|
@ -87,9 +88,11 @@ class AccessVector(util.Comparison):
|
|||
self.tgt_type = None
|
||||
self.obj_class = None
|
||||
self.perms = refpolicy.IdSet()
|
||||
self.audit_msgs = []
|
||||
self.type = audit2why.TERULE
|
||||
self.data = []
|
||||
|
||||
self.audit_msgs = []
|
||||
self.type = audit2why.TERULE
|
||||
self.data = []
|
||||
self.xperms = {}
|
||||
# when implementing __eq__ also __hash__ is needed on py2
|
||||
# if object is muttable __hash__ should be None
|
||||
self.__hash__ = None
|
||||
|
@ -131,6 +134,15 @@ class AccessVector(util.Comparison):
|
|||
l.extend(sorted(self.perms))
|
||||
return l
|
||||
|
||||
def merge(self, av):
|
||||
"""Add permissions and extended permissions from AV"""
|
||||
self.perms.update(av.perms)
|
||||
|
||||
for op in av.xperms:
|
||||
if op not in self.xperms:
|
||||
self.xperms[op] = refpolicy.XpermSet()
|
||||
self.xperms[op].extend(av.xperms[op])
|
||||
|
||||
def __str__(self):
|
||||
return self.to_string()
|
||||
|
||||
|
@ -260,28 +272,28 @@ class AccessVectorSet:
|
|||
def add(self, src_type, tgt_type, obj_class, perms, audit_msg=None, avc_type=audit2why.TERULE, data=[]):
|
||||
"""Add an access vector to the set.
|
||||
"""
|
||||
tgt = self.src.setdefault(src_type, { })
|
||||
cls = tgt.setdefault(tgt_type, { })
|
||||
|
||||
if (obj_class, avc_type) in cls:
|
||||
access = cls[obj_class, avc_type]
|
||||
else:
|
||||
access = AccessVector()
|
||||
access.src_type = src_type
|
||||
access.tgt_type = tgt_type
|
||||
access.obj_class = obj_class
|
||||
access.data = data
|
||||
access.type = avc_type
|
||||
cls[obj_class, avc_type] = access
|
||||
av = AccessVector()
|
||||
av.src_type = src_type
|
||||
av.tgt_type = tgt_type
|
||||
av.obj_class = obj_class
|
||||
av.perms = perms
|
||||
av.data = data
|
||||
av.type = avc_type
|
||||
|
||||
access.perms.update(perms)
|
||||
if audit_msg:
|
||||
access.audit_msgs.append(audit_msg)
|
||||
self.add_av(av, audit_msg)
|
||||
|
||||
def add_av(self, av, audit_msg=None):
|
||||
"""Add an access vector to the set."""
|
||||
self.add(av.src_type, av.tgt_type, av.obj_class, av.perms)
|
||||
tgt = self.src.setdefault(av.src_type, { })
|
||||
cls = tgt.setdefault(av.tgt_type, { })
|
||||
|
||||
if (av.obj_class, av.type) in cls:
|
||||
cls[av.obj_class, av.type].merge(av)
|
||||
else:
|
||||
cls[av.obj_class, av.type] = av
|
||||
|
||||
if audit_msg:
|
||||
cls[av.obj_class, av.type].audit_msgs.append(audit_msg)
|
||||
|
||||
def avs_extract_types(avs):
|
||||
types = refpolicy.IdSet()
|
||||
|
|
|
@ -152,6 +152,7 @@ class AVCMessage(AuditMessage):
|
|||
access - list of accesses that were allowed or denied
|
||||
denial - boolean indicating whether this was a denial (True) or granted
|
||||
(False) message.
|
||||
ioctlcmd - ioctl 'request' parameter
|
||||
|
||||
An example audit message generated from the audit daemon looks like (line breaks
|
||||
added):
|
||||
|
@ -178,6 +179,7 @@ class AVCMessage(AuditMessage):
|
|||
self.name = ""
|
||||
self.accesses = []
|
||||
self.denial = True
|
||||
self.ioctlcmd = None
|
||||
self.type = audit2why.TERULE
|
||||
|
||||
def __parse_access(self, recs, start):
|
||||
|
@ -237,6 +239,11 @@ class AVCMessage(AuditMessage):
|
|||
self.exe = fields[1][1:-1]
|
||||
elif fields[0] == "name":
|
||||
self.name = fields[1][1:-1]
|
||||
elif fields[0] == "ioctlcmd":
|
||||
try:
|
||||
self.ioctlcmd = int(fields[1], 16)
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
if not found_src or not found_tgt or not found_class or not found_access:
|
||||
raise ValueError("AVC message in invalid format [%s]\n" % self.message)
|
||||
|
@ -522,13 +529,20 @@ class AuditParser:
|
|||
for avc in self.avc_msgs:
|
||||
if avc.denial != True and only_denials:
|
||||
continue
|
||||
if avc_filter:
|
||||
if avc_filter.filter(avc):
|
||||
av_set.add(avc.scontext.type, avc.tcontext.type, avc.tclass,
|
||||
avc.accesses, avc, avc_type=avc.type, data=avc.data)
|
||||
else:
|
||||
av_set.add(avc.scontext.type, avc.tcontext.type, avc.tclass,
|
||||
avc.accesses, avc, avc_type=avc.type, data=avc.data)
|
||||
|
||||
if not avc_filter or avc_filter.filter(avc):
|
||||
av = access.AccessVector([avc.scontext.type, avc.tcontext.type,
|
||||
avc.tclass] + avc.accesses)
|
||||
av.data = avc.data
|
||||
av.type = avc.type
|
||||
|
||||
if avc.ioctlcmd:
|
||||
xperm_set = refpolicy.XpermSet()
|
||||
xperm_set.add(avc.ioctlcmd)
|
||||
av.xperms["ioctl"] = xperm_set
|
||||
|
||||
av_set.add_av(av, audit_msg=avc)
|
||||
|
||||
return av_set
|
||||
|
||||
class AVCTypeFilter:
|
||||
|
|
|
@ -22,7 +22,7 @@ import re
|
|||
|
||||
# Select the correct location for the development files based on a
|
||||
# path variable (optionally read from a configuration file)
|
||||
class PathChoooser(object):
|
||||
class PathChooser(object):
|
||||
def __init__(self, pathname):
|
||||
self.config = dict()
|
||||
if not os.path.exists(pathname):
|
||||
|
@ -68,10 +68,10 @@ def attribute_info():
|
|||
return data_dir() + "/attribute_info"
|
||||
|
||||
def refpolicy_makefile():
|
||||
chooser = PathChoooser("/etc/selinux/sepolgen.conf")
|
||||
chooser = PathChooser("/etc/selinux/sepolgen.conf")
|
||||
return chooser("Makefile")
|
||||
|
||||
def headers():
|
||||
chooser = PathChoooser("/etc/selinux/sepolgen.conf")
|
||||
chooser = PathChooser("/etc/selinux/sepolgen.conf")
|
||||
return chooser("include")
|
||||
|
||||
|
|
|
@ -50,10 +50,11 @@ class PolicyGenerator:
|
|||
in the form of access vectors.
|
||||
|
||||
It generates allow rules and optionally module require
|
||||
statements and reference policy interfaces. By default
|
||||
only allow rules are generated. The methods .set_gen_refpol
|
||||
and .set_gen_requires turns on interface generation and
|
||||
requires generation respectively.
|
||||
statements, reference policy interfaces, and extended
|
||||
permission access vector rules. By default only allow rules
|
||||
are generated. The methods .set_gen_refpol, .set_gen_requires
|
||||
and .set_gen_xperms turns on interface generation,
|
||||
requires generation, and xperms rules genration respectively.
|
||||
|
||||
PolicyGenerator can also optionally add comments explaining
|
||||
why a particular access was allowed based on the audit
|
||||
|
@ -82,6 +83,7 @@ class PolicyGenerator:
|
|||
self.module = refpolicy.Module()
|
||||
|
||||
self.dontaudit = False
|
||||
self.xperms = False
|
||||
|
||||
self.domains = None
|
||||
def set_gen_refpol(self, if_set=None, perm_maps=None):
|
||||
|
@ -120,6 +122,12 @@ class PolicyGenerator:
|
|||
def set_gen_dontaudit(self, dontaudit):
|
||||
self.dontaudit = dontaudit
|
||||
|
||||
def set_gen_xperms(self, xperms):
|
||||
"""Set whether extended permission access vector rules
|
||||
are generated.
|
||||
"""
|
||||
self.xperms = xperms
|
||||
|
||||
def __set_module_style(self):
|
||||
if self.ifgen:
|
||||
refpolicy = True
|
||||
|
@ -153,51 +161,69 @@ class PolicyGenerator:
|
|||
"""Return the generated module"""
|
||||
return self.module
|
||||
|
||||
def __add_allow_rules(self, avs):
|
||||
for av in avs:
|
||||
rule = refpolicy.AVRule(av)
|
||||
def __add_av_rule(self, av):
|
||||
"""Add access vector rule.
|
||||
"""
|
||||
rule = refpolicy.AVRule(av)
|
||||
|
||||
if self.dontaudit:
|
||||
rule.rule_type = rule.DONTAUDIT
|
||||
rule.comment = ""
|
||||
if self.explain:
|
||||
rule.comment = str(refpolicy.Comment(explain_access(av, verbosity=self.explain)))
|
||||
|
||||
if av.type == audit2why.ALLOW:
|
||||
rule.comment += "\n#!!!! This avc is allowed in the current policy"
|
||||
|
||||
if av.xperms:
|
||||
rule.comment += "\n#!!!! This av rule may have been overridden by an extended permission av rule"
|
||||
|
||||
if av.type == audit2why.DONTAUDIT:
|
||||
rule.comment += "\n#!!!! This avc has a dontaudit rule in the current policy"
|
||||
|
||||
if av.type == audit2why.BOOLEAN:
|
||||
if len(av.data) > 1:
|
||||
rule.comment += "\n#!!!! This avc can be allowed using one of the these booleans:\n# %s" % ", ".join([x[0] for x in av.data])
|
||||
else:
|
||||
rule.comment += "\n#!!!! This avc can be allowed using the boolean '%s'" % av.data[0][0]
|
||||
|
||||
if av.type == audit2why.CONSTRAINT:
|
||||
rule.comment += "\n#!!!! This avc is a constraint violation. You would need to modify the attributes of either the source or target types to allow this access."
|
||||
rule.comment += "\n#Constraint rule: "
|
||||
rule.comment += "\n#\t" + av.data[0]
|
||||
for reason in av.data[1:]:
|
||||
rule.comment += "\n#\tPossible cause is the source %s and target %s are different." % reason
|
||||
|
||||
try:
|
||||
if ( av.type == audit2why.TERULE and
|
||||
"write" in av.perms and
|
||||
( "dir" in av.obj_class or "open" in av.perms )):
|
||||
if not self.domains:
|
||||
self.domains = seinfo(ATTRIBUTE, name="domain")[0]["types"]
|
||||
types=[]
|
||||
|
||||
for i in [x[TCONTEXT] for x in sesearch([ALLOW], {SCONTEXT: av.src_type, CLASS: av.obj_class, PERMS: av.perms})]:
|
||||
if i not in self.domains:
|
||||
types.append(i)
|
||||
if len(types) == 1:
|
||||
rule.comment += "\n#!!!! The source type '%s' can write to a '%s' of the following type:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types))
|
||||
elif len(types) >= 1:
|
||||
rule.comment += "\n#!!!! The source type '%s' can write to a '%s' of the following types:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types))
|
||||
except:
|
||||
pass
|
||||
|
||||
self.module.children.append(rule)
|
||||
|
||||
def __add_ext_av_rules(self, av):
|
||||
"""Add extended permission access vector rules.
|
||||
"""
|
||||
for op in av.xperms.keys():
|
||||
extrule = refpolicy.AVExtRule(av, op)
|
||||
|
||||
if self.dontaudit:
|
||||
rule.rule_type = rule.DONTAUDIT
|
||||
rule.comment = ""
|
||||
if self.explain:
|
||||
rule.comment = str(refpolicy.Comment(explain_access(av, verbosity=self.explain)))
|
||||
if av.type == audit2why.ALLOW:
|
||||
rule.comment += "\n#!!!! This avc is allowed in the current policy"
|
||||
if av.type == audit2why.DONTAUDIT:
|
||||
rule.comment += "\n#!!!! This avc has a dontaudit rule in the current policy"
|
||||
|
||||
if av.type == audit2why.BOOLEAN:
|
||||
if len(av.data) > 1:
|
||||
rule.comment += "\n#!!!! This avc can be allowed using one of the these booleans:\n# %s" % ", ".join([x[0] for x in av.data])
|
||||
else:
|
||||
rule.comment += "\n#!!!! This avc can be allowed using the boolean '%s'" % av.data[0][0]
|
||||
|
||||
if av.type == audit2why.CONSTRAINT:
|
||||
rule.comment += "\n#!!!! This avc is a constraint violation. You would need to modify the attributes of either the source or target types to allow this access."
|
||||
rule.comment += "\n#Constraint rule: "
|
||||
rule.comment += "\n#\t" + av.data[0]
|
||||
for reason in av.data[1:]:
|
||||
rule.comment += "\n#\tPossible cause is the source %s and target %s are different." % reason
|
||||
|
||||
try:
|
||||
if ( av.type == audit2why.TERULE and
|
||||
"write" in av.perms and
|
||||
( "dir" in av.obj_class or "open" in av.perms )):
|
||||
if not self.domains:
|
||||
self.domains = seinfo(ATTRIBUTE, name="domain")[0]["types"]
|
||||
types=[]
|
||||
|
||||
for i in [x[TCONTEXT] for x in sesearch([ALLOW], {SCONTEXT: av.src_type, CLASS: av.obj_class, PERMS: av.perms})]:
|
||||
if i not in self.domains:
|
||||
types.append(i)
|
||||
if len(types) == 1:
|
||||
rule.comment += "\n#!!!! The source type '%s' can write to a '%s' of the following type:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types))
|
||||
elif len(types) >= 1:
|
||||
rule.comment += "\n#!!!! The source type '%s' can write to a '%s' of the following types:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types))
|
||||
except:
|
||||
pass
|
||||
self.module.children.append(rule)
|
||||
extrule.rule_type = extrule.DONTAUDITXPERM
|
||||
|
||||
self.module.children.append(extrule)
|
||||
|
||||
def add_access(self, av_set):
|
||||
"""Add the access from the access vector set to this
|
||||
|
@ -215,7 +241,10 @@ class PolicyGenerator:
|
|||
raw_allow = av_set
|
||||
|
||||
# Generate the raw allow rules from the filtered list
|
||||
self.__add_allow_rules(raw_allow)
|
||||
for av in raw_allow:
|
||||
self.__add_av_rule(av)
|
||||
if self.xperms and av.xperms:
|
||||
self.__add_ext_av_rules(av)
|
||||
|
||||
def add_role_types(self, role_type_set):
|
||||
for role_type in role_type_set:
|
||||
|
|
|
@ -109,6 +109,9 @@ class Node(PolicyBase):
|
|||
def avrules(self):
|
||||
return filter(lambda x: isinstance(x, AVRule), walktree(self))
|
||||
|
||||
def avextrules(self):
|
||||
return filter(lambda x: isinstance(x, AVExtRule), walktree(self))
|
||||
|
||||
def typerules(self):
|
||||
return filter(lambda x: isinstance(x, TypeRule), walktree(self))
|
||||
|
||||
|
@ -284,6 +287,11 @@ class SecurityContext(Leaf):
|
|||
|
||||
Raises ValueError if the string is not parsable as a security context.
|
||||
"""
|
||||
# try to translate the context string to raw form
|
||||
raw = selinux.selinux_trans_to_raw_context(context)
|
||||
if raw[0] == 0:
|
||||
context = raw[1]
|
||||
|
||||
fields = context.split(":")
|
||||
if len(fields) < 3:
|
||||
raise ValueError("context string [%s] not in a valid format" % context)
|
||||
|
@ -347,6 +355,65 @@ class ObjectClass(Leaf):
|
|||
self.name = name
|
||||
self.perms = IdSet()
|
||||
|
||||
class XpermSet():
|
||||
"""Extended permission set.
|
||||
|
||||
This class represents one or more extended permissions
|
||||
represented by numeric values or ranges of values. The
|
||||
.complement attribute is used to specify all permission
|
||||
except those specified.
|
||||
|
||||
Two xperm set can be merged using the .extend() method.
|
||||
"""
|
||||
def __init__(self, complement=False):
|
||||
self.complement = complement
|
||||
self.ranges = []
|
||||
|
||||
def __normalize_ranges(self):
|
||||
"""Ensure that ranges are not overlapping.
|
||||
"""
|
||||
self.ranges.sort()
|
||||
|
||||
i = 0
|
||||
while i < len(self.ranges):
|
||||
while i + 1 < len(self.ranges):
|
||||
if self.ranges[i + 1][0] <= self.ranges[i][1] + 1:
|
||||
self.ranges[i] = (self.ranges[i][0], max(self.ranges[i][1],
|
||||
self.ranges[i + 1][1]))
|
||||
del self.ranges[i + 1]
|
||||
else:
|
||||
break
|
||||
i += 1
|
||||
|
||||
def extend(self, s):
|
||||
"""Add ranges from an xperm set
|
||||
"""
|
||||
self.ranges.extend(s.ranges)
|
||||
self.__normalize_ranges()
|
||||
|
||||
def add(self, minimum, maximum=None):
|
||||
"""Add value of range of values to the xperm set.
|
||||
"""
|
||||
if maximum is None:
|
||||
maximum = minimum
|
||||
self.ranges.append((minimum, maximum))
|
||||
self.__normalize_ranges()
|
||||
|
||||
def to_string(self):
|
||||
if not self.ranges:
|
||||
return ""
|
||||
|
||||
compl = "~ " if self.complement else ""
|
||||
|
||||
# print single value without braces
|
||||
if len(self.ranges) == 1 and self.ranges[0][0] == self.ranges[0][1]:
|
||||
return compl + str(self.ranges[0][0])
|
||||
|
||||
vals = map(lambda x: str(x[0]) if x[0] == x[1] else "%s-%s" % x,
|
||||
self.ranges)
|
||||
|
||||
return "%s{ %s }" % (compl, " ".join(vals))
|
||||
|
||||
# Basic statements
|
||||
|
||||
class TypeAttribute(Leaf):
|
||||
|
@ -467,8 +534,10 @@ class AVRule(Leaf):
|
|||
return "allow"
|
||||
elif self.rule_type == self.DONTAUDIT:
|
||||
return "dontaudit"
|
||||
else:
|
||||
elif self.rule_type == self.AUDITALLOW:
|
||||
return "auditallow"
|
||||
elif self.rule_type == self.NEVERALLOW:
|
||||
return "neverallow"
|
||||
|
||||
def from_av(self, av):
|
||||
"""Add the access from an access vector to this allow
|
||||
|
@ -492,6 +561,65 @@ class AVRule(Leaf):
|
|||
self.tgt_types.to_space_str(),
|
||||
self.obj_classes.to_space_str(),
|
||||
self.perms.to_space_str())
|
||||
|
||||
class AVExtRule(Leaf):
|
||||
"""Extended permission access vector rule.
|
||||
|
||||
The AVExtRule class represents allowxperm, dontauditxperm,
|
||||
auditallowxperm, and neverallowxperm rules.
|
||||
|
||||
The source and target types, and object classes are represented
|
||||
by sets containing strings. The operation is a single string,
|
||||
e.g. 'ioctl'. Extended permissions are represented by an XpermSet.
|
||||
"""
|
||||
ALLOWXPERM = 0
|
||||
DONTAUDITXPERM = 1
|
||||
AUDITALLOWXPERM = 2
|
||||
NEVERALLOWXPERM = 3
|
||||
|
||||
def __init__(self, av=None, op=None, parent=None):
|
||||
Leaf.__init__(self, parent)
|
||||
self.src_types = IdSet()
|
||||
self.tgt_types = IdSet()
|
||||
self.obj_classes = IdSet()
|
||||
self.rule_type = self.ALLOWXPERM
|
||||
self.xperms = XpermSet()
|
||||
self.operation = op
|
||||
if av:
|
||||
self.from_av(av, op)
|
||||
|
||||
def __rule_type_str(self):
|
||||
if self.rule_type == self.ALLOWXPERM:
|
||||
return "allowxperm"
|
||||
elif self.rule_type == self.DONTAUDITXPERM:
|
||||
return "dontauditxperm"
|
||||
elif self.rule_type == self.AUDITALLOWXPERM:
|
||||
return "auditallowxperm"
|
||||
elif self.rule_type == self.NEVERALLOWXPERM:
|
||||
return "neverallowxperm"
|
||||
|
||||
def from_av(self, av, op):
|
||||
self.src_types.add(av.src_type)
|
||||
if av.src_type == av.tgt_type:
|
||||
self.tgt_types.add("self")
|
||||
else:
|
||||
self.tgt_types.add(av.tgt_type)
|
||||
self.obj_classes.add(av.obj_class)
|
||||
self.operation = op
|
||||
self.xperms = av.xperms[op]
|
||||
|
||||
def to_string(self):
|
||||
"""Return a string representation of the rule that is
|
||||
a valid policy language representation (assuming that
|
||||
the types, object class, etc. are valid).
|
||||
"""
|
||||
return "%s %s %s:%s %s %s;" % (self.__rule_type_str(),
|
||||
self.src_types.to_space_str(),
|
||||
self.tgt_types.to_space_str(),
|
||||
self.obj_classes.to_space_str(),
|
||||
self.operation,
|
||||
self.xperms.to_string())
|
||||
|
||||
class TypeRule(Leaf):
|
||||
"""SELinux type rules.
|
||||
|
||||
|
|
|
@ -32,6 +32,7 @@ class TestAccessVector(unittest.TestCase):
|
|||
self.assertEqual(a.obj_class, None)
|
||||
self.assertTrue(isinstance(a.perms, refpolicy.IdSet))
|
||||
self.assertTrue(isinstance(a.audit_msgs, type([])))
|
||||
self.assertTrue(isinstance(a.xperms, type({})))
|
||||
self.assertEqual(len(a.audit_msgs), 0)
|
||||
|
||||
# Construction from a list
|
||||
|
@ -61,6 +62,10 @@ class TestAccessVector(unittest.TestCase):
|
|||
self.assertEqual(a.obj_class, l.obj_class)
|
||||
self.assertEqual(a.perms, l.perms)
|
||||
|
||||
l2 = access.AccessVector()
|
||||
with self.assertRaises(ValueError):
|
||||
l2.from_list(['foo', 'bar', 'file'])
|
||||
|
||||
def test_to_list(self):
|
||||
a = access.AccessVector()
|
||||
a.src_type = "foo"
|
||||
|
@ -145,7 +150,80 @@ class TestAccessVector(unittest.TestCase):
|
|||
|
||||
b.perms = refpolicy.IdSet(["read", "append"])
|
||||
self.assertNotEqual(a, b)
|
||||
|
||||
def test_merge_noxperm(self):
|
||||
"""Test merging two AVs without xperms"""
|
||||
a = access.AccessVector(["foo", "bar", "file", "read", "write"])
|
||||
b = access.AccessVector(["foo", "bar", "file", "append"])
|
||||
|
||||
a.merge(b)
|
||||
self.assertEqual(sorted(list(a.perms)), ["append", "read", "write"])
|
||||
|
||||
def text_merge_xperm1(self):
|
||||
"""Test merging AV that contains xperms with AV that does not"""
|
||||
a = access.AccessVector(["foo", "bar", "file", "read"])
|
||||
b = access.AccessVector(["foo", "bar", "file", "read"])
|
||||
xp = refpolicy.XpermSet()
|
||||
xp.add(42)
|
||||
xp.add(12345)
|
||||
b.xperms = {"ioctl": xp}
|
||||
|
||||
a.merge(b)
|
||||
self.assertEqual(sorted(list(a.perms)), ["append", "read", "write"])
|
||||
self.assertEqual(list(a.xperms.keys()), ["ioctl"])
|
||||
self.assertEqual(a.xperms["ioctl"].to_string(), "{ 42 12345 }")
|
||||
|
||||
def text_merge_xperm2(self):
|
||||
"""Test merging AV that does not contain xperms with AV that does"""
|
||||
a = access.AccessVector(["foo", "bar", "file", "read"])
|
||||
xp = refpolicy.XpermSet()
|
||||
xp.add(42)
|
||||
xp.add(12345)
|
||||
a.xperms = {"ioctl": xp}
|
||||
b = access.AccessVector(["foo", "bar", "file", "read"])
|
||||
|
||||
a.merge(b)
|
||||
self.assertEqual(sorted(list(a.perms)), ["append", "read", "write"])
|
||||
self.assertEqual(list(a.xperms.keys()), ["ioctl"])
|
||||
self.assertEqual(a.xperms["ioctl"].to_string(), "{ 42 12345 }")
|
||||
|
||||
def test_merge_xperm_diff_op(self):
|
||||
"""Test merging two AVs that contain xperms with different operation"""
|
||||
a = access.AccessVector(["foo", "bar", "file", "read"])
|
||||
xp1 = refpolicy.XpermSet()
|
||||
xp1.add(23)
|
||||
a.xperms = {"asdf": xp1}
|
||||
|
||||
b = access.AccessVector(["foo", "bar", "file", "read"])
|
||||
xp2 = refpolicy.XpermSet()
|
||||
xp2.add(42)
|
||||
xp2.add(12345)
|
||||
b.xperms = {"ioctl": xp2}
|
||||
|
||||
a.merge(b)
|
||||
self.assertEqual(list(a.perms), ["read"])
|
||||
self.assertEqual(sorted(list(a.xperms.keys())), ["asdf", "ioctl"])
|
||||
self.assertEqual(a.xperms["asdf"].to_string(), "23")
|
||||
self.assertEqual(a.xperms["ioctl"].to_string(), "{ 42 12345 }")
|
||||
|
||||
def test_merge_xperm_same_op(self):
|
||||
"""Test merging two AVs that contain xperms with same operation"""
|
||||
a = access.AccessVector(["foo", "bar", "file", "read"])
|
||||
xp1 = refpolicy.XpermSet()
|
||||
xp1.add(23)
|
||||
a.xperms = {"ioctl": xp1}
|
||||
|
||||
b = access.AccessVector(["foo", "bar", "file", "read"])
|
||||
xp2 = refpolicy.XpermSet()
|
||||
xp2.add(42)
|
||||
xp2.add(12345)
|
||||
b.xperms = {"ioctl": xp2}
|
||||
|
||||
a.merge(b)
|
||||
self.assertEqual(list(a.perms), ["read"])
|
||||
self.assertEqual(list(a.xperms.keys()), ["ioctl"])
|
||||
self.assertEqual(a.xperms["ioctl"].to_string(), "{ 23 42 12345 }")
|
||||
|
||||
class TestUtilFunctions(unittest.TestCase):
|
||||
def test_is_idparam(self):
|
||||
self.assertTrue(access.is_idparam("$1"))
|
||||
|
@ -260,3 +338,53 @@ class TestAccessVectorSet(unittest.TestCase):
|
|||
b = access.AccessVectorSet()
|
||||
b.from_list(avl)
|
||||
self.assertEqual(len(b), 3)
|
||||
|
||||
def test_add_av_first(self):
|
||||
"""Test adding first AV to the AV set"""
|
||||
avs = access.AccessVectorSet()
|
||||
av = access.AccessVector(['foo', 'bar', 'file', 'read'])
|
||||
|
||||
avs.add_av(av)
|
||||
|
||||
self.assertEqual(avs.to_list(), [['foo', 'bar', 'file', 'read']])
|
||||
|
||||
def test_add_av_second(self):
|
||||
"""Test adding second AV to the AV set with same source and target
|
||||
context and class"""
|
||||
avs = access.AccessVectorSet()
|
||||
av1 = access.AccessVector(['foo', 'bar', 'file', 'read'])
|
||||
av2 = access.AccessVector(['foo', 'bar', 'file', 'write'])
|
||||
|
||||
avs.add_av(av1)
|
||||
avs.add_av(av2)
|
||||
|
||||
self.assertEqual(avs.to_list(), [['foo', 'bar', 'file', 'read',
|
||||
'write']])
|
||||
|
||||
def test_add_av_with_msg(self):
|
||||
"""Test adding audit message"""
|
||||
avs = access.AccessVectorSet()
|
||||
av = access.AccessVector(['foo', 'bar', 'file', 'read'])
|
||||
|
||||
avs.add_av(av, 'test message')
|
||||
|
||||
self.assertEqual(avs.src['foo']['bar']['file', av.type].audit_msgs,
|
||||
['test message'])
|
||||
|
||||
def test_add(self):
|
||||
"""Test adding AV to the set"""
|
||||
s = access.AccessVectorSet()
|
||||
|
||||
def test_add_av(av, audit_msg=None):
|
||||
self.assertEqual(av.src_type, 'foo')
|
||||
self.assertEqual(av.tgt_type, 'bar')
|
||||
self.assertEqual(av.obj_class, 'file')
|
||||
self.assertEqual(list(av.perms), ['read'])
|
||||
self.assertEqual(av.data, 'test data')
|
||||
self.assertEqual(av.type, 42)
|
||||
self.assertEqual(audit_msg, 'test message')
|
||||
|
||||
s.add_av = test_add_av
|
||||
|
||||
s.add("foo", "bar", "file", refpolicy.IdSet(["read"]),
|
||||
audit_msg='test message', avc_type=42, data='test data')
|
||||
|
|
|
@ -56,6 +56,18 @@ type=SYSCALL msg=audit(1162852201.019:1225): arch=40000003 syscall=11 success=ye
|
|||
type=AVC msg=audit(1162852201.019:1225): avc: denied { execute_no_trans } for pid=6974 comm="sh" name="sa1" dev=dm-0 ino=13061698 scontext=system_u:system_r:crond_t:s0-s0:c0.c1023 tcontext=system_u:object_r:lib_t:s0 tclass=file
|
||||
type=AVC msg=audit(1162852201.019:1225): avc: denied { execute } for pid=6974 comm="sh" name="sa1" dev=dm-0 ino=13061698 scontext=system_u:system_r:crond_t:s0-s0:c0.c1023 tcontext=system_u:object_r:lib_t:s0 tclass=file"""
|
||||
|
||||
xperms1 = """type=AVC msg=audit(1516626657.910:4461): avc: denied { ioctl } for pid=4310 comm="test" path="/root/test" ino=8619937 ioctlcmd=0x42 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=file permissive=0
|
||||
"""
|
||||
xperms2 = """type=AVC msg=audit(1516626657.910:4461): avc: denied { ioctl } for pid=4310 comm="test" path="/root/test" ino=8619937 ioctlcmd=0x42 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=file permissive=0
|
||||
type=AVC msg=audit(1516626657.910:4461): avc: denied { ioctl } for pid=4310 comm="test" path="/root/test" ino=8619937 ioctlcmd=0x1234 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=file permissive=0
|
||||
type=AVC msg=audit(1516626657.910:4461): avc: denied { ioctl } for pid=4310 comm="test" path="/root/test" ino=8619937 ioctlcmd=0xdead scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=file permissive=0
|
||||
type=AVC msg=audit(1516626657.910:4461): avc: denied { getattr } for pid=4310 comm="test" path="/root/test" ino=8619937 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=dir permissive=0
|
||||
"""
|
||||
xperms_invalid = """type=AVC msg=audit(1516626657.910:4461): avc: denied { ioctl } for pid=4310 comm="test" path="/root/test" ino=8619937 ioctlcmd=asdf scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=file permissive=0
|
||||
"""
|
||||
xperms_without = """type=AVC msg=audit(1516626657.910:4461): avc: denied { ioctl } for pid=4310 comm="test" path="/root/test" ino=8619937 scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:object_r:test_file_t:s0 tclass=file permissive=0
|
||||
"""
|
||||
|
||||
class TestAVCMessage(unittest.TestCase):
|
||||
def test_defs(self):
|
||||
avc = sepolgen.audit.AVCMessage(audit1)
|
||||
|
@ -64,6 +76,7 @@ class TestAVCMessage(unittest.TestCase):
|
|||
self.assertEqual(avc.tcontext, sc)
|
||||
self.assertEqual(avc.tclass, "")
|
||||
self.assertEqual(avc.accesses, [])
|
||||
self.assertEqual(avc.ioctlcmd, None)
|
||||
|
||||
def test_granted(self):
|
||||
avc = sepolgen.audit.AVCMessage(granted1)
|
||||
|
@ -84,6 +97,29 @@ class TestAVCMessage(unittest.TestCase):
|
|||
|
||||
self.assertEqual(avc.denial, False)
|
||||
|
||||
def test_xperms(self):
|
||||
"""Test that the ioctlcmd field is parsed"""
|
||||
avc = sepolgen.audit.AVCMessage(xperms1)
|
||||
recs = xperms1.split()
|
||||
avc.from_split_string(recs)
|
||||
|
||||
self.assertEqual(avc.ioctlcmd, 66)
|
||||
|
||||
def test_xperms_invalid(self):
|
||||
"""Test message with invalid value in the ioctlcmd field"""
|
||||
avc = sepolgen.audit.AVCMessage(xperms_invalid)
|
||||
recs = xperms_invalid.split()
|
||||
avc.from_split_string(recs)
|
||||
|
||||
self.assertIsNone(avc.ioctlcmd)
|
||||
|
||||
def test_xperms_without(self):
|
||||
"""Test message without the ioctlcmd field"""
|
||||
avc = sepolgen.audit.AVCMessage(xperms_without)
|
||||
recs = xperms_without.split()
|
||||
avc.from_split_string(recs)
|
||||
|
||||
self.assertIsNone(avc.ioctlcmd)
|
||||
|
||||
def test_from_split_string(self):
|
||||
# syslog message
|
||||
|
@ -172,6 +208,20 @@ class TestAuditParser(unittest.TestCase):
|
|||
self.assertEqual(len(a.invalid_msgs), 0)
|
||||
self.assertEqual(len(a.policy_load_msgs), 0)
|
||||
|
||||
def test_parse_xperms(self):
|
||||
""" Test that correct access vectors are generated from a set of AVC
|
||||
denial messages. """
|
||||
a = sepolgen.audit.AuditParser()
|
||||
a.parse_string(xperms2)
|
||||
av_set = a.to_access()
|
||||
|
||||
self.assertEqual(len(av_set), 2)
|
||||
av_list = list(sorted(av_set))
|
||||
self.assertEqual(av_list[0].xperms, {})
|
||||
self.assertEqual(list(av_list[1].xperms), ["ioctl"])
|
||||
self.assertEqual(av_list[1].xperms["ioctl"].ranges, [(66,66),
|
||||
(4660,4660), (57005,57005)])
|
||||
|
||||
class TestGeneration(unittest.TestCase):
|
||||
def test_generation(self):
|
||||
parser = sepolgen.audit.AuditParser()
|
||||
|
|
|
@ -19,13 +19,117 @@
|
|||
|
||||
import unittest
|
||||
import sepolgen.policygen as policygen
|
||||
import sepolgen.access as access
|
||||
import sepolgen.refpolicy as refpolicy
|
||||
|
||||
class PolicyGenerator(unittest.TestCase):
|
||||
def __init__(self):
|
||||
g = policygen.PolicyGenerator()
|
||||
|
||||
class TestPolicyGenerator(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.g = policygen.PolicyGenerator()
|
||||
|
||||
def test_init(self):
|
||||
""" Test that extended permission AV rules are not generated by
|
||||
default. """
|
||||
self.assertFalse(self.g.xperms)
|
||||
|
||||
def test_set_gen_xperms(self):
|
||||
""" Test turning on and off generating of extended permission
|
||||
AV rules. """
|
||||
self.g.set_gen_xperms(True)
|
||||
self.assertTrue(self.g.xperms)
|
||||
self.g.set_gen_xperms(False)
|
||||
self.assertFalse(self.g.xperms)
|
||||
|
||||
def test_av_rules(self):
|
||||
""" Test generating of AV rules from access vectors. """
|
||||
av1 = access.AccessVector(["test_src_t", "test_tgt_t", "file", "ioctl"])
|
||||
av2 = access.AccessVector(["test_src_t", "test_tgt_t", "file", "open"])
|
||||
av3 = access.AccessVector(["test_src_t", "test_tgt_t", "file", "read"])
|
||||
|
||||
avs = access.AccessVectorSet()
|
||||
avs.add_av(av1)
|
||||
avs.add_av(av2)
|
||||
avs.add_av(av3)
|
||||
|
||||
self.g.add_access(avs)
|
||||
|
||||
self.assertEqual(len(self.g.module.children), 1)
|
||||
r = self.g.module.children[0]
|
||||
self.assertIsInstance(r, refpolicy.AVRule)
|
||||
self.assertEqual(r.to_string(),
|
||||
"allow test_src_t test_tgt_t:file { ioctl open read };")
|
||||
|
||||
def test_ext_av_rules(self):
|
||||
""" Test generating of extended permission AV rules from access
|
||||
vectors. """
|
||||
self.g.set_gen_xperms(True)
|
||||
|
||||
av1 = access.AccessVector(["test_src_t", "test_tgt_t", "file", "ioctl"])
|
||||
av1.xperms['ioctl'] = refpolicy.XpermSet()
|
||||
av1.xperms['ioctl'].add(42)
|
||||
av2 = access.AccessVector(["test_src_t", "test_tgt_t", "file", "ioctl"])
|
||||
av2.xperms['ioctl'] = refpolicy.XpermSet()
|
||||
av2.xperms['ioctl'].add(1234)
|
||||
av3 = access.AccessVector(["test_src_t", "test_tgt_t", "dir", "ioctl"])
|
||||
av3.xperms['ioctl'] = refpolicy.XpermSet()
|
||||
av3.xperms['ioctl'].add(2345)
|
||||
|
||||
avs = access.AccessVectorSet()
|
||||
avs.add_av(av1)
|
||||
avs.add_av(av2)
|
||||
avs.add_av(av3)
|
||||
|
||||
self.g.add_access(avs)
|
||||
|
||||
self.assertEqual(len(self.g.module.children), 4)
|
||||
|
||||
# we cannot sort the rules, so find all rules manually
|
||||
av_rule1 = av_rule2 = av_ext_rule1 = av_ext_rule2 = None
|
||||
|
||||
for r in self.g.module.children:
|
||||
if isinstance(r, refpolicy.AVRule):
|
||||
if 'file' in r.obj_classes:
|
||||
av_rule1 = r
|
||||
else:
|
||||
av_rule2 = r
|
||||
elif isinstance(r, refpolicy.AVExtRule):
|
||||
if 'file' in r.obj_classes:
|
||||
av_ext_rule1 = r
|
||||
else:
|
||||
av_ext_rule2 = r
|
||||
else:
|
||||
self.fail("Unexpected rule type '%s'" % type(r))
|
||||
|
||||
# check that all rules are present
|
||||
self.assertNotIn(None, (av_rule1, av_rule2, av_ext_rule1, av_ext_rule2))
|
||||
|
||||
self.assertEqual(av_rule1.rule_type, av_rule1.ALLOW)
|
||||
self.assertEqual(av_rule1.src_types, {"test_src_t"})
|
||||
self.assertEqual(av_rule1.tgt_types, {"test_tgt_t"})
|
||||
self.assertEqual(av_rule1.obj_classes, {"file"})
|
||||
self.assertEqual(av_rule1.perms, {"ioctl"})
|
||||
|
||||
self.assertEqual(av_ext_rule1.rule_type, av_ext_rule1.ALLOWXPERM)
|
||||
self.assertEqual(av_ext_rule1.src_types, {"test_src_t"})
|
||||
self.assertEqual(av_ext_rule1.tgt_types, {"test_tgt_t"})
|
||||
self.assertEqual(av_ext_rule1.obj_classes, {"file"})
|
||||
self.assertEqual(av_ext_rule1.operation, "ioctl")
|
||||
xp1 = refpolicy.XpermSet()
|
||||
xp1.add(42)
|
||||
xp1.add(1234)
|
||||
self.assertEqual(av_ext_rule1.xperms.ranges, xp1.ranges)
|
||||
|
||||
self.assertEqual(av_rule2.rule_type, av_rule2.ALLOW)
|
||||
self.assertEqual(av_rule2.src_types, {"test_src_t"})
|
||||
self.assertEqual(av_rule2.tgt_types, {"test_tgt_t"})
|
||||
self.assertEqual(av_rule2.obj_classes, {"dir"})
|
||||
self.assertEqual(av_rule2.perms, {"ioctl"})
|
||||
|
||||
self.assertEqual(av_ext_rule2.rule_type, av_ext_rule2.ALLOWXPERM)
|
||||
self.assertEqual(av_ext_rule2.src_types, {"test_src_t"})
|
||||
self.assertEqual(av_ext_rule2.tgt_types, {"test_tgt_t"})
|
||||
self.assertEqual(av_ext_rule2.obj_classes, {"dir"})
|
||||
self.assertEqual(av_ext_rule2.operation, "ioctl")
|
||||
xp2 = refpolicy.XpermSet()
|
||||
xp2.add(2345)
|
||||
self.assertEqual(av_ext_rule2.xperms.ranges, xp2.ranges)
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
import unittest
|
||||
import sepolgen.refpolicy as refpolicy
|
||||
import sepolgen.access as access
|
||||
import selinux
|
||||
|
||||
class TestIdSet(unittest.TestCase):
|
||||
|
@ -33,6 +34,74 @@ class TestIdSet(unittest.TestCase):
|
|||
s.add("read")
|
||||
self.assertEqual(s.to_space_str(), "read")
|
||||
|
||||
class TestXpermSet(unittest.TestCase):
|
||||
def test_init(self):
|
||||
""" Test that all atttributes are correctly initialized. """
|
||||
s1 = refpolicy.XpermSet()
|
||||
self.assertEqual(s1.complement, False)
|
||||
self.assertEqual(s1.ranges, [])
|
||||
|
||||
s2 = refpolicy.XpermSet(True)
|
||||
self.assertEqual(s2.complement, True)
|
||||
self.assertEqual(s2.ranges, [])
|
||||
|
||||
def test_normalize_ranges(self):
|
||||
""" Test that ranges that are overlapping or neighboring are correctly
|
||||
merged into one range. """
|
||||
s = refpolicy.XpermSet()
|
||||
s.ranges = [(1, 7), (5, 10), (100, 110), (102, 107), (200, 205),
|
||||
(205, 210), (300, 305), (306, 310), (400, 405), (407, 410),
|
||||
(500, 502), (504, 508), (500, 510)]
|
||||
s._XpermSet__normalize_ranges()
|
||||
|
||||
i = 0
|
||||
r = list(sorted(s.ranges))
|
||||
while i < len(r) - 1:
|
||||
# check that range low bound is less than equal than the upper bound
|
||||
self.assertLessEqual(r[i][0], r[i][1])
|
||||
# check that two ranges are not overlapping or neighboring
|
||||
self.assertGreater(r[i + 1][0] - r[i][1], 1)
|
||||
i += 1
|
||||
|
||||
def test_add(self):
|
||||
""" Test adding new values or ranges to the set. """
|
||||
s = refpolicy.XpermSet()
|
||||
s.add(1, 7)
|
||||
s.add(5, 10)
|
||||
s.add(42)
|
||||
self.assertEqual(s.ranges, [(1,10), (42,42)])
|
||||
|
||||
def test_extend(self):
|
||||
""" Test adding ranges from another XpermSet object. """
|
||||
a = refpolicy.XpermSet()
|
||||
a.add(1, 7)
|
||||
|
||||
b = refpolicy.XpermSet()
|
||||
b.add(5, 10)
|
||||
|
||||
a.extend(b)
|
||||
self.assertEqual(a.ranges, [(1,10)])
|
||||
|
||||
def test_to_string(self):
|
||||
""" Test printing the values to a string. """
|
||||
a = refpolicy.XpermSet()
|
||||
a.complement = False
|
||||
self.assertEqual(a.to_string(), "")
|
||||
a.complement = True
|
||||
self.assertEqual(a.to_string(), "")
|
||||
a.add(1234)
|
||||
self.assertEqual(a.to_string(), "~ 1234")
|
||||
a.complement = False
|
||||
self.assertEqual(a.to_string(), "1234")
|
||||
a.add(2345)
|
||||
self.assertEqual(a.to_string(), "{ 1234 2345 }")
|
||||
a.complement = True
|
||||
self.assertEqual(a.to_string(), "~ { 1234 2345 }")
|
||||
a.add(42,64)
|
||||
self.assertEqual(a.to_string(), "~ { 42-64 1234 2345 }")
|
||||
a.complement = False
|
||||
self.assertEqual(a.to_string(), "{ 42-64 1234 2345 }")
|
||||
|
||||
class TestSecurityContext(unittest.TestCase):
|
||||
def test_init(self):
|
||||
sc = refpolicy.SecurityContext()
|
||||
|
@ -110,6 +179,76 @@ class TestAVRule(unittest.TestCase):
|
|||
b.sort()
|
||||
self.assertEqual(a, b)
|
||||
|
||||
class TestAVExtRule(unittest.TestCase):
|
||||
def test_init(self):
|
||||
""" Test initialization of attributes """
|
||||
a = refpolicy.AVExtRule()
|
||||
self.assertEqual(a.rule_type, a.ALLOWXPERM)
|
||||
self.assertIsInstance(a.src_types, set)
|
||||
self.assertIsInstance(a.tgt_types, set)
|
||||
self.assertIsInstance(a.obj_classes, set)
|
||||
self.assertIsNone(a.operation)
|
||||
self.assertIsInstance(a.xperms, refpolicy.XpermSet)
|
||||
|
||||
def test_rule_type_str(self):
|
||||
""" Test strings returned by __rule_type_str() """
|
||||
a = refpolicy.AVExtRule()
|
||||
self.assertEqual(a._AVExtRule__rule_type_str(), "allowxperm")
|
||||
a.rule_type = a.ALLOWXPERM
|
||||
self.assertEqual(a._AVExtRule__rule_type_str(), "allowxperm")
|
||||
a.rule_type = a.DONTAUDITXPERM
|
||||
self.assertEqual(a._AVExtRule__rule_type_str(), "dontauditxperm")
|
||||
a.rule_type = a.NEVERALLOWXPERM
|
||||
self.assertEqual(a._AVExtRule__rule_type_str(), "neverallowxperm")
|
||||
a.rule_type = a.AUDITALLOWXPERM
|
||||
self.assertEqual(a._AVExtRule__rule_type_str(), "auditallowxperm")
|
||||
a.rule_type = 42
|
||||
self.assertIsNone(a._AVExtRule__rule_type_str())
|
||||
|
||||
def test_from_av(self):
|
||||
""" Test creating the rule from an access vector. """
|
||||
av = access.AccessVector(["foo", "bar", "file", "ioctl"])
|
||||
xp = refpolicy.XpermSet()
|
||||
av.xperms = { "ioctl": xp }
|
||||
|
||||
a = refpolicy.AVExtRule()
|
||||
|
||||
a.from_av(av, "ioctl")
|
||||
self.assertEqual(a.src_types, {"foo"})
|
||||
self.assertEqual(a.tgt_types, {"bar"})
|
||||
self.assertEqual(a.obj_classes, {"file"})
|
||||
self.assertEqual(a.operation, "ioctl")
|
||||
self.assertIs(a.xperms, xp)
|
||||
|
||||
def test_from_av_self(self):
|
||||
""" Test creating the rule from an access vector that has same
|
||||
source and target context. """
|
||||
av = access.AccessVector(["foo", "foo", "file", "ioctl"])
|
||||
xp = refpolicy.XpermSet()
|
||||
av.xperms = { "ioctl": xp }
|
||||
|
||||
a = refpolicy.AVExtRule()
|
||||
|
||||
a.from_av(av, "ioctl")
|
||||
self.assertEqual(a.src_types, {"foo"})
|
||||
self.assertEqual(a.tgt_types, {"self"})
|
||||
self.assertEqual(a.obj_classes, {"file"})
|
||||
self.assertEqual(a.operation, "ioctl")
|
||||
self.assertIs(a.xperms, xp)
|
||||
|
||||
def test_to_string(self):
|
||||
""" Test printing the rule to a string. """
|
||||
a = refpolicy.AVExtRule()
|
||||
a._AVExtRule__rule_type_str = lambda: "first"
|
||||
a.src_types.to_space_str = lambda: "second"
|
||||
a.tgt_types.to_space_str = lambda: "third"
|
||||
a.obj_classes.to_space_str = lambda: "fourth"
|
||||
a.operation = "fifth"
|
||||
a.xperms.to_string = lambda: "seventh"
|
||||
|
||||
self.assertEqual(a.to_string(),
|
||||
"first second third:fourth fifth seventh;")
|
||||
|
||||
class TestTypeRule(unittest.TestCase):
|
||||
def test_init(self):
|
||||
a = refpolicy.TypeRule()
|
||||
|
|
|
@ -31,7 +31,7 @@ List all interfaces
|
|||
List all domains with SELinux user role interface
|
||||
.TP
|
||||
.I \-v, \-\-verbose
|
||||
Display extended information about the interface including parameters and desctiprion if available.
|
||||
Display extended information about the interface including parameters and description if available.
|
||||
|
||||
.SH "AUTHOR"
|
||||
This man page was written by Daniel Walsh <dwalsh@redhat.com>
|
||||
|
|
|
@ -10,4 +10,4 @@ SELinux Systems can boot in three different modes.
|
|||
|
||||
You can use this screen to change the enforcing mode.
|
||||
|
||||
Note if you disable SELinux, you will need to to reboot, to turn it off. Also the next time you turn SELinux on, a full system relabel will be performed.
|
||||
Note if you disable SELinux, you will need to reboot, to turn it off. Also the next time you turn SELinux on, a full system relabel will be performed.
|
||||
|
|
|
@ -1283,7 +1283,7 @@ USERNAME ALL=(ALL) ROLE=%(user)s_r TYPE=%(user)s_t COMMAND
|
|||
.br
|
||||
sudo will run COMMAND as staff_u:%(user)s_r:%(user)s_t:LEVEL
|
||||
|
||||
When using a a non login role, you need to setup SELinux so that your SELinux user can reach %(user)s_r role.
|
||||
When using a non login role, you need to setup SELinux so that your SELinux user can reach %(user)s_r role.
|
||||
|
||||
Execute the following to see all of the assigned SELinux roles:
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ DBUSSERVICEDIR = $(PREFIX)/share/dbus-1/services
|
|||
SYSTEMDDIR ?= $(PREFIX)/lib/systemd
|
||||
|
||||
autostart_DATA = sealertauto.desktop
|
||||
INITDIR ?= $(DESTDIR)/etc/rc.d/init.d
|
||||
SELINUXDIR = $(DESTDIR)/etc/selinux
|
||||
INITDIR ?= /etc/rc.d/init.d
|
||||
SELINUXDIR = /etc/selinux
|
||||
|
||||
DBUSFLAGS = -DHAVE_DBUS $(shell $(PKG_CONFIG) --cflags dbus-glib-1)
|
||||
DBUSLIB = $(shell $(PKG_CONFIG) --libs dbus-glib-1)
|
||||
|
@ -42,11 +42,11 @@ install: all
|
|||
-mkdir -p $(DESTDIR)$(SBINDIR)
|
||||
install -m 755 restorecond $(DESTDIR)$(SBINDIR)
|
||||
install -m 644 restorecond.8 $(DESTDIR)$(MANDIR)/man8
|
||||
-mkdir -p $(INITDIR)
|
||||
install -m 755 restorecond.init $(INITDIR)/restorecond
|
||||
-mkdir -p $(SELINUXDIR)
|
||||
install -m 644 restorecond.conf $(SELINUXDIR)/restorecond.conf
|
||||
install -m 644 restorecond_user.conf $(SELINUXDIR)/restorecond_user.conf
|
||||
-mkdir -p $(DESTDIR)$(INITDIR)
|
||||
install -m 755 restorecond.init $(DESTDIR)$(INITDIR)/restorecond
|
||||
-mkdir -p $(DESTDIR)$(SELINUXDIR)
|
||||
install -m 644 restorecond.conf $(DESTDIR)$(SELINUXDIR)/restorecond.conf
|
||||
install -m 644 restorecond_user.conf $(DESTDIR)$(SELINUXDIR)/restorecond_user.conf
|
||||
-mkdir -p $(DESTDIR)$(AUTOSTARTDIR)
|
||||
install -m 644 restorecond.desktop $(DESTDIR)$(AUTOSTARTDIR)/restorecond.desktop
|
||||
-mkdir -p $(DESTDIR)$(DBUSSERVICEDIR)
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.7
|
||||
2.8
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
/*
|
||||
* Note that the restorecond(8) service build links with these functions.
|
||||
* Therefore any changes here should also be tested against that utility.
|
||||
*/
|
||||
|
||||
#include "restore.h"
|
||||
#include <glob.h>
|
||||
|
||||
#ifndef GLOB_TILDE
|
||||
#define GLOB_TILDE 0
|
||||
#endif
|
||||
|
||||
#ifndef GLOB_BRACE
|
||||
#define GLOB_BRACE 0
|
||||
#endif
|
||||
|
||||
char **exclude_list;
|
||||
int exclude_count;
|
||||
|
||||
|
|
|
@ -105,6 +105,7 @@ static int write_pid_file(void)
|
|||
}
|
||||
if (write(pidfd, val, (unsigned int)len) != len) {
|
||||
syslog(LOG_ERR, "Unable to write to pidfile (%s)", strerror(errno));
|
||||
close(pidfd);
|
||||
return 1;
|
||||
}
|
||||
close(pidfd);
|
||||
|
|
|
@ -20,6 +20,14 @@
|
|||
#include "stringslist.h"
|
||||
#include "utmpwatcher.h"
|
||||
|
||||
#ifndef GLOB_TILDE
|
||||
#define GLOB_TILDE 0
|
||||
#endif
|
||||
|
||||
#ifndef GLOB_BRACE
|
||||
#define GLOB_BRACE 0
|
||||
#endif
|
||||
|
||||
/* size of the event structure, not counting name */
|
||||
#define EVENT_SIZE (sizeof (struct inotify_event))
|
||||
/* reasonable guess as to size of 1024 events */
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.7
|
||||
2.8
|
||||
|
|
|
@ -16,7 +16,7 @@ within the specified context, using the alternate home directory and /tmp direct
|
|||
Alternate homedir to be used by the application. Homedir must be owned by the user.
|
||||
.TP
|
||||
\fB\-t\ tmpdir
|
||||
Use alternate tempory directory to mount on /tmp. tmpdir must be owned by the user.
|
||||
Use alternate temporary directory to mount on /tmp. tmpdir must be owned by the user.
|
||||
.TP
|
||||
\fB\-C --capabilities\fR
|
||||
Allow apps executed within the namespace to use capabilities. Default is no capabilities.
|
||||
|
|
1
scripts/.gitignore
vendored
Normal file
1
scripts/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/output-scan-build/
|
33
scripts/run-scan-build
Executable file
33
scripts/run-scan-build
Executable file
|
@ -0,0 +1,33 @@
|
|||
#!/bin/sh
|
||||
# Run clang's static analyzer (scan-build) and record its output in output-scan-build/
|
||||
|
||||
# Ensure the current directory is where this script is
|
||||
cd "$(dirname -- "$0")" || exit $?
|
||||
|
||||
OUTPUTDIR="$(pwd)/output-scan-build"
|
||||
|
||||
# Display the commands which are run, and make sure they succeed
|
||||
set -x -e
|
||||
|
||||
# Use a temporary directory as an installation directory, if $DESTDIR is not set
|
||||
if [ -z "$DESTDIR" ] ; then
|
||||
DESTDIR="$(mktemp --tmpdir -d scan-build-destdir-XXXXXXXXXX)"
|
||||
fi
|
||||
|
||||
# Make sure to use the newly-installed libraries when running tests
|
||||
export LD_LIBRARY_PATH="$DESTDIR/usr/lib:$DESTDIR/lib"
|
||||
export PATH="$DESTDIR/usr/sbin:$DESTDIR/usr/bin:$DESTDIR/sbin:$DESTDIR/bin:$PATH"
|
||||
export PYTHONPATH="$DESTDIR$(${PYTHON:-python} -c "from distutils.sysconfig import *;print(get_python_lib(prefix='/usr'))")"
|
||||
export RUBYLIB="$DESTDIR/$(${RUBY:-ruby} -e 'puts RbConfig::CONFIG["vendorlibdir"]'):$DESTDIR/$(${RUBY:-ruby} -e 'puts RbConfig::CONFIG["vendorarchdir"]')"
|
||||
|
||||
# Build and analyze
|
||||
make -C .. CC=clang clean distclean -j"$(nproc)"
|
||||
scan-build -analyze-headers -o "$OUTPUTDIR" make -C .. CC=clang DESTDIR="$DESTDIR" install install-pywrap install-rubywrap all test
|
||||
|
||||
# Reduce the verbosity in order to keep the message from scan-build saying
|
||||
# "scan-build: Run 'scan-view /.../output-scan-build/2018-...' to examine bug reports.
|
||||
set +x
|
||||
|
||||
# Remove the destination directory without using "rm -rf"
|
||||
chmod u+w "$DESTDIR/usr/bin/newrole"
|
||||
rm -r "$DESTDIR"
|
|
@ -58,6 +58,7 @@ clean:
|
|||
rm -f file_contexts
|
||||
rm -f $(SECILC_MANPAGE)
|
||||
rm -f $(SECIL2CONF_MANPAGE)
|
||||
$(MAKE) -C docs clean
|
||||
|
||||
relabel:
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.7
|
||||
2.8
|
||||
|
|
|
@ -1 +1 @@
|
|||
2.7
|
||||
2.8
|
||||
|
|
Loading…
Reference in a new issue