From ff991d84b66b7aa68c6f24f3ec4b0e35b830a789 Mon Sep 17 00:00:00 2001 From: Hrvoje Senjan Date: Fri, 11 Apr 2014 17:41:46 +0200 Subject: [PATCH 1/1] Use capabilities instead of SUID where available This requires that both libcap libraries and setcap executable are found during build, otherwise the old procedure of SUID is used CCMAIL: krahmer@suse.com CCMAIL: kde-packager@kde.org REVIEW: 117125 (cherry picked from commit e898d13b430692e775060d49342181192e122fdf) --- CMakeLists.txt | 11 +++++++- cmake/FindLibcap.cmake | 59 +++++++++++++++++++++++++++++++++++++++ src/config-kdeinit.h.cmake | 1 + src/start_kdeinit/CMakeLists.txt | 20 +++++++++---- src/start_kdeinit/start_kdeinit.c | 14 ++++++++++ 5 files changed, 99 insertions(+), 6 deletions(-) create mode 100644 cmake/FindLibcap.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index 8bd43d8..2ba9bbd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,7 @@ cmake_minimum_required(VERSION 2.8.12) project(KInit) find_package(ECM 0.0.12 REQUIRED NO_MODULE) -set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) +set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/cmake) set(REQUIRED_QT_VERSION "5.2") find_package(Qt5 "${REQUIRED_QT_VERSION}" CONFIG REQUIRED Core Gui DBus) @@ -50,6 +50,15 @@ if("${CMAKE_BINARY_DIR}" STREQUAL "${CMAKE_CURRENT_BINARY_DIR}") # Remove when we depend on CMake 3.0.0 endif() +if (NOT WIN32) +find_package(Libcap) +set_package_properties(Libcap PROPERTIES + TYPE OPTIONAL + PURPOSE "KInit needs setcap in order to install start_kdeinit with CAP_SYS_RESOURCE capabilities" + ) +endif () +set(HAVE_CAPABILITIES ${Libcap_FOUND}) + set(CMAKECONFIG_INSTALL_DIR "${CMAKECONFIG_INSTALL_PREFIX}/KF5Init") ecm_configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/KF5InitConfig.cmake.in" diff --git a/cmake/FindLibcap.cmake b/cmake/FindLibcap.cmake new file mode 100644 index 0000000..4a32446 --- /dev/null +++ b/cmake/FindLibcap.cmake @@ -0,0 +1,59 @@ +# Try to find the setcap binary and cap libraries +# +# This will define: +# +# Libcap_FOUND - system has the cap library and setcap binary +# Libcap_LIBRARIES - cap libraries to link against +# SETCAP_EXECUTABLE - path of the setcap binary +# In addition, the following targets are defined: +# +# Libcap::SetCapabilities +# + + +# Copyright (c) 2014, Hrvoje Senjan, +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# +# 1. Redistributions of source code must retain the copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +find_program(SETCAP_EXECUTABLE NAMES setcap DOC "The setcap executable") + +find_library(Libcap_LIBRARIES NAMES cap DOC "The cap (capabilities) library") + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(Libcap FOUND_VAR Libcap_FOUND + REQUIRED_VARS SETCAP_EXECUTABLE Libcap_LIBRARIES) + +if(Libcap_FOUND AND NOT TARGET Libcap::SetCapabilities) + add_executable(Libcap::SetCapabilities IMPORTED) + set_target_properties(Libcap::SetCapabilities PROPERTIES + IMPORTED_LOCATION "${SETCAP_EXECUTABLE}" + ) +endif() + +mark_as_advanced(SETCAP_EXECUTABLE Libcap_LIBRARIES) + +include(FeatureSummary) +set_package_properties(Libcap PROPERTIES + URL https://sites.google.com/site/fullycapable/ + DESCRIPTION "Capabilities are a measure to limit the omnipotence of the superuser.") diff --git a/src/config-kdeinit.h.cmake b/src/config-kdeinit.h.cmake index c89c713..8f162fa 100644 --- a/src/config-kdeinit.h.cmake +++ b/src/config-kdeinit.h.cmake @@ -13,6 +13,7 @@ #cmakedefine01 CAN_CLOBBER_ARGV #cmakedefine01 HAVE_X11 +#cmakedefine01 HAVE_CAPABILITIES #cmakedefine01 HAVE_SYS_SELECT_H /* for start_kdeinit */ diff --git a/src/start_kdeinit/CMakeLists.txt b/src/start_kdeinit/CMakeLists.txt index 6bfc496..8f52ea9 100644 --- a/src/start_kdeinit/CMakeLists.txt +++ b/src/start_kdeinit/CMakeLists.txt @@ -5,10 +5,20 @@ install(TARGETS start_kdeinit DESTINATION ${LIBEXEC_INSTALL_DIR}) install(TARGETS start_kdeinit_wrapper DESTINATION ${LIBEXEC_INSTALL_DIR}) if (CMAKE_SYSTEM_NAME MATCHES Linux) - MESSAGE(STATUS "Using setuid root kdeinit wrapper in order to protect it from bad Linux OOM-killer") - set(KDEINIT_OOM_PROTECT 1) - install(CODE " - set(START_KDEINIT_PATH \"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${LIBEXEC_INSTALL_DIR}/start_kdeinit\") - EXECUTE_PROCESS(COMMAND sh -c \"chown 0 '\${START_KDEINIT_PATH}' && chmod u+s '\${START_KDEINIT_PATH}'\") + set(KDEINIT_OOM_PROTECT 1) + if (Libcap_FOUND) + message(STATUS "Using capabilities kdeinit wrapper in order to protect it from bad Linux OOM-killer") + install( CODE "execute_process( + COMMAND + ${SETCAP_EXECUTABLE} + CAP_SYS_RESOURCE=+ep + $ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${LIBEXEC_INSTALL_DIR}/start_kdeinit)" + ) + else() + message(STATUS "Using setuid root kdeinit wrapper in order to protect it from bad Linux OOM-killer") + install(CODE " + set(START_KDEINIT_PATH \"\$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/${LIBEXEC_INSTALL_DIR}/start_kdeinit\") + EXECUTE_PROCESS(COMMAND sh -c \"chown 0 '\${START_KDEINIT_PATH}' && chmod u+s '\${START_KDEINIT_PATH}'\") ") + endif () endif () diff --git a/src/start_kdeinit/start_kdeinit.c b/src/start_kdeinit/start_kdeinit.c index 3c733e7..07a28d3 100644 --- a/src/start_kdeinit/start_kdeinit.c +++ b/src/start_kdeinit/start_kdeinit.c @@ -27,6 +27,9 @@ #include #include #include +#if HAVE_CAPABILITIES +#include +#endif #define EXECUTE CMAKE_INSTALL_PREFIX"/"BIN_INSTALL_DIR "/kdeinit5" @@ -98,6 +101,9 @@ int main(int argc, char **argv) unsigned i; char **orig_environ = NULL; char header[ 7 ]; +#if HAVE_CAPABILITIES + cap_t caps; +#endif if (pipe(pipes) < 0) { perror("pipe()"); return 1; @@ -111,6 +117,14 @@ int main(int argc, char **argv) perror("fork()"); return 1; default: /* parent, drop privileges and exec */ +#if HAVE_CAPABILITIES + caps = cap_init(); + if (cap_set_proc(caps) < 0) { + perror("cap_set_proc()"); + return 1; + } + cap_free(caps); +#endif if (setgid(getgid())) { perror("setgid()"); return 1; -- 1.9.1