+2262. [sec]* fdupont
+ Change the umask to no group write and no other access
+ at the entry of Kea server/agent binaries.
+ CVE:2025-32803
+ (Gitlab #3841, #3832)
+
2170. [sec]* tmark
kea-dhcp4, kea-dhcp6, kea-dhcp-ddns, and kea-ctrl-agent will
now only load hook libraries from the default installation
# used.
set -eu
+# Set no group write and no other access umask
+orig_umask=$(umask)
+umask $((orig_umask | 0027))
+
# These are the default parameters. They will likely not work in any
# specific deployment. Also used in unit tests.
db_host='localhost'
#include <config.h>
#include <agent/ca_controller.h>
#include <exceptions/exceptions.h>
+#include <util/filesystem.h>
#include <cstdlib>
#include <iostream>
using namespace isc::process;
int main(int argc, char* argv[]) {
+ isc::util::file::setUmask();
+
int ret = EXIT_SUCCESS;
// Launch the controller passing in command line arguments.
-#line 1 "d2_lexer.cc"
+#line 2 "d2_lexer.cc"
-#line 3 "d2_lexer.cc"
+#line 4 "d2_lexer.cc"
#define YY_INT_ALIGNED short int
/* To avoid the call to exit... oops! */
#define YY_FATAL_ERROR(msg) isc::d2::D2ParserContext::fatal(msg)
-#line 1139 "d2_lexer.cc"
+#line 1140 "d2_lexer.cc"
/* noyywrap disables automatic rewinding for the next file to parse. Since we
always parse only a single string, there's no need to do any wraps. And
using yywrap requires linking with -lfl, which provides the default yywrap
by moving it ahead by yyleng bytes. yyleng specifies the length of the
currently matched token. */
#define YY_USER_ACTION driver.loc_.columns(yyleng);
-#line 1165 "d2_lexer.cc"
#line 1166 "d2_lexer.cc"
+#line 1167 "d2_lexer.cc"
#define INITIAL 0
#define COMMENT 1
}
-#line 1486 "d2_lexer.cc"
+#line 1487 "d2_lexer.cc"
while ( /*CONSTCOND*/1 ) /* loops until end-of-file is reached */
{
#line 816 "d2_lexer.ll"
ECHO;
YY_BREAK
-#line 2468 "d2_lexer.cc"
+#line 2469 "d2_lexer.cc"
case YY_END_OF_BUFFER:
{
#include <exceptions/exceptions.h>
#include <log/logger_manager.h>
#include <log/logger_support.h>
+#include <util/filesystem.h>
#include <iostream>
/// The exit value of the program will be EXIT_SUCCESS if there were no
/// errors, EXIT_FAILURE otherwise.
int main(int argc, char* argv[]) {
+ isc::util::file::setUmask();
+
int ret = EXIT_SUCCESS;
// Launch the controller passing in command line arguments.
#include <log/output_option.h>
#include <process/cfgrpt/config_report.h>
#include <process/daemon.h>
+#include <util/filesystem.h>
#include <boost/lexical_cast.hpp>
int
main(int argc, char* argv[]) {
+ isc::util::file::setUmask();
+
int ch;
// The default. Any other values are useful for testing only.
int server_port_number = DHCP4_SERVER_PORT;
#include <log/output_option.h>
#include <process/cfgrpt/config_report.h>
#include <process/daemon.h>
+#include <util/filesystem.h>
#include <boost/lexical_cast.hpp>
int
main(int argc, char* argv[]) {
+ isc::util::file::setUmask();
+
int ch;
// The default. Any other values are useful for testing only.
int server_port_number = DHCP6_SERVER_PORT;
# used.
set -eu
+# Set no group write and no other access umask
+orig_umask=$(umask)
+umask $((orig_umask | 0027))
+
VERSION="@PACKAGE_VERSION@"
# Set the have_netconf flag to know if netconf is available.
#include <exceptions/exceptions.h>
#include <log/logger_support.h>
#include <log/logger_manager.h>
+#include <util/filesystem.h>
#include <boost/exception/diagnostic_information.hpp>
#include <boost/exception_ptr.hpp>
#include <iostream>
/// The exit value of the program will be EXIT_SUCCESS if there were no
/// errors, EXIT_FAILURE otherwise.
int main(int argc, char* argv[]) {
+ isc::util::file::setUmask();
+
int ret = EXIT_SUCCESS;
try {
// Ask scheduling to not give too much resources to LFC.
#include <config.h>
#include <exceptions/exceptions.h>
+#include <util/filesystem.h>
#include <netconf/netconf_controller.h>
#include <cstdlib>
using namespace std;
int main(int argc, char* argv[]) {
+ isc::util::file::setUmask();
+
int ret = EXIT_SUCCESS;
// Launch the controller passing in command line arguments.
#include <config.h>
+#include <util/filesystem.h>
#include <perfdhcp/avalanche_scen.h>
#include <perfdhcp/basic_scen.h>
#include <perfdhcp/command_options.h>
int
main(int argc, char* argv[]) {
+ isc::util::file::setUmask();
+
int ret_code = 0;
std::string diags;
bool parser_error = true;
return ((statbuf.st_mode & S_IFMT) == S_IFREG);
}
-Umask::Umask(mode_t mask) : orig_umask_(umask(S_IWGRP | S_IWOTH)) {
- umask(orig_umask_ | mask);
-}
-
-Umask::~Umask() {
- umask(orig_umask_);
-}
-
bool
isSocket(string const& path) {
struct stat statbuf;
return ((statbuf.st_mode & S_IFMT) == S_IFSOCK);
}
+void
+setUmask() {
+ // No group write and no other access.
+ mode_t mask(S_IWGRP | S_IRWXO);
+ mode_t orig = umask(mask);
+ // Handle the case where the original umask was already more restrictive.
+ if ((orig | mask) != mask) {
+ static_cast<void>(umask(orig | mask));
+ }
+}
+
Path::Path(string const& full_name) {
if (!full_name.empty()) {
bool dir_present = false;
bool
isFile(const std::string& path);
-/// @brief RAII device to limit access of created files.
-struct Umask {
- /// @brief Constructor
- ///
- /// Set wanted bits in umask.
- Umask(mode_t mask);
-
- /// @brief Destructor.
- ///
- /// Restore umask.
- ~Umask();
-
-private:
- /// @brief Original umask.
- mode_t orig_umask_;
-};
-
bool
isSocket(const std::string& path);
+/// @brief Set umask (at least 0027 i.e. no group write and no other access).
+void
+setUmask();
+
/// @brief Paths on a filesystem
struct Path {
/// @brief Constructor
namespace {
+/// @brief Test fixture class for testing operations on umask.
+struct UMaskUtilTest : ::testing::Test {
+ /// @brief Constructor.
+ ///
+ /// Cache the original umask value.
+ UMaskUtilTest() : orig_umask_(umask(S_IWGRP | S_IWOTH)) { }
+
+ /// @brief Destructor.
+ ///
+ /// Restore the original umask value.
+ virtual ~UMaskUtilTest() {
+ static_cast<void>(umask(orig_umask_));
+ }
+
+private:
+ /// @brief Original umask.
+ mode_t orig_umask_;
+};
+
+/// @brief Check setUmask from 0000.
+TEST_F(UMaskUtilTest, umask0) {
+ static_cast<void>(umask(0));
+ ASSERT_NO_THROW(setUmask());
+ EXPECT_EQ(S_IWGRP | S_IRWXO, umask(0));
+}
+
+/// @brief Check setUmask from no group access.
+TEST_F(UMaskUtilTest, umask077) {
+ static_cast<void>(umask(S_IRWXG | S_IRWXO));
+ ASSERT_NO_THROW(setUmask());
+ EXPECT_EQ(S_IRWXG | S_IRWXO, umask(0));
+}
+
/// @brief Check that the components are split correctly.
TEST(PathTest, components) {
// Complete name