[PATCH] --secontext: Implement displaying of expected context upon mismatch

Renaud Métrich rmetrich at redhat.com
Sun Jan 2 19:00:04 UTC 2022


Hello Dmitry,

Please find attached the "fixed" patch.

And inline for comments.

On 12/29/21 23:55, Dmitry V. Levin wrote:
> On Wed, Dec 29, 2021 at 02:33:06PM +0100, Renaud Métrich wrote:
>> Attached is the updated patch with all comments.
> [...]
>> --- a/NEWS
>> +++ b/NEWS
>> @@ -3,6 +3,8 @@ Noteworthy changes in release ?.?? (????-??-??)
>>   
>>   * Improvements
>>     * Updated lists of ioctl commands from Linux 5.16.
>> +  * Implemented --secontext=mismatch option to find mismatches in SELinux
>> +    contexts.
> If you have a look at the NEWS file, you'll see that almost every
> "Improvements" section ends with "Updated lists of ioctl commands" line.
> Let's keep this tradition, please add your line before rather than after
> that line.
OK
> [...]
>> @@ -259,8 +259,9 @@ is one of
>>   .BR inject ,
>>   .BR status ,
>>   .BR quiet " (or " silent " or " silence " or " q ),
>> +.if '@ENABLE_SECONTEXT_FALSE@'#' .BR secontext ,
>>   .BR decode\-fds " (or " decode\-fd ),
>> -.BR decode\-pids " (or " decode\-pid ),
>> +.BR decode\-pids " (or " decode\-pid )
>>   or
>>   .BR kvm ,
>>   and
> Please do not remove that serial comma.
Restored.
> [...]
>> @@ -1166,13 +1167,33 @@ strace's namespace, too.
>>   .BR \-\-decode\-pids = comm
>>   Print command names for PIDs.
>>   .if '@ENABLE_SECONTEXT_FALSE@'#' .TP
>> -.if '@ENABLE_SECONTEXT_FALSE@'#' .BR \-\-secontext [= full ]
>> +.if '@ENABLE_SECONTEXT_FALSE@'#' .BR \-\-secontext\fR[=\fIformat\fR]
>> +.if '@ENABLE_SECONTEXT_FALSE@'#' .TQ
>> +.if '@ENABLE_SECONTEXT_FALSE@'#' .BR \-e\ secontext\fR=\fIformat\fR
>>   .if '@ENABLE_SECONTEXT_FALSE@'#' When SELinux is available and is not disabled,
>>   .if '@ENABLE_SECONTEXT_FALSE@'#' print in square brackets SELinux contexts of
>> -.if '@ENABLE_SECONTEXT_FALSE@'#' processes, files, and descriptors.  When
>> -.if '@ENABLE_SECONTEXT_FALSE@'#' .B full
>> -.if '@ENABLE_SECONTEXT_FALSE@'#' is specified, print the complete context (user,
>> -.if '@ENABLE_SECONTEXT_FALSE@'#' role, type and category) instead of just the type.
>> +.if '@ENABLE_SECONTEXT_FALSE@'#' processes, files, and descriptors.  The
>> +.if '@ENABLE_SECONTEXT_FALSE@'#' .I format
>> +.if '@ENABLE_SECONTEXT_FALSE@'#' argument is a comma-separated list of with items
>> +.if '@ENABLE_SECONTEXT_FALSE@'#' being one of the following:
> Sorry, a comma-separated list of what?
I fixed this as " a comma-separated list of items being ..."
> [...]
>> +static int
>> +get_expected_filecontext(const char *realpath, char **result)
>> +{
>> +	static struct selabel_handle *hdl = NULL;
>> +	static bool disabled = false;
>> +
>> +	if (disabled)
>> +		return -1;
>> +
>> +	if (!hdl) {
>> +		hdl = selabel_open(SELABEL_CTX_FILE, NULL, 0);
>> +		if (!hdl) {
>> +			perror_msg("could not open SELinux database, disabling "
>> +				   "context mismatch checking");
> Just an idea, maybe it would be more useful to print the file name
> instead of "SELinux database".
That cannot be: SELABEL_CTX_FILE is not a filename but an opaque number 
to select the right database. See /usr/include/selinux/label.h
>> +			disabled = true;
>> +			return -1;
>> +		}
>> +	}
>> +
>> +	struct stat statbuf;
>> +	if (stat(realpath, &statbuf) == -1) {
>> +		return -1;
>> +	}
> When checking a syscall return code, I usually prefer "< 0" to "== -1".
> In most cases there is no practical difference, so it's a matter of
> style rather than correctness.
OK
> [...]
>> @@ -97,7 +155,32 @@ selinux_getfdcon(pid_t pid, int fd, char **result)
>>   	xsprintf(linkpath, "/proc/%u/fd/%u", proc_pid, fd);
>>   
>>   	char *secontext;
>> -	return getcontext(getfilecon(linkpath, &secontext), &secontext, result);
>> +	int rc = getcontext(getfilecon(linkpath, &secontext), &secontext, result);
>> +	if (rc == -1 || !is_number_in_set(SECONTEXT_MISMATCH, secontext_set))
>> +		return rc;
>> +
>> +	/*
>> +	 * We need to resolve the path, because selabel_lookup() doesn't
>> +	 * resolve anything. Using readlink() is sufficient here.
>> +	 */
>> +
>> +	char buf[PATH_MAX];
>> +	ssize_t n = readlink(linkpath, buf, sizeof(buf));
>> +	if ((size_t) n >= sizeof(buf))
>> +		return 0;
> As readlink() does not append a terminating null byte to buf,
> it has to be added explicitly, e.g.
>
> 	buf[n] = '\0';
My bad ... got fooled again by this weird behaviour.
>> +	char *expected;
>> +	if (get_expected_filecontext(buf, &expected) == -1)
>> +		return 0;
>> +	if (strcmp(expected, *result) == 0) {
>> +		free(expected);
>> +		return 0;
>> +	}
>> +	char *final_result = xasprintf("%s!!%s", *result, expected);
>> +	free(*result);
>> +	free(expected);
>> +	*result = final_result;
> Please reorder free(*result) and free(expected), it would look a bit
> nicer this way:
>
> 	free(expected);
> 	free(*result);
> 	*result = final_result;
OK
> [...]
>> --- a/tests/linkat.c
>> +++ b/tests/linkat.c
>> @@ -15,6 +15,9 @@
>>   #include <stdlib.h>
>>   #include <unistd.h>
>>   #include <sys/stat.h>
>> +#ifdef PRINT_SECONTEXT_MISMATCH
>> +# include <string.h>
>> +#endif
> To be honest, I wouldn't bother ifdef'ing inclusion of this basic header.
OK
> [...]
>> +static char *
>> +raw_expected_secontext_full_file(const char *filename)
>> +{
>> +	int saved_errno = errno;
>> +	char *secontext;
>> +
>> +	static struct selabel_handle *hdl = NULL;
> No need to explicitly initialize static pointers with NULL.
OK, but thought it was more clear.
>> +	if (!hdl) {
>> +		hdl = selabel_open(SELABEL_CTX_FILE, NULL, 0);
>> +		if (!hdl)
>> +			perror_msg_and_skip("selabel_open");
> Let's add the file name to this diagnostics, e.g.
>
> 			perror_msg_and_skip("selabel_open: %s",
> 					    SELABEL_CTX_FILE);
See above, it's an opaque number, not a filename.
>> +	}
>> +
>> +	char *resolved = realpath(filename, NULL);
>> +	if (!resolved)
>> +		perror_msg_and_fail("realpath");
> Likewise, let's add the file name to this diagnostics, e.g.
>
> 		perror_msg_and_fail("realpath: %s", filename);
OK & for the rest as well.
>> +	struct stat statbuf;
>> +	if (stat(resolved, &statbuf) == -1)
>> +		perror_msg_and_fail("stat");
> Likewise, let's add the file name to this diagnostics, e.g.
>
> 		perror_msg_and_fail("stat: %s", resolved);
>
>> +	if (selabel_lookup(hdl, &secontext, resolved, statbuf.st_mode) == -1)
>> +		perror_msg_and_skip("selabel_lookup");
> Likewise, let's add the file name to this diagnostics, e.g.
>
> 		perror_msg_and_skip("selabel_lookup: %s", resolved);
>
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-Implement-displaying-of-expected-context-upon-mismat.patch
Type: text/x-patch
Size: 37246 bytes
Desc: not available
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20220102/a6243349/attachment.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: OpenPGP_signature
Type: application/pgp-signature
Size: 840 bytes
Desc: OpenPGP digital signature
URL: <http://lists.strace.io/pipermail/strace-devel/attachments/20220102/a6243349/attachment-0001.bin>


More information about the Strace-devel mailing list