From 56c629dbebdabc05ecd5a5f907951ff1132a112d Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Fri, 2 Aug 2013 14:42:48 -0400 Subject: [PATCH] Update sepolicy gui code, adding dbus calls - Update Translations --- policycoreutils-rhat.patch | 3042 +----------------------------------- policycoreutils.spec | 9 +- 2 files changed, 16 insertions(+), 3035 deletions(-) diff --git a/policycoreutils-rhat.patch b/policycoreutils-rhat.patch index a17b15b..5dab833 100644 --- a/policycoreutils-rhat.patch +++ b/policycoreutils-rhat.patch @@ -1,2851 +1,3 @@ -diff --git a/checkpolicy/checkmodule.8 b/checkpolicy/checkmodule.8 -index 40f73c5..2a7ab5c 100644 ---- a/checkpolicy/checkmodule.8 -+++ b/checkpolicy/checkmodule.8 -@@ -3,7 +3,7 @@ - checkmodule \- SELinux policy module compiler - .SH SYNOPSIS - .B checkmodule --.I "[-h] [-b] [-m] [-M] [-U handle_unknown ] [-V] [-o output_file] [input_file]" -+.I "[\-h] [\-b] [\-m] [\-M] [\-U handle_unknown ] [\-V] [\-o output_file] [input_file]" - .SH "DESCRIPTION" - This manual page describes the - .BR checkmodule -@@ -12,7 +12,7 @@ command. - .B checkmodule - is a program that checks and compiles a SELinux security policy module - into a binary representation. It can generate either a base policy --module (default) or a non-base policy module (-m option); typically, -+module (default) or a non-base policy module (\-m option); typically, - you would build a non-base policy module to add to an existing module - store that already has a base module provided by the base policy. Use - semodule_package to combine this module with its optional file -@@ -48,7 +48,7 @@ Specify how the kernel should handle unknown classes or permissions (deny, allow - .SH EXAMPLE - .nf - # Build a MLS/MCS-enabled non-base policy module. --$ checkmodule -M -m httpd.te -o httpd.mod -+$ checkmodule \-M \-m httpd.te \-o httpd.mod - .fi - - .SH "SEE ALSO" -diff --git a/checkpolicy/checkpolicy.8 b/checkpolicy/checkpolicy.8 -index 6826938..0086bdc 100644 ---- a/checkpolicy/checkpolicy.8 -+++ b/checkpolicy/checkpolicy.8 -@@ -3,7 +3,7 @@ - checkpolicy \- SELinux policy compiler - .SH SYNOPSIS - .B checkpolicy --.I "[-b] [-d] [-M] [-c policyvers] [-o output_file] [input_file]" -+.I "[\-b] [\-d] [\-M] [\-c policyvers] [\-o output_file] [input_file]" - .br - .SH "DESCRIPTION" - This manual page describes the -@@ -14,7 +14,7 @@ command. - is a program that checks and compiles a SELinux security policy configuration - into a binary representation that can be loaded into the kernel. If no - input file name is specified, checkpolicy will attempt to read from --policy.conf or policy, depending on whether the -b flag is specified. -+policy.conf or policy, depending on whether the \-b flag is specified. - - .SH OPTIONS - .TP -diff --git a/checkpolicy/checkpolicy.c b/checkpolicy/checkpolicy.c -index 544f235..292f568 100644 ---- a/checkpolicy/checkpolicy.c -+++ b/checkpolicy/checkpolicy.c -@@ -402,7 +402,7 @@ int main(int argc, char **argv) - {"binary", no_argument, NULL, 'b'}, - {"debug", no_argument, NULL, 'd'}, - {"version", no_argument, NULL, 'V'}, -- {"handle-unknown", optional_argument, NULL, 'U'}, -+ {"handle-unknown", required_argument, NULL, 'U'}, - {"mls", no_argument, NULL, 'M'}, - {"help", no_argument, NULL, 'h'}, - {NULL, 0, NULL, 0} -diff --git a/checkpolicy/policy_scan.l b/checkpolicy/policy_scan.l -index bba7667..ab046cc 100644 ---- a/checkpolicy/policy_scan.l -+++ b/checkpolicy/policy_scan.l -@@ -240,7 +240,7 @@ HIGH { return(HIGH); } - low | - LOW { return(LOW); } - "/"({alnum}|[_\.\-/])* { return(PATH); } --\"({alnum}|[_\.\-\+\~])+\" { return(FILENAME); } -+\"({alnum}|[_\.\-\+\~\: ])+\" { return(FILENAME); } - {letter}({alnum}|[_\-])*([\.]?({alnum}|[_\-]))* { return(IDENTIFIER); } - {alnum}*{letter}{alnum}* { return(FILESYSTEM); } - {digit}+|0x{hexval}+ { return(NUMBER); } -diff --git a/checkpolicy/test/Makefile b/checkpolicy/test/Makefile -index 0731e89..63b4d24 100644 ---- a/checkpolicy/test/Makefile -+++ b/checkpolicy/test/Makefile -@@ -3,7 +3,7 @@ - # - PREFIX ?= $(DESTDIR)/usr - BINDIR=$(PREFIX)/bin --LIBDIR=$(PREFIX)/lib -+LIBDIR ?= $(PREFIX)/lib - INCLUDEDIR ?= $(PREFIX)/include - - CFLAGS ?= -g -Wall -W -Werror -O2 -pipe -diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h -index a4079aa..0b122af 100644 ---- a/libselinux/include/selinux/selinux.h -+++ b/libselinux/include/selinux/selinux.h -@@ -177,6 +177,7 @@ extern void selinux_set_callback(int type, union selinux_callback cb); - #define SELINUX_WARNING 1 - #define SELINUX_INFO 2 - #define SELINUX_AVC 3 -+#define SELINUX_TRANS_DIR "/var/run/setrans" - - /* Compute an access decision. */ - extern int security_compute_av(const security_context_t scon, -@@ -496,8 +497,15 @@ extern int selinux_getpolicytype(char **policytype); - */ - extern const char *selinux_policy_root(void); - -+/* -+ selinux_set_policy_root sets an alternate policy root directory path under -+ which the compiled policy file and context configuration files exist. -+ */ -+extern int selinux_set_policy_root(const char *rootpath); -+ - /* These functions return the paths to specific files under the - policy root directory. */ -+extern const char *selinux_current_policy_path(void); - extern const char *selinux_binary_policy_path(void); - extern const char *selinux_failsafe_context_path(void); - extern const char *selinux_removable_context_path(void); -diff --git a/libselinux/man/man3/security_compute_av.3 b/libselinux/man/man3/security_compute_av.3 -index c6837fc..de62d26 100644 ---- a/libselinux/man/man3/security_compute_av.3 -+++ b/libselinux/man/man3/security_compute_av.3 -@@ -37,9 +37,9 @@ the SELinux policy database in the kernel - .sp - .BI "int security_compute_user_raw(security_context_t "scon ", const char *" username ", security_context_t **" con ); - .sp --.BI "int security_get_initial_context(const char *" name ", security_context_t " con ); -+.BI "int security_get_initial_context(const char *" name ", security_context_t *" con ); - .sp --.BI "int security_get_initial_context_raw(const char *" name ", security_context_t " con ); -+.BI "int security_get_initial_context_raw(const char *" name ", security_context_t *" con ); - .sp - .BI "int selinux_check_access(const security_context_t " scon ", const security_context_t " tcon ", const char *" class ", const char *" perm ", void *" auditdata); - .sp -diff --git a/libselinux/man/man3/security_disable.3 b/libselinux/man/man3/security_disable.3 -index aeb78da..c75ce0d 100644 ---- a/libselinux/man/man3/security_disable.3 -+++ b/libselinux/man/man3/security_disable.3 -@@ -17,7 +17,7 @@ and then unmounts - This function can only be called at runtime and prior to the initial policy - load. After the initial policy load, the SELinux kernel code cannot be disabled, - but only placed in "permissive" mode by using --.BR setenforce (1). -+.BR security_setenforce(3). - . - .SH "RETURN VALUE" - .BR security_disable () -@@ -27,4 +27,4 @@ returns zero on success or \-1 on error. - This manual page has been written by Guido Trentalancia - . - .SH "SEE ALSO" --.BR selinux (8), " setenforce "(3) -+.BR selinux (8), " setenforce "(8) -diff --git a/libselinux/man/man3/security_load_policy.3 b/libselinux/man/man3/security_load_policy.3 -index c4439bf..af56163 100644 ---- a/libselinux/man/man3/security_load_policy.3 -+++ b/libselinux/man/man3/security_load_policy.3 -@@ -43,7 +43,7 @@ unmounted using a call to - .BR security_disable (3). - Therefore, after the initial policy load, the only operational changes - are those permitted by --.BR setenforce (3) -+.BR security_setenforce (3) - (i.e. eventually setting the framework in permissive mode rather than - in enforcing one). - . -@@ -54,4 +54,4 @@ Returns zero on success or \-1 on error. - This manual page has been written by Guido Trentalancia - . - .SH "SEE ALSO" --.BR selinux "(8), " security_disable "(3), " setenforce "(1) -+.BR selinux "(8), " security_disable "(3), " setenforce "(8) -diff --git a/libselinux/man/man3/selinux_binary_policy_path.3 b/libselinux/man/man3/selinux_binary_policy_path.3 -index ec97dcf..503c52c 100644 ---- a/libselinux/man/man3/selinux_binary_policy_path.3 -+++ b/libselinux/man/man3/selinux_binary_policy_path.3 -@@ -1,6 +1,6 @@ - .TH "selinux_binary_policy_path" "3" "15 November 2004" "dwalsh@redhat.com" "SELinux API Documentation" - .SH "NAME" --selinux_path, selinux_policy_root, selinux_binary_policy_path, -+selinux_path, selinux_policy_root, selinux_binary_policy_path, selinux_current_policy_path, - selinux_failsafe_context_path, selinux_removable_context_path, - selinux_default_context_path, selinux_user_contexts_path, - selinux_file_context_path, selinux_media_context_path, -@@ -17,6 +17,8 @@ directories and files - .sp - .B const char *selinux_binary_policy_path(void); - .sp -+.B const char *selinux_current_policy_path(void); -+.sp - .B const char *selinux_failsafe_context_path(void); - .sp - .B const char *selinux_removable_context_path(void); -@@ -55,6 +57,9 @@ returns the top-level policy directory. - .BR selinux_binary_policy_path () - returns the binary policy file loaded into kernel. - .sp -+.BR selinux_current_policy_path () -+returns the currently loaded policy file from the kernel. -+.sp - .BR selinux_default_type_path () - returns the context file mapping roles to default types. - .sp -diff --git a/libselinux/man/man3/selinux_current_policy_path.3 b/libselinux/man/man3/selinux_current_policy_path.3 -new file mode 100644 -index 0000000..175a611 ---- /dev/null -+++ b/libselinux/man/man3/selinux_current_policy_path.3 -@@ -0,0 +1 @@ -+.so man3/selinux_binary_policy_path.3 -diff --git a/libselinux/man/man3/selinux_policy_root.3 b/libselinux/man/man3/selinux_policy_root.3 -index a6ccf86..63dc901 100644 ---- a/libselinux/man/man3/selinux_policy_root.3 -+++ b/libselinux/man/man3/selinux_policy_root.3 -@@ -1,21 +1,34 @@ - .TH "selinux_policy_root" "3" "25 May 2004" "dwalsh@redhat.com" "SELinux API documentation" - .SH "NAME" - selinux_policy_root \- return the path of the SELinux policy files for this machine -+selinux_set_policy_root \- Set an alternate SELinux root path for the SELinux policy files for this machine. - . - .SH "SYNOPSIS" - .B #include - .sp - .B const char *selinux_policy_root(void); - . -+.sp -+.B int selinux_set_policy_root(const char *policypath); -+. - .SH "DESCRIPTION" - .BR selinux_policy_root () - reads the contents of the - .I /etc/selinux/config - file to determine which policy files should be used for this machine. - . -+.BR selinux_set_policy_root () -+sets up all all policy paths based on the alternate root -+ -+.I /etc/selinux/config -+file to determine which policy files should be used for this machine. -+. - .SH "RETURN VALUE" --On success, returns a directory path containing the SELinux policy files. --On failure, NULL is returned. -+On success, selinux_policy_root returns a directory path containing the SELinux policy files. -+On failure, selinux_policy_root returns NULL. -+ -+On success, selinux_set_policy_root returns 0 on success -1 on failure. -+ - . - .SH "SEE ALSO" - .BR selinux "(8)" -diff --git a/libselinux/man/man3/selinux_set_policy_root.3 b/libselinux/man/man3/selinux_set_policy_root.3 -new file mode 100644 -index 0000000..8077658 ---- /dev/null -+++ b/libselinux/man/man3/selinux_set_policy_root.3 -@@ -0,0 +1 @@ -+.so man3/selinux_policy_root.3 -diff --git a/libselinux/man/man5/secolor.conf.5 b/libselinux/man/man5/secolor.conf.5 -deleted file mode 100644 -index b834577..0000000 ---- a/libselinux/man/man5/secolor.conf.5 -+++ /dev/null -@@ -1,178 +0,0 @@ --.TH "secolor.conf" "5" "08 April 2011" "SELinux API documentation" --.SH "NAME" --secolor.conf \- The SELinux color configuration file --. --.SH "DESCRIPTION" --This optional file controls the color to be associated to the context components associated to the --.I raw --context passed by --.BR selinux_raw_context_to_color "(3)," --when context related information is to be displayed in color by an SELinux-aware application. --.sp --.BR selinux_raw_context_to_color "(3)" --obtains this color information from the active policy --.B secolor.conf --file as returned by --.BR selinux_colors_path "(3)." --. --.SH "FILE FORMAT" --The file format is as follows: --.RS --.B color --.I color_name --.BI "= #"color_mask --.br --[...] --.sp --.I context_component string --.B = --.I fg_color_name bg_color_name --.br --[...] --.sp --.RE -- --Where: --.br --.B color --.RS --The color keyword. Each color entry is on a new line. --.RE --.I color_name --.RS --A single word name for the color (e.g. red). --.RE --.I color_mask --.RS --A color mask starting with a hash (#) that describes the hexadecimal RGB colors with black being #000000 and white being #ffffff. --.RE --.I context_component --.RS --The context component name that must be one of the following: --.br --.RS --user, role, type or range --.RE --Each --.IR context_component " " string " ..." --entry is on a new line. --.RE --.I string --.RS --This is the --.I context_component --string that will be matched with the --.I raw --context component passed by --.BR selinux_raw_context_to_color "(3)." --.br --A wildcard '*' may be used to match any undefined string for the user, role and type --.I context_component --entries only. --.RE -- --.I fg_color_name --.RS --The color_name string that will be used as the foreground color. --A --.I color_mask --may also be used. --.RE --.I bg_color_name --.RS --The color_name string that will be used as the background color. --A --.I color_mask --may also be used. --.RE --. --.SH "EXAMPLES" --Example 1 entries are: --.RS --color black = #000000 --.br --color green = #008000 --.br --color yellow = #ffff00 --.br --color blue = #0000ff --.br --color white = #ffffff --.br --color red = #ff0000 --.br --color orange = #ffa500 --.br --color tan = #D2B48C --.sp --user * = black white --.br --role * = white black --.br --type * = tan orange --.br --range s0\-s0:c0.c1023 = black green --.br --range s1\-s1:c0.c1023 = white green --.br --range s3\-s3:c0.c1023 = black tan --.br --range s5\-s5:c0.c1023 = white blue --.br --range s7\-s7:c0.c1023 = black red --.br --range s9\-s9:c0.c1023 = black orange --.br --range s15:c0.c1023 = black yellow --.RE -- --.sp --Example 2 entries are: --.RS --color black = #000000 --.br --color green = #008000 --.br --color yellow = #ffff00 --.br --color blue = #0000ff --.br --color white = #ffffff --.br --color red = #ff0000 --.br --color orange = #ffa500 --.br --color tan = #d2b48c --.sp --user unconfined_u = #ff0000 green --.br --role unconfined_r = red #ffffff --.br --type unconfined_t = red orange --.br --user user_u = black green --.br --role user_r = white black --.br --type user_t = tan red --.br --user xguest_u = black yellow --.br --role xguest_r = black red --.br --type xguest_t = black green --.br --user sysadm_u = white black --.br --range s0:c0.c1023 = black white --.br --user * = black white --.br --role * = black white --.br --type * = black white --.RE --. --.SH "SEE ALSO" --.BR selinux "(8), " selinux_raw_context_to_color "(3), " selinux_colors_path "(3)" -diff --git a/libselinux/man/man8/getenforce.8 b/libselinux/man/man8/getenforce.8 -index 906279f..e0924d8 100644 ---- a/libselinux/man/man8/getenforce.8 -+++ b/libselinux/man/man8/getenforce.8 -@@ -1,4 +1,4 @@ --.TH "getenforce" "1" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation" -+.TH "getenforce" "8" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation" - .SH "NAME" - getenforce \- get the current mode of SELinux - . -diff --git a/libselinux/man/man8/matchpathcon.8 b/libselinux/man/man8/matchpathcon.8 -index 368991f..5d60789 100644 ---- a/libselinux/man/man8/matchpathcon.8 -+++ b/libselinux/man/man8/matchpathcon.8 -@@ -13,6 +13,8 @@ matchpathcon \- get the default SELinux security context for the specified path - .IR file_contexts_file ] - .RB [ \-p - .IR prefix ] -+.RB [ \-P -+.IR policy_root_path ] - .I filepath... - . - .SH "DESCRIPTION" -@@ -46,6 +48,9 @@ Use alternate file_context file - .BI \-p " prefix" - Use prefix to speed translations - .TP -+.BI \-P " policy_root_path" -+Use alternate policy root path -+.TP - .B \-V - Verify file context on disk matches defaults - . -diff --git a/libselinux/man/man8/sefcontext_compile.8 b/libselinux/man/man8/sefcontext_compile.8 -new file mode 100644 -index 0000000..c37ed4a ---- /dev/null -+++ b/libselinux/man/man8/sefcontext_compile.8 -@@ -0,0 +1,19 @@ -+.TH "sefcontext_compile" "8" "27 Jun 2013" "dwalsh@redhat.com" "SELinux Command Line documentation" -+.SH "NAME" -+sefcontext_compile \- compile file context regular expression files -+. -+.SH "SYNOPSIS" -+.B sefcontext_compile inputfile -+. -+.SH "DESCRIPTION" -+sefcontext_compile is used libsemanage to compile file context regular expressions into prce format. sefcontext_compile writes the compiled prce file with the .bin suffix appended "inputfile".bin. This compiled file is used by libselinux file labeling functions. -+ -+.SH "EXAMPLE" -+sefcontext_compile /etc/selinux/targeted/contexts/files/file_contexts -+. -+.SH AUTHOR -+Dan Walsh, -+. -+.SH "SEE ALSO" -+.BR selinux (8), -+.BR semanage (8), -diff --git a/libselinux/man/man8/selinux.8 b/libselinux/man/man8/selinux.8 -index a328866..50868e4 100644 ---- a/libselinux/man/man8/selinux.8 -+++ b/libselinux/man/man8/selinux.8 -@@ -37,20 +37,22 @@ The - configuration file also controls what policy - is active on the system. SELinux allows for multiple policies to be - installed on the system, but only one policy may be active at any --given time. At present, two kinds of SELinux policy exist: targeted --and strict. The targeted policy is designed as a policy where most --processes operate without restrictions, and only specific services are -+given time. At present, multiple kinds of SELinux policy exist: targeted, -+mls for example. The targeted policy is designed as a policy where most -+user processes operate without restrictions, and only specific services are - placed into distinct security domains that are confined by the policy. - For example, the user would run in a completely unconfined domain - while the named daemon or apache daemon would run in a specific domain --tailored to its operation. The strict policy is designed as a policy --where all processes are partitioned into fine-grained security domains --and confined by policy. It is anticipated in the future that other --policies will be created (Multi-Level Security for example). You can -+tailored to its operation. The MLS (Multi-Level Security) policy is designed -+as a policy where all processes are partitioned into fine-grained security -+domains and confined by policy. MLS also supports the Bell And LaPadula model, where processes are not only confined by the type but also the level of the data. -+ -+You can - define which policy you will run by setting the - .B SELINUXTYPE - environment variable within - .IR /etc/selinux/config . -+You must reboot and possibly relabel if you change the policy type to have it take effect on the system. - The corresponding - policy configuration for each such policy must be installed in the - .I /etc/selinux/{SELINUXTYPE}/ -@@ -58,7 +60,7 @@ directories. - - A given SELinux policy can be customized further based on a set of - compile-time tunable options and a set of runtime policy booleans. --.B \%system\-config\-securitylevel -+.B \%system\-config\-selinux - allows customization of these booleans and tunables. - - Many domains that are protected by SELinux also include SELinux man pages explaining how to customize their policy. -@@ -86,11 +88,13 @@ This manual page was written by Dan Walsh . - .nh - .BR booleans (8), - .BR setsebool (8), --.BR selinuxenabled (8), -+.BR sepolicy (8), -+.BR system-config-selinux (8), - .BR togglesebool (8), - .BR restorecon (8), -+.BR fixfiles (8), - .BR setfiles (8), --.BR semange (8), -+.BR semanage (8), - .BR sepolicy(8) - - Every confined service on the system has a man page in the following format: -diff --git a/libselinux/man/man8/selinuxenabled.8 b/libselinux/man/man8/selinuxenabled.8 -index e0b5201..ac20587 100644 ---- a/libselinux/man/man8/selinuxenabled.8 -+++ b/libselinux/man/man8/selinuxenabled.8 -@@ -1,4 +1,4 @@ --.TH "selinuxenabled" "1" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation" -+.TH "selinuxenabled" "8" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation" - .SH "NAME" - selinuxenabled \- tool to be used within shell scripts to determine if selinux is enabled - . -diff --git a/libselinux/man/man8/selinuxexeccon.8 b/libselinux/man/man8/selinuxexeccon.8 -index 765cf8c..30c20ed 100644 ---- a/libselinux/man/man8/selinuxexeccon.8 -+++ b/libselinux/man/man8/selinuxexeccon.8 -@@ -1,4 +1,4 @@ --.TH "selinuxexeccon" "1" "14 May 2011" "dwalsh@redhat.com" "SELinux Command Line documentation" -+.TH "selinuxexeccon" "8" "14 May 2011" "dwalsh@redhat.com" "SELinux Command Line documentation" - .SH "NAME" - selinuxexeccon \- report SELinux context used for this executable - . -diff --git a/libselinux/man/man8/setenforce.8 b/libselinux/man/man8/setenforce.8 -index b038da0..8a24f1c 100644 ---- a/libselinux/man/man8/setenforce.8 -+++ b/libselinux/man/man8/setenforce.8 -@@ -1,4 +1,4 @@ --.TH "setenforce" "1" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation" -+.TH "setenforce" "8" "7 April 2004" "dwalsh@redhat.com" "SELinux Command Line documentation" - .SH "NAME" - setenforce \- modify the mode SELinux is running in - . -diff --git a/libselinux/man/man8/togglesebool.8 b/libselinux/man/man8/togglesebool.8 -index 948aff1..598dc94 100644 ---- a/libselinux/man/man8/togglesebool.8 -+++ b/libselinux/man/man8/togglesebool.8 -@@ -1,4 +1,4 @@ --.TH "togglesebool" "1" "26 Oct 2004" "sgrubb@redhat.com" "SELinux Command Line documentation" -+.TH "togglesebool" "8" "26 Oct 2004" "sgrubb@redhat.com" "SELinux Command Line documentation" - .SH "NAME" - togglesebool \- flip the current value of a SELinux boolean - . -diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile -index c4f5d4c..8f557a1 100644 ---- a/libselinux/src/Makefile -+++ b/libselinux/src/Makefile -@@ -18,9 +18,7 @@ RUBYLIBVER ?= $(shell $(RUBY) -e 'print RUBY_VERSION.split(".")[0..1].join(".")' - RUBYPLATFORM ?= $(shell $(RUBY) -e 'print RUBY_PLATFORM') - RUBYINC ?= $(shell pkg-config --cflags ruby) - RUBYINSTALL ?= $(LIBDIR)/ruby/site_ruby/$(RUBYLIBVER)/$(RUBYPLATFORM) --LIBBASE=$(shell basename $(LIBDIR)) -- --LDFLAGS ?= -lpcre -lpthread -+LIBBASE ?= $(shell basename $(LIBDIR)) - - VERSION = $(shell cat ../VERSION) - LIBVERSION = 1 -@@ -116,7 +114,7 @@ $(LIBA): $(OBJS) - $(RANLIB) $@ - - $(LIBSO): $(LOBJS) -- $(CC) $(CFLAGS) -shared -o $@ $^ -ldl $(LDFLAGS) -L$(LIBDIR) -Wl,-soname,$(LIBSO),-z,defs,-z,relro -+ $(CC) $(CFLAGS) -shared -o $@ $^ -lpcre -lpthread -ldl $(LDFLAGS) -L$(LIBDIR) -Wl,-soname,$(LIBSO),-z,defs,-z,relro - ln -sf $@ $(TARGET) - - $(LIBPC): $(LIBPC).in ../VERSION -diff --git a/libselinux/src/audit2why.c b/libselinux/src/audit2why.c -index ffe381b..560bc25 100644 ---- a/libselinux/src/audit2why.c -+++ b/libselinux/src/audit2why.c -@@ -210,27 +210,12 @@ static int __policy_init(const char *init_path) - return 1; - } - } else { -- vers = sepol_policy_kern_vers_max(); -- if (vers < 0) { -- snprintf(errormsg, sizeof(errormsg), -- "Could not get policy version: %s\n", -- strerror(errno)); -- PyErr_SetString( PyExc_ValueError, errormsg); -- return 1; -- } -- snprintf(path, PATH_MAX, "%s.%d", -- selinux_binary_policy_path(), vers); -- fp = fopen(path, "r"); -- while (!fp && errno == ENOENT && --vers) { -- snprintf(path, PATH_MAX, "%s.%d", -- selinux_binary_policy_path(), vers); -- fp = fopen(path, "r"); -- } -+ fp = fopen(selinux_current_policy_path(), "r"); - if (!fp) { - snprintf(errormsg, sizeof(errormsg), -- "unable to open %s.%d: %s\n", -- selinux_binary_policy_path(), -- security_policyvers(), strerror(errno)); -+ "unable to open %s: %s\n", -+ selinux_current_policy_path(), -+ strerror(errno)); - PyErr_SetString( PyExc_ValueError, errormsg); - return 1; - } -@@ -310,10 +295,12 @@ static PyObject *init(PyObject *self __attribute__((unused)), PyObject *args) { - } - - #define RETURN(X) \ -- PyTuple_SetItem(result, 0, Py_BuildValue("i", X)); \ -- return result; -+ { \ -+ return Py_BuildValue("iO", (X), Py_None); \ -+ } - - static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args) { -+ char *reason_buf = NULL; - security_context_t scon; - security_context_t tcon; - char *tclassstr; -@@ -328,10 +315,6 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args - struct sepol_av_decision avd; - int rc; - int i=0; -- PyObject *result = PyTuple_New(2); -- if (!result) return NULL; -- Py_INCREF(Py_None); -- PyTuple_SetItem(result, 1, Py_None); - - if (!PyArg_ParseTuple(args,(char *)"sssO!:audit2why",&scon,&tcon,&tclassstr,&PyList_Type, &listObj)) - return NULL; -@@ -342,22 +325,21 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args - /* should raise an error here. */ - if (numlines < 0) return NULL; /* Not a list */ - -- if (!avc) { -+ if (!avc) - RETURN(NOPOLICY) -- } - - rc = sepol_context_to_sid(scon, strlen(scon) + 1, &ssid); -- if (rc < 0) { -+ if (rc < 0) - RETURN(BADSCON) -- } -+ - rc = sepol_context_to_sid(tcon, strlen(tcon) + 1, &tsid); -- if (rc < 0) { -+ if (rc < 0) - RETURN(BADTCON) -- } -+ - tclass = string_to_security_class(tclassstr); -- if (!tclass) { -+ if (!tclass) - RETURN(BADTCLASS) -- } -+ - /* Convert the permission list to an AV. */ - av = 0; - -@@ -377,21 +359,20 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args - #endif - - perm = string_to_av_perm(tclass, permstr); -- if (!perm) { -+ if (!perm) - RETURN(BADPERM) -- } -+ - av |= perm; - } - - /* Reproduce the computation. */ -- rc = sepol_compute_av_reason(ssid, tsid, tclass, av, &avd, &reason); -- if (rc < 0) { -+ rc = sepol_compute_av_reason_buffer(ssid, tsid, tclass, av, &avd, &reason, &reason_buf, 0); -+ if (rc < 0) - RETURN(BADCOMPUTE) -- } - -- if (!reason) { -+ if (!reason) - RETURN(ALLOW) -- } -+ - if (reason & SEPOL_COMPUTEAV_TE) { - avc->ssid = ssid; - avc->tsid = tsid; -@@ -404,28 +385,34 @@ static PyObject *analyze(PyObject *self __attribute__((unused)) , PyObject *args - RETURN(TERULE) - } - } else { -- PyTuple_SetItem(result, 0, Py_BuildValue("i", BOOLEAN)); -+ PyObject *outboollist; - struct boolean_t *b = bools; - int len=0; - while (b->name) { - len++; b++; - } - b = bools; -- PyObject *outboollist = PyTuple_New(len); -+ outboollist = PyList_New(len); - len=0; - while(b->name) { -- PyObject *bool = Py_BuildValue("(si)", b->name, b->active); -- PyTuple_SetItem(outboollist, len++, bool); -+ PyObject *bool_ = Py_BuildValue("(si)", b->name, b->active); -+ PyList_SetItem(outboollist, len++, bool_); - b++; - } - free(bools); -- PyTuple_SetItem(result, 1, outboollist); -- return result; -+ /* 'N' steals the reference to outboollist */ -+ return Py_BuildValue("iN", BOOLEAN, outboollist); - } - } - - if (reason & SEPOL_COMPUTEAV_CONS) { -- RETURN(CONSTRAINT); -+ if (reason_buf) { -+ PyObject *result = NULL; -+ result = Py_BuildValue("is", CONSTRAINT, reason_buf); -+ free(reason_buf); -+ return result; -+ } -+ RETURN(CONSTRAINT) - } - - if (reason & SEPOL_COMPUTEAV_RBAC) -diff --git a/libselinux/src/avc.c b/libselinux/src/avc.c -index 802a07f..6ff83a7 100644 ---- a/libselinux/src/avc.c -+++ b/libselinux/src/avc.c -@@ -827,6 +827,7 @@ int avc_has_perm(security_id_t ssid, security_id_t tsid, - errsave = errno; - avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata); - errno = errsave; -+ if (!avc_enforcing) return 0; - return rc; - } - -diff --git a/libselinux/src/get_context_list.c b/libselinux/src/get_context_list.c -index b9e8002..355730a 100644 ---- a/libselinux/src/get_context_list.c -+++ b/libselinux/src/get_context_list.c -@@ -426,7 +426,7 @@ int get_ordered_context_list(const char *user, - /* Initialize ordering array. */ - ordering = malloc(nreach * sizeof(unsigned int)); - if (!ordering) -- goto oom_order; -+ goto failsafe; - for (i = 0; i < nreach; i++) - ordering[i] = nreach; - -@@ -435,7 +435,7 @@ int get_ordered_context_list(const char *user, - fname_len = strlen(user_contexts_path) + strlen(user) + 2; - fname = malloc(fname_len); - if (!fname) -- goto oom_order; -+ goto failsafe; - snprintf(fname, fname_len, "%s%s", user_contexts_path, user); - fp = fopen(fname, "r"); - if (fp) { -@@ -465,31 +465,28 @@ int get_ordered_context_list(const char *user, - } - } - -+ if (!nordered) -+ goto failsafe; -+ - /* Apply the ordering. */ -- if (nordered) { -- co = malloc(nreach * sizeof(struct context_order)); -- if (!co) -- goto oom_order; -- for (i = 0; i < nreach; i++) { -- co[i].con = reachable[i]; -- co[i].order = ordering[i]; -- } -- qsort(co, nreach, sizeof(struct context_order), order_compare); -- for (i = 0; i < nreach; i++) -- reachable[i] = co[i].con; -- free(co); -+ co = malloc(nreach * sizeof(struct context_order)); -+ if (!co) -+ goto failsafe; -+ for (i = 0; i < nreach; i++) { -+ co[i].con = reachable[i]; -+ co[i].order = ordering[i]; - } -+ qsort(co, nreach, sizeof(struct context_order), order_compare); -+ for (i = 0; i < nreach; i++) -+ reachable[i] = co[i].con; -+ free(co); - -- /* Return the ordered list. -- If we successfully ordered it, then only report the ordered entries -- to the caller. Otherwise, fall back to the entire reachable list. */ -- if (nordered && nordered < nreach) { -+ /* Only report the ordered entries to the caller. */ -+ if (nordered < nreach) { - for (i = nordered; i < nreach; i++) - free(reachable[i]); - reachable[nordered] = NULL; - rc = nordered; -- } else { -- rc = nreach; - } - - out: -@@ -523,14 +520,6 @@ int get_ordered_context_list(const char *user, - } - rc = 1; /* one context in the list */ - goto out; -- -- oom_order: -- /* Unable to order context list due to OOM condition. -- Fall back to unordered reachable context list. */ -- fprintf(stderr, "%s: out of memory, unable to order list\n", -- __FUNCTION__); -- rc = nreach; -- goto out; - } - - hidden_def(get_ordered_context_list) -diff --git a/libselinux/src/label.c b/libselinux/src/label.c -index 11f6e96..f5cb52a 100644 ---- a/libselinux/src/label.c -+++ b/libselinux/src/label.c -@@ -43,12 +43,18 @@ static void selabel_subs_fini(struct selabel_sub *ptr) - static char *selabel_sub(struct selabel_sub *ptr, const char *src) - { - char *dst = NULL; -+ int len; - - while (ptr) { - if (strncmp(src, ptr->src, ptr->slen) == 0 ) { - if (src[ptr->slen] == '/' || - src[ptr->slen] == 0) { -- if (asprintf(&dst, "%s%s", ptr->dst, &src[ptr->slen]) < 0) -+ if ((src[ptr->slen] == '/') && -+ (strcmp(ptr->dst, "/") == 0)) -+ len = ptr->slen + 1; -+ else -+ len = ptr->slen; -+ if (asprintf(&dst, "%s%s", ptr->dst, &src[len]) < 0) - return NULL; - return dst; - } -diff --git a/libselinux/src/label_file.c b/libselinux/src/label_file.c -index 5f697f3..9b0d6b0 100644 ---- a/libselinux/src/label_file.c -+++ b/libselinux/src/label_file.c -@@ -649,6 +649,8 @@ static struct selabel_lookup_rec *lookup(struct selabel_handle *rec, - break; - } else if (rc == PCRE_ERROR_NOMATCH) - continue; -+ -+ errno = ENOENT; - /* else it's an error */ - goto finish; - } -@@ -660,6 +662,7 @@ static struct selabel_lookup_rec *lookup(struct selabel_handle *rec, - goto finish; - } - -+ errno = 0; - ret = &spec_arr[i].lr; - - finish: -diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c -index 2d7369e..2a00807 100644 ---- a/libselinux/src/matchpathcon.c -+++ b/libselinux/src/matchpathcon.c -@@ -2,6 +2,7 @@ - #include - #include - #include -+#include - #include "selinux_internal.h" - #include "label_internal.h" - #include "callbacks.h" -@@ -62,7 +63,7 @@ static void - { - va_list ap; - va_start(ap, fmt); -- vfprintf(stderr, fmt, ap); -+ vsyslog(LOG_ERR, fmt, ap); - va_end(ap); - } - -diff --git a/libselinux/src/procattr.c b/libselinux/src/procattr.c -index 6c5b45a..f6b896e 100644 ---- a/libselinux/src/procattr.c -+++ b/libselinux/src/procattr.c -@@ -9,13 +9,15 @@ - #include "selinux_internal.h" - #include "policy.h" - -+#define UNSET (const security_context_t) -1 -+ - static __thread pid_t cpid; - static __thread pid_t tid; --static __thread security_context_t prev_current; --static __thread security_context_t prev_exec; --static __thread security_context_t prev_fscreate; --static __thread security_context_t prev_keycreate; --static __thread security_context_t prev_sockcreate; -+static __thread security_context_t prev_current = UNSET; -+static __thread security_context_t prev_exec = UNSET; -+static __thread security_context_t prev_fscreate = UNSET; -+static __thread security_context_t prev_keycreate = UNSET; -+static __thread security_context_t prev_sockcreate = UNSET; - - static pthread_once_t once = PTHREAD_ONCE_INIT; - static pthread_key_t destructor_key; -@@ -29,11 +31,16 @@ static pid_t gettid(void) - - static void procattr_thread_destructor(void __attribute__((unused)) *unused) - { -- free(prev_current); -- free(prev_exec); -- free(prev_fscreate); -- free(prev_keycreate); -- free(prev_sockcreate); -+ if (prev_current != UNSET) -+ free(prev_current); -+ if (prev_exec != UNSET) -+ free(prev_exec); -+ if (prev_fscreate != UNSET) -+ free(prev_fscreate); -+ if (prev_keycreate != UNSET) -+ free(prev_keycreate); -+ if (prev_sockcreate != UNSET) -+ free(prev_sockcreate); - } - - static void free_procattr(void) -@@ -41,7 +48,7 @@ static void free_procattr(void) - procattr_thread_destructor(NULL); - tid = 0; - cpid = getpid(); -- prev_current = prev_exec = prev_fscreate = prev_keycreate = prev_sockcreate = NULL; -+ prev_current = prev_exec = prev_fscreate = prev_keycreate = prev_sockcreate = UNSET; - } - - void __attribute__((destructor)) procattr_destructor(void); -@@ -131,7 +138,7 @@ static int getprocattrcon_raw(security_context_t * context, - return -1; - }; - -- if (prev_context) { -+ if (prev_context && prev_context != UNSET) { - *context = strdup(prev_context); - if (!(*context)) { - return -1; -@@ -230,7 +237,8 @@ static int setprocattrcon_raw(security_context_t context, - - if (!context && !*prev_context) - return 0; -- if (context && *prev_context && !strcmp(context, *prev_context)) -+ if (context && *prev_context && *prev_context != UNSET -+ && !strcmp(context, *prev_context)) - return 0; - - fd = openattr(pid, attr, O_RDWR); -@@ -257,6 +265,8 @@ out: - free(context); - return -1; - } else { -+ if (*prev_context != UNSET) -+ free(*prev_context); - *prev_context = context; - return 0; - } -diff --git a/libselinux/src/selinux_config.c b/libselinux/src/selinux_config.c -index 296f357..9aee32f 100644 ---- a/libselinux/src/selinux_config.c -+++ b/libselinux/src/selinux_config.c -@@ -8,6 +8,8 @@ - #include - #include - #include -+#include -+#include "policy.h" - #include "selinux_internal.h" - #include "get_default_type_internal.h" - -@@ -138,6 +140,13 @@ int selinux_getpolicytype(char **type) - - hidden_def(selinux_getpolicytype) - -+static int setpolicytype(const char *type) -+{ -+ free(selinux_policytype); -+ selinux_policytype = strdup(type); -+ return selinux_policytype ? 0 : -1; -+} -+ - static char *selinux_policyroot = NULL; - static const char *selinux_rootpath = SELINUXDIR; - -@@ -261,6 +270,37 @@ const char *selinux_policy_root(void) - return selinux_policyroot; - } - -+int selinux_set_policy_root(const char *path) -+{ -+ int i; -+ char *policy_type = strrchr(path, '/'); -+ if (!policy_type) { -+ errno = EINVAL; -+ return -1; -+ } -+ policy_type++; -+ -+ fini_selinuxmnt(); -+ fini_selinux_policyroot(); -+ -+ selinux_policyroot = strdup(path); -+ if (! selinux_policyroot) -+ return -1; -+ -+ if (setpolicytype(policy_type) != 0) -+ return -1; -+ -+ for (i = 0; i < NEL; i++) -+ if (asprintf(&file_paths[i], "%s%s", -+ selinux_policyroot, -+ file_path_suffixes_data.str + -+ file_path_suffixes_idx[i]) -+ == -1) -+ return -1; -+ -+ return 0; -+} -+ - const char *selinux_path(void) - { - return selinux_rootpath; -@@ -303,6 +343,31 @@ const char *selinux_binary_policy_path(void) - - hidden_def(selinux_binary_policy_path) - -+const char *selinux_current_policy_path(void) -+{ -+ int rc = 0; -+ int vers = 0; -+ static char policy_path[PATH_MAX]; -+ -+ if (selinux_mnt) { -+ snprintf(policy_path, sizeof(policy_path), "%s/policy", selinux_mnt); -+ if (access(policy_path, F_OK) == 0 ) { -+ return policy_path; -+ } -+ } -+ vers = security_policyvers(); -+ do { -+ /* Check prior versions to see if old policy is available */ -+ snprintf(policy_path, sizeof(policy_path), "%s.%d", -+ selinux_binary_policy_path(), vers); -+ } while ((rc = access(policy_path, F_OK)) && --vers > 0); -+ -+ if (rc) return NULL; -+ return policy_path; -+} -+ -+hidden_def(selinux_current_policy_path) -+ - const char *selinux_file_context_path(void) - { - return get_path(FILE_CONTEXTS); -diff --git a/libselinux/src/selinux_internal.h b/libselinux/src/selinux_internal.h -index 2c7c85c..4a4aebc 100644 ---- a/libselinux/src/selinux_internal.h -+++ b/libselinux/src/selinux_internal.h -@@ -60,6 +60,7 @@ hidden_proto(selinux_mkload_policy) - hidden_proto(security_setenforce) - hidden_proto(security_deny_unknown) - hidden_proto(selinux_boolean_sub) -+ hidden_proto(selinux_current_policy_path) - hidden_proto(selinux_binary_policy_path) - hidden_proto(selinux_booleans_subs_path) - hidden_proto(selinux_default_context_path) -diff --git a/libselinux/src/selinuxswig_python.i b/libselinux/src/selinuxswig_python.i -index 359bd02..0ab0bae 100644 ---- a/libselinux/src/selinuxswig_python.i -+++ b/libselinux/src/selinuxswig_python.i -@@ -74,6 +74,10 @@ def install(src, dest): - $1 = &temp; - } - -+%typemap(in, numinputs=0) void *(char *temp=NULL) { -+ $1 = temp; -+} -+ - /* Makes security_compute_user() return a Python list of contexts */ - %typemap(argout) (security_context_t **con) { - PyObject* plist; -diff --git a/libselinux/src/setrans_internal.h b/libselinux/src/setrans_internal.h -index a801ee8..b3bdca2 100644 ---- a/libselinux/src/setrans_internal.h -+++ b/libselinux/src/setrans_internal.h -@@ -1,6 +1,7 @@ - /* Author: Trusted Computer Solutions, Inc. */ -+#include - --#define SETRANS_UNIX_SOCKET "/var/run/setrans/.setrans-unix" -+#define SETRANS_UNIX_SOCKET SELINUX_TRANS_DIR "/.setrans-unix" - - #define RAW_TO_TRANS_CONTEXT 2 - #define TRANS_TO_RAW_CONTEXT 3 -diff --git a/libselinux/utils/matchpathcon.c b/libselinux/utils/matchpathcon.c -index dd5aaa3..9d3ff3a 100644 ---- a/libselinux/utils/matchpathcon.c -+++ b/libselinux/utils/matchpathcon.c -@@ -12,11 +12,10 @@ - #include - #include - -- - static void usage(const char *progname) - { - fprintf(stderr, -- "usage: %s [-N] [-n] [-f file_contexts] [-p prefix] [-Vq] path...\n", -+ "usage: %s [-N] [-n] [-f file_contexts] [ -P policy_root_path ] [-p prefix] [-Vq] path...\n", - progname); - exit(1); - } -@@ -78,7 +77,7 @@ int main(int argc, char **argv) - if (argc < 2) - usage(argv[0]); - -- while ((opt = getopt(argc, argv, "m:Nnf:p:Vq")) > 0) { -+ while ((opt = getopt(argc, argv, "m:Nnf:P:p:Vq")) > 0) { - switch (opt) { - case 'n': - header = 0; -@@ -113,6 +112,15 @@ int main(int argc, char **argv) - exit(1); - } - break; -+ case 'P': -+ if (selinux_set_policy_root(optarg) < 0 ) { -+ fprintf(stderr, -+ "Error setting policy root %s: %s\n", -+ optarg, -+ errno ? strerror(errno) : "invalid"); -+ exit(1); -+ } -+ break; - case 'p': - if (init) { - fprintf(stderr, -diff --git a/libselinux/utils/sefcontext_compile.c b/libselinux/utils/sefcontext_compile.c -index 6f79dd6..e019a07 100644 ---- a/libselinux/utils/sefcontext_compile.c -+++ b/libselinux/utils/sefcontext_compile.c -@@ -145,7 +145,7 @@ static int process_file(struct saved_data *data, const char *filename) - * u32 - data length of the pcre regex study daya - * char - a buffer holding the raw pcre regex study data - */ --static int write_binary_file(struct saved_data *data, char *filename) -+static int write_binary_file(struct saved_data *data, int fd) - { - struct spec *specs = data->spec_arr; - FILE *bin_file; -@@ -155,7 +155,7 @@ static int write_binary_file(struct saved_data *data, char *filename) - uint32_t i; - int rc; - -- bin_file = fopen(filename, "w"); -+ bin_file = fdopen(fd, "w"); - if (!bin_file) { - perror("fopen output_file"); - exit(EXIT_FAILURE); -@@ -321,7 +321,9 @@ int main(int argc, char *argv[]) - const char *path; - char stack_path[PATH_MAX + 1]; - int rc; -- -+ char *tmp= NULL; -+ int fd; -+ - if (argc != 2) { - fprintf(stderr, "usage: %s input_file\n", argv[0]); - exit(EXIT_FAILURE); -@@ -342,13 +344,29 @@ int main(int argc, char *argv[]) - rc = snprintf(stack_path, sizeof(stack_path), "%s.bin", path); - if (rc < 0 || rc >= sizeof(stack_path)) - return rc; -- rc = write_binary_file(&data, stack_path); -+ -+ if (asprintf(&tmp, "%sXXXXXX", stack_path) < 0) -+ return -1; -+ -+ fd = mkstemp(tmp); -+ if (fd < 0) -+ goto err; -+ -+ rc = write_binary_file(&data, fd); -+ - if (rc < 0) -- return rc; -+ goto err; - -+ rename(tmp, stack_path); - rc = free_specs(&data); - if (rc < 0) -- return rc; -+ goto err; - -- return 0; -+ rc = 0; -+out: -+ free(tmp); -+ return rc; -+err: -+ rc = -1; -+ goto out; - } -diff --git a/libsemanage/man/man3/semanage_bool_set_active.3 b/libsemanage/man/man3/semanage_bool_set_active.3 -index 026e29d..d868fe8 100644 ---- a/libsemanage/man/man3/semanage_bool_set_active.3 -+++ b/libsemanage/man/man3/semanage_bool_set_active.3 -@@ -40,7 +40,7 @@ This function requires an semanage connection to be established (see - ). - - .SH "RETURN VALUE" --In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error. -+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. - Otherwise 0 is returned. - - .SH "SEE ALSO" -diff --git a/libsemanage/man/man3/semanage_count.3 b/libsemanage/man/man3/semanage_count.3 -index b131cbe..b865a21 100644 ---- a/libsemanage/man/man3/semanage_count.3 -+++ b/libsemanage/man/man3/semanage_count.3 -@@ -33,7 +33,7 @@ This function requires an semanage connection to be established (see - ) - - .SH "RETURN VALUE" --In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error. -+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. - Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other semanage object read calls until the next commit. - - .SH "SEE ALSO" -diff --git a/libsemanage/man/man3/semanage_del.3 b/libsemanage/man/man3/semanage_del.3 -index 5b11ce3..4dd0a77 100644 ---- a/libsemanage/man/man3/semanage_del.3 -+++ b/libsemanage/man/man3/semanage_del.3 -@@ -40,7 +40,7 @@ This function requires an semanage connection to be established (see - ). - - .SH "RETURN VALUE" --In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error. -+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. - Otherwise 0 is returned. - - .SH "SEE ALSO" -diff --git a/libsemanage/man/man3/semanage_exists.3 b/libsemanage/man/man3/semanage_exists.3 -index da401c2..6d68c76 100644 ---- a/libsemanage/man/man3/semanage_exists.3 -+++ b/libsemanage/man/man3/semanage_exists.3 -@@ -38,7 +38,7 @@ This function requires an semanage connection to be established (see - ) - - .SH "RETURN VALUE" --In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error. -+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. - Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other read calls to the semanage database until the next commit. - - .SH "SEE ALSO" -diff --git a/libsemanage/man/man3/semanage_iterate.3 b/libsemanage/man/man3/semanage_iterate.3 -index 8773800..1528164 100644 ---- a/libsemanage/man/man3/semanage_iterate.3 -+++ b/libsemanage/man/man3/semanage_iterate.3 -@@ -31,7 +31,7 @@ if that is necessary. - - The handler code may not invoke any semanage write requests for the same object type (i.e. modifying the underlying store is not allowed). The iterate function is reentrant only while inside a transaction (see - .B semanage_begin_transaction --). It is not safe to execute other semanage read or write requests within iterate if not inside a transaction. The handler may return -1 to signal error exit, 0 to signal continue, and 1 to signal successful exit early (the iterate function will stop accordingly). -+). It is not safe to execute other semanage read or write requests within iterate if not inside a transaction. The handler may return \-1 to signal error exit, 0 to signal continue, and 1 to signal successful exit early (the iterate function will stop accordingly). - - .TP - .B Parameters: -@@ -50,7 +50,7 @@ This function requires an semanage connection to be established (see - ) - - .SH "RETURN VALUE" --In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error. -+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. - Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other semanage object read calls until the next commit. - - .SH "SEE ALSO" -diff --git a/libsemanage/man/man3/semanage_list.3 b/libsemanage/man/man3/semanage_list.3 -index 9376702..acc161f 100644 ---- a/libsemanage/man/man3/semanage_list.3 -+++ b/libsemanage/man/man3/semanage_list.3 -@@ -39,7 +39,7 @@ This function requires an semanage connection to be established (see - ) - - .SH "RETURN VALUE" --In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error. -+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. - Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other semanage object read calls until the next commit. - - .SH "SEE ALSO" -diff --git a/libsemanage/man/man3/semanage_modify.3 b/libsemanage/man/man3/semanage_modify.3 -index 04bd801..ee23900 100644 ---- a/libsemanage/man/man3/semanage_modify.3 -+++ b/libsemanage/man/man3/semanage_modify.3 -@@ -42,7 +42,7 @@ This function requires an semanage connection to be established (see - ). - - .SH "RETURN VALUE" --In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error. -+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. - Otherwise 0 is returned. - - .SH "SEE ALSO" -diff --git a/libsemanage/man/man3/semanage_query.3 b/libsemanage/man/man3/semanage_query.3 -index 1a6cdb2..e61c8b8 100644 ---- a/libsemanage/man/man3/semanage_query.3 -+++ b/libsemanage/man/man3/semanage_query.3 -@@ -39,7 +39,7 @@ This function requires an semanage connection to be established (see - ) - - .SH "RETURN VALUE" --In case of failure, -1 is returned, and the semanage error callback is invoked, describing the error. -+In case of failure, \-1 is returned, and the semanage error callback is invoked, describing the error. - Otherwise a non-negative integer is returned (a commit number). The same number will be returned by all other semanage object read calls until the next commit. - - .SH "SEE ALSO" -diff --git a/libsemanage/man/man3/semanage_set_root.3 b/libsemanage/man/man3/semanage_set_root.3 -index 2ae0f17..664822e 100644 ---- a/libsemanage/man/man3/semanage_set_root.3 -+++ b/libsemanage/man/man3/semanage_set_root.3 -@@ -15,7 +15,7 @@ Set the alternate root directory for SELinux configuration directory. - This function sets an alternate root directory to for SELinux configuration paths to be used by the semanage library. - - .SH "RETURN VALUE" --In case of failure, -1 is returned. -+In case of failure, \-1 is returned. - Otherwise 0 is returned. - - .SH "SEE ALSO" -diff --git a/libsemanage/src/Makefile b/libsemanage/src/Makefile -index c63bb22..edb84cc 100644 ---- a/libsemanage/src/Makefile -+++ b/libsemanage/src/Makefile -@@ -92,7 +92,7 @@ $(LIBA): $(OBJS) - $(RANLIB) $@ - - $(LIBSO): $(LOBJS) -- $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ -lsepol -lselinux -lbz2 -lustr -L$(LIBDIR) -Wl,-soname,$(LIBSO),--version-script=libsemanage.map,-z,defs -+ $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ -lsepol -laudit -lselinux -lbz2 -lustr -L$(LIBDIR) -Wl,-soname,$(LIBSO),--version-script=libsemanage.map,-z,defs - ln -sf $@ $(TARGET) - - $(LIBPC): $(LIBPC).in ../VERSION -diff --git a/libsemanage/src/genhomedircon.c b/libsemanage/src/genhomedircon.c -index 3c81d7a..f3b9b5c 100644 ---- a/libsemanage/src/genhomedircon.c -+++ b/libsemanage/src/genhomedircon.c -@@ -283,7 +283,7 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s) - char *rbuf = NULL; - char *path = NULL; - long rbuflen; -- uid_t temp, minuid = 500; -+ uid_t temp, minuid = 500, maxuid = 60000; - int minuid_set = 0; - struct passwd pwstorage, *pwbuf; - struct stat buf; -@@ -333,6 +333,14 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s) - free(path); - path = NULL; - -+ path = semanage_findval(PATH_ETC_LOGIN_DEFS, "UID_MAX", NULL); -+ if (path && *path) { -+ temp = atoi(path); -+ maxuid = temp; -+ } -+ free(path); -+ path = NULL; -+ - path = semanage_findval(PATH_ETC_LIBUSER, "LU_UIDNUMBER", "="); - if (path && *path) { - temp = atoi(path); -@@ -352,7 +360,7 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s) - goto fail; - setpwent(); - while ((retval = getpwent_r(&pwstorage, rbuf, rbuflen, &pwbuf)) == 0) { -- if (pwbuf->pw_uid < minuid) -+ if (pwbuf->pw_uid < minuid || pwbuf->pw_uid > maxuid) - continue; - if (!semanage_list_find(shells, pwbuf->pw_shell)) - continue; -@@ -385,7 +393,7 @@ static semanage_list_t *get_home_dirs(genhomedircon_settings_t * s) - - /* NOTE: old genhomedircon printed a warning on match */ - if (hand.matched) { -- WARN(s->h_semanage, "%s homedir %s or its parent directory conflicts with a file context already specified in the policy. This usually indicates an incorrectly defined system account. If it is a system account please make sure its uid is less than %u or its login shell is /sbin/nologin.", pwbuf->pw_name, pwbuf->pw_dir, minuid); -+ WARN(s->h_semanage, "%s homedir %s or its parent directory conflicts with a file context already specified in the policy. This usually indicates an incorrectly defined system account. If it is a system account please make sure its uid is less than %u or greater than %u or its login shell is /sbin/nologin.", pwbuf->pw_name, pwbuf->pw_dir, minuid, maxuid); - } else { - if (semanage_list_push(&homedir_list, path)) - goto fail; -diff --git a/libsemanage/src/seusers_local.c b/libsemanage/src/seusers_local.c -index e7cf12c..ed0af21 100644 ---- a/libsemanage/src/seusers_local.c -+++ b/libsemanage/src/seusers_local.c -@@ -8,27 +8,117 @@ typedef struct semanage_seuser record_t; - - #include - #include -+#include -+#include - #include "user_internal.h" - #include "seuser_internal.h" - #include "handle.h" - #include "database.h" - #include "debug.h" -+#include "string.h" -+#include -+ -+static char *semanage_user_roles(semanage_handle_t * handle, const char *sename) { -+ char *roles = NULL; -+ unsigned int num_roles; -+ size_t i; -+ size_t size = 0; -+ const char **roles_arr; -+ semanage_user_key_t *key = NULL; -+ semanage_user_t * user; -+ if (semanage_user_key_create(handle, sename, &key) >= 0) { -+ if (semanage_user_query(handle, key, &user) >= 0) { -+ if (semanage_user_get_roles(handle, -+ user, -+ &roles_arr, -+ &num_roles) >= 0) { -+ for (i = 0; i -+#include - #include "user_internal.h" -+#include "seuser_internal.h" - #include "handle.h" - #include "database.h" -+#include "errno.h" -+#include "debug.h" - - int semanage_user_modify_local(semanage_handle_t * handle, - const semanage_user_key_t * key, -@@ -19,9 +24,43 @@ int semanage_user_modify_local(semanage_handle_t * handle, - return dbase_modify(handle, dconfig, key, data); - } - -+static int lookup_seuser(semanage_handle_t * handle, const semanage_user_key_t *k) { -+ semanage_user_t *user; -+ semanage_seuser_t **records; -+ const char *name; -+ const char *sename; -+ unsigned int count; -+ size_t i; -+ int rc = 0; -+ if (semanage_user_query(handle, k, &user) < 0) -+ return 0; -+ name = semanage_user_get_name(user); -+ semanage_seuser_list_local(handle, -+ &records, -+ &count); -+ for(i=0; iop = expr->op; - if (new_expr->expr_type == CEXPR_NAMES) { - if (new_expr->attr & CEXPR_TYPE) { -+ /* -+ * Copy over constraint policy source types and/or -+ * attributes for sepol_compute_av_reason_buffer(3) so that -+ * utilities can analyse constraint errors. -+ */ -+ if (map_ebitmap(&expr->type_names->types, -+ &new_expr->type_names->types, -+ state->typemap)) { -+ ERR(NULL, "Failed to map type_names->types"); -+ goto out_of_mem; -+ } - /* Type sets require expansion and conversion. */ - if (expand_convert_type_set(state->out, - state-> -diff --git a/libsepol/src/policydb.c b/libsepol/src/policydb.c -index 1f49261..8c7efbc 100644 ---- a/libsepol/src/policydb.c -+++ b/libsepol/src/policydb.c -@@ -165,6 +165,13 @@ static struct policydb_compat_info policydb_compat[] = { - .target_platform = SEPOL_TARGET_SELINUX, - }, - { -+ .type = POLICY_KERN, -+ .version = POLICYDB_VERSION_CONSTRAINT_NAMES, -+ .sym_num = SYM_NUM, -+ .ocon_num = OCON_NODE6 + 1, -+ .target_platform = SEPOL_TARGET_SELINUX, -+ }, -+ { - .type = POLICY_BASE, - .version = MOD_POLICYDB_VERSION_BASE, - .sym_num = SYM_NUM, -@@ -256,6 +263,13 @@ static struct policydb_compat_info policydb_compat[] = { - .target_platform = SEPOL_TARGET_SELINUX, - }, - { -+ .type = POLICY_BASE, -+ .version = MOD_POLICYDB_VERSION_CONSTRAINT_NAMES, -+ .sym_num = SYM_NUM, -+ .ocon_num = OCON_NODE6 + 1, -+ .target_platform = SEPOL_TARGET_SELINUX, -+ }, -+ { - .type = POLICY_MOD, - .version = MOD_POLICYDB_VERSION_BASE, - .sym_num = SYM_NUM, -@@ -346,6 +360,13 @@ static struct policydb_compat_info policydb_compat[] = { - .ocon_num = 0, - .target_platform = SEPOL_TARGET_SELINUX, - }, -+ { -+ .type = POLICY_MOD, -+ .version = MOD_POLICYDB_VERSION_CONSTRAINT_NAMES, -+ .sym_num = SYM_NUM, -+ .ocon_num = 0, -+ .target_platform = SEPOL_TARGET_SELINUX, -+ }, - }; - - #if 0 -@@ -2019,6 +2040,10 @@ static int read_cons_helper(policydb_t * p, constraint_node_t ** nodep, - if (p->policy_type != POLICY_KERN && - type_set_read(e->type_names, fp)) - return -1; -+ else if (p->policy_type == POLICY_KERN && -+ p->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES && -+ type_set_read(e->type_names, fp)) -+ return -1; - break; - default: - return -1; -diff --git a/libsepol/src/services.c b/libsepol/src/services.c -index 7fac4a0..43ec07e 100644 ---- a/libsepol/src/services.c -+++ b/libsepol/src/services.c -@@ -43,6 +43,11 @@ - * Implementation of the security services. - */ - -+/* The initial sizes malloc'd for sepol_compute_av_reason_buffer() support */ -+#define REASON_BUF_SIZE 2048 -+#define EXPR_BUF_SIZE 1024 -+#define STACK_LEN 32 -+ - #include - #include - #include -@@ -54,6 +59,7 @@ - #include - #include - #include -+#include - - #include "debug.h" - #include "private.h" -@@ -70,6 +76,50 @@ static int selinux_enforcing = 1; - static sidtab_t mysidtab, *sidtab = &mysidtab; - static policydb_t mypolicydb, *policydb = &mypolicydb; - -+/* Used by sepol_compute_av_reason_buffer() to keep track of entries */ -+static int reason_buf_used; -+static int reason_buf_len; -+ -+/* Stack services for RPN to infix conversion. */ -+static char **stack; -+static int stack_len; -+static int next_stack_entry; -+ -+static void push(char * expr_ptr) -+{ -+ if (next_stack_entry >= stack_len) { -+ char **new_stack = stack; -+ int new_stack_len; -+ -+ if (stack_len == 0) -+ new_stack_len = STACK_LEN; -+ else -+ new_stack_len = stack_len * 2; -+ -+ new_stack = realloc(stack, new_stack_len * sizeof(*stack)); -+ if (!new_stack) { -+ ERR(NULL, "unable to allocate stack space"); -+ return; -+ } -+ stack_len = new_stack_len; -+ stack = new_stack; -+ } -+ stack[next_stack_entry] = expr_ptr; -+ next_stack_entry++; -+} -+ -+static char *pop(void) -+{ -+ next_stack_entry--; -+ if (next_stack_entry < 0) { -+ next_stack_entry = 0; -+ ERR(NULL, "pop called with no stack entries"); -+ return NULL; -+ } -+ return stack[next_stack_entry]; -+} -+/* End Stack services */ -+ - int hidden sepol_set_sidtab(sidtab_t * s) - { - sidtab = s; -@@ -113,20 +163,195 @@ int sepol_set_policydb_from_file(FILE * fp) - static uint32_t latest_granting = 0; - - /* -- * Return the boolean value of a constraint expression -- * when it is applied to the specified source and target -+ * cat_expr_buf adds a string to an expression buffer and handles realloc's if -+ * buffer is too small. The array of expression text buffer pointers and its -+ * counter are globally defined here as constraint_expr_eval_reason() sets -+ * them up and cat_expr_buf updates the e_buf pointer if the buffer is realloc'ed. -+ */ -+static int expr_counter; -+static char **expr_list; -+static int expr_buf_used; -+static int expr_buf_len; -+ -+static void cat_expr_buf(char *e_buf, char *string) -+{ -+ int len, new_buf_len; -+ char *p, *new_buf = e_buf; -+ -+ while (1) { -+ p = e_buf + expr_buf_used; -+ len = snprintf(p, expr_buf_len - expr_buf_used, "%s", string); -+ if (len < 0 || len >= expr_buf_len - expr_buf_used) { -+ new_buf_len = expr_buf_len + EXPR_BUF_SIZE; -+ new_buf = realloc(e_buf, new_buf_len); -+ if (!new_buf) { -+ ERR(NULL, "failed to realloc expr buffer"); -+ return; -+ } -+ /* Update the new ptr in the expr list and locally + new len */ -+ expr_list[expr_counter] = new_buf; -+ e_buf = new_buf; -+ expr_buf_len = new_buf_len; -+ } else { -+ expr_buf_used += len; -+ return; -+ } -+ } -+} -+ -+/* -+ * If the POLICY_KERN version is < POLICYDB_VERSION_CONSTRAINT_NAMES, -+ * then just return. -+ * -+ * If the POLICY_KERN version is >= POLICYDB_VERSION_CONSTRAINT_NAMES, -+ * then for 'types' only, read the types_names->types list as it will -+ * contain a list of types and attributes that were defined in the -+ * policy source. -+ */ -+static void get_names_list(constraint_expr_t *e, int type) -+{ -+ ebitmap_t *types; -+ types = &e->type_names->types; -+ int rc = 0; -+ unsigned int i; -+ char tmp_buf[128]; -+ /* if -type_names->types is 0, then output string */ -+ int empty_set = 0; -+ -+ if (policydb->policy_type == POLICY_KERN && -+ policydb->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES && -+ type == CEXPR_TYPE) { -+ /* -+ * Process >= POLICYDB_VERSION_CONSTRAINT_NAMES with CEXPR_TYPE, then -+ * obtain the list of names defined in the policy source. -+ */ -+ cat_expr_buf(expr_list[expr_counter], "{ POLICY_SOURCE: "); -+ for (i = ebitmap_startbit(types); i < ebitmap_length(types); i++) { -+ if ((rc = ebitmap_get_bit(types, i)) == 0) -+ continue; -+ /* Collect entries */ -+ snprintf(tmp_buf, sizeof(tmp_buf), "%s ", policydb->p_type_val_to_name[i]); -+ cat_expr_buf(expr_list[expr_counter], tmp_buf); -+ empty_set++; -+ } -+ if (empty_set == 0) -+ cat_expr_buf(expr_list[expr_counter], " "); -+ cat_expr_buf(expr_list[expr_counter], "} "); -+ } -+ return; -+} -+ -+static void msgcat(char *src, char *tgt, char *rel, int failed) -+{ -+ char tmp_buf[1024]; -+ if (failed) -+ snprintf(tmp_buf, sizeof(tmp_buf), "(%s %s %s -Fail-) ", -+ src, rel, tgt); -+ else -+ snprintf(tmp_buf, sizeof(tmp_buf), "(%s %s %s -Pass-) ", -+ src, rel, tgt); -+ cat_expr_buf(expr_list[expr_counter], tmp_buf); -+} -+ -+/* Returns a buffer with class, statement type and permissions */ -+static char *get_class_info(sepol_security_class_t tclass, -+ constraint_node_t *constraint, -+ context_struct_t * xcontext) -+{ -+ constraint_expr_t *e; -+ int mls, state_num; -+ -+ /* Find if MLS statement or not */ -+ mls = 0; -+ for (e = constraint->expr; e; e = e->next) { -+ if (e->attr >= CEXPR_L1L2) { -+ mls = 1; -+ break; -+ } -+ } -+ -+ /* Determine statement type */ -+ char *statements[] = { -+ "constrain ", /* 0 */ -+ "mlsconstrain ", /* 1 */ -+ "validatetrans ", /* 2 */ -+ "mlsvalidatetrans ", /* 3 */ -+ 0 }; -+ -+ if (xcontext == NULL) -+ state_num = mls + 0; -+ else -+ state_num = mls + 2; -+ -+ int class_buf_len = 0; -+ int new_class_buf_len; -+ int len, buf_used; -+ char *class_buf = NULL, *p; -+ char *new_class_buf = NULL; -+ -+ while (1) { -+ new_class_buf_len = class_buf_len + EXPR_BUF_SIZE; -+ new_class_buf = realloc(class_buf, new_class_buf_len); -+ if (!new_class_buf) -+ return NULL; -+ class_buf_len = new_class_buf_len; -+ class_buf = new_class_buf; -+ buf_used = 0; -+ p = class_buf; -+ -+ /* Add statement type */ -+ len = snprintf(p, class_buf_len - buf_used, "%s", statements[state_num]); -+ if (len < 0 || len >= class_buf_len - buf_used) -+ continue; -+ -+ /* Add class entry */ -+ p += len; -+ buf_used += len; -+ len = snprintf(p, class_buf_len - buf_used, "%s ", -+ policydb->p_class_val_to_name[tclass - 1]); -+ if (len < 0 || len >= class_buf_len - buf_used) -+ continue; -+ -+ /* Add permission entries */ -+ p += len; -+ buf_used += len; -+ len = snprintf(p, class_buf_len - buf_used, "{%s } (", -+ sepol_av_to_string(policydb, tclass, constraint->permissions)); -+ if (len < 0 || len >= class_buf_len - buf_used) -+ continue; -+ break; -+ } -+ return class_buf; -+} -+ -+/* -+ * Modified version of constraint_expr_eval that will process each -+ * constraint as before but adds the information to text buffers that -+ * will hold various components. The expression will be in RPN format, -+ * therefore there is a stack based RPN to infix converter to produce -+ * the final readable constraint. -+ * -+ * Return the boolean value of a constraint expression -+ * when it is applied to the specified source and target - * security contexts. - * - * xcontext is a special beast... It is used by the validatetrans rules - * only. For these rules, scontext is the context before the transition, - * tcontext is the context after the transition, and xcontext is the context - * of the process performing the transition. All other callers of -- * constraint_expr_eval should pass in NULL for xcontext. -+ * constraint_expr_eval_reason should pass in NULL for xcontext. -+ * -+ * This function will also build a buffer as the constraint is processed -+ * for analysis. If this option is not required, then: -+ * 'tclass' should be '0' and r_buf MUST be NULL. - */ --static int constraint_expr_eval(context_struct_t * scontext, -+static int constraint_expr_eval_reason(context_struct_t * scontext, - context_struct_t * tcontext, - context_struct_t * xcontext, -- constraint_expr_t * cexpr) -+ sepol_security_class_t tclass, -+ constraint_node_t *constraint, -+ char **r_buf, -+ unsigned int flags) - { - uint32_t val1, val2; - context_struct_t *c; -@@ -136,56 +361,137 @@ static int constraint_expr_eval(context_struct_t * scontext, - int s[CEXPR_MAXDEPTH]; - int sp = -1; - -- for (e = cexpr; e; e = e->next) { -+ char tmp_buf[128]; -+ -+/* -+ * Define the s_t_x_num values that make up r1, t2 etc. in text strings -+ * Set 1 = source, 2 = target, 3 = xcontext for validatetrans -+ */ -+#define SOURCE 1 -+#define TARGET 2 -+#define XTARGET 3 -+ -+ int s_t_x_num = SOURCE; -+ -+ /* Set 0 = fail, u = CEXPR_USER, r = CEXPR_ROLE, t = CEXPR_TYPE */ -+ int u_r_t = 0; -+ -+ char *name1, *name2; -+ char *src = NULL; -+ char *tgt = NULL; -+ -+ int rc = 0, x; -+ -+ char *class_buf = NULL; -+ -+ class_buf = get_class_info(tclass, constraint, xcontext); -+ if (!class_buf) { -+ ERR(NULL, "failed to allocate class buffer"); -+ return -ENOMEM; -+ } -+ -+ /* Original function but with buffer support */ -+ int expr_list_len = 0; -+ expr_counter = 0; -+ expr_list = NULL; -+ for (e = constraint->expr; e; e = e->next) { -+ /* Allocate a stack to hold expression buffer entries */ -+ if (expr_counter >= expr_list_len) { -+ char **new_expr_list = expr_list; -+ int new_expr_list_len; -+ -+ if (expr_list_len == 0) -+ new_expr_list_len = STACK_LEN; -+ else -+ new_expr_list_len = expr_list_len * 2; -+ -+ new_expr_list = realloc(expr_list, new_expr_list_len * sizeof(*expr_list)); -+ if (!new_expr_list) { -+ ERR(NULL, "failed to allocate expr buffer stack"); -+ rc = -ENOMEM; -+ goto out; -+ } -+ expr_list_len = new_expr_list_len; -+ expr_list = new_expr_list; -+ } -+ -+ /* -+ * malloc a buffer to store each expression text component. If the -+ * buffer is too small cat_expr_buf() will realloc extra space. -+ */ -+ expr_buf_len = EXPR_BUF_SIZE; -+ expr_list[expr_counter] = malloc(expr_buf_len); -+ if (!expr_list[expr_counter]) { -+ ERR(NULL, "failed to allocate expr buffer"); -+ rc = -ENOMEM; -+ goto out; -+ } -+ expr_buf_used = 0; -+ -+ /* Now process each expression of the constraint */ - switch (e->expr_type) { - case CEXPR_NOT: - BUG_ON(sp < 0); - s[sp] = !s[sp]; -+ cat_expr_buf(expr_list[expr_counter], "not"); - break; - case CEXPR_AND: - BUG_ON(sp < 1); - sp--; - s[sp] &= s[sp + 1]; -+ cat_expr_buf(expr_list[expr_counter], "and"); - break; - case CEXPR_OR: - BUG_ON(sp < 1); - sp--; - s[sp] |= s[sp + 1]; -+ cat_expr_buf(expr_list[expr_counter], "or"); - break; - case CEXPR_ATTR: - if (sp == (CEXPR_MAXDEPTH - 1)) -- return 0; -+ goto out; -+ - switch (e->attr) { - case CEXPR_USER: - val1 = scontext->user; - val2 = tcontext->user; -+ free(src); src = strdup("u1"); -+ free(tgt); tgt = strdup("u2"); - break; - case CEXPR_TYPE: - val1 = scontext->type; - val2 = tcontext->type; -+ free(src); src = strdup("t1"); -+ free(tgt); tgt = strdup("t2"); - break; - case CEXPR_ROLE: - val1 = scontext->role; - val2 = tcontext->role; - r1 = policydb->role_val_to_struct[val1 - 1]; - r2 = policydb->role_val_to_struct[val2 - 1]; -+ name1 = policydb->p_role_val_to_name[r1->s.value - 1]; -+ name2 = policydb->p_role_val_to_name[r2->s.value - 1]; -+ snprintf(tmp_buf, sizeof(tmp_buf), "r1=%s", name1); -+ free(src); src = strdup(tmp_buf); -+ snprintf(tmp_buf, sizeof(tmp_buf), "r2=%s ", name2); -+ free(tgt); tgt = strdup(tmp_buf); -+ - switch (e->op) { - case CEXPR_DOM: -- s[++sp] = -- ebitmap_get_bit(&r1->dominates, -- val2 - 1); -+ s[++sp] = ebitmap_get_bit(&r1->dominates, val2 - 1); -+ msgcat(src, tgt, "dom", s[sp] == 0); -+ expr_counter++; - continue; - case CEXPR_DOMBY: -- s[++sp] = -- ebitmap_get_bit(&r2->dominates, -- val1 - 1); -+ s[++sp] = ebitmap_get_bit(&r2->dominates, val1 - 1); -+ msgcat(src, tgt, "domby", s[sp] == 0); -+ expr_counter++; - continue; - case CEXPR_INCOMP: -- s[++sp] = -- (!ebitmap_get_bit -- (&r1->dominates, val2 - 1) -- && !ebitmap_get_bit(&r2->dominates, -- val1 - 1)); -+ s[++sp] = (!ebitmap_get_bit(&r1->dominates, val2 - 1) -+ && !ebitmap_get_bit(&r2->dominates, val1 - 1)); -+ msgcat(src, tgt, "incomp", s[sp] == 0); -+ expr_counter++; - continue; - default: - break; -@@ -194,110 +500,327 @@ static int constraint_expr_eval(context_struct_t * scontext, - case CEXPR_L1L2: - l1 = &(scontext->range.level[0]); - l2 = &(tcontext->range.level[0]); -+ free(src); src = strdup("l1"); -+ free(tgt); tgt = strdup("l2"); - goto mls_ops; - case CEXPR_L1H2: - l1 = &(scontext->range.level[0]); - l2 = &(tcontext->range.level[1]); -+ free(src); src = strdup("l1"); -+ free(tgt); tgt = strdup("h2"); - goto mls_ops; - case CEXPR_H1L2: - l1 = &(scontext->range.level[1]); - l2 = &(tcontext->range.level[0]); -+ free(src); src = strdup("h1"); -+ free(tgt); tgt = strdup("L2"); - goto mls_ops; - case CEXPR_H1H2: - l1 = &(scontext->range.level[1]); - l2 = &(tcontext->range.level[1]); -+ free(src); src = strdup("h1"); -+ free(tgt); tgt = strdup("h2"); - goto mls_ops; - case CEXPR_L1H1: - l1 = &(scontext->range.level[0]); - l2 = &(scontext->range.level[1]); -+ free(src); src = strdup("l1"); -+ free(tgt); tgt = strdup("h1"); - goto mls_ops; - case CEXPR_L2H2: - l1 = &(tcontext->range.level[0]); - l2 = &(tcontext->range.level[1]); -- goto mls_ops; -- mls_ops: -+ free(src); src = strdup("l2"); -+ free(tgt); tgt = strdup("h2"); -+ mls_ops: - switch (e->op) { - case CEXPR_EQ: - s[++sp] = mls_level_eq(l1, l2); -+ msgcat(src, tgt, "eq", s[sp] == 0); -+ expr_counter++; - continue; - case CEXPR_NEQ: - s[++sp] = !mls_level_eq(l1, l2); -+ msgcat(src, tgt, "neq", s[sp] == 0); -+ expr_counter++; - continue; - case CEXPR_DOM: - s[++sp] = mls_level_dom(l1, l2); -+ msgcat(src, tgt, "dom", s[sp] == 0); -+ expr_counter++; - continue; - case CEXPR_DOMBY: - s[++sp] = mls_level_dom(l2, l1); -+ msgcat(src, tgt, "domby", s[sp] == 0); -+ expr_counter++; - continue; - case CEXPR_INCOMP: - s[++sp] = mls_level_incomp(l2, l1); -+ msgcat(src, tgt, "incomp", s[sp] == 0); -+ expr_counter++; - continue; - default: - BUG(); -- return 0; -+ goto out; - } - break; - default: - BUG(); -- return 0; -+ goto out; - } - - switch (e->op) { - case CEXPR_EQ: - s[++sp] = (val1 == val2); -+ msgcat(src, tgt, "eq", s[sp] == 0); - break; - case CEXPR_NEQ: - s[++sp] = (val1 != val2); -+ msgcat(src, tgt, "neq", s[sp] == 0); - break; - default: - BUG(); -- return 0; -+ goto out; - } - break; - case CEXPR_NAMES: - if (sp == (CEXPR_MAXDEPTH - 1)) -- return 0; -+ goto out; -+ s_t_x_num = SOURCE; - c = scontext; -- if (e->attr & CEXPR_TARGET) -+ if (e->attr & CEXPR_TARGET) { -+ s_t_x_num = TARGET; - c = tcontext; -- else if (e->attr & CEXPR_XTARGET) { -+ } else if (e->attr & CEXPR_XTARGET) { -+ s_t_x_num = XTARGET; - c = xcontext; -- if (!c) { -- BUG(); -- return 0; -- } - } -- if (e->attr & CEXPR_USER) -+ if (!c) { -+ BUG(); -+ goto out; -+ } -+ if (e->attr & CEXPR_USER) { -+ u_r_t = CEXPR_USER; - val1 = c->user; -- else if (e->attr & CEXPR_ROLE) -+ name1 = policydb->p_user_val_to_name[val1 - 1]; -+ snprintf(tmp_buf, sizeof(tmp_buf), "u%d=%s ", -+ s_t_x_num, name1); -+ free(src); src = strdup(tmp_buf); -+ } -+ else if (e->attr & CEXPR_ROLE) { -+ u_r_t = CEXPR_ROLE; - val1 = c->role; -- else if (e->attr & CEXPR_TYPE) -+ name1 = policydb->p_role_val_to_name[val1 - 1]; -+ snprintf(tmp_buf, sizeof(tmp_buf), "r%d=%s ", s_t_x_num, name1); -+ free(src); src = strdup(tmp_buf); -+ } -+ else if (e->attr & CEXPR_TYPE) { -+ u_r_t = CEXPR_TYPE; - val1 = c->type; -+ name1 = policydb->p_type_val_to_name[val1 - 1]; -+ snprintf(tmp_buf, sizeof(tmp_buf), -+ "t%d=%s ", s_t_x_num, name1); -+ free(src); src = strdup(tmp_buf); -+ } - else { - BUG(); -- return 0; -+ goto out; - } - - switch (e->op) { - case CEXPR_EQ: -+ switch (u_r_t) { -+ case CEXPR_USER: -+ free(tgt); tgt=strdup("USER_ENTRY"); -+ break; -+ case CEXPR_ROLE: -+ free(tgt); tgt=strdup("ROLE_ENTRY"); -+ break; -+ case CEXPR_TYPE: -+ free(tgt); tgt=strdup("TYPE_ENTRY"); -+ break; -+ default: -+ ERR(NULL, "unrecognized u_r_t Value: %d", u_r_t); -+ break; -+ } -+ - s[++sp] = ebitmap_get_bit(&e->names, val1 - 1); -+ msgcat(src, tgt, "eq", s[sp] == 0); -+ if (s[sp] == 0) { -+ get_names_list(e, u_r_t); -+ } - break; -+ - case CEXPR_NEQ: -+ switch (u_r_t) { -+ case CEXPR_USER: -+ free(tgt); tgt=strdup("USER_ENTRY"); -+ break; -+ case CEXPR_ROLE: -+ free(tgt); tgt=strdup("ROLE_ENTRY"); -+ break; -+ case CEXPR_TYPE: -+ free(tgt); tgt=strdup("TYPE_ENTRY"); -+ break; -+ default: -+ ERR(NULL, "unrecognized u_r_t Value: %d", u_r_t); -+ break; -+ } -+ - s[++sp] = !ebitmap_get_bit(&e->names, val1 - 1); -+ msgcat(src, tgt, "neq", s[sp] == 0); -+ if (s[sp] == 0) { -+ get_names_list(e, u_r_t); -+ } - break; - default: - BUG(); -- return 0; -+ goto out; - } - break; - default: - BUG(); -- return 0; -+ goto out; - } -+ expr_counter++; -+ } -+ -+ /* -+ * At this point each expression of the constraint is in -+ * expr_list[n+1] and in RPN format. Now convert to 'infix' -+ */ -+ -+ /* -+ * Save expr count but zero expr_counter to detect if 'BUG(); goto out;' -+ * was called as we need to release any used expr_list malloc's. Normally -+ * they are released by the RPN to infix code. -+ */ -+ int expr_count = expr_counter; -+ expr_counter = 0; -+ -+ /* -+ * The array of expression answer buffer pointers and counter. Generate -+ * the same number of answer buffer entries as expression buffers (as -+ * there will never be more required). -+ */ -+ char **answer_list; -+ int answer_counter = 0; -+ -+ answer_list = malloc(expr_count * sizeof(*answer_list)); -+ if (!answer_list) { -+ ERR(NULL, "failed to allocate answer stack"); -+ rc = -ENOMEM; -+ goto out; - } - -- BUG_ON(sp != 0); -- return s[0]; -+ /* The pop operands */ -+ char *a; -+ char *b; -+ int a_len, b_len; -+ -+ /* Convert constraint from RPN to infix notation. */ -+ for (x = 0; x != expr_count; x++) { -+ if (strncmp(expr_list[x], "and", 3) == 0 || strncmp(expr_list[x], -+ "or", 2) == 0) { -+ b = pop(); -+ b_len = strlen(b); -+ a = pop(); -+ a_len = strlen(a); -+ -+ /* get a buffer to hold the answer */ -+ answer_list[answer_counter] = malloc(a_len + b_len + 8); -+ if (!answer_list[answer_counter]) { -+ ERR(NULL, "failed to allocate answer buffer"); -+ rc = -ENOMEM; -+ goto out; -+ } -+ memset(answer_list[answer_counter], '\0', a_len + b_len + 8); -+ -+ sprintf(answer_list[answer_counter], "%s %s %s", a, expr_list[x], b); -+ push(answer_list[answer_counter++]); -+ free(a); -+ free(b); -+ } else if (strncmp(expr_list[x], "not", 3) == 0) { -+ b = pop(); -+ b_len = strlen(b); -+ -+ answer_list[answer_counter] = malloc(b_len + 8); -+ if (!answer_list[answer_counter]) { -+ ERR(NULL, "failed to allocate answer buffer"); -+ rc = -ENOMEM; -+ goto out; -+ } -+ memset(answer_list[answer_counter], '\0', b_len + 8); -+ -+ if (strncmp(b, "not", 3) == 0) -+ sprintf(answer_list[answer_counter], "%s (%s)", expr_list[x], b); -+ else -+ sprintf(answer_list[answer_counter], "%s%s", expr_list[x], b); -+ push(answer_list[answer_counter++]); -+ free(b); -+ } else { -+ push(expr_list[x]); -+ } -+ } -+ /* Get the final answer from tos and build constraint text */ -+ a = pop(); -+ -+ /* Constraint calculation: rc = 0 is denied, rc = 1 is granted */ -+ sprintf(tmp_buf,"Constraint %s\n", s[0] ? "GRANTED" : "DENIED"); -+ -+ int len, new_buf_len; -+ char *p, **new_buf = r_buf; -+ /* -+ * These contain the constraint components that are added to the -+ * callers reason buffer. -+ */ -+ char *buffers[] = { class_buf, a, "); ", tmp_buf, 0 }; -+ -+ /* -+ * This will add the constraints to the callers reason buffer (who is -+ * responsible for freeing the memory). It will handle any realloc's -+ * should the buffer be too short. -+ * The reason_buf_used and reason_buf_len counters are defined globally -+ * as multiple constraints can be in the buffer. -+ */ -+ if (r_buf && ((s[0] == 0) || ((s[0] == 1 && -+ (flags & SHOW_GRANTED) == SHOW_GRANTED)))) { -+ for (x = 0; buffers[x] != NULL; x++) { -+ while (1) { -+ p = *r_buf + reason_buf_used; -+ len = snprintf(p, reason_buf_len - reason_buf_used, "%s", buffers[x]); -+ if (len < 0 || len >= reason_buf_len - reason_buf_used) { -+ new_buf_len = reason_buf_len + REASON_BUF_SIZE; -+ *new_buf = realloc(*r_buf, new_buf_len); -+ if (!new_buf) { -+ ERR(NULL, "failed to realloc reason buffer"); -+ goto out1; -+ } -+ **r_buf = **new_buf; -+ reason_buf_len = new_buf_len; -+ continue; -+ } else { -+ reason_buf_used += len; -+ break; -+ } -+ } -+ } -+ } -+ -+out1: -+ rc = s[0]; -+ free(a); -+ -+out: -+ free(class_buf); -+ free(src); -+ free(tgt); -+ -+ if (expr_counter) { -+ for (x = 0; expr_list[x] != NULL; x++) -+ free(expr_list[x]); -+ } -+ return rc; - } - - /* -@@ -309,7 +832,9 @@ static int context_struct_compute_av(context_struct_t * scontext, - sepol_security_class_t tclass, - sepol_access_vector_t requested, - struct sepol_av_decision *avd, -- unsigned int *reason) -+ unsigned int *reason, -+ char **r_buf, -+ unsigned int flags) - { - constraint_node_t *constraint; - struct role_allow *ra; -@@ -384,8 +909,8 @@ static int context_struct_compute_av(context_struct_t * scontext, - constraint = tclass_datum->constraints; - while (constraint) { - if ((constraint->permissions & (avd->allowed)) && -- !constraint_expr_eval(scontext, tcontext, NULL, -- constraint->expr)) { -+ !constraint_expr_eval_reason(scontext, tcontext, NULL, -+ tclass, constraint, r_buf, flags)) { - avd->allowed = - (avd->allowed) & ~(constraint->permissions); - } -@@ -460,8 +985,8 @@ int hidden sepol_validate_transition(sepol_security_id_t oldsid, - - constraint = tclass_datum->validatetrans; - while (constraint) { -- if (!constraint_expr_eval(ocontext, ncontext, tcontext, -- constraint->expr)) { -+ if (!constraint_expr_eval_reason(ocontext, ncontext, tcontext, -+ 0, constraint, NULL, 0)) { - return -EPERM; - } - constraint = constraint->next; -@@ -494,11 +1019,59 @@ int hidden sepol_compute_av_reason(sepol_security_id_t ssid, - } - - rc = context_struct_compute_av(scontext, tcontext, tclass, -- requested, avd, reason); -+ requested, avd, reason, NULL, 0); - out: - return rc; - } - -+/* -+ * sepol_compute_av_reason_buffer - the reason buffer is malloc'd to -+ * REASON_BUF_SIZE. If the buffer size is exceeded, then it is realloc'd -+ * in the constraint_expr_eval_reason() function. -+ */ -+int hidden sepol_compute_av_reason_buffer(sepol_security_id_t ssid, -+ sepol_security_id_t tsid, -+ sepol_security_class_t tclass, -+ sepol_access_vector_t requested, -+ struct sepol_av_decision *avd, -+ unsigned int *reason, -+ char **reason_buf, -+ unsigned int flags) -+{ -+ *reason_buf = malloc(REASON_BUF_SIZE); -+ if (!*reason_buf) { -+ ERR(NULL, "failed to allocate reason buffer"); -+ return -ENOMEM; -+ } -+ /* -+ * These are defined globally as the buffer can contain multiple -+ * constraint statements so need to keep track -+ */ -+ reason_buf_used = 0; -+ reason_buf_len = REASON_BUF_SIZE; -+ -+ context_struct_t *scontext = 0, *tcontext = 0; -+ int rc = 0; -+ -+ scontext = sepol_sidtab_search(sidtab, ssid); -+ if (!scontext) { -+ ERR(NULL, "unrecognized SID %d", ssid); -+ rc = -EINVAL; -+ goto out; -+ } -+ tcontext = sepol_sidtab_search(sidtab, tsid); -+ if (!tcontext) { -+ ERR(NULL, "unrecognized SID %d", tsid); -+ rc = -EINVAL; -+ goto out; -+ } -+ -+ rc = context_struct_compute_av(scontext, tcontext, tclass, -+ requested, avd, reason, reason_buf, flags); -+out: -+ return rc; -+} -+ - int hidden sepol_compute_av(sepol_security_id_t ssid, - sepol_security_id_t tsid, - sepol_security_class_t tclass, -@@ -511,6 +1084,70 @@ int hidden sepol_compute_av(sepol_security_id_t ssid, - } - - /* -+ * Return a class ID associated with the class string specified by -+ * class_name. -+ */ -+int hidden sepol_class_name_to_id(const char *class_name, -+ sepol_security_class_t *tclass) -+{ -+ char *class = NULL; -+ sepol_security_class_t id; -+ -+ for (id = 1; ; id++) { -+ if ((class = policydb->p_class_val_to_name[id - 1]) == NULL) { -+ ERR(NULL, "could not convert %s to class id", class_name); -+ return STATUS_ERR; -+ } -+ if ((strcmp(class, class_name)) == 0) { -+ *tclass = id; -+ return STATUS_SUCCESS; -+ } -+ } -+} -+ -+/* -+ * Return access vector bit associated with the class ID and permission -+ * string. -+ */ -+int hidden sepol_perm_name_to_av(sepol_security_class_t tclass, -+ const char *perm_name, -+ sepol_access_vector_t *av) -+{ -+ class_datum_t *tclass_datum; -+ perm_datum_t *perm_datum; -+ -+ if (!tclass || tclass > policydb->p_classes.nprim) { -+ ERR(NULL, "unrecognized class %d", tclass); -+ return -EINVAL; -+ } -+ tclass_datum = policydb->class_val_to_struct[tclass - 1]; -+ -+ /* Check for unique perms then the common ones (if any) */ -+ perm_datum = (perm_datum_t *) -+ hashtab_search(tclass_datum->permissions.table, -+ (hashtab_key_t)perm_name); -+ if (perm_datum != NULL) { -+ *av = 0x1 << (perm_datum->s.value - 1); -+ return STATUS_SUCCESS; -+ } -+ -+ if (tclass_datum->comdatum == NULL) -+ goto out; -+ -+ perm_datum = (perm_datum_t *) -+ hashtab_search(tclass_datum->comdatum->permissions.table, -+ (hashtab_key_t)perm_name); -+ -+ if (perm_datum != NULL) { -+ *av = 0x1 << (perm_datum->s.value - 1); -+ return STATUS_SUCCESS; -+ } -+out: -+ ERR(NULL, "could not convert %s to av bit", perm_name); -+ return STATUS_ERR; -+} -+ -+/* - * Write the security context string representation of - * the context associated with `sid' into a dynamically - * allocated string of the correct size. Set `*scontext' -@@ -1339,7 +1976,7 @@ int hidden sepol_get_user_sids(sepol_security_id_t fromsid, - rc = context_struct_compute_av(fromcon, &usercon, - SECCLASS_PROCESS, - PROCESS__TRANSITION, -- &avd, &reason); -+ &avd, &reason, NULL, 0); - if (rc || !(avd.allowed & PROCESS__TRANSITION)) - continue; - rc = sepol_sidtab_context_to_sid(sidtab, &usercon, -diff --git a/libsepol/src/write.c b/libsepol/src/write.c -index 55992f8..6fe73e6 100644 ---- a/libsepol/src/write.c -+++ b/libsepol/src/write.c -@@ -893,8 +893,11 @@ static int write_cons_helper(policydb_t * p, - if (ebitmap_write(&e->names, fp)) { - return POLICYDB_ERROR; - } -- if (p->policy_type != POLICY_KERN && -- type_set_write(e->type_names, fp)) { -+ if ((p->policy_type != POLICY_KERN && -+ type_set_write(e->type_names, fp)) || -+ (p->policy_type == POLICY_KERN && -+ (p->policyvers >= POLICYDB_VERSION_CONSTRAINT_NAMES) && -+ type_set_write(e->type_names, fp))) { - return POLICYDB_ERROR; - } - break; diff --git a/policycoreutils/.tx/config b/policycoreutils/.tx/config index 07643e9..daff18c 100644 --- a/policycoreutils/.tx/config @@ -515761,7 +512913,7 @@ index 378eac2..3186c86 100644 +tmp +*.bak diff --git a/policycoreutils/sepolicy/Makefile b/policycoreutils/sepolicy/Makefile -index 11b534f..4669fa5 100644 +index 11b534f..028bcf8 100644 --- a/policycoreutils/sepolicy/Makefile +++ b/policycoreutils/sepolicy/Makefile @@ -7,11 +7,11 @@ SBINDIR ?= $(PREFIX)/sbin @@ -515799,14 +512951,14 @@ index 11b534f..4669fa5 100644 -mkdir -p $(BASHCOMPLETIONDIR) - install -m 644 $(BASHCOMPLETIONS) $(BASHCOMPLETIONDIR) + install -m 644 $(BASHCOMPLETIONS) $(BASHCOMPLETIONDIR)/sepolicy -+ -mkdir -p /etc/dbus-1/system.d/ -+ install -m 644 org.fedoraproject.selinux.conf /etc/dbus-1/system.d/ -+ -mkdir -p /usr/share/dbus-1/system -+ install -m 644 org.fedoraproject.selinux.service /usr/share/dbus-1/system -+ -mkdir -p /usr/share/polkit-1/actions/ -+ install -m 644 org.fedoraproject.selinux.policy /usr/share/polkit-1/actions/ -+ -mkdir -p /usr/share/system-config-selinux -+ install -m 755 selinux_server.py /usr/share/system-config-selinux ++ -mkdir -p $(DESTDIR)/etc/dbus-1/system.d/ ++ install -m 644 org.fedoraproject.selinux.conf $(DESTDIR)/etc/dbus-1/system.d/ ++ -mkdir -p $(DESTDIR)/usr/share/dbus-1/system ++ install -m 644 org.fedoraproject.selinux.service $(DESTDIR)/usr/share/dbus-1/system ++ -mkdir -p $(DESTDIR)/usr/share/polkit-1/actions/ ++ install -m 644 org.fedoraproject.selinux.policy $(DESTDIR)/usr/share/polkit-1/actions/ ++ -mkdir -p $(DESTDIR)/usr/share/system-config-selinux ++ install -m 755 selinux_server.py $(DESTDIR)/usr/share/system-config-selinux diff --git a/policycoreutils/sepolicy/info.c b/policycoreutils/sepolicy/info.c index 65458e6..cd1026a 100644 --- a/policycoreutils/sepolicy/info.c @@ -525688,179 +522840,3 @@ index 86578f7..219e088 100644 return -1; } -diff --git a/sepolgen/src/sepolgen/audit.py b/sepolgen/src/sepolgen/audit.py -index d636091..56919be 100644 ---- a/sepolgen/src/sepolgen/audit.py -+++ b/sepolgen/src/sepolgen/audit.py -@@ -259,13 +259,13 @@ class AVCMessage(AuditMessage): - raise ValueError("Error during access vector computation") - - if self.type == audit2why.CONSTRAINT: -- self.data = [] -+ self.data = [ self.data ] - if self.scontext.user != self.tcontext.user: -- self.data.append("user") -+ self.data.append(("user (%s)" % self.scontext.user, 'user (%s)' % self.tcontext.user)) - if self.scontext.role != self.tcontext.role and self.tcontext.role != "object_r": -- self.data.append("role") -+ self.data.append(("role (%s)" % self.scontext.role, 'role (%s)' % self.tcontext.role)) - if self.scontext.level != self.tcontext.level: -- self.data.append("level") -+ self.data.append(("level (%s)" % self.scontext.level, 'level (%s)' % self.tcontext.level)) - - avcdict[(scontext, tcontext, self.tclass, access_tuple)] = (self.type, self.data) - -diff --git a/sepolgen/src/sepolgen/interfaces.py b/sepolgen/src/sepolgen/interfaces.py -index ae1c9c5..3258684 100644 ---- a/sepolgen/src/sepolgen/interfaces.py -+++ b/sepolgen/src/sepolgen/interfaces.py -@@ -273,10 +273,10 @@ class InterfaceVector: - self.add_av(av) - - # Add typeattribute access -- if attributes != None: -+ if attributes: - for typeattribute in interface.typeattributes(): - for attr in typeattribute.attributes: -- if not attributes.attributes.has_key(attr): -+ if not attributes.has_key(attr): - # print "missing attribute " + attr - continue - attr_vec = attributes.attributes[attr] -diff --git a/sepolgen/src/sepolgen/policygen.py b/sepolgen/src/sepolgen/policygen.py -index cc9f8ea..ce643e5 100644 ---- a/sepolgen/src/sepolgen/policygen.py -+++ b/sepolgen/src/sepolgen/policygen.py -@@ -161,21 +161,21 @@ class PolicyGenerator: - if self.explain: - rule.comment = str(refpolicy.Comment(explain_access(av, verbosity=self.explain))) - if av.type == audit2why.ALLOW: -- rule.comment += "#!!!! This avc is allowed in the current policy\n" -+ rule.comment += "\n#!!!! This avc is allowed in the current policy" - if av.type == audit2why.DONTAUDIT: -- rule.comment += "#!!!! This avc has a dontaudit rule in the current policy\n" -+ rule.comment += "\n#!!!! This avc has a dontaudit rule in the current policy" - - if av.type == audit2why.BOOLEAN: - if len(av.data) > 1: -- rule.comment += "#!!!! This avc can be allowed using one of the these booleans:\n# %s\n" % ", ".join(map(lambda x: x[0], av.data)) -+ rule.comment += "\n#!!!! This avc can be allowed using one of the these booleans:\n# %s" % ", ".join(map(lambda x: x[0], av.data)) - else: -- rule.comment += "#!!!! This avc can be allowed using the boolean '%s'\n" % av.data[0][0] -+ rule.comment += "\n#!!!! This avc can be allowed using the boolean '%s'" % av.data[0][0] - - if av.type == audit2why.CONSTRAINT: -- rule.comment += "#!!!! This avc is a constraint violation. You will need to add an attribute to either the source or target type to make it work.\n" -- rule.comment += "#Constraint rule: " -- for reason in av.data: -- rule.comment += "\n#\tPossible cause source context and target context '%s' differ\b" % reason -+ rule.comment += "\n#!!!! This avc is a constraint violation. You would need to modify the attributes of either the source or target types to allow this access.\n" -+ rule.comment += "#Constraint rule: \n\t" + av.data[0] -+ for reason in av.data[1:]: -+ rule.comment += "#\tPossible cause is the source %s and target %s are different." % reason - - try: - if ( av.type == audit2why.TERULE and -@@ -189,9 +189,9 @@ class PolicyGenerator: - if i not in self.domains: - types.append(i) - if len(types) == 1: -- rule.comment += "#!!!! The source type '%s' can write to a '%s' of the following type:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types)) -+ rule.comment += "\n#!!!! The source type '%s' can write to a '%s' of the following type:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types)) - elif len(types) >= 1: -- rule.comment += "#!!!! The source type '%s' can write to a '%s' of the following types:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types)) -+ rule.comment += "\n#!!!! The source type '%s' can write to a '%s' of the following types:\n# %s\n" % ( av.src_type, av.obj_class, ", ".join(types)) - except: - pass - self.module.children.append(rule) -diff --git a/sepolgen/src/sepolgen/refparser.py b/sepolgen/src/sepolgen/refparser.py -index 7b76261..a05d9d1 100644 ---- a/sepolgen/src/sepolgen/refparser.py -+++ b/sepolgen/src/sepolgen/refparser.py -@@ -65,6 +65,7 @@ tokens = ( - 'BAR', - 'EXPL', - 'EQUAL', -+ 'FILENAME', - 'IDENTIFIER', - 'NUMBER', - 'PATH', -@@ -249,11 +250,17 @@ def t_refpolicywarn(t): - t.lexer.lineno += 1 - - def t_IDENTIFIER(t): -- r'[a-zA-Z_\$\"][a-zA-Z0-9_\-\+\.\$\*\"~]*' -+ r'[a-zA-Z_\$][a-zA-Z0-9_\-\+\.\$\*~]*' - # Handle any keywords - t.type = reserved.get(t.value,'IDENTIFIER') - return t - -+def t_FILENAME(t): -+ r'\"[a-zA-Z0-9_\-\+\.\$\*~ :]+\"' -+ # Handle any keywords -+ t.type = reserved.get(t.value,'FILENAME') -+ return t -+ - def t_comment(t): - r'\#.*\n' - # Ignore all comments -@@ -450,6 +457,7 @@ def p_interface_call_param(p): - | nested_id_set - | TRUE - | FALSE -+ | FILENAME - ''' - # Intentionally let single identifiers pass through - # List means set, non-list identifier -@@ -461,6 +469,7 @@ def p_interface_call_param(p): - def p_interface_call_param_list(p): - '''interface_call_param_list : interface_call_param - | interface_call_param_list COMMA interface_call_param -+ | interface_call_param_list COMMA interface_call_param COMMA interface_call_param_list - ''' - if len(p) == 2: - p[0] = [p[1]] -@@ -787,6 +796,7 @@ def p_avrule_def(p): - - def p_typerule_def(p): - '''typerule_def : TYPE_TRANSITION names names COLON names IDENTIFIER SEMI -+ | TYPE_TRANSITION names names COLON names IDENTIFIER FILENAME SEMI - | TYPE_TRANSITION names names COLON names IDENTIFIER IDENTIFIER SEMI - | TYPE_CHANGE names names COLON names IDENTIFIER SEMI - | TYPE_MEMBER names names COLON names IDENTIFIER SEMI -@@ -800,6 +810,7 @@ def p_typerule_def(p): - t.tgt_types = p[3] - t.obj_classes = p[5] - t.dest_type = p[6] -+ t.file_name = p[7] - p[0] = t - - def p_bool(p): -diff --git a/sepolgen/tests/test_matching.py b/sepolgen/tests/test_matching.py -index 2282eca..ca3f871 100644 ---- a/sepolgen/tests/test_matching.py -+++ b/sepolgen/tests/test_matching.py -@@ -51,12 +51,12 @@ class TestMatchList(unittest.TestCase): - a = matching.Match() - a.dist = 100 - ml.append(a) -- self.assertEqual(len(ml), 1) -+ self.assertEqual(len(ml), 2) - - a = matching.Match() - a.dist = 200 - ml.append(a) -- self.assertEqual(len(ml), 1) -+ self.assertEqual(len(ml), 2) - self.assertEqual(len(ml.bastards), 1) - - ml.allow_info_dir_change = False -@@ -64,7 +64,7 @@ class TestMatchList(unittest.TestCase): - a.dist = 0 - a.info_dir_change = True - ml.append(a) -- self.assertEqual(len(ml), 1) -+ self.assertEqual(len(ml), 3) - self.assertEqual(len(ml.bastards), 2) - - def test_sort(self): diff --git a/policycoreutils.spec b/policycoreutils.spec index d167f99..aaf9073 100644 --- a/policycoreutils.spec +++ b/policycoreutils.spec @@ -127,6 +127,11 @@ an SELinux environment. %{python_sitearch}/sepolicy/manpage.py* %{python_sitearch}/sepolicy/network.py* %{python_sitearch}/sepolicy/transition.py* +%{python_sitearch}/sepolicy/sedbus.py* +%{_sysconfdir}/dbus-1/system.d/org.fedoraproject.selinux.conf +%{_datadir}/system-config-selinux/selinux_server.py +%{_datadir}/dbus-1/system/org.fedoraproject.selinux.service +%{_datadir}/polkit-1/actions/org.fedoraproject.selinux.policy %{python_sitearch}/%{name}*.egg-info %{python_sitearch}/sepolicy*.egg-info @@ -137,8 +142,8 @@ an SELinux environment. %{_mandir}/man8/sandbox.8* %{_mandir}/man8/semanage*.8* %{_mandir}/ru/man8/semanage.8* -%{_usr}/share/bash-completion/completions/semanage -%{_usr}/share/bash-completion/completions/setsebool +%{_datadir}/bash-completion/completions/semanage +%{_datadir}/bash-completion/completions/setsebool %package devel Summary: SELinux policy core policy devel utilities