]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/capabilities.cc
rec: allow exception to proxy protocal usage for specific listen addresses
[thirdparty/pdns.git] / pdns / capabilities.cc
1 /*
2 * This file is part of PowerDNS or dnsdist.
3 * Copyright -- PowerDNS.COM B.V. and its contributors
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * In addition, for the avoidance of any doubt, permission is granted to
10 * link this program with OpenSSL and to (re)distribute the binaries
11 * produced as the result of such linking.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23 #include "config.h"
24
25 #include <cstring>
26 #include <stdexcept>
27
28 #ifdef HAVE_LIBCAP
29 #include <sys/capability.h>
30 #include <sys/prctl.h>
31 #endif
32
33 #include "capabilities.hh"
34 #include "misc.hh"
35
36 bool dropCapabilities([[maybe_unused]] std::set<std::string> capabilitiesToKeep)
37 {
38 #ifdef HAVE_LIBCAP
39 cap_t caps = cap_get_proc();
40 if (caps != nullptr) {
41 cap_clear(caps);
42
43 if (!capabilitiesToKeep.empty()) {
44 std::vector<cap_value_t> toKeep;
45 toKeep.reserve(capabilitiesToKeep.size());
46
47 for (const auto& capToKeep : capabilitiesToKeep) {
48 cap_value_t value;
49 int res = cap_from_name(capToKeep.c_str(), &value);
50 if (res != 0) {
51 cap_free(caps);
52 throw std::runtime_error("Unable to convert capability name '" + capToKeep + "': " + stringerror());
53 }
54 toKeep.push_back(value);
55 }
56
57 if (cap_set_flag(caps, CAP_EFFECTIVE, toKeep.size(), toKeep.data(), CAP_SET) != 0) {
58 cap_free(caps);
59 throw std::runtime_error("Unable to set effective flag capabilities: " + stringerror());
60 }
61
62 if (cap_set_flag(caps, CAP_PERMITTED, toKeep.size(), toKeep.data(), CAP_SET) != 0) {
63 cap_free(caps);
64 throw std::runtime_error("Unable to set permitted flag capabilities: " + stringerror());
65 }
66 }
67
68 if (cap_set_proc(caps) != 0) {
69 cap_free(caps);
70 if (errno == EPERM) {
71 return false;
72 }
73 throw std::runtime_error("Unable to drop capabilities: " + stringerror());
74 }
75
76 cap_free(caps);
77 return true;
78 }
79 #endif /* HAVE_LIBCAP */
80 return false;
81 }
82
83 bool dropCapabilitiesAfterSwitchingIDs()
84 {
85 #ifdef HAVE_LIBCAP
86 #ifdef PR_SET_KEEPCAPS
87 if (prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0) == 0) {
88 return true;
89 }
90 #endif /* PR_SET_KEEPCAPS */
91 return false;
92 #else
93 return false;
94 #endif /* HAVE_LIBCAP */
95 }
96
97 bool keepCapabilitiesAfterSwitchingIDs()
98 {
99 #ifdef HAVE_LIBCAP
100 #ifdef PR_SET_KEEPCAPS
101 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == 0) {
102 return true;
103 }
104 #endif /* PR_SET_KEEPCAPS */
105 return false;
106 #else
107 return false;
108 #endif /* HAVE_LIBCAP */
109 }