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
This commit is contained in:
Dan Walsh 2011-08-30 11:08:49 -04:00
parent 4eca5fc79f
commit 495b754734
2 changed files with 56 additions and 465 deletions

View File

@ -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 <selinux/selinux.h>
.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 <selinux/selinux.h>
+.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 <string.h>
#include <errno.h>
#include <stdio.h>
@ -254,11 +22,7 @@ index 5fd8fe4..410dd9d 100644
#include "selinux_internal.h"
#include "label_internal.h"
#include "callbacks.h"
+#include <limits.h>
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;

View File

@ -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 <dwalsh@redhat.com> - 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 <dwalsh@redhat.com> - 2.1.4-2
- Move to new Makefile that can build with or without PYTHON being set