Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!
Bug 777267 - app-admin/sudo[secure-path]: sudo sets /usr/local/bin and /usr/local/sbin after other */*bin in PATH
Summary: app-admin/sudo[secure-path]: sudo sets /usr/local/bin and /usr/local/sbin aft...
Status: RESOLVED FIXED
Alias: None
Product: Gentoo Linux
Classification: Unclassified
Component: Current packages (show other bugs)
Hardware: All Linux
: Normal normal (vote)
Assignee: Gentoo's Team for Core System packages
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2021-03-19 14:14 UTC by konsolebox
Modified: 2021-03-21 15:12 UTC (History)
1 user (show)

See Also:
Package list:
Runtime testing required: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description konsolebox 2021-03-19 14:14:42 UTC
To produce, run `sudo -u user bash -c 'declare -p PATH'`.

The value of PATH would begin with this: '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/opt/bin'

This is unintuitive and is inconsistent with the default value of ROOTPATH which is '/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin'.

If one would create wrappers or different versions of a binary in /usr/local/*bin, they would expect them to execute first regardless if sudo is being used or not.

The code responsible for this can be found in sudo's ebuild:

set_secure_path() {
	# FIXME: secure_path is a compile time setting. using PATH or
	# ROOTPATH is not perfect, env-update may invalidate this, but until it
	# is available as a sudoers setting this will have to do.
	einfo "Setting secure_path ..."

	# first extract the default ROOTPATH from build env
	SECURE_PATH=$(unset ROOTPATH; . "${EPREFIX}"/etc/profile.env;
		echo "${ROOTPATH}")
		case "${SECURE_PATH}" in
			*/usr/sbin*) ;;
			*) SECURE_PATH=$(unset PATH;
				. "${EPREFIX}"/etc/profile.env; echo "${PATH}")
				;;
		esac
	if [[ -z ${SECURE_PATH} ]] ; then
		ewarn "	Failed to detect SECURE_PATH, please report this"
	fi

	# then remove duplicate path entries
	cleanpath() {
		local newpath thisp IFS=:
		for thisp in $1 ; do
			if [[ :${newpath}: != *:${thisp}:* ]] ; then
				newpath+=:${thisp}
			else
				einfo "   Duplicate entry ${thisp} removed..."
			fi
		done
		SECURE_PATH=${newpath#:}
	}
	cleanpath /bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:/opt/bin${SECURE_PATH:+:${SECURE_PATH}}

	# finally, strip gcc paths #136027
	rmpath() {
		local e newpath thisp IFS=:
		for thisp in ${SECURE_PATH} ; do
			for e ; do [[ ${thisp} == ${e} ]] && continue 2 ; done
			newpath+=:${thisp}
		done
		SECURE_PATH=${newpath#:}
	}
	rmpath '*/gcc-bin/*' '*/gnat-gcc-bin/*' '*/gnat-gcc/*'

	einfo "... done"
}
Comment 1 konsolebox 2021-03-19 16:32:33 UTC
The set_secure_path function can be made simpler like this:

set_secure_path() {
	einfo "Setting secure_path ..."

	SECURE_PATH=$(unset ROOTPATH; . "${EPREFIX}"/etc/profile.env; echo "${ROOTPATH}")
	[[ ${SECURE_PATH} != */usr/sbin* ]] && SECURE_PATH=$(unset PATH; . "${EPREFIX}"/etc/profile.env;
			echo "${PATH}")

	local IFS=: __
	set -- /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin /opt/bin ${SECURE_PATH}
	SECURE_PATH=

	for __; do
		case $__ in
		''|*/gcc-bin/*|*/gnat-gcc-bin/*|*/gnat-gcc/*)
			;;
		*)
			[[ :${SECURE_PATH}: != *:"$__":* ]] && SECURE_PATH+=:$__
			;;
		esac
	done

	SECURE_PATH=${SECURE_PATH#:}
	einfo "... done"
}
Comment 2 Ionen Wolkens gentoo-dev 2021-03-19 20:49:22 UTC
Not up to me but note that, if unspecified, sudo upstream also starts with /bin and doesn't even add /usr/local at all when using optional --with-secure-path.
Comment 3 konsolebox 2021-03-19 21:48:46 UTC
As I've tested earlier, the value of PATH when secure-path is disabled, is set to the PATH of calling environment (as root).  I only haven't tested it as a user.  But point is if there's going be a default value for PATH set through --with-secure-path, better just base it on ROOTPATH.
Comment 4 konsolebox 2021-03-19 23:27:07 UTC
Here's an example output of sudo with secure-path disabled.

# declare -p PATH; sudo -u (user) bash -c 'declare -p PATH'                                              
declare -x PATH="/home/base/.gem/ruby/2.6.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin:/usr/lib/llvm/11/bin:/write/sbin:/write/bin:/usr/games/bin"
declare -x PATH="/home/base/.gem/ruby/2.6.0/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin:/usr/lib/llvm/11/bin:/write/sbin:/write/bin:/usr/games/bin

As you can see, bash not having the -l option just inherits the value of the calling environment's PATH where /usr/local/*bin come first.

This idea that sudo upstream starts with /bin needs to be verified as it might simply be caused by the shell or something else not exactly sudo.
Comment 5 konsolebox 2021-03-20 11:53:07 UTC
I just found out that secure_path can be configured via /etc/sudoers thanks to ggabriel.  I didn't see it in my first attempt to grep /etc, and the configuration was found in /etc/sudoers.dist.  The phrase " but until it is available as a sudoers setting this will have to do." also made me think the configuration wasn't available.

Anyway this is my final solution for this, but I'm not closing this bug yet since I believe even this compile-time default should still be corrected.

---------- /etc/portage/bashrc ----------

if [[ ${CATEGORY} == app-admin && ${PN} == sudo ]]; then
	set_secure_path() {
		SECURE_PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin
	}
fi

---------- /usr/local/sbin ----------

#!/bin/bash

set -f

update_secure_path() {
	local secure_path=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/opt/bin
	local extra_path=$(unset ROOTPATH; . "${EPREFIX}"/etc/profile.env; echo "${ROOTPATH}")

	if [[ ${extra_path} != */usr/sbin* ]]; then
		extra_path=$(unset PATH; . "${EPREFIX}"/etc/profile.env; echo "${PATH}")
	fi

	local IFS=: __
	set -- ${extra_path}

	for __; do
		case $__ in
		''|*/gcc-bin/*|*/gnat-gcc-bin/*|*/gnat-gcc/*)
			;;
		*)
			[[ :${secure_path}: != *:"$__":* ]] && secure_path+=:$__
			;;
		esac
	done

	printf 'Defaults secure_path="%s"\n' "${secure_path}" > /etc/sudoers.d/secure_path
}

function main {
	local PATH=${PATH}:/lib/rc/bin

	einfo "Calling /usr/sbin/env-update ... "
	/usr/sbin/env-update
	eend "$?" || return

	einfo "Updating /etc/sudoers.d/secure_path ... "
	update_secure_path
	eend "$?"
}

main
Comment 6 konsolebox 2021-03-20 12:20:58 UTC
By the way please don't make env-update updating /etc/sudoers.d/secure_path a hardcoded solution as it would be difficult to customize.  Maybe just save it in /etc/sudoers.secure_path instead and allow user to include it if they like (or if enabled by default, allow them to disable).
Comment 7 konsolebox 2021-03-20 15:14:12 UTC
I created a request to make env-update call post-update scripts in https://bugs.gentoo.org/777393.  If this gets granted, app-admin/sudo can install its own post-update script that updates /etc/sudoers.d/secure_path.  I like the method since I can easily customize the script, or disable it by remove the exec bit if I want to.
Comment 8 Larry the Git Cow gentoo-dev 2021-03-21 15:06:21 UTC
The bug has been closed via the following commit(s):

https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=45fd59bda6eaec275f44ecba6cd5b8a29cfb535f

commit 45fd59bda6eaec275f44ecba6cd5b8a29cfb535f
Author:     Mike Gilbert <floppym@gentoo.org>
AuthorDate: 2021-03-21 15:02:51 +0000
Commit:     Mike Gilbert <floppym@gentoo.org>
CommitDate: 2021-03-21 15:06:06 +0000

    app-admin/sudo: re-order default secure_path
    
    Match the order from baselayout.
    
    Closes: https://bugs.gentoo.org/777267
    Signed-off-by: Mike Gilbert <floppym@gentoo.org>

 app-admin/sudo/{sudo-1.9.6_p1.ebuild => sudo-1.9.6_p1-r1.ebuild} | 3 ++-
 app-admin/sudo/sudo-9999.ebuild                                  | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)
Comment 9 Larry the Git Cow gentoo-dev 2021-03-21 15:12:41 UTC
The bug has been referenced in the following commit(s):

https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=786ecd5f4c84942af2dc178c2ac9fcaab224a7c9

commit 786ecd5f4c84942af2dc178c2ac9fcaab224a7c9
Author:     Mike Gilbert <floppym@gentoo.org>
AuthorDate: 2021-03-21 15:09:41 +0000
Commit:     Mike Gilbert <floppym@gentoo.org>
CommitDate: 2021-03-21 15:09:41 +0000

    app-admin/sudo: remove obsolete comments
    
    The built-in secure_path should be viewed as a reasonable fallback.
    The sysadmin may in fact customize it via sudoers at runtime.
    
    Also drop the useless einfo output: this function takes a fraction of a
    second to complete, and there is no need for a status message.
    
    Bug: https://bugs.gentoo.org/777267
    Signed-off-by: Mike Gilbert <floppym@gentoo.org>

 app-admin/sudo/sudo-1.9.6_p1-r1.ebuild | 7 -------
 app-admin/sudo/sudo-9999.ebuild        | 7 -------
 2 files changed, 14 deletions(-)