Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for capabilities #9

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ set (${PROJECT_NAME}_VERSION
set (CMAKE_MODULE_PATH
${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/build_files/cmake/modules/")

find_package(PkgConfig REQUIRED)
pkg_check_modules(LIBCAPNG libcap-ng REQUIRED)

include_directories(${LIBCAPNG_INCLUDE_DIR})

# Set output directory for binaries
set (EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin/)

Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ To build example of the daemon you have to have following tools

* CMake
* GCC/CLang
* libcap-ng-devel

## Build

Expand Down
1 change: 0 additions & 1 deletion daemon.spec
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ rm -rf $RPM_BUILD_ROOT
%attr(755,%{username},%{groupname}) %{_rundir}/daemon



# This is section, where you should describe all important changes
# in RPM
%changelog
Expand Down
2 changes: 2 additions & 0 deletions forking-daemon.service
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Description=Example of forking daemon program
[Service]
Type=forking
PIDFile=/run/daemon/daemon.pid
AmbientCapabilities=cap_chown cap_setpcap
CapabilityBoundingSet=cap_chown cap_setpcap
ExecStart=/usr/bin/daemon \
--conf_file /etc/daemon/daemon.conf \
--log_file /var/log/daemon/daemon.log \
Expand Down
2 changes: 2 additions & 0 deletions simple-daemon.service
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ Description=Example of simple daemon program

[Service]
Type=simple
AmbientCapabilities=cap_chown cap_setpcap
CapabilityBoundingSet=cap_chown cap_setpcap
ExecStart=/usr/bin/daemon \
--conf_file /etc/daemon/daemon.conf \
--log_file /var/log/daemon/daemon.log
Expand Down
3 changes: 3 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ endif (CMAKE_COMPILER_IS_GNUCC)

add_executable (daemon ${daemon_src})

add_dependencies (daemon ${LIBCAPNG_LIBRARIES})
target_link_libraries (daemon ${LIBCAPNG_LIBRARIES})

# The rule to install daemon binary
install (TARGETS daemon
RUNTIME
Expand Down
97 changes: 96 additions & 1 deletion src/daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
*
* ***** END GPL LICENSE BLOCK *****
*
* Contributor(s): Jiri Hnidek <jiri.hnidek@tul.cz>.
* Contributor(s): Jiri Hnidek <jiri.hnidek@gmail.com>.
*
*/

Expand All @@ -34,6 +34,11 @@
#include <sys/types.h>
#include <errno.h>

#include <pwd.h>
#include <grp.h>

#include <cap-ng.h>

static int running = 0;
static int delay = 1;
static int counter = 0;
Expand All @@ -43,6 +48,92 @@ static int pid_fd = -1;
static char *app_name = NULL;
static FILE *log_stream;


int do_chown(const char *file_path, const char *user_name, const char *group_name)
{
uid_t uid;
gid_t gid;
struct passwd *pwd;
struct group *grp;

pwd = getpwnam(user_name);
if (pwd == NULL) {
syslog(LOG_ERR, "Failed to get uid");
return -1;
}
uid = pwd->pw_uid;

grp = getgrnam(group_name);
if (grp == NULL) {
syslog(LOG_ERR, "Failed to get gid");
return -2;
}
gid = grp->gr_gid;

if (chown(file_path, uid, gid) == -1) {
syslog(LOG_ERR, "chown failed");
return -3;
}

syslog(LOG_INFO, "Owner changed");

return 0;

}

/**
* \brief Keep only necessary capabilities
*/
int set_capabilities(void)
{
if (capng_get_caps_process() == 0) {
syslog(LOG_INFO, "Process capability obtained");
} else {
syslog(LOG_INFO, "Unable to obtain process capability");
}

if (capng_have_capabilities(CAPNG_SELECT_CAPS) > CAPNG_NONE) {
syslog(LOG_INFO, "Process has some capability");
} else {
syslog(LOG_INFO, "Process does not have any capability");
}

if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) {
syslog(LOG_INFO, "The process has capability CAP_SETPCAP...");
} else {
syslog(LOG_INFO, "The process does not have capability CAP_SETPCAP...");
}

if (capng_have_capability(CAPNG_EFFECTIVE, CAP_CHOWN)) {
syslog(LOG_INFO, "The process has capability CAP_CHOWN...");
} else {
syslog(LOG_INFO, "The process does not have capability CAP_CHOWN...");
}

capng_clear(CAPNG_SELECT_BOTH);
/* We want to change only chown to be able to change owner of file */
capng_update(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED, CAP_CHOWN);
capng_apply(CAPNG_SELECT_BOTH);

if (capng_get_caps_process() == 0) {
syslog(LOG_INFO, "Process capability obtained");
} else {
syslog(LOG_INFO, "Unable to obtain process capability");
}

if (capng_have_capability(CAPNG_EFFECTIVE, CAP_CHOWN)) {
syslog(LOG_INFO, "The process has capability CAP_CHOWN now");
} else {
syslog(LOG_ERR, "The process still does not have capability CAP_CHOWN");
return 2;
}

do_chown("/tmp/hello.txt", "root", "root");

return 0;
}


/**
* \brief Read configuration from config file
*/
Expand Down Expand Up @@ -287,10 +378,14 @@ int main(int argc, char *argv[])
daemonize();
}


/* Open system log and write message to it */
openlog(argv[0], LOG_PID|LOG_CONS, LOG_DAEMON);
syslog(LOG_INFO, "Started %s", app_name);

/* Enable all required capabilities */
set_capabilities();

/* Daemon will handle two signals */
signal(SIGINT, handle_signal);
signal(SIGHUP, handle_signal);
Expand Down