diff --git a/BUILD.gn b/BUILD.gn index 758f1070db8b0003184713601205e3ce95601f6a..5395025b35f11cdc34b87ff0100a523892a60064 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -129,7 +129,7 @@ ohos_shared_library("libsepol") { "ramdisk", "updater", ] - license_file = "$LIBSEPOL_ROOT_DIR/COPYING" + license_file = "$LIBSEPOL_ROOT_DIR/LICENSE" part_name = "selinux" subsystem_name = "thirdparty" } @@ -143,7 +143,7 @@ ohos_executable("chkcon") { "-D_GNU_SOURCE", "-w", ] - license_file = "$LIBSEPOL_ROOT_DIR/COPYING" + license_file = "$LIBSEPOL_ROOT_DIR/LICENSE" part_name = "selinux" subsystem_name = "thirdparty" } @@ -202,6 +202,12 @@ ohos_shared_library("libselinux") { "$LIBSELINUX_ROOT_DIR/src/sha1.c", "$LIBSELINUX_ROOT_DIR/src/stringrep.c", ] + + if (current_toolchain == host_toolchain) { + # host build + sources += [ "$LIBSELINUX_ROOT_DIR/src/selinux_internal.c" ] + } + include_dirs = [ "$LIBSELINUX_ROOT_DIR/include", "$LIBPCRE2_ROOT_DIR/pcre2/src", @@ -438,7 +444,7 @@ ohos_executable("secilc") { "-Werror", "-Wshadow", ] - license_file = "$LIBSEPOL_ROOT_DIR/COPYING" + license_file = "$LIBSEPOL_ROOT_DIR/LICENSE" part_name = "selinux" subsystem_name = "thirdparty" } diff --git a/OAT.xml b/OAT.xml index a2f0c6ec60ac062146ee6de78dcae96643613e3d..f8a174c1525d0f0fea369e69bb4d5ac830831335 100644 --- a/OAT.xml +++ b/OAT.xml @@ -26,7 +26,7 @@ - + @@ -36,7 +36,7 @@ - + diff --git a/checkpolicy/COPYING b/checkpolicy/LICENSE similarity index 100% rename from checkpolicy/COPYING rename to checkpolicy/LICENSE diff --git a/checkpolicy/VERSION b/checkpolicy/VERSION index 2f4b60750dc3500b0e4cf08f316a960a7ca42b40..5a958026daa3208cb329c403433beb56abd5c036 100644 --- a/checkpolicy/VERSION +++ b/checkpolicy/VERSION @@ -1 +1 @@ -3.4 +3.5 diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c index 926ce72c1cfdd56bea93ca2f8e51e98e4155aa75..48c312612b0bcfe46523217014cb26094e0844e6 100644 --- a/checkpolicy/checkpolicy.c +++ b/checkpolicy/checkpolicy.c @@ -1148,12 +1148,11 @@ int main(int argc, char **argv) FGETS(ans, sizeof(ans), stdin); ans[strlen(ans) - 1] = 0; - name = malloc((strlen(ans) + 1) * sizeof(char)); + name = strdup(ans); if (name == NULL) { - fprintf(stderr, "couldn't malloc string.\n"); + fprintf(stderr, "couldn't strdup string.\n"); break; } - strcpy(name, ans); printf("state? "); FGETS(ans, sizeof(ans), stdin); @@ -1296,12 +1295,11 @@ int main(int argc, char **argv) FGETS(ans, sizeof(ans), stdin); ans[strlen(ans) - 1] = 0; - name = malloc((strlen(ans) + 1) * sizeof(char)); + name = strdup(ans); if (!name) { - fprintf(stderr, "couldn't malloc string.\n"); + fprintf(stderr, "couldn't strdup string.\n"); break; } - strcpy(name, ans); printf("port? "); FGETS(ans, sizeof(ans), stdin); diff --git a/checkpolicy/module_compiler.c b/checkpolicy/module_compiler.c index 129650fa24372b4f5734cce4d2cc9dbccfb42b2b..3188af892aa3909ad5a842e40b4c2799b52fcab2 100644 --- a/checkpolicy/module_compiler.c +++ b/checkpolicy/module_compiler.c @@ -851,6 +851,14 @@ int require_class(int pass) free(perm_id); return -1; } + if (datum->permissions.nprim >= PERM_SYMTAB_SIZE) { + yyerror2("Class %s would have too many permissions " + "to fit in an access vector with permission %s", + policydbp->p_class_val_to_name[datum->s.value - 1], + perm_id); + free(perm_id); + return -1; + } allocated = 1; if ((perm = malloc(sizeof(*perm))) == NULL) { yyerror("Out of memory!"); diff --git a/checkpolicy/policy_define.c b/checkpolicy/policy_define.c index 8bf36859439c8444c884416e51f3408f05314412..c2ae7fe5aa53fd2d100442a68d34d36f947fd995 100644 --- a/checkpolicy/policy_define.c +++ b/checkpolicy/policy_define.c @@ -117,12 +117,11 @@ int insert_id(const char *id, int push) char *newid = 0; int error; - newid = (char *)malloc(strlen(id) + 1); + newid = strdup(id); if (!newid) { yyerror("out of memory"); return -1; } - strcpy(newid, id); if (push) error = queue_push(id_queue, (queue_element_t) newid); else @@ -1417,7 +1416,7 @@ static int define_typebounds_helper(char *bounds_id, char *type_id) if (!type->bounds) type->bounds = bounds->s.value; else if (type->bounds != bounds->s.value) { - yyerror2("type %s has inconsistent master {%s,%s}", + yyerror2("type %s has inconsistent bounds %s/%s", type_id, policydbp->p_type_val_to_name[type->bounds - 1], policydbp->p_type_val_to_name[bounds->s.value - 1]); @@ -2209,7 +2208,7 @@ static int avrule_ioctl_partialdriver(struct av_ioctl_range_list *rangelist, xperms = calloc(1, sizeof(av_extended_perms_t)); if (!xperms) { yyerror("out of memory"); - return - 1; + return -1; } r = rangelist; @@ -2246,7 +2245,7 @@ static int avrule_ioctl_completedriver(struct av_ioctl_range_list *rangelist, xperms = calloc(1, sizeof(av_extended_perms_t)); if (!xperms) { yyerror("out of memory"); - return - 1; + return -1; } r = rangelist; @@ -2290,7 +2289,7 @@ static int avrule_ioctl_func(struct av_ioctl_range_list *rangelist, xperms = calloc(1, sizeof(av_extended_perms_t)); if (!xperms) { yyerror("out of memory"); - return - 1; + return -1; } r = rangelist; @@ -2353,11 +2352,11 @@ static int avrule_cpy(avrule_t *dest, const avrule_t *src) dest->flags = src->flags; if (type_set_cpy(&dest->stypes, &src->stypes)) { yyerror("out of memory"); - return - 1; + return -1; } if (type_set_cpy(&dest->ttypes, &src->ttypes)) { yyerror("out of memory"); - return - 1; + return -1; } dest->line = src->line; dest->source_filename = strdup(source_file); @@ -2371,11 +2370,12 @@ static int avrule_cpy(avrule_t *dest, const avrule_t *src) src_perms = src->perms; while (src_perms) { dest_perms = (class_perm_node_t *) calloc(1, sizeof(class_perm_node_t)); - class_perm_node_init(dest_perms); if (!dest_perms) { yyerror("out of memory"); return -1; } + class_perm_node_init(dest_perms); + if (!dest->perms) dest->perms = dest_perms; else @@ -4904,7 +4904,7 @@ bad: return -1; } -int define_devicetree_context() +int define_devicetree_context(void) { ocontext_t *newc, *c, *l, *head; @@ -5295,7 +5295,7 @@ int define_netif_context(void) return 0; } -int define_ipv4_node_context() +int define_ipv4_node_context(void) { char *id; int rc = 0; diff --git a/checkpolicy/test/dispol.c b/checkpolicy/test/dispol.c index 8ddefb04ac89480c94317b05c57d9993f62f7eb4..36a3362c89c27f1a0907b779869e0af044a135a1 100644 --- a/checkpolicy/test/dispol.c +++ b/checkpolicy/test/dispol.c @@ -486,12 +486,11 @@ int main(int argc, char **argv) } ans[strlen(ans) - 1] = 0; - name = malloc((strlen(ans) + 1) * sizeof(char)); + name = strdup(ans); if (name == NULL) { - fprintf(stderr, "couldn't malloc string.\n"); + fprintf(stderr, "couldn't strdup string.\n"); break; } - strcpy(name, ans); printf("state? "); if (fgets(ans, sizeof(ans), stdin) == NULL) { diff --git a/libselinux/VERSION b/libselinux/VERSION index 2f4b60750dc3500b0e4cf08f316a960a7ca42b40..5a958026daa3208cb329c403433beb56abd5c036 100644 --- a/libselinux/VERSION +++ b/libselinux/VERSION @@ -1 +1 @@ -3.4 +3.5 diff --git a/libselinux/include/selinux/avc.h b/libselinux/include/selinux/avc.h index 9b23357ad17fc48f7a6d9d6dff8728a4900ce5ac..4bbd2382404b90afe8a0e7035a1c85ad0539f469 100644 --- a/libselinux/include/selinux/avc.h +++ b/libselinux/include/selinux/avc.h @@ -24,7 +24,7 @@ struct security_id { }; typedef struct security_id *security_id_t; -#define SECSID_WILD (security_id_t)NULL /* unspecified SID */ +#define SECSID_WILD ((security_id_t)NULL) /* unspecified SID */ /** * avc_sid_to_context - get copy of context corresponding to SID. diff --git a/libselinux/include/selinux/context.h b/libselinux/include/selinux/context.h index 949fb1e14cac036da5e9a8e3ba2fafce7bfa6bd9..59d9bb69ba7da4854aacd051e85b96474420f20a 100644 --- a/libselinux/include/selinux/context.h +++ b/libselinux/include/selinux/context.h @@ -17,7 +17,7 @@ extern "C" { /* Return a new context initialized to a context string */ - extern context_t context_new(const char *); + extern context_t context_new(const char *str); /* * Return a pointer to the string value of the context_t @@ -25,24 +25,24 @@ extern "C" { * for the same context_t* */ - extern char *context_str(context_t); + extern const char *context_str(context_t con); /* Free the storage used by a context */ - extern void context_free(context_t); + extern void context_free(context_t con); /* Get a pointer to the string value of a context component */ - extern const char *context_type_get(context_t); - extern const char *context_range_get(context_t); - extern const char *context_role_get(context_t); - extern const char *context_user_get(context_t); + extern const char *context_type_get(context_t con); + extern const char *context_range_get(context_t con); + extern const char *context_role_get(context_t con); + extern const char *context_user_get(context_t con); /* Set a context component. Returns nonzero if unsuccessful */ - extern int context_type_set(context_t, const char *); - extern int context_range_set(context_t, const char *); - extern int context_role_set(context_t, const char *); - extern int context_user_set(context_t, const char *); + extern int context_type_set(context_t con, const char *type); + extern int context_range_set(context_t con, const char *range); + extern int context_role_set(context_t con, const char *role); + extern int context_user_set(context_t con, const char *user); #ifdef __cplusplus } diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h index ae98a92e393e757d8cad0e3942495765f8fe215a..a0948853fd985094fef11d2d9646408e19807d3d 100644 --- a/libselinux/include/selinux/selinux.h +++ b/libselinux/include/selinux/selinux.h @@ -54,6 +54,11 @@ extern int getpidcon_raw(pid_t pid, char ** con); extern int getprevcon(char ** con); extern int getprevcon_raw(char ** con); +/* Get previous context (prior to last exec) of process identified by pid, and + set *con to refer to it. Caller must free via freecon. */ +extern int getpidprevcon(pid_t pid, char ** con); +extern int getpidprevcon_raw(pid_t pid, char ** con); + /* Get exec context, and set *con to refer to it. Sets *con to NULL if no exec context has been set, i.e. using default. If non-NULL, caller must free via freecon. */ @@ -279,7 +284,7 @@ extern int security_validatetrans_raw(const char *scon, const char *newcon); /* Load a policy configuration. */ -extern int security_load_policy(void *data, size_t len); +extern int security_load_policy(const void *data, size_t len); /* Get the context of an initial kernel security identifier by name. Caller must free via freecon */ diff --git a/libselinux/man/man3/context_str.3 b/libselinux/man/man3/context_str.3 new file mode 100644 index 0000000000000000000000000000000000000000..f4f03a6d9cf3c5b0cce7d8c23890e437bb6d1202 --- /dev/null +++ b/libselinux/man/man3/context_str.3 @@ -0,0 +1 @@ +.so man3/context_new.3 diff --git a/libselinux/man/man3/getcon.3 b/libselinux/man/man3/getcon.3 index e7e394f305b7116a380bfd20f0e53cbc05fc24f9..be60341b4b7ad0bdbe9933f53519eaed23cabd0c 100644 --- a/libselinux/man/man3/getcon.3 +++ b/libselinux/man/man3/getcon.3 @@ -23,6 +23,10 @@ setcon \- set current security context of a process .sp .BI "int getpidcon_raw(pid_t " pid ", char **" context ); .sp +.BI "int getpidprevcon(pid_t " pid ", char **" context ); +.sp +.BI "int getpidprevcon_raw(pid_t " pid ", char **" context ); +.sp .BI "int getpeercon(int " fd ", char **" context ); .sp .BI "int getpeercon_raw(int " fd ", char **" context ); @@ -50,6 +54,11 @@ same as getcon but gets the context before the last exec. returns the process context for the specified PID, which must be free'd with .BR freecon (). +.TP +.BR getpidprevcon () +returns the process context before the last exec for the specified PID, which must be free'd with +.BR freecon (). + .TP .BR getpeercon () retrieves the context of the peer socket, which must be free'd with @@ -125,6 +134,7 @@ will fail if it is not allowed by policy. .BR getcon_raw (), .BR getprevcon_raw (), .BR getpidcon_raw (), +.BR getpidprevcon_raw (), .BR getpeercon_raw () and .BR setcon_raw () @@ -139,5 +149,9 @@ The retrieval functions might return success and set .I *context to NULL if and only if SELinux is not enabled. +Querying a foreign process via its PID, e.g. \fBgetpidcon\fR() or +\fBgetpidprevcon\fR(), is inherently racy and therefore should never be relied +upon for security purposes. + .SH "SEE ALSO" .BR selinux "(8), " setexeccon "(3)" diff --git a/libselinux/man/man3/getpidprevcon.3 b/libselinux/man/man3/getpidprevcon.3 new file mode 100644 index 0000000000000000000000000000000000000000..1210b5a0d9f08a948b30532b811b9c64171fe85d --- /dev/null +++ b/libselinux/man/man3/getpidprevcon.3 @@ -0,0 +1 @@ +.so man3/getcon.3 diff --git a/libselinux/man/man3/getpidprevcon_raw.3 b/libselinux/man/man3/getpidprevcon_raw.3 new file mode 100644 index 0000000000000000000000000000000000000000..1210b5a0d9f08a948b30532b811b9c64171fe85d --- /dev/null +++ b/libselinux/man/man3/getpidprevcon_raw.3 @@ -0,0 +1 @@ +.so man3/getcon.3 diff --git a/libselinux/man/man3/security_get_checkreqprot.3 b/libselinux/man/man3/security_get_checkreqprot.3 new file mode 100644 index 0000000000000000000000000000000000000000..d59e5c2cc2e7863ee775db9274cc728ac1cecd51 --- /dev/null +++ b/libselinux/man/man3/security_get_checkreqprot.3 @@ -0,0 +1 @@ +.so man3/security_getenforce.3 diff --git a/libselinux/man/man3/security_load_policy.3 b/libselinux/man/man3/security_load_policy.3 index af56163636928312fcdff4254dca126eba786f86..b2da02560799d9e2153701855ba63ea6103251af 100644 --- a/libselinux/man/man3/security_load_policy.3 +++ b/libselinux/man/man3/security_load_policy.3 @@ -5,7 +5,7 @@ security_load_policy \- load a new SELinux policy .SH "SYNOPSIS" .B #include .sp -.BI "int security_load_policy(void *" data ", size_t "len ); +.BI "int security_load_policy(const void *" data ", size_t "len ); .sp .BI "int selinux_mkload_policy(int " preservebools ");" .sp diff --git a/libselinux/man/man3/security_set_boolean_list.3 b/libselinux/man/man3/security_set_boolean_list.3 new file mode 100644 index 0000000000000000000000000000000000000000..29731efaecad29509f1ffa147f921dfd3080af8f --- /dev/null +++ b/libselinux/man/man3/security_set_boolean_list.3 @@ -0,0 +1 @@ +.so man3/security_load_booleans.3 diff --git a/libselinux/man/man3/selinux_sepgsql_context_path.3 b/libselinux/man/man3/selinux_sepgsql_context_path.3 new file mode 100644 index 0000000000000000000000000000000000000000..175a611a3ef06bcc4007ae3453531475ad705906 --- /dev/null +++ b/libselinux/man/man3/selinux_sepgsql_context_path.3 @@ -0,0 +1 @@ +.so man3/selinux_binary_policy_path.3 diff --git a/libselinux/man/man3/setexecfilecon.3 b/libselinux/man/man3/setexecfilecon.3 new file mode 100644 index 0000000000000000000000000000000000000000..b2e6ab8141ce396a5bdc07e02aba10e206cfaa99 --- /dev/null +++ b/libselinux/man/man3/setexecfilecon.3 @@ -0,0 +1 @@ +.so man3/getexeccon.3 diff --git a/libselinux/src/.gitignore b/libselinux/src/.gitignore index 001f20b01e3936e33d86c3cc86c5a990b4486ca9..94400e81fb33207f35486d0dd051ebb12238d41d 100644 --- a/libselinux/src/.gitignore +++ b/libselinux/src/.gitignore @@ -1,3 +1,4 @@ selinux.py selinuxswig_python_wrap.c selinuxswig_ruby_wrap.c +selinux.egg-info/ diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile index 04bf4f240168e728af032ec1903b34c00c646c09..36d57122bbd29fd5d89201fcb21549c3e0f5585b 100644 --- a/libselinux/src/Makefile +++ b/libselinux/src/Makefile @@ -14,7 +14,7 @@ SHLIBDIR ?= /lib INCLUDEDIR ?= $(PREFIX)/include PYINC ?= $(shell $(PKG_CONFIG) --cflags $(PYPREFIX)) PYLIBS ?= $(shell $(PKG_CONFIG) --libs $(PYPREFIX)) -PYTHONLIBDIR ?= $(shell $(PYTHON) -c "from distutils.sysconfig import *; print(get_python_lib(plat_specific=1, prefix='$(PREFIX)'))") +PYTHONLIBDIR ?= $(shell $(PYTHON) -c "import sysconfig; print(sysconfig.get_path('platlib', vars={'platbase': '$(PREFIX)', 'base': '$(PREFIX)'}))") PYCEXT ?= $(shell $(PYTHON) -c 'import importlib.machinery;print(importlib.machinery.EXTENSION_SUFFIXES[0])') RUBYINC ?= $(shell $(RUBY) -e 'puts "-I" + RbConfig::CONFIG["rubyarchhdrdir"] + " -I" + RbConfig::CONFIG["rubyhdrdir"]') RUBYLIBS ?= $(shell $(RUBY) -e 'puts "-L" + RbConfig::CONFIG["libdir"] + " -L" + RbConfig::CONFIG["archlibdir"] + " " + RbConfig::CONFIG["LIBRUBYARG_SHARED"]') @@ -86,7 +86,7 @@ CFLAGS ?= -O -Wall -W -Wundef -Wformat-y2k -Wformat-security -Winit-self -Wmissi -Wno-missing-field-initializers -Wno-sign-compare \ -Wno-format-nonliteral -Wframe-larger-than=$(MAX_STACK_SIZE) \ -fstack-protector-all --param=ssp-buffer-size=4 -fexceptions \ - -fasynchronous-unwind-tables -fdiagnostics-show-option -funit-at-a-time \ + -fasynchronous-unwind-tables -fdiagnostics-show-option \ -Werror -Wno-aggregate-return -Wno-redundant-decls \ $(EXTRA_CFLAGS) @@ -103,6 +103,12 @@ FTS_LDLIBS ?= override CFLAGS += -I../include -D_GNU_SOURCE $(DISABLE_FLAGS) $(PCRE_CFLAGS) +# check for strlcpy(3) availability +H := \# +ifeq (yes,$(shell printf '${H}include \nint main(void){char*d,*s;strlcpy(d, s, 0);return 0;}' | $(CC) -x c -o /dev/null - >/dev/null 2>&1 && echo yes)) +override CFLAGS += -DHAVE_STRLCPY +endif + SWIG_CFLAGS += -Wno-error -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-parameter \ -Wno-shadow -Wno-uninitialized -Wno-missing-prototypes -Wno-missing-declarations \ -Wno-deprecated-declarations @@ -181,7 +187,7 @@ install: all ln -sf --relative $(DESTDIR)$(SHLIBDIR)/$(LIBSO) $(DESTDIR)$(LIBDIR)/$(TARGET) install-pywrap: pywrap - $(PYTHON) setup.py install --prefix=$(PREFIX) `test -n "$(DESTDIR)" && echo --root $(DESTDIR)` $(PYTHON_SETUP_ARGS) + $(PYTHON) -m pip install --prefix=$(PREFIX) `test -n "$(DESTDIR)" && echo --root $(DESTDIR) --ignore-installed --no-deps` $(PYTHON_SETUP_ARGS) . install -m 644 $(SWIGPYOUT) $(DESTDIR)$(PYTHONLIBDIR)/selinux/__init__.py ln -sf --relative $(DESTDIR)$(PYTHONLIBDIR)/selinux/_selinux$(PYCEXT) $(DESTDIR)$(PYTHONLIBDIR)/_selinux$(PYCEXT) @@ -195,7 +201,7 @@ relabel: clean-pywrap: -rm -f $(SWIGLOBJ) $(SWIGSO) $(AUDIT2WHYLOBJ) $(AUDIT2WHYSO) $(PYTHON) setup.py clean - -rm -rf build *~ \#* *pyc .#* + -rm -rf build *~ \#* *pyc .#* selinux.egg-info/ clean-rubywrap: -rm -f $(SWIGRUBYLOBJ) $(SWIGRUBYSO) diff --git a/libselinux/src/audit2why.c b/libselinux/src/audit2why.c index ca38e13c0eeb4ebf521f863126170fce71fb581f..ba1a66eb47e14d742afe2b27064585eed3449b05 100644 --- a/libselinux/src/audit2why.c +++ b/libselinux/src/audit2why.c @@ -191,26 +191,17 @@ static PyObject *finish(PyObject *self __attribute__((unused)), PyObject *args) static int __policy_init(const char *init_path) { - FILE *fp; - char path[PATH_MAX]; + FILE *fp = NULL; + const char *curpolicy; char errormsg[PATH_MAX+1024+20]; struct sepol_policy_file *pf = NULL; int rc; unsigned int cnt; - path[PATH_MAX-1] = '\0'; if (init_path) { - strncpy(path, init_path, PATH_MAX-1); - fp = fopen(path, "re"); - if (!fp) { - snprintf(errormsg, sizeof(errormsg), - "unable to open %s: %m\n", - path); - PyErr_SetString( PyExc_ValueError, errormsg); - return 1; - } + curpolicy = init_path; } else { - const char *curpolicy = selinux_current_policy_path(); + curpolicy = selinux_current_policy_path(); if (!curpolicy) { /* SELinux disabled, must use -p option. */ snprintf(errormsg, sizeof(errormsg), @@ -218,14 +209,15 @@ static int __policy_init(const char *init_path) PyErr_SetString( PyExc_ValueError, errormsg); return 1; } - fp = fopen(curpolicy, "re"); - if (!fp) { - snprintf(errormsg, sizeof(errormsg), - "unable to open %s: %m\n", - curpolicy); - PyErr_SetString( PyExc_ValueError, errormsg); - return 1; - } + } + + fp = fopen(curpolicy, "re"); + if (!fp) { + snprintf(errormsg, sizeof(errormsg), + "unable to open %s: %m\n", + curpolicy); + PyErr_SetString( PyExc_ValueError, errormsg); + return 1; } avc = calloc(sizeof(struct avc_t), 1); @@ -243,18 +235,17 @@ static int __policy_init(const char *init_path) snprintf(errormsg, sizeof(errormsg), "policydb_init failed: %m\n"); PyErr_SetString( PyExc_RuntimeError, errormsg); - fclose(fp); - return 1; + goto err; } sepol_policy_file_set_fp(pf, fp); if (sepol_policydb_read(avc->policydb, pf)) { snprintf(errormsg, sizeof(errormsg), - "invalid binary policy %s\n", path); + "invalid binary policy %s\n", curpolicy); PyErr_SetString( PyExc_ValueError, errormsg); - fclose(fp); - return 1; + goto err; } fclose(fp); + fp = NULL; sepol_set_policydb(&avc->policydb->p); avc->handle = sepol_handle_create(); /* Turn off messages */ @@ -264,13 +255,13 @@ static int __policy_init(const char *init_path) avc->policydb, &cnt); if (rc < 0) { PyErr_SetString( PyExc_RuntimeError, "unable to get bool count\n"); - return 1; + goto err; } boollist = calloc(cnt, sizeof(*boollist)); if (!boollist) { PyErr_SetString( PyExc_MemoryError, "Out of memory\n"); - return 1; + goto err; } sepol_bool_iterate(avc->handle, avc->policydb, @@ -281,11 +272,26 @@ static int __policy_init(const char *init_path) rc = sepol_sidtab_init(&sidtab); if (rc < 0) { PyErr_SetString( PyExc_RuntimeError, "unable to init sidtab\n"); - free(boollist); - return 1; + goto err; } sepol_set_sidtab(&sidtab); return 0; + +err: + if (boollist) + free(boollist); + if (avc){ + if (avc->handle) + sepol_handle_destroy(avc->handle); + if (avc->policydb) + sepol_policydb_free(avc->policydb); + free(avc); + } + if (pf) + sepol_policy_file_free(pf); + if (fp) + fclose(fp); + return 1; } static PyObject *init(PyObject *self __attribute__((unused)), PyObject *args) { diff --git a/libselinux/src/avc.c b/libselinux/src/avc.c index 7493e4b24df2d144b96f022cdf1c46db29c07b47..8d5983a2fe0c12fc75b3ceecd62419c0fba4838a 100644 --- a/libselinux/src/avc.c +++ b/libselinux/src/avc.c @@ -725,7 +725,6 @@ void avc_audit(security_id_t ssid, security_id_t tsid, if (denied) log_append(avc_audit_buf, " permissive=%u", result ? 0 : 1); - log_append(avc_audit_buf, "\n"); avc_log(SELINUX_AVC, "%s", avc_audit_buf); avc_release_lock(avc_log_lock); diff --git a/libselinux/src/avc_internal.c b/libselinux/src/avc_internal.c index 71a1357bc564cb33a8da221490f2ec49eadb42c2..ffc663e5da4434e6dbe2288d4b079c63245eed01 100644 --- a/libselinux/src/avc_internal.c +++ b/libselinux/src/avc_internal.c @@ -51,7 +51,6 @@ char avc_prefix[AVC_PREFIX_SIZE] = "uavc"; int avc_running = 0; int avc_enforcing = 1; int avc_setenforce = 0; -int avc_netlink_trouble = 0; /* process setenforce events for netlink and sestatus */ int avc_process_setenforce(int enforcing) @@ -295,7 +294,6 @@ void avc_netlink_loop(void) close(fd); fd = -1; - avc_netlink_trouble = 1; avc_log(SELINUX_ERROR, "%s: netlink thread: errors encountered, terminating\n", avc_prefix); diff --git a/libselinux/src/avc_internal.h b/libselinux/src/avc_internal.h index a9a4aa0b3c42c3b63428f28a5670de41ec26f810..54f0ce28c205390821ed8789827099e06ac822f8 100644 --- a/libselinux/src/avc_internal.h +++ b/libselinux/src/avc_internal.h @@ -180,7 +180,4 @@ int avc_ss_set_auditdeny(security_id_t ssid, security_id_t tsid, security_class_t tclass, access_vector_t perms, uint32_t seqno, uint32_t enable) ; -/* netlink kernel message code */ -extern int avc_netlink_trouble ; - #endif /* _SELINUX_AVC_INTERNAL_H_ */ diff --git a/libselinux/src/booleans.c b/libselinux/src/booleans.c index ef1f64a05d84817be7c5f681c3df2c90ea21d10d..e34b39ffb589f22454180d6a0604711872de4ff6 100644 --- a/libselinux/src/booleans.c +++ b/libselinux/src/booleans.c @@ -7,7 +7,6 @@ #ifndef DISABLE_BOOL -#include #include #include #include @@ -132,7 +131,8 @@ char *selinux_boolean_sub(const char *name) ptr++; *ptr = '\0'; - sub = strdup(dst); + if (!strchr(dst, '/')) + sub = strdup(dst); break; } @@ -147,12 +147,12 @@ out: static int bool_open(const char *name, int flag) { char *fname = NULL; char *alt_name = NULL; - int len; + size_t len; int fd = -1; int ret; char *ptr; - if (!name) { + if (!name || strchr(name, '/')) { errno = EINVAL; return -1; } @@ -164,9 +164,8 @@ static int bool_open(const char *name, int flag) { return -1; ret = snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, name); - if (ret < 0) + if (ret < 0 || (size_t)ret >= len) goto out; - assert(ret < len); fd = open(fname, flag); if (fd >= 0 || errno != ENOENT) @@ -184,9 +183,8 @@ static int bool_open(const char *name, int flag) { fname = ptr; ret = snprintf(fname, len, "%s%s%s", selinux_mnt, SELINUX_BOOL_DIR, alt_name); - if (ret < 0) + if (ret < 0 || (size_t)ret >= len) goto out; - assert(ret < len); fd = open(fname, flag); out: diff --git a/libselinux/src/canonicalize_context.c b/libselinux/src/canonicalize_context.c index faab730592c2c306f9baca017824f19057874f2a..6af8491dd4a666f40c202c4575801e52d2bfe05a 100644 --- a/libselinux/src/canonicalize_context.c +++ b/libselinux/src/canonicalize_context.c @@ -33,7 +33,11 @@ int security_canonicalize_context_raw(const char * con, ret = -1; goto out; } - strncpy(buf, con, size); + if (strlcpy(buf, con, size) >= size) { + errno = EOVERFLOW; + ret = -1; + goto out2; + } ret = write(fd, buf, strlen(buf) + 1); if (ret < 0) diff --git a/libselinux/src/compute_av.c b/libselinux/src/compute_av.c index 9d17339d1a32c9581b79ae06a4cd4de561e447b6..354a19e1051c67e01a5c8b12fe6db0011b0a1b9f 100644 --- a/libselinux/src/compute_av.c +++ b/libselinux/src/compute_av.c @@ -40,8 +40,14 @@ int security_compute_av_flags_raw(const char * scon, } kclass = unmap_class(tclass); - snprintf(buf, len, "%s %s %hu %x", scon, tcon, + + ret = snprintf(buf, len, "%s %s %hu %x", scon, tcon, kclass, unmap_perm(tclass, requested)); + if (ret < 0 || (size_t)ret >= len) { + errno = EOVERFLOW; + ret = -1; + goto out2; + } ret = write(fd, buf, strlen(buf)); if (ret < 0) diff --git a/libselinux/src/compute_create.c b/libselinux/src/compute_create.c index 1d75714d852d75036795e8f80ec422dda30c419b..e9f3c96a1a6ae02dc9655684df54be7fa3d8234d 100644 --- a/libselinux/src/compute_create.c +++ b/libselinux/src/compute_create.c @@ -75,8 +75,15 @@ int security_compute_create_name_raw(const char * scon, ret = -1; goto out; } + len = snprintf(buf, size, "%s %s %hu", scon, tcon, unmap_class(tclass)); + if (len < 0 || (size_t)len >= size) { + errno = EOVERFLOW; + ret = -1; + goto out2; + } + if (objname && object_name_encode(objname, buf + len, size - len) < 0) { errno = ENAMETOOLONG; diff --git a/libselinux/src/compute_member.c b/libselinux/src/compute_member.c index 16234b7908f234a3bcd71f0906d0033d7e996f64..53d2f55950f6a081e1c11165e5b2c1fe887c7c5e 100644 --- a/libselinux/src/compute_member.c +++ b/libselinux/src/compute_member.c @@ -36,7 +36,13 @@ int security_compute_member_raw(const char * scon, ret = -1; goto out; } - snprintf(buf, size, "%s %s %hu", scon, tcon, unmap_class(tclass)); + + ret = snprintf(buf, size, "%s %s %hu", scon, tcon, unmap_class(tclass)); + if (ret < 0 || (size_t)ret >= size) { + errno = EOVERFLOW; + ret = -1; + goto out2; + } ret = write(fd, buf, strlen(buf)); if (ret < 0) diff --git a/libselinux/src/compute_relabel.c b/libselinux/src/compute_relabel.c index dd20d6525993f4d843992396b88588d0ade33e0c..9c0a2304f356c4dbd67a0cdbe78d22ebcee503ef 100644 --- a/libselinux/src/compute_relabel.c +++ b/libselinux/src/compute_relabel.c @@ -36,7 +36,13 @@ int security_compute_relabel_raw(const char * scon, ret = -1; goto out; } - snprintf(buf, size, "%s %s %hu", scon, tcon, unmap_class(tclass)); + + ret = snprintf(buf, size, "%s %s %hu", scon, tcon, unmap_class(tclass)); + if (ret < 0 || (size_t)ret >= size) { + errno = EOVERFLOW; + ret = -1; + goto out2; + } ret = write(fd, buf, strlen(buf)); if (ret < 0) diff --git a/libselinux/src/compute_user.c b/libselinux/src/compute_user.c index ae5e7b4a8f6858839e134471e5983bd97c9c2765..f55f945a01e04142b6a0d7843e85972fee24c941 100644 --- a/libselinux/src/compute_user.c +++ b/libselinux/src/compute_user.c @@ -38,7 +38,13 @@ int security_compute_user_raw(const char * scon, ret = -1; goto out; } - snprintf(buf, size, "%s %s", scon, user); + + ret = snprintf(buf, size, "%s %s", scon, user); + if (ret < 0 || (size_t)ret >= size) { + errno = EOVERFLOW; + ret = -1; + goto out2; + } ret = write(fd, buf, strlen(buf)); if (ret < 0) diff --git a/libselinux/src/context.c b/libselinux/src/context.c index b2144c7cf76c77393c81cb13aac7b6d2b4bb0b75..33c48ef3d7c8c0724ee1162f3e91828c79eda5d3 100644 --- a/libselinux/src/context.c +++ b/libselinux/src/context.c @@ -68,11 +68,9 @@ context_t context_new(const char *str) for (p = tok; *p; p++) { /* empty */ } } - n->component[i] = (char *)malloc(p - tok + 1); + n->component[i] = strndup(tok, p - tok); if (n->component[i] == 0) goto err; - strncpy(n->component[i], tok, p - tok); - n->component[i][p - tok] = '\0'; tok = *p ? p + 1 : p; } return result; @@ -116,7 +114,7 @@ void context_free(context_t context) /* * Return a pointer to the string value of the context. */ -char *context_str(context_t context) +const char *context_str(context_t context) { context_private_t *n = context->ptr; int i; @@ -149,19 +147,18 @@ static int set_comp(context_private_t * n, int idx, const char *str) char *t = NULL; const char *p; if (str) { - t = (char *)malloc(strlen(str) + 1); - if (!t) { - return -1; - } for (p = str; *p; p++) { if (*p == '\t' || *p == '\n' || *p == '\r' || ((*p == ':' || *p == ' ') && idx != COMP_RANGE)) { - free(t); errno = EINVAL; return -1; } } - strcpy(t, str); + + t = strdup(str); + if (!t) { + return -1; + } } conditional_free(&n->component[idx]); n->component[idx] = t; diff --git a/libselinux/src/exception.sh b/libselinux/src/exception.sh old mode 100644 new mode 100755 diff --git a/libselinux/src/fgetfilecon.c b/libselinux/src/fgetfilecon.c index baf38ec1221f4623488609f959c2b3c8ce26d722..d7051171cf0d7e9a87285399d34a5e0d170b918e 100644 --- a/libselinux/src/fgetfilecon.c +++ b/libselinux/src/fgetfilecon.c @@ -26,7 +26,10 @@ static ssize_t fgetxattr_wrapper(int fd, const char *name, void *value, size_t s snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd); errno = saved_errno; - return getxattr(buf, name, value, size); + ret = getxattr(buf, name, value, size); + if (ret < 0 && errno == ENOENT) + errno = EBADF; + return ret; } int fgetfilecon_raw(int fd, char ** context) diff --git a/libselinux/src/file_path_suffixes.h b/libselinux/src/file_path_suffixes.h index 93a81b6413952bdcdaf57739aff8a6e27bde5223..a5573134c58ef055f2960786f70da4a2ceb7f9d6 100644 --- a/libselinux/src/file_path_suffixes.h +++ b/libselinux/src/file_path_suffixes.h @@ -1,11 +1,7 @@ /* File name suffixes. */ S_(BINPOLICY, "/policy/policy") S_(CONTEXTS_DIR, "/contexts") - // FIXME 此处不应该改变 file_contexts 的约定路径! - // 因为 OpenHarmony 的 e2fsdroid 无法支持五级系统目录,所以在此作出规避, - // 但是很显然这是不应当的。 - //S_(FILE_CONTEXTS, "/contexts/files/file_contexts") - S_(FILE_CONTEXTS, "/contexts/file_contexts") + S_(FILE_CONTEXTS, "/contexts/files/file_contexts") S_(HOMEDIR_CONTEXTS, "/contexts/files/homedir_template") S_(DEFAULT_CONTEXTS, "/contexts/default_contexts") S_(USER_CONTEXTS, "/contexts/users/") diff --git a/libselinux/src/fsetfilecon.c b/libselinux/src/fsetfilecon.c index be821c7a6be25c599fb307ab1c92607e48500b6e..19ea15b711cc6ab00b1a95f2f428a6050f2cad03 100644 --- a/libselinux/src/fsetfilecon.c +++ b/libselinux/src/fsetfilecon.c @@ -25,7 +25,10 @@ static int fsetxattr_wrapper(int fd, const char* name, const void* value, size_t snprintf(buf, sizeof(buf), "/proc/self/fd/%d", fd); errno = saved_errno; - return setxattr(buf, name, value, size, flags); + rc = setxattr(buf, name, value, size, flags); + if (rc < 0 && errno == ENOENT) + errno = EBADF; + return rc; } int fsetfilecon_raw(int fd, const char * context) diff --git a/libselinux/src/get_context_list.c b/libselinux/src/get_context_list.c index cfe38e59b20740b54d3a48ff3ae469166eaa8e93..d774b9cf604bba8febf4e33902b1cc6f8ffd686e 100644 --- a/libselinux/src/get_context_list.c +++ b/libselinux/src/get_context_list.c @@ -143,6 +143,7 @@ static int get_context_user(FILE * fp, char *linerole, *linetype; char **new_reachable = NULL; char *usercon_str; + const char *usercon_str2; context_t con; context_t usercon; @@ -257,20 +258,20 @@ static int get_context_user(FILE * fp, rc = -1; goto out; } - usercon_str = context_str(usercon); - if (!usercon_str) { + usercon_str2 = context_str(usercon); + if (!usercon_str2) { context_free(usercon); rc = -1; goto out; } /* check whether usercon is already in reachable */ - if (is_in_reachable(*reachable, usercon_str)) { + if (is_in_reachable(*reachable, usercon_str2)) { context_free(usercon); start = end; continue; } - if (security_check_context(usercon_str) == 0) { + if (security_check_context(usercon_str2) == 0) { new_reachable = realloc(*reachable, (*nreachable + 2) * sizeof(char *)); if (!new_reachable) { context_free(usercon); @@ -278,7 +279,7 @@ static int get_context_user(FILE * fp, goto out; } *reachable = new_reachable; - new_reachable[*nreachable] = strdup(usercon_str); + new_reachable[*nreachable] = strdup(usercon_str2); if (new_reachable[*nreachable] == NULL) { context_free(usercon); rc = -1; diff --git a/libselinux/src/get_default_type.c b/libselinux/src/get_default_type.c index dd7b5d790c97cd15eb0782487524e37c648872c5..766ea4b7880c8db266113509d203742d93d1d3ac 100644 --- a/libselinux/src/get_default_type.c +++ b/libselinux/src/get_default_type.c @@ -62,10 +62,9 @@ static int find_default_type(FILE * fp, const char *role, char **type) return -1; } - t = malloc(strlen(buf) - len); + t = strndup(ptr, strlen(buf) - len - 1); if (!t) return -1; - strcpy(t, ptr); *type = t; return 0; } diff --git a/libselinux/src/get_initial_context.c b/libselinux/src/get_initial_context.c index 97ae3dcfb5a6255b14d1825e8dfac25975dc5566..0f25ba3f56194cb979c01469be30744b2bd9e8d3 100644 --- a/libselinux/src/get_initial_context.c +++ b/libselinux/src/get_initial_context.c @@ -23,8 +23,17 @@ int security_get_initial_context_raw(const char * name, char ** con) return -1; } - snprintf(path, sizeof path, "%s%s%s", - selinux_mnt, SELINUX_INITCON_DIR, name); + if (strchr(name, '/')) { + errno = EINVAL; + return -1; + } + + ret = snprintf(path, sizeof path, "%s%s%s", selinux_mnt, SELINUX_INITCON_DIR, name); + if (ret < 0 || (size_t)ret >= sizeof path) { + errno = EOVERFLOW; + return -1; + } + fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) return -1; diff --git a/libselinux/src/label_db.c b/libselinux/src/label_db.c index 94c05c6d439709dad7fab3565e9b509264c3fecc..3f803037d75a1aa38f9844a9d531c31936243674 100644 --- a/libselinux/src/label_db.c +++ b/libselinux/src/label_db.c @@ -31,7 +31,7 @@ * For example: * ---------------------------------------- * # - * # It is an example specfile for database obejcts + * # It is an example specfile for database objects * # * db_database template1 system_u:object_r:sepgsql_db_t:s0 * @@ -293,6 +293,11 @@ db_init(const struct selinux_opt *opts, unsigned nopts, return NULL; } rec->spec_file = strdup(path); + if (!rec->spec_file) { + free(catalog); + fclose(filp); + return NULL; + } /* * Parse for each lines @@ -322,18 +327,19 @@ db_init(const struct selinux_opt *opts, unsigned nopts, if (process_line(path, line_buf, ++line_num, catalog) < 0) goto out_error; } - free(line_buf); if (digest_add_specfile(rec->digest, filp, NULL, sb.st_size, path) < 0) goto out_error; digest_gen_hash(rec->digest); + free(line_buf); fclose(filp); return catalog; out_error: + free(line_buf); for (i = 0; i < catalog->nspec; i++) { spec_t *spec = &catalog->specs[i]; diff --git a/libselinux/src/libselinux.map b/libselinux/src/libselinux.map index 6e04eb61c0c5f85bf10c31c82390b429574f678c..5e00f45b7a021d244a6e2d6bcd4d82acadb40f08 100644 --- a/libselinux/src/libselinux.map +++ b/libselinux/src/libselinux.map @@ -246,3 +246,9 @@ LIBSELINUX_3.4 { selinux_restorecon_get_skipped_errors; selinux_restorecon_parallel; } LIBSELINUX_1.0; + +LIBSELINUX_3.5 { + global: + getpidprevcon; + getpidprevcon_raw; +} LIBSELINUX_3.4; diff --git a/libselinux/src/load_policy.c b/libselinux/src/load_policy.c index d8c715edb0b67119e8da3491719f4d447ca52b97..17918e8be2b07bd2f986fd05b70dd53e7f25be49 100644 --- a/libselinux/src/load_policy.c +++ b/libselinux/src/load_policy.c @@ -23,7 +23,7 @@ #define MNT_DETACH 2 #endif -int security_load_policy(void *data, size_t len) +int security_load_policy(const void *data, size_t len) { char path[PATH_MAX]; int fd, ret; diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c index ea78a23edc5a6736760110f31914632ebb2436af..bf2da083170605dcee5a9b5fa777ccd2f3595a4e 100644 --- a/libselinux/src/matchpathcon.c +++ b/libselinux/src/matchpathcon.c @@ -215,10 +215,9 @@ int matchpathcon_filespec_add(ino_t ino, int specind, const char *file) if (ret < 0 || sb.st_ino != ino) { fl->specind = specind; free(fl->file); - fl->file = malloc(strlen(file) + 1); + fl->file = strdup(file); if (!fl->file) goto oom; - strcpy(fl->file, file); return fl->specind; } @@ -232,10 +231,9 @@ int matchpathcon_filespec_add(ino_t ino, int specind, const char *file) __FUNCTION__, file, fl->file, con_array[fl->specind]); free(fl->file); - fl->file = malloc(strlen(file) + 1); + fl->file = strdup(file); if (!fl->file) goto oom; - strcpy(fl->file, file); return fl->specind; } @@ -248,10 +246,9 @@ int matchpathcon_filespec_add(ino_t ino, int specind, const char *file) goto oom; fl->ino = ino; fl->specind = specind; - fl->file = malloc(strlen(file) + 1); + fl->file = strdup(file); if (!fl->file) goto oom_freefl; - strcpy(fl->file, file); fl->next = prevfl->next; prevfl->next = fl; return fl->specind; diff --git a/libselinux/src/procattr.c b/libselinux/src/procattr.c index 9896483e25f0fdadb73901b257c0ce1ca997009d..b7a93a2b3a3049149f8b55e8214d0f6277b71886 100644 --- a/libselinux/src/procattr.c +++ b/libselinux/src/procattr.c @@ -11,11 +11,14 @@ #define UNSET (char *) -1 +/* Cached values so that when a thread calls set*con() then gen*con(), the value + * which was set is directly returned. + */ static __thread char *prev_current = UNSET; -static __thread char * prev_exec = UNSET; -static __thread char * prev_fscreate = UNSET; -static __thread char * prev_keycreate = UNSET; -static __thread char * prev_sockcreate = UNSET; +static __thread char *prev_exec = UNSET; +static __thread char *prev_fscreate = UNSET; +static __thread char *prev_keycreate = UNSET; +static __thread char *prev_sockcreate = UNSET; static pthread_once_t once = PTHREAD_ONCE_INIT; static pthread_key_t destructor_key; @@ -111,43 +114,18 @@ out: return fd; } -static int getprocattrcon_raw(char ** context, - pid_t pid, const char *attr) +static int getprocattrcon_raw(char **context, pid_t pid, const char *attr, + const char *prev_context) { char *buf; size_t size; int fd; ssize_t ret; int errno_hold; - char * prev_context; __selinux_once(once, init_procattr); init_thread_destructor(); - switch (attr[0]) { - case 'c': - prev_context = NULL; - break; - case 'e': - prev_context = prev_exec; - break; - case 'f': - prev_context = prev_fscreate; - break; - case 'k': - prev_context = prev_keycreate; - break; - case 's': - prev_context = prev_sockcreate; - break; - case 'p': - prev_context = NULL; - break; - default: - errno = ENOENT; - return -1; - } - if (prev_context && prev_context != UNSET) { *context = strdup(prev_context); if (!(*context)) { @@ -194,13 +172,13 @@ static int getprocattrcon_raw(char ** context, return ret; } -static int getprocattrcon(char ** context, - pid_t pid, const char *attr) +static int getprocattrcon(char **context, pid_t pid, const char *attr, + const char *prev_context) { int ret; char * rcontext; - ret = getprocattrcon_raw(&rcontext, pid, attr); + ret = getprocattrcon_raw(&rcontext, pid, attr, prev_context); if (!ret) { ret = selinux_raw_to_trans_context(rcontext, context); @@ -210,45 +188,24 @@ static int getprocattrcon(char ** context, return ret; } -static int setprocattrcon_raw(const char * context, - pid_t pid, const char *attr) +static int setprocattrcon_raw(const char *context, const char *attr, + char **prev_context) { int fd; ssize_t ret; int errno_hold; - char **prev_context, *context2 = NULL; + char *context2 = NULL; __selinux_once(once, init_procattr); init_thread_destructor(); - switch (attr[0]) { - case 'c': - prev_context = &prev_current; - break; - case 'e': - prev_context = &prev_exec; - break; - case 'f': - prev_context = &prev_fscreate; - break; - case 'k': - prev_context = &prev_keycreate; - break; - case 's': - prev_context = &prev_sockcreate; - break; - default: - errno = ENOENT; - return -1; - } - if (!context && !*prev_context) return 0; if (context && *prev_context && *prev_context != UNSET && !strcmp(context, *prev_context)) return 0; - fd = openattr(pid, attr, O_RDWR | O_CLOEXEC); + fd = openattr(0, attr, O_RDWR | O_CLOEXEC); if (fd < 0) return -1; if (context) { @@ -279,8 +236,8 @@ out: } } -static int setprocattrcon(const char * context, - pid_t pid, const char *attr) +static int setprocattrcon(const char *context, const char *attr, + char **prev_context) { int ret; char * rcontext; @@ -288,62 +245,76 @@ static int setprocattrcon(const char * context, if (selinux_trans_to_raw_context(context, &rcontext)) return -1; - ret = setprocattrcon_raw(rcontext, pid, attr); + ret = setprocattrcon_raw(rcontext, attr, prev_context); freecon(rcontext); return ret; } -#define getselfattr_def(fn, attr) \ +#define getselfattr_def(fn, attr, prev_context) \ int get##fn##_raw(char **c) \ { \ - return getprocattrcon_raw(c, 0, #attr); \ + return getprocattrcon_raw(c, 0, attr, prev_context); \ } \ int get##fn(char **c) \ { \ - return getprocattrcon(c, 0, #attr); \ + return getprocattrcon(c, 0, attr, prev_context); \ } -#define setselfattr_def(fn, attr) \ +#define setselfattr_def(fn, attr, prev_context) \ int set##fn##_raw(const char * c) \ { \ - return setprocattrcon_raw(c, 0, #attr); \ + return setprocattrcon_raw(c, attr, &prev_context); \ } \ int set##fn(const char * c) \ { \ - return setprocattrcon(c, 0, #attr); \ + return setprocattrcon(c, attr, &prev_context); \ } -#define all_selfattr_def(fn, attr) \ - getselfattr_def(fn, attr) \ - setselfattr_def(fn, attr) +#define all_selfattr_def(fn, attr, prev_context) \ + getselfattr_def(fn, attr, prev_context) \ + setselfattr_def(fn, attr, prev_context) -#define getpidattr_def(fn, attr) \ - int get##fn##_raw(pid_t pid, char **c) \ - { \ - if (pid <= 0) { \ - errno = EINVAL; \ - return -1; \ - } else { \ - return getprocattrcon_raw(c, pid, #attr); \ - } \ - } \ - int get##fn(pid_t pid, char **c) \ - { \ - if (pid <= 0) { \ - errno = EINVAL; \ - return -1; \ - } else { \ - return getprocattrcon(c, pid, #attr); \ - } \ +all_selfattr_def(con, "current", prev_current) + getselfattr_def(prevcon, "prev", NULL) + all_selfattr_def(execcon, "exec", prev_exec) + all_selfattr_def(fscreatecon, "fscreate", prev_fscreate) + all_selfattr_def(sockcreatecon, "sockcreate", prev_sockcreate) + all_selfattr_def(keycreatecon, "keycreate", prev_keycreate) + +int getpidcon_raw(pid_t pid, char **c) +{ + if (pid <= 0) { + errno = EINVAL; + return -1; + } + return getprocattrcon_raw(c, pid, "current", NULL); +} + +int getpidcon(pid_t pid, char **c) +{ + if (pid <= 0) { + errno = EINVAL; + return -1; } + return getprocattrcon(c, pid, "current", NULL); +} -all_selfattr_def(con, current) - getpidattr_def(pidcon, current) - getselfattr_def(prevcon, prev) - all_selfattr_def(execcon, exec) - all_selfattr_def(fscreatecon, fscreate) - all_selfattr_def(sockcreatecon, sockcreate) - all_selfattr_def(keycreatecon, keycreate) +int getpidprevcon_raw(pid_t pid, char **c) +{ + if (pid <= 0) { + errno = EINVAL; + return -1; + } + return getprocattrcon_raw(c, pid, "prev", NULL); +} +int getpidprevcon(pid_t pid, char **c) +{ + if (pid <= 0) { + errno = EINVAL; + return -1; + } + return getprocattrcon(c, pid, "prev", NULL); +} diff --git a/libselinux/src/query_user_context.c b/libselinux/src/query_user_context.c index b8125c96ed81b5a31a5ddf5204aebdc5b1de7047..29a1b360e945ecaab73ffec653fe72152ca60f7c 100644 --- a/libselinux/src/query_user_context.c +++ b/libselinux/src/query_user_context.c @@ -115,7 +115,7 @@ int manual_user_enter_context(const char *user, char ** newcon) int mls_enabled = is_selinux_mls_enabled(); context_t new_context; /* The new context chosen by the user */ - char *user_context = NULL; /* String value of the user's context */ + const char *user_context = NULL; /* String value of the user's context */ int done = 0; /* true if a valid sid has been obtained */ /* Initialize the context. How this is done depends on whether diff --git a/libselinux/src/regex.c b/libselinux/src/regex.c index 73987d9f106389ec5b8e9108a31a95bbf4e839dc..16df67908aec2d82691d695bc9822f716a225e37 100644 --- a/libselinux/src/regex.c +++ b/libselinux/src/regex.c @@ -60,11 +60,13 @@ char const *regex_arch_string(void) struct regex_data { pcre2_code *regex; /* compiled regular expression */ +#ifndef AGGRESSIVE_FREE_AFTER_REGEX_MATCH /* * match data block required for the compiled * pattern in pcre2 */ pcre2_match_data *match_data; +#endif pthread_mutex_t match_mutex; }; @@ -84,11 +86,13 @@ int regex_prepare_data(struct regex_data **regex, char const *pattern_string, goto err; } +#ifndef AGGRESSIVE_FREE_AFTER_REGEX_MATCH (*regex)->match_data = pcre2_match_data_create_from_pattern((*regex)->regex, NULL); if (!(*regex)->match_data) { goto err; } +#endif return 0; err: @@ -138,10 +142,12 @@ int regex_load_mmap(struct mmap_area *mmap_area, struct regex_data **regex, if (rc != 1) goto err; +#ifndef AGGRESSIVE_FREE_AFTER_REGEX_MATCH (*regex)->match_data = pcre2_match_data_create_from_pattern((*regex)->regex, NULL); if (!(*regex)->match_data) goto err; +#endif *regex_compiled = true; } @@ -167,7 +173,7 @@ int regex_writef(struct regex_data *regex, FILE *fp, int do_write_precompregex) PCRE2_UCHAR *bytes = NULL; if (do_write_precompregex) { - /* encode the patter for serialization */ + /* encode the pattern for serialization */ rc = pcre2_serialize_encode((const pcre2_code **)®ex->regex, 1, &bytes, &serialized_size, NULL); if (rc != 1) { @@ -203,8 +209,12 @@ void regex_data_free(struct regex_data *regex) if (regex) { if (regex->regex) pcre2_code_free(regex->regex); + +#ifndef AGGRESSIVE_FREE_AFTER_REGEX_MATCH if (regex->match_data) pcre2_match_data_free(regex->match_data); +#endif + __pthread_mutex_destroy(®ex->match_mutex); free(regex); } @@ -213,10 +223,30 @@ void regex_data_free(struct regex_data *regex) int regex_match(struct regex_data *regex, char const *subject, int partial) { int rc; + pcre2_match_data *match_data; __pthread_mutex_lock(®ex->match_mutex); + +#ifdef AGGRESSIVE_FREE_AFTER_REGEX_MATCH + match_data = pcre2_match_data_create_from_pattern( + regex->regex, NULL); + if (match_data == NULL) { + __pthread_mutex_unlock(®ex->match_mutex); + return REGEX_ERROR; + } +#else + match_data = regex->match_data; +#endif + rc = pcre2_match( regex->regex, (PCRE2_SPTR)subject, PCRE2_ZERO_TERMINATED, 0, - partial ? PCRE2_PARTIAL_SOFT : 0, regex->match_data, NULL); + partial ? PCRE2_PARTIAL_SOFT : 0, match_data, NULL); + +#ifdef AGGRESSIVE_FREE_AFTER_REGEX_MATCH + // pcre2_match allocates heap and it won't be freed until + // pcre2_match_data_free, resulting in heap overhead. + pcre2_match_data_free(match_data); +#endif + __pthread_mutex_unlock(®ex->match_mutex); if (rc > 0) return REGEX_MATCH; @@ -257,6 +287,9 @@ struct regex_data *regex_data_create(void) { struct regex_data *regex_data = (struct regex_data *)calloc(1, sizeof(struct regex_data)); + if (!regex_data) + return NULL; + __pthread_mutex_init(®ex_data->match_mutex, NULL); return regex_data; } diff --git a/libselinux/src/selinux_internal.c b/libselinux/src/selinux_internal.c new file mode 100644 index 0000000000000000000000000000000000000000..c2be7c0a9128a8eff95f21af866c8112e3d3ba2f --- /dev/null +++ b/libselinux/src/selinux_internal.c @@ -0,0 +1,18 @@ +#include "selinux_internal.h" + +#include + + +#ifndef HAVE_STRLCPY +size_t strlcpy(char *dest, const char *src, size_t size) +{ + size_t ret = strlen(src); + + if (size) { + size_t len = (ret >= size) ? size - 1 : ret; + memcpy(dest, src, len); + dest[len] = '\0'; + } + return ret; +} +#endif /* HAVE_STRLCPY */ diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h index 297dcf26dee360168d0ac9586e20a28eb2929428..06f2c0383bc2c12a757e92033718d4ade71a837c 100644 --- a/libselinux/src/selinux_internal.h +++ b/libselinux/src/selinux_internal.h @@ -1,3 +1,6 @@ +#ifndef SELINUX_INTERNAL_H_ +#define SELINUX_INTERNAL_H_ + #include #include @@ -90,3 +93,9 @@ extern int selinux_page_size ; #define SELINUXCONFIG SELINUXDIR "config" extern int has_selinux_config ; + +#ifndef HAVE_STRLCPY +size_t strlcpy(char *dest, const char *src, size_t size); +#endif + +#endif /* SELINUX_INTERNAL_H_ */ diff --git a/libselinux/src/selinux_restorecon.c b/libselinux/src/selinux_restorecon.c index dea3adbcb69198519ea6527ed456c5db998df631..2953e87dad47e1c93a8f7519a1f72f235c97319c 100644 --- a/libselinux/src/selinux_restorecon.c +++ b/libselinux/src/selinux_restorecon.c @@ -432,10 +432,11 @@ static pthread_mutex_t fl_mutex = PTHREAD_MUTEX_INITIALIZER; * that matched. */ static int filespec_add(ino_t ino, const char *con, const char *file, - struct rest_flags *flags) + const struct rest_flags *flags) { file_spec_t *prevfl, *fl; - int h, ret; + uint32_t h; + int ret; struct stat64 sb; __pthread_mutex_lock(&fl_mutex); @@ -524,7 +525,8 @@ unlock_1: static void filespec_eval(void) { file_spec_t *fl; - int h, used, nel, len, longest; + uint32_t h; + size_t used, nel, len, longest; if (!fl_head) return; @@ -544,7 +546,7 @@ static void filespec_eval(void) } selinux_log(SELINUX_INFO, - "filespec hash table stats: %d elements, %d/%d buckets used, longest chain length %d\n", + "filespec hash table stats: %zu elements, %zu/%zu buckets used, longest chain length %zu\n", nel, used, HASH_BUCKETS, longest); } #else @@ -559,7 +561,7 @@ static void filespec_eval(void) static void filespec_destroy(void) { file_spec_t *fl, *tmp; - int h; + uint32_t h; if (!fl_head) return; @@ -629,16 +631,15 @@ out: #define DATA_APP_EL4 "/data/app/el4/" #define DATA_ACCOUNTS_ACCOUNT_0 "/data/accounts/account_0/" -static int restorecon_sb(const char *pathname, struct rest_flags *flags, bool first) +static int restorecon_sb(const char *pathname, const struct stat *sb, + const struct rest_flags *flags, bool first) { char *newcon = NULL; char *curcon = NULL; char *newtypecon = NULL; - int fd = -1, rc; - struct stat stat_buf; - bool updated = false; + int rc; const char *lookup_path = pathname; - float pc; + if (!strncmp(pathname, DATA_APP_EL1, sizeof(DATA_APP_EL1) - 1) || !strncmp(pathname, DATA_APP_EL2, sizeof(DATA_APP_EL2) - 1) || !strncmp(pathname, DATA_APP_EL3, sizeof(DATA_APP_EL3) - 1) || @@ -646,6 +647,7 @@ static int restorecon_sb(const char *pathname, struct rest_flags *flags, bool fi !strncmp(pathname, DATA_ACCOUNTS_ACCOUNT_0, sizeof(DATA_ACCOUNTS_ACCOUNT_0) - 1)) { goto out; } + if (rootpath) { if (strncmp(rootpath, lookup_path, rootpathlen) != 0) { selinux_log(SELINUX_ERROR, @@ -656,21 +658,13 @@ static int restorecon_sb(const char *pathname, struct rest_flags *flags, bool fi lookup_path += rootpathlen; } - fd = open(pathname, O_PATH | O_NOFOLLOW | O_EXCL); - if (fd < 0) - goto err; - - rc = fstat(fd, &stat_buf); - if (rc < 0) - goto err; - if (rootpath != NULL && lookup_path[0] == '\0') /* this is actually the root dir of the alt root. */ rc = selabel_lookup_raw(fc_sehandle, &newcon, "/", - stat_buf.st_mode); + sb->st_mode & S_IFMT); else rc = selabel_lookup_raw(fc_sehandle, &newcon, lookup_path, - stat_buf.st_mode); + sb->st_mode & S_IFMT); if (rc < 0) { if (errno == ENOENT) { @@ -679,10 +673,10 @@ static int restorecon_sb(const char *pathname, struct rest_flags *flags, bool fi "Warning no default label for %s\n", lookup_path); - goto out; /* no match, but not an error */ + return 0; /* no match, but not an error */ } - goto err; + return -1; } if (flags->progress) { @@ -690,7 +684,7 @@ static int restorecon_sb(const char *pathname, struct rest_flags *flags, bool fi fc_count++; if (fc_count % STAR_COUNT == 0) { if (flags->mass_relabel && efile_count > 0) { - pc = (fc_count < efile_count) ? (100.0 * + float pc = (fc_count < efile_count) ? (100.0 * fc_count / efile_count) : 100; fprintf(stdout, "\r%-.1f%%", (double)pc); } else { @@ -702,17 +696,19 @@ static int restorecon_sb(const char *pathname, struct rest_flags *flags, bool fi } if (flags->add_assoc) { - rc = filespec_add(stat_buf.st_ino, newcon, pathname, flags); + rc = filespec_add(sb->st_ino, newcon, pathname, flags); if (rc < 0) { selinux_log(SELINUX_ERROR, "filespec_add error: %s\n", pathname); - goto out1; + freecon(newcon); + return -1; } if (rc > 0) { /* Already an association and it took precedence. */ - goto out; + freecon(newcon); + return 0; } } @@ -720,7 +716,7 @@ static int restorecon_sb(const char *pathname, struct rest_flags *flags, bool fi selinux_log(SELINUX_INFO, "%s matched by %s\n", pathname, newcon); - if (fgetfilecon_raw(fd, &curcon) < 0) { + if (lgetfilecon_raw(pathname, &curcon) < 0) { if (errno != ENODATA) goto err; @@ -728,6 +724,8 @@ static int restorecon_sb(const char *pathname, struct rest_flags *flags, bool fi } if (curcon == NULL || strcmp(curcon, newcon) != 0) { + bool updated = false; + if (!flags->set_specctx && curcon && (is_context_customizable(curcon) > 0)) { if (flags->verbose) { @@ -753,7 +751,7 @@ static int restorecon_sb(const char *pathname, struct rest_flags *flags, bool fi } if (!flags->nochange) { - if (fsetfilecon(fd, newcon) < 0) + if (lsetfilecon(pathname, newcon) < 0) goto err; updated = true; } @@ -762,7 +760,9 @@ static int restorecon_sb(const char *pathname, struct rest_flags *flags, bool fi selinux_log(SELINUX_INFO, "%s %s from %s to %s\n", updated ? "Relabeled" : "Would relabel", - pathname, curcon, newcon); + pathname, + curcon ? curcon : "", + newcon); if (flags->syslog_changes && !flags->nochange) { if (curcon) @@ -778,8 +778,6 @@ static int restorecon_sb(const char *pathname, struct rest_flags *flags, bool fi out: rc = 0; out1: - if (fd >= 0) - close(fd); freecon(curcon); freecon(newcon); return rc; @@ -877,6 +875,7 @@ static void *selinux_restorecon_thread(void *arg) FTSENT *ftsent; int error; char ent_path[PATH_MAX]; + struct stat ent_st; bool first = false; if (state->parallel) @@ -973,12 +972,21 @@ loop_body: } /* fall through */ default: - strcpy(ent_path, ftsent->fts_path); + if (strlcpy(ent_path, ftsent->fts_path, sizeof(ent_path)) >= sizeof(ent_path)) { + selinux_log(SELINUX_ERROR, + "Path name too long on %s.\n", + ftsent->fts_path); + errno = ENAMETOOLONG; + state->error = -1; + state->abort = true; + goto finish; + } + ent_st = *ftsent->fts_statp; if (state->parallel) pthread_mutex_unlock(&state->mutex); - error = restorecon_sb(ent_path, &state->flags, + error = restorecon_sb(ent_path, &ent_st, &state->flags, first); if (state->parallel) { @@ -1116,6 +1124,10 @@ static int selinux_restorecon_common(const char *pathname_orig, pathname = realpath(pathname_orig, NULL); if (!pathname) { free(basename_cpy); + /* missing parent directory */ + if (state.flags.ignore_noent && errno == ENOENT) { + return 0; + } goto realpatherr; } } else { @@ -1129,6 +1141,9 @@ static int selinux_restorecon_common(const char *pathname_orig, free(dirname_cpy); if (!pathdnamer) { free(basename_cpy); + if (state.flags.ignore_noent && errno == ENOENT) { + return 0; + } goto realpatherr; } if (!strcmp(pathdnamer, "/")) @@ -1174,7 +1189,7 @@ static int selinux_restorecon_common(const char *pathname_orig, goto cleanup; } - error = restorecon_sb(pathname, &state.flags, true); + error = restorecon_sb(pathname, &sb, &state.flags, true); goto cleanup; } diff --git a/libselinux/src/sestatus.c b/libselinux/src/sestatus.c index 89c1f6216702d1b3775ac89509e2a38ca4752420..fbe6430155f6aef859adae724d55ce0b99c549f9 100644 --- a/libselinux/src/sestatus.c +++ b/libselinux/src/sestatus.c @@ -343,7 +343,6 @@ error: if (avc_using_threads) { fallback_netlink_thread = avc_create_thread(&avc_netlink_loop); - avc_netlink_trouble = 0; } fallback_sequence = 0; diff --git a/libselinux/src/setrans_client.c b/libselinux/src/setrans_client.c index faa126813a7755a88cc8acefb71f9f8574ea5b58..920f9032c3f65c62e4ff1caa21222de54a7ffab4 100644 --- a/libselinux/src/setrans_client.c +++ b/libselinux/src/setrans_client.c @@ -66,7 +66,13 @@ static int setransd_open(void) memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, SETRANS_UNIX_SOCKET, sizeof(addr.sun_path)); + + if (strlcpy(addr.sun_path, SETRANS_UNIX_SOCKET, sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) { + close(fd); + errno = EOVERFLOW; + return -1; + } + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { close(fd); return -1; diff --git a/libselinux/src/setup.py b/libselinux/src/setup.py index 71e69a107f0194f0a5847ea46a56588c2eef678f..48007379f86ffb741890492089d3908bcb4e8785 100644 --- a/libselinux/src/setup.py +++ b/libselinux/src/setup.py @@ -1,10 +1,10 @@ #!/usr/bin/python3 -from distutils.core import Extension, setup +from setuptools import Extension, setup setup( name="selinux", - version="3.4", + version="3.5", description="SELinux python 3 bindings", author="SELinux Project", author_email="selinux@vger.kernel.org", diff --git a/libselinux/src/sha1.c b/libselinux/src/sha1.c index a848467785f3a13aa448ac60251c9e1c29f0837d..9d51e04ac33127a248cd408d61220c6b68a23927 100644 --- a/libselinux/src/sha1.c +++ b/libselinux/src/sha1.c @@ -11,7 +11,7 @@ // Modified to: // - stop symbols being exported for libselinux shared library - October 2015 // Richard Haines -// - Not cast the workspace from a byte array to a CHAR64LONG16 due to alignment isses. +// - Not cast the workspace from a byte array to a CHAR64LONG16 due to alignment issues. // Fixes: // sha1.c:73:33: error: cast from 'uint8_t *' (aka 'unsigned char *') to 'CHAR64LONG16 *' increases required alignment from 1 to 4 [-Werror,-Wcast-align] // CHAR64LONG16* block = (CHAR64LONG16*) workspace; diff --git a/libselinux/src/stringrep.c b/libselinux/src/stringrep.c index 2fe69f4391aeee0502cf85921b990a08c0ccaed5..d2237d1c15320a0e4e0a67678e272e95e6679248 100644 --- a/libselinux/src/stringrep.c +++ b/libselinux/src/stringrep.c @@ -63,6 +63,9 @@ static struct discover_class_node * discover_class(const char *s) return NULL; } + if (strchr(s, '/') != NULL) + return NULL; + /* allocate a node */ node = malloc(sizeof(struct discover_class_node)); if (node == NULL) @@ -79,7 +82,10 @@ static struct discover_class_node * discover_class(const char *s) goto err2; /* load up class index */ - snprintf(path, sizeof path, "%s/class/%s/index", selinux_mnt,s); + ret = snprintf(path, sizeof path, "%s/class/%s/index", selinux_mnt,s); + if (ret < 0 || (size_t)ret >= sizeof path) + goto err3; + fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) goto err3; @@ -94,7 +100,10 @@ static struct discover_class_node * discover_class(const char *s) goto err3; /* load up permission indices */ - snprintf(path, sizeof path, "%s/class/%s/perms",selinux_mnt,s); + ret = snprintf(path, sizeof path, "%s/class/%s/perms",selinux_mnt,s); + if (ret < 0 || (size_t)ret >= sizeof path) + goto err3; + dir = opendir(path); if (dir == NULL) goto err3; @@ -104,7 +113,10 @@ static struct discover_class_node * discover_class(const char *s) unsigned int value; struct stat m; - snprintf(path, sizeof path, "%s/class/%s/perms/%s", selinux_mnt,s,dentry->d_name); + ret = snprintf(path, sizeof path, "%s/class/%s/perms/%s", selinux_mnt,s,dentry->d_name); + if (ret < 0 || (size_t)ret >= sizeof path) + goto err4; + fd = open(path, O_RDONLY | O_CLOEXEC); if (fd < 0) goto err4; diff --git a/libselinux/utils/.gitignore b/libselinux/utils/.gitignore index 3ef343747c500e695f5e3a0431fbe79af216eb10..b19b94a87fd474d51a7b54f5ded29b51f93982f6 100644 --- a/libselinux/utils/.gitignore +++ b/libselinux/utils/.gitignore @@ -9,6 +9,7 @@ getdefaultcon getenforce getfilecon getpidcon +getpidprevcon getsebool getseuser matchpathcon diff --git a/libselinux/utils/Makefile b/libselinux/utils/Makefile index 801066cb051a8a8b3e39fce02d82e4c91c5172e0..f3cedc111db0463c49aaa57b24e433e2ac39c83b 100644 --- a/libselinux/utils/Makefile +++ b/libselinux/utils/Makefile @@ -32,7 +32,7 @@ CFLAGS ?= -O -Wall -W -Wundef -Wformat-y2k -Wformat-security -Winit-self -Wmissi -Wno-missing-field-initializers -Wno-sign-compare \ -Wno-format-nonliteral -Wframe-larger-than=$(MAX_STACK_SIZE) -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 \ -fstack-protector-all --param=ssp-buffer-size=4 -fexceptions \ - -fasynchronous-unwind-tables -fdiagnostics-show-option -funit-at-a-time \ + -fasynchronous-unwind-tables -fdiagnostics-show-option \ -Werror -Wno-aggregate-return -Wno-redundant-decls -Wstrict-overflow=5 \ $(EXTRA_CFLAGS) diff --git a/libselinux/utils/compute_create.c b/libselinux/utils/compute_create.c index c6481f4b01c18ea35cfa8ef32a9594da5e020a9b..5401fe967a532a04fab720e266933e3f08a63a89 100644 --- a/libselinux/utils/compute_create.c +++ b/libselinux/utils/compute_create.c @@ -10,10 +10,11 @@ int main(int argc, char **argv) { char *buf; security_class_t tclass; + const char *objname; int ret; - if (argc != 4) { - fprintf(stderr, "usage: %s scontext tcontext tclass\n", + if (argc != 4 && argc != 5) { + fprintf(stderr, "usage: %s scontext tcontext tclass [objname]\n", argv[0]); exit(1); } @@ -34,7 +35,9 @@ int main(int argc, char **argv) exit(2); } - ret = security_compute_create(argv[1], argv[2], tclass, &buf); + objname = (argc == 5) ? argv[4] : NULL; + + ret = security_compute_create_name(argv[1], argv[2], tclass, objname, &buf); if (ret < 0) { fprintf(stderr, "%s: security_compute_create failed: %s\n", argv[0], strerror(errno)); diff --git a/libselinux/utils/getpidprevcon.c b/libselinux/utils/getpidprevcon.c new file mode 100644 index 0000000000000000000000000000000000000000..662ad500a8e237b13cfe5ffd5a465dcd0005cb9a --- /dev/null +++ b/libselinux/utils/getpidprevcon.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include +#include + +int main(int argc, char **argv) +{ + pid_t pid; + char *buf; + int rc; + + if (argc != 2) { + fprintf(stderr, "usage: %s pid\n", argv[0]); + exit(1); + } + + if (sscanf(argv[1], "%d", &pid) != 1) { + fprintf(stderr, "%s: invalid pid %s\n", argv[0], argv[1]); + exit(2); + } + + rc = getpidprevcon(pid, &buf); + if (rc < 0) { + fprintf(stderr, "%s: getpidprevcon() failed: %s\n", argv[0], strerror(errno)); + exit(3); + } + + printf("%s\n", buf); + freecon(buf); + exit(EXIT_SUCCESS); +} diff --git a/libselinux/utils/selabel_lookup_best_match.c b/libselinux/utils/selabel_lookup_best_match.c index a4af0679807918008b0509abc36ffbaea74d6253..e816c04b530fc0a64d0f099fc32b880d3fa5298b 100644 --- a/libselinux/utils/selabel_lookup_best_match.c +++ b/libselinux/utils/selabel_lookup_best_match.c @@ -30,7 +30,7 @@ static __attribute__ ((__noreturn__)) void usage(const char *progname) exit(1); } -static mode_t string_to_mode(char *s) +static mode_t string_to_mode(const char *s) { switch (s[0]) { case 'b': @@ -53,7 +53,7 @@ static mode_t string_to_mode(char *s) int main(int argc, char **argv) { - int raw = 0, mode = 0, rc, opt, i, num_links, string_len; + int raw = 0, mode = 0, rc, opt, i, num_links; char *validate = NULL, *path = NULL, *context = NULL, *file = NULL; char **links = NULL; @@ -101,13 +101,11 @@ int main(int argc, char **argv) } for (i = optind, num_links = 0; i < argc; i++, num_links++) { - string_len = strlen(argv[i]) + 1; - links[num_links] = malloc(string_len); + links[num_links] = strdup(argv[i]); if (!links[num_links]) { - fprintf(stderr, "ERROR: malloc failed.\n"); + fprintf(stderr, "ERROR: strdup failed.\n"); exit(1); } - strcpy(links[num_links], argv[i]); } } diff --git a/libsepol/COPYING b/libsepol/LICENSE similarity index 100% rename from libsepol/COPYING rename to libsepol/LICENSE diff --git a/libsepol/VERSION b/libsepol/VERSION index 2f4b60750dc3500b0e4cf08f316a960a7ca42b40..5a958026daa3208cb329c403433beb56abd5c036 100644 --- a/libsepol/VERSION +++ b/libsepol/VERSION @@ -1 +1 @@ -3.4 +3.5 diff --git a/libsepol/cil/src/cil_build_ast.c b/libsepol/cil/src/cil_build_ast.c index 26fa79069b96fb590c014f2e7e86efd19cab8fd3..4177c9f6778c7a28929aae9f2cd9c807e8f56484 100644 --- a/libsepol/cil/src/cil_build_ast.c +++ b/libsepol/cil/src/cil_build_ast.c @@ -4619,7 +4619,6 @@ int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, str } else { cil_log(CIL_ERR, "Invalid file type \"%s\"\n", file_type); } - rc = SEPOL_ERR; goto exit; } context_node = parse_current->next->next->next->next; diff --git a/libsepol/cil/src/cil_post.c b/libsepol/cil/src/cil_post.c index 714ce227e5f9f4b2b6f06245407bfb15219ffc52..a7c66eadb53e9f7124ceb876c78b25767277f96d 100644 --- a/libsepol/cil/src/cil_post.c +++ b/libsepol/cil/src/cil_post.c @@ -1191,10 +1191,9 @@ static int __cil_cat_expr_range_to_bitmap_helper(struct cil_list_item *i1, struc struct cil_tree_node *n2 = d2->nodes->head->data; struct cil_cat *c1 = (struct cil_cat *)d1; struct cil_cat *c2 = (struct cil_cat *)d2; - int i; if (n1->flavor == CIL_CATSET || n2->flavor == CIL_CATSET) { - cil_log(CIL_ERR, "Category sets cannont be used in a category range\n"); + cil_log(CIL_ERR, "Category sets cannot be used in a category range\n"); goto exit; } @@ -1213,12 +1212,10 @@ static int __cil_cat_expr_range_to_bitmap_helper(struct cil_list_item *i1, struc goto exit; } - for (i = c1->value; i <= c2->value; i++) { - if (ebitmap_set_bit(bitmap, i, 1)) { - cil_log(CIL_ERR, "Failed to set cat bit\n"); - ebitmap_destroy(bitmap); - goto exit; - } + if (ebitmap_init_range(bitmap, c1->value, c2->value)) { + cil_log(CIL_ERR, "Failed to set cat bit\n"); + ebitmap_destroy(bitmap); + goto exit; } return SEPOL_OK; @@ -1234,7 +1231,6 @@ static int __cil_permissionx_expr_range_to_bitmap_helper(struct cil_list_item *i char *p2 = i2->data; uint16_t v1; uint16_t v2; - uint32_t i; rc = __cil_permx_str_to_int(p1, &v1); if (rc != SEPOL_OK) { @@ -1246,12 +1242,10 @@ static int __cil_permissionx_expr_range_to_bitmap_helper(struct cil_list_item *i goto exit; } - for (i = v1; i <= v2; i++) { - if (ebitmap_set_bit(bitmap, i, 1)) { - cil_log(CIL_ERR, "Failed to set permissionx bit\n"); - ebitmap_destroy(bitmap); - goto exit; - } + if (ebitmap_init_range(bitmap, v1, v2)) { + cil_log(CIL_ERR, "Failed to set permissionx bits\n"); + ebitmap_destroy(bitmap); + goto exit; } return SEPOL_OK; @@ -1318,9 +1312,7 @@ static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, enum cil_flavor op = (enum cil_flavor)(uintptr_t)curr->data; if (op == CIL_ALL) { - ebitmap_init(&b1); /* all zeros */ - rc = ebitmap_not(&tmp, &b1, max); - ebitmap_destroy(&b1); + rc = ebitmap_init_range(&tmp, 0, max - 1); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to expand 'all' operator\n"); ebitmap_destroy(&tmp); @@ -1328,19 +1320,15 @@ static int __cil_expr_to_bitmap(struct cil_list *expr, ebitmap_t *out, int max, } } else if (op == CIL_RANGE) { if (flavor == CIL_CAT) { - ebitmap_init(&tmp); rc = __cil_cat_expr_range_to_bitmap_helper(curr->next, curr->next->next, &tmp); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to expand category range\n"); - ebitmap_destroy(&tmp); goto exit; } } else if (flavor == CIL_PERMISSIONX) { - ebitmap_init(&tmp); rc = __cil_permissionx_expr_range_to_bitmap_helper(curr->next, curr->next->next, &tmp); if (rc != SEPOL_OK) { cil_log(CIL_INFO, "Failed to expand category range\n"); - ebitmap_destroy(&tmp); goto exit; } } else { @@ -2302,6 +2290,7 @@ static int __cil_post_process_context_rules(struct cil_sort *sort, int (*compar) } else { removed++; if (!db->multiple_decls || concompar(&sort->array[i], &sort->array[j]) != 0) { + rc = SEPOL_ERR; conflicting++; if (log_level >= CIL_WARN) { struct cil_list_item li; @@ -2309,7 +2298,6 @@ static int __cil_post_process_context_rules(struct cil_sort *sort, int (*compar) li.flavor = flavor; if (conflicting == 1) { cil_log(CIL_WARN, "Found conflicting %s rules\n", flavor_str); - rc = SEPOL_ERR; li.data = sort->array[i]; rc2 = cil_tree_walk(db->ast->root, __cil_post_report_conflict, NULL, NULL, &li); diff --git a/libsepol/cil/src/cil_resolve_ast.c b/libsepol/cil/src/cil_resolve_ast.c index f5e22c97f37d01c9d4207427da42dfbf0487b937..d2bfdc8127ea65d10ef249c5894416ed2c621df1 100644 --- a/libsepol/cil/src/cil_resolve_ast.c +++ b/libsepol/cil/src/cil_resolve_ast.c @@ -778,7 +778,7 @@ int cil_resolve_classcommon(struct cil_tree_node *current, void *extra_args) class = (struct cil_class *)class_datum; common = (struct cil_class *)common_datum; if (class->common != NULL) { - cil_log(CIL_ERR, "class cannot be associeated with more than one common\n"); + cil_log(CIL_ERR, "class cannot be associated with more than one common\n"); rc = SEPOL_ERR; goto exit; } diff --git a/libsepol/include/sepol/errcodes.h b/libsepol/include/sepol/errcodes.h index 6e9ff3161eec8943000f07028ce72d620e41157a..e5fe71e36590e4324ea0d4e60f46810ce9e41437 100644 --- a/libsepol/include/sepol/errcodes.h +++ b/libsepol/include/sepol/errcodes.h @@ -16,15 +16,14 @@ extern "C" { * codes that don't map to system error codes should be defined * outside of the range of system error codes. */ -#define SEPOL_ERR -1 -#define SEPOL_ENOTSUP -2 /* feature not supported in module language */ -#define SEPOL_EREQ -3 /* requirements not met */ +#define SEPOL_ERR (-1) +#define SEPOL_ENOTSUP (-2) /* feature not supported in module language */ +#define SEPOL_EREQ (-3) /* requirements not met */ /* Error codes that map to system error codes */ -#define SEPOL_ENOMEM -ENOMEM -#define SEPOL_ERANGE -ERANGE -#define SEPOL_EEXIST -EEXIST -#define SEPOL_ENOENT -ENOENT +#define SEPOL_ENOMEM (-ENOMEM) +#define SEPOL_EEXIST (-EEXIST) +#define SEPOL_ENOENT (-ENOENT) #ifdef __cplusplus } diff --git a/libsepol/include/sepol/policydb/avtab.h b/libsepol/include/sepol/policydb/avtab.h index 10ecde9aaf820fd942600e537fe0f17ad0401f88..e4c48576177e12e022e46b716fc04b5eadab50ce 100644 --- a/libsepol/include/sepol/policydb/avtab.h +++ b/libsepol/include/sepol/policydb/avtab.h @@ -112,7 +112,7 @@ extern avtab_datum_t *avtab_search(avtab_t * h, avtab_key_t * k); extern void avtab_destroy(avtab_t * h); -extern int avtab_map(avtab_t * h, +extern int avtab_map(const avtab_t * h, int (*apply) (avtab_key_t * k, avtab_datum_t * d, void *args), void *args); diff --git a/libsepol/include/sepol/policydb/constraint.h b/libsepol/include/sepol/policydb/constraint.h index b91fc4e9f2fb15db5b28a6089e9221a476d49eca..82335e2192ad349ead096bf3dc8e3c520b6e1cb1 100644 --- a/libsepol/include/sepol/policydb/constraint.h +++ b/libsepol/include/sepol/policydb/constraint.h @@ -18,7 +18,6 @@ #ifndef _SEPOL_POLICYDB_CONSTRAINT_H_ #define _SEPOL_POLICYDB_CONSTRAINT_H_ -#include #include #include @@ -70,8 +69,6 @@ typedef struct constraint_node { struct constraint_node *next; /* next constraint */ } constraint_node_t; -struct policydb; - extern int constraint_expr_init(constraint_expr_t * expr); extern void constraint_expr_destroy(constraint_expr_t * expr); diff --git a/libsepol/include/sepol/policydb/ebitmap.h b/libsepol/include/sepol/policydb/ebitmap.h index 81d0c7a67347809112328e36d8c777f94aeaf22a..85b7ccfb260423d1c54cd142c4e4dccd075c1095 100644 --- a/libsepol/include/sepol/policydb/ebitmap.h +++ b/libsepol/include/sepol/policydb/ebitmap.h @@ -94,6 +94,7 @@ extern int ebitmap_contains(const ebitmap_t * e1, const ebitmap_t * e2); extern int ebitmap_match_any(const ebitmap_t *e1, const ebitmap_t *e2); extern int ebitmap_get_bit(const ebitmap_t * e, unsigned int bit); extern int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value); +extern int ebitmap_init_range(ebitmap_t * e, unsigned int minbit, unsigned int maxbit); extern unsigned int ebitmap_highest_set_bit(const ebitmap_t * e); extern void ebitmap_destroy(ebitmap_t * e); extern int ebitmap_read(ebitmap_t * e, void *fp); diff --git a/libsepol/include/sepol/policydb/policydb.h b/libsepol/include/sepol/policydb/policydb.h index de0068a6c6f270cf3b18db3f3df2d7a1566cd99d..ef1a014a513003d4cd9428e8950bb7f7480cb37f 100644 --- a/libsepol/include/sepol/policydb/policydb.h +++ b/libsepol/include/sepol/policydb/policydb.h @@ -251,9 +251,9 @@ typedef struct class_perm_node { struct class_perm_node *next; } class_perm_node_t; -#define xperm_test(x, p) (UINT32_C(1) & (p[x >> 5] >> (x & 0x1f))) -#define xperm_set(x, p) (p[x >> 5] |= (UINT32_C(1) << (x & 0x1f))) -#define xperm_clear(x, p) (p[x >> 5] &= ~(UINT32_C(1) << (x & 0x1f))) +#define xperm_test(x, p) (UINT32_C(1) & ((p)[(x) >> 5] >> ((x) & 0x1f))) +#define xperm_set(x, p) ((p)[(x) >> 5] |= (UINT32_C(1) << ((x) & 0x1f))) +#define xperm_clear(x, p) ((p)[(x) >> 5] &= ~(UINT32_C(1) << ((x) & 0x1f))) #define EXTENDED_PERMS_LEN 8 typedef struct av_extended_perms { @@ -795,9 +795,9 @@ extern int policydb_set_target_platform(policydb_t *p, int platform); #define policydb_has_boundary_feature(p) \ (((p)->policy_type == POLICY_KERN \ - && p->policyvers >= POLICYDB_VERSION_BOUNDARY) || \ + && (p)->policyvers >= POLICYDB_VERSION_BOUNDARY) || \ ((p)->policy_type != POLICY_KERN \ - && p->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY)) + && (p)->policyvers >= MOD_POLICYDB_VERSION_BOUNDARY)) /* the config flags related to unknown classes/perms are bits 2 and 3 */ #define DENY_UNKNOWN SEPOL_DENY_UNKNOWN diff --git a/libsepol/include/sepol/policydb/util.h b/libsepol/include/sepol/policydb/util.h index ee236a25fafe696a97b68f4390e231619584c984..db8da213f89ff18a41ab5c159f14bf32736a9c30 100644 --- a/libsepol/include/sepol/policydb/util.h +++ b/libsepol/include/sepol/policydb/util.h @@ -23,6 +23,8 @@ #ifndef __SEPOL_UTIL_H__ #define __SEPOL_UTIL_H__ +#include + #ifdef __cplusplus extern "C" { #endif diff --git a/libsepol/src/avtab.c b/libsepol/src/avtab.c index 7920b60a3a430277456382251c5db2550117a66f..82fec783e0c3712171eb396ca9d4eb6f3b79613d 100644 --- a/libsepol/src/avtab.c +++ b/libsepol/src/avtab.c @@ -330,7 +330,7 @@ void avtab_destroy(avtab_t * h) h->mask = 0; } -int avtab_map(avtab_t * h, +int avtab_map(const avtab_t * h, int (*apply) (avtab_key_t * k, avtab_datum_t * d, void *args), void *args) { diff --git a/libsepol/src/ebitmap.c b/libsepol/src/ebitmap.c index bd98c0f8cbea0e1063638420ebc92a064b783d4a..3ec1042fe70a2f931d42e87890a0ca2c3ca804e2 100644 --- a/libsepol/src/ebitmap.c +++ b/libsepol/src/ebitmap.c @@ -31,7 +31,6 @@ int ebitmap_or(ebitmap_t * dst, const ebitmap_t * e1, const ebitmap_t * e2) ebitmap_destroy(dst); return -ENOMEM; } - memset(new, 0, sizeof(ebitmap_node_t)); if (n1 && n2 && n1->startbit == n2->startbit) { new->startbit = n1->startbit; new->map = n1->map | n2->map; @@ -74,41 +73,143 @@ int ebitmap_union(ebitmap_t * dst, const ebitmap_t * e1) int ebitmap_and(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) { - unsigned int i, length = min(ebitmap_length(e1), ebitmap_length(e2)); + const ebitmap_node_t *n1, *n2; + ebitmap_node_t *new, *prev = NULL; + ebitmap_init(dst); - for (i=0; i < length; i++) { - if (ebitmap_get_bit(e1, i) && ebitmap_get_bit(e2, i)) { - int rc = ebitmap_set_bit(dst, i, 1); - if (rc < 0) - return rc; + + n1 = e1->node; + n2 = e2->node; + while (n1 && n2) { + if (n1->startbit == n2->startbit) { + if (n1->map & n2->map) { + new = malloc(sizeof(ebitmap_node_t)); + if (!new) { + ebitmap_destroy(dst); + return -ENOMEM; + } + new->startbit = n1->startbit; + new->map = n1->map & n2->map; + new->next = NULL; + + if (prev) + prev->next = new; + else + dst->node = new; + prev = new; + } + + n1 = n1->next; + n2 = n2->next; + } else if (n1->startbit > n2->startbit) { + n2 = n2->next; + } else { + n1 = n1->next; } } + + if (prev) + dst->highbit = prev->startbit + MAPSIZE; + return 0; } int ebitmap_xor(ebitmap_t *dst, const ebitmap_t *e1, const ebitmap_t *e2) { - unsigned int i, length = max(ebitmap_length(e1), ebitmap_length(e2)); + const ebitmap_node_t *n1, *n2; + ebitmap_node_t *new, *prev = NULL; + uint32_t startbit; + MAPTYPE map; + ebitmap_init(dst); - for (i=0; i < length; i++) { - int val = ebitmap_get_bit(e1, i) ^ ebitmap_get_bit(e2, i); - int rc = ebitmap_set_bit(dst, i, val); - if (rc < 0) - return rc; + + n1 = e1->node; + n2 = e2->node; + while (n1 || n2) { + if (n1 && n2 && n1->startbit == n2->startbit) { + startbit = n1->startbit; + map = n1->map ^ n2->map; + n1 = n1->next; + n2 = n2->next; + } else if (!n2 || (n1 && n1->startbit < n2->startbit)) { + startbit = n1->startbit; + map = n1->map; + n1 = n1->next; + } else { + startbit = n2->startbit; + map = n2->map; + n2 = n2->next; + } + + if (map != 0) { + new = malloc(sizeof(ebitmap_node_t)); + if (!new) { + ebitmap_destroy(dst); + return -ENOMEM; + } + new->startbit = startbit; + new->map = map; + new->next = NULL; + if (prev) + prev->next = new; + else + dst->node = new; + prev = new; + } } + + if (prev) + dst->highbit = prev->startbit + MAPSIZE; + return 0; } int ebitmap_not(ebitmap_t *dst, const ebitmap_t *e1, unsigned int maxbit) { - unsigned int i; + const ebitmap_node_t *n; + ebitmap_node_t *new, *prev = NULL; + uint32_t startbit, cur_startbit; + MAPTYPE map; + ebitmap_init(dst); - for (i=0; i < maxbit; i++) { - int val = ebitmap_get_bit(e1, i); - int rc = ebitmap_set_bit(dst, i, !val); - if (rc < 0) - return rc; + + n = e1->node; + for (cur_startbit = 0; cur_startbit < maxbit; cur_startbit += MAPSIZE) { + if (n && n->startbit == cur_startbit) { + startbit = n->startbit; + map = ~n->map; + + n = n->next; + } else { + startbit = cur_startbit; + map = ~((MAPTYPE) 0); + } + + if (maxbit - cur_startbit < MAPSIZE) + map &= (((MAPTYPE)1) << (maxbit - cur_startbit)) - 1; + + if (map != 0) { + new = malloc(sizeof(ebitmap_node_t)); + if (!new) { + ebitmap_destroy(dst); + return -ENOMEM; + } + + new->startbit = startbit; + new->map = map; + new->next = NULL; + + if (prev) + prev->next = new; + else + dst->node = new; + prev = new; + } } + + if (prev) + dst->highbit = prev->startbit + MAPSIZE; + return 0; } @@ -188,7 +289,6 @@ int ebitmap_cpy(ebitmap_t * dst, const ebitmap_t * src) ebitmap_destroy(dst); return -ENOMEM; } - memset(new, 0, sizeof(ebitmap_node_t)); new->startbit = n->startbit; new->map = n->map; new->next = 0; @@ -328,7 +428,6 @@ int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value) new = (ebitmap_node_t *) malloc(sizeof(ebitmap_node_t)); if (!new) return -ENOMEM; - memset(new, 0, sizeof(ebitmap_node_t)); new->startbit = startbit; new->map = (MAPBIT << (bit - new->startbit)); @@ -349,6 +448,55 @@ int ebitmap_set_bit(ebitmap_t * e, unsigned int bit, int value) return 0; } +int ebitmap_init_range(ebitmap_t * e, unsigned int minbit, unsigned int maxbit) +{ + ebitmap_node_t *new, *prev = NULL; + uint32_t minstartbit = minbit & ~(MAPSIZE - 1); + uint32_t maxstartbit = maxbit & ~(MAPSIZE - 1); + uint32_t minhighbit = minstartbit + MAPSIZE; + uint32_t maxhighbit = maxstartbit + MAPSIZE; + uint32_t startbit; + MAPTYPE mask; + + ebitmap_init(e); + + if (minbit > maxbit) + return -EINVAL; + + if (minhighbit == 0 || maxhighbit == 0) + return -EOVERFLOW; + + for (startbit = minstartbit; startbit <= maxstartbit; startbit += MAPSIZE) { + new = malloc(sizeof(ebitmap_node_t)); + if (!new) + return -ENOMEM; + + new->next = NULL; + new->startbit = startbit; + + if (startbit != minstartbit && startbit != maxstartbit) { + new->map = ~((MAPTYPE)0); + } else if (startbit != maxstartbit) { + new->map = ~((MAPTYPE)0) << (minbit - startbit); + } else if (startbit != minstartbit) { + new->map = ~((MAPTYPE)0) >> (MAPSIZE - (maxbit - startbit + 1)); + } else { + mask = ~((MAPTYPE)0) >> (MAPSIZE - (maxbit - minbit + 1)); + new->map = (mask << (minbit - startbit)); + } + + if (prev) + prev->next = new; + else + e->node = new; + prev = new; + } + + e->highbit = maxhighbit; + + return 0; +} + unsigned int ebitmap_highest_set_bit(const ebitmap_t * e) { const ebitmap_node_t *n; diff --git a/libsepol/src/kernel_to_cil.c b/libsepol/src/kernel_to_cil.c index 9128ac553315939b3a31dfec4901dec045a7f03e..ad4121d50ae1ee31d7d1fde979275a9a78ad0470 100644 --- a/libsepol/src/kernel_to_cil.c +++ b/libsepol/src/kernel_to_cil.c @@ -1626,7 +1626,7 @@ exit: return rc; } -#define next_bit_in_range(i, p) ((i + 1 < sizeof(p)*8) && xperm_test((i + 1), p)) +#define next_bit_in_range(i, p) (((i) + 1 < sizeof(p)*8) && xperm_test(((i) + 1), p)) static char *xperms_to_str(avtab_extended_perms_t *xperms) { @@ -1894,7 +1894,7 @@ static int map_filename_trans_to_str(hashtab_key_t key, void *data, void *arg) ebitmap_for_each_positive_bit(&datum->stypes, node, bit) { src = pdb->p_type_val_to_name[bit]; rc = strs_create_and_add(strs, - "(typetransition %s %s %s %s %s)", + "(typetransition %s %s %s \"%s\" %s)", 5, src, tgt, class, filename, new); if (rc) return rc; diff --git a/libsepol/src/kernel_to_conf.c b/libsepol/src/kernel_to_conf.c index 63dffd9b47f0ff565b235b8f977b23b16fa20f43..73b72b5dfd29b2b2818d4f2c6d480143dbec4610 100644 --- a/libsepol/src/kernel_to_conf.c +++ b/libsepol/src/kernel_to_conf.c @@ -591,16 +591,21 @@ static int write_class_and_common_rules_to_conf(FILE *out, struct policydb *pdb) class = pdb->class_val_to_struct[i]; if (!class) continue; name = pdb->p_class_val_to_name[i]; - sepol_printf(out, "class %s", name); - if (class->comkey) { - sepol_printf(out, " inherits %s", class->comkey); - } perms = class_or_common_perms_to_str(&class->permissions); - if (perms) { - sepol_printf(out, " { %s }", perms); - free(perms); + /* Do not write empty classes, their declaration was alreedy + * printed in write_class_decl_rules_to_conf() */ + if (perms || class->comkey) { + sepol_printf(out, "class %s", name); + if (class->comkey) { + sepol_printf(out, " inherits %s", class->comkey); + } + + if (perms) { + sepol_printf(out, " { %s }", perms); + free(perms); + } + sepol_printf(out, "\n"); } - sepol_printf(out, "\n"); } exit: diff --git a/libsepol/src/link.c b/libsepol/src/link.c index 7e8313cbc3912a9047f9e7a0889e3a4f0674d3b2..cbe4cea40123baa02bce1388696ddd917b0c2e23 100644 --- a/libsepol/src/link.c +++ b/libsepol/src/link.c @@ -958,26 +958,28 @@ static int alias_copy_callback(hashtab_key_t key, hashtab_datum_t datum, /*********** callbacks that fix bitmaps ***********/ -static int type_set_convert(type_set_t * types, type_set_t * dst, - policy_module_t * mod, link_state_t * state - __attribute__ ((unused))) +static int ebitmap_convert(const ebitmap_t *src, ebitmap_t *dst, const uint32_t *map) { - unsigned int i; - ebitmap_node_t *tnode; - ebitmap_for_each_positive_bit(&types->types, tnode, i) { - assert(mod->map[SYM_TYPES][i]); - if (ebitmap_set_bit - (&dst->types, mod->map[SYM_TYPES][i] - 1, 1)) { - goto cleanup; - } - } - ebitmap_for_each_positive_bit(&types->negset, tnode, i) { - assert(mod->map[SYM_TYPES][i]); - if (ebitmap_set_bit - (&dst->negset, mod->map[SYM_TYPES][i] - 1, 1)) { - goto cleanup; - } + unsigned int bit; + ebitmap_node_t *node; + ebitmap_for_each_positive_bit(src, node, bit) { + assert(map[bit]); + if (ebitmap_set_bit(dst, map[bit] - 1, 1)) + return -1; } + + return 0; +} + +static int type_set_convert(const type_set_t * types, type_set_t * dst, + const policy_module_t * mod) +{ + if (ebitmap_convert(&types->types, &dst->types, mod->map[SYM_TYPES])) + goto cleanup; + + if (ebitmap_convert(&types->negset, &dst->negset, mod->map[SYM_TYPES])) + goto cleanup; + dst->flags = types->flags; return 0; @@ -988,13 +990,13 @@ static int type_set_convert(type_set_t * types, type_set_t * dst, /* OR 2 typemaps together and at the same time map the src types to * the correct values in the dst typeset. */ -static int type_set_or_convert(type_set_t * types, type_set_t * dst, - policy_module_t * mod, link_state_t * state) +static int type_set_or_convert(const type_set_t * types, type_set_t * dst, + const policy_module_t * mod) { type_set_t ts_tmp; type_set_init(&ts_tmp); - if (type_set_convert(types, &ts_tmp, mod, state) == -1) { + if (type_set_convert(types, &ts_tmp, mod) == -1) { goto cleanup; } if (type_set_or_eq(dst, &ts_tmp)) { @@ -1004,7 +1006,6 @@ static int type_set_or_convert(type_set_t * types, type_set_t * dst, return 0; cleanup: - ERR(state->handle, "Out of memory!"); type_set_destroy(&ts_tmp); return -1; } @@ -1012,18 +1013,11 @@ static int type_set_or_convert(type_set_t * types, type_set_t * dst, static int role_set_or_convert(role_set_t * roles, role_set_t * dst, policy_module_t * mod, link_state_t * state) { - unsigned int i; ebitmap_t tmp; - ebitmap_node_t *rnode; ebitmap_init(&tmp); - ebitmap_for_each_positive_bit(&roles->roles, rnode, i) { - assert(mod->map[SYM_ROLES][i]); - if (ebitmap_set_bit - (&tmp, mod->map[SYM_ROLES][i] - 1, 1)) { - goto cleanup; - } - } + if (ebitmap_convert(&roles->roles, &tmp, mod->map[SYM_ROLES])) + goto cleanup; if (ebitmap_union(&dst->roles, &tmp)) { goto cleanup; } @@ -1088,13 +1082,11 @@ static int mls_range_convert(mls_semantic_range_t * src, mls_semantic_range_t * static int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { - unsigned int i; char *id = key; role_datum_t *role, *dest_role = NULL; link_state_t *state = (link_state_t *) data; ebitmap_t e_tmp; policy_module_t *mod = state->cur; - ebitmap_node_t *rnode; hashtab_t role_tab; role = (role_datum_t *) datum; @@ -1111,30 +1103,20 @@ static int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum, } ebitmap_init(&e_tmp); - ebitmap_for_each_positive_bit(&role->dominates, rnode, i) { - assert(mod->map[SYM_ROLES][i]); - if (ebitmap_set_bit - (&e_tmp, mod->map[SYM_ROLES][i] - 1, 1)) { - goto cleanup; - } - } + if (ebitmap_convert(&role->dominates, &e_tmp, mod->map[SYM_ROLES])) + goto cleanup; if (ebitmap_union(&dest_role->dominates, &e_tmp)) { goto cleanup; } - if (type_set_or_convert(&role->types, &dest_role->types, mod, state)) { + if (type_set_or_convert(&role->types, &dest_role->types, mod)) { goto cleanup; } ebitmap_destroy(&e_tmp); if (role->flavor == ROLE_ATTRIB) { ebitmap_init(&e_tmp); - ebitmap_for_each_positive_bit(&role->roles, rnode, i) { - assert(mod->map[SYM_ROLES][i]); - if (ebitmap_set_bit - (&e_tmp, mod->map[SYM_ROLES][i] - 1, 1)) { - goto cleanup; - } - } + if (ebitmap_convert(&role->roles, &e_tmp, mod->map[SYM_ROLES])) + goto cleanup; if (ebitmap_union(&dest_role->roles, &e_tmp)) { goto cleanup; } @@ -1152,13 +1134,11 @@ static int role_fix_callback(hashtab_key_t key, hashtab_datum_t datum, static int type_fix_callback(hashtab_key_t key, hashtab_datum_t datum, void *data) { - unsigned int i; char *id = key; type_datum_t *type, *new_type = NULL; link_state_t *state = (link_state_t *) data; ebitmap_t e_tmp; policy_module_t *mod = state->cur; - ebitmap_node_t *tnode; symtab_t *typetab; type = (type_datum_t *) datum; @@ -1181,13 +1161,8 @@ static int type_fix_callback(hashtab_key_t key, hashtab_datum_t datum, } ebitmap_init(&e_tmp); - ebitmap_for_each_positive_bit(&type->types, tnode, i) { - assert(mod->map[SYM_TYPES][i]); - if (ebitmap_set_bit - (&e_tmp, mod->map[SYM_TYPES][i] - 1, 1)) { - goto cleanup; - } - } + if (ebitmap_convert(&type->types, &e_tmp, mod->map[SYM_TYPES])) + goto cleanup; if (ebitmap_union(&new_type->types, &e_tmp)) { goto cleanup; } @@ -1269,9 +1244,8 @@ static int copy_avrule_list(avrule_t * list, avrule_t ** dst, new_rule->specified = cur->specified; new_rule->flags = cur->flags; if (type_set_convert - (&cur->stypes, &new_rule->stypes, module, state) == -1 - || type_set_convert(&cur->ttypes, &new_rule->ttypes, module, - state) == -1) { + (&cur->stypes, &new_rule->stypes, module) == -1 + || type_set_convert(&cur->ttypes, &new_rule->ttypes, module) == -1) { goto cleanup; } @@ -1355,8 +1329,6 @@ static int copy_role_trans_list(role_trans_rule_t * list, policy_module_t * module, link_state_t * state) { role_trans_rule_t *cur, *new_rule = NULL, *tail; - unsigned int i; - ebitmap_node_t *cnode; cur = list; tail = *dst; @@ -1374,19 +1346,12 @@ static int copy_role_trans_list(role_trans_rule_t * list, if (role_set_or_convert (&cur->roles, &new_rule->roles, module, state) || type_set_or_convert(&cur->types, &new_rule->types, - module, state)) { + module)) { goto cleanup; } - ebitmap_for_each_positive_bit(&cur->classes, cnode, i) { - assert(module->map[SYM_CLASSES][i]); - if (ebitmap_set_bit(&new_rule->classes, - module-> - map[SYM_CLASSES][i] - 1, - 1)) { - goto cleanup; - } - } + if (ebitmap_convert(&cur->classes, &new_rule->classes, module->map[SYM_CLASSES])) + goto cleanup; new_rule->new_role = module->map[SYM_ROLES][cur->new_role - 1]; @@ -1476,8 +1441,8 @@ static int copy_filename_trans_list(filename_trans_rule_t * list, if (!new_rule->name) goto err; - if (type_set_or_convert(&cur->stypes, &new_rule->stypes, module, state) || - type_set_or_convert(&cur->ttypes, &new_rule->ttypes, module, state)) + if (type_set_or_convert(&cur->stypes, &new_rule->stypes, module) || + type_set_or_convert(&cur->ttypes, &new_rule->ttypes, module)) goto err; new_rule->tclass = module->map[SYM_CLASSES][cur->tclass - 1]; @@ -1497,8 +1462,6 @@ static int copy_range_trans_list(range_trans_rule_t * rules, policy_module_t * mod, link_state_t * state) { range_trans_rule_t *rule, *new_rule = NULL; - unsigned int i; - ebitmap_node_t *cnode; for (rule = rules; rule; rule = rule->next) { new_rule = @@ -1512,21 +1475,15 @@ static int copy_range_trans_list(range_trans_rule_t * rules, *dst = new_rule; if (type_set_convert(&rule->stypes, &new_rule->stypes, - mod, state)) + mod)) goto cleanup; if (type_set_convert(&rule->ttypes, &new_rule->ttypes, - mod, state)) + mod)) goto cleanup; - ebitmap_for_each_positive_bit(&rule->tclasses, cnode, i) { - assert(mod->map[SYM_CLASSES][i]); - if (ebitmap_set_bit - (&new_rule->tclasses, - mod->map[SYM_CLASSES][i] - 1, 1)) { - goto cleanup; - } - } + if (ebitmap_convert(&rule->tclasses, &new_rule->tclasses, mod->map[SYM_CLASSES])) + goto cleanup; if (mls_range_convert(&rule->trange, &new_rule->trange, mod, state)) goto cleanup; @@ -1688,15 +1645,12 @@ static int copy_scope_index(scope_index_t * src, scope_index_t * dest, } dest->class_perms_len = largest_mapped_class_value; for (i = 0; i < src->class_perms_len; i++) { - ebitmap_t *srcmap = src->class_perms_map + i; + const ebitmap_t *srcmap = src->class_perms_map + i; ebitmap_t *destmap = dest->class_perms_map + module->map[SYM_CLASSES][i] - 1; - ebitmap_for_each_positive_bit(srcmap, node, j) { - if (ebitmap_set_bit(destmap, module->perm_map[i][j] - 1, - 1)) { - goto cleanup; - } - } + + if (ebitmap_convert(srcmap, destmap, module->perm_map[i])) + goto cleanup; } return 0; diff --git a/libsepol/src/mls.h b/libsepol/src/mls.h index eb4a1cb8b5228801e4d3ea4fbbd38d53bf636ae8..befd12c5ed058075155b72fcfb72e21f35f1ab26 100644 --- a/libsepol/src/mls.h +++ b/libsepol/src/mls.h @@ -25,6 +25,7 @@ #include "policydb_internal.h" #include +#include #include "handle.h" extern int mls_from_string(sepol_handle_t * handle, diff --git a/libsepol/src/module_to_cil.c b/libsepol/src/module_to_cil.c index b35bf055f07368d986e4dad27a7f705a08ead1a3..2b24d33e691ef6adcf76e5d28180e8cf8e76195d 100644 --- a/libsepol/src/module_to_cil.c +++ b/libsepol/src/module_to_cil.c @@ -624,7 +624,7 @@ exit: return rc; } -#define next_bit_in_range(i, p) ((i + 1 < sizeof(p)*8) && xperm_test((i + 1), p)) +#define next_bit_in_range(i, p) (((i) + 1 < sizeof(p)*8) && xperm_test(((i) + 1), p)) static int xperms_to_cil(const av_extended_perms_t *xperms) { @@ -2330,7 +2330,7 @@ static int user_to_cil(int indent, struct policydb *pdb, struct avrule_block *bl } if (block->flags & AVRULE_OPTIONAL) { - // sensitivites in user statements in optionals do not have the + // sensitivities in user statements in optionals do not have the // standard -1 offset sens_offset = 0; } diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c index fc260eb664b1c7eb5c9733393dbe60312c6a679c..b79c19b94c3374f5fd90ba7edef70d17398e44ff 100644 --- a/libsepol/src/policydb.c +++ b/libsepol/src/policydb.c @@ -776,12 +776,11 @@ static int roles_init(policydb_t * p) rc = -ENOMEM; goto out; } - key = malloc(strlen(OBJECT_R) + 1); + key = strdup(OBJECT_R); if (!key) { rc = -ENOMEM; goto out_free_role; } - strcpy(key, OBJECT_R); rc = symtab_insert(p, SYM_ROLES, key, role, (p->policy_type == POLICY_MOD ? SCOPE_REQ : SCOPE_DECL), 1, @@ -4570,7 +4569,7 @@ int policydb_read(policydb_t * p, struct policy_file *fp, unsigned verbose) } } - if (validate_policydb(fp->handle, p)) + if (policydb_validate(fp->handle, p)) goto bad; return POLICYDB_SUCCESS; diff --git a/libsepol/src/policydb_validate.c b/libsepol/src/policydb_validate.c index da18282bafc87a6a5a7e0bce83ead8092395b7ec..469c14f474257c1427b4ab8cf7bf16c29159353d 100644 --- a/libsepol/src/policydb_validate.c +++ b/libsepol/src/policydb_validate.c @@ -8,7 +8,7 @@ #include "policydb_validate.h" #define bool_xor(a, b) (!(a) != !(b)) -#define bool_xnor(a, b) !bool_xor(a, b) +#define bool_xnor(a, b) (!bool_xor(a, b)) typedef struct validate { uint32_t nprim; @@ -18,7 +18,7 @@ typedef struct validate { typedef struct map_arg { validate_t *flavors; sepol_handle_t *handle; - int mls; + const policydb_t *policy; } map_arg_t; static int create_gap_ebitmap(char **val_to_name, uint32_t nprim, ebitmap_t *gaps) @@ -46,8 +46,10 @@ static int validate_init(validate_t *flavor, char **val_to_name, uint32_t nprim) return 0; } -static int validate_array_init(policydb_t *p, validate_t flavors[]) +static int validate_array_init(const policydb_t *p, validate_t flavors[]) { + if (validate_init(&flavors[SYM_COMMONS], p->p_common_val_to_name, p->p_commons.nprim)) + goto bad; if (validate_init(&flavors[SYM_CLASSES], p->p_class_val_to_name, p->p_classes.nprim)) goto bad; if (validate_init(&flavors[SYM_ROLES], p->p_role_val_to_name, p->p_roles.nprim)) @@ -91,7 +93,7 @@ int value_isvalid(uint32_t value, uint32_t nprim) return 1; } -static int validate_value(uint32_t value, validate_t *flavor) +static int validate_value(uint32_t value, const validate_t *flavor) { if (!value || value > flavor->nprim) goto bad; @@ -104,7 +106,7 @@ bad: return -1; } -static int validate_ebitmap(ebitmap_t *map, validate_t *flavor) +static int validate_ebitmap(const ebitmap_t *map, const validate_t *flavor) { if (ebitmap_length(map) > 0 && ebitmap_highest_set_bit(map) >= flavor->nprim) goto bad; @@ -117,7 +119,7 @@ bad: return -1; } -static int validate_type_set(type_set_t *type_set, validate_t *type) +static int validate_type_set(const type_set_t *type_set, const validate_t *type) { if (validate_ebitmap(&type_set->types, type)) goto bad; @@ -139,7 +141,7 @@ bad: return -1; } -static int validate_empty_type_set(type_set_t *type_set) +static int validate_empty_type_set(const type_set_t *type_set) { if (!ebitmap_is_empty(&type_set->types)) goto bad; @@ -154,7 +156,7 @@ bad: return -1; } -static int validate_role_set(role_set_t *role_set, validate_t *role) +static int validate_role_set(const role_set_t *role_set, const validate_t *role) { if (validate_ebitmap(&role_set->roles, role)) goto bad; @@ -176,8 +178,8 @@ bad: static int validate_scope(__attribute__ ((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) { - scope_datum_t *scope_datum = (scope_datum_t *)d; - uint32_t *nprim = (uint32_t *)args; + const scope_datum_t *scope_datum = (scope_datum_t *)d; + const uint32_t *nprim = (uint32_t *)args; unsigned int i; switch (scope_datum->scope) { @@ -199,9 +201,9 @@ bad: return -1; } -static int validate_scopes(sepol_handle_t *handle, symtab_t scopes[], avrule_block_t *block) +static int validate_scopes(sepol_handle_t *handle, const symtab_t scopes[], const avrule_block_t *block) { - avrule_decl_t *decl; + const avrule_decl_t *decl; unsigned int i; unsigned int num_decls = 0; @@ -223,9 +225,9 @@ bad: return -1; } -static int validate_constraint_nodes(sepol_handle_t *handle, unsigned int nperms, constraint_node_t *cons, validate_t flavors[]) +static int validate_constraint_nodes(sepol_handle_t *handle, unsigned int nperms, const constraint_node_t *cons, validate_t flavors[]) { - constraint_expr_t *cexp; + const constraint_expr_t *cexp; for (; cons; cons = cons->next) { if (nperms == 0 && cons->permissions != 0) @@ -235,6 +237,9 @@ static int validate_constraint_nodes(sepol_handle_t *handle, unsigned int nperms if (nperms > 0 && nperms != PERM_SYMTAB_SIZE && cons->permissions >= (UINT32_C(1) << nperms)) goto bad; + if (!cons->expr) + goto bad; + for (cexp = cons->expr; cexp; cexp = cexp->next) { if (cexp->expr_type == CEXPR_NAMES) { if (cexp->attr & CEXPR_XTARGET && nperms != 0) @@ -339,10 +344,33 @@ bad: return -1; } -static int validate_class_datum(sepol_handle_t *handle, class_datum_t *class, validate_t flavors[]) +static int validate_common_datum(sepol_handle_t *handle, const common_datum_t *common, validate_t flavors[]) +{ + if (validate_value(common->s.value, &flavors[SYM_COMMONS])) + goto bad; + if (common->permissions.nprim > PERM_SYMTAB_SIZE) + goto bad; + + return 0; + +bad: + ERR(handle, "Invalid common class datum"); + return -1; +} + +static int validate_common_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) +{ + map_arg_t *margs = args; + + return validate_common_datum(margs->handle, d, margs->flavors); +} + +static int validate_class_datum(sepol_handle_t *handle, const class_datum_t *class, validate_t flavors[]) { if (validate_value(class->s.value, &flavors[SYM_CLASSES])) goto bad; + if (class->comdatum && validate_common_datum(handle, class->comdatum, flavors)) + goto bad; if (class->permissions.nprim > PERM_SYMTAB_SIZE) goto bad; if (validate_constraint_nodes(handle, class->permissions.nprim, class->constraints, flavors)) @@ -405,26 +433,7 @@ static int validate_class_datum_wrapper(__attribute__((unused)) hashtab_key_t k, return validate_class_datum(margs->handle, d, margs->flavors); } -static int validate_common_datum(sepol_handle_t *handle, common_datum_t *common) -{ - if (common->permissions.nprim > PERM_SYMTAB_SIZE) - goto bad; - - return 0; - -bad: - ERR(handle, "Invalid common class datum"); - return -1; -} - -static int validate_common_datum_wrapper(__attribute__((unused)) hashtab_key_t k, hashtab_datum_t d, void *args) -{ - map_arg_t *margs = args; - - return validate_common_datum(margs->handle, d); -} - -static int validate_role_datum(sepol_handle_t *handle, role_datum_t *role, validate_t flavors[]) +static int validate_role_datum(sepol_handle_t *handle, const role_datum_t *role, validate_t flavors[]) { if (validate_value(role->s.value, &flavors[SYM_ROLES])) goto bad; @@ -437,6 +446,14 @@ static int validate_role_datum(sepol_handle_t *handle, role_datum_t *role, valid if (validate_ebitmap(&role->roles, &flavors[SYM_ROLES])) goto bad; + switch(role->flavor) { + case ROLE_ROLE: + case ROLE_ATTRIB: + break; + default: + goto bad; + } + return 0; bad: @@ -451,19 +468,46 @@ static int validate_role_datum_wrapper(__attribute__((unused)) hashtab_key_t k, return validate_role_datum(margs->handle, d, margs->flavors); } -static int validate_type_datum(sepol_handle_t *handle, type_datum_t *type, validate_t flavors[]) +static int validate_simpletype(uint32_t value, const policydb_t *p, validate_t flavors[]) { - if (validate_value(type->s.value, &flavors[SYM_TYPES])) + const type_datum_t *type; + + if (validate_value(value, &flavors[SYM_TYPES])) + goto bad; + + type = p->type_val_to_struct[value - 1]; + if (!type) + goto bad; + + if (type->flavor == TYPE_ATTRIB) goto bad; - if (validate_ebitmap(&type->types, &flavors[SYM_TYPES])) + + return 0; + +bad: + return -1; +} + +static int validate_type_datum(sepol_handle_t *handle, const type_datum_t *type, const policydb_t *p, validate_t flavors[]) +{ + if (validate_value(type->s.value, &flavors[SYM_TYPES])) goto bad; - if (type->bounds && validate_value(type->bounds, &flavors[SYM_TYPES])) + if (type->primary && validate_value(type->primary, &flavors[SYM_TYPES])) goto bad; switch (type->flavor) { case TYPE_TYPE: - case TYPE_ATTRIB: case TYPE_ALIAS: + if (!ebitmap_is_empty(&type->types)) + goto bad; + if (type->bounds && validate_simpletype(type->bounds, p, flavors)) + goto bad; + break; + case TYPE_ATTRIB: + if (validate_ebitmap(&type->types, &flavors[SYM_TYPES])) + goto bad; + if (type->bounds) + goto bad; break; default: goto bad; @@ -491,10 +535,10 @@ static int validate_type_datum_wrapper(__attribute__((unused)) hashtab_key_t k, { map_arg_t *margs = args; - return validate_type_datum(margs->handle, d, margs->flavors); + return validate_type_datum(margs->handle, d, margs->policy, margs->flavors); } -static int validate_mls_semantic_cat(mls_semantic_cat_t *cat, validate_t *cats) +static int validate_mls_semantic_cat(const mls_semantic_cat_t *cat, const validate_t *cats) { for (; cat; cat = cat->next) { if (validate_value(cat->low, cats)) @@ -509,7 +553,7 @@ bad: return -1; } -static int validate_mls_semantic_level(mls_semantic_level_t *level, validate_t *sens, validate_t *cats) +static int validate_mls_semantic_level(const mls_semantic_level_t *level, const validate_t *sens, const validate_t *cats) { if (level->sens == 0) return 0; @@ -524,7 +568,7 @@ bad: return -1; } -static int validate_mls_semantic_range(mls_semantic_range_t *range, validate_t *sens, validate_t *cats) +static int validate_mls_semantic_range(const mls_semantic_range_t *range, const validate_t *sens, const validate_t *cats) { if (validate_mls_semantic_level(&range->level[0], sens, cats)) goto bad; @@ -537,7 +581,7 @@ bad: return -1; } -static int validate_mls_level(mls_level_t *level, validate_t *sens, validate_t *cats) +static int validate_mls_level(const mls_level_t *level, const validate_t *sens, const validate_t *cats) { if (validate_value(level->sens, sens)) goto bad; @@ -558,7 +602,7 @@ static int validate_level_datum(__attribute__ ((unused)) hashtab_key_t k, hashta return validate_mls_level(level->level, &flavors[SYM_LEVELS], &flavors[SYM_CATS]); } -static int validate_mls_range(mls_range_t *range, validate_t *sens, validate_t *cats) +static int validate_mls_range(const mls_range_t *range, const validate_t *sens, const validate_t *cats) { if (validate_mls_level(&range->level[0], sens, cats)) goto bad; @@ -571,7 +615,7 @@ static int validate_mls_range(mls_range_t *range, validate_t *sens, validate_t * return -1; } -static int validate_user_datum(sepol_handle_t *handle, user_datum_t *user, validate_t flavors[], int mls) +static int validate_user_datum(sepol_handle_t *handle, const user_datum_t *user, validate_t flavors[], const policydb_t *p) { if (validate_value(user->s.value, &flavors[SYM_USERS])) goto bad; @@ -581,9 +625,9 @@ static int validate_user_datum(sepol_handle_t *handle, user_datum_t *user, valid goto bad; if (validate_mls_semantic_level(&user->dfltlevel, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) goto bad; - if (mls && validate_mls_range(&user->exp_range, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) + if (p->mls && p->policy_type != POLICY_MOD && validate_mls_range(&user->exp_range, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) goto bad; - if (mls && validate_mls_level(&user->exp_dfltlevel, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) + if (p->mls && p->policy_type != POLICY_MOD && validate_mls_level(&user->exp_dfltlevel, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) goto bad; if (user->bounds && validate_value(user->bounds, &flavors[SYM_USERS])) goto bad; @@ -599,10 +643,10 @@ static int validate_user_datum_wrapper(__attribute__((unused)) hashtab_key_t k, { map_arg_t *margs = args; - return validate_user_datum(margs->handle, d, margs->flavors, margs->mls); + return validate_user_datum(margs->handle, d, margs->flavors, margs->policy); } -static int validate_bool_datum(sepol_handle_t *handle, cond_bool_datum_t *boolean, validate_t flavors[]) +static int validate_bool_datum(sepol_handle_t *handle, const cond_bool_datum_t *boolean, validate_t flavors[]) { if (validate_value(boolean->s.value, &flavors[SYM_BOOLS])) goto bad; @@ -637,7 +681,7 @@ static int validate_bool_datum_wrapper(__attribute__((unused)) hashtab_key_t k, return validate_bool_datum(margs->handle, d, margs->flavors); } -static int validate_datum_array_gaps(sepol_handle_t *handle, policydb_t *p, validate_t flavors[]) +static int validate_datum_array_gaps(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { unsigned int i; @@ -687,9 +731,9 @@ static int validate_datum(__attribute__ ((unused))hashtab_key_t k, hashtab_datum return !value_isvalid(s->value, *nprim); } -static int validate_datum_array_entries(sepol_handle_t *handle, policydb_t *p, validate_t flavors[]) +static int validate_datum_array_entries(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { - map_arg_t margs = { flavors, handle, p->mls }; + map_arg_t margs = { flavors, handle, p }; if (hashtab_map(p->p_commons.table, validate_common_datum_wrapper, &margs)) goto bad; @@ -726,12 +770,20 @@ bad: * Functions to validate a kernel policydb */ -static int validate_avtab_key(avtab_key_t *key, int conditional, validate_t flavors[]) +static int validate_avtab_key(const avtab_key_t *key, int conditional, const policydb_t *p, validate_t flavors[]) { - if (validate_value(key->source_type, &flavors[SYM_TYPES])) - goto bad; - if (validate_value(key->target_type, &flavors[SYM_TYPES])) - goto bad; + if (p->policy_type == POLICY_KERN && key->specified & AVTAB_TYPE) { + if (validate_simpletype(key->source_type, p, flavors)) + goto bad; + if (validate_simpletype(key->target_type, p, flavors)) + goto bad; + } else { + if (validate_value(key->source_type, &flavors[SYM_TYPES])) + goto bad; + if (validate_value(key->target_type, &flavors[SYM_TYPES])) + goto bad; + } + if (validate_value(key->target_class, &flavors[SYM_CLASSES])) goto bad; switch (0xFFF & key->specified) { @@ -758,22 +810,42 @@ bad: return -1; } +static int validate_xperms(const avtab_extended_perms_t *xperms) +{ + switch (xperms->specified) { + case AVTAB_XPERMS_IOCTLDRIVER: + case AVTAB_XPERMS_IOCTLFUNCTION: + break; + default: + goto bad; + } + + return 0; + +bad: + return -1; +} static int validate_avtab_key_and_datum(avtab_key_t *k, avtab_datum_t *d, void *args) { - validate_t *flavors = (validate_t *)args; + map_arg_t *margs = args; + + if (validate_avtab_key(k, 0, margs->policy, margs->flavors)) + return -1; - if (validate_avtab_key(k, 0, flavors)) + if ((k->specified & AVTAB_TYPE) && validate_simpletype(d->data, margs->policy, margs->flavors)) return -1; - if ((k->specified & AVTAB_TYPE) && validate_value(d->data, &flavors[SYM_TYPES])) + if ((k->specified & AVTAB_XPERMS) && validate_xperms(d->xperms)) return -1; return 0; } -static int validate_avtab(sepol_handle_t *handle, avtab_t *avtab, validate_t flavors[]) +static int validate_avtab(sepol_handle_t *handle, const avtab_t *avtab, const policydb_t *p, validate_t flavors[]) { - if (avtab_map(avtab, validate_avtab_key_and_datum, flavors)) { + map_arg_t margs = { flavors, handle, p }; + + if (avtab_map(avtab, validate_avtab_key_and_datum, &margs)) { ERR(handle, "Invalid avtab"); return -1; } @@ -781,13 +853,13 @@ static int validate_avtab(sepol_handle_t *handle, avtab_t *avtab, validate_t fla return 0; } -static int validate_cond_av_list(sepol_handle_t *handle, cond_av_list_t *cond_av, validate_t flavors[]) +static int validate_cond_av_list(sepol_handle_t *handle, const cond_av_list_t *cond_av, const policydb_t *p, validate_t flavors[]) { - avtab_ptr_t avtab_ptr; + const struct avtab_node *avtab_ptr; for (; cond_av; cond_av = cond_av->next) { for (avtab_ptr = cond_av->node; avtab_ptr; avtab_ptr = avtab_ptr->next) { - if (validate_avtab_key(&avtab_ptr->key, 1, flavors)) { + if (validate_avtab_key(&avtab_ptr->key, 1, p, flavors)) { ERR(handle, "Invalid cond av list"); return -1; } @@ -797,20 +869,15 @@ static int validate_cond_av_list(sepol_handle_t *handle, cond_av_list_t *cond_av return 0; } -static int validate_avrules(sepol_handle_t *handle, avrule_t *avrule, int conditional, validate_t flavors[]) +static int validate_avrules(sepol_handle_t *handle, const avrule_t *avrule, int conditional, const policydb_t *p, validate_t flavors[]) { - class_perm_node_t *class; + const class_perm_node_t *classperm; for (; avrule; avrule = avrule->next) { if (validate_type_set(&avrule->stypes, &flavors[SYM_TYPES])) goto bad; if (validate_type_set(&avrule->ttypes, &flavors[SYM_TYPES])) goto bad; - class = avrule->perms; - for (; class; class = class->next) { - if (validate_value(class->tclass, &flavors[SYM_CLASSES])) - goto bad; - } switch(avrule->specified) { case AVRULE_ALLOWED: @@ -833,6 +900,13 @@ static int validate_avrules(sepol_handle_t *handle, avrule_t *avrule, int condit goto bad; } + for (classperm = avrule->perms; classperm; classperm = classperm->next) { + if (validate_value(classperm->tclass, &flavors[SYM_CLASSES])) + goto bad; + if ((avrule->specified & AVRULE_TYPE) && validate_simpletype(classperm->data, p, flavors)) + goto bad; + } + if (avrule->specified & AVRULE_XPERMS) { if (!avrule->xperms) goto bad; @@ -862,7 +936,7 @@ bad: return -1; } -static int validate_bool_id_array(sepol_handle_t *handle, uint32_t bool_ids[], unsigned int nbools, validate_t *bool) +static int validate_bool_id_array(sepol_handle_t *handle, const uint32_t bool_ids[], unsigned int nbools, const validate_t *boolean) { unsigned int i; @@ -870,7 +944,7 @@ static int validate_bool_id_array(sepol_handle_t *handle, uint32_t bool_ids[], u goto bad; for (i=0; i < nbools; i++) { - if (validate_value(bool_ids[i], bool)) + if (validate_value(bool_ids[i], boolean)) goto bad; } @@ -881,14 +955,17 @@ bad: return -1; } -static int validate_cond_expr(sepol_handle_t *handle, struct cond_expr *expr, validate_t *bool) +static int validate_cond_expr(sepol_handle_t *handle, const struct cond_expr *expr, const validate_t *boolean) { int depth = -1; + if (!expr) + goto bad; + for (; expr; expr = expr->next) { switch(expr->expr_type) { case COND_BOOL: - if (validate_value(expr->bool, bool)) + if (validate_value(expr->bool, boolean)) goto bad; if (depth == (COND_EXPR_MAXDEPTH - 1)) goto bad; @@ -922,21 +999,37 @@ bad: return -1; } -static int validate_cond_list(sepol_handle_t *handle, cond_list_t *cond, validate_t flavors[]) +static int validate_cond_list(sepol_handle_t *handle, const cond_list_t *cond, const policydb_t *p, validate_t flavors[]) { for (; cond; cond = cond->next) { if (validate_cond_expr(handle, cond->expr, &flavors[SYM_BOOLS])) goto bad; - if (validate_cond_av_list(handle, cond->true_list, flavors)) + if (validate_cond_av_list(handle, cond->true_list, p, flavors)) goto bad; - if (validate_cond_av_list(handle, cond->false_list, flavors)) + if (validate_cond_av_list(handle, cond->false_list, p, flavors)) goto bad; - if (validate_avrules(handle, cond->avtrue_list, 1, flavors)) + if (validate_avrules(handle, cond->avtrue_list, 1, p, flavors)) goto bad; - if (validate_avrules(handle, cond->avfalse_list, 1, flavors)) + if (validate_avrules(handle, cond->avfalse_list, 1, p, flavors)) goto bad; if (validate_bool_id_array(handle, cond->bool_ids, cond->nbools, &flavors[SYM_BOOLS])) goto bad; + + switch (cond->cur_state) { + case 0: + case 1: + break; + default: + goto bad; + } + + switch (cond->flags) { + case 0: + case COND_NODE_FLAGS_TUNABLE: + break; + default: + goto bad; + } } return 0; @@ -946,7 +1039,7 @@ bad: return -1; } -static int validate_role_transes(sepol_handle_t *handle, role_trans_t *role_trans, validate_t flavors[]) +static int validate_role_transes(sepol_handle_t *handle, const role_trans_t *role_trans, validate_t flavors[]) { for (; role_trans; role_trans = role_trans->next) { if (validate_value(role_trans->role, &flavors[SYM_ROLES])) @@ -966,7 +1059,7 @@ bad: return -1; } -static int validate_role_allows(sepol_handle_t *handle, role_allow_t *role_allow, validate_t flavors[]) +static int validate_role_allows(sepol_handle_t *handle, const role_allow_t *role_allow, validate_t flavors[]) { for (; role_allow; role_allow = role_allow->next) { if (validate_value(role_allow->role, &flavors[SYM_ROLES])) @@ -984,14 +1077,16 @@ bad: static int validate_filename_trans(hashtab_key_t k, hashtab_datum_t d, void *args) { - filename_trans_key_t *ftk = (filename_trans_key_t *)k; - filename_trans_datum_t *ftd = d; + const filename_trans_key_t *ftk = (filename_trans_key_t *)k; + const filename_trans_datum_t *ftd = d; validate_t *flavors = (validate_t *)args; if (validate_value(ftk->ttype, &flavors[SYM_TYPES])) goto bad; if (validate_value(ftk->tclass, &flavors[SYM_CLASSES])) goto bad; + if (!ftd) + goto bad; for (; ftd; ftd = ftd->next) { if (validate_ebitmap(&ftd->stypes, &flavors[SYM_TYPES])) goto bad; @@ -1015,7 +1110,7 @@ static int validate_filename_trans_hashtab(sepol_handle_t *handle, hashtab_t fil return 0; } -static int validate_context(context_struct_t *con, validate_t flavors[], int mls) +static int validate_context(const context_struct_t *con, validate_t flavors[], int mls) { if (validate_value(con->user, &flavors[SYM_USERS])) return -1; @@ -1029,9 +1124,9 @@ static int validate_context(context_struct_t *con, validate_t flavors[], int mls return 0; } -static int validate_ocontexts(sepol_handle_t *handle, policydb_t *p, validate_t flavors[]) +static int validate_ocontexts(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { - ocontext_t *octx; + const ocontext_t *octx; unsigned int i; for (i = 0; i < OCON_NUM; i++) { @@ -1046,6 +1141,10 @@ static int validate_ocontexts(sepol_handle_t *handle, policydb_t *p, validate_t if (validate_context(&octx->context[1], flavors, p->mls)) goto bad; break; + case OCON_PORT: + if (octx->u.port.low_port > octx->u.port.high_port) + goto bad; + break; case OCON_FSUSE: switch (octx->v.behavior) { case SECURITY_FS_USE_XATTR: @@ -1067,16 +1166,21 @@ bad: return -1; } -static int validate_genfs(sepol_handle_t *handle, policydb_t *p, validate_t flavors[]) +static int validate_genfs(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { - genfs_t *genfs; - ocontext_t *octx; + const genfs_t *genfs; + const ocontext_t *octx; for (genfs = p->genfs; genfs; genfs = genfs->next) { for (octx = genfs->head; octx; octx = octx->next) { if (validate_context(&octx->context[0], flavors, p->mls)) goto bad; + if (octx->v.sclass && validate_value(octx->v.sclass, &flavors[SYM_CLASSES])) + goto bad; } + + if (!genfs->fstype) + goto bad; } return 0; @@ -1090,7 +1194,7 @@ bad: * Functions to validate a module policydb */ -static int validate_role_trans_rules(sepol_handle_t *handle, role_trans_rule_t *role_trans, validate_t flavors[]) +static int validate_role_trans_rules(sepol_handle_t *handle, const role_trans_rule_t *role_trans, validate_t flavors[]) { for (; role_trans; role_trans = role_trans->next) { if (validate_role_set(&role_trans->roles, &flavors[SYM_ROLES])) @@ -1110,7 +1214,7 @@ bad: return -1; } -static int validate_role_allow_rules(sepol_handle_t *handle, role_allow_rule_t *role_allow, validate_t flavors[]) +static int validate_role_allow_rules(sepol_handle_t *handle, const role_allow_rule_t *role_allow, validate_t flavors[]) { for (; role_allow; role_allow = role_allow->next) { if (validate_role_set(&role_allow->roles, &flavors[SYM_ROLES])) @@ -1126,7 +1230,7 @@ bad: return -1; } -static int validate_range_trans_rules(sepol_handle_t *handle, range_trans_rule_t *range_trans, validate_t flavors[]) +static int validate_range_trans_rules(sepol_handle_t *handle, const range_trans_rule_t *range_trans, validate_t flavors[]) { for (; range_trans; range_trans = range_trans->next) { if (validate_type_set(&range_trans->stypes, &flavors[SYM_TYPES])) @@ -1146,7 +1250,7 @@ bad: return -1; } -static int validate_scope_index(sepol_handle_t *handle, scope_index_t *scope_index, validate_t flavors[]) +static int validate_scope_index(sepol_handle_t *handle, const scope_index_t *scope_index, validate_t flavors[]) { if (validate_ebitmap(&scope_index->p_classes_scope, &flavors[SYM_CLASSES])) goto bad; @@ -1173,7 +1277,7 @@ bad: } -static int validate_filename_trans_rules(sepol_handle_t *handle, filename_trans_rule_t *filename_trans, validate_t flavors[]) +static int validate_filename_trans_rules(sepol_handle_t *handle, const filename_trans_rule_t *filename_trans, const policydb_t *p, validate_t flavors[]) { for (; filename_trans; filename_trans = filename_trans->next) { if (validate_type_set(&filename_trans->stypes, &flavors[SYM_TYPES])) @@ -1182,7 +1286,7 @@ static int validate_filename_trans_rules(sepol_handle_t *handle, filename_trans_ goto bad; if (validate_value(filename_trans->tclass,&flavors[SYM_CLASSES] )) goto bad; - if (validate_value(filename_trans->otype, &flavors[SYM_TYPES])) + if (validate_simpletype(filename_trans->otype, p, flavors)) goto bad; /* currently only the RULE_SELF flag can be set */ @@ -1197,7 +1301,7 @@ bad: return -1; } -static int validate_symtabs(sepol_handle_t *handle, symtab_t symtabs[], validate_t flavors[]) +static int validate_symtabs(sepol_handle_t *handle, const symtab_t symtabs[], validate_t flavors[]) { unsigned int i; @@ -1211,15 +1315,15 @@ static int validate_symtabs(sepol_handle_t *handle, symtab_t symtabs[], validate return 0; } -static int validate_avrule_blocks(sepol_handle_t *handle, avrule_block_t *avrule_block, validate_t flavors[]) +static int validate_avrule_blocks(sepol_handle_t *handle, const avrule_block_t *avrule_block, const policydb_t *p, validate_t flavors[]) { - avrule_decl_t *decl; + const avrule_decl_t *decl; for (; avrule_block; avrule_block = avrule_block->next) { for (decl = avrule_block->branch_list; decl != NULL; decl = decl->next) { - if (validate_cond_list(handle, decl->cond_list, flavors)) + if (validate_cond_list(handle, decl->cond_list, p, flavors)) goto bad; - if (validate_avrules(handle, decl->avrules, 0, flavors)) + if (validate_avrules(handle, decl->avrules, 0, p, flavors)) goto bad; if (validate_role_trans_rules(handle, decl->role_tr_rules, flavors)) goto bad; @@ -1231,7 +1335,7 @@ static int validate_avrule_blocks(sepol_handle_t *handle, avrule_block_t *avrule goto bad; if (validate_scope_index(handle, &decl->declared, flavors)) goto bad; - if (validate_filename_trans_rules(handle, decl->filename_trans_rules, flavors)) + if (validate_filename_trans_rules(handle, decl->filename_trans_rules, p, flavors)) goto bad; if (validate_symtabs(handle, decl->symtab, flavors)) goto bad; @@ -1253,13 +1357,13 @@ bad: return -1; } -static int validate_permissives(sepol_handle_t *handle, policydb_t *p, validate_t flavors[]) +static int validate_permissives(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) { ebitmap_node_t *node; unsigned i; ebitmap_for_each_positive_bit(&p->permissive_map, node, i) { - if (validate_value(i, &flavors[SYM_TYPES])) + if (validate_simpletype(i, p, flavors)) goto bad; } @@ -1270,7 +1374,62 @@ bad: return -1; } -static int validate_properties(sepol_handle_t *handle, policydb_t *p) +static int validate_range_transition(hashtab_key_t key, hashtab_datum_t data, void *args) +{ + const range_trans_t *rt = (const range_trans_t *)key; + const mls_range_t *r = data; + const map_arg_t *margs = args; + const validate_t *flavors = margs->flavors; + + if (validate_value(rt->source_type, &flavors[SYM_TYPES])) + goto bad; + if (validate_value(rt->target_type, &flavors[SYM_TYPES])) + goto bad; + if (validate_value(rt->target_class, &flavors[SYM_CLASSES])) + goto bad; + + if (validate_mls_range(r, &flavors[SYM_LEVELS], &flavors[SYM_CATS])) + goto bad; + + return 0; + +bad: + return -1; +} + +static int validate_range_transitions(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) +{ + map_arg_t margs = { flavors, handle, p }; + + if (hashtab_map(p->range_tr, validate_range_transition, &margs)) { + ERR(handle, "Invalid range transition"); + return -1; + } + + return 0; +} + +static int validate_typeattr_map(sepol_handle_t *handle, const policydb_t *p, validate_t flavors[]) +{ + const ebitmap_t *maps = p->type_attr_map; + unsigned int i; + + if (p->policy_type == POLICY_KERN) { + for (i = 0; i < p->p_types.nprim; i++) { + if (validate_ebitmap(&maps[i], &flavors[SYM_TYPES])) + goto bad; + } + } else if (maps) + goto bad; + + return 0; + +bad: + ERR(handle, "Invalid type attr map"); + return -1; +} + +static int validate_properties(sepol_handle_t *handle, const policydb_t *p) { switch (p->policy_type) { case POLICY_KERN: @@ -1330,7 +1489,7 @@ static void validate_array_destroy(validate_t flavors[]) /* * Validate policydb */ -int validate_policydb(sepol_handle_t *handle, policydb_t *p) +int policydb_validate(sepol_handle_t *handle, const policydb_t *p) { validate_t flavors[SYM_NUM] = {}; @@ -1341,10 +1500,10 @@ int validate_policydb(sepol_handle_t *handle, policydb_t *p) goto bad; if (p->policy_type == POLICY_KERN) { - if (validate_avtab(handle, &p->te_avtab, flavors)) + if (validate_avtab(handle, &p->te_avtab, p, flavors)) goto bad; if (p->policyvers >= POLICYDB_VERSION_BOOL) - if (validate_cond_list(handle, p->cond_list, flavors)) + if (validate_cond_list(handle, p->cond_list, p, flavors)) goto bad; if (validate_role_transes(handle, p->role_tr, flavors)) goto bad; @@ -1354,7 +1513,7 @@ int validate_policydb(sepol_handle_t *handle, policydb_t *p) if (validate_filename_trans_hashtab(handle, p->filename_trans, flavors)) goto bad; } else { - if (validate_avrule_blocks(handle, p->global, flavors)) + if (validate_avrule_blocks(handle, p->global, p, flavors)) goto bad; } @@ -1376,6 +1535,14 @@ int validate_policydb(sepol_handle_t *handle, policydb_t *p) if (validate_permissives(handle, p, flavors)) goto bad; + if (validate_range_transitions(handle, p, flavors)) + goto bad; + + if (p->policyvers >= POLICYDB_VERSION_AVTAB) { + if (validate_typeattr_map(handle, p, flavors)) + goto bad; + } + validate_array_destroy(flavors); return 0; diff --git a/libsepol/src/policydb_validate.h b/libsepol/src/policydb_validate.h index d9f7229bf765460fec4815b46dad9c6a106bc4fc..86a531683bfe12f34301c36cbc4be7bc38bac809 100644 --- a/libsepol/src/policydb_validate.h +++ b/libsepol/src/policydb_validate.h @@ -4,4 +4,4 @@ #include int value_isvalid(uint32_t value, uint32_t nprim); -int validate_policydb(sepol_handle_t *handle, policydb_t *p); +int policydb_validate(sepol_handle_t *handle, const policydb_t *p); diff --git a/libsepol/src/services.c b/libsepol/src/services.c index d7510e9dae510a36cfcd6ff9339bf52669dabe64..062510ab0ea1c375386e19d53bafd0e73a9f4199 100644 --- a/libsepol/src/services.c +++ b/libsepol/src/services.c @@ -394,7 +394,7 @@ static int constraint_expr_eval_reason(context_struct_t *scontext, role_datum_t *r1, *r2; mls_level_t *l1, *l2; constraint_expr_t *e; - int s[CEXPR_MAXDEPTH]; + int s[CEXPR_MAXDEPTH] = {}; int sp = -1; char tmp_buf[128]; @@ -894,7 +894,8 @@ static void type_attribute_bounds_av(context_struct_t *scontext, /* mask violated permissions */ avd->allowed &= ~masked; - *reason |= SEPOL_COMPUTEAV_BOUNDS; + if (reason) + *reason |= SEPOL_COMPUTEAV_BOUNDS; } /* diff --git a/libsepol/src/util.c b/libsepol/src/util.c index 1cd1308d1687aaf819619f285a89cebcf04b229d..0a2edc852b456f24818a00c3f4164db3fc75eb8c 100644 --- a/libsepol/src/util.c +++ b/libsepol/src/util.c @@ -124,7 +124,7 @@ char *sepol_av_to_string(policydb_t * policydbp, uint32_t tclass, return avbuf; } -#define next_bit_in_range(i, p) ((i + 1 < sizeof(p)*8) && xperm_test((i + 1), p)) +#define next_bit_in_range(i, p) (((i) + 1 < sizeof(p)*8) && xperm_test(((i) + 1), p)) char *sepol_extended_perms_to_string(avtab_extended_perms_t *xperms) { diff --git a/libsepol/src/write.c b/libsepol/src/write.c index 48ed21ea683a28aee6a762f7a1c470157356579b..a9fdf93a8ee1dc487fa6e932b943b9dfdbec54b4 100644 --- a/libsepol/src/write.c +++ b/libsepol/src/write.c @@ -1097,16 +1097,18 @@ static int class_write(hashtab_key_t key, hashtab_datum_t datum, void *ptr) p->policyvers >= POLICYDB_VERSION_NEW_OBJECT_DEFAULTS) || (p->policy_type == POLICY_BASE && p->policyvers >= MOD_POLICYDB_VERSION_NEW_OBJECT_DEFAULTS)) { + char default_range = cladatum->default_range; + buf[0] = cpu_to_le32(cladatum->default_user); buf[1] = cpu_to_le32(cladatum->default_role); - if (!glblub_version && cladatum->default_range == DEFAULT_GLBLUB) { + if (!glblub_version && default_range == DEFAULT_GLBLUB) { WARN(fp->handle, - "class %s default_range set to GLBLUB but policy version is %d (%d required), discarding", - p->p_class_val_to_name[cladatum->s.value - 1], p->policyvers, - p->policy_type == POLICY_KERN? POLICYDB_VERSION_GLBLUB:MOD_POLICYDB_VERSION_GLBLUB); - cladatum->default_range = 0; - } - buf[2] = cpu_to_le32(cladatum->default_range); + "class %s default_range set to GLBLUB but policy version is %d (%d required), discarding", + p->p_class_val_to_name[cladatum->s.value - 1], p->policyvers, + p->policy_type == POLICY_KERN? POLICYDB_VERSION_GLBLUB:MOD_POLICYDB_VERSION_GLBLUB); + default_range = 0; + } + buf[2] = cpu_to_le32(default_range); items = put_entry(buf, sizeof(uint32_t), 3, fp); if (items != 3) return POLICYDB_ERROR; diff --git a/libsepol/tests/Makefile b/libsepol/tests/Makefile index a72c327dee9a7dbf6d958dd432a76cfe6e6d111f..273373b03d8a45a12f8a5041fc33116df0537636 100644 --- a/libsepol/tests/Makefile +++ b/libsepol/tests/Makefile @@ -1,9 +1,24 @@ ENV ?= env -M4 ?= m4 +M4 ?= m4 -E -E MKDIR ?= mkdir EXE ?= libsepol-tests -CFLAGS += -g3 -gdwarf-2 -O0 -Wall -W -Wundef -Wmissing-noreturn -Wmissing-format-attribute -Wno-unused-parameter -Werror +CFLAGS += -g3 -gdwarf-2 -O0 \ + -Werror -Wall -Wextra \ + -Wfloat-equal \ + -Wformat=2 \ + -Winit-self \ + -Wmissing-format-attribute \ + -Wmissing-noreturn \ + -Wmissing-prototypes \ + -Wnull-dereference \ + -Wpointer-arith \ + -Wshadow \ + -Wstrict-prototypes \ + -Wundef \ + -Wunused \ + -Wwrite-strings \ + -fno-common # Statically link libsepol on the assumption that we are going to # be testing internal functions. diff --git a/libsepol/tests/libsepol-tests.c b/libsepol/tests/libsepol-tests.c index dc8fd5ce5f6cec2f1bece086edb134ba04ac6bf2..968e3cc2143408d546ad7d729286a8ff6d7b6e68 100644 --- a/libsepol/tests/libsepol-tests.c +++ b/libsepol/tests/libsepol-tests.c @@ -19,10 +19,12 @@ */ #include "test-cond.h" +#include "test-ebitmap.h" #include "test-linker.h" #include "test-expander.h" #include "test-deps.h" #include "test-downgrade.h" +#include "test-neverallow.h" #include #include @@ -64,11 +66,13 @@ static bool do_tests(int interactive, int verbose) if (CUE_SUCCESS != CU_initialize_registry()) return CU_get_error(); + DECLARE_SUITE(ebitmap); DECLARE_SUITE(cond); DECLARE_SUITE(linker); DECLARE_SUITE(expander); DECLARE_SUITE(deps); DECLARE_SUITE(downgrade); + DECLARE_SUITE(neverallow); if (verbose) CU_basic_set_mode(CU_BRM_VERBOSE); diff --git a/libsepol/tests/policies/test-deps/base-metreq.conf b/libsepol/tests/policies/test-deps/base-metreq.conf index b7528dde5e269f4df5dca5177c915abcd32f28b2..d8e1f40b3bc65d54651c7e944506125119172f73 100644 --- a/libsepol/tests/policies/test-deps/base-metreq.conf +++ b/libsepol/tests/policies/test-deps/base-metreq.conf @@ -33,7 +33,7 @@ class key_socket class unix_stream_socket class unix_dgram_socket -# sysv-ipc-related clases +# sysv-ipc-related classes class sem class msg class msgq diff --git a/libsepol/tests/policies/test-deps/base-notmetreq.conf b/libsepol/tests/policies/test-deps/base-notmetreq.conf index eee36dcaf43d120ef9a8c052b94897fddf1463de..ecd92f6fa421bc2b36c993578249fad811de9b09 100644 --- a/libsepol/tests/policies/test-deps/base-notmetreq.conf +++ b/libsepol/tests/policies/test-deps/base-notmetreq.conf @@ -33,7 +33,7 @@ class key_socket class unix_stream_socket class unix_dgram_socket -# sysv-ipc-related clases +# sysv-ipc-related classes class msg class msgq class shm diff --git a/libsepol/tests/policies/test-deps/small-base.conf b/libsepol/tests/policies/test-deps/small-base.conf index 98f49c23e33d5d6b43d696855728d5337324ee21..848d1741b99537e7b395ab9bdff7ffbe72ff8d5f 100644 --- a/libsepol/tests/policies/test-deps/small-base.conf +++ b/libsepol/tests/policies/test-deps/small-base.conf @@ -33,7 +33,7 @@ class key_socket class unix_stream_socket class unix_dgram_socket -# sysv-ipc-related clases +# sysv-ipc-related classes class sem class msg class msgq diff --git a/libsepol/tests/policies/test-expander/alias-base.conf b/libsepol/tests/policies/test-expander/alias-base.conf index b950039df185127b52a35371f07d1dfb340d605f..349559241b6c10d93c8bbe10408dafc5a5a6dcf2 100644 --- a/libsepol/tests/policies/test-expander/alias-base.conf +++ b/libsepol/tests/policies/test-expander/alias-base.conf @@ -33,7 +33,7 @@ class key_socket class unix_stream_socket class unix_dgram_socket -# sysv-ipc-related clases +# sysv-ipc-related classes class sem class msg class msgq diff --git a/libsepol/tests/policies/test-expander/role-base.conf b/libsepol/tests/policies/test-expander/role-base.conf index 8e88b4be80d80060ec1562350456b78b8efecc9b..a387c8c0d4ccf32b040caa748943fbe6b842c5da 100644 --- a/libsepol/tests/policies/test-expander/role-base.conf +++ b/libsepol/tests/policies/test-expander/role-base.conf @@ -33,7 +33,7 @@ class key_socket class unix_stream_socket class unix_dgram_socket -# sysv-ipc-related clases +# sysv-ipc-related classes class sem class msg class msgq diff --git a/libsepol/tests/policies/test-expander/small-base.conf b/libsepol/tests/policies/test-expander/small-base.conf index 055ea0544885ea0d09ce6ad2d9bedf32f51fc893..ac180f355d2f1b312f6dbd477e0aebc74bae26cc 100644 --- a/libsepol/tests/policies/test-expander/small-base.conf +++ b/libsepol/tests/policies/test-expander/small-base.conf @@ -33,7 +33,7 @@ class key_socket class unix_stream_socket class unix_dgram_socket -# sysv-ipc-related clases +# sysv-ipc-related classes class sem class msg class msgq diff --git a/libsepol/tests/policies/test-expander/user-base.conf b/libsepol/tests/policies/test-expander/user-base.conf index b31ee8cd2043e163212195cffe1cc310bf1f5991..789a59a208394366cb6c1a32f96cef8831165404 100644 --- a/libsepol/tests/policies/test-expander/user-base.conf +++ b/libsepol/tests/policies/test-expander/user-base.conf @@ -33,7 +33,7 @@ class key_socket class unix_stream_socket class unix_dgram_socket -# sysv-ipc-related clases +# sysv-ipc-related classes class sem class msg class msgq diff --git a/libsepol/tests/policies/test-hooks/cmp_policy.conf b/libsepol/tests/policies/test-hooks/cmp_policy.conf index 9082b333dc800b977870f374a525009329858e12..3c510bc4a5da4514fda0f86042e7065ca65534cb 100644 --- a/libsepol/tests/policies/test-hooks/cmp_policy.conf +++ b/libsepol/tests/policies/test-hooks/cmp_policy.conf @@ -33,7 +33,7 @@ class key_socket class unix_stream_socket class unix_dgram_socket -# sysv-ipc-related clases +# sysv-ipc-related classes class sem class msg class msgq diff --git a/libsepol/tests/policies/test-hooks/small-base.conf b/libsepol/tests/policies/test-hooks/small-base.conf index 9082b333dc800b977870f374a525009329858e12..3c510bc4a5da4514fda0f86042e7065ca65534cb 100644 --- a/libsepol/tests/policies/test-hooks/small-base.conf +++ b/libsepol/tests/policies/test-hooks/small-base.conf @@ -33,7 +33,7 @@ class key_socket class unix_stream_socket class unix_dgram_socket -# sysv-ipc-related clases +# sysv-ipc-related classes class sem class msg class msgq diff --git a/libsepol/tests/policies/test-linker/small-base.conf b/libsepol/tests/policies/test-linker/small-base.conf index 890ebbebc8e3e4f8216cd987caafddd5032c90a2..15ced459209a9664b52f9e14fffdb3a4c6cf878a 100644 --- a/libsepol/tests/policies/test-linker/small-base.conf +++ b/libsepol/tests/policies/test-linker/small-base.conf @@ -33,7 +33,7 @@ class key_socket class unix_stream_socket class unix_dgram_socket -# sysv-ipc-related clases +# sysv-ipc-related classes class sem class msg class msgq diff --git a/libsepol/tests/policies/test-neverallow/policy.conf b/libsepol/tests/policies/test-neverallow/policy.conf new file mode 100644 index 0000000000000000000000000000000000000000..67a163722d643c97e0690433188e1f0d796a2a8e --- /dev/null +++ b/libsepol/tests/policies/test-neverallow/policy.conf @@ -0,0 +1,298 @@ +class process +class blk_file +class chr_file +class dir +class fifo_file +class file +class lnk_file +class sock_file + +sid kernel +sid security +sid unlabeled +sid file +sid port +sid netif +sid netmsg +sid node +sid devnull + +class process { dyntransition transition } +class file { getattr ioctl open read write } + +ifdef(`enable_mls',` +sensitivity s0; +dominance { s0 } +category c0; category c1; category c2; category c3; +category c4; category c5; category c6; category c7; +category c8; category c9; category c10; category c11; +category c12; category c13; category c14; category c15; +category c16; category c17; category c18; category c19; +category c20; category c21; category c22; category c23; + +level s0:c0.c23; + +mlsconstrain file { write } ( h1 dom h2 ); +') + + +######################################## +# +# Test start +# +######################################## + + +## Test 1 (basic) + +type test1_t; +allow test1_t test1_t : file { read write }; +neverallow test1_t test1_t : file read; + + +## Test 2 (wildcard permission) + +type test2_t; +allow test2_t test2_t : file { read write }; +neverallow test2_t test2_t : file *; + + +## Test 3 (complement permission) + +type test3_t; +allow test3_t test3_t : file { read write }; +neverallow test3_t test3_t : file ~{ write }; + + +## Test 4 (wildcard source) + +type test4_t; +allow test4_t test4_t : file { read write }; +neverallow * test4_t : file read; + + +## Test 5 (wildcard target) + +type test5_t; +allow test5_t test5_t : file { read write }; +neverallow test5_t * : file read; + + +## Test 6 (complement source) + +type test6_1_t; +type test6_2_t; +allow { test6_1_t test6_2_t } { test6_1_t test6_2_t } : file { read write }; +neverallow ~{ test6_2_t } test6_1_t : file read; + + +## Test 7 (complement target) + +type test7_1_t; +type test7_2_t; +allow { test7_1_t test7_2_t } { test7_1_t test7_2_t } : file { read write }; +neverallow test7_1_t ~{ test7_2_t } : file read; + + +## Test 8 (source attribute) + +attribute test8_a; +type test8_t, test8_a; +allow test8_a test8_a : file read; +allow test8_t test8_t : file write; +neverallow test8_a test8_t : file { read write }; + + +## Test 9 (target attribute) + +attribute test9_a; +type test9_t, test9_a; +allow test9_a test9_a : file read; +allow test9_t test9_t : file write; +neverallow test9_t test9_a : file { read write }; + + +## Test 10 (self) + +attribute test10_a; +type test10_1_t, test10_a; +type test10_2_t; +allow { test10_1_t test10_2_t } { test10_1_t test10_2_t } : file read; +neverallow test10_a self : file *; + + +## Test 11 (wildcard) + +type test11_t; +allow test11_t self : process *; +neverallow * * : process *; + + +## Test 12 (complement attributes) + +attribute test12_1_a; +attribute test12_2_a; +attribute test12_3_a; +type test12_1_t, test12_1_a; +type test12_2_t, test12_2_a; +type test12_3_t, test12_3_a; +allow { test12_1_a test12_2_a test12_3_a } { test12_1_a test12_2_a test12_3_a } : file *; +neverallow ~{ test12_1_a test12_2_t } ~{ test12_3_a } : file getattr; +neverallow ~{ test12_1_a } ~{ test12_2_a test12_3_t } : file open; + + +## Test 13 (excludes) + +attribute test13_1_a; +attribute test13_2_a; +attribute test13_3_a; +type test13_1_t, test13_1_a; +type test13_2_t, test13_2_a; +type test13_3_t, test13_3_a; +allow { test13_1_a test13_2_a test13_3_a } { test13_1_a test13_2_a test13_3_a } : file { read write }; +neverallow { test13_1_a test13_2_a test13_3_a -test13_2_a -test13_3_t } { test13_1_a test13_2_a test13_3_a -test13_2_t -test13_3_a } : file read; + + +## Test 14 (misc avrules) + +type test14_t; +auditallow test14_t test14_t : file read; +dontaudit test14_t test14_t : file write; +neverallow test14_t test14_t : file { read write }; +type_transition test14_t test14_t : file test14_t; +type_transition test14_t test14_t : file test14_t "objname"; +neverallow test14_t test14_t : file *; # nofail + + +## Test 15 (extended permissions - standard allow) + +type test15_t; +allow test15_t self : file ioctl; +neverallowxperm test15_t self : file ioctl 0x1111; + + +## Test 16 (extended permissions - allowxperm) + +type test16_t; +allow test16_t self : file ioctl; +allowxperm test16_t self : file ioctl 0x1111; +neverallowxperm test16_t self : file ioctl 0x1111; + + +## Test 17 (extended permissions - allowxperm mismatch) + +type test17_t; +allow test17_t self : file ioctl; +allowxperm test17_t self : file ioctl 0x1111; +neverallowxperm test17_t self : file ioctl 0x2222; # nofail + + +## Test 18 (extended permissions - allowxperm range I) + +type test18_t; +allow test18_t self : file ioctl; +allowxperm test18_t self : file ioctl { 0x1100-0x1300 }; +neverallowxperm test18_t self : file ioctl 0x1111; + + +## Test 19 (extended permissions - allowxperm range II) + +type test19_t; +allow test19_t self : file ioctl; +allowxperm test19_t self : file ioctl 0x1111; +neverallowxperm test19_t self : file ioctl { 0x1100-0x1300 }; + + +## Test 20 (extended permissions - misc targets I) + +attribute test20_a; +type test20_t, test20_a; + +allow test20_a test20_a : file ioctl; +allowxperm test20_a test20_a : file ioctl 0x1111; +neverallowxperm test20_a self : file ioctl 0x1111; + + +## Test 21 (extended permissions - misc targets II) + +attribute test21_1_a; +attribute test21_2_a; +type test21_t, test21_1_a, test21_2_a; + +allow test21_1_a test21_1_a : file ioctl; +allowxperm test21_1_a test21_2_a : file ioctl 0x1111; +neverallowxperm test21_1_a self : file ioctl 0x1111; + + +## Test 22 (extended permissions - misc targets III) + +attribute test22_a; +type test22_t, test22_a; + +allow test22_a test22_a : file ioctl; +allowxperm test22_t self : file ioctl 0x1111; +neverallowxperm test22_a self : file ioctl 0x1111; + + +## Test 23 (extended permissions - misc targets IV) + +attribute test23_a; +type test23_t, test23_a; + +allow test23_a test23_a : file ioctl; +allowxperm test23_t test23_t : file ioctl 0x1111; +neverallowxperm test23_a self : file ioctl 0x1111; + + +## Test 24 (extended permissions - misc targets V) + +attribute test24_a; +type test24_t, test24_a; + +allow test24_a test24_a : file ioctl; +allowxperm test24_t test24_a : file ioctl 0x1111; +neverallowxperm test24_a self : file ioctl 0x1111; + + +## Test 25 (extended permissions - misc targets VI) + +attribute test25_a; +type test25_t, test25_a; + +allow test25_a test25_a : file ioctl; +allowxperm test25_a self : file ioctl 0x1111; +neverallowxperm test25_a self : file ioctl 0x1111; + + +## Test 26 (extended permissions - assert twice) + +attribute test26_a; +type test26_1_t, test26_a; +type test26_2_t, test26_a; +allow test26_a test26_a : file ioctl; +allowxperm test26_a test26_a : file ioctl 0x1111; +neverallowxperm test26_1_t test26_a : file ioctl 0x1111; + + +######################################## +# +# Test End +# +######################################## + + +type sys_isid; +role sys_role; +role sys_role types sys_isid; +gen_user(sys_user,, sys_role, s0, s0 - s0:c0.c23) +sid kernel gen_context(sys_user:sys_role:sys_isid, s0) +sid security gen_context(sys_user:sys_role:sys_isid, s0) +sid unlabeled gen_context(sys_user:sys_role:sys_isid, s0) +sid file gen_context(sys_user:sys_role:sys_isid, s0) +sid port gen_context(sys_user:sys_role:sys_isid, s0) +sid netif gen_context(sys_user:sys_role:sys_isid, s0) +sid netmsg gen_context(sys_user:sys_role:sys_isid, s0) +sid node gen_context(sys_user:sys_role:sys_isid, s0) +sid devnull gen_context(sys_user:sys_role:sys_isid, s0) +fs_use_trans devpts gen_context(sys_user:sys_role:sys_isid, s0); +fs_use_trans devtmpfs gen_context(sys_user:sys_role:sys_isid, s0); diff --git a/libsepol/tests/test-ebitmap.c b/libsepol/tests/test-ebitmap.c new file mode 100644 index 0000000000000000000000000000000000000000..8774555e65e6c42c1b8e079bd9b9bb94e0b57e1c --- /dev/null +++ b/libsepol/tests/test-ebitmap.c @@ -0,0 +1,1080 @@ +#include "test-ebitmap.h" + +#include +#include + +#include +#include + +#define RANDOM_ROUNDS 10 + + +static int ebitmap_init_random(ebitmap_t *e, unsigned int length, int set_chance) +{ + unsigned int i; + int rc; + + if (set_chance <= 0 || set_chance > 100) + return -EINVAL; + + ebitmap_init(e); + + for (i = 0; i < length; i++) { + if ((random() % 100) < set_chance) { + rc = ebitmap_set_bit(e, i, 1); + if (rc) + return rc; + } + } + + return 0; +} + +static void test_ebitmap_init_destroy(void) +{ + ebitmap_t e; + + /* verify idempotence */ + ebitmap_init(&e); + ebitmap_init(&e); + ebitmap_init(&e); + + CU_ASSERT(ebitmap_is_empty(&e)); + CU_ASSERT_PTR_NULL(ebitmap_startnode(&e)); + + /* verify idempotence */ + ebitmap_destroy(&e); + ebitmap_destroy(&e); + ebitmap_destroy(&e); + + CU_ASSERT(ebitmap_is_empty(&e)); + CU_ASSERT_PTR_NULL(ebitmap_startnode(&e)); +} + +static void test_ebitmap_cmp(void) +{ + ebitmap_t e1, e2; + + ebitmap_init(&e1); + ebitmap_init(&e2); + + CU_ASSERT(ebitmap_cmp(&e1, &e2)); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 10, 1), 0); + CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 10, 1), 0); + CU_ASSERT(ebitmap_cmp(&e1, &e2)); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 63, 1), 0); + CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 63, 1), 0); + CU_ASSERT(ebitmap_cmp(&e1, &e2)); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 64, 1), 0); + CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 64, 1), 0); + CU_ASSERT(ebitmap_cmp(&e1, &e2)); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1022, 1), 0); + CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 1022, 1), 0); + CU_ASSERT(ebitmap_cmp(&e1, &e2)); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1023, 1), 0); + CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 1023, 1), 0); + CU_ASSERT(ebitmap_cmp(&e1, &e2)); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1024, 1), 0); + CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 1024, 1), 0); + CU_ASSERT(ebitmap_cmp(&e1, &e2)); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1025, 1), 0); + CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 1025, 1), 0); + CU_ASSERT(ebitmap_cmp(&e1, &e2)); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 255, 1), 0); + CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 255, 1), 0); + CU_ASSERT(ebitmap_cmp(&e1, &e2)); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 256, 1), 0); + CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 256, 1), 0); + CU_ASSERT(ebitmap_cmp(&e1, &e2)); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 639, 1), 0); + CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 639, 1), 0); + CU_ASSERT(ebitmap_cmp(&e1, &e2)); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 640, 1), 0); + CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 640, 1), 0); + CU_ASSERT(ebitmap_cmp(&e1, &e2)); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 900, 1), 0); + CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 900, 1), 0); + CU_ASSERT(ebitmap_cmp(&e1, &e2)); + + ebitmap_destroy(&e2); + + CU_ASSERT_FALSE(ebitmap_cmp(&e1, &e2)); + + ebitmap_destroy(&e1); + + CU_ASSERT(ebitmap_cmp(&e1, &e2)); +} + +static void test_ebitmap_set_and_get(void) +{ + ebitmap_t e; + + ebitmap_init(&e); + + CU_ASSERT(ebitmap_is_empty(&e)); + CU_ASSERT_TRUE(ebitmap_is_empty(&e)); + CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 0); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 0); + CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 10), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e, UINT32_MAX, 1), -EINVAL); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 10, 0), 0); + CU_ASSERT(ebitmap_is_empty(&e)); + CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 0); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 0); + CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 10), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 10, 1), 0); + CU_ASSERT_FALSE(ebitmap_is_empty(&e)); + CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 1); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 10); + CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 10), 1); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 100, 1), 0); + CU_ASSERT_FALSE(ebitmap_is_empty(&e)); + CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 2); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 100); + CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 100), 1); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 50, 1), 0); + CU_ASSERT_FALSE(ebitmap_is_empty(&e)); + CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 3); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 100); + CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 50), 1); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 1023, 1), 0); + CU_ASSERT_FALSE(ebitmap_is_empty(&e)); + CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 4); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1023); + CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 1023), 1); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 1024, 1), 0); + CU_ASSERT_FALSE(ebitmap_is_empty(&e)); + CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 5); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1024); + CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 1024), 1); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 1050, 1), 0); + CU_ASSERT_FALSE(ebitmap_is_empty(&e)); + CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 6); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1050); + CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 1050), 1); + + { + ebitmap_node_t *n; + unsigned int bit, count; + + /* iterate all allocated bits */ + count = 0; + ebitmap_for_each_bit(&e, n, bit) { + CU_ASSERT( bit < 64 || + (64 <= bit && bit < 128) || + (960 <= bit && bit < 1024) || + (1024 <= bit && bit < 1088)); + count++; + } + CU_ASSERT_EQUAL(count, 4 * 64); + + count = 0; + ebitmap_for_each_positive_bit(&e, n, bit) { + CU_ASSERT(bit == 10 || + bit == 50 || + bit == 100 || + bit == 1023 || + bit == 1024 || + bit == 1050); + CU_ASSERT_EQUAL(ebitmap_get_bit(&e, bit), 1); + count++; + } + CU_ASSERT_EQUAL(count, 6); + } + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 1024, 0), 0); + CU_ASSERT_FALSE(ebitmap_is_empty(&e)); + CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 5); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1050); + CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 1024), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 1050, 0), 0); + CU_ASSERT_FALSE(ebitmap_is_empty(&e)); + CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 4); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1023); + CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 1050), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 100, 0), 0); + CU_ASSERT_FALSE(ebitmap_is_empty(&e)); + CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 3); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1023); + CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 100), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 10, 0), 0); + CU_ASSERT_FALSE(ebitmap_is_empty(&e)); + CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 2); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1023); + CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 10), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 50, 0), 0); + CU_ASSERT_FALSE(ebitmap_is_empty(&e)); + CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 1); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 1023); + CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 50), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e, 1023, 0), 0); + CU_ASSERT_TRUE(ebitmap_is_empty(&e)); + CU_ASSERT_EQUAL(ebitmap_cardinality(&e), 0); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e), 0); + CU_ASSERT_EQUAL(ebitmap_get_bit(&e, 1023), 0); + + ebitmap_destroy(&e); +} + +static void test_ebitmap_init_range(void) +{ + ebitmap_t e1, e2, e3, e4, e5, e6; + + CU_ASSERT_EQUAL(ebitmap_init_range(&e1, 0, 0), 0); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e1), 0); + CU_ASSERT_EQUAL(ebitmap_cardinality(&e1), 1); + + CU_ASSERT_EQUAL(ebitmap_init_range(&e2, 0, 5), 0); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e2), 5); + CU_ASSERT_EQUAL(ebitmap_cardinality(&e2), 6); + + CU_ASSERT_EQUAL(ebitmap_init_range(&e3, 20, 100), 0); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e3), 100); + CU_ASSERT_EQUAL(ebitmap_cardinality(&e3), 81); + + CU_ASSERT_EQUAL(ebitmap_init_range(&e4, 100, 400), 0); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&e4), 400); + CU_ASSERT_EQUAL(ebitmap_cardinality(&e4), 301); + + CU_ASSERT_EQUAL(ebitmap_init_range(&e5, 10, 5), -EINVAL); + CU_ASSERT_EQUAL(ebitmap_init_range(&e6, 0, UINT32_MAX), -EOVERFLOW); + + ebitmap_destroy(&e6); + ebitmap_destroy(&e5); + ebitmap_destroy(&e4); + ebitmap_destroy(&e3); + ebitmap_destroy(&e2); + ebitmap_destroy(&e1); +} + +static void test_ebitmap_or(void) +{ + ebitmap_t e1, e2, e3, e4; + + ebitmap_init(&e1); + ebitmap_init(&e2); + ebitmap_init(&e3); + ebitmap_init(&e4); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 10, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 100, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 101, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 318, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 319, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 383, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 384, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 449, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1013, 1), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 11, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 101, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 430, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 665, 1), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 10, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 11, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 100, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 101, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 318, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 319, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 383, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 384, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 430, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 449, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 665, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 1013, 1), 0); + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_or(&dst, &e1, &e1), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e1)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_or(&dst, &e2, &e2), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e2)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_or(&dst, &e1, &e2), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e3)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_or(&dst, &e3, &e3), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e3)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_or(&dst, &e3, &e4), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e3)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_or(&dst, &e4, &e4), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e4)); + + ebitmap_destroy(&dst); + } + + ebitmap_destroy(&e4); + ebitmap_destroy(&e3); + ebitmap_destroy(&e2); + ebitmap_destroy(&e1); +} + +static void test_ebitmap_and(void) +{ + { + ebitmap_t e1, e2, e12, e3, e4; + + ebitmap_init(&e1); + ebitmap_init(&e2); + ebitmap_init(&e12); + ebitmap_init(&e3); + ebitmap_init(&e4); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 10, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 100, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 101, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 318, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 319, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 383, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 384, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 449, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1013, 1), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 11, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 101, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 319, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 665, 1), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e12, 101, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e12, 319, 1), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 10, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 11, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 100, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 101, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 318, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 319, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 383, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 384, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 430, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 449, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 665, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 1013, 1), 0); + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_and(&dst, &e1, &e1), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e1)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_and(&dst, &e2, &e2), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e2)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_and(&dst, &e1, &e2), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e12)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_and(&dst, &e3, &e3), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e3)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_and(&dst, &e1, &e3), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e1)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_and(&dst, &e2, &e3), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e2)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_and(&dst, &e4, &e4), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e4)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_and(&dst, &e3, &e4), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e4)); + + ebitmap_destroy(&dst); + } + + ebitmap_destroy(&e4); + ebitmap_destroy(&e3); + ebitmap_destroy(&e12); + ebitmap_destroy(&e2); + ebitmap_destroy(&e1); + } + + { + ebitmap_t e5; + ebitmap_t e6; + ebitmap_t e56; + ebitmap_t dst; + + ebitmap_init(&e5); + ebitmap_init(&e6); + ebitmap_init(&e56); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 63, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 191, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 192, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 318, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 319, 1), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 64, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 192, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 319, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 320, 1), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 192, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 319, 1), 0); + + CU_ASSERT_EQUAL(ebitmap_and(&dst, &e5, &e6), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e56)); + + ebitmap_destroy(&dst); + ebitmap_destroy(&e56); + ebitmap_destroy(&e6); + ebitmap_destroy(&e5); + } +} + +static void test_ebitmap_xor(void) +{ + { + ebitmap_t e1, e2, e3, e4; + + ebitmap_init(&e1); + ebitmap_init(&e2); + ebitmap_init(&e3); + ebitmap_init(&e4); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 5, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 10, 1), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 1, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 3, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 6, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 9, 1), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 3, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 5, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 6, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 9, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 10, 1), 0); + + { + ebitmap_t dst1, dst2; + + CU_ASSERT_EQUAL(ebitmap_xor(&dst1, &e1, &e1), 0); + CU_ASSERT(ebitmap_cmp(&dst1, &e4)); + CU_ASSERT_EQUAL(ebitmap_xor(&dst2, &dst1, &e1), 0); + CU_ASSERT(ebitmap_cmp(&dst2, &e1)); + + ebitmap_destroy(&dst2); + ebitmap_destroy(&dst1); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_xor(&dst, &e2, &e2), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e4)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_xor(&dst, &e3, &e3), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e4)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_xor(&dst, &e4, &e4), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e4)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_xor(&dst, &e1, &e2), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e3)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_xor(&dst, &e2, &e4), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e2)); + + ebitmap_destroy(&dst); + } + + ebitmap_destroy(&e4); + ebitmap_destroy(&e3); + ebitmap_destroy(&e2); + ebitmap_destroy(&e1); + } + + { + ebitmap_t e5; + ebitmap_t e6; + ebitmap_t e56; + ebitmap_t dst; + + ebitmap_init(&e5); + ebitmap_init(&e6); + ebitmap_init(&e56); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 63, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 191, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 192, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 318, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 319, 1), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 64, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 192, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 319, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 320, 1), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 63, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 64, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 191, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 318, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 320, 1), 0); + + CU_ASSERT_EQUAL(ebitmap_xor(&dst, &e5, &e6), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e56)); + + ebitmap_destroy(&dst); + ebitmap_destroy(&e56); + ebitmap_destroy(&e6); + ebitmap_destroy(&e5); + } +} + +static void test_ebitmap_not(void) +{ + { + ebitmap_t e1, e2, e3, e4; + + ebitmap_init(&e1); + ebitmap_init(&e2); + ebitmap_init(&e3); + ebitmap_init(&e4); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 0, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 5, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 10, 1), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 2, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 3, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 4, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 6, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 7, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 8, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 9, 1), 0); + + { + ebitmap_t dst1, dst2; + + CU_ASSERT_EQUAL(ebitmap_not(&dst1, &e3, 10), 0); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&dst1), 9); + CU_ASSERT_EQUAL(ebitmap_cardinality(&dst1), 10); + + CU_ASSERT_EQUAL(ebitmap_not(&dst2, &dst1, 10), 0); + CU_ASSERT(ebitmap_cmp(&dst2, &e3)); + + ebitmap_destroy(&dst2); + ebitmap_destroy(&dst1); + } + + { + ebitmap_t dst1, dst2; + + CU_ASSERT_EQUAL(ebitmap_not(&dst1, &e1, 11), 0); + CU_ASSERT(ebitmap_cmp(&dst1, &e2)); + CU_ASSERT_EQUAL(ebitmap_not(&dst2, &dst1, 11), 0); + CU_ASSERT(ebitmap_cmp(&dst2, &e1)); + + ebitmap_destroy(&dst2); + ebitmap_destroy(&dst1); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_not(&dst, &e1, 8), 0); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&dst), 7); + CU_ASSERT_EQUAL(ebitmap_cardinality(&dst), 5); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_not(&dst, &e1, 12), 0); + CU_ASSERT_EQUAL(ebitmap_highest_set_bit(&dst), 11); + CU_ASSERT_EQUAL(ebitmap_cardinality(&dst), 8); + + ebitmap_destroy(&dst); + } + + ebitmap_destroy(&e3); + ebitmap_destroy(&e2); + ebitmap_destroy(&e1); + } + + { + ebitmap_t e5; + ebitmap_t e5not; + ebitmap_node_t *n; + unsigned int bit; + + ebitmap_init(&e5); + ebitmap_init(&e5not); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 63, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 191, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 192, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 318, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 319, 1), 0); + + for (bit = 0; bit < 317; bit++) + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5not, bit, 1), 0); + ebitmap_for_each_positive_bit(&e5, n, bit) + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5not, bit, 0), 0); + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_not(&dst, &e5, 317), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e5not)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_not(&dst, &e5, 318), 0); + CU_ASSERT_FALSE(ebitmap_cmp(&dst, &e5not)); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5not, 317, 1), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e5not)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_not(&dst, &e5, 319), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e5not)); + + ebitmap_destroy(&dst); + } + + ebitmap_destroy(&e5not); + ebitmap_destroy(&e5); + } +} + +static void test_ebitmap_andnot(void) +{ + { + ebitmap_t e1, e2, e12, e3, e4; + + ebitmap_init(&e1); + ebitmap_init(&e2); + ebitmap_init(&e12); + ebitmap_init(&e3); + ebitmap_init(&e4); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 10, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 100, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 101, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 430, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e1, 1013, 1), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 11, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 101, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e2, 665, 1), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e12, 10, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e12, 100, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e12, 430, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e12, 1013, 1), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 10, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 11, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 100, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 101, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 430, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 665, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e3, 1013, 1), 0); + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e1, &e1, 1024), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e4)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e2, &e2, 1024), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e4)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e1, &e2, 1024), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e12)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e3, &e3, 1024), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e4)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e1, &e3, 1024), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e4)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e2, &e12, 1024), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e2)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e4, &e4, 1024), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e4)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e3, &e4, 1024), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e3)); + + ebitmap_destroy(&dst); + } + + ebitmap_destroy(&e4); + ebitmap_destroy(&e3); + ebitmap_destroy(&e12); + ebitmap_destroy(&e2); + ebitmap_destroy(&e1); + } + + { + ebitmap_t e5; + ebitmap_t e6; + ebitmap_t e56; + + ebitmap_init(&e5); + ebitmap_init(&e6); + ebitmap_init(&e56); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 63, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 191, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 192, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 318, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e5, 319, 1), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 64, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 192, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 319, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e6, 320, 1), 0); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 63, 1), 0); + CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 191, 1), 0); + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e5, &e6, 317), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e56)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e5, &e6, 318), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e56)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e5, &e6, 319), 0); + CU_ASSERT_FALSE(ebitmap_cmp(&dst, &e56)); + + CU_ASSERT_EQUAL(ebitmap_set_bit(&e56, 318, 1), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e56)); + + ebitmap_destroy(&dst); + } + + { + ebitmap_t dst; + + CU_ASSERT_EQUAL(ebitmap_andnot(&dst, &e5, &e6, 320), 0); + CU_ASSERT(ebitmap_cmp(&dst, &e56)); + + ebitmap_destroy(&dst); + } + + ebitmap_destroy(&e56); + ebitmap_destroy(&e6); + ebitmap_destroy(&e5); + } +} + +static void test_ebitmap__random_impl(unsigned int length, int set_chance) +{ + ebitmap_t e1, e2, dst_cpy, dst_or, dst_and, dst_xor1, dst_xor2, dst_not1, dst_not2, dst_andnot; + unsigned int i; + + CU_ASSERT_EQUAL(ebitmap_init_random(&e1, length, set_chance), 0); + CU_ASSERT_EQUAL(ebitmap_init_random(&e2, length, set_chance), 0); + + CU_ASSERT_EQUAL(ebitmap_cpy(&dst_cpy, &e1), 0); + CU_ASSERT(ebitmap_cmp(&dst_cpy, &e1)); + + CU_ASSERT_EQUAL(ebitmap_or(&dst_or, &e1, &e2), 0); + for (i = 0; i < length; i++) + CU_ASSERT_EQUAL(ebitmap_get_bit(&dst_or, i), ebitmap_get_bit(&e1, i) | ebitmap_get_bit(&e2, i)); + + CU_ASSERT_EQUAL(ebitmap_and(&dst_and, &e1, &e2), 0); + for (i = 0; i < length; i++) + CU_ASSERT_EQUAL(ebitmap_get_bit(&dst_and, i), ebitmap_get_bit(&e1, i) & ebitmap_get_bit(&e2, i)); + + CU_ASSERT_EQUAL(ebitmap_xor(&dst_xor1, &e1, &e2), 0); + for (i = 0; i < length; i++) + CU_ASSERT_EQUAL(ebitmap_get_bit(&dst_xor1, i), ebitmap_get_bit(&e1, i) ^ ebitmap_get_bit(&e2, i)); + CU_ASSERT_EQUAL(ebitmap_xor(&dst_xor2, &dst_xor1, &e2), 0); + CU_ASSERT(ebitmap_cmp(&dst_xor2, &e1)); + + CU_ASSERT_EQUAL(ebitmap_not(&dst_not1, &e1, length), 0); + for (i = 0; i < length; i++) + CU_ASSERT_EQUAL(ebitmap_get_bit(&dst_not1, i), !ebitmap_get_bit(&e1, i)); + CU_ASSERT_EQUAL(ebitmap_not(&dst_not2, &dst_not1, length), 0); + CU_ASSERT(ebitmap_cmp(&dst_not2, &e1)); + + CU_ASSERT_EQUAL(ebitmap_andnot(&dst_andnot, &e1, &e2, length), 0); + for (i = 0; i < length; i++) + CU_ASSERT_EQUAL(ebitmap_get_bit(&dst_andnot, i), ebitmap_get_bit(&e1, i) & !ebitmap_get_bit(&e2, i)); + + ebitmap_destroy(&dst_andnot); + ebitmap_destroy(&dst_not2); + ebitmap_destroy(&dst_not1); + ebitmap_destroy(&dst_xor2); + ebitmap_destroy(&dst_xor1); + ebitmap_destroy(&dst_and); + ebitmap_destroy(&dst_or); + ebitmap_destroy(&dst_cpy); + ebitmap_destroy(&e2); + ebitmap_destroy(&e1); +} + +static void test_ebitmap__random(void) +{ + unsigned int i; + + for (i = 0; i < RANDOM_ROUNDS; i++) + test_ebitmap__random_impl(5, 10); + + for (i = 0; i < RANDOM_ROUNDS; i++) + test_ebitmap__random_impl(5, 90); + + for (i = 0; i < RANDOM_ROUNDS; i++) + test_ebitmap__random_impl(1024, 50); + + for (i = 0; i < RANDOM_ROUNDS; i++) + test_ebitmap__random_impl(8000, 5); + + for (i = 0; i < RANDOM_ROUNDS; i++) + test_ebitmap__random_impl(8000, 95); +} + +/* + * External hooks + */ + +int ebitmap_test_init(void) +{ + srandom(time(NULL)); + + /* silence ebitmap_set_bit() failure message */ + sepol_debug(0); + + return 0; +} + +int ebitmap_test_cleanup(void) +{ + return 0; +} + +#define ADD_TEST(name) \ + do { \ + if (NULL == CU_add_test(suite, #name, test_##name)) { \ + return CU_get_error(); \ + } \ + } while (0) + +int ebitmap_add_tests(CU_pSuite suite) +{ + ADD_TEST(ebitmap_init_destroy); + ADD_TEST(ebitmap_cmp); + ADD_TEST(ebitmap_set_and_get); + ADD_TEST(ebitmap_init_range); + ADD_TEST(ebitmap_or); + ADD_TEST(ebitmap_and); + ADD_TEST(ebitmap_xor); + ADD_TEST(ebitmap_not); + ADD_TEST(ebitmap_andnot); + ADD_TEST(ebitmap__random); + return 0; +} diff --git a/libsepol/tests/test-ebitmap.h b/libsepol/tests/test-ebitmap.h new file mode 100644 index 0000000000000000000000000000000000000000..952a042109e3199b5a509eec935b7ca9385d4a1b --- /dev/null +++ b/libsepol/tests/test-ebitmap.h @@ -0,0 +1,10 @@ +#ifndef TEST_EBITMAP_H__ +#define TEST_EBITMAP_H__ + +#include + +int ebitmap_test_init(void); +int ebitmap_test_cleanup(void); +int ebitmap_add_tests(CU_pSuite suite); + +#endif /* TEST_EBITMAP_H__ */ diff --git a/libsepol/tests/test-linker-roles.c b/libsepol/tests/test-linker-roles.c index 2b17dffd50432fc023740379f34ac3b1c0f760f0..b35bdbe684a349d09ca0a18c52f1e82cd34b28af 100644 --- a/libsepol/tests/test-linker-roles.c +++ b/libsepol/tests/test-linker-roles.c @@ -53,7 +53,7 @@ /* this simply tests whether the passed in role only has its own * value in its dominates ebitmap */ -static void only_dominates_self(policydb_t * p, role_datum_t * role) +static void only_dominates_self(policydb_t * p __attribute__ ((unused)), role_datum_t * role) { ebitmap_node_t *tnode; unsigned int i; diff --git a/libsepol/tests/test-neverallow.c b/libsepol/tests/test-neverallow.c new file mode 100644 index 0000000000000000000000000000000000000000..d973a0e3def81128289f3bd8a27095dfdfbcfd35 --- /dev/null +++ b/libsepol/tests/test-neverallow.c @@ -0,0 +1,172 @@ +#define _GNU_SOURCE /* vasprintf(3) */ + +#include "test-neverallow.h" + +#include "helpers.h" +#include "test-common.h" + +#include +#include +#include + +#include +#include + +extern int mls; + +int neverallow_test_init(void) +{ + return 0; +} + +int neverallow_test_cleanup(void) +{ + return 0; +} + +static struct msg_list { + char *msg; + struct msg_list *next; +} *messages; + +static void messages_clean(void) +{ + while (messages) { + struct msg_list *n = messages->next; + free(messages->msg); + free(messages); + messages = n; + } +} + +static void messages_check(unsigned count, const char *const expected[count]) +{ + unsigned i; + const struct msg_list *m = messages; + + for (i = 0; i < count; i++, m = m->next) { + if (!m) { + CU_FAIL("less messages than expected"); + fprintf(stderr, "\n\n", count, i); + return; + } + + if (strcmp(expected[i], m->msg) != 0) { + CU_FAIL("messages differ from expected"); + fprintf(stderr, "\n\n", expected[i], m->msg); + } + } + + if (m) { + CU_FAIL("more messages than expected"); + fprintf(stderr, "\n\n", count, m->msg); + } +} + +__attribute__ ((format(printf, 3, 4))) +static void msg_handler(void *varg __attribute__ ((unused)), + sepol_handle_t * handle __attribute__ ((unused)), + const char *fmt, ...) +{ + char *msg; + va_list ap; + int r; + + va_start(ap, fmt); + r = vasprintf(&msg, fmt, ap); + if (r < 0) + CU_FAIL_FATAL("oom"); + va_end(ap); + + struct msg_list *new = malloc(sizeof(*new)); + if (!new) + CU_FAIL_FATAL("oom"); + new->msg = msg; + new->next = messages; + messages = new; +} + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a)) + +static void test_neverallow_basic(void) +{ + policydb_t basemod, base_expanded; + sepol_handle_t *handle; + static const char *const expected_messages[] = { + "30 neverallow failures occurred", + "neverallow on line 53 of policies/test-neverallow/policy.conf.std (or line 53 of policies/test-neverallow/policy.conf.std) violated by allow test1_t test1_t:file { read };", + "neverallow on line 60 of policies/test-neverallow/policy.conf.std (or line 60 of policies/test-neverallow/policy.conf.std) violated by allow test2_t test2_t:file { read write };", + "neverallow on line 67 of policies/test-neverallow/policy.conf.std (or line 67 of policies/test-neverallow/policy.conf.std) violated by allow test3_t test3_t:file { read };", + "neverallow on line 74 of policies/test-neverallow/policy.conf.std (or line 74 of policies/test-neverallow/policy.conf.std) violated by allow test4_t test4_t:file { read };", + "neverallow on line 81 of policies/test-neverallow/policy.conf.std (or line 81 of policies/test-neverallow/policy.conf.std) violated by allow test5_t test5_t:file { read };", + "neverallow on line 89 of policies/test-neverallow/policy.conf.std (or line 89 of policies/test-neverallow/policy.conf.std) violated by allow test6_1_t test6_1_t:file { read };", + "neverallow on line 97 of policies/test-neverallow/policy.conf.std (or line 97 of policies/test-neverallow/policy.conf.std) violated by allow test7_1_t test7_1_t:file { read };", + "neverallow on line 106 of policies/test-neverallow/policy.conf.std (or line 106 of policies/test-neverallow/policy.conf.std) violated by allow test8_t test8_t:file { write };", + "neverallow on line 106 of policies/test-neverallow/policy.conf.std (or line 106 of policies/test-neverallow/policy.conf.std) violated by allow test8_t test8_t:file { read };", + "neverallow on line 115 of policies/test-neverallow/policy.conf.std (or line 115 of policies/test-neverallow/policy.conf.std) violated by allow test9_t test9_t:file { read };", + "neverallow on line 115 of policies/test-neverallow/policy.conf.std (or line 115 of policies/test-neverallow/policy.conf.std) violated by allow test9_t test9_t:file { write };", + "neverallow on line 124 of policies/test-neverallow/policy.conf.std (or line 124 of policies/test-neverallow/policy.conf.std) violated by allow test10_1_t test10_1_t:file { read };", + "neverallow on line 131 of policies/test-neverallow/policy.conf.std (or line 131 of policies/test-neverallow/policy.conf.std) violated by allow test11_t test11_t:process { dyntransition transition };", + "neverallow on line 143 of policies/test-neverallow/policy.conf.std (or line 143 of policies/test-neverallow/policy.conf.std) violated by allow test12_3_t test12_1_t:file { getattr };", + "neverallow on line 143 of policies/test-neverallow/policy.conf.std (or line 143 of policies/test-neverallow/policy.conf.std) violated by allow test12_3_t test12_2_t:file { getattr };", + "neverallow on line 144 of policies/test-neverallow/policy.conf.std (or line 144 of policies/test-neverallow/policy.conf.std) violated by allow test12_3_t test12_1_t:file { open };", + "neverallow on line 144 of policies/test-neverallow/policy.conf.std (or line 144 of policies/test-neverallow/policy.conf.std) violated by allow test12_2_t test12_1_t:file { open };", + "neverallow on line 156 of policies/test-neverallow/policy.conf.std (or line 156 of policies/test-neverallow/policy.conf.std) violated by allow test13_1_t test13_1_t:file { read };", + "neverallowxperm on line 174 of policies/test-neverallow/policy.conf.std (or line 174 of policies/test-neverallow/policy.conf.std) violated by\nallow test15_t test15_t:file { ioctl };", + "neverallowxperm on line 182 of policies/test-neverallow/policy.conf.std (or line 182 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test16_t test16_t:file ioctl { 0x1111 };", + "neverallowxperm on line 198 of policies/test-neverallow/policy.conf.std (or line 198 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test18_t test18_t:file ioctl { 0x1111 };", + "neverallowxperm on line 206 of policies/test-neverallow/policy.conf.std (or line 206 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test19_t test19_t:file ioctl { 0x1111 };", + "neverallowxperm on line 216 of policies/test-neverallow/policy.conf.std (or line 216 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test20_a test20_a:file ioctl { 0x1111 };", + "neverallowxperm on line 227 of policies/test-neverallow/policy.conf.std (or line 227 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test21_1_a test21_2_a:file ioctl { 0x1111 };", + "neverallowxperm on line 237 of policies/test-neverallow/policy.conf.std (or line 237 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test22_t test22_t:file ioctl { 0x1111 };", + "neverallowxperm on line 247 of policies/test-neverallow/policy.conf.std (or line 247 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test23_t test23_t:file ioctl { 0x1111 };", + "neverallowxperm on line 257 of policies/test-neverallow/policy.conf.std (or line 257 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test24_t test24_a:file ioctl { 0x1111 };", + "neverallowxperm on line 267 of policies/test-neverallow/policy.conf.std (or line 267 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test25_t test25_t:file ioctl { 0x1111 };", + "neverallowxperm on line 277 of policies/test-neverallow/policy.conf.std (or line 277 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test26_a test26_a:file ioctl { 0x1111 };", + "neverallowxperm on line 277 of policies/test-neverallow/policy.conf.std (or line 277 of policies/test-neverallow/policy.conf.std) violated by\nallowxperm test26_a test26_a:file ioctl { 0x1111 };", + }; + + if (policydb_init(&base_expanded)) + CU_FAIL_FATAL("Failed to initialize policy"); + + if (test_load_policy(&basemod, POLICY_BASE, mls, "test-neverallow", "policy.conf")) + CU_FAIL_FATAL("Failed to load policy"); + + if (link_modules(NULL, &basemod, NULL, 0, 0)) + CU_FAIL_FATAL("Failed to link base module"); + + if (expand_module(NULL, &basemod, &base_expanded, 0, 0)) + CU_FAIL_FATAL("Failed to expand policy"); + + if ((handle = sepol_handle_create()) == NULL) + CU_FAIL_FATAL("Failed to initialize handle"); + + sepol_msg_set_callback(handle, msg_handler, NULL); + + if (check_assertions(handle, &base_expanded, base_expanded.global->branch_list->avrules) != -1) + CU_FAIL("Assertions did not trigger"); + + messages_check(ARRAY_SIZE(expected_messages), expected_messages); + + sepol_handle_destroy(handle); + messages_clean(); + policydb_destroy(&basemod); + policydb_destroy(&base_expanded); +} + +int neverallow_add_tests(CU_pSuite suite) +{ + /* + * neverallow rules operate only on types and are unaffected by MLS + * (avoid adjusting the messages for std and mls) + */ + if (mls) + return 0; + + if (NULL == CU_add_test(suite, "neverallow_basic", test_neverallow_basic)) { + CU_cleanup_registry(); + return CU_get_error(); + } + + return 0; +} diff --git a/libsepol/tests/test-neverallow.h b/libsepol/tests/test-neverallow.h new file mode 100644 index 0000000000000000000000000000000000000000..d3c2a74e2d2130ab4920ee8c5f43320f64cd9b1e --- /dev/null +++ b/libsepol/tests/test-neverallow.h @@ -0,0 +1,10 @@ +#ifndef TEST_NEVERALLOW_H__ +#define TEST_NEVERALLOW_H__ + +#include + +int neverallow_test_init(void); +int neverallow_test_cleanup(void); +int neverallow_add_tests(CU_pSuite suite); + +#endif /* TEST_NEVERALLOW_H__ */ diff --git a/libsepol/utils/sepol_check_access.c b/libsepol/utils/sepol_check_access.c index bd2ea89600f366840bd61037d9aefde1eb01c5bb..5d2bf6794c8b103944ffe9b04cdf67f7e0c5022a 100644 --- a/libsepol/utils/sepol_check_access.c +++ b/libsepol/utils/sepol_check_access.c @@ -109,7 +109,7 @@ int main(int argc, char *argv[]) if (reason & SEPOL_COMPUTEAV_RBAC) { if (i > 0) printf(", "); - printf("transition-constraint"); + printf("role-transition"); i++; } if (reason & SEPOL_COMPUTEAV_BOUNDS) { diff --git a/secilc/COPYING b/secilc/LICENSE similarity index 100% rename from secilc/COPYING rename to secilc/LICENSE diff --git a/secilc/VERSION b/secilc/VERSION index 2f4b60750dc3500b0e4cf08f316a960a7ca42b40..5a958026daa3208cb329c403433beb56abd5c036 100644 --- a/secilc/VERSION +++ b/secilc/VERSION @@ -1 +1 @@ -3.4 +3.5 diff --git a/secilc/docs/Makefile b/secilc/docs/Makefile index a03ebeed5a40c44cab9a389602299f06bbee008a..7e2ba40eb6627be15429af5c17687a4cfea5a7e5 100644 --- a/secilc/docs/Makefile +++ b/secilc/docs/Makefile @@ -58,11 +58,25 @@ $(TMPDIR)/policy.cil: $(TESTDIR)/policy.cil html: $(PANDOC_FILE_LIST) $(TMPDIR)/policy.cil secil.xml mkdir -p $(HTMLDIR) - $(PANDOC) --highlight-style=$(PANDOC_HIGHLIGHT_STYLE) --syntax-definition=secil.xml --standalone --metadata title="CIL Reference Guide" -t html $(PANDOC_FILE_LIST) $(TMPDIR)/policy.cil -o $(HTMLDIR)/$(HTML_OUT) + $(PANDOC) \ + --highlight-style=$(PANDOC_HIGHLIGHT_STYLE) \ + --syntax-definition=secil.xml \ + --standalone \ + --metadata title="CIL Reference Guide" \ + --metadata document-css=false \ + -t html \ + $(PANDOC_FILE_LIST) $(TMPDIR)/policy.cil \ + -o $(HTMLDIR)/$(HTML_OUT) pdf: $(PANDOC_FILE_LIST) $(TMPDIR)/policy.cil secil.xml mkdir -p $(PDFDIR) - $(PANDOC) --highlight-style=$(PANDOC_HIGHLIGHT_STYLE) --syntax-definition=secil.xml --standalone --toc $(PANDOC_FILE_LIST) $(TMPDIR)/policy.cil -o $(PDFDIR)/$(PDF_OUT) + $(PANDOC) \ + --highlight-style=$(PANDOC_HIGHLIGHT_STYLE) \ + --syntax-definition=secil.xml \ + --standalone \ + --toc \ + $(PANDOC_FILE_LIST) $(TMPDIR)/policy.cil \ + -o $(PDFDIR)/$(PDF_OUT) clean: rm -rf $(HTMLDIR) diff --git a/secilc/docs/cil_class_and_permission_statements.md b/secilc/docs/cil_class_and_permission_statements.md index 368e3a4d11a9d553ced19ce98da1f4400dbec4b7..c494f144ee99451ba260343bfd94ec9e172ae5f8 100644 --- a/secilc/docs/cil_class_and_permission_statements.md +++ b/secilc/docs/cil_class_and_permission_statements.md @@ -536,7 +536,7 @@ Defines a named extended permission, which can be used in the [`allowx`](cil_acc class_id -A single previously declared class identifier. +A single previously declared class or classmap identifier. permission diff --git a/secilc/docs/secil.xml b/secilc/docs/secil.xml index b015490d3201b9ccc38eed4ef12174f0f78725ef..38d7b0308c50f8482c0a4b4e2f00423580ecd02a 100644 --- a/secilc/docs/secil.xml +++ b/secilc/docs/secil.xml @@ -2,182 +2,182 @@ - - - allow - allowx - auditallow - auditallowx - block - blockabstract - boolean - booleanif - category - categoryalias - categoryaliasactual - categoryorder - categoryset - class - classcommon - classmap - classmapping - classorder - classpermission - classpermissionset - common - constrain - context - defaultrange - defaultrole - defaulttype - defaultuser - devicetreecon - dontaudit - dontauditx - expandtypeattribute - false - filecon - fsuse - genfscon - handleunknown - ibendportcon - ibpkeycon - ioctl - iomemcon - ioportcon - ipaddr - level - levelrange - mls - mlsconstrain - mlsvalidatetrans - netifcon - neverallow - neverallowx - nodecon - optional - pcidevicecon - perm - permissionx - pirqcon - policycap - portcon - rangetransition - role - roleallow - roleattribute - roleattributeset - rolebounds - roletransition - roletype - selinuxuser - selinuxuserdefault - sensitivity - sensitivityalias - sensitivityaliasactual - sensitivitycategory - sensitivityorder - sid - sidcontext - sidorder - true - tunable - tunableif - type - typealias - typealiasactual - typeattribute - typeattributeset - typebounds - typechange - typemember - typepermissive - typetransition - unordered - user - userattribute - userattributeset - userbounds - userlevel - userprefix - userrange - userrole - validatetrans - + + + + allow + allowx + auditallow + auditallowx + block + blockabstract + boolean + booleanif + category + categoryalias + categoryaliasactual + categoryorder + categoryset + class + classcommon + classmap + classmapping + classorder + classpermission + classpermissionset + common + constrain + context + defaultrange + defaultrole + defaulttype + defaultuser + devicetreecon + dontaudit + dontauditx + expandtypeattribute + false + filecon + fsuse + genfscon + handleunknown + ibendportcon + ibpkeycon + ioctl + iomemcon + ioportcon + ipaddr + level + levelrange + mls + mlsconstrain + mlsvalidatetrans + netifcon + neverallow + neverallowx + nodecon + optional + pcidevicecon + perm + permissionx + pirqcon + policycap + portcon + rangetransition + role + roleallow + roleattribute + roleattributeset + rolebounds + roletransition + roletype + selinuxuser + selinuxuserdefault + sensitivity + sensitivityalias + sensitivityaliasactual + sensitivitycategory + sensitivityorder + sid + sidcontext + sidorder + true + tunable + tunableif + type + typealias + typealiasactual + typeattribute + typeattributeset + typebounds + typechange + typemember + typepermissive + typetransition + unordered + user + userattribute + userattributeset + userbounds + userlevel + userprefix + userrange + userrole + validatetrans + - - blockinherit - call - in - macro - + + blockinherit + call + in + macro + - - and - dom - domby - eq - incomp - neq - not - or - range - xor - + + and + dom + domby + eq + incomp + neq + not + or + range + xor + - - - * - all - dccp - false - h1 - h2 - l1 - l2 - object_r - r1 - r2 - r3 - sctp - self - t1 - t2 - t3 - tcp - true - u1 - u2 - u3 - udp + + + * + all + dccp + false + h1 + h2 + l1 + l2 + object_r + r1 + r2 + r3 + sctp + self + t1 + t2 + t3 + tcp + true + u1 + u2 + u3 + udp - - - + +
class_id
A single previously declared class identifier.
class
A single previously declared class or classmap identifier.
classmap
permission