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

Dmitry V. Levin ldv at altlinux.org
Mon Jan 3 00:47:19 UTC 2022


On Sun, Jan 02, 2022 at 08:00:04PM +0100, Renaud Métrich wrote:
[...]
> @@ -97,7 +155,33 @@ 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;
> +	buf[n] = '\0';
> +
> +	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(expected);
> +	free(*result);
> +	*result = final_result;
> +	return 0;
>  }
>  
>  /*
> @@ -108,29 +192,56 @@ selinux_getfdcon(pid_t pid, int fd, char **result)
>  int
>  selinux_getfilecon(struct tcb *tcp, const char *path, char **result)
>  {
> -	if (!selinux_context)
> +	if (number_set_array_is_empty(secontext_set, 0))
>  		return -1;
>  
>  	int proc_pid = get_proc_pid(tcp->pid);
>  	if (!proc_pid)
>  		return -1;
>  
> -	int ret = -1;
> +	int rc = -1;
>  	char fname[PATH_MAX];
>  
>  	if (path[0] == '/')
> -		ret = snprintf(fname, sizeof(fname), "/proc/%u/root%s",
> +		rc = snprintf(fname, sizeof(fname), "/proc/%u/root%s",
>  			       proc_pid, path);
>  	else if (tcp->last_dirfd == AT_FDCWD)
> -		ret = snprintf(fname, sizeof(fname), "/proc/%u/cwd/%s",
> +		rc = snprintf(fname, sizeof(fname), "/proc/%u/cwd/%s",
>  			       proc_pid, path);
>  	else if (tcp->last_dirfd >= 0 )
> -		ret = snprintf(fname, sizeof(fname), "/proc/%u/fd/%u/%s",
> +		rc = snprintf(fname, sizeof(fname), "/proc/%u/fd/%u/%s",
>  			       proc_pid, tcp->last_dirfd, path);
>  
> -	if ((unsigned int) ret >= sizeof(fname))
> +	if ((unsigned int) rc >= sizeof(fname))
>  		return -1;
>  
>  	char *secontext;
> -	return getcontext(getfilecon(fname, &secontext), &secontext, result);
> +	rc = getcontext(getfilecon(fname, &secontext), &secontext, result);
> +	if (rc == -1 || !is_number_in_set(SECONTEXT_MISMATCH, secontext_set))
> +		return rc;
> +
> +	/*
> +	 * We need to fully resolve the path, because selabel_lookup() doesn't
> +	 * resolve anything. Using realpath() is the only solution here to make
> +	 * sure the path is canonicalized.
> +	 */
> +
> +	char *resolved = realpath(fname, NULL);
> +	if (!resolved)
> +		return -1;

Is it correct to return -1 here, that is, to avoid printing context?
For comparison, selinux_getfdcon returns 0 when readlink fails.

[...]
>  char *
> -secontext_full_file(const char *filename)
> +secontext_full_file(const char *filename, bool mismatch)
>  {
> -	return FORMAT_SPACE_BEFORE(raw_secontext_full_file(filename));
> +	char *context = raw_secontext_full_file(filename);
> +	if (mismatch) {
> +		char *expected = raw_expected_secontext_full_file(filename);
> +		if (expected && strcmp(context, expected) != 0) {

What if context == NULL here?


-- 
ldv


More information about the Strace-devel mailing list