Commit fd6abee1 authored by Marek Vavrusa's avatar Marek Vavrusa

Moved to libcaps-ng as libcaps seems to be deprecated soon.

libcaps-ng http://http://people.redhat.com/sgrubb/libcap-ng/
Capabilities functionality is optional.
No extra dependencies.

refs #1556
parent 967b1152
......@@ -73,8 +73,6 @@ src/common/slab/alloc-common.h
src/common/libtap/tap.c
src/common/libtap/tap.h
src/common/libtap/tap_unit.h
src/common/caps.h
src/common/caps.c
src/common/lists.h
src/common/lists.c
src/common/base32.h
......
......@@ -113,12 +113,12 @@ AC_SEARCH_LIBS([rcu_set_pointer_sym], [urcu], [], [AC_MSG_ERROR([liburcu not fou
AC_SEARCH_LIBS([dlopen], [dl])
AC_SEARCH_LIBS([clock_gettime], [rt], [], [AC_MSG_ERROR([librt not found])])
AC_SEARCH_LIBS([OpenSSL_add_all_digests], [crypto],[], [AC_MSG_ERROR([libcrypto not found])])
AC_SEARCH_LIBS([cap_set_flag], [cap])
AC_SEARCH_LIBS([capng_apply], [cap-ng])
#AC_SEARCH_LIBS([ldns_rr_list_pop_rrset], [ldns], [], [AC_MSG_ERROR([libldns not found])])
# Checks for header files.
AC_HEADER_RESOLV
AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h malloc.h netdb.h netinet/in_systm.h netinet/in.h stdint.h stdlib.h string.h strings.h sys/socket.h sys/time.h sys/capability.h syslog.h unistd.h urcu.h ev.h])
AC_CHECK_HEADERS([arpa/inet.h fcntl.h inttypes.h limits.h malloc.h netdb.h netinet/in_systm.h netinet/in.h stdint.h stdlib.h string.h strings.h sys/socket.h sys/time.h cap-ng.h syslog.h unistd.h urcu.h ev.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_HEADER_STDBOOL
......
......@@ -223,8 +223,6 @@ libknots_la_SOURCES = \
common/libtap/tap.c \
common/libtap/tap.h \
common/libtap/tap_unit.h \
common/caps.c \
common/caps.h \
common/lists.c \
common/base32.c \
common/lists.h \
......
/* Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "caps.h"
int cap_drop_all() {
#ifdef USE_CAPABILITIES
cap_t caps = cap_init();
if (caps == NULL) {
return -1;
}
int ret = cap_apply(caps);
cap_free(caps);
return ret;
#else
return -1;
#endif
}
/* Copyright (C) 2011 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*!
* \file caps.h
*
* \author Marek Vavrusa <marek.vavrusa@nic.cz>
*
* \brief POSIX 1003.1e capabilities interface.
*
* \addtogroup common_lib
* @{
*/
#ifndef _KNOTD_CAPS_H_
#define _KNOTD_CAPS_H_
#include <unistd.h>
#include <config.h>
/* Include required types. */
#ifdef HAVE_SYS_CAPABILITY_H
#include <sys/capability.h>
/* Check gettid(). */
#ifndef HAVE_GETTID
#include <sys/syscall.h>
static pid_t gettid() {
#ifdef SYS_gettid
return (pid_t)syscall(SYS_gettid);
#define HAVE_GETTID 1
#else
return (pid_t)0;
#endif
}
#endif
#else
/* Stub types. */
typedef void* cap_t;
typedef int cap_value_t;
typedef int cap_flag_value_t;
#endif
/* Summarize. */
#ifdef HAVE_SYS_CAPABILITY_H
#ifdef HAVE_GETTID
#define USE_CAPABILITIES
#endif
#endif
/*!
* \brief Set Permitted & Effective flag.
* \param caps Capabilities context.
* \param cp Flag to be set.
* \retval 0 if success.
* \retval -1 on error.
*/
static inline int cap_set_pe(cap_t caps, cap_value_t cp) {
#ifdef USE_CAPABILITIES
return cap_set_flag(caps, CAP_EFFECTIVE, 1, &cp, CAP_SET) +
cap_set_flag(caps, CAP_PERMITTED, 1, &cp, CAP_SET);
#else
return -1;
#endif
}
/*!
* \brief Apply privileges.
* \param caps Capabilities context.
* \retval 0 if success.
* \retval -1 on error.
*/
static inline int cap_apply(cap_t caps) {
#ifdef USE_CAPABILITIES
return capsetp(gettid(), caps);
#else
return -1;
#endif
}
/*!
* \brief Drop all capabilities.
* \retval 0 if success.
* \retval -1 on error.
*/
int cap_drop_all();
#endif //_KNOTD_CAPS_H_
......@@ -19,10 +19,12 @@
#include <stdlib.h>
#include <unistd.h>
#include <getopt.h>
#include "common.h"
#ifdef HAVE_CAP_NG_H
#include <cap-ng.h>
#endif /* HAVE_CAP_NG_H */
#include "common.h"
#include "common/evqueue.h"
#include "common/caps.h"
#include "knot/common.h"
#include "knot/other/error.h"
#include "knot/server/server.h"
......@@ -183,48 +185,39 @@ int main(int argc, char **argv)
config_fn = abs_cfg;
}
/* Linux capabilities. */
#ifdef USE_CAPABILITIES
cap_t caps = cap_get_proc();
if (caps != NULL) {
/* Read current and clear. */
cap_flag_value_t set_caps = CAP_CLEAR;
cap_get_flag(caps, CAP_SETPCAP, CAP_EFFECTIVE, &set_caps);
cap_clear(caps);
/* Retain ability to set capabilities. */
cap_set_pe(caps, CAP_SETPCAP);
/* Allow binding to privileged ports.
* (Not inheritable)
*/
cap_set_pe(caps, CAP_NET_BIND_SERVICE);
/* Allow setuid/setgid. */
cap_set_pe(caps, CAP_SETUID);
cap_set_pe(caps, CAP_SETGID);
/* Allow priorities changing. */
cap_set_pe(caps, CAP_SYS_NICE);
/* Apply */
int caps_res = 0;
if (set_caps == CAP_SET) {
caps_res = cap_apply(caps);
} else {
log_server_info("User uid=%d is not allowed to set "
"capabilities, skipping.\n", getuid());
}
if (caps_res < 0) {
/* POSIX 1003.1e capabilities. */
#ifdef HAVE_CAP_NG_H
/* Drop all capabilities. */
capng_clear(CAPNG_SELECT_BOTH);
/* Retain ability to set capabilities. */
capng_type_t tp = CAPNG_EFFECTIVE|CAPNG_PERMITTED;
capng_update(CAPNG_ADD, tp, CAP_SETPCAP);
/* Allow binding to privileged ports.
* (Not inheritable)
*/
capng_update(CAPNG_ADD, tp, CAP_NET_BIND_SERVICE);
/* Allow setuid/setgid. */
capng_update(CAPNG_ADD, tp, CAP_SETUID);
capng_update(CAPNG_ADD, tp, CAP_SETGID);
/* Allow priorities changing. */
capng_update(CAPNG_ADD, tp, CAP_SYS_NICE);
/* Apply */
if (capng_have_capability(CAPNG_EFFECTIVE, CAP_SETPCAP)) {
if (capng_apply(CAPNG_SELECT_BOTH) < 0) {
log_server_error("Couldn't set process capabilities - "
"%s.\n", strerror(errno));
}
/* Free capabilities list. */
cap_free(caps);
} else {
log_server_error("Couldn't initialize Linux capabilities.\n");
log_server_info("User uid=%d is not allowed to set "
"capabilities, skipping.\n", getuid());
}
#endif
#endif /* HAVE_CAP_NG_H */
// Open configuration
log_server_info("Parsing configuration '%s' ...\n", config_fn);
......
......@@ -21,12 +21,14 @@
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#ifdef HAVE_CAP_NG_H
#include <cap-ng.h>
#endif /* HAVE_CAP_NG_H */
#include "knot/common.h"
#include "knot/server/dthreads.h"
#include "knot/other/log.h"
#include "knot/other/error.h"
#include "common/caps.h"
/*! \brief Lock thread state for R/W. */
static inline void lock_thread_rw(dthread_t *thread)
......@@ -126,7 +128,10 @@ static void *thread_ep(void *data)
dbg_dt("dthreads: [%p] entered ep\n", thread);
// Drop capabilities
cap_drop_all();
#ifdef HAVE_CAP_NG_H
capng_clear(CAPNG_SELECT_BOTH);
capng_apply(CAPNG_SELECT_BOTH);
#endif /* HAVE_CAP_NG_H */
// Run loop
for (;;) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment