Re: selinux_file_context_verify function returns wrong value.

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

 



-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On 03/09/2011 11:34 AM, Richard Haines wrote:
> 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.
> 
> 
Patch looks good to me.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.11 (GNU/Linux)
Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/

iEYEARECAAYFAk1459kACgkQrlYvE4MpobOTUwCg0GzXn30xUVCTFHxuvBfc1DQF
qCcAnRN4XC9rljBLw1Rj2yi9oRhiTIfW
=LMXf
-----END PGP SIGNATURE-----

--
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