From 495b754734bd647bd13c51650d19332b65dce326 Mon Sep 17 00:00:00 2001 From: Dan Walsh Date: Tue, 30 Aug 2011 11:08:49 -0400 Subject: [PATCH] Change matchpatcon to use proper myprintf Fix symlink_realpath to always include "/" Update to upstream * selinux_file_context_verify function returns wrong value. * move realpath helper to matchpathcon library * python wrapper makefile changes --- libselinux-rhat.patch | 509 ++++-------------------------------------- libselinux.spec | 12 +- 2 files changed, 56 insertions(+), 465 deletions(-) diff --git a/libselinux-rhat.patch b/libselinux-rhat.patch index e103180..cb9e54b 100644 --- a/libselinux-rhat.patch +++ b/libselinux-rhat.patch @@ -1,235 +1,3 @@ -diff --git a/libselinux/include/selinux/selinux.h b/libselinux/include/selinux/selinux.h -index f110dcf..d29b0c1 100644 ---- a/libselinux/include/selinux/selinux.h -+++ b/libselinux/include/selinux/selinux.h -@@ -566,7 +566,7 @@ extern int selinux_file_context_cmp(const security_context_t a, - - /* - * Verify the context of the file 'path' against policy. -- * Return 0 if correct. -+ * Return 1 if match, 0 if not and -1 on error. - */ - extern int selinux_file_context_verify(const char *path, mode_t mode); - -diff --git a/libselinux/man/man3/selinux_file_context_cmp.3 b/libselinux/man/man3/selinux_file_context_cmp.3 -index 51e8c20..cd67188 100644 ---- a/libselinux/man/man3/selinux_file_context_cmp.3 -+++ b/libselinux/man/man3/selinux_file_context_cmp.3 -@@ -1,25 +1,75 @@ --.TH "selinux_file_context_cmp" "3" "21 November 2009" "sds@tycho.nsa.gov" "SELinux API documentation" -+.TH "selinux_file_context_cmp" "3" "08 March 2011" "SELinux API documentation" -+ - .SH "NAME" --selinux_file_context_cmp, selinux_file_context_verify \- comparison of two file contexts. -+selinux_file_context_cmp \- Compare two SELinux security contexts excluding the 'user' component. - - .SH "SYNOPSIS" - .B #include - .sp -- --.BI "int selinux_file_context_cmp(const security_context_t " a ", const security_context_t " b ");" -- --.BI "int selinux_file_context_verify(const char *" path ", mode_t " mode ");" -+.BI "int selinux_file_context_cmp(const security_context_t " a ", " -+.RS -+.BI "const security_context_t " b ");" -+.RE - - .SH "DESCRIPTION" - .B selinux_file_context_cmp --compares two file contexts to see if their differences are "significant", the function runs the strcmp function ignoring the user componant of the file context. --.sp --.B selinux_file_context_verify --compares the file context on disk to the system default. -+compares two context strings excluding the user component with -+.B strcmp(3) -+as shown in the -+.B EXAMPLE -+section. - .sp -+This is useful as for most object contexts, the user component is not relevant. - - .SH "RETURN VALUE" --Returns zero on success or \-1 otherwise. -+The return values follow the -+.B strcmp(3) -+function, where: -+.RS -+0 if they are equal. -+.RE -+.RS -+1 if -+.I a -+is greater than -+.I b -+.RE -+.RS -+\-1 if -+.I a -+is less than -+.I b -+.RE -+ -+.SH "ERRORS" -+None. -+ -+.SH "NOTES" -+The contexts being compared do not specifically need to be file contexts. -+ -+.SH "EXAMPLE" -+If context -+.I a -+is: -+.RS -+user_u:user_r:user_t:s0 -+.RE -+.sp -+and context -+.I b -+is: -+.RS -+root:user_r:user_t:s0 -+.RE -+.sp -+then the actual strings compared are: -+.RS -+:user_r:user_t:s0 and :user_r:user_t:s0 -+.RE -+.sp -+Therefore they will match and -+.B selinux_file_context_cmp -+will return zero. - - .SH "SEE ALSO" --.BR selinux "(8), " selinux_lsetfilecon "(3), " matchpathcon "(3), " freecon "(3), " setfilecon "(3), " setfscreatecon "(3)" -+.BR selinux "(8)" -diff --git a/libselinux/man/man3/selinux_file_context_verify.3 b/libselinux/man/man3/selinux_file_context_verify.3 -index d777547..e22be70 100644 ---- a/libselinux/man/man3/selinux_file_context_verify.3 -+++ b/libselinux/man/man3/selinux_file_context_verify.3 -@@ -1 +1,98 @@ --.so man3/selinux_file_context_cmp.3 -+.TH "selinux_file_context_verify" "3" "08 March 2011" "SELinux API documentation" -+ -+.SH "NAME" -+selinux_file_context_verify \- Compare the SELinux security context on disk to the default security context required by the policy file contexts file. -+ -+.SH "SYNOPSIS" -+.B #include -+.sp -+.BI "int selinux_file_context_verify(const char *" path ", mode_t " mode ");" -+ -+.SH "DESCRIPTION" -+.B selinux_file_context_verify -+compares the context of the specified -+.I path -+that is held on disk (in the extended attribute), to the system default entry held in the file contexts series of files. -+.sp -+The -+.I mode -+may be zero. -+.sp -+Note that the two contexts are compared for "significant" differences (i.e. the user component of the contexts are ignored) as shown in the -+.B EXAMPLE -+section. -+ -+.SH "RETURN VALUE" -+If the contexts significantly match, 1 (one) is returned. -+.sp -+If the contexts do not match 0 (zero) is returned and -+.I errno -+is set to either -+.B ENOENT -+or -+.B EINVAL -+for the reasons listed in the -+.B ERRORS -+section, or if -+.I errno -+= 0 then the contexts did not match. -+.sp -+On failure \-1 is returned and -+.I errno -+set appropriately. -+ -+.SH "ERRORS" -+.TP -+.B ENOTSUP -+if extended attributes are not supported by the file system. -+.TP -+.B ENOENT -+if there is no entry in the file contexts series of files or -+.I path -+does not exist. -+.TP -+.B EINVAL -+if the entry in the file contexts series of files or -+.I path -+are invalid, or the returned context fails validation. -+.TP -+.B ENOMEM -+if attempt to allocate memory failed. -+ -+.SH "FILES" -+The following configuration files (the file contexts series of files) supporting the active policy will be used (should they exist) to determine the -+.I path -+default context: -+.sp -+.RS -+contexts/files/file_contexts - This file must exist. -+.sp -+contexts/files/file_contexts.local - If exists has local customizations. -+.sp -+contexts/files/file_contexts.homedirs - If exists has users home directory customizations. -+.sp -+contexts/files/file_contexts.subs - If exists has substitutions that are then applied to the 'in memory' version of the file contexts files. -+.RE -+ -+.SH "EXAMPLE" -+If the files context is: -+.RS -+unconfined_u:object_r:admin_home_t:s0 -+.RE -+.sp -+and the default context defined in the file contexts file is: -+.RS -+system_u:object_r:admin_home_t:s0 -+.RE -+.sp -+then the actual strings compared are: -+.RS -+:object_r:admin_home_t:s0 and :object_r:admin_home_t:s0 -+.RE -+.sp -+Therefore they will match and -+.B selinux_file_context_verify -+will return 1. -+ -+.SH "SEE ALSO" -+.BR selinux "(8)" -diff --git a/libselinux/src/Makefile b/libselinux/src/Makefile -index 15f7c1a..7680008 100644 ---- a/libselinux/src/Makefile -+++ b/libselinux/src/Makefile -@@ -10,7 +10,8 @@ LIBDIR ?= $(PREFIX)/lib - SHLIBDIR ?= $(PREFIX)/lib - INCLUDEDIR ?= $(PREFIX)/include - PYLIBVER ?= $(shell $(PYTHON) -c 'import sys;print("python%d.%d" % sys.version_info[0:2])') --PYINC ?= $(shell pkg-config --cflags `basename $(PYTHON)`) -+PYINC ?= $(shell pkg-config --cflags $(PYPREFIX)) -+PYTHONLIBDIR ?= $(shell pkg-config --libs $(PYPREFIX)) - PYLIBDIR ?= $(LIBDIR)/$(PYLIBVER) - RUBYLIBVER ?= $(shell ruby -e 'print RUBY_VERSION.split(".")[0..1].join(".")') - RUBYPLATFORM ?= $(shell ruby -e 'print RUBY_PLATFORM') -@@ -78,7 +79,7 @@ $(SWIGRUBYLOBJ): $(SWIGRUBYCOUT) - $(CC) $(filter-out -Werror, $(CFLAGS)) -I$(RUBYINC) -fPIC -DSHARED -c -o $@ $< - - $(SWIGSO): $(SWIGLOBJ) -- $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $< -L. -lselinux -L$(LIBDIR) -Wl,-soname,$@ -+ $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $< -L. -lselinux -L$(LIBDIR) $(PYTHONLIBDIR) -Wl,-soname,$@,-z,defs - - $(SWIGRUBYSO): $(SWIGRUBYLOBJ) - $(CC) $(CFLAGS) $(LDFLAGS) -shared -o $@ $^ -L. -lselinux -L$(LIBDIR) -Wl,-soname,$@ diff --git a/libselinux/src/callbacks.c b/libselinux/src/callbacks.c index b245364..7c47222 100644 --- a/libselinux/src/callbacks.c @@ -243,10 +11,10 @@ index b245364..7c47222 100644 rc = vfprintf(stderr, fmt, ap); va_end(ap); diff --git a/libselinux/src/matchpathcon.c b/libselinux/src/matchpathcon.c -index 5fd8fe4..410dd9d 100644 +index 9717b14..df83b30 100644 --- a/libselinux/src/matchpathcon.c +++ b/libselinux/src/matchpathcon.c -@@ -2,9 +2,11 @@ +@@ -2,6 +2,7 @@ #include #include #include @@ -254,11 +22,7 @@ index 5fd8fe4..410dd9d 100644 #include "selinux_internal.h" #include "label_internal.h" #include "callbacks.h" -+#include - - static __thread struct selabel_handle *hnd; - -@@ -61,7 +63,7 @@ static void +@@ -62,7 +63,7 @@ static void { va_list ap; va_start(ap, fmt); @@ -267,234 +31,53 @@ index 5fd8fe4..410dd9d 100644 va_end(ap); } -@@ -337,14 +339,82 @@ void matchpathcon_fini(void) - } - } +@@ -353,7 +354,7 @@ static int symlink_realpath(const char *name, char *resolved_path) --int matchpathcon(const char *name, mode_t mode, security_context_t * con) -+/* -+ * We do not want to resolve a symlink to a real path if it is the final -+ * component of the name. Thus we split the pathname on the last "/" and -+ * determine a real path component of the first portion. We then have to -+ * copy the last part back on to get the final real path. Wheww. -+ */ -+static int symlink_realpath(const char *name, char *resolved_path) -+{ -+ char *last_component; -+ char *tmp_path, *p; -+ size_t len = 0; -+ int rc = 0; -+ -+ tmp_path = strdup(name); -+ if (!tmp_path) { -+ fprintf(stderr, "symlink_realpath(%s) strdup() failed: %s\n", -+ name, strerror(errno)); -+ rc = -1; -+ goto out; -+ } -+ -+ last_component = strrchr(tmp_path, '/'); -+ -+ if (last_component == tmp_path) { -+ last_component++; -+ p = strcpy(resolved_path, "/"); -+ } else if (last_component) { -+ *last_component = '\0'; -+ last_component++; -+ p = realpath(tmp_path, resolved_path); -+ } else { -+ last_component = tmp_path; -+ p = realpath("./", resolved_path); -+ } -+ -+ if (!p) { -+ fprintf(stderr, "symlink_realpath(%s) realpath() failed: %s\n", -+ name, strerror(errno)); -+ rc = -1; -+ goto out; -+ } -+ -+ len = strlen(p); -+ if (len + strlen(last_component) + 1 > PATH_MAX) { -+ fprintf(stderr, "symlink_realpath(%s) failed: Filename too long \n", -+ name); -+ rc = -1; -+ goto out; -+ } -+ -+ resolved_path += len; -+ strcpy(resolved_path, last_component); -+out: -+ free(tmp_path); -+ return rc; -+} -+ -+int matchpathcon(const char *path, mode_t mode, security_context_t * con) - { -+ char stackpath[PATH_MAX + 1]; -+ char *p = NULL; - if (!hnd && (matchpathcon_init_prefix(NULL, NULL) < 0)) - return -1; - -+ if (S_ISLNK(mode)) { -+ if (!symlink_realpath(path, stackpath)) -+ path = stackpath; -+ } else { -+ p = realpath(path, stackpath); -+ if (p) -+ path = p; -+ } -+ - return notrans ? -- selabel_lookup_raw(hnd, con, name, mode) : -- selabel_lookup(hnd, con, name, mode); -+ selabel_lookup_raw(hnd, con, path, mode) : -+ selabel_lookup(hnd, con, path, mode); - } - - int matchpathcon_index(const char *name, mode_t mode, security_context_t * con) -@@ -394,7 +464,7 @@ int selinux_file_context_verify(const char *path, mode_t mode) - rc = lgetfilecon_raw(path, &con); - if (rc == -1) { - if (errno != ENOTSUP) -- return 1; -+ return -1; - else - return 0; - } -@@ -404,11 +474,18 @@ int selinux_file_context_verify(const char *path, mode_t mode) - - if (selabel_lookup_raw(hnd, &fcontext, path, mode) != 0) { - if (errno != ENOENT) -- rc = 1; -+ rc = -1; - else - rc = 0; -- } else -+ } else { -+ /* -+ * Need to set errno to 0 as it can be set to ENOENT if the -+ * file_contexts.subs file does not exist (see selabel_open in -+ * label.c), thus causing confusion if errno is checked on return. -+ */ -+ errno = 0; - rc = (selinux_file_context_cmp(fcontext, con) == 0); -+ } - - freecon(con); - freecon(fcontext); -diff --git a/libselinux/utils/matchpathcon.c b/libselinux/utils/matchpathcon.c -index 3ecd52f..5f0a4c2 100644 ---- a/libselinux/utils/matchpathcon.c -+++ b/libselinux/utils/matchpathcon.c -@@ -43,63 +43,6 @@ int printmatchpathcon(char *path, int header, int mode) - return 0; - } - --/* -- * We do not want to resolve a symlink to a real path if it is the final -- * component of the name. Thus we split the pathname on the last "/" and -- * determine a real path component of the first portion. We then have to -- * copy the last part back on to get the final real path. Wheww. -- */ --static int symlink_realpath(char *name, char *resolved_path) --{ -- char *last_component; -- char *tmp_path, *p; -- size_t len = 0; -- int rc = 0; -- -- tmp_path = strdup(name); -- if (!tmp_path) { + tmp_path = strdup(name); + if (!tmp_path) { - fprintf(stderr, "symlink_realpath(%s) strdup() failed: %s\n", -- name, strerror(errno)); -- rc = -1; -- goto out; -- } -- -- last_component = strrchr(tmp_path, '/'); -- -- if (last_component == tmp_path) { -- last_component++; -- p = strcpy(resolved_path, "/"); -- } else if (last_component) { -- *last_component = '\0'; -- last_component++; -- p = realpath(tmp_path, resolved_path); -- } else { -- last_component = tmp_path; -- p = realpath("./", resolved_path); -- } -- -- if (!p) { ++ myprintf("symlink_realpath(%s) strdup() failed: %s\n", + name, strerror(errno)); + rc = -1; + goto out; +@@ -374,21 +375,24 @@ static int symlink_realpath(const char *name, char *resolved_path) + } + + if (!p) { - fprintf(stderr, "symlink_realpath(%s) realpath() failed: %s\n", -- name, strerror(errno)); -- rc = -1; -- goto out; -- } -- -- len = strlen(p); ++ myprintf("symlink_realpath(%s) realpath() failed: %s\n", + name, strerror(errno)); + rc = -1; + goto out; + } + + len = strlen(p); - if (len + strlen(last_component) + 1 > PATH_MAX) { - fprintf(stderr, "symlink_realpath(%s) failed: Filename too long \n", -- name); -- rc = -1; -- goto out; -- } -- -- resolved_path += len; -- strcpy(resolved_path, last_component); --out: -- free(tmp_path); -- return rc; --} -- ++ if (len + strlen(last_component) + 2 > PATH_MAX) { ++ myprintf("symlink_realpath(%s) failed: Filename too long \n", + name); ++ errno=ENAMETOOLONG; + rc = -1; + goto out; + } + + resolved_path += len; ++ strcpy(resolved_path, "/"); ++ resolved_path += 1; + strcpy(resolved_path, last_component); + out: + free(tmp_path); +diff --git a/libselinux/utils/matchpathcon.c b/libselinux/utils/matchpathcon.c +index 2fa21bc..5f0a4c2 100644 +--- a/libselinux/utils/matchpathcon.c ++++ b/libselinux/utils/matchpathcon.c +@@ -45,7 +45,7 @@ int printmatchpathcon(char *path, int header, int mode) + int main(int argc, char **argv) { - int i, init = 0; -@@ -166,8 +109,7 @@ int main(int argc, char **argv) - for (i = optind; i < argc; i++) { - int rc, mode = 0; - struct stat buf; -- char *p, *path = argv[i]; -- char stackpath[PATH_MAX + 1]; -+ char *path = argv[i]; - int len = strlen(path); - if (len > 1 && path[len - 1 ] == '/') - path[len - 1 ] = '\0'; -@@ -175,31 +117,23 @@ int main(int argc, char **argv) - if (lstat(path, &buf) == 0) - mode = buf.st_mode; - -- if (S_ISLNK(mode)) { -- rc = symlink_realpath(path, stackpath); -- if (!rc) -- path = stackpath; -- } else { -- p = realpath(path, stackpath); -- if (p) -- path = p; -- } -- - if (verify) { - rc = selinux_file_context_verify(path, mode); - - if (quiet) { -- if (rc) -+ if (rc == 1) - continue; - else - exit(1); - } - -- if (rc) { -+ if (rc == -1) { -+ printf("%s error: %s\n", path, strerror(errno)); -+ exit(1); -+ } else if (rc == 1) { - printf("%s verified.\n", path); - } else { - security_context_t con; -- int rc; - error = 1; - if (notrans) - rc = lgetfilecon_raw(path, &con); +- int i, init = 0, rc = 0; ++ int i, init = 0; + int header = 1, opt; + int verify = 0; + int notrans = 0; diff --git a/libselinux.spec b/libselinux.spec index 958a277..b205ab0 100644 --- a/libselinux.spec +++ b/libselinux.spec @@ -6,8 +6,8 @@ Summary: SELinux library and simple utilities Name: libselinux -Version: 2.1.4 -Release: 2%{?dist} +Version: 2.1.5 +Release: 1%{?dist} License: Public Domain Group: System Environment/Libraries Source: %{name}-%{version}.tgz @@ -233,6 +233,14 @@ exit 0 %{ruby_sitearch}/selinux.so %changelog +* Tue Aug 30 2011 Dan Walsh - 2.1.5-1 +- Change matchpatcon to use proper myprintf +- Fix symlink_realpath to always include "/" +- Update to upstream + * selinux_file_context_verify function returns wrong value. + * move realpath helper to matchpathcon library + * python wrapper makefile changes + * Mon Aug 22 2011 Dan Walsh - 2.1.4-2 - Move to new Makefile that can build with or without PYTHON being set