From f7e1587986414bed7bdbff7c9df70d62a9a36da9 Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Mon, 24 Aug 2015 17:07:57 +0200 Subject: [PATCH 01/16] lxcpp: Dropping capabilities from the bounding set [Feature] N/A [Cause] N/A [Solution] N/A [Verification] Build, install, run tests Change-Id: Id9e351d1993b43850e6a4d2a59b9eac2b4c5d354 --- libs/lxcpp/capability.cpp | 76 +++++++++++++++++++++++++++++++++++++++++++ libs/lxcpp/capability.hpp | 33 +++++++++++++++++++ libs/lxcpp/container-impl.cpp | 3 ++ libs/lxcpp/exception.hpp | 5 +++ 4 files changed, 117 insertions(+) create mode 100644 libs/lxcpp/capability.cpp create mode 100644 libs/lxcpp/capability.hpp diff --git a/libs/lxcpp/capability.cpp b/libs/lxcpp/capability.cpp new file mode 100644 index 0000000..075f4a7 --- /dev/null +++ b/libs/lxcpp/capability.cpp @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @author Jan Olszak (j.olszak@samsung.com) + * @brief Linux capabilities handling routines + */ + +#include "lxcpp/capability.hpp" +#include "lxcpp/exception.hpp" + +#include "logger/logger.hpp" +#include "utils/exception.hpp" + +#include +#include +#include +#include + +#include + +namespace lxcpp { + +namespace { + +int getLastCap() +{ + std::ifstream ifs("/proc/sys/kernel/cap_last_cap"); + if (!ifs.good()) { + const std::string msg = "Failed to open /proc/sys/kernel/cap_last_cap"; + LOGE(msg); + throw CapabilitySetupException(msg); + } + + int lastCap; + ifs >> lastCap; + + return lastCap; +} + +} // namespace + +void dropCapsFromBoundingExcept(unsigned long long mask) +{ + // This is thread safe in C++11 + static int lastCap = getLastCap(); + + // Drop caps except those in the mask + for (int cap = 0; cap <= lastCap; ++cap) { + if (mask & (1LL << cap)) + continue; + + if (::prctl(PR_CAPBSET_DROP, cap, 0, 0, 0)) { + const std::string msg = "Failed to remove capability id: " + std::to_string(cap) + + ", error: " + utils::getSystemErrorMessage(); + LOGE(msg); + throw ProcessSetupException(msg); + } + } +} +} // namespace lxcpp diff --git a/libs/lxcpp/capability.hpp b/libs/lxcpp/capability.hpp new file mode 100644 index 0000000..10105e1 --- /dev/null +++ b/libs/lxcpp/capability.hpp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @author Jan Olszak (j.olszak@samsung.com) + * @brief Linux capabilities handling routines + */ + +#ifndef LXCPP_CAPABILITY_HPP +#define LXCPP_CAPABILITY_HPP + +namespace lxcpp { + +void dropCapsFromBoundingExcept(unsigned long long mask); + +} // namespace lxcpp + +#endif // LXCPP_CAPABILITY_HPP diff --git a/libs/lxcpp/container-impl.cpp b/libs/lxcpp/container-impl.cpp index 2ac232f..9af272f 100644 --- a/libs/lxcpp/container-impl.cpp +++ b/libs/lxcpp/container-impl.cpp @@ -26,6 +26,7 @@ #include "lxcpp/process.hpp" #include "lxcpp/filesystem.hpp" #include "lxcpp/namespace.hpp" +#include "lxcpp/capability.hpp" #include "utils/exception.hpp" @@ -133,6 +134,8 @@ void setupMountPoints() int ContainerImpl::attachChild(void* data) { try { + // TODO Pass mask and options via data + dropCapsFromBoundingExcept(0); setupMountPoints(); return (*static_cast(data))(); } catch(...) { diff --git a/libs/lxcpp/exception.hpp b/libs/lxcpp/exception.hpp index bdb56f7..9d8b2cd 100644 --- a/libs/lxcpp/exception.hpp +++ b/libs/lxcpp/exception.hpp @@ -51,6 +51,11 @@ struct FileSystemSetupException: public Exception { : Exception(message) {} }; +struct CapabilitySetupException: public Exception { + CapabilitySetupException(const std::string& message = "Error during a capability operation") + : Exception(message) {} +}; + struct BadArgument: public Exception { BadArgument(const std::string& message = "Bad argument passed") : Exception(message) {} -- 2.7.4 From eb055c7913b512c5e3bda7f90efb750d8f82e393 Mon Sep 17 00:00:00 2001 From: Pawel Kubik Date: Wed, 19 Aug 2015 17:28:08 +0200 Subject: [PATCH 02/16] Add Doxygen libConfig documentation. [Feature] libConfig documentation [Cause] Explain the library usage [Verification] Built HTML using generate_documentation.sh and rendered it in browser Change-Id: I459756566055023f357fb2037b3409410129f53e --- libs/config/fields-union.hpp | 46 ++++++++++++++++------------- libs/config/fields.hpp | 26 ++++++++++------ libs/config/manager.hpp | 70 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 29 deletions(-) diff --git a/libs/config/fields-union.hpp b/libs/config/fields-union.hpp index 67720e7..edc2b80 100644 --- a/libs/config/fields-union.hpp +++ b/libs/config/fields-union.hpp @@ -31,10 +31,26 @@ #include #include +class DisableMoveAnyWrapper : public boost::any +{ + public: + DisableMoveAnyWrapper() {} + DisableMoveAnyWrapper(const DisableMoveAnyWrapper& any) + : boost::any(static_cast(any)) {}; + DisableMoveAnyWrapper& operator=(DisableMoveAnyWrapper&& any) = delete; + DisableMoveAnyWrapper& operator=(const DisableMoveAnyWrapper& any) { + static_cast(*this) = static_cast(any); + return *this; + } +}; + /** - * Use this macro to declare and register config fields + * @ingroup libConfig * - * Example: + * Use this macro to declare and register config fields. + * + * Example of fields registration: + * @code * struct Foo { * std::string bar; * @@ -52,8 +68,10 @@ * int * ) * }; + * @endcode * - * Example of valid configuration: + * Example of valid configuration: + * @code * 1. { * "type": "Foo", * "value": { "bar": "some string" } @@ -62,9 +80,10 @@ * "type": "int", * "value": 1 * } + * @endcode * - * - * Usage: + * Usage of existing bindings: + * @code * Config config; * // ... * if (config.isSet()) { @@ -83,24 +102,11 @@ * config.set(std::move(foo)); //< copy sic! * config.set(Foo({"some string"})); * } + * @endcode */ - -class DisbaleMoveAnyWrapper : public boost::any -{ - public: - DisbaleMoveAnyWrapper() {} - DisbaleMoveAnyWrapper(const DisbaleMoveAnyWrapper& any) - : boost::any(static_cast(any)) {}; - DisbaleMoveAnyWrapper& operator=(DisbaleMoveAnyWrapper&& any) = delete; - DisbaleMoveAnyWrapper& operator=(const DisbaleMoveAnyWrapper& any) { - static_cast(*this) = static_cast(any); - return *this; - } -}; - #define CONFIG_DECLARE_UNION(...) \ private: \ - DisbaleMoveAnyWrapper mConfigDeclareField; \ + DisableMoveAnyWrapper mConfigDeclareField; \ \ template \ void visitOption(Visitor& v, const std::string& name) { \ diff --git a/libs/config/fields.hpp b/libs/config/fields.hpp index d1fc4be..7a43bf6 100644 --- a/libs/config/fields.hpp +++ b/libs/config/fields.hpp @@ -18,8 +18,9 @@ /** * @file - * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) - * @brief Macros for registering configuration fields + * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) + * @addtogroup libConfig libConfig + * @brief C++ library for handling configurations */ #ifndef COMMON_CONFIG_FIELDS_HPP @@ -35,9 +36,21 @@ #endif /** - * Use this macro to register config fields. + * @ingroup libConfig + * Register empty config class + */ +#define CONFIG_REGISTER_EMPTY \ + template \ + static void accept(Visitor ) { \ + } \ + +/** + * @ingroup libConfig + * + * Registers config fields within class. * * Example: + * @code * struct Foo * { * std::string bar; @@ -56,13 +69,8 @@ * sub_a * ) * }; + * @endcode */ - -#define CONFIG_REGISTER_EMPTY \ - template \ - static void accept(Visitor ) { \ - } \ - #define CONFIG_REGISTER(...) \ template \ void accept(Visitor v) { \ diff --git a/libs/config/manager.hpp b/libs/config/manager.hpp index f3bac43..e2877df 100644 --- a/libs/config/manager.hpp +++ b/libs/config/manager.hpp @@ -19,7 +19,73 @@ /** * @file * @author Piotr Bartosiewicz (p.bartosiewi@partner.samsung.com) + * @defgroup manager Manager + * @ingroup libConfig * @brief Configuration management functions + * + * Example of various data formats operations: + * + * @code + * #include "config/fields.hpp" + * #include "config/manager.hpp" + * #include + * #include + * + * struct Foo + * { + * std::string bar = "plain-text"; + * std::vector tab = std::vector{1, 2, 4, 8}; + * double number = 3.14; + * + * CONFIG_REGISTER + * ( + * bar, + * tab, + * number + * ) + * }; + * + * int main() + * { + * Foo foo; + * + * const std::string jsonString = config::saveToJsonString(foo); + * config::loadFromJsonString(jsonString, foo); + * + * const GVariant* gVariantPointer = config::saveToGVariant(foo); + * config::loadFromGVariant(gVariantPointer, foo); + * g_variant_unref(gVariantPointer); + * + * constexpr std::string jsonFile = "foo.json"; + * config::saveToJsonFile(jsonFile, foo); + * config::loadFromJsonFile(jsonFile, foo); + * + * constexpr std::string kvDBPath = "kvdb"; + * constexpr std::string key = "foo"; + * config::saveToKVStore(kvDBPath, foo, key); + * config::loadFromKVStore(kvDBPath, foo, key); + * + * config::loadFromKVStoreWithJson(kvDBPath, jsonString, foo, key); + * config::loadFromKVStoreWithJsonFile(kvDBPath, jsonFile, foo, key); + * + * FILE* file = fopen("blob", "wb"); + * if (!file) + * { + * return EXIT_FAILURE; + * } + * const int fd = ::fileno(file); + * config::saveToFD(fd, foo); + * ::fclose(file); + * file = ::fopen("blob", "rb"); + * if(!file) { + * return EXIT_FAILURE; + * } + * config::loadFromFD(fd, foo); + * ::fclose(file); + * + * return 0; + * } + * @endcode */ #ifndef COMMON_CONFIG_MANAGER_HPP @@ -39,6 +105,8 @@ namespace config { +/*@{*/ + /** * Fills the configuration with data stored in the GVariant * @@ -254,4 +322,6 @@ void saveToFD(const int fd, const Config& config) } // namespace config +/*@}*/ + #endif // COMMON_CONFIG_MANAGER_HPP -- 2.7.4 From 9c3710942aac6095d0f28587286868783ec1ef6a Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Fri, 21 Aug 2015 17:08:22 +0200 Subject: [PATCH 03/16] lxcpp: network interface [Feature] Network interface for lxcpp [Cause] N/A [Solution] N/A [Verification] Build, install, run tests Change-Id: Ifcf03b46662168c198a8e36c268b6856639ff52e --- libs/lxcpp/container-impl.cpp | 56 +++++++++++++++++- libs/lxcpp/container-impl.hpp | 22 +++++++ libs/lxcpp/container.hpp | 34 +++++++++++ libs/lxcpp/exception.hpp | 5 ++ libs/lxcpp/network-config.cpp | 47 +++++++++++++++ libs/lxcpp/network-config.hpp | 116 ++++++++++++++++++++++++++++++++++++ libs/lxcpp/network.cpp | 134 ++++++++++++++++++++++++++++++++++++++++++ libs/lxcpp/network.hpp | 73 +++++++++++++++++++++++ 8 files changed, 486 insertions(+), 1 deletion(-) create mode 100644 libs/lxcpp/network-config.cpp create mode 100644 libs/lxcpp/network-config.hpp create mode 100644 libs/lxcpp/network.cpp create mode 100644 libs/lxcpp/network.hpp diff --git a/libs/lxcpp/container-impl.cpp b/libs/lxcpp/container-impl.cpp index 9af272f..cba0691 100644 --- a/libs/lxcpp/container-impl.cpp +++ b/libs/lxcpp/container-impl.cpp @@ -33,7 +33,6 @@ #include #include - namespace lxcpp { ContainerImpl::ContainerImpl() @@ -185,6 +184,61 @@ void ContainerImpl::attach(Container::AttachCall& call) } } +void ContainerImpl::addInterfaceConfig(const std::string& hostif, + const std::string& zoneif, + InterfaceType type, + MacVLanMode mode) +{ + mInterfaceConfig.push_back(NetworkInterfaceConfig(hostif,zoneif,type,mode)); +} + +void ContainerImpl::addAddrConfig(const std::string& /*ifname*/, const InetAddr& /*addr*/) +{ + throw NotImplementedException(); +} + +std::vector ContainerImpl::getInterfaces() +{ + return NetworkInterface::getInterfaces(getInitPid()); +} + +NetworkInterfaceInfo ContainerImpl::getInterfaceInfo(const std::string& /*ifname*/) +{ + throw NotImplementedException(); +} + +void ContainerImpl::createInterface(const std::string& hostif, + const std::string& zoneif, + InterfaceType type, + MacVLanMode mode) +{ + NetworkInterface ni(*this, zoneif); + ni.create(hostif, type, mode); +} + +void ContainerImpl::destroyInterface(const std::string& /*ifname*/) +{ + throw NotImplementedException(); +} + +void ContainerImpl::setUp(const std::string& /*ifname*/) +{ + throw NotImplementedException(); +} + +void ContainerImpl::setDown(const std::string& /*ifname*/) +{ + throw NotImplementedException(); +} +void ContainerImpl::addAddr(const std::string& /*ifname*/, const InetAddr& /*addr*/) +{ + throw NotImplementedException(); +} + +void ContainerImpl::delAddr(const std::string& /*ifname*/, const InetAddr& /*addr*/) +{ + throw NotImplementedException(); +} } // namespace lxcpp diff --git a/libs/lxcpp/container-impl.hpp b/libs/lxcpp/container-impl.hpp index e236932..a57c340 100644 --- a/libs/lxcpp/container-impl.hpp +++ b/libs/lxcpp/container-impl.hpp @@ -26,6 +26,7 @@ #include "lxcpp/container.hpp" #include "lxcpp/namespace.hpp" +#include "lxcpp/network.hpp" #include "utils/channel.hpp" @@ -56,6 +57,26 @@ public: // Other void attach(Container::AttachCall& attachCall); + // Network interfaces setup/config + void addInterfaceConfig(const std::string& hostif, + const std::string& zoneif, + InterfaceType type, + MacVLanMode mode); + void addAddrConfig(const std::string& ifname, const InetAddr& addr); + + // Network interfaces (runtime) + std::vector getInterfaces(); + NetworkInterfaceInfo getInterfaceInfo(const std::string& ifname); + void createInterface(const std::string& hostif, + const std::string& zoneif, + InterfaceType type, + MacVLanMode mode); + void destroyInterface(const std::string& ifname); + void setUp(const std::string& ifname); + void setDown(const std::string& ifname); + void addAddr(const std::string& ifname, const InetAddr& addr); + void delAddr(const std::string& ifname, const InetAddr& addr); + private: // Methods for different stages of setting up the attachment @@ -65,6 +86,7 @@ private: pid_t mInitPid; std::vector mNamespaces; + std::vector mInterfaceConfig; }; } // namespace lxcpp diff --git a/libs/lxcpp/container.hpp b/libs/lxcpp/container.hpp index 4f2d697..44a3567 100644 --- a/libs/lxcpp/container.hpp +++ b/libs/lxcpp/container.hpp @@ -24,11 +24,25 @@ #ifndef LXCPP_CONTAINER_HPP #define LXCPP_CONTAINER_HPP +#include "lxcpp/network-config.hpp" + #include #include +#include namespace lxcpp { +enum class NetStatus { + DOWN, + UP +}; + +struct NetworkInterfaceInfo { + const std::string ifname; + const NetStatus status; + const std::vector addrs; +}; + class Container { public: typedef std::function AttachCall; @@ -54,6 +68,26 @@ public: // Other virtual void attach(AttachCall& attachCall) = 0; + + // Network interfaces setup/config + virtual void addInterfaceConfig(const std::string& hostif, + const std::string& zoneif, + InterfaceType type, + MacVLanMode mode) = 0; + virtual void addAddrConfig(const std::string& ifname, const InetAddr& addr) = 0; + + // Network interfaces (runtime) + virtual std::vector getInterfaces() = 0; + virtual NetworkInterfaceInfo getInterfaceInfo(const std::string& ifname) = 0; + virtual void createInterface(const std::string& hostif, + const std::string& zoneif, + InterfaceType type, + MacVLanMode mode) = 0; + virtual void destroyInterface(const std::string& ifname) = 0; + virtual void setUp(const std::string& ifname) = 0; + virtual void setDown(const std::string& ifname) = 0; + virtual void addAddr(const std::string& ifname, const InetAddr& addr) = 0; + virtual void delAddr(const std::string& ifname, const InetAddr& addr) = 0; }; } // namespace lxcpp diff --git a/libs/lxcpp/exception.hpp b/libs/lxcpp/exception.hpp index 9d8b2cd..51dc5ec 100644 --- a/libs/lxcpp/exception.hpp +++ b/libs/lxcpp/exception.hpp @@ -61,6 +61,11 @@ struct BadArgument: public Exception { : Exception(message) {} }; +struct NetworkException : public Exception { + NetworkException (const std::string& message = "Error during setting up a network") + : Exception(message) {} +}; + } // namespace lxcpp #endif // LXCPP_EXCEPTION_HPP diff --git a/libs/lxcpp/network-config.cpp b/libs/lxcpp/network-config.cpp new file mode 100644 index 0000000..77e220a --- /dev/null +++ b/libs/lxcpp/network-config.cpp @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +/** + * @file + * @author Krzysztof Dynowski (k.dynowski@samsumg.com) + * @brief Network configuration classes + */ + +#include "lxcpp/network-config.hpp" +#include "lxcpp/exception.hpp" +#include + +namespace lxcpp { + +void NetworkInterfaceConfig::addNetAddr(const InetAddr& addr) +{ + std::vector::iterator exists = std::find(mIpAddrList.begin(), mIpAddrList.end(), addr); + if (exists != mIpAddrList.end()) { + std::string msg("Address alredy assigned"); + throw NetworkException(msg); + } + mIpAddrList.push_back(addr); +} + +void NetworkInterfaceConfig::delNetAddr(const InetAddr& addr) +{ + std::vector::iterator exists = std::find(mIpAddrList.begin(), mIpAddrList.end(), addr); + mIpAddrList.erase(exists); +} + +} //namespace lxcpp diff --git a/libs/lxcpp/network-config.hpp b/libs/lxcpp/network-config.hpp new file mode 100644 index 0000000..b490aa0 --- /dev/null +++ b/libs/lxcpp/network-config.hpp @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @author Krzysztof Dynowski (k.dynowski@samsumg.com) + * @brief Network configuration classes + */ + +#ifndef LXCPP_NETWORK_CONFIG_HPP +#define LXCPP_NETWORK_CONFIG_HPP + +#include +#include + +#include +#include + +namespace lxcpp { + +/** + * Created interface type + */ +enum class InterfaceType { + VETH, + BRIDGE, + MACVLAN, + MOVE +}; + +/** + * Suported MacVLan modes + */ +enum class MacVLanMode { + PRIVATE, + VEPA, + BRIDGE, + PASSTHRU +}; + +/** + * Suported address types + */ +enum class InetAddrType { + IPV4, + IPV6 +}; + +/** + * Unified ip address + */ +struct InetAddr { + InetAddrType type; + int prefix; + union { + struct in_addr ipv4; + struct in6_addr ipv6; + } addr; +}; + +static inline bool operator==(const InetAddr& a, const InetAddr& b) { + if (a.type == b.type && a.prefix == b.prefix) { + if (a.type == InetAddrType::IPV4) { + return ::memcmp(&a.addr.ipv4, &b.addr.ipv4, sizeof(a.addr.ipv4)) == 0; + } + if (a.type == InetAddrType::IPV6) { + return ::memcmp(&a.addr.ipv6, &b.addr.ipv6, sizeof(a.addr.ipv6)) == 0; + } + } + return false; +} + + +/** + * Network interface configuration + */ +class NetworkInterfaceConfig { +public: + NetworkInterfaceConfig(const std::string& hostif, + const std::string& zoneif, + InterfaceType type, + MacVLanMode mode = MacVLanMode::PRIVATE) : + mHostIf(hostif), + mZoneIf(zoneif), + mType(type), + mMode(mode) + { + } + void addNetAddr(const InetAddr&); + void delNetAddr(const InetAddr&); + +private: + const std::string mHostIf; + const std::string mZoneIf; + const InterfaceType mType; + const MacVLanMode mMode; + std::vector mIpAddrList; +}; + +} //namespace lxcpp + +#endif // LXCPP_NETWORK_CONFIG_HPP diff --git a/libs/lxcpp/network.cpp b/libs/lxcpp/network.cpp new file mode 100644 index 0000000..ad01f6f --- /dev/null +++ b/libs/lxcpp/network.cpp @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @author Krzysztof Dynowski (k.dynowski@samsumg.com) + * @brief Actions on network interace in the container + */ + + +#include "lxcpp/network.hpp" +#include "lxcpp/exception.hpp" +#include "netlink/netlink-message.hpp" +#include "utils/make-clean.hpp" + +#include + +using namespace vasum::netlink; + +namespace lxcpp { + +void NetworkInterface::create(const std::string& hostif, + InterfaceType type, + MacVLanMode mode) +{ + switch (type) { + case InterfaceType::VETH: + createVeth(hostif); + break; + case InterfaceType::BRIDGE: + createBridge(hostif); + break; + case InterfaceType::MACVLAN: + createMacVLan(hostif, mode); + break; + case InterfaceType::MOVE: + move(hostif); + break; + default: + throw NetworkException("Unsuported interface type"); + } +} + +void NetworkInterface::createVeth(const std::string& /*hostif*/) +{ + throw NotImplementedException(); +} + +void NetworkInterface::createBridge(const std::string& /*hostif*/) +{ + throw NotImplementedException(); +} + +void NetworkInterface::createMacVLan(const std::string& /*hostif*/, MacVLanMode /*mode*/) +{ + throw NotImplementedException(); +} + +void NetworkInterface::move(const std::string& /*hostif*/) +{ + throw NotImplementedException(); +} + +void NetworkInterface::destroy() +{ + throw NotImplementedException(); +} + +NetStatus NetworkInterface::status() +{ + throw NotImplementedException(); + /* + //TODO get container status, if stopped return CONFIGURED + if (mContainer.getInitPid()<=0) return CONFIGURED; + // read netlink + return DOWN;*/ +} + + +void NetworkInterface::up() +{ + throw NotImplementedException(); +} + +void NetworkInterface::down() +{ + throw NotImplementedException(); +} + +void NetworkInterface::setAttrs(const Attrs& /*attrs*/) +{ + throw NotImplementedException(); +} + +const Attrs NetworkInterface::getAttrs() const +{ + throw NotImplementedException(); +} + +std::vector NetworkInterface::getInterfaces(pid_t initpid) +{ + // get interfaces seen by netlink + NetlinkMessage nlm(RTM_GETLINK, NLM_F_REQUEST|NLM_F_DUMP|NLM_F_ROOT); + ifinfomsg info = utils::make_clean(); + info.ifi_family = AF_PACKET; + nlm.put(info); + NetlinkResponse response = send(nlm, initpid); + + std::vector iflist; + while (response.hasMessage()) { + std::string ifName; + response.skip(); + response.fetch(IFLA_IFNAME, ifName); + iflist.push_back(ifName); + response.fetchNextMessage(); + } + return iflist; +} + +} // namespace lxcpp diff --git a/libs/lxcpp/network.hpp b/libs/lxcpp/network.hpp new file mode 100644 index 0000000..44ab268 --- /dev/null +++ b/libs/lxcpp/network.hpp @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @author Krzysztof Dynowski (k.dynowski@samsumg.com) + * @brief Actions on network interace in the container + */ + +#ifndef LXCPP_NETWORK_HPP +#define LXCPP_NETWORK_HPP + +#include "lxcpp/container.hpp" +#include + +namespace lxcpp { + +struct Attr { + std::string name; + std::string value; +}; + +typedef std::vector Attrs; + + +/// Network operations to be performed on given container and interface +/// operates on netlink device +class NetworkInterface { +public: + NetworkInterface(Container& c, const std::string& ifname) : + mContainer(c), + mIfname(ifname) + { } + + //Network actions on Container + void create(const std::string& hostif, InterfaceType type, MacVLanMode mode=MacVLanMode::PRIVATE); + void destroy(); + + NetStatus status(); + void up(); + void down(); + void setAttrs(const Attrs& attrs); + const Attrs getAttrs() const; + + static std::vector getInterfaces(pid_t initpid); + +private: + void createVeth(const std::string& hostif); + void createBridge(const std::string& hostif); + void createMacVLan(const std::string& hostif, MacVLanMode mode); + void move(const std::string& hostif); + + Container& mContainer; ///< Container to operate on + const std::string mIfname; ///< network interface name inside zone +}; + +} // namespace lxcpp + +#endif // LXCPP_NETWORK_HPP -- 2.7.4 From 780d827c738f367461de445812b81e5edc1d4071 Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Wed, 26 Aug 2015 18:42:18 +0200 Subject: [PATCH 04/16] lxcpp: AttachManager and chdir [Feature] Added AttachManager for handling attaching It's possible to set cwd inside container. [Cause] N/A [Solution] N/A [Verification] Build, install, run tests Change-Id: Ida77e56a7d4f42225554c8fe02b5794509b83ef2 --- libs/lxcpp/attach-manager.cpp | 139 ++++++++++++++++++++++++++++++++++++++++++ libs/lxcpp/attach-manager.hpp | 64 +++++++++++++++++++ libs/lxcpp/container-impl.cpp | 85 +++----------------------- libs/lxcpp/container-impl.hpp | 12 ++-- libs/lxcpp/container.hpp | 6 +- libs/lxcpp/filesystem.cpp | 19 ++++++ libs/lxcpp/filesystem.hpp | 4 ++ libs/lxcpp/network-config.hpp | 4 ++ libs/lxcpp/network.hpp | 5 +- 9 files changed, 251 insertions(+), 87 deletions(-) create mode 100644 libs/lxcpp/attach-manager.cpp create mode 100644 libs/lxcpp/attach-manager.hpp diff --git a/libs/lxcpp/attach-manager.cpp b/libs/lxcpp/attach-manager.cpp new file mode 100644 index 0000000..3479673 --- /dev/null +++ b/libs/lxcpp/attach-manager.cpp @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @author Jan Olszak (j.olszak@samsung.com) + * @brief Implementation of attaching to a container + */ + +#include "lxcpp/attach-manager.hpp" +#include "lxcpp/exception.hpp" +#include "lxcpp/process.hpp" +#include "lxcpp/filesystem.hpp" +#include "lxcpp/namespace.hpp" +#include "lxcpp/capability.hpp" + +#include "utils/exception.hpp" + +#include +#include + + +namespace lxcpp { + +namespace { + +void setupMountPoints() +{ + /* TODO: Uncomment when preparing the final attach() version + + // TODO: This unshare should be optional only if we attach to PID/NET namespace, but not MNT. + // Otherwise container already has remounted /proc /sys + lxcpp::unshare(Namespace::MNT); + + if (isMountPointShared("/")) { + // TODO: Handle case when the container rootfs or mount location is MS_SHARED, but not '/' + lxcpp::mount(nullptr, "/", nullptr, MS_SLAVE | MS_REC, nullptr); + } + + if(isMountPoint("/proc")) { + lxcpp::umount("/proc", MNT_DETACH); + lxcpp::mount("none", "/proc", "proc", 0, nullptr); + } + + if(isMountPoint("/sys")) { + lxcpp::umount("/sys", MNT_DETACH); + lxcpp::mount("none", "/sys", "sysfs", 0, nullptr); + } + + */ +} + +} // namespace + +AttachManager::AttachManager(lxcpp::ContainerImpl& container) + : mContainer(container) +{ +} + +AttachManager::~AttachManager() +{ +} + +void AttachManager::attach(Container::AttachCall& call, + const std::string& wdInContainer) +{ + // Channels for setup synchronization + utils::Channel intermChannel; + + const pid_t interPid = lxcpp::fork(); + if (interPid > 0) { + intermChannel.setLeft(); + parent(intermChannel, interPid); + intermChannel.shutdown(); + } else { + intermChannel.setRight(); + interm(intermChannel, wdInContainer, call); + intermChannel.shutdown(); + ::_exit(0); + } +} + +int AttachManager::child(void* data) +{ + try { + // TODO Pass mask and options via data + dropCapsFromBoundingExcept(0); + setupMountPoints(); + return (*static_cast(data))(); + } catch(...) { + return -1; // Non-zero on failure + } + return 0; // Success +} + +void AttachManager::parent(utils::Channel& intermChannel, const pid_t interPid) +{ + // TODO: Setup cgroups etc + const pid_t childPid = intermChannel.read(); + + // Wait for all processes + lxcpp::waitpid(interPid); + lxcpp::waitpid(childPid); +} + +void AttachManager::interm(utils::Channel& intermChannel, + const std::string& wdInContainer, + Container::AttachCall& call) +{ + lxcpp::setns(mContainer.getInitPid(), mContainer.getNamespaces()); + + // Change the current work directory + // wdInContainer is a path relative to the container's root + lxcpp::chdir(wdInContainer); + + // PID namespace won't affect the returned pid + // CLONE_PARENT: Child's PPID == Caller's PID + const pid_t childPid = lxcpp::clone(&AttachManager::child, + &call, + CLONE_PARENT); + intermChannel.write(childPid); + +} + +} // namespace lxcpp diff --git a/libs/lxcpp/attach-manager.hpp b/libs/lxcpp/attach-manager.hpp new file mode 100644 index 0000000..be37ade --- /dev/null +++ b/libs/lxcpp/attach-manager.hpp @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @author Jan Olszak (j.olszak@samsung.com) + * @brief Implementation of attaching to a container + */ + +#ifndef LXCPP_ATTACH_MANAGER_HPP +#define LXCPP_ATTACH_MANAGER_HPP + +#include "lxcpp/container-impl.hpp" +#include "utils/channel.hpp" + +#include + +namespace lxcpp { + +class AttachManager final { +public: + AttachManager(lxcpp::ContainerImpl& container); + ~AttachManager(); + + /** + * Runs the call in the container's context + * + * @param call function to run inside container + * @param wdInContainer Current Work Directory. Path relative to container's root + */ + void attach(Container::AttachCall& call, + const std::string& wdInContainer); + +private: + const lxcpp::ContainerImpl& mContainer; + + // Methods for different stages of setting up the attachment + static int child(void* data); + + void parent(utils::Channel& intermChannel, + const pid_t pid); + + void interm(utils::Channel& intermChannel, + const std::string& wdInContainer, + Container::AttachCall& call); +}; + +} // namespace lxcpp + +#endif // LXCPP_ATTACH_MANAGER_HPP \ No newline at end of file diff --git a/libs/lxcpp/container-impl.cpp b/libs/lxcpp/container-impl.cpp index cba0691..6de22dc 100644 --- a/libs/lxcpp/container-impl.cpp +++ b/libs/lxcpp/container-impl.cpp @@ -27,6 +27,7 @@ #include "lxcpp/filesystem.hpp" #include "lxcpp/namespace.hpp" #include "lxcpp/capability.hpp" +#include "lxcpp/attach-manager.hpp" #include "utils/exception.hpp" @@ -78,9 +79,9 @@ void ContainerImpl::reboot() throw NotImplementedException(); } -int ContainerImpl::getInitPid() +pid_t ContainerImpl::getInitPid() const { - throw NotImplementedException(); + return mInitPid; } void ContainerImpl::create() @@ -103,86 +104,18 @@ std::string ContainerImpl::getRootPath() throw NotImplementedException(); } -namespace { -void setupMountPoints() +void ContainerImpl::attach(Container::AttachCall& call, + const std::string& cwdInContainer) { - /* TODO: Uncomment when preparing the final attach() version - - // TODO: This unshare should be optional only if we attach to PID/NET namespace, but not MNT. - // Otherwise container already has remounted /proc /sys - lxcpp::unshare(Namespace::MNT); - - if (isMountPointShared("/")) { - // TODO: Handle case when the container rootfs or mount location is MS_SHARED, but not '/' - lxcpp::mount(nullptr, "/", nullptr, MS_SLAVE | MS_REC, nullptr); - } - - if(isMountPoint("/proc")) { - lxcpp::umount("/proc", MNT_DETACH); - lxcpp::mount("none", "/proc", "proc", 0, nullptr); - } - - if(isMountPoint("/sys")) { - lxcpp::umount("/sys", MNT_DETACH); - lxcpp::mount("none", "/sys", "sysfs", 0, nullptr); - } - - */ -} -} // namespace - -int ContainerImpl::attachChild(void* data) { - try { - // TODO Pass mask and options via data - dropCapsFromBoundingExcept(0); - setupMountPoints(); - return (*static_cast(data))(); - } catch(...) { - return -1; // Non-zero on failure - } - return 0; // Success + AttachManager attachManager(*this); + attachManager.attach(call, cwdInContainer); } -void ContainerImpl::attachParent(utils::Channel& channel, const pid_t interPid) +const std::vector& ContainerImpl::getNamespaces() const { - // TODO: Setup cgroups etc - pid_t childPid = channel.read(); - - // Wait for the Intermediate process - lxcpp::waitpid(interPid); - - // Wait for the Child process - lxcpp::waitpid(childPid); -} - -void ContainerImpl::attachIntermediate(utils::Channel& channel, Container::AttachCall& call) -{ - lxcpp::setns(mInitPid, mNamespaces); - - // PID namespace won't affect the returned pid - // CLONE_PARENT: Child's PPID == Caller's PID - const pid_t pid = lxcpp::clone(&ContainerImpl::attachChild, - &call, - CLONE_PARENT); - channel.write(pid); + return mNamespaces; } -void ContainerImpl::attach(Container::AttachCall& call) -{ - utils::Channel channel; - - const pid_t interPid = lxcpp::fork(); - if (interPid > 0) { - channel.setLeft(); - attachParent(channel, interPid); - channel.shutdown(); - } else { - channel.setRight(); - attachIntermediate(channel, call); - channel.shutdown(); - ::_exit(0); - } -} void ContainerImpl::addInterfaceConfig(const std::string& hostif, const std::string& zoneif, diff --git a/libs/lxcpp/container-impl.hpp b/libs/lxcpp/container-impl.hpp index a57c340..c862473 100644 --- a/libs/lxcpp/container-impl.hpp +++ b/libs/lxcpp/container-impl.hpp @@ -46,7 +46,8 @@ public: void freeze(); void unfreeze(); void reboot(); - int getInitPid(); + pid_t getInitPid() const; + const std::vector& getNamespaces() const; //Filesystem actions void create(); @@ -55,7 +56,8 @@ public: std::string getRootPath(); // Other - void attach(Container::AttachCall& attachCall); + void attach(Container::AttachCall& attachCall, + const std::string& cwdInContainer); // Network interfaces setup/config void addInterfaceConfig(const std::string& hostif, @@ -78,12 +80,6 @@ public: void delAddr(const std::string& ifname, const InetAddr& addr); private: - - // Methods for different stages of setting up the attachment - void attachParent(utils::Channel& channel, const pid_t pid); - void attachIntermediate(utils::Channel& channel, Container::AttachCall& call); - static int attachChild(void* data); - pid_t mInitPid; std::vector mNamespaces; std::vector mInterfaceConfig; diff --git a/libs/lxcpp/container.hpp b/libs/lxcpp/container.hpp index 44a3567..d07bc27 100644 --- a/libs/lxcpp/container.hpp +++ b/libs/lxcpp/container.hpp @@ -25,6 +25,7 @@ #define LXCPP_CONTAINER_HPP #include "lxcpp/network-config.hpp" +#include #include #include @@ -58,7 +59,7 @@ public: virtual void freeze() = 0; virtual void unfreeze() = 0; virtual void reboot() = 0; - virtual int getInitPid() = 0; + virtual pid_t getInitPid() const = 0; //Filesystem actions virtual void create() = 0; @@ -67,7 +68,8 @@ public: virtual std::string getRootPath() = 0; // Other - virtual void attach(AttachCall& attachCall) = 0; + virtual void attach(AttachCall& attachCall, + const std::string& cwdInContainer) = 0; // Network interfaces setup/config virtual void addInterfaceConfig(const std::string& hostif, diff --git a/libs/lxcpp/filesystem.cpp b/libs/lxcpp/filesystem.cpp index c085861..4881449 100644 --- a/libs/lxcpp/filesystem.cpp +++ b/libs/lxcpp/filesystem.cpp @@ -34,6 +34,7 @@ #include #include #include +#include namespace lxcpp { @@ -119,4 +120,22 @@ bool isMountPointShared(const std::string& path) return false; } +void fchdir(int fd) +{ + if(-1 == ::fchdir(fd)) { + const std::string msg = "fchdir() failed: " + utils::getSystemErrorMessage(); + LOGE(msg); + throw FileSystemSetupException(msg); + } +} + +void chdir(const std::string& path) +{ + if(-1 == ::chdir(path.c_str())) { + const std::string msg = "chdir() failed: " + utils::getSystemErrorMessage(); + LOGE(msg); + throw FileSystemSetupException(msg); + } +} + } // namespace lxcpp \ No newline at end of file diff --git a/libs/lxcpp/filesystem.hpp b/libs/lxcpp/filesystem.hpp index 6833ffc..63aacee 100644 --- a/libs/lxcpp/filesystem.hpp +++ b/libs/lxcpp/filesystem.hpp @@ -47,6 +47,10 @@ bool isMountPoint(const std::string& path); */ bool isMountPointShared(const std::string& path); +void fchdir(int fd); + +void chdir(const std::string& path); + } // namespace lxcpp #endif // LXCPP_FILESYSTEM_HPP \ No newline at end of file diff --git a/libs/lxcpp/network-config.hpp b/libs/lxcpp/network-config.hpp index b490aa0..b4e2fe0 100644 --- a/libs/lxcpp/network-config.hpp +++ b/libs/lxcpp/network-config.hpp @@ -99,7 +99,11 @@ public: mType(type), mMode(mode) { + // TODO: Remove temporary usage + (void) mType; + (void) mMode; } + void addNetAddr(const InetAddr&); void delNetAddr(const InetAddr&); diff --git a/libs/lxcpp/network.hpp b/libs/lxcpp/network.hpp index 44ab268..8381611 100644 --- a/libs/lxcpp/network.hpp +++ b/libs/lxcpp/network.hpp @@ -44,7 +44,10 @@ public: NetworkInterface(Container& c, const std::string& ifname) : mContainer(c), mIfname(ifname) - { } + { + // TODO: Remove temporary usage + (void) mContainer; + } //Network actions on Container void create(const std::string& hostif, InterfaceType type, MacVLanMode mode=MacVLanMode::PRIVATE); -- 2.7.4 From fb84beec90283c39442ecb4de15586948ce934bb Mon Sep 17 00:00:00 2001 From: Pawel Kubik Date: Fri, 21 Aug 2015 17:19:46 +0200 Subject: [PATCH 05/16] Improved CLI connection error note. [Feature] CLI connection error note, and suggestion to launch vasum-server [Cause] Previous information was inacurate [Solution] Added proper error handling [Verification] Build, install, run cli/vsm when the server is not running Change-Id: I59a4467a25ef40e6ed650485c8ac690f955e29cc --- cli/cli-exception.hpp | 52 ++++++++++++++++++++++++++++++++++++++++++ cli/command-line-interface.cpp | 3 ++- cli/main.cpp | 5 ++++ 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 cli/cli-exception.hpp diff --git a/cli/cli-exception.hpp b/cli/cli-exception.hpp new file mode 100644 index 0000000..982f52d --- /dev/null +++ b/cli/cli-exception.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Pawel Kubik + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +/** + * @file + * @author Pawel Kubik (p.kubik@samsung.com) + * @brief Exceptions for the cli + */ + + +#ifndef CLI_EXCEPTION_HPP +#define CLI_EXCEPTION_HPP + +#include "base-exception.hpp" + + +namespace vasum { +namespace cli { + + +/** + * Base class for exceptions in Vasum CLI + */ +struct CliException: public VasumException { + + CliException(const std::string& error) : VasumException(error) {} +}; + +struct IOException: public CliException { + + IOException(const std::string& error) : CliException(error) {} +}; + +} // namespace cli +} // namespace vasum + +#endif // CLI_EXCEPTION_HPP diff --git a/cli/command-line-interface.cpp b/cli/command-line-interface.cpp index 93201c3..27d7cac 100644 --- a/cli/command-line-interface.cpp +++ b/cli/command-line-interface.cpp @@ -26,6 +26,7 @@ #include "command-line-interface.hpp" #include "vasum-client.h" #include "utils/c-array.hpp" +#include "cli-exception.hpp" #include #include @@ -204,7 +205,7 @@ void CommandLineInterface::connect() string msg = vsm_get_status_message(CommandLineInterface::client); vsm_client_free(CommandLineInterface::client); CommandLineInterface::client = nullptr; - throw runtime_error(msg); + throw IOException(msg); } } diff --git a/cli/main.cpp b/cli/main.cpp index 528c4c8..537ad69 100644 --- a/cli/main.cpp +++ b/cli/main.cpp @@ -23,6 +23,7 @@ */ #include "command-line-interface.hpp" +#include "cli-exception.hpp" #include #include @@ -284,6 +285,10 @@ int connect() { try { CommandLineInterface::connect(); + } catch (const IOException& ex) { + std::cerr << ex.what() << std::endl; + std::cout << "Client connection error. Is vasum-server running?" << std::endl; + return EXIT_FAILURE; } catch (const std::runtime_error& ex) { std::cerr << ex.what() << std::endl; return EXIT_FAILURE; -- 2.7.4 From a61093cd82f7b06e7594071f50763615c14754e1 Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Fri, 28 Aug 2015 12:52:51 +0200 Subject: [PATCH 06/16] lxcpp: add all required objects to lxcpp.so, add test executable [Feature] Linking with lxcpp give unknown symbol errors [Cause] No requird objects in lxcpp.so [Solution] Add them to CMakeLists.txt, create test app [Verification] Build, install Change-Id: I4dc59091ea294aa51a6201236f6fe51162459b83 --- common/netlink/netlink.cpp | 3 +-- libs/lxcpp/CMakeLists.txt | 16 +++++++++--- tests/unit_tests/CMakeLists.txt | 7 ++++- tests/unit_tests/lxcpp/lxcpp-api-compile-test.cpp | 32 +++++++++++++++++++++++ 4 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 tests/unit_tests/lxcpp/lxcpp-api-compile-test.cpp diff --git a/common/netlink/netlink.cpp b/common/netlink/netlink.cpp index dd11ef3..1d966cb 100644 --- a/common/netlink/netlink.cpp +++ b/common/netlink/netlink.cpp @@ -23,8 +23,7 @@ */ #include "config.hpp" -#include "netlink.hpp" -#include "utils.hpp" +#include "netlink/netlink.hpp" #include "utils/exception.hpp" #include "utils/make-clean.hpp" #include "utils/environment.hpp" diff --git a/libs/lxcpp/CMakeLists.txt b/libs/lxcpp/CMakeLists.txt index c7bd926..b04e437 100644 --- a/libs/lxcpp/CMakeLists.txt +++ b/libs/lxcpp/CMakeLists.txt @@ -23,17 +23,25 @@ MESSAGE(STATUS "") MESSAGE(STATUS "Generating makefile for the liblxcpp...") FILE(GLOB HEADERS *.hpp) FILE(GLOB HEADERS_UTILS ${COMMON_FOLDER}/utils/fd-utils.hpp - ${COMMON_FOLDER}/utils/exception.hpp) + ${COMMON_FOLDER}/utils/exception.hpp + ${COMMON_FOLDER}/utils/channel.hpp + ${COMMON_FOLDER}/utils/environment.hpp + ${COMMON_FOLDER}/utils/execute.hpp) +FILE(GLOB HEADERS_NETLINK ${COMMON_FOLDER}/netlink/*.hpp) FILE(GLOB SRCS *.cpp *.hpp) FILE(GLOB SRCS_UTILS ${COMMON_FOLDER}/utils/fd-utils.cpp - ${COMMON_FOLDER}/utils/exception.cpp) + ${COMMON_FOLDER}/utils/exception.cpp + ${COMMON_FOLDER}/utils/channel.cpp + ${COMMON_FOLDER}/utils/environment.cpp + ${COMMON_FOLDER}/utils/execute.cpp) +FILE(GLOB SRCS_NETLINK ${COMMON_FOLDER}/netlink/*.cpp) SET(_LIB_VERSION_ "${VERSION}") SET(_LIB_SOVERSION_ "0") SET(PC_FILE "lib${PROJECT_NAME}.pc") ## Setup target ################################################################ -ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS} ${SRCS_UTILS}) +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS} ${SRCS_UTILS} ${SRCS_NETLINK}) SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${_LIB_SOVERSION_} VERSION ${_LIB_VERSION_} @@ -60,3 +68,5 @@ INSTALL(FILES ${HEADERS} DESTINATION ${INCLUDE_INSTALL_DIR}/lxcpp) INSTALL(FILES ${HEADERS_UTILS} DESTINATION ${INCLUDE_INSTALL_DIR}/lxcpp/utils) +INSTALL(FILES ${HEADERS_NETLINK} + DESTINATION ${INCLUDE_INSTALL_DIR}/lxcpp/netlink) diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index 956082d..b532336 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -24,12 +24,13 @@ FILE(GLOB_RECURSE common_SRCS ${COMMON_FOLDER}/*.cpp ${COMMON_FOLDER}/*.hpp) FILE(GLOB server_SRCS ${SERVER_FOLDER}/*.cpp ${SERVER_FOLDER}/*.hpp) FILE(GLOB client_SRCS ${CLIENT_FOLDER}/*.cpp ${CLIENT_FOLDER}/*.h) FILE(GLOB socket_test_SRCS ${SOCKET_TEST_FOLDER}/*.cpp ${SOCKET_TEST_FOLDER}/*.hpp) +FILE(GLOB lxcpp_test_SRCS lxcpp/lxcpp-api-compile-test.cpp) FILE(GLOB main_SRC ${SERVER_FOLDER}/main.cpp) LIST(REMOVE_ITEM server_SRCS ${main_SRC}) # We must compile socket-test separately, exclude it from unit-test build -LIST(REMOVE_ITEM project_SRCS ${socket_test_SRCS}) +LIST(REMOVE_ITEM project_SRCS ${socket_test_SRCS} ${lxcpp_test_SRCS}) ## Setup target ################################################################ @@ -39,6 +40,10 @@ ADD_EXECUTABLE(${UT_SERVER_CODENAME} ${project_SRCS} ${common_SRCS} ${server_SRC ## A fake target to test vasum-client C API ADD_EXECUTABLE("vasum-client-c-api-compile-test" client/client-c-api-compile-test.c) +## A fake target to test lxcpp API +ADD_EXECUTABLE("lxcpp-api-compile-test" lxcpp/lxcpp-api-compile-test.cpp) +TARGET_LINK_LIBRARIES("lxcpp-api-compile-test" lxcpp) + IF(NOT WITHOUT_SYSTEMD) SET(SOCKET_TEST_CODENAME "${PROJECT_NAME}-socket-test") diff --git a/tests/unit_tests/lxcpp/lxcpp-api-compile-test.cpp b/tests/unit_tests/lxcpp/lxcpp-api-compile-test.cpp new file mode 100644 index 0000000..2e72bfb --- /dev/null +++ b/tests/unit_tests/lxcpp/lxcpp-api-compile-test.cpp @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @author Krzysztof Dynowski (k.dynowski@samsumg.com) + * @brief Test compilation and linking with lxcpp library + */ + +#include "lxcpp/lxcpp.hpp" + +using namespace lxcpp; + +int main(int /*argc*/, const char * /*argv*/ []) +{ + Container* c = createContainer(); + delete c; +} -- 2.7.4 From 5c42af644173e5c3fed411dfcb8e5c56ba264f46 Mon Sep 17 00:00:00 2001 From: Pawel Kubik Date: Tue, 25 Aug 2015 10:30:03 +0200 Subject: [PATCH 07/16] Refactored logging code. [Feature] Improved logging messages [Cause] Inconsistent logging messages on different loggers [Solution] Unified logging messages [Verification] Build, install, run tests Change-Id: I7424733e97a4081707f64c3c4256021c560c7cfc --- common/lxc/exception.hpp | 4 ++ common/lxc/zone.cpp | 10 +++-- common/netlink/netlink-message.cpp | 15 ++++--- common/netlink/netlink.cpp | 15 ++++--- common/utils/eventfd.cpp | 6 +-- common/utils/exception.hpp | 5 +++ common/utils/fd-utils.cpp | 45 ++++++++++--------- common/utils/signal.cpp | 48 ++++++++++---------- common/utils/signalfd.cpp | 12 ++--- libs/ipc/epoll/event-poll.cpp | 25 ++++++----- libs/ipc/internals/request-queue.hpp | 5 ++- libs/ipc/internals/socket.cpp | 63 ++++++++++++++------------- libs/lxcpp/namespace.cpp | 5 ++- server/exception.hpp | 4 ++ server/host-dbus-connection.cpp | 5 ++- server/input-monitor.cpp | 17 +++++--- server/netdev.cpp | 35 +++++++++------ server/server.cpp | 6 +-- server/zone-provision.cpp | 13 +++--- server/zones-manager.cpp | 36 ++++++++------- tests/unit_tests/lxc/ut-zone.cpp | 2 +- tests/unit_tests/server/ut-input-monitor.cpp | 5 +-- tests/unit_tests/server/ut-zone-provision.cpp | 5 +-- zone-daemon/daemon-connection.cpp | 5 ++- 24 files changed, 221 insertions(+), 170 deletions(-) diff --git a/common/lxc/exception.hpp b/common/lxc/exception.hpp index 85272b5..379fe43 100644 --- a/common/lxc/exception.hpp +++ b/common/lxc/exception.hpp @@ -40,6 +40,10 @@ struct LxcException: public VasumException { LxcException(const std::string& error) : VasumException(error) {} }; +struct KeyNotFoundException: public LxcException { + + KeyNotFoundException(const std::string& error) : LxcException(error) {} +}; } // namespace vasum diff --git a/common/lxc/zone.cpp b/common/lxc/zone.cpp index 65207bd..611e043 100644 --- a/common/lxc/zone.cpp +++ b/common/lxc/zone.cpp @@ -101,8 +101,9 @@ LxcZone::LxcZone(const std::string& lxcPath, const std::string& zoneName) { mLxcContainer = lxc_container_new(zoneName.c_str(), lxcPath.c_str()); if (!mLxcContainer) { - LOGE("Could not initialize lxc zone " << zoneName << " in path " << lxcPath); - throw LxcException("Could not initialize lxc zone"); + const std::string msg = "Could not initialize lxc zone " + zoneName + " in path " + lxcPath; + LOGE(msg); + throw LxcException(msg); } } @@ -121,8 +122,9 @@ std::string LxcZone::getConfigItem(const std::string& key) char buffer[1024]; int len = mLxcContainer->get_config_item(mLxcContainer, key.c_str(), buffer, sizeof(buffer)); if (len < 0) { - LOGE("Key '" << key << "' not found in zone " << getName()); - throw LxcException("Key not found"); + const std::string msg = "Key '" + key + "' not found in zone " + getName(); + LOGE(msg); + throw KeyNotFoundException(msg); } return buffer; } diff --git a/common/netlink/netlink-message.cpp b/common/netlink/netlink-message.cpp index 58aa1a2..cef7828 100644 --- a/common/netlink/netlink-message.cpp +++ b/common/netlink/netlink-message.cpp @@ -192,8 +192,9 @@ NetlinkResponse& NetlinkResponse::openNested(int ifla) { const rtattr *rta = asAttr(get(RTA_LENGTH(0))); if (rta->rta_type == ifla) { - LOGE("Wrong attribute type, expected: " << ifla << ", got: " << rta->rta_type); - throw VasumException("Wrong attribute type"); + const std::string msg = "Wrong attribute type, expected: " + std::to_string(ifla) + ", got: " + std::to_string(rta->rta_type); + LOGE(msg); + throw VasumException(msg); } int pos = mPosition; seek(RTA_LENGTH(0)); @@ -227,12 +228,14 @@ const char* NetlinkResponse::get(int ifla, int len) const { const rtattr *rta = asAttr(get(RTA_LENGTH(len < 0 ? 0 : len))); if (rta->rta_type != ifla) { - LOGE("Wrong attribute type, expected:" << ifla << ", got: " << rta->rta_type); - throw VasumException("Wrong attribute type"); + const std::string msg = "Wrong attribute type, expected: " + std::to_string(ifla) + ", got: " + std::to_string(rta->rta_type); + LOGE(msg); + throw VasumException(msg); } if (len >= 0 && rta->rta_len != RTA_LENGTH(len)) { - LOGE("Wrong attribute length, expected: " << rta->rta_len << ", got " << len); - throw VasumException("Wrong attribute length"); + const std::string msg = "Wrong attribute length, expected: " + std::to_string(rta->rta_len) + ", got: " + std::to_string(len); + LOGE(msg); + throw VasumException(msg); } return reinterpret_cast(RTA_DATA(get(rta->rta_len))); } diff --git a/common/netlink/netlink.cpp b/common/netlink/netlink.cpp index 1d966cb..3408293 100644 --- a/common/netlink/netlink.cpp +++ b/common/netlink/netlink.cpp @@ -75,8 +75,9 @@ void vsm_sendmsg(int fd, const struct msghdr *msg, int flags) { int ret = sendmsg(fd, msg, flags); if (ret < 0) { - LOGE("Can't send message: " << getSystemErrorMessage()); - throw VasumException("Can't send netlink message"); + const std::string msg = "Can't send netlink message: " + getSystemErrorMessage(); + LOGE(msg); + throw VasumException(msg); } } @@ -117,8 +118,9 @@ void Netlink::open(int netNsPid) if (bind(mFd, (struct sockaddr *)&local, sizeof(local)) < 0) { int err = errno; close(); - LOGE("Can't bind to socket: " << getSystemErrorMessage(err)); - throw VasumException("Can't set up netlink connection"); + const std::string msg = "Can't bind to socket: " + getSystemErrorMessage(err); + LOGE(msg); + throw VasumException(msg); } } @@ -187,8 +189,9 @@ std::unique_ptr> Netlink::rcv(unsigned int nlmsgSeq) } } if (lastOk == NULL) { - LOGE("Something went terribly wrong. Check vsm_recvmsg function"); - throw VasumException("Can't receive data from system"); + const std::string msg = "Can't receive data from the system"; + LOGE(msg); + throw VasumException(msg); } offset += NLMSG_ALIGN(ret); } while (lastOk->nlmsg_type != NLMSG_DONE && lastOk->nlmsg_flags & NLM_F_MULTI); diff --git a/common/utils/eventfd.cpp b/common/utils/eventfd.cpp index 9af1114..bc5e64a 100644 --- a/common/utils/eventfd.cpp +++ b/common/utils/eventfd.cpp @@ -40,9 +40,9 @@ EventFD::EventFD() { mFD = ::eventfd(0, EFD_SEMAPHORE | EFD_CLOEXEC); if (mFD == -1) { - const std::string msg = getSystemErrorMessage(); - LOGE("Error in eventfd: " << msg); - throw UtilsException("Error in eventfd: " + msg); + const std::string msg = "Error in eventfd: " + getSystemErrorMessage(); + LOGE(msg); + throw UtilsException(msg); } } diff --git a/common/utils/exception.hpp b/common/utils/exception.hpp index ca5564a..fda0554 100644 --- a/common/utils/exception.hpp +++ b/common/utils/exception.hpp @@ -39,6 +39,11 @@ struct UtilsException: public std::runtime_error { UtilsException(const std::string& error) : std::runtime_error(error) {} }; +struct ProvisionExistsException: public UtilsException { + + ProvisionExistsException(const std::string& error) : UtilsException(error) {} +}; + /** * Return string describing error number * it is wrapper for strerror_r diff --git a/common/utils/fd-utils.cpp b/common/utils/fd-utils.cpp index 030d1fc..3b7b998 100644 --- a/common/utils/fd-utils.cpp +++ b/common/utils/fd-utils.cpp @@ -69,14 +69,15 @@ void waitForEvent(int fd, if (errno == EINTR) { continue; } - const std::string msg = getSystemErrorMessage(); - LOGE("Error in poll: " + msg); - throw UtilsException("Error in poll: " + msg); + const std::string msg = "Error in poll: " + getSystemErrorMessage(); + LOGE(msg); + throw UtilsException(msg); } if (ret == 0) { - LOGE("Timeout in read"); - throw UtilsException("Timeout in read"); + const std::string msg = "Timeout in read"; + LOGE(msg); + throw UtilsException(msg); } if (fds[0].revents & event) { @@ -85,8 +86,9 @@ void waitForEvent(int fd, } if (fds[0].revents & POLLHUP) { - LOGW("Peer disconnected"); - throw UtilsException("Peer disconnected"); + const std::string msg = "Peer disconnected"; + LOGW(msg); + throw UtilsException(msg); } } } @@ -144,9 +146,9 @@ void write(int fd, const void* bufferPtr, const size_t size, int timeoutMS) // Neglected errors LOGD("Retrying write"); } else { - const std::string msg = getSystemErrorMessage(); - LOGE("Error during writing: " + msg); - throw UtilsException("Error during writing: " + msg); + const std::string msg = "Error during writing: " + getSystemErrorMessage(); + LOGE(msg); + throw UtilsException(msg); } waitForEvent(fd, POLLOUT, deadline); @@ -170,16 +172,17 @@ void read(int fd, void* bufferPtr, const size_t size, int timeoutMS) break; } if (n == 0) { - LOGW("Peer disconnected"); - throw UtilsException("Peer disconnected"); + const std::string msg = "Peer disconnected"; + LOGW(msg); + throw UtilsException(msg); } } else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { // Neglected errors LOGD("Retrying read"); } else { - const std::string msg = getSystemErrorMessage(); - LOGE("Error during reading: " + msg); - throw UtilsException("Error during reading: " + msg); + const std::string msg = "Error during reading: " + getSystemErrorMessage(); + LOGE(msg); + throw UtilsException(msg); } waitForEvent(fd, POLLIN, deadline); @@ -190,9 +193,9 @@ unsigned int getMaxFDNumber() { struct rlimit rlim; if (-1 == getrlimit(RLIMIT_NOFILE, &rlim)) { - const std::string msg = getSystemErrorMessage(); - LOGE("Error during getrlimit: " + msg); - throw UtilsException("Error during getrlimit: " + msg); + const std::string msg = "Error during getrlimit: " + getSystemErrorMessage(); + LOGE(msg); + throw UtilsException(msg); } return rlim.rlim_cur; } @@ -203,9 +206,9 @@ void setMaxFDNumber(unsigned int limit) rlim.rlim_cur = limit; rlim.rlim_max = limit; if (-1 == setrlimit(RLIMIT_NOFILE, &rlim)) { - const std::string msg = getSystemErrorMessage(); - LOGE("Error during setrlimit: " + msg); - throw UtilsException("Error during setrlimit: " + msg); + const std::string msg = "Error during setrlimit: " + getSystemErrorMessage(); + LOGE(msg); + throw UtilsException(msg); } } diff --git a/common/utils/signal.cpp b/common/utils/signal.cpp index cdd79e6..bad3b0b 100644 --- a/common/utils/signal.cpp +++ b/common/utils/signal.cpp @@ -39,24 +39,24 @@ void setSignalMask(int how, const ::sigset_t& set) { int ret = ::pthread_sigmask(how, &set, nullptr /*&oldSet*/); if(ret != 0) { - const std::string msg = getSystemErrorMessage(ret); - LOGE("Error in pthread_sigmask: " << msg); - throw UtilsException("Error in pthread_sigmask: " + msg); + const std::string msg = "Error in pthread_sigmask: " + getSystemErrorMessage(ret); + LOGE(msg); + throw UtilsException(msg); } } void changeSignal(int how, const int sigNum) { ::sigset_t set; if(-1 == ::sigemptyset(&set)) { - const std::string msg = getSystemErrorMessage(); - LOGE("Error in sigfillset: " << msg); - throw UtilsException("Error in sigfillset: " + msg); + const std::string msg = "Error in sigfillset: " + getSystemErrorMessage(); + LOGE(msg); + throw UtilsException(msg); } if(-1 ==::sigaddset(&set, sigNum)) { - const std::string msg = getSystemErrorMessage(); - LOGE("Error in sigdelset: " << msg); - throw UtilsException("Error in sigdelset: " + msg); + const std::string msg = "Error in sigdelset: " + getSystemErrorMessage(); + LOGE(msg); + throw UtilsException(msg); } setSignalMask(how, set); @@ -69,9 +69,9 @@ void changeSignal(int how, const int sigNum) { ::sigset_t set; int ret = ::pthread_sigmask(0 /*ignored*/, nullptr /*get the oldset*/, &set); if(ret != 0) { - const std::string msg = getSystemErrorMessage(ret); - LOGE("Error in pthread_sigmask: " << msg); - throw UtilsException("Error in pthread_sigmask: " + msg); + const std::string msg = "Error in pthread_sigmask: " + getSystemErrorMessage(ret); + LOGE(msg); + throw UtilsException(msg); } return set; } @@ -82,9 +82,9 @@ bool isSignalBlocked(const int sigNum) int ret = ::sigismember(&set, sigNum); if(-1 == ret) { - const std::string msg = getSystemErrorMessage(); - LOGE("Error in sigismember: " << msg); - throw UtilsException("Error in sigismember: " + msg); + const std::string msg = "Error in sigismember: " + getSystemErrorMessage(); + LOGE(msg); + throw UtilsException(msg); } return ret == 1; @@ -99,16 +99,16 @@ void signalBlockAllExcept(const std::initializer_list& signals) { ::sigset_t set; if(-1 == ::sigfillset(&set)) { - const std::string msg = getSystemErrorMessage(); - LOGE("Error in sigfillset: " << msg); - throw UtilsException("Error in sigfillset: " + msg); + const std::string msg = "Error in sigfillset: " + getSystemErrorMessage(); + LOGE(msg); + throw UtilsException(msg); } for(const int s: signals) { if(-1 == ::sigaddset(&set, s)) { - const std::string msg = getSystemErrorMessage(); - LOGE("Error in sigaddset: " << msg); - throw UtilsException("Error in sigaddset: " + msg); + const std::string msg = "Error in sigaddset: " + getSystemErrorMessage(); + LOGE(msg); + throw UtilsException(msg); } } setSignalMask(SIG_BLOCK, set); @@ -126,9 +126,9 @@ void signalIgnore(const std::initializer_list& signals) for(const int s: signals) { if(-1 == ::sigaction(s, &act, nullptr)) { - const std::string msg = getSystemErrorMessage(); - LOGE("Error in sigaction: " << msg); - throw UtilsException("Error in sigaction: " + msg); + const std::string msg = "Error in sigaction: " + getSystemErrorMessage(); + LOGE(msg); + throw UtilsException(msg); } } } diff --git a/common/utils/signalfd.cpp b/common/utils/signalfd.cpp index 6ffa5cb..61d04d5 100644 --- a/common/utils/signalfd.cpp +++ b/common/utils/signalfd.cpp @@ -39,9 +39,9 @@ SignalFD::SignalFD(ipc::epoll::EventPoll& eventPoll) mFD = ::signalfd(-1, &set, SFD_CLOEXEC); if (mFD == -1) { - const std::string msg = getSystemErrorMessage(); - LOGE("Error in signalfd: " << msg); - throw UtilsException("Error in signalfd: " + msg); + const std::string msg = "Error in signalfd: " + getSystemErrorMessage(); + LOGE(msg); + throw UtilsException(msg); } mEventPoll.addFD(mFD, EPOLLIN, std::bind(&SignalFD::handleInternal, this)); @@ -66,9 +66,9 @@ void SignalFD::setHandler(const int sigNum, const Callback&& callback) int error = ::signalfd(mFD, &set, SFD_CLOEXEC); if (error != mFD) { - const std::string msg = getSystemErrorMessage(); - LOGE("Error in signalfd: " << msg); - throw UtilsException("Error in signalfd: " + msg); + const std::string msg = "Error in signalfd: " + getSystemErrorMessage(); + LOGE(msg); + throw UtilsException(msg); } mCallbacks.insert({sigNum, callback}); diff --git a/libs/ipc/epoll/event-poll.cpp b/libs/ipc/epoll/event-poll.cpp index 650e121..c4b1f40 100644 --- a/libs/ipc/epoll/event-poll.cpp +++ b/libs/ipc/epoll/event-poll.cpp @@ -42,8 +42,9 @@ EventPoll::EventPoll() : mPollFD(::epoll_create1(EPOLL_CLOEXEC)) { if (mPollFD == -1) { - LOGE("Failed to create epoll: " << getSystemErrorMessage()); - throw UtilsException("Could not create epoll"); + const std::string msg = "Failed to create epoll: " + getSystemErrorMessage(); + LOGE(msg); + throw UtilsException(msg); } } @@ -69,13 +70,15 @@ void EventPoll::addFD(const int fd, const Events events, Callback&& callback) std::lock_guard lock(mMutex); if (mCallbacks.find(fd) != mCallbacks.end()) { - LOGE("Already added fd: " << fd); - throw UtilsException("FD already added"); + const std::string msg = "fd " + std::to_string(fd) + " already added"; + LOGE(msg); + throw UtilsException(msg); } if (!addFDInternal(fd, events)) { - LOGE("Could not add fd"); - throw UtilsException("Could not add fd"); + const std::string msg = "Could not add fd"; + LOGE(msg); + throw UtilsException(msg); } mCallbacks.insert({fd, std::make_shared(std::move(callback))}); @@ -86,8 +89,9 @@ void EventPoll::modifyFD(const int fd, const Events events) { // No need to lock and check mCallbacks map if (!modifyFDInternal(fd, events)) { - LOGE("Could not modify fd: " << fd); - throw UtilsException("Could not modify fd"); + const std::string msg = "Could not modify fd: " + std::to_string(fd); + LOGE(msg); + throw UtilsException(msg); } } @@ -117,8 +121,9 @@ bool EventPoll::dispatchIteration(const int timeoutMs) if (errno == EINTR) { continue; } - LOGE("Failed to wait on epoll: " << getSystemErrorMessage()); - throw UtilsException("Could not wait for event"); + const std::string msg = "Failed to wait on epoll: " + getSystemErrorMessage(); + LOGE(msg); + throw UtilsException(msg); } // callback could be removed in the meantime, so be careful, find it inside lock diff --git a/libs/ipc/internals/request-queue.hpp b/libs/ipc/internals/request-queue.hpp index 810175f..e0951bd 100644 --- a/libs/ipc/internals/request-queue.hpp +++ b/libs/ipc/internals/request-queue.hpp @@ -157,8 +157,9 @@ typename RequestQueue::Request RequestQueue::pop() Lock lock(mStateMutex); mEventFD.receive(); if (mRequests.empty()) { - LOGE("Request queue is empty"); - throw IPCException("Request queue is empty"); + const std::string msg = "Request queue is empty"; + LOGE(msg); + throw IPCException(msg); } Request request = std::move(mRequests.front()); mRequests.pop_front(); diff --git a/libs/ipc/internals/socket.cpp b/libs/ipc/internals/socket.cpp index c58809d..a88ff0d 100644 --- a/libs/ipc/internals/socket.cpp +++ b/libs/ipc/internals/socket.cpp @@ -52,9 +52,9 @@ void setFdOptions(int fd) { // Prevent from inheriting fd by zones if (-1 == ::fcntl(fd, F_SETFD, FD_CLOEXEC)) { - const std::string msg = getSystemErrorMessage(); - LOGE("Error in fcntl: " + msg); - throw IPCException("Error in fcntl: " + msg); + const std::string msg = "Error in fcntl: " + getSystemErrorMessage(); + LOGE(msg); + throw IPCException(msg); } } @@ -94,9 +94,9 @@ std::shared_ptr Socket::accept() { int sockfd = ::accept(mFD, nullptr, nullptr); if (sockfd == -1) { - const std::string msg = getSystemErrorMessage(); - LOGE("Error in accept: " << msg); - throw IPCException("Error in accept: " + msg); + const std::string msg = "Error in accept: " + getSystemErrorMessage(); + LOGE(msg); + throw IPCException(msg); } setFdOptions(sockfd); return std::make_shared(sockfd); @@ -119,8 +119,9 @@ int Socket::getSystemdSocketInternal(const std::string& path) { int n = ::sd_listen_fds(-1 /*Block further calls to sd_listen_fds*/); if (n < 0) { - LOGE("sd_listen_fds fails with errno: " << n); - throw IPCException("sd_listen_fds fails with errno: " + std::to_string(n)); + const std::string msg = "sd_listen_fds failed: " + getSystemErrorMessage(-n); + LOGE(msg); + throw IPCException(msg); } for (int fd = SD_LISTEN_FDS_START; @@ -140,15 +141,16 @@ int Socket::createSocketInternal(const std::string& path) { // Isn't the path too long? if (path.size() >= sizeof(sockaddr_un::sun_path)) { - LOGE("Socket's path too long"); - throw IPCException("Socket's path too long"); + const std::string msg = "Socket's path too long"; + LOGE(msg); + throw IPCException(msg); } int sockfd = ::socket(AF_UNIX, SOCK_STREAM, 0); if (sockfd == -1) { - const std::string msg = getSystemErrorMessage(); - LOGE("Error in socket: " + msg); - throw IPCException("Error in socket: " + msg); + const std::string msg = "Error in socket: " + getSystemErrorMessage(); + LOGE(msg); + throw IPCException(msg); } setFdOptions(sockfd); @@ -162,18 +164,18 @@ int Socket::createSocketInternal(const std::string& path) if (-1 == ::bind(sockfd, reinterpret_cast(&serverAddress), sizeof(struct sockaddr_un))) { - std::string message = getSystemErrorMessage(); utils::close(sockfd); - LOGE("Error in bind: " << message); - throw IPCException("Error in bind: " + message); + const std::string msg = "Error in bind: " + getSystemErrorMessage(); + LOGE(msg); + throw IPCException(msg); } if (-1 == ::listen(sockfd, MAX_QUEUE_LENGTH)) { - std::string message = getSystemErrorMessage(); utils::close(sockfd); - LOGE("Error in listen: " << message); - throw IPCException("Error in listen: " + message); + const std::string msg = "Error in listen: " + getSystemErrorMessage(); + LOGE(msg); + throw IPCException(msg); } return sockfd; @@ -199,15 +201,16 @@ Socket Socket::connectSocket(const std::string& path) { // Isn't the path too long? if (path.size() >= sizeof(sockaddr_un::sun_path)) { - LOGE("Socket's path too long"); - throw IPCException("Socket's path too long"); + const std::string msg = "Socket's path too long"; + LOGE(msg); + throw IPCException(msg); } int fd = socket(AF_UNIX, SOCK_STREAM, 0); if (fd == -1) { - const std::string msg = getSystemErrorMessage(); - LOGE("Error in socket: " + msg); - throw IPCException("Error in socket: " + msg); + const std::string msg = "Error in socket: " + getSystemErrorMessage(); + LOGE(msg); + throw IPCException(msg); } setFdOptions(fd); @@ -218,19 +221,19 @@ Socket Socket::connectSocket(const std::string& path) if (-1 == connect(fd, reinterpret_cast(&serverAddress), sizeof(struct sockaddr_un))) { - const std::string msg = getSystemErrorMessage(); utils::close(fd); - LOGE("Error in connect: " + msg); - throw IPCException("Error in connect: " + msg); + const std::string msg = "Error in connect: " + getSystemErrorMessage(); + LOGE(msg); + throw IPCException(msg); } // Nonblock socket int flags = fcntl(fd, F_GETFL, 0); if (-1 == fcntl(fd, F_SETFL, flags | O_NONBLOCK)) { - const std::string msg = getSystemErrorMessage(); utils::close(fd); - LOGE("Error in fcntl: " + msg); - throw IPCException("Error in fcntl: " + msg); + const std::string msg = "Error in fcntl: " + getSystemErrorMessage(); + LOGE(msg); + throw IPCException(msg); } return Socket(fd); diff --git a/libs/lxcpp/namespace.cpp b/libs/lxcpp/namespace.cpp index 35bc140..0ee8c88 100644 --- a/libs/lxcpp/namespace.cpp +++ b/libs/lxcpp/namespace.cpp @@ -52,8 +52,9 @@ std::string toString(const Namespace ns) case Namespace::NET: return "net"; default: - LOGE("Bad namespace passed to the function"); - throw BadArgument("Bad namespace passed to the function"); + const std::string msg = "Bad namespace passed to the function"; + LOGE(msg); + throw BadArgument(msg); } } diff --git a/server/exception.hpp b/server/exception.hpp index bf5a106..e1b3be4 100644 --- a/server/exception.hpp +++ b/server/exception.hpp @@ -82,6 +82,10 @@ struct InputMonitorException: public ServerException { InputMonitorException(const std::string& error) : ServerException(error) {} }; +struct TimeoutException: public InputMonitorException { + + TimeoutException(const std::string& error) : InputMonitorException (error) {} +}; } diff --git a/server/host-dbus-connection.cpp b/server/host-dbus-connection.cpp index ce415c8..b5a0625 100644 --- a/server/host-dbus-connection.cpp +++ b/server/host-dbus-connection.cpp @@ -62,8 +62,9 @@ HostDbusConnection::HostDbusConnection(ZonesManager* zonesManagerPtr) std::bind(&HostDbusConnection::onNameLost, this)); if (!waitForName(NAME_ACQUIRED_TIMEOUT)) { - LOGE("Could not acquire dbus name: " << api::dbus::BUS_NAME); - throw HostConnectionException("Could not acquire dbus name: " + api::dbus::BUS_NAME); + const std::string msg = "Could not acquire dbus name: " + api::dbus::BUS_NAME; + LOGE(msg); + throw HostConnectionException(msg); } LOGT("Registering DBUS interface"); diff --git a/server/input-monitor.cpp b/server/input-monitor.cpp index bb65b90..45982af 100644 --- a/server/input-monitor.cpp +++ b/server/input-monitor.cpp @@ -71,13 +71,15 @@ InputMonitor::InputMonitor(ipc::epoll::EventPoll& eventPoll, , mEventPoll(eventPoll) { if (mConfig.timeWindowMs > MAX_TIME_WINDOW_SEC * 1000L) { - LOGE("Time window exceeds maximum: " << MAX_TIME_WINDOW_SEC); - throw InputMonitorException("Time window exceeds maximum"); + const std::string msg = "Time window exceeds maximum: " + MAX_TIME_WINDOW_SEC; + LOGE(msg); + throw TimeoutException(msg); } if (mConfig.numberOfEvents > MAX_NUMBER_OF_EVENTS) { - LOGE("Number of events exceeds maximum: " << MAX_NUMBER_OF_EVENTS); - throw InputMonitorException("Number of events exceeds maximum"); + const std::string msg = "Number of events exceeds maximum: " + MAX_NUMBER_OF_EVENTS; + LOGE(msg); + throw InputMonitorException(msg); } mDevicePath = getDevicePath(); @@ -185,9 +187,10 @@ void InputMonitor::setHandler(const std::string& devicePath) // We need NONBLOCK for FIFOs in the tests mFd = ::open(devicePath.c_str(), O_RDONLY | O_NONBLOCK | O_CLOEXEC); if (mFd < 0) { - LOGE("Cannot create input monitor channel. Device file: " << - devicePath << " doesn't exist"); - throw InputMonitorException("Device does not exist"); + const std::string msg = "Cannot create input monitor channel. Device file: " + + devicePath + " doesn't exist"; + LOGE(msg); + throw InputMonitorException(msg); } mEventPoll.addFD(mFd, EPOLLIN, std::bind(&InputMonitor::handleInternal, this, _1, _2)); } diff --git a/server/netdev.cpp b/server/netdev.cpp index 3086e7f..dc8642c 100644 --- a/server/netdev.cpp +++ b/server/netdev.cpp @@ -98,8 +98,9 @@ string getUniqueVethName() uint32_t getInterfaceIndex(const string& name) { uint32_t index = if_nametoindex(name.c_str()); if (!index) { - LOGE("Can't get " << name << " interface index (" << getSystemErrorMessage() << ")"); - throw ZoneOperationException("Can't find interface"); + const std::string msg = "Can't get " + name + " interface index (" + getSystemErrorMessage() + ")"; + LOGE(msg); + throw ZoneOperationException(msg); } return index; } @@ -163,8 +164,9 @@ void attachToBridge(const string& bridge, const string& netdev) uint32_t index = getInterfaceIndex(netdev); int fd = socket(AF_LOCAL, SOCK_STREAM, 0); if (fd < 0) { - LOGE("Can't open socket (" << getSystemErrorMessage() << ")"); - throw ZoneOperationException("Can't attach to bridge"); + const std::string msg = "Can't open socket (" + getSystemErrorMessage() + ")"; + LOGE(msg); + throw ZoneOperationException(msg); } struct ifreq ifr = utils::make_clean(); @@ -175,8 +177,9 @@ void attachToBridge(const string& bridge, const string& netdev) int error = errno; //TODO: Close can be interrupted. Move util functions from ipc ::close(fd); - LOGE("Can't attach to bridge (" + getSystemErrorMessage(error) + ")"); - throw ZoneOperationException("Can't attach to bridge"); + const std::string msg = "Can't attach to bridge (" + getSystemErrorMessage(error) + ")"; + LOGE(msg); + throw ZoneOperationException(msg); } close(fd); } @@ -276,8 +279,9 @@ std::vector getIpAddresses(const pid_t nsPid, int family, uint32_t index) } addr = inet_ntop(family, addr, buf, sizeof(buf)); if (addr == NULL) { - LOGE("Can't convert ip address: " << getSystemErrorMessage()); - throw VasumException("Can't get ip address"); + const std::string msg = "Can't convert ip address: " + getSystemErrorMessage(); + LOGE(msg); + throw VasumException(msg); } attrs.push_back(make_tuple("ip", buf)); break; @@ -594,8 +598,9 @@ void setAttrs(const pid_t nsPid, const std::string& netdev, const Attrs& attrs) for (const auto& addrAttr : split(params, ip, is_any_of(","))) { size_t pos = addrAttr.find(":"); if (pos == string::npos || pos == addrAttr.length()) { - LOGE("Wrong input data format: ill formed address attribute: " << addrAttr); - throw VasumException("Wrong input data format: ill formed address attribute"); + const std::string msg = "Wrong input data format: ill formed address attribute: " + addrAttr; + LOGE(msg); + throw VasumException(msg); } attrs.push_back(make_tuple(addrAttr.substr(0, pos), addrAttr.substr(pos + 1))); } @@ -614,15 +619,17 @@ void deleteIpAddress(const pid_t nsPid, uint32_t index = getInterfaceIndex(netdev, nsPid); size_t slash = ip.find('/'); if (slash == string::npos) { - LOGE("Wrong address format: it is not CIDR notation: can't find '/'"); - throw VasumException("Wrong address format"); + const std::string msg = "Wrong address format: it is not CIDR notation: can't find '/'"; + LOGE(msg); + throw VasumException(msg); } int prefixlen = 0; try { prefixlen = stoi(ip.substr(slash + 1)); } catch (const std::exception& ex) { - LOGE("Wrong address format: invalid prefixlen"); - throw VasumException("Wrong address format: invalid prefixlen"); + const std::string msg = "Wrong address format: invalid prefixlen"; + LOGE(msg); + throw VasumException(msg); } deleteIpAddress(nsPid, index, ip.substr(0, slash), prefixlen, getIpFamily(ip)); } diff --git a/server/server.cpp b/server/server.cpp index a42d239..2fc8a65 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -131,9 +131,9 @@ void Server::terminate() LOGI("Terminating server"); int ret = ::pthread_kill(mDispatchingThread, SIGINT); if(ret != 0) { - const std::string msg = utils::getSystemErrorMessage(ret); - LOGE("Error during Server termination: " << msg); - throw ServerException("Error during Server termination: " + msg); + const std::string msg = "Error during Server termination: " + utils::getSystemErrorMessage(ret); + LOGE(msg); + throw ServerException(msg); } } diff --git a/server/zone-provision.cpp b/server/zone-provision.cpp index 4e99f83..ed0eeea 100644 --- a/server/zone-provision.cpp +++ b/server/zone-provision.cpp @@ -77,8 +77,9 @@ std::string ZoneProvision::declareProvision(ZoneProvisioningConfig::Provision&& return getId(existingProvision) == id; }); if (it != mProvisioningConfig.provisions.end()) { - LOGE("Can't add provision. It already exists: " << id); - throw UtilsException("Provision already exists"); + const std::string msg = "Can't add provision. It already exists: " + id; + LOGE(msg); + throw ProvisionExistsException(msg); } mProvisioningConfig.provisions.push_back(std::move(provision)); saveProvisioningConfig(); @@ -249,10 +250,10 @@ void ZoneProvision::link(const ZoneProvisioningConfig::Link& config) return; } } - LOGE("Failed to create hard link: path=host: " - << srcHostPath - << ", msg: Path prefix is not valid path"); - throw UtilsException("Failed to hard link: path prefix is not valid"); + const std::string msg = "Failed to create hard link: path=host: " + + srcHostPath + ", msg: Path prefix is not valid path"; + LOGE(msg); + throw UtilsException(msg); } std::string ZoneProvision::getId(const ZoneProvisioningConfig::File& file) diff --git a/server/zones-manager.cpp b/server/zones-manager.cpp index 5280d21..55e63f5 100644 --- a/server/zones-manager.cpp +++ b/server/zones-manager.cpp @@ -357,8 +357,9 @@ void ZonesManager::destroyZone(const std::string& zoneId) auto iter = findZone(zoneId); if (iter == mZones.end()) { - LOGE("Failed to destroy zone " << zoneId << ": no such zone"); - throw InvalidZoneIdException("No such zone"); + const std::string msg = "Failed to destroy zone " + zoneId + ": no such zone"; + LOGE(msg); + throw InvalidZoneIdException(msg); } get(iter).setDestroyOnExit(); @@ -1186,8 +1187,9 @@ int ZonesManager::getVTForNewZone() candidates.erase(zone->getVT()); } if (candidates.empty()) { - LOGE("No free VT for zone"); - throw ZoneOperationException("No free VT for zone"); + const std::string msg = "No free VT for zone"; + LOGE(msg); + throw ZoneOperationException(msg); } // return the smallest return *candidates.begin(); @@ -1197,13 +1199,15 @@ void ZonesManager::createZone(const std::string& id, const std::string& templateName) { if (id.empty() || !isalnum(id)) { - LOGE("Failed to add zone - invalid name."); - throw InvalidZoneIdException("Invalid name"); + const std::string msg = "Failed to add zone - invalid name."; + LOGE(msg); + throw InvalidZoneIdException(msg); } if (find(prohibitedZonesNames.begin(), prohibitedZonesNames.end(), id) != prohibitedZonesNames.end()) { - LOGE("Cannot create " << id << " zone - name is not allowed!"); - throw InvalidZoneIdException("Zone name is not allowed"); + const std::string msg = "Cannot create " + id + " zone - name is not allowed!"; + LOGE(msg); + throw InvalidZoneIdException(msg); } LOGI("Creating zone " << id); @@ -1216,14 +1220,15 @@ void ZonesManager::createZone(const std::string& id, // check if zone does not exist if (findZone(id) != mZones.end()) { - LOGE("Cannot create " << id << " zone - already exists!"); - throw InvalidZoneIdException("Already exists"); + const std::string msg = "Cannot create " + id + " zone - already exists!"; + LOGE(msg); + throw InvalidZoneIdException(msg); } if (fs::exists(fs::path(mConfig.zonesPath) / id)) { - LOGE("Cannot create " << id << " zone - file system already exists!"); - throw InvalidZoneIdException("Zone file system already exists but there is no configuration for it. " - "Check cleanUpZonesPath in daemon.conf"); + const std::string msg = "Cannot create " + id + " zone - file system already exists!"; + LOGE(msg); + throw InvalidZoneIdException(msg); } const std::string zonePathStr = utils::createFilePath(mConfig.zonesPath, id, "/"); @@ -1236,8 +1241,9 @@ void ZonesManager::createZone(const std::string& id, zonePathStr); if (!utils::launchAsRoot(copyImageContentsWrapper)) { - LOGE("Failed to copy zone image."); - throw ZoneOperationException("Failed to copy zone image."); + const std::string msg = "Failed to copy zone image."; + LOGE(msg); + throw ZoneOperationException(msg); } } diff --git a/tests/unit_tests/lxc/ut-zone.cpp b/tests/unit_tests/lxc/ut-zone.cpp index 80c003f..7dae96e 100644 --- a/tests/unit_tests/lxc/ut-zone.cpp +++ b/tests/unit_tests/lxc/ut-zone.cpp @@ -96,7 +96,7 @@ BOOST_AUTO_TEST_CASE(CreateDestroy) BOOST_CHECK(lxc.isDefined()); BOOST_CHECK_EQUAL(lxc.getConfigItem("lxc.rootfs"), ZONE_PATH + ZONE_NAME + "/rootfs"); - BOOST_CHECK_EXCEPTION(lxc.getConfigItem("xxx"), LxcException, WhatEquals("Key not found")); + BOOST_CHECK_THROW(lxc.getConfigItem("xxx"), KeyNotFoundException); BOOST_CHECK(lxc.destroy()); diff --git a/tests/unit_tests/server/ut-input-monitor.cpp b/tests/unit_tests/server/ut-input-monitor.cpp index 75079a2..c889bb9 100644 --- a/tests/unit_tests/server/ut-input-monitor.cpp +++ b/tests/unit_tests/server/ut-input-monitor.cpp @@ -127,9 +127,8 @@ BOOST_AUTO_TEST_CASE(ConfigTimeWindowMsTooHigh) ZonesManager cm(getPoll(), TEST_CONFIG_PATH); inputConfig.timeWindowMs = 50000; - BOOST_REQUIRE_EXCEPTION(InputMonitor inputMonitor(getPoll(), inputConfig, &cm), - InputMonitorException, - WhatEquals("Time window exceeds maximum")); + BOOST_REQUIRE_THROW(InputMonitor inputMonitor(getPoll(), inputConfig, &cm), + TimeoutException); } BOOST_AUTO_TEST_CASE(ConfigDeviceFilePathNotExisting) diff --git a/tests/unit_tests/server/ut-zone-provision.cpp b/tests/unit_tests/server/ut-zone-provision.cpp index 034552e..360ffda 100644 --- a/tests/unit_tests/server/ut-zone-provision.cpp +++ b/tests/unit_tests/server/ut-zone-provision.cpp @@ -257,9 +257,8 @@ BOOST_AUTO_TEST_CASE(DeclareMount) ZoneProvision zoneProvision = create({}); zoneProvision.declareMount("/fake/path1", "/fake/path2", "tmpfs", 077, "fake"); zoneProvision.declareMount("/fake/path2", "/fake/path2", "tmpfs", 077, "fake"); - BOOST_CHECK_EXCEPTION(zoneProvision.declareMount("/fake/path2", "/fake/path2", "tmpfs", 077, "fake"), - UtilsException, - WhatEquals("Provision already exists")); + BOOST_CHECK_THROW(zoneProvision.declareMount("/fake/path2", "/fake/path2", "tmpfs", 077, "fake"), + ProvisionExistsException); ZoneProvisioningConfig config; load(config); diff --git a/zone-daemon/daemon-connection.cpp b/zone-daemon/daemon-connection.cpp index 3fb40ac..e1cb734 100644 --- a/zone-daemon/daemon-connection.cpp +++ b/zone-daemon/daemon-connection.cpp @@ -58,8 +58,9 @@ DaemonConnection::DaemonConnection(const NameLostCallback& nameLostCallback, std::bind(&DaemonConnection::onNameLost, this)); if (!waitForNameAndSetCallback(NAME_ACQUIRED_TIMEOUT, nameLostCallback)) { - LOGE("Could not acquire dbus name: " << zone_daemon::api::BUS_NAME); - throw ZoneDaemonException("Could not acquire dbus name: " + zone_daemon::api::BUS_NAME); + const std::string msg = "Could not acquire dbus name: " + zone_daemon::api::BUS_NAME; + LOGE(msg); + throw ZoneDaemonException(msg); } LOGD("Setting callbacks"); -- 2.7.4 From bea6af081607f1fe7c5b8ffa34bd74f65fd2d0e3 Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Thu, 27 Aug 2015 17:32:21 +0200 Subject: [PATCH 08/16] Fix GetNetdevAttrs test [Feature] N/A [Cause] N/A [Solution] N/A [Verification] Build, install, run tests Change-Id: I75ba46b0a923622e07d857535496615ac1708ce3 --- tests/unit_tests/server/ut-zone.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/unit_tests/server/ut-zone.cpp b/tests/unit_tests/server/ut-zone.cpp index 0072d74..aefb29a 100644 --- a/tests/unit_tests/server/ut-zone.cpp +++ b/tests/unit_tests/server/ut-zone.cpp @@ -294,6 +294,7 @@ BOOST_AUTO_TEST_CASE(GetNetdevAttrs) bool gotMtu = false; bool gotFlags = false; bool gotType = false; + bool gotLink = false; for (auto& attr : attrs) { if (std::get<0>(attr) == "mtu") { BOOST_CHECK(!gotMtu); @@ -306,6 +307,9 @@ BOOST_AUTO_TEST_CASE(GetNetdevAttrs) BOOST_CHECK(!gotType); BOOST_CHECK_EQUAL(1 /*IFF_802_1Q_VLAN */, stol(std::get<1>(attr))); gotType = true; + } else if (std::get<0>(attr) == "link") { + BOOST_CHECK(!gotLink); + gotLink = true; } else { BOOST_CHECK_MESSAGE(false, "Got unexpected option " + std::get<0>(attr)); } -- 2.7.4 From 5bc4836840cd866fef8295e5f82a70e2cdb943b2 Mon Sep 17 00:00:00 2001 From: Pawel Kubik Date: Mon, 31 Aug 2015 12:34:44 +0200 Subject: [PATCH 09/16] Move ccolor to common/utils [Feature] Move ccolor.hpp and ccolor.cpp from libs/logger to common/utils [Cause] ccolor should be available to the CLI without logger as dependency [Solution] N/A [Verification] Build, install, run tests Change-Id: Ic16301b30bd90e60300e243ee8b2dac309eadfac --- {libs/logger => common/utils}/ccolor.cpp | 9 ++++----- {libs/logger => common/utils}/ccolor.hpp | 12 ++++++------ libs/logger/CMakeLists.txt | 13 +++++++++---- libs/logger/formatter.cpp | 18 +++++++++--------- 4 files changed, 28 insertions(+), 24 deletions(-) rename {libs/logger => common/utils}/ccolor.cpp (87%) rename {libs/logger => common/utils}/ccolor.hpp (85%) diff --git a/libs/logger/ccolor.cpp b/common/utils/ccolor.cpp similarity index 87% rename from libs/logger/ccolor.cpp rename to common/utils/ccolor.cpp index 9cc652d..d95dac9 100644 --- a/libs/logger/ccolor.cpp +++ b/common/utils/ccolor.cpp @@ -19,15 +19,14 @@ /** * @file * @author Dariusz Michaluk (d.michaluk@samsung.com) - * @brief Console color for StderrBackend logger + * @brief Console colors utility */ -#include "logger/config.hpp" -#include "logger/ccolor.hpp" +#include "utils/ccolor.hpp" #include -namespace logger { +namespace utils { std::string getConsoleEscapeSequence(Attributes attr, Color color) { @@ -38,4 +37,4 @@ std::string getConsoleEscapeSequence(Attributes attr, Color color) return std::string(command); } -} // namespace logger +} // namespace utils diff --git a/libs/logger/ccolor.hpp b/common/utils/ccolor.hpp similarity index 85% rename from libs/logger/ccolor.hpp rename to common/utils/ccolor.hpp index 47cc25e..1700967 100644 --- a/libs/logger/ccolor.hpp +++ b/common/utils/ccolor.hpp @@ -19,15 +19,15 @@ /** * @file * @author Dariusz Michaluk (d.michaluk@samsung.com) - * @brief Console color for StderrBackend logger + * @brief Console colors utility */ -#ifndef COMMON_LOGGER_CCOLOR_HPP -#define COMMON_LOGGER_CCOLOR_HPP +#ifndef COMMON_UTILS_CCOLOR_HPP +#define COMMON_UTILS_CCOLOR_HPP #include -namespace logger { +namespace utils { enum class Color : unsigned int { DEFAULT = 0, @@ -48,6 +48,6 @@ enum class Attributes : unsigned int { std::string getConsoleEscapeSequence(Attributes attr, Color color); -} // namespace logger +} // namespace utils -#endif // COMMON_LOGGER_CCOLOR_HPP +#endif // COMMON_UTILS_CCOLOR_HPP diff --git a/libs/logger/CMakeLists.txt b/libs/logger/CMakeLists.txt index 61027c2..6a65b34 100644 --- a/libs/logger/CMakeLists.txt +++ b/libs/logger/CMakeLists.txt @@ -21,15 +21,17 @@ PROJECT(Logger) MESSAGE(STATUS "") MESSAGE(STATUS "Generating makefile for the libLogger...") -FILE(GLOB HEADERS *.hpp) -FILE(GLOB SRCS *.cpp *.hpp) +FILE(GLOB HEADERS *.hpp) +FILE(GLOB SRCS *.cpp *.hpp) +FILE(GLOB HEADERS_UTILS ${COMMON_FOLDER}/utils/ccolor.hpp) +FILE(GLOB SRCS_UTILS ${COMMON_FOLDER}/utils/ccolor.cpp) SET(_LIB_VERSION_ "${VERSION}") SET(_LIB_SOVERSION_ "0") SET(PC_FILE "lib${PROJECT_NAME}.pc") ## Setup target ################################################################ -ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS}) +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS} ${SRCS_UTILS}) SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${_LIB_SOVERSION_} VERSION ${_LIB_VERSION_} @@ -40,7 +42,7 @@ IF(NOT WITHOUT_SYSTEMD) PKG_CHECK_MODULES(LOGGER_DEPS REQUIRED libsystemd-journal) ENDIF(NOT WITHOUT_SYSTEMD) -INCLUDE_DIRECTORIES(${LIBS_FOLDER}) +INCLUDE_DIRECTORIES(${LIBS_FOLDER} ${COMMON_FOLDER}) INCLUDE_DIRECTORIES(SYSTEM ${LOGGER_DEPS_INCLUDE_DIRS}) TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} ${LOGGER_DEPS_LIBRARIES}) @@ -57,3 +59,6 @@ INSTALL(TARGETS ${PROJECT_NAME} INSTALL(FILES ${HEADERS} DESTINATION ${INCLUDE_INSTALL_DIR}/vasum-tools/logger) + +INSTALL(FILES ${HEADERS_UTILS} + DESTINATION ${INCLUDE_INSTALL_DIR}/vasum-tools/logger/utils) diff --git a/libs/logger/formatter.cpp b/libs/logger/formatter.cpp index 815a111..17bed53 100644 --- a/libs/logger/formatter.cpp +++ b/libs/logger/formatter.cpp @@ -24,7 +24,7 @@ #include "logger/config.hpp" #include "logger/formatter.hpp" -#include "logger/ccolor.hpp" +#include "utils/ccolor.hpp" #include #include @@ -78,25 +78,25 @@ std::string LogFormatter::getConsoleColor(LogLevel logLevel) { switch (logLevel) { case LogLevel::ERROR: - return getConsoleEscapeSequence(Attributes::BOLD, Color::RED); + return utils::getConsoleEscapeSequence(utils::Attributes::BOLD, utils::Color::RED); case LogLevel::WARN: - return getConsoleEscapeSequence(Attributes::BOLD, Color::YELLOW); + return utils::getConsoleEscapeSequence(utils::Attributes::BOLD, utils::Color::YELLOW); case LogLevel::INFO: - return getConsoleEscapeSequence(Attributes::BOLD, Color::BLUE); + return utils::getConsoleEscapeSequence(utils::Attributes::BOLD, utils::Color::BLUE); case LogLevel::DEBUG: - return getConsoleEscapeSequence(Attributes::DEFAULT, Color::GREEN); + return utils::getConsoleEscapeSequence(utils::Attributes::DEFAULT, utils::Color::GREEN); case LogLevel::TRACE: - return getConsoleEscapeSequence(Attributes::DEFAULT, Color::BLACK); + return utils::getConsoleEscapeSequence(utils::Attributes::DEFAULT, utils::Color::BLACK); case LogLevel::HELP: - return getConsoleEscapeSequence(Attributes::BOLD, Color::MAGENTA); + return utils::getConsoleEscapeSequence(utils::Attributes::BOLD, utils::Color::MAGENTA); default: - return getConsoleEscapeSequence(Attributes::DEFAULT, Color::DEFAULT); + return utils::getConsoleEscapeSequence(utils::Attributes::DEFAULT, utils::Color::DEFAULT); } } std::string LogFormatter::getDefaultConsoleColor(void) { - return getConsoleEscapeSequence(Attributes::DEFAULT, Color::DEFAULT); + return utils::getConsoleEscapeSequence(utils::Attributes::DEFAULT, utils::Color::DEFAULT); } std::string LogFormatter::stripProjectDir(const std::string& file, -- 2.7.4 From 73407867e8f6c282e3a9fc8dbe8bf9b623ff773e Mon Sep 17 00:00:00 2001 From: Pawel Kubik Date: Mon, 31 Aug 2015 16:29:47 +0200 Subject: [PATCH 10/16] Fixed clang compilation errors [Feature] Fixed clang compilation errors [Cause] C++ flags were being passed to the C compiler [Solution] Pass C++ flags to the C++ compiler only [Verification] Build using clang Change-Id: Ie9c7abfaea0ef47381bc045353d1ea3724a19671 --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 735b349..9823735 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,7 +35,7 @@ INCLUDE(GNUInstallDirs) IF (( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9)) OR ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )) - ADD_DEFINITIONS("-fdiagnostics-color=always") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fdiagnostics-color=always") ENDIF() ## Compiler flags, depending on the build type ################################# @@ -93,7 +93,7 @@ ADD_DEFINITIONS(-D__STDC_LIMIT_MACROS) IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") # Warn about documentation problems - ADD_DEFINITIONS("-Wdocumentation") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wdocumentation") IF(ALL_WARNINGS) # turn on every -W flags except a few explicitly mentioned -- 2.7.4 From 4ca9365ce360cfe9e2a916b1cb70a69b409c26cd Mon Sep 17 00:00:00 2001 From: Lukasz Kostyra Date: Thu, 13 Aug 2015 15:29:03 +0200 Subject: [PATCH 11/16] Change MessageID and PeerID type to UIDs [Feature] MessageID and PeerID are generated with UIDs - a timestamp and UUID pair. [Cause] Previously used unsigned ints might overflow and create a security issue. [Solution] Implement UID class, change MessageID and PeerID to use UID [Verification] Build, install, run tests Change-Id: I493cba8e55cc9985d3b2b544b78c434d4deb4191 --- common/api/ipc-method-result-builder.cpp | 2 +- libs/ipc/CMakeLists.txt | 2 +- libs/ipc/client.cpp | 2 +- libs/ipc/internals/processor.cpp | 48 ++++++++-------- libs/ipc/internals/processor.hpp | 11 ++++ libs/ipc/types.cpp | 24 ++++++-- libs/ipc/types.hpp | 4 +- libs/ipc/unique-id.cpp | 64 +++++++++++++++++++++ libs/ipc/unique-id.hpp | 97 ++++++++++++++++++++++++++++++++ packaging/vasum.spec | 2 + server/host-ipc-connection.cpp | 2 +- tests/unit_tests/ipc/ut-ipc.cpp | 3 +- tests/unit_tests/ipc/ut-unique-id.cpp | 73 ++++++++++++++++++++++++ 13 files changed, 300 insertions(+), 34 deletions(-) create mode 100644 libs/ipc/unique-id.cpp create mode 100644 libs/ipc/unique-id.hpp create mode 100644 tests/unit_tests/ipc/ut-unique-id.cpp diff --git a/common/api/ipc-method-result-builder.cpp b/common/api/ipc-method-result-builder.cpp index d7ac681..5d7e2c4 100644 --- a/common/api/ipc-method-result-builder.cpp +++ b/common/api/ipc-method-result-builder.cpp @@ -50,7 +50,7 @@ void IPCMethodResultBuilder::setError(const std::string& , const std::string& me std::string IPCMethodResultBuilder::getID() const { - return IPC_CONNECTION_PREFIX + std::to_string(mMethodResultPtr->getPeerID()); + return IPC_CONNECTION_PREFIX + mMethodResultPtr->getPeerID(); } } // namespace result diff --git a/libs/ipc/CMakeLists.txt b/libs/ipc/CMakeLists.txt index 2fce8cb..854e0de 100644 --- a/libs/ipc/CMakeLists.txt +++ b/libs/ipc/CMakeLists.txt @@ -50,7 +50,7 @@ SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES ## Link libraries ############################################################## IF(NOT WITHOUT_SYSTEMD) -PKG_CHECK_MODULES(IPC_DEPS REQUIRED libsystemd-daemon) +PKG_CHECK_MODULES(IPC_DEPS REQUIRED libsystemd-daemon uuid) ENDIF(NOT WITHOUT_SYSTEMD) INCLUDE_DIRECTORIES(${LIBS_FOLDER}) diff --git a/libs/ipc/client.cpp b/libs/ipc/client.cpp index 245faee..c5105f9 100644 --- a/libs/ipc/client.cpp +++ b/libs/ipc/client.cpp @@ -32,7 +32,7 @@ namespace ipc { Client::Client(epoll::EventPoll& eventPoll, const std::string& socketPath) : mEventPoll(eventPoll), - mServiceID(-1), + mServiceID(), mProcessor(eventPoll, "[CLIENT] "), mSocketPath(socketPath) { diff --git a/libs/ipc/internals/processor.cpp b/libs/ipc/internals/processor.cpp index a8c671e..fdbcbe8 100644 --- a/libs/ipc/internals/processor.cpp +++ b/libs/ipc/internals/processor.cpp @@ -26,7 +26,8 @@ #include "ipc/exception.hpp" #include "ipc/internals/processor.hpp" -#include "utils/exception.hpp" +#include "config/manager.hpp" +#include "config/exception.hpp" #include #include @@ -290,39 +291,36 @@ bool Processor::handleInput(const FileDescriptor fd) return false; } - - MethodID methodID; - MessageID messageID; + MessageHeader hdr; { try { // Read information about the incoming data Socket& socket = *peerIt->socketPtr; Socket::Guard guard = socket.getGuard(); - socket.read(&methodID, sizeof(methodID)); - socket.read(&messageID, sizeof(messageID)); - } catch (const UtilsException& e) { + config::loadFromFD(socket.getFD(), hdr); + } catch (const config::ConfigException& e) { LOGE(mLogPrefix + "Error during reading the socket"); removePeerInternal(peerIt, std::make_exception_ptr(IPCNaughtyPeerException())); return true; } - if (methodID == RETURN_METHOD_ID) { - return onReturnValue(peerIt, messageID); + if (hdr.methodID == RETURN_METHOD_ID) { + return onReturnValue(peerIt, hdr.messageID); } else { - if (mMethodsCallbacks.count(methodID)) { + if (mMethodsCallbacks.count(hdr.methodID)) { // Method - std::shared_ptr methodCallbacks = mMethodsCallbacks.at(methodID); - return onRemoteMethod(peerIt, methodID, messageID, methodCallbacks); + std::shared_ptr methodCallbacks = mMethodsCallbacks.at(hdr.methodID); + return onRemoteMethod(peerIt, hdr.methodID, hdr.messageID, methodCallbacks); - } else if (mSignalsCallbacks.count(methodID)) { + } else if (mSignalsCallbacks.count(hdr.methodID)) { // Signal - std::shared_ptr signalCallbacks = mSignalsCallbacks.at(methodID); - return onRemoteSignal(peerIt, methodID, messageID, signalCallbacks); + std::shared_ptr signalCallbacks = mSignalsCallbacks.at(hdr.methodID); + return onRemoteSignal(peerIt, hdr.methodID, hdr.messageID, signalCallbacks); } else { - LOGW(mLogPrefix + "No method or signal callback for methodID: " << methodID); + LOGW(mLogPrefix + "No method or signal callback for methodID: " << hdr.methodID); removePeerInternal(peerIt, std::make_exception_ptr(IPCNaughtyPeerException())); return true; @@ -503,12 +501,14 @@ bool Processor::onMethodRequest(MethodRequest& request) std::move(request.parse), std::move(request.process))); + MessageHeader hdr; try { // Send the call with the socket Socket& socket = *peerIt->socketPtr; Socket::Guard guard = socket.getGuard(); - socket.write(&request.methodID, sizeof(request.methodID)); - socket.write(&request.messageID, sizeof(request.messageID)); + hdr.methodID = request.methodID; + hdr.messageID = request.messageID; + config::saveToFD(socket.getFD(), hdr); LOGT(mLogPrefix + "Serializing the message"); request.serialize(socket.getFD(), request.data); } catch (const std::exception& e) { @@ -540,12 +540,14 @@ bool Processor::onSignalRequest(SignalRequest& request) return false; } + MessageHeader hdr; try { // Send the call with the socket Socket& socket = *peerIt->socketPtr; Socket::Guard guard = socket.getGuard(); - socket.write(&request.methodID, sizeof(request.methodID)); - socket.write(&request.messageID, sizeof(request.messageID)); + hdr.methodID = request.methodID; + hdr.messageID = request.messageID; + config::saveToFD(socket.getFD(), hdr); request.serialize(socket.getFD(), request.data); } catch (const std::exception& e) { LOGE(mLogPrefix + "Error during sending a signal: " << e.what()); @@ -627,12 +629,14 @@ bool Processor::onSendResultRequest(SendResultRequest& request) return true; } + MessageHeader hdr; try { // Send the call with the socket Socket& socket = *peerIt->socketPtr; Socket::Guard guard = socket.getGuard(); - socket.write(&RETURN_METHOD_ID, sizeof(RETURN_METHOD_ID)); - socket.write(&request.messageID, sizeof(request.messageID)); + hdr.methodID = RETURN_METHOD_ID; + hdr.messageID = request.messageID; + config::saveToFD(socket.getFD(), hdr); LOGT(mLogPrefix + "Serializing the message"); methodCallbacks->serialize(socket.getFD(), request.data); } catch (const std::exception& e) { diff --git a/libs/ipc/internals/processor.hpp b/libs/ipc/internals/processor.hpp index 7f7cd63..2706792 100644 --- a/libs/ipc/internals/processor.hpp +++ b/libs/ipc/internals/processor.hpp @@ -336,6 +336,17 @@ private: CONFIG_REGISTER_EMPTY }; + struct MessageHeader { + MethodID methodID; + MessageID messageID; + + CONFIG_REGISTER + ( + methodID, + messageID + ) + }; + struct RegisterSignalsProtocolMessage { RegisterSignalsProtocolMessage() = default; RegisterSignalsProtocolMessage(const std::vector& ids) diff --git a/libs/ipc/types.cpp b/libs/ipc/types.cpp index 0961b35..6098cb4 100644 --- a/libs/ipc/types.cpp +++ b/libs/ipc/types.cpp @@ -25,25 +25,39 @@ #include "config.hpp" #include "ipc/types.hpp" +#include "ipc/unique-id.hpp" #include "logger/logger.hpp" -#include +#include namespace ipc { namespace { -std::atomic gLastMessageID(0); -std::atomic gLastPeerID(0); +// complex types cannot be easily used with std::atomic - these require libatomic to be linked +// instead, secure the ID getters with mutex +MessageID gLastMessageID; +PeerID gLastPeerID; + +std::mutex gMessageIDMutex; +std::mutex gPeerIDMutex; } // namespace MessageID getNextMessageID() { - return ++gLastMessageID; + std::unique_lock lock(gMessageIDMutex); + UniqueID uid; + uid.generate(); + gLastMessageID = uid; + return gLastMessageID; } PeerID getNextPeerID() { - return ++gLastPeerID; + std::unique_lock lock(gPeerIDMutex); + UniqueID uid; + uid.generate(); + gLastPeerID = uid; + return gLastPeerID; } diff --git a/libs/ipc/types.hpp b/libs/ipc/types.hpp index ab4ed00..fad01b3 100644 --- a/libs/ipc/types.hpp +++ b/libs/ipc/types.hpp @@ -33,8 +33,8 @@ namespace ipc { typedef int FileDescriptor; typedef unsigned int MethodID; -typedef unsigned int MessageID; -typedef unsigned int PeerID; +typedef std::string MessageID; +typedef std::string PeerID; typedef std::function PeerCallback; typedef std::function& data)> SerializeCallback; diff --git a/libs/ipc/unique-id.cpp b/libs/ipc/unique-id.cpp new file mode 100644 index 0000000..bcdd4bc --- /dev/null +++ b/libs/ipc/unique-id.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Lukasz Kostyra + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +/** + * @file + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @brief Unique ID type definition + */ + +#include "unique-id.hpp" + +namespace ipc { + +UniqueID::UniqueID() +{ + mTime.tv_sec = 0; + mTime.tv_nsec = 0; + ::uuid_clear(mUUID); +} + +void UniqueID::generate() +{ + ::clock_gettime(CLOCK_REALTIME, &mTime); + ::uuid_generate_random(mUUID); +} + +bool UniqueID::operator==(const UniqueID& other) const +{ + return (mTime.tv_sec == other.mTime.tv_sec) + && (mTime.tv_nsec == other.mTime.tv_nsec) + && (::uuid_compare(mUUID, other.mUUID) == 0); // uuid_compare works just like strcmp +} + +UniqueID::operator std::string() const +{ + char uuid[37]; // uuid_unparse assures that it will print 36 chars + terminating zero + ::uuid_unparse(mUUID, uuid); + return std::to_string(mTime.tv_sec) + '.' + std::to_string(mTime.tv_nsec) + ':' + uuid; +} + +std::ostream& operator<<(std::ostream& str, const UniqueID& id) +{ + char uuid[37]; + ::uuid_unparse(id.mUUID, uuid); + str << id.mTime.tv_sec << "." << id.mTime.tv_nsec << ":" << uuid; + return str; +} + +} // namespace ipc diff --git a/libs/ipc/unique-id.hpp b/libs/ipc/unique-id.hpp new file mode 100644 index 0000000..bceda62 --- /dev/null +++ b/libs/ipc/unique-id.hpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Lukasz Kostyra + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +/** + * @file + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @brief Unique ID type declaration + */ + +#ifndef IPC_UNIQUE_ID_HPP +#define IPC_UNIQUE_ID_HPP + +#include +#include +#include +#include + +namespace ipc { + +class UniqueID { +public: + typedef struct timespec TimestampType; + typedef uuid_t UUIDType; + + /** + * Default constructor. Generates an empty ID. + */ + UniqueID(); + + /** + * Generate new timestamp and UUID pair. + */ + void generate(); + + /** + * Compare two IDs + * + * @param other Other ID to compare to. + * @return True if both timestamp and UUID are equal, false otherwise. + */ + bool operator==(const UniqueID& other) const; + + /** + * Casts current ID to string + */ + operator std::string() const; + + /** + * Overloaded << operator for debugging purposes. Used in ut-uid.cpp tests. + */ + friend std::ostream& operator<<(std::ostream& str, const UniqueID& id); + + + TimestampType mTime; //< timestamp when generate() was called + UUIDType mUUID; //< random UUID generated with libuuid +}; + +template +class hash; + +template <> +class hash +{ +public: + std::size_t operator()(const ipc::UniqueID& id) const + { + char uuid[37]; // 36 chars for UUID + terminating zero + ::uuid_unparse(id.mUUID, uuid); + + // STL does not provide correct hash implementation for char * + // Instead, just convert it to string + std::string uuids(uuid); + + return std::hash()(id.mTime.tv_sec) + ^ std::hash()(id.mTime.tv_nsec) + ^ std::hash()(uuids); + } +}; + +} // namespace ipc + +#endif // IPC_UNIQUE_ID_HPP diff --git a/packaging/vasum.spec b/packaging/vasum.spec index 22de326..2cd5dd8 100644 --- a/packaging/vasum.spec +++ b/packaging/vasum.spec @@ -437,6 +437,8 @@ The package provides libConfig development tools and libs. Summary: IPC library Group: Security/Other Requires: libConfig +Requires: libuuid +BuildRequires: libuuid-devel Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig diff --git a/server/host-ipc-connection.cpp b/server/host-ipc-connection.cpp index c2ba755..a575c70 100644 --- a/server/host-ipc-connection.cpp +++ b/server/host-ipc-connection.cpp @@ -42,7 +42,7 @@ HostIPCConnection::HostIPCConnection(ipc::epoll::EventPoll& eventPoll, ZonesMana ipc::PeerCallback removedCallback = [this](const ipc::PeerID peerID, const ipc::FileDescriptor) { - std::string id = api::IPC_CONNECTION_PREFIX + std::to_string(peerID); + std::string id = api::IPC_CONNECTION_PREFIX + peerID; mZonesManagerPtr->disconnectedCallback(id); }; mService.reset(new ipc::Service(eventPoll, HOST_IPC_SOCKET, diff --git a/tests/unit_tests/ipc/ut-ipc.cpp b/tests/unit_tests/ipc/ut-ipc.cpp index 8bb829e..853faa2 100644 --- a/tests/unit_tests/ipc/ut-ipc.cpp +++ b/tests/unit_tests/ipc/ut-ipc.cpp @@ -33,6 +33,7 @@ #include "ipc/service.hpp" #include "ipc/client.hpp" #include "ipc/types.hpp" +#include "ipc/unique-id.hpp" #include "ipc/result.hpp" #include "ipc/epoll/thread-dispatcher.hpp" #include "ipc/epoll/glib-dispatcher.hpp" @@ -224,7 +225,7 @@ PeerID connect(Service& s, Client& c) PeerID peerID = peerIDLatch.get(TIMEOUT); s.setNewPeerCallback(nullptr); - BOOST_REQUIRE_NE(peerID, 0); + BOOST_REQUIRE_NE(peerID, static_cast(ipc::UniqueID())); return peerID; } diff --git a/tests/unit_tests/ipc/ut-unique-id.cpp b/tests/unit_tests/ipc/ut-unique-id.cpp new file mode 100644 index 0000000..05ce1bb --- /dev/null +++ b/tests/unit_tests/ipc/ut-unique-id.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Lukasz Kostyra + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + + +/** + * @file + * @author Lukasz Kostyra (l.kostyra@samsung.com) + * @brief Unit tests of UID + */ + +#include "config.hpp" +#include "ut.hpp" + +#include "ipc/unique-id.hpp" + +#include +#include + +namespace { + +const std::string EMPTY_UUID = "00000000-0000-0000-0000-000000000000"; + +} // namespace + +BOOST_AUTO_TEST_SUITE(UniqueIDSuite) + +// constructor should provide empty timestamp and UUID +BOOST_AUTO_TEST_CASE(Constructor) +{ + ipc::UniqueID uid; + + BOOST_CHECK_EQUAL(static_cast(uid.mTime.tv_sec), 0); + BOOST_CHECK_EQUAL(uid.mTime.tv_nsec, 0); + char uuid[37]; // 36 chars + terminating zero + ::uuid_unparse(uid.mUUID, uuid); + BOOST_CHECK(EMPTY_UUID.compare(uuid) == 0); +} + +// generate one UID and compare with empty +BOOST_AUTO_TEST_CASE(Generate) +{ + ipc::UniqueID uid, emptyuid; + uid.generate(); + + BOOST_CHECK_NE(uid, emptyuid); +} + +// generate two UIDs and compare them +BOOST_AUTO_TEST_CASE(DoubleGenerate) +{ + ipc::UniqueID uid1, uid2; + + uid1.generate(); + uid2.generate(); + BOOST_CHECK_NE(uid1, uid2); +} + +BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From 42745f132f330133017084e7d10749a7ccbf48e3 Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Thu, 27 Aug 2015 17:06:30 +0200 Subject: [PATCH 12/16] lxcpp: Setting up environment variables [Feature] Setting up environement in attach Created the commands directory [Cause] N/A [Solution] N/A [Verification] Build, install, run tests Change-Id: I7526f04ca48e931be75a99cdbf774b4c5fbb5c35 --- libs/lxcpp/CMakeLists.txt | 17 ++-- libs/lxcpp/{ => commands}/attach-manager.cpp | 65 +++++++++---- libs/lxcpp/{ => commands}/attach-manager.hpp | 20 +++- libs/lxcpp/container-impl.cpp | 15 ++- libs/lxcpp/container.hpp | 2 +- libs/lxcpp/environment.cpp | 92 ++++++++++++++++++ libs/lxcpp/environment.hpp | 52 ++++++++++ libs/lxcpp/exception.hpp | 10 ++ tests/unit_tests/lxcpp/ut-environment.cpp | 140 +++++++++++++++++++++++++++ 9 files changed, 378 insertions(+), 35 deletions(-) rename libs/lxcpp/{ => commands}/attach-manager.cpp (66%) rename libs/lxcpp/{ => commands}/attach-manager.hpp (64%) create mode 100644 libs/lxcpp/environment.cpp create mode 100644 libs/lxcpp/environment.hpp create mode 100644 tests/unit_tests/lxcpp/ut-environment.cpp diff --git a/libs/lxcpp/CMakeLists.txt b/libs/lxcpp/CMakeLists.txt index b04e437..c76de74 100644 --- a/libs/lxcpp/CMakeLists.txt +++ b/libs/lxcpp/CMakeLists.txt @@ -22,12 +22,14 @@ PROJECT(lxcpp) MESSAGE(STATUS "") MESSAGE(STATUS "Generating makefile for the liblxcpp...") FILE(GLOB HEADERS *.hpp) -FILE(GLOB HEADERS_UTILS ${COMMON_FOLDER}/utils/fd-utils.hpp - ${COMMON_FOLDER}/utils/exception.hpp - ${COMMON_FOLDER}/utils/channel.hpp - ${COMMON_FOLDER}/utils/environment.hpp - ${COMMON_FOLDER}/utils/execute.hpp) +FILE(GLOB HEADERS_UTILS ${COMMON_FOLDER}/utils/fd-utils.hpp + ${COMMON_FOLDER}/utils/exception.hpp + ${COMMON_FOLDER}/utils/channel.hpp + ${COMMON_FOLDER}/utils/environment.hpp + ${COMMON_FOLDER}/utils/execute.hpp) FILE(GLOB HEADERS_NETLINK ${COMMON_FOLDER}/netlink/*.hpp) +FILE(GLOB HEADERS_COMMANDS commands/*.hpp) + FILE(GLOB SRCS *.cpp *.hpp) FILE(GLOB SRCS_UTILS ${COMMON_FOLDER}/utils/fd-utils.cpp ${COMMON_FOLDER}/utils/exception.cpp @@ -35,13 +37,14 @@ FILE(GLOB SRCS_UTILS ${COMMON_FOLDER}/utils/fd-utils.cpp ${COMMON_FOLDER}/utils/environment.cpp ${COMMON_FOLDER}/utils/execute.cpp) FILE(GLOB SRCS_NETLINK ${COMMON_FOLDER}/netlink/*.cpp) +FILE(GLOB SRCS_COMMANDS commands/*.cpp) SET(_LIB_VERSION_ "${VERSION}") SET(_LIB_SOVERSION_ "0") SET(PC_FILE "lib${PROJECT_NAME}.pc") ## Setup target ################################################################ -ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS} ${SRCS_UTILS} ${SRCS_NETLINK}) +ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRCS} ${SRCS_UTILS} ${SRCS_NETLINK} ${SRCS_COMMANDS}) SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES SOVERSION ${_LIB_SOVERSION_} VERSION ${_LIB_VERSION_} @@ -70,3 +73,5 @@ INSTALL(FILES ${HEADERS_UTILS} DESTINATION ${INCLUDE_INSTALL_DIR}/lxcpp/utils) INSTALL(FILES ${HEADERS_NETLINK} DESTINATION ${INCLUDE_INSTALL_DIR}/lxcpp/netlink) +INSTALL(FILES ${HEADERS_COMMANDS} + DESTINATION ${INCLUDE_INSTALL_DIR}/lxcpp/commands) diff --git a/libs/lxcpp/attach-manager.cpp b/libs/lxcpp/commands/attach-manager.cpp similarity index 66% rename from libs/lxcpp/attach-manager.cpp rename to libs/lxcpp/commands/attach-manager.cpp index 3479673..1a274d3 100644 --- a/libs/lxcpp/attach-manager.cpp +++ b/libs/lxcpp/commands/attach-manager.cpp @@ -21,18 +21,20 @@ * @brief Implementation of attaching to a container */ -#include "lxcpp/attach-manager.hpp" +#include "lxcpp/commands/attach-manager.hpp" #include "lxcpp/exception.hpp" #include "lxcpp/process.hpp" #include "lxcpp/filesystem.hpp" #include "lxcpp/namespace.hpp" #include "lxcpp/capability.hpp" +#include "lxcpp/environment.hpp" #include "utils/exception.hpp" #include #include +#include namespace lxcpp { @@ -64,6 +66,16 @@ void setupMountPoints() */ } +int execFunction(void* call) +{ + try { + return (*static_cast(call))(); + } catch(...) { + return -1; // Non-zero on failure + } + return 0; // Success +} + } // namespace AttachManager::AttachManager(lxcpp::ContainerImpl& container) @@ -75,12 +87,21 @@ AttachManager::~AttachManager() { } -void AttachManager::attach(Container::AttachCall& call, - const std::string& wdInContainer) +void AttachManager::attach(Container::AttachCall& userCall, + const int capsToKeep, + const std::string& workDirInContainer, + const std::vector& envToKeep, + const std::vector>& envToSet) { // Channels for setup synchronization utils::Channel intermChannel; + Call call = std::bind(&AttachManager::child, + std::move(userCall), + capsToKeep, + std::move(envToKeep), + std::move(envToSet)); + const pid_t interPid = lxcpp::fork(); if (interPid > 0) { intermChannel.setLeft(); @@ -88,23 +109,29 @@ void AttachManager::attach(Container::AttachCall& call, intermChannel.shutdown(); } else { intermChannel.setRight(); - interm(intermChannel, wdInContainer, call); + interm(intermChannel, workDirInContainer, call); intermChannel.shutdown(); ::_exit(0); } } -int AttachManager::child(void* data) +int AttachManager::child(const Container::AttachCall& call, + const int capsToKeep, + const std::vector& envToKeep, + const std::vector>& envToSet) { - try { - // TODO Pass mask and options via data - dropCapsFromBoundingExcept(0); - setupMountPoints(); - return (*static_cast(data))(); - } catch(...) { - return -1; // Non-zero on failure - } - return 0; // Success + // Setup capabilities + dropCapsFromBoundingExcept(capsToKeep); + + // Setup /proc /sys mount + setupMountPoints(); + + // Setup environment variables + clearenvExcept(envToKeep); + setenv(envToSet); + + // Run user's code + return call(); } void AttachManager::parent(utils::Channel& intermChannel, const pid_t interPid) @@ -118,18 +145,18 @@ void AttachManager::parent(utils::Channel& intermChannel, const pid_t interPid) } void AttachManager::interm(utils::Channel& intermChannel, - const std::string& wdInContainer, - Container::AttachCall& call) + const std::string& workDirInContainer, + Call& call) { lxcpp::setns(mContainer.getInitPid(), mContainer.getNamespaces()); // Change the current work directory - // wdInContainer is a path relative to the container's root - lxcpp::chdir(wdInContainer); + // workDirInContainer is a path relative to the container's root + lxcpp::chdir(workDirInContainer); // PID namespace won't affect the returned pid // CLONE_PARENT: Child's PPID == Caller's PID - const pid_t childPid = lxcpp::clone(&AttachManager::child, + const pid_t childPid = lxcpp::clone(execFunction, &call, CLONE_PARENT); intermChannel.write(childPid); diff --git a/libs/lxcpp/attach-manager.hpp b/libs/lxcpp/commands/attach-manager.hpp similarity index 64% rename from libs/lxcpp/attach-manager.hpp rename to libs/lxcpp/commands/attach-manager.hpp index be37ade..f286564 100644 --- a/libs/lxcpp/attach-manager.hpp +++ b/libs/lxcpp/commands/attach-manager.hpp @@ -33,6 +33,8 @@ namespace lxcpp { class AttachManager final { public: + typedef std::function Call; + AttachManager(lxcpp::ContainerImpl& container); ~AttachManager(); @@ -40,22 +42,32 @@ public: * Runs the call in the container's context * * @param call function to run inside container - * @param wdInContainer Current Work Directory. Path relative to container's root + * @param capsToKeep mask of the capabilities that shouldn't be dropped + * @param workDirInContainer Current Work Directory. Path relative to container's root + * @param envToKeep environment variables to keep in container + * @param envToSet environment variables to add/modify in container */ void attach(Container::AttachCall& call, - const std::string& wdInContainer); + const int capsToKeep, + const std::string& workDirInContainer, + const std::vector& envToKeep, + const std::vector>& envToSet); private: + const lxcpp::ContainerImpl& mContainer; // Methods for different stages of setting up the attachment - static int child(void* data); + static int child(const Container::AttachCall& call, + const int capsToKeep, + const std::vector& envToKeep, + const std::vector>& envToSet); void parent(utils::Channel& intermChannel, const pid_t pid); void interm(utils::Channel& intermChannel, - const std::string& wdInContainer, + const std::string& workDirInContainer, Container::AttachCall& call); }; diff --git a/libs/lxcpp/container-impl.cpp b/libs/lxcpp/container-impl.cpp index 6de22dc..0d8d5b1 100644 --- a/libs/lxcpp/container-impl.cpp +++ b/libs/lxcpp/container-impl.cpp @@ -27,7 +27,7 @@ #include "lxcpp/filesystem.hpp" #include "lxcpp/namespace.hpp" #include "lxcpp/capability.hpp" -#include "lxcpp/attach-manager.hpp" +#include "lxcpp/commands/attach-manager.hpp" #include "utils/exception.hpp" @@ -108,7 +108,12 @@ void ContainerImpl::attach(Container::AttachCall& call, const std::string& cwdInContainer) { AttachManager attachManager(*this); - attachManager.attach(call, cwdInContainer); + // TODO: Env variables should agree with the ones already in the container + attachManager.attach(call, + /*capsToKeep*/ 0, + cwdInContainer, + /*envToKeep*/ {}, + /*envInContainer*/{{"container","lxcpp"}} ); } const std::vector& ContainerImpl::getNamespaces() const @@ -141,9 +146,9 @@ NetworkInterfaceInfo ContainerImpl::getInterfaceInfo(const std::string& /*ifname } void ContainerImpl::createInterface(const std::string& hostif, - const std::string& zoneif, - InterfaceType type, - MacVLanMode mode) + const std::string& zoneif, + InterfaceType type, + MacVLanMode mode) { NetworkInterface ni(*this, zoneif); ni.create(hostif, type, mode); diff --git a/libs/lxcpp/container.hpp b/libs/lxcpp/container.hpp index d07bc27..882aa87 100644 --- a/libs/lxcpp/container.hpp +++ b/libs/lxcpp/container.hpp @@ -46,7 +46,7 @@ struct NetworkInterfaceInfo { class Container { public: - typedef std::function AttachCall; + typedef std::function AttachCall; virtual ~Container() {}; diff --git a/libs/lxcpp/environment.cpp b/libs/lxcpp/environment.cpp new file mode 100644 index 0000000..489608b --- /dev/null +++ b/libs/lxcpp/environment.cpp @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @author Jan Olszak (j.olszak@samsung.com) + * @brief Handling environment variables + */ + +#include "lxcpp/environment.hpp" +#include "lxcpp/exception.hpp" + +#include "logger/logger.hpp" +#include "utils/exception.hpp" + +#include + +namespace lxcpp { + +void clearenvExcept(const std::vector& names) +{ + // Backup keeps pairs (name,value) + std::vector> backup; + for(const auto& name: names) { + try { + backup.push_back({name, lxcpp::getenv(name)}); + } catch(const NoSuchValue&) { + // Continue if there's no such variable + } + } + + lxcpp::clearenv(); + + // Restore backup + lxcpp::setenv(backup); +} + +void clearenv() +{ + if(::clearenv()) { + const std::string msg = "clearenv() failed: " + + utils::getSystemErrorMessage(); + LOGE(msg); + throw EnvironmentSetupException(msg); + } +} + +std::string getenv(const std::string& name) +{ + const char* value = ::getenv(name.c_str()); + if (!value) { + const std::string msg = "getenv() failed: No such name"; + LOGW(msg); + throw NoSuchValue(msg); + } + return value; +} + +void setenv(const std::string& name, const std::string& value) +{ + if (-1 == ::setenv(name.c_str(), + value.c_str(), + 1 /*write if exists*/)) { + const std::string msg = "setenv() failed. Not all env set. " + + utils::getSystemErrorMessage(); + LOGE(msg); + throw EnvironmentSetupException(msg); + } +} + +void setenv(const std::vector>& variables) +{ + for(const auto& variable: variables) { + lxcpp::setenv(variable.first, variable.second); + } +} + +} // namespace lxcpp diff --git a/libs/lxcpp/environment.hpp b/libs/lxcpp/environment.hpp new file mode 100644 index 0000000..c9d8a20 --- /dev/null +++ b/libs/lxcpp/environment.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @author Jan Olszak (j.olszak@samsung.com) + * @brief Handling environment variables + */ + +#ifndef LXCPP_ENVIRONMENT_HPP +#define LXCPP_ENVIRONMENT_HPP + +#include +#include +#include + +namespace lxcpp { + +void clearenv(); + +/** + * Clears the env variables except those listed. + * There's a race condition - a moment when listed variables aren't set + * Function should be used only for setting up a new process. + * + * @param names names of the variables to keep + */ +void clearenvExcept(const std::vector& names); + +std::string getenv(const std::string& name); + +void setenv(const std::string& name, const std::string& value); + +void setenv(const std::vector>& variables); + +} // namespace lxcpp + +#endif // LXCPP_ENVIRONMENT_HPP diff --git a/libs/lxcpp/exception.hpp b/libs/lxcpp/exception.hpp index 51dc5ec..8c11131 100644 --- a/libs/lxcpp/exception.hpp +++ b/libs/lxcpp/exception.hpp @@ -51,6 +51,11 @@ struct FileSystemSetupException: public Exception { : Exception(message) {} }; +struct EnvironmentSetupException: public Exception { + EnvironmentSetupException(const std::string& message = "Error during handling environment variables") + : Exception(message) {} +}; + struct CapabilitySetupException: public Exception { CapabilitySetupException(const std::string& message = "Error during a capability operation") : Exception(message) {} @@ -61,6 +66,11 @@ struct BadArgument: public Exception { : Exception(message) {} }; +struct NoSuchValue: public Exception { + NoSuchValue(const std::string& message = "Value not found") + : Exception(message) {} +}; + struct NetworkException : public Exception { NetworkException (const std::string& message = "Error during setting up a network") : Exception(message) {} diff --git a/tests/unit_tests/lxcpp/ut-environment.cpp b/tests/unit_tests/lxcpp/ut-environment.cpp new file mode 100644 index 0000000..8d6d45d --- /dev/null +++ b/tests/unit_tests/lxcpp/ut-environment.cpp @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jan Olszak(j.olszak@samsung.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + + +/** + * @file + * @author Jan Olszak(j.olszak@samsung.com) + * @brief Unit tests of lxcpp namespace helpers + */ + +#include "config.hpp" +#include "ut.hpp" + +#include "lxcpp/environment.hpp" +#include "lxcpp/exception.hpp" +#include "lxcpp/namespace.hpp" +#include "lxcpp/process.hpp" + +#include "utils/execute.hpp" + +#include +#include +#include + +namespace { + +struct Fixture { + Fixture() {} + ~Fixture() {} +}; + +const int TEST_PASSED = 0; +const int ERROR = 1; + +const std::string TEST_NAME = "TEST_NAME"; +const std::string TEST_VALUE = "TEST_VALUE"; + +const std::string TEST_NAME_REMOVED = "TEST_NAME_REMOVED"; +const std::string TEST_VALUE_REMOVED = "TEST_VALUE_REMOVED"; + +} // namespace + +BOOST_FIXTURE_TEST_SUITE(LxcppEnvironmentSuite, Fixture) + +using namespace lxcpp; + +BOOST_AUTO_TEST_CASE(SetGetEnv) +{ + pid_t pid = lxcpp::fork(); + if (pid == 0) { + try { + lxcpp::setenv(TEST_NAME, TEST_VALUE); + + if(lxcpp::getenv(TEST_NAME) == TEST_VALUE) { + ::_exit(TEST_PASSED); + } + ::_exit(ERROR); + } catch(...) { + ::_exit(ERROR); + } + } else if (pid > 0) { + int status = -1; + BOOST_REQUIRE(utils::waitPid(pid, status)); + BOOST_REQUIRE(status == TEST_PASSED); + } +} + +BOOST_AUTO_TEST_CASE(ClearEnvExcept) +{ + pid_t pid = lxcpp::fork(); + if (pid == 0) { + try { + lxcpp::setenv(TEST_NAME, TEST_VALUE); + lxcpp::setenv(TEST_NAME_REMOVED, TEST_VALUE_REMOVED); + + clearenvExcept({TEST_NAME}); + + try { + lxcpp::getenv(TEST_NAME_REMOVED); + } catch(const lxcpp::NoSuchValue&) { + if(lxcpp::getenv(TEST_NAME) == TEST_VALUE) { + ::_exit(TEST_PASSED); + } + } + ::_exit(ERROR); + } catch(...) { + ::_exit(ERROR); + } + } else if (pid > 0) { + int status = -1; + BOOST_REQUIRE(utils::waitPid(pid, status)); + BOOST_REQUIRE(status == TEST_PASSED); + } +} + +BOOST_AUTO_TEST_CASE(ClearEnv) +{ + pid_t pid = lxcpp::fork(); + if (pid == 0) { + try { + lxcpp::setenv(TEST_NAME_REMOVED, TEST_VALUE_REMOVED); + lxcpp::clearenv(); + + // clearenv should clear environ + if (::environ) { + ::_exit(ERROR); + } + + try { + lxcpp::getenv(TEST_NAME_REMOVED); + } catch(const lxcpp::NoSuchValue&) { + ::_exit(TEST_PASSED); + } + ::_exit(ERROR); + } catch(...) { + ::_exit(ERROR); + } + } else if (pid > 0) { + int status = -1; + BOOST_REQUIRE(utils::waitPid(pid, status)); + BOOST_REQUIRE(status == TEST_PASSED); + } +} + +BOOST_AUTO_TEST_SUITE_END() -- 2.7.4 From 21e5a635a691a7c0ab045e1aee74284f340e6f92 Mon Sep 17 00:00:00 2001 From: "Maciej J. Karpiuk" Date: Fri, 28 Aug 2015 15:39:41 +0200 Subject: [PATCH 13/16] server: logging-backend selection via command line. [Feature] command-line option to select logging backend [Cause] logging backend selected in compile-time, no flexibility [Solution] add command-line option, select backend in runtime [Verification] start service with different logging options. Change-Id: I410457521462b29d4c40995b37bbd8ea06e479b4 --- server/main.cpp | 34 ++++++++++++++++++++++++++-------- zone-daemon/main.cpp | 34 +++++++++++++++++++++++++++------- 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/server/main.cpp b/server/main.cpp index 7ed4ef1..af30cd2 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -58,8 +58,12 @@ const std::string CONFIG_PATH = "/etc/vasum/daemon.conf"; int main(int argc, char* argv[]) { bool runAsRoot = false; - try { +#ifndef NDEBUG + const char *defaultLoggingBackend = "stderr"; +#else + const char *defaultLoggingBackend = "syslog"; +#endif po::options_description desc("Allowed options"); desc.add_options() @@ -67,6 +71,12 @@ int main(int argc, char* argv[]) ("root,r", "Don't drop root privileges at startup") ("daemon,d", "Run server as daemon") ("log-level,l", po::value()->default_value("DEBUG"), "set log level") + ("log-backend,b", po::value()->default_value(defaultLoggingBackend), + "set log backend [stderr,syslog" +#ifdef HAVE_SYSTEMD + ",journal" +#endif + "]") ("check,c", "check runtime environment and exit") ("version,v", "show application version") ; @@ -113,13 +123,22 @@ int main(int argc, char* argv[]) } Logger::setLogLevel(vm["log-level"].as()); -#if !defined(NDEBUG) - Logger::setLogBackend(new StderrBackend()); -#elif HAVE_SYSTEMD - Logger::setLogBackend(new SystemdJournalBackend()); -#else - Logger::setLogBackend(new SyslogBackend()); + const std::string logBackend = vm["log-backend"].as(); + if(logBackend.compare("stderr") == 0) { + Logger::setLogBackend(new StderrBackend()); + } +#ifdef HAVE_SYSTEMD + else if(logBackend.compare("journal") == 0) { + Logger::setLogBackend(new SystemdJournalBackend()); + } #endif + else if(logBackend.compare("syslog") == 0) { + Logger::setLogBackend(new SyslogBackend()); + } + else { + std::cerr << "Error: unrecognized logging backend option: " << logBackend << std::endl; + return 1; + } runAsRoot = vm.count("root") > 0; @@ -149,4 +168,3 @@ int main(int argc, char* argv[]) return 0; } - diff --git a/zone-daemon/main.cpp b/zone-daemon/main.cpp index 1bb3091..82b152e 100644 --- a/zone-daemon/main.cpp +++ b/zone-daemon/main.cpp @@ -55,12 +55,24 @@ const std::string PROGRAM_NAME_AND_VERSION = int main(int argc, char* argv[]) { try { +#ifndef NDEBUG + const char *defaultLoggingBackend = "stderr"; +#else + const char *defaultLoggingBackend = "syslog"; +#endif + po::options_description desc("Allowed options"); desc.add_options() ("help,h", "print this help") ("daemon,d", "Run server as daemon") ("log-level,l", po::value()->default_value("DEBUG"), "set log level") + ("log-backend,b", po::value()->default_value(defaultLoggingBackend), + "set log backend [stderr,syslog" +#ifdef HAVE_SYSTEMD + ",journal" +#endif + "]") ("version,v", "show application version") ; @@ -103,13 +115,22 @@ int main(int argc, char* argv[]) } Logger::setLogLevel(vm["log-level"].as()); -#if !defined(NDEBUG) - Logger::setLogBackend(new StderrBackend()); -#elif HAVE_SYSTEMD - Logger::setLogBackend(new SystemdJournalBackend()); -#else - Logger::setLogBackend(new SyslogBackend()); + const std::string logBackend = vm["log-backend"].as(); + if(logBackend.compare("stderr") == 0) { + Logger::setLogBackend(new StderrBackend()); + } +#ifdef HAVE_SYSTEMD + else if(logBackend.compare("journal") == 0) { + Logger::setLogBackend(new SystemdJournalBackend()); + } #endif + else if(logBackend.compare("syslog") == 0) { + Logger::setLogBackend(new SyslogBackend()); + } + else { + std::cerr << "Error: unrecognized logging backend option: " << logBackend << std::endl; + return 1; + } } catch (std::exception& e) { std::cerr << e.what() << std::endl; @@ -127,4 +148,3 @@ int main(int argc, char* argv[]) return 0; } - -- 2.7.4 From f74e6dababe7066d5184668137cf50800e2f331d Mon Sep 17 00:00:00 2001 From: Lukasz Kostyra Date: Thu, 3 Sep 2015 14:47:47 +0200 Subject: [PATCH 14/16] ipc: Fix critical build break in unique-id [Bug] Build break using Clang due to recently added unique-id code [Cause] Incorrectly used Doxygen syntax causing critical build error [Solution] Correct the syntax. [Verification] Build, install, run tests Change-Id: Ia0194aadfcd5cdcfba90cd518d24fe733edc934b --- libs/ipc/unique-id.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/ipc/unique-id.hpp b/libs/ipc/unique-id.hpp index bceda62..795c2d6 100644 --- a/libs/ipc/unique-id.hpp +++ b/libs/ipc/unique-id.hpp @@ -66,8 +66,8 @@ public: friend std::ostream& operator<<(std::ostream& str, const UniqueID& id); - TimestampType mTime; //< timestamp when generate() was called - UUIDType mUUID; //< random UUID generated with libuuid + TimestampType mTime; ///< timestamp when generate() was called + UUIDType mUUID; ///< random UUID generated with libuuid }; template -- 2.7.4 From c0c76a68a17ee4a7137a8f516087c8389a3eba07 Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Wed, 2 Sep 2015 17:04:45 +0200 Subject: [PATCH 15/16] lxcpp: Command implementation [Feature] Base class for commands Attach command [Cause] N/A [Solution] N/A [Verification] Build, install, run tests Change-Id: Id9ed43c145704f5d9d21f1aa210694fed1615c57 --- .../commands/{attach-manager.cpp => attach.cpp} | 55 ++++++++++++---------- .../commands/{attach-manager.hpp => attach.hpp} | 51 +++++++++++--------- libs/lxcpp/commands/command.hpp | 36 ++++++++++++++ libs/lxcpp/container-impl.cpp | 15 +++--- 4 files changed, 103 insertions(+), 54 deletions(-) rename libs/lxcpp/commands/{attach-manager.cpp => attach.cpp} (71%) rename libs/lxcpp/commands/{attach-manager.hpp => attach.hpp} (54%) create mode 100644 libs/lxcpp/commands/command.hpp diff --git a/libs/lxcpp/commands/attach-manager.cpp b/libs/lxcpp/commands/attach.cpp similarity index 71% rename from libs/lxcpp/commands/attach-manager.cpp rename to libs/lxcpp/commands/attach.cpp index 1a274d3..98a4599 100644 --- a/libs/lxcpp/commands/attach-manager.cpp +++ b/libs/lxcpp/commands/attach.cpp @@ -21,7 +21,7 @@ * @brief Implementation of attaching to a container */ -#include "lxcpp/commands/attach-manager.hpp" +#include "lxcpp/commands/attach.hpp" #include "lxcpp/exception.hpp" #include "lxcpp/process.hpp" #include "lxcpp/filesystem.hpp" @@ -69,7 +69,7 @@ void setupMountPoints() int execFunction(void* call) { try { - return (*static_cast(call))(); + return (*static_cast(call))(); } catch(...) { return -1; // Non-zero on failure } @@ -78,29 +78,35 @@ int execFunction(void* call) } // namespace -AttachManager::AttachManager(lxcpp::ContainerImpl& container) - : mContainer(container) +Attach::Attach(lxcpp::ContainerImpl& container, + Container::AttachCall& userCall, + const int capsToKeep, + const std::string& workDirInContainer, + const std::vector& envToKeep, + const std::vector>& envToSet) + : mContainer(container), + mUserCall(userCall), + mCapsToKeep(capsToKeep), + mWorkDirInContainer(workDirInContainer), + mEnvToKeep(envToKeep), + mEnvToSet(envToSet) { } -AttachManager::~AttachManager() +Attach::~Attach() { } -void AttachManager::attach(Container::AttachCall& userCall, - const int capsToKeep, - const std::string& workDirInContainer, - const std::vector& envToKeep, - const std::vector>& envToSet) +void Attach::execute() { // Channels for setup synchronization utils::Channel intermChannel; - Call call = std::bind(&AttachManager::child, - std::move(userCall), - capsToKeep, - std::move(envToKeep), - std::move(envToSet)); + Call call = std::bind(&Attach::child, + mUserCall, + mCapsToKeep, + mEnvToKeep, + mEnvToSet); const pid_t interPid = lxcpp::fork(); if (interPid > 0) { @@ -109,16 +115,16 @@ void AttachManager::attach(Container::AttachCall& userCall, intermChannel.shutdown(); } else { intermChannel.setRight(); - interm(intermChannel, workDirInContainer, call); + interm(intermChannel, call); intermChannel.shutdown(); ::_exit(0); } } -int AttachManager::child(const Container::AttachCall& call, - const int capsToKeep, - const std::vector& envToKeep, - const std::vector>& envToSet) +int Attach::child(const Container::AttachCall& call, + const int capsToKeep, + const std::vector& envToKeep, + const std::vector>& envToSet) { // Setup capabilities dropCapsFromBoundingExcept(capsToKeep); @@ -134,7 +140,7 @@ int AttachManager::child(const Container::AttachCall& call, return call(); } -void AttachManager::parent(utils::Channel& intermChannel, const pid_t interPid) +void Attach::parent(utils::Channel& intermChannel, const pid_t interPid) { // TODO: Setup cgroups etc const pid_t childPid = intermChannel.read(); @@ -144,15 +150,13 @@ void AttachManager::parent(utils::Channel& intermChannel, const pid_t interPid) lxcpp::waitpid(childPid); } -void AttachManager::interm(utils::Channel& intermChannel, - const std::string& workDirInContainer, - Call& call) +void Attach::interm(utils::Channel& intermChannel, Call& call) { lxcpp::setns(mContainer.getInitPid(), mContainer.getNamespaces()); // Change the current work directory // workDirInContainer is a path relative to the container's root - lxcpp::chdir(workDirInContainer); + lxcpp::chdir(mWorkDirInContainer); // PID namespace won't affect the returned pid // CLONE_PARENT: Child's PPID == Caller's PID @@ -160,7 +164,6 @@ void AttachManager::interm(utils::Channel& intermChannel, &call, CLONE_PARENT); intermChannel.write(childPid); - } } // namespace lxcpp diff --git a/libs/lxcpp/commands/attach-manager.hpp b/libs/lxcpp/commands/attach.hpp similarity index 54% rename from libs/lxcpp/commands/attach-manager.hpp rename to libs/lxcpp/commands/attach.hpp index f286564..342b613 100644 --- a/libs/lxcpp/commands/attach-manager.hpp +++ b/libs/lxcpp/commands/attach.hpp @@ -21,9 +21,10 @@ * @brief Implementation of attaching to a container */ -#ifndef LXCPP_ATTACH_MANAGER_HPP -#define LXCPP_ATTACH_MANAGER_HPP +#ifndef LXCPP_COMMANDS_ATTACH_HPP +#define LXCPP_COMMANDS_ATTACH_HPP +#include "lxcpp/commands/command.hpp" #include "lxcpp/container-impl.hpp" #include "utils/channel.hpp" @@ -31,31 +32,40 @@ namespace lxcpp { -class AttachManager final { +class Attach final: Command { public: typedef std::function Call; - AttachManager(lxcpp::ContainerImpl& container); - ~AttachManager(); - /** - * Runs the call in the container's context + * Runs call in the container's context + * + * Object attach should be used immediately after creation. + * It will not be stored for future use like most other commands. * - * @param call function to run inside container - * @param capsToKeep mask of the capabilities that shouldn't be dropped - * @param workDirInContainer Current Work Directory. Path relative to container's root - * @param envToKeep environment variables to keep in container - * @param envToSet environment variables to add/modify in container + * @param container container to which it attaches + * @param userCall user's function to run + * @param capsToKeep capabilities that will be kept + * @param workDirInContainer work directory set for the new process + * @param envToKeep environment variables that will be kept + * @param envToSet new environment variables that will be set */ - void attach(Container::AttachCall& call, - const int capsToKeep, - const std::string& workDirInContainer, - const std::vector& envToKeep, - const std::vector>& envToSet); + Attach(lxcpp::ContainerImpl& container, + Container::AttachCall& userCall, + const int capsToKeep, + const std::string& workDirInContainer, + const std::vector& envToKeep, + const std::vector>& envToSet); + ~Attach(); -private: + void execute(); +private: const lxcpp::ContainerImpl& mContainer; + const Container::AttachCall& mUserCall; + const int mCapsToKeep; + const std::string& mWorkDirInContainer; + const std::vector& mEnvToKeep; + const std::vector>& mEnvToSet; // Methods for different stages of setting up the attachment static int child(const Container::AttachCall& call, @@ -67,10 +77,9 @@ private: const pid_t pid); void interm(utils::Channel& intermChannel, - const std::string& workDirInContainer, - Container::AttachCall& call); + Call& call); }; } // namespace lxcpp -#endif // LXCPP_ATTACH_MANAGER_HPP \ No newline at end of file +#endif // LXCPP_COMMANDS_ATTACH_HPP \ No newline at end of file diff --git a/libs/lxcpp/commands/command.hpp b/libs/lxcpp/commands/command.hpp new file mode 100644 index 0000000..cd301ee --- /dev/null +++ b/libs/lxcpp/commands/command.hpp @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @author Jan Olszak (j.olszak@samsung.com) + * @brief Command interface definition + */ + +#ifndef LXCPP_COMMANDS_COMMAND_HPP +#define LXCPP_COMMANDS_COMMAND_HPP + +namespace lxcpp { + +class Command { +public: + virtual void execute() = 0; +}; + +} // namespace lxcpp + +#endif // LXCPP_COMMANDS_COMMAND_HPP \ No newline at end of file diff --git a/libs/lxcpp/container-impl.cpp b/libs/lxcpp/container-impl.cpp index 0d8d5b1..7189bc7 100644 --- a/libs/lxcpp/container-impl.cpp +++ b/libs/lxcpp/container-impl.cpp @@ -27,7 +27,7 @@ #include "lxcpp/filesystem.hpp" #include "lxcpp/namespace.hpp" #include "lxcpp/capability.hpp" -#include "lxcpp/commands/attach-manager.hpp" +#include "lxcpp/commands/attach.hpp" #include "utils/exception.hpp" @@ -107,13 +107,14 @@ std::string ContainerImpl::getRootPath() void ContainerImpl::attach(Container::AttachCall& call, const std::string& cwdInContainer) { - AttachManager attachManager(*this); + Attach attach(*this, + call, + /*capsToKeep*/ 0, + cwdInContainer, + /*envToKeep*/ {}, + /*envInContainer*/ {{"container","lxcpp"}}); // TODO: Env variables should agree with the ones already in the container - attachManager.attach(call, - /*capsToKeep*/ 0, - cwdInContainer, - /*envToKeep*/ {}, - /*envInContainer*/{{"container","lxcpp"}} ); + attach.execute(); } const std::vector& ContainerImpl::getNamespaces() const -- 2.7.4 From ff9f7d8f7100c3dca173de14e3253e25b677f370 Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Thu, 3 Sep 2015 20:50:19 +0200 Subject: [PATCH 16/16] lxcpp: UID/GID setting in Attach [Feature] UID/GID setting [Cause] N/A [Solution] N/A [Verification] Build, install, run tests Change-Id: Iaa83cab137df53a1391f01c0a29ef236da030aee --- libs/lxcpp/commands/attach.cpp | 25 ++++++++++++++-- libs/lxcpp/commands/attach.hpp | 14 +++++++++ libs/lxcpp/container-impl.cpp | 3 ++ libs/lxcpp/credentials.cpp | 66 ++++++++++++++++++++++++++++++++++++++++++ libs/lxcpp/credentials.hpp | 43 +++++++++++++++++++++++++++ libs/lxcpp/exception.hpp | 5 ++++ 6 files changed, 153 insertions(+), 3 deletions(-) create mode 100644 libs/lxcpp/credentials.cpp create mode 100644 libs/lxcpp/credentials.hpp diff --git a/libs/lxcpp/commands/attach.cpp b/libs/lxcpp/commands/attach.cpp index 98a4599..0ff856e 100644 --- a/libs/lxcpp/commands/attach.cpp +++ b/libs/lxcpp/commands/attach.cpp @@ -28,6 +28,7 @@ #include "lxcpp/namespace.hpp" #include "lxcpp/capability.hpp" #include "lxcpp/environment.hpp" +#include "lxcpp/credentials.hpp" #include "utils/exception.hpp" @@ -80,12 +81,18 @@ int execFunction(void* call) Attach::Attach(lxcpp::ContainerImpl& container, Container::AttachCall& userCall, + const uid_t uid, + const gid_t gid, + const std::vector& supplementaryGids, const int capsToKeep, const std::string& workDirInContainer, const std::vector& envToKeep, const std::vector>& envToSet) : mContainer(container), mUserCall(userCall), + mUid(uid), + mGid(gid), + mSupplementaryGids(supplementaryGids), mCapsToKeep(capsToKeep), mWorkDirInContainer(workDirInContainer), mEnvToKeep(envToKeep), @@ -104,6 +111,9 @@ void Attach::execute() Call call = std::bind(&Attach::child, mUserCall, + mUid, + mGid, + mSupplementaryGids, mCapsToKeep, mEnvToKeep, mEnvToSet); @@ -122,20 +132,29 @@ void Attach::execute() } int Attach::child(const Container::AttachCall& call, + const uid_t uid, + const gid_t gid, + const std::vector& supplementaryGids, const int capsToKeep, const std::vector& envToKeep, const std::vector>& envToSet) { - // Setup capabilities - dropCapsFromBoundingExcept(capsToKeep); - // Setup /proc /sys mount setupMountPoints(); + // Setup capabilities + dropCapsFromBoundingExcept(capsToKeep); + // Setup environment variables clearenvExcept(envToKeep); setenv(envToSet); + // Set uid/gids + lxcpp::setgid(gid); + setgroups(supplementaryGids); + + lxcpp::setuid(uid); + // Run user's code return call(); } diff --git a/libs/lxcpp/commands/attach.hpp b/libs/lxcpp/commands/attach.hpp index 342b613..36c57ba 100644 --- a/libs/lxcpp/commands/attach.hpp +++ b/libs/lxcpp/commands/attach.hpp @@ -28,6 +28,8 @@ #include "lxcpp/container-impl.hpp" #include "utils/channel.hpp" +#include + #include namespace lxcpp { @@ -44,6 +46,9 @@ public: * * @param container container to which it attaches * @param userCall user's function to run + * @param uid uid in the container + * @param gid gid in the container + * @param supplementaryGids supplementary groups in container * @param capsToKeep capabilities that will be kept * @param workDirInContainer work directory set for the new process * @param envToKeep environment variables that will be kept @@ -51,6 +56,9 @@ public: */ Attach(lxcpp::ContainerImpl& container, Container::AttachCall& userCall, + const uid_t uid, + const gid_t gid, + const std::vector& supplementaryGids, const int capsToKeep, const std::string& workDirInContainer, const std::vector& envToKeep, @@ -62,6 +70,9 @@ public: private: const lxcpp::ContainerImpl& mContainer; const Container::AttachCall& mUserCall; + const uid_t mUid; + const gid_t mGid; + const std::vector& mSupplementaryGids; const int mCapsToKeep; const std::string& mWorkDirInContainer; const std::vector& mEnvToKeep; @@ -69,6 +80,9 @@ private: // Methods for different stages of setting up the attachment static int child(const Container::AttachCall& call, + const uid_t uid, + const gid_t gid, + const std::vector& supplementaryGids, const int capsToKeep, const std::vector& envToKeep, const std::vector>& envToSet); diff --git a/libs/lxcpp/container-impl.cpp b/libs/lxcpp/container-impl.cpp index 7189bc7..02e9f3a 100644 --- a/libs/lxcpp/container-impl.cpp +++ b/libs/lxcpp/container-impl.cpp @@ -109,6 +109,9 @@ void ContainerImpl::attach(Container::AttachCall& call, { Attach attach(*this, call, + /*uid in container*/ 0, + /*gid in container*/ 0, + /*supplementary gids in container*/ {}, /*capsToKeep*/ 0, cwdInContainer, /*envToKeep*/ {}, diff --git a/libs/lxcpp/credentials.cpp b/libs/lxcpp/credentials.cpp new file mode 100644 index 0000000..692be25 --- /dev/null +++ b/libs/lxcpp/credentials.cpp @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @author Jan Olszak (j.olszak@samsung.com) + * @brief Process credentials handling + */ + +#include "lxcpp/credentials.hpp" +#include "lxcpp/exception.hpp" + +#include "logger/logger.hpp" +#include "utils/exception.hpp" + +#include +#include + +namespace lxcpp { + +void setgroups(const std::vector& gids) +{ + if(-1 == ::setgroups(gids.size(), gids.data())) { + const std::string msg = "setgroups() failed: " + + utils::getSystemErrorMessage(); + LOGE(msg); + throw CredentialSetupException(msg); + } +} + +void setgid(const gid_t gid) +{ + if(-1 == ::setgid(gid)) { + const std::string msg = "setgid() failed: " + + utils::getSystemErrorMessage(); + LOGE(msg); + throw CredentialSetupException(msg); + } +} + +void setuid(const uid_t uid) +{ + if(-1 == ::setuid(uid)) { + const std::string msg = "setuid() failed: " + + utils::getSystemErrorMessage(); + LOGE(msg); + throw CredentialSetupException(msg); + } +} + +} // namespace lxcpp + diff --git a/libs/lxcpp/credentials.hpp b/libs/lxcpp/credentials.hpp new file mode 100644 index 0000000..df00ce5 --- /dev/null +++ b/libs/lxcpp/credentials.hpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1 as published by the Free Software Foundation. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * @author Jan Olszak (j.olszak@samsung.com) + * @brief Process credentials handling + */ + +#ifndef LXCPP_CREDENTIALS_HPP +#define LXCPP_CREDENTIALS_HPP + +#include + +#include + +namespace lxcpp { + +void setgroups(const std::vector& groups); + +void setgid(const gid_t gid); + +void setuid(const uid_t uid); + + + +} // namespace lxcpp + +#endif // LXCPP_CREDENTIALS_HPP \ No newline at end of file diff --git a/libs/lxcpp/exception.hpp b/libs/lxcpp/exception.hpp index 8c11131..037da41 100644 --- a/libs/lxcpp/exception.hpp +++ b/libs/lxcpp/exception.hpp @@ -56,6 +56,11 @@ struct EnvironmentSetupException: public Exception { : Exception(message) {} }; +struct CredentialSetupException: public Exception { + CredentialSetupException(const std::string& message = "Error during handling environment variables") + : Exception(message) {} +}; + struct CapabilitySetupException: public Exception { CapabilitySetupException(const std::string& message = "Error during a capability operation") : Exception(message) {} -- 2.7.4