Re: selinux_file_context_verify function returns wrong value.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



I thought I would have a go at fixing the problem so here is a patch that may be acceptable. I've tested it on libselinux 2.0.98 and 2.0.99.

selinux_file_context_verify(3) should now return the correct codes and matchpathcon(8) has been modified to handle them.

The selinux_file_context_verify(3)and selinux_file_context_cmp(3) man pages have also been updated (re-written really) to correct return codes.

I found that selabel_open left errno set to ENOENT because a file_contexts.subs file did not exist on my system, but left selabel_open alone and set errno = 0 before calling selinux_filecontext_cmp.


diff --git a/include/selinux/selinux.h b/include/selinux/selinux.h
index 0725b57..6627f7d 100644
--- a/include/selinux/selinux.h
+++ b/include/selinux/selinux.h
@@ -562,7 +562,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/man/man3/selinux_file_context_cmp.3 b/man/man3/selinux_file_context_cmp.3
index 51e8c20..048ef45 100644
--- a/man/man3/selinux_file_context_cmp.3
+++ b/man/man3/selinux_file_context_cmp.3
@@ -1,25 +1,76 @@
-.TH "selinux_file_context_cmp" "3" "21 November 2009" "sds@xxxxxxxxxxxxx" "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/man/man3/selinux_file_context_verify.3 b/man/man3/selinux_file_context_verify.3
index d777547..fcc716d 100644
--- a/man/man3/selinux_file_context_verify.3
+++ b/man/man3/selinux_file_context_verify.3
@@ -1 +1,99 @@
-.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/src/matchpathcon.c b/src/matchpathcon.c
index bb4eb9f..7e7be9a 100644
--- a/src/matchpathcon.c
+++ b/src/matchpathcon.c
@@ -386,7 +386,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;
 	}
@@ -396,11 +396,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/utils/matchpathcon.c b/utils/matchpathcon.c
index 4453a88..ff98f0a 100644
--- a/utils/matchpathcon.c
+++ b/utils/matchpathcon.c
@@ -41,7 +41,7 @@ int printmatchpathcon(char *path, int header, int mode)
 
 int main(int argc, char **argv)
 {
-	int i, init = 0;
+	int i, init, rc = 0;
 	int header = 1, opt;
 	int verify = 0;
 	int notrans = 0;
@@ -115,16 +115,20 @@ int main(int argc, char **argv)
 
 		if (verify) {
 			if (quiet) {
-				if (selinux_file_context_verify(argv[i], mode))
+				if ((rc = selinux_file_context_verify(argv[i], mode)) == 1)
 					continue;
 				else
 					exit(1);
 			}
-			if (selinux_file_context_verify(argv[i], mode)) {
+
+			rc = selinux_file_context_verify(argv[i], mode);
+			if (rc == -1) {
+				printf("%s error: %s\n", argv[i], strerror(errno));
+				exit(1);
+			} else if (rc == 1)
 				printf("%s verified.\n", argv[i]);
-			} else {
+			else {
 				security_context_t con;
-				int rc;
 				error = 1;
 				if (notrans)
 					rc = lgetfilecon_raw(argv[i], &con);



Richard

--- On Wed, 16/2/11, Stephen Smalley <sds@xxxxxxxxxxxxx> wrote:

> From: Stephen Smalley <sds@xxxxxxxxxxxxx>
> Subject: Re: selinux_file_context_verify function returns wrong value.
> To: "Richard Haines" <richard_c_haines@xxxxxxxxxxxxxx>
> Cc: selinux@xxxxxxxxxxxxx, "Daniel J Walsh" <dwalsh@xxxxxxxxxx>
> Date: Wednesday, 16 February, 2011, 18:25
> On Mon, 2011-02-14 at 15:56 +0000,
> Richard Haines wrote:
> > The selinux_file_context_verify seems to return the
> wrong value when I
> > know the context of the file and that in the
> file_contexts file are
> > the same (returns '1' but according to man page should
> be '0').
> >  
> > Looking at the libselinux source code (matchpathcon.c)
> the line:
> >  
> >        rc =
> (selinux_file_context_cmp(fcontext, con) == 0);
> >  
> > seems the problem.
> >  
> > I'm using libselinux 2.0.96
> >  
> > So should it return 0 on match, 1 if contexts are
> different (or if the
> > file / file_contexts entries do not exist) and -1 on
> error.
> >  
> > And just to clarify the selinux_file_context_cmp
> function return
> > values:
> >  
> >      Should it return 0 on match (after
> the 'user:' portion), 1 if
> > contexts do not match and -1 on error.
> >  
> > Thanks
> > Richard
> >  
> 
> Looks like a bug in the man page, combined with
> inconsistent return
> values on certain error paths within the code.  It
> looks like the intent
> was for selinux_file_context_verify() to return 1 if they
> match, 0 if
> they do not match, and -1 on error.  However:
> a) that isn't what the man page says,
> b) there is some special case handling of ENOTSUP and
> ENOENT internally
> that looks suspect to me, and
> c) utils/matchpathcon.c doesn't check for < 0
> 
> selinux_file_context_cmp is a bit simpler - it just follows
> strcmp
> conventions, i.e. -1 for "less than", 0 for equal, and 1
> for "greater
> than".
> 
> Dan?
> 
> 
> -- 
> Stephen Smalley
> National Security Agency
> 
> 


--
This message was distributed to subscribers of the selinux mailing list.
If you no longer wish to subscribe, send mail to majordomo@xxxxxxxxxxxxx with
the words "unsubscribe selinux" without quotes as the message.


[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux