Instead of clobbering the entire file mode, just toggle the suid bit if
needed. In most cases this will result in a world-readable file.

Introduce the FCAPS_DENY_WORLD_READ setting for users who insist on
having their suid binaries unreadable.

Skip calling chown/chmod if the owner/mode is empty. This may be used by
ebuild authors in certain use cases.

Bug: https://bugs.gentoo.org/938164
Signed-off-by: Mike Gilbert <flop...@gentoo.org>
---
 eclass/fcaps.eclass | 35 ++++++++++++++++++++++++++---------
 1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/eclass/fcaps.eclass b/eclass/fcaps.eclass
index 477e1e954ab8..5cb781a7a75d 100644
--- a/eclass/fcaps.eclass
+++ b/eclass/fcaps.eclass
@@ -1,4 +1,4 @@
-# Copyright 1999-2023 Gentoo Authors
+# Copyright 1999-2024 Gentoo Authors
 # Distributed under the terms of the GNU General Public License v2
 
 # @ECLASS: fcaps.eclass
@@ -66,6 +66,12 @@ esac
 #
 # Note: If you override pkg_postinst, you must call fcaps_pkg_postinst 
yourself.
 
+# @ECLASS_VARIABLE: FCAPS_DENY_WORLD_READ
+# @USER_VARIABLE
+# @DEFAULT_UNSET
+# @DESCRIPTION:
+# When set, deny read access on files updated by the fcaps function.
+
 # @FUNCTION: fcaps
 # @USAGE: [-o <owner>] [-g <group>] [-m <mode>] [-M <caps mode>] 
<capabilities> <file[s]>
 # @DESCRIPTION:
@@ -96,8 +102,13 @@ fcaps() {
        # Process the user options first.
        local owner='0'
        local group='0'
-       local mode='4711'
-       local caps_mode='711'
+       local mode=u+s
+       local caps_mode=
+
+       if [[ -n ${FCAPS_DENY_WORLD_READ} ]]; then
+               mode=u+s,go-r
+               caps_mode=go-r
+       fi
 
        while [[ $# -gt 0 ]] ; do
                case $1 in
@@ -137,9 +148,10 @@ fcaps() {
                        # fs doesn't support it, but abort on all others.
                        debug-print "${FUNCNAME}: setting caps '${caps}' on 
'${file}'"
 
-                       # If everything goes well, we don't want the file to be 
readable
-                       # by people.
-                       chmod ${caps_mode} "${file}" || die
+                       # Remove the read bits if requested.
+                       if [[ -n ${caps_mode} ]]; then
+                               chmod ${caps_mode} "${file}" || die
+                       fi
 
                        if ! out=$(LC_ALL=C setcap "${caps}" "${file}" 2>&1) ; 
then
                                case ${out} in
@@ -170,9 +182,14 @@ fcaps() {
                fi
 
                # If we're still here, setcaps failed.
-               debug-print "${FUNCNAME}: setting owner/mode on '${file}'"
-               chown "${owner}:${group}" "${file}" || die
-               chmod ${mode} "${file}" || die
+               if [[ -n ${owner} || -n ${group} ]]; then
+                       debug-print "${FUNCNAME}: setting owner on '${file}'"
+                       chown "${owner}:${group}" "${file}" || die
+               fi
+               if [[ -n ${mode} ]]; then
+                       debug-print "${FUNCNAME}: setting mode on '${file}'"
+                       chmod ${mode} "${file}" || die
+               fi
        done
 }
 
-- 
2.47.0


Reply via email to