From 27932ad509b7dda08344e62ba7fb5b1c1d71cc3d Mon Sep 17 00:00:00 2001 From: Lukasz Kostyra Date: Wed, 20 May 2015 11:30:54 +0200 Subject: [PATCH 01/16] Fix critical bug in environment.cpp [Bug] "Namespaced" word was misspelled in "passNamespacedFd" function declaration, definition and usage. Assuming someone does not use syntax recognition, it could case critical errors during compilation and a lot of confusion. [Cause] Author of passNamespacedFd function made a typo. [Solution] Replace "Nemaspaced" with correct version - "Namespaced". [Verification] Build, install, run tests. Change-Id: I3df106ee8e275210af43de572a9c69ba0a220a56 --- common/netlink/netlink.cpp | 2 +- common/utils/environment.cpp | 2 +- common/utils/environment.hpp | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/common/netlink/netlink.cpp b/common/netlink/netlink.cpp index 6dd0ae5..6d7be95 100644 --- a/common/netlink/netlink.cpp +++ b/common/netlink/netlink.cpp @@ -106,7 +106,7 @@ void Netlink::open(int netNsPid) LOGE("Can't open socket: " << getSystemErrorMessage()); } } else { - mFd = utils::passNemaspacedFd(netNsPid, CLONE_NEWNET, fdFactory); + mFd = utils::passNamespacedFd(netNsPid, CLONE_NEWNET, fdFactory); } if (mFd == -1) { throw VasumException("Can't open netlink connection"); diff --git a/common/utils/environment.cpp b/common/utils/environment.cpp index 7bd7d07..57b6e2a 100644 --- a/common/utils/environment.cpp +++ b/common/utils/environment.cpp @@ -218,7 +218,7 @@ bool joinToNs(int nsPid, int ns) return true; } -int passNemaspacedFd(int nsPid, int ns, const std::function& fdFactory) +int passNamespacedFd(int nsPid, int ns, const std::function& fdFactory) { int fds[2]; int ret = socketpair(PF_LOCAL, SOCK_RAW, 0, fds); diff --git a/common/utils/environment.hpp b/common/utils/environment.hpp index b4e3194..9039239 100644 --- a/common/utils/environment.hpp +++ b/common/utils/environment.hpp @@ -59,7 +59,7 @@ bool joinToNs(int nsPid, int ns); /** * Pass file descriptor from namespace of some process */ -int passNemaspacedFd(int nsPid, int ns, const std::function& fdFactory); +int passNamespacedFd(int nsPid, int ns, const std::function& fdFactory); } // namespace utils -- 2.7.4 From 88fa8ab69b1079df9eeabd8c1fa120c85db17978 Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Wed, 20 May 2015 10:58:50 +0200 Subject: [PATCH 02/16] Add libsystemd-daemon build dependencies [Bug] LibIpc need libsystemd-daemon [Cause] N/A [Solution] N/A [Verification] Build, install on target Change-Id: I6da84631ed75e80d8e0f417dd4aacdc51f797a11 --- client/CMakeLists.txt | 2 +- libs/ipc/CMakeLists.txt | 6 ++++-- packaging/vasum.spec | 4 ++-- server/CMakeLists.txt | 2 +- tests/unit_tests/CMakeLists.txt | 3 +-- wrapper/CMakeLists.txt | 2 +- zone-daemon/CMakeLists.txt | 2 +- 7 files changed, 11 insertions(+), 10 deletions(-) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 56ed2e7..c1fdd19 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -44,7 +44,7 @@ SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES ## Link libraries ############################################################## FIND_PACKAGE(Boost COMPONENTS system filesystem) -PKG_CHECK_MODULES(LIB_DEPS REQUIRED gio-2.0 libsystemd-daemon libcap-ng) +PKG_CHECK_MODULES(LIB_DEPS REQUIRED gio-2.0 libcap-ng) INCLUDE_DIRECTORIES(SYSTEM ${LIB_DEPS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) INCLUDE_DIRECTORIES(${COMMON_FOLDER}) INCLUDE_DIRECTORIES(${LIBS_FOLDER}) diff --git a/libs/ipc/CMakeLists.txt b/libs/ipc/CMakeLists.txt index d760883..84bb812 100644 --- a/libs/ipc/CMakeLists.txt +++ b/libs/ipc/CMakeLists.txt @@ -49,10 +49,12 @@ SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES ) ## Link libraries ############################################################## +PKG_CHECK_MODULES(IPC_DEPS REQUIRED libsystemd-daemon) + INCLUDE_DIRECTORIES(${LIBS_FOLDER}) INCLUDE_DIRECTORIES(${COMMON_FOLDER}) -INCLUDE_DIRECTORIES(SYSTEM ${DBUS_DEPS_INCLUDE_DIRS}) -TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} Logger Config) +INCLUDE_DIRECTORIES(SYSTEM ${DBUS_DEPS_INCLUDE_DIRS} ${IPC_DEPS_INCLUDE_DIRS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} ${IPC_DEPS_LIBRARIES} Logger Config) ## Generate the pc file ######################################################## CONFIGURE_FILE(${PC_FILE}.in ${CMAKE_CURRENT_BINARY_DIR}/${PC_FILE} @ONLY) diff --git a/packaging/vasum.spec b/packaging/vasum.spec index 11c1599..3b241df 100644 --- a/packaging/vasum.spec +++ b/packaging/vasum.spec @@ -23,8 +23,6 @@ BuildRequires: libjson-devel >= 0.10 BuildRequires: libcap-ng-devel BuildRequires: lxc-devel BuildRequires: pkgconfig(glib-2.0) -BuildRequires: pkgconfig(libsystemd-journal) -BuildRequires: pkgconfig(libsystemd-daemon) BuildRequires: pkgconfig(sqlite3) Requires(post): libcap-tools Requires: iproute2 @@ -261,6 +259,7 @@ systemctl daemon-reload %package -n libLogger Summary: Logger library Group: Security/Other +BuildRequires: pkgconfig(libsystemd-journal) Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig @@ -364,6 +363,7 @@ The package provides libConfig development tools and libs. %package -n libIpc Summary: IPC library Group: Security/Other +BuildRequires: pkgconfig(libsystemd-daemon) Requires: libConfig Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 6181e15..f9ce867 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -30,7 +30,7 @@ ADD_EXECUTABLE(${SERVER_CODENAME} ${project_SRCS} ${common_SRCS}) ## Link libraries ############################################################## FIND_PACKAGE(Boost COMPONENTS program_options system filesystem regex) -PKG_CHECK_MODULES(SERVER_DEPS REQUIRED lxc json gio-2.0 libsystemd-journal libsystemd-daemon libcap-ng) +PKG_CHECK_MODULES(SERVER_DEPS REQUIRED lxc json gio-2.0 libcap-ng) INCLUDE_DIRECTORIES(${COMMON_FOLDER}) INCLUDE_DIRECTORIES(${LIBS_FOLDER}) diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index 452a54a..2b5a09e 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -47,8 +47,7 @@ ADD_EXECUTABLE(${SOCKET_TEST_CODENAME} ${socket_test_SRCS} ${common_SRCS} ${clie ## Link libraries ############################################################## FIND_PACKAGE (Boost COMPONENTS unit_test_framework system filesystem regex) -PKG_CHECK_MODULES(UT_SERVER_DEPS REQUIRED lxc json gio-2.0 libsystemd-daemon - libsystemd-journal libcap-ng) +PKG_CHECK_MODULES(UT_SERVER_DEPS REQUIRED lxc json gio-2.0 libcap-ng) INCLUDE_DIRECTORIES(${COMMON_FOLDER} ${SERVER_FOLDER} ${UNIT_TESTS_FOLDER} ${CLIENT_FOLDER} ${LIBS_FOLDER} ${SOCKET_TEST_FOLDER}) INCLUDE_DIRECTORIES(SYSTEM ${UT_SERVER_DEPS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) diff --git a/wrapper/CMakeLists.txt b/wrapper/CMakeLists.txt index 532e693..7f5ea46 100644 --- a/wrapper/CMakeLists.txt +++ b/wrapper/CMakeLists.txt @@ -51,7 +51,7 @@ SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES ## Link libraries ############################################################## FIND_PACKAGE(Boost COMPONENTS system filesystem) -PKG_CHECK_MODULES(LIB_DEPS REQUIRED gio-2.0 libsystemd-daemon libcap-ng) +PKG_CHECK_MODULES(LIB_DEPS REQUIRED gio-2.0 libcap-ng) INCLUDE_DIRECTORIES(SYSTEM ${LIB_DEPS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) INCLUDE_DIRECTORIES(${COMMON_FOLDER}) INCLUDE_DIRECTORIES(${LIBS_FOLDER}) diff --git a/zone-daemon/CMakeLists.txt b/zone-daemon/CMakeLists.txt index e721dbf..4d48141 100644 --- a/zone-daemon/CMakeLists.txt +++ b/zone-daemon/CMakeLists.txt @@ -31,7 +31,7 @@ ADD_EXECUTABLE(${ZONE_DAEMON_CODENAME} ${project_SRCS} ${common_SRCS}) ## Link libraries ############################################################## FIND_PACKAGE (Boost COMPONENTS program_options system filesystem) -PKG_CHECK_MODULES(ZONE_DAEMON_DEPS REQUIRED gio-2.0 libsystemd-journal libcap-ng) +PKG_CHECK_MODULES(ZONE_DAEMON_DEPS REQUIRED gio-2.0 libcap-ng) INCLUDE_DIRECTORIES(${COMMON_FOLDER}) INCLUDE_DIRECTORIES(${LIBS_FOLDER}) -- 2.7.4 From 3d3322780ebd21cd989e3a8ef7b03e4b66e475bc Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Wed, 20 May 2015 11:03:39 +0200 Subject: [PATCH 03/16] Fix building on x86_64 [Bug] Removed unneeded cast [Cause] Lose precision cast [Solution] N/A [Verification] Build on x86_64 Change-Id: I2302eaefed4f0c94f29ad94468ff9d83fa15166e --- wrapper/wrapper.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 72eece3..9483a87 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -718,7 +718,7 @@ API const char *vsm_error_string(vsm_error_e e) return vsm_error_string_v0_34((struct vsm_context *)ctx); } else { - return vsm_error_string_v0_3_1(static_cast((int)ctx)); + return vsm_error_string_v0_3_1(e); } } -- 2.7.4 From c49644b6bebb9f8889abe8dc01f9b068b0ccd2fd Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Wed, 20 May 2015 11:46:33 +0200 Subject: [PATCH 04/16] Add vsm_get_zone_rootpath API function [Bug/Feature] Introduce new API function: vsm_get_zone_rootpath [Cause] N/A [Solution] N/A [Verification] Build, install, run tests Change-Id: Ia4f9f6701f20d6a32878bf13c59a8ad9ade9a9bb --- client/vasum-client-impl.cpp | 12 ++++++++++++ client/vasum-client-impl.hpp | 5 +++++ client/vasum-client.cpp | 5 +++++ client/vasum-client.h | 11 +++++++++++ tests/unit_tests/client/ut-client.cpp | 17 +++++++++++++++++ 5 files changed, 50 insertions(+) diff --git a/client/vasum-client-impl.cpp b/client/vasum-client-impl.cpp index b9af36f..38e4c5a 100644 --- a/client/vasum-client-impl.cpp +++ b/client/vasum-client-impl.cpp @@ -241,6 +241,18 @@ VsmStatus Client::vsm_get_active_zone_id(VsmString* id) noexcept }); } +VsmStatus Client::vsm_get_zone_rootpath(const char* id, VsmString* rootpath) noexcept +{ + assert(id); + assert(rootpath); + + return coverException([&] { + api::ZoneInfoOut info; + mHostClient.callGetZoneInfo({ id }, info); + *rootpath = ::strdup(info.rootPath.c_str()); + }); +} + VsmStatus Client::vsm_lookup_zone_by_pid(int pid, VsmString* id) noexcept { assert(id); diff --git a/client/vasum-client-impl.hpp b/client/vasum-client-impl.hpp index 0b96149..86f7a5e 100644 --- a/client/vasum-client-impl.hpp +++ b/client/vasum-client-impl.hpp @@ -105,6 +105,11 @@ public: VsmStatus vsm_get_active_zone_id(VsmString* id) noexcept; /** + * @see ::vsm_get_zone_rootpath + */ + VsmStatus vsm_get_zone_rootpath(const char* id, VsmString* rootpath) noexcept; + + /** * @see ::vsm_lookup_zone_by_pid */ VsmStatus vsm_lookup_zone_by_pid(int pid, VsmString* id) noexcept; diff --git a/client/vasum-client.cpp b/client/vasum-client.cpp index c12e8c6..b1028e2 100644 --- a/client/vasum-client.cpp +++ b/client/vasum-client.cpp @@ -133,6 +133,11 @@ API VsmStatus vsm_get_active_zone_id(VsmClient client, VsmString* id) return getClient(client).vsm_get_active_zone_id(id); } +API VsmStatus vsm_get_zone_rootpath(VsmClient client, const char* id, VsmString* rootpath) +{ + return getClient(client).vsm_get_zone_rootpath(id, rootpath); +} + API VsmStatus vsm_lookup_zone_by_pid(VsmClient client, int pid, VsmString* id) { return getClient(client).vsm_lookup_zone_by_pid(pid, id); diff --git a/client/vasum-client.h b/client/vasum-client.h index 1d43094..6c68fe2 100644 --- a/client/vasum-client.h +++ b/client/vasum-client.h @@ -334,6 +334,17 @@ VsmStatus vsm_get_zone_ids(VsmClient client, VsmArrayString* array); VsmStatus vsm_get_active_zone_id(VsmClient client, VsmString* id); /** + * Get zone rootfs path. + * + * @param[in] client vasum-server's client + * @param[in] id zone name + * @param[out] rootpath zone rootfs path + * @return status of this function call + * @remark Use @p vsm_string_free() to free memory occupied by @p rootpath. + */ +VsmStatus vsm_get_zone_rootpath(VsmClient client, const char* id, VsmString* rootpath); + +/** * Get zone name of process with given pid. * * @param[in] client vasum-server's client diff --git a/tests/unit_tests/client/ut-client.cpp b/tests/unit_tests/client/ut-client.cpp index 328a5bd..3e83884 100644 --- a/tests/unit_tests/client/ut-client.cpp +++ b/tests/unit_tests/client/ut-client.cpp @@ -167,6 +167,23 @@ BOOST_AUTO_TEST_CASE(GetActiveZoneId) vsm_client_free(client); } +BOOST_AUTO_TEST_CASE(GetZoneRootPath) +{ + const std::string zoneId = "zone1"; + + VsmClient client = vsm_client_create(); + VsmStatus status = vsm_connect(client); + BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status); + VsmString rootpath; + status = vsm_get_zone_rootpath(client, zoneId.c_str(), &rootpath); + BOOST_REQUIRE_EQUAL(VSMCLIENT_SUCCESS, status); + + BOOST_CHECK_EQUAL(rootpath, "/tmp/ut-zones/" + zoneId + "/rootfs"); + + vsm_string_free(rootpath); + vsm_client_free(client); +} + BOOST_AUTO_TEST_CASE(LookupZoneById) { const std::string activeZoneId = "zone1"; -- 2.7.4 From 13d3aa32753860aa97f66d5641c81b0d00c83ae5 Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Thu, 21 May 2015 16:12:53 +0200 Subject: [PATCH 05/16] Fix IPCSuite/WriteTimeout [Bug] IPCSuite/WriteTimeout some time fails [Cause] To large write timeout and too small response time - checking timeout when response has already been callSync only sometimes takes into account the serialization time [Solution] Increase response time. Wait for sending till timeout countdown start [Verification] Build, install on emulator, run IPCSuite/WriteTimeout test (multiple times) Change-Id: Ic9e814a0ae5cb85a769f0398d5126b0b67f5c626 --- libs/ipc/internals/processor.hpp | 27 ++++++++++++++++++++++----- tests/unit_tests/ipc/ut-ipc.cpp | 11 ++++++++++- tests/unit_tests/ut.cpp | 2 ++ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/libs/ipc/internals/processor.hpp b/libs/ipc/internals/processor.hpp index ecc3a1d..b1b0a5f 100644 --- a/libs/ipc/internals/processor.hpp +++ b/libs/ipc/internals/processor.hpp @@ -442,6 +442,12 @@ private: unsigned int mMaxNumberOfPeers; template + MessageID callAsyncInternal(const MethodID methodID, + const PeerID peerID, + const std::shared_ptr& data, + const typename ResultHandler::type& process); + + template void setMethodHandlerInternal(const MethodID methodID, const typename MethodHandler::type& process); @@ -597,6 +603,15 @@ MessageID Processor::callAsync(const MethodID methodID, const typename ResultHandler::type& process) { Lock lock(mStateMutex); + return callAsyncInternal(methodID, peerID, data, process); +} + +template +MessageID Processor::callAsyncInternal(const MethodID methodID, + const PeerID peerID, + const std::shared_ptr& data, + const typename ResultHandler::type& process) +{ auto request = MethodRequest::create(methodID, peerID, data, process); mRequestQueue.pushBack(Event::METHOD, request); return request->messageID; @@ -618,17 +633,19 @@ std::shared_ptr Processor::callSync(const MethodID methodID, cv.notify_all(); }; - MessageID messageID = callAsync(methodID, - peerID, - data, - process); + Lock lock(mStateMutex); + MessageID messageID = callAsyncInternal(methodID, + peerID, + data, + process); auto isResultInitialized = [&result]() { return result.isValid(); }; - Lock lock(mStateMutex); LOGT(mLogPrefix + "Waiting for the response..."); + //In the case of too large sending time response can be received far after timeoutMS but + //before this thread wakes up and before predicate check (there will by no timeout exception) if (!cv.wait_for(lock, std::chrono::milliseconds(timeoutMS), isResultInitialized)) { LOGW(mLogPrefix + "Probably a timeout in callSync. Checking..."); diff --git a/tests/unit_tests/ipc/ut-ipc.cpp b/tests/unit_tests/ipc/ut-ipc.cpp index e71a160..958f1f2 100644 --- a/tests/unit_tests/ipc/ut-ipc.cpp +++ b/tests/unit_tests/ipc/ut-ipc.cpp @@ -180,6 +180,15 @@ void longEchoCallback(const PeerID, methodResult->set(returnData); } +void shortEchoCallback(const PeerID, + std::shared_ptr& data, + MethodResult::Pointer methodResult) +{ + std::this_thread::sleep_for(std::chrono::milliseconds(SHORT_OPERATION_TIME)); + auto returnData = std::make_shared(data->intVal); + methodResult->set(returnData); +} + PeerID connect(Service& s, Client& c) { // Connects the Client to the Service and returns Clients PeerID @@ -497,7 +506,7 @@ MULTI_FIXTURE_TEST_CASE(ReadTimeout, F, ThreadedFixture, GlibFixture) MULTI_FIXTURE_TEST_CASE(WriteTimeout, F, ThreadedFixture, GlibFixture) { Service s(F::getPoll(), SOCKET_PATH); - s.setMethodHandler(1, echoCallback); + s.setMethodHandler(1, shortEchoCallback); s.start(); Client c(F::getPoll(), SOCKET_PATH); diff --git a/tests/unit_tests/ut.cpp b/tests/unit_tests/ut.cpp index bb45e84..718bd2c 100644 --- a/tests/unit_tests/ut.cpp +++ b/tests/unit_tests/ut.cpp @@ -30,6 +30,7 @@ #include +#include "utils/signal.hpp" using namespace boost::unit_test; using namespace logger; @@ -39,5 +40,6 @@ test_suite* init_unit_test_suite(int /*argc*/, char** /*argv*/) Logger::setLogLevel(LogLevel::TRACE); Logger::setLogBackend(new StderrBackend()); + utils::signalBlock(SIGPIPE); return NULL; } -- 2.7.4 From d4d3a18185664a406b86719d541becd5e1d439ee Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Thu, 21 May 2015 17:05:16 +0200 Subject: [PATCH 06/16] Fix SwitchToDefault and AllowSwitchToDefault [Bug] SwitchToDefault and AllowSwitchToDefault some times fails [Cause] Signal handler are not set [Solution] Ensure signal handler propagate (wait) [Verification] Build, install on emulator, run ZonesManagerSuite/SwitchToDefault and ZonesManagerSuite/AllowSwitchToDefault tests (multiple times) Change-Id: I3c9c2549903cebcc30496af3ccb427c1186d1b23 --- tests/unit_tests/server/ut-zones-manager.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/unit_tests/server/ut-zones-manager.cpp b/tests/unit_tests/server/ut-zones-manager.cpp index f73e164..0283fd9 100644 --- a/tests/unit_tests/server/ut-zones-manager.cpp +++ b/tests/unit_tests/server/ut-zones-manager.cpp @@ -73,6 +73,7 @@ const std::string CONFIG_DIR = VSM_TEST_CONFIG_INSTALL_DIR; const std::string TEST_CONFIG_PATH = CONFIG_DIR + "/test-daemon.conf"; const std::string MISSING_CONFIG_PATH = CONFIG_DIR + "/missing-daemon.conf"; const int EVENT_TIMEOUT = 5000; +const int SIGNAL_PROPAGATE_TIME = 500; // ms //const int UNEXPECTED_EVENT_TIMEOUT = EVENT_TIMEOUT / 5; const std::string TEST_APP_NAME = "testapp"; const std::string TEST_MESSAGE = "testmessage"; @@ -870,6 +871,7 @@ MULTI_FIXTURE_TEST_CASE(SwitchToDefault, F, ACCESSORS) cm.restoreAll(); typename F::HostAccessory host; + std::this_thread::sleep_for(std::chrono::milliseconds(SIGNAL_PROPAGATE_TIME)); auto isDefaultFocused = [&cm]() -> bool { return cm.getRunningForegroundZoneId() == "zone1"; @@ -892,6 +894,7 @@ MULTI_FIXTURE_TEST_CASE(AllowSwitchToDefault, F, ACCESSORS) cm.restoreAll(); typename F::HostAccessory host; + std::this_thread::sleep_for(std::chrono::milliseconds(SIGNAL_PROPAGATE_TIME)); auto isDefaultFocused = [&cm]() -> bool { return cm.getRunningForegroundZoneId() == "zone1"; -- 2.7.4 From 8118a30e23585d04c92e30aa67b8b716a51400f5 Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Wed, 20 May 2015 17:41:52 +0200 Subject: [PATCH 07/16] Vasum wrapper #7, add functions introduced in last vasum old API, link to Ipc [Bug/Feature] latest image not works with wrapper [Cause] last vasum old API introduced new functions [Solution] #7 implement those new functions [Verification] Build, install on target, check journal Change-Id: I95d46157d419e0886beb00574bc94a1bfe316677 --- wrapper/CMakeLists.txt | 2 +- wrapper/wrapper-compatibility.cpp | 235 +++++++++++++--------------------- wrapper/wrapper.cpp | 257 ++++++++++++++++++++++++-------------- 3 files changed, 249 insertions(+), 245 deletions(-) diff --git a/wrapper/CMakeLists.txt b/wrapper/CMakeLists.txt index 7f5ea46..a75bfa9 100644 --- a/wrapper/CMakeLists.txt +++ b/wrapper/CMakeLists.txt @@ -58,7 +58,7 @@ INCLUDE_DIRECTORIES(${LIBS_FOLDER}) INCLUDE_DIRECTORIES(${SERVER_FOLDER}) INCLUDE_DIRECTORIES(${CLIENT_FOLDER}) TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${LIB_DEPS_LIBRARIES} ${Boost_LIBRARIES} - Config SimpleDbus) + Config SimpleDbus Ipc) ## Generate the pc file ######################################################## CONFIGURE_FILE(${PC_FILE}.in ${CMAKE_BINARY_DIR}/${PC_FILE} @ONLY) diff --git a/wrapper/wrapper-compatibility.cpp b/wrapper/wrapper-compatibility.cpp index adb1edd..303fcfe 100644 --- a/wrapper/wrapper-compatibility.cpp +++ b/wrapper/wrapper-compatibility.cpp @@ -39,167 +39,66 @@ #include #include #include +#include #include #include +#include "logger/logger.hpp" +#include "logger/logger-scope.hpp" + #define UNUSED(x) ((void)(x)) extern "C" { // find_container_by_pid API char *find_container_by_pid(pid_t /*pid*/) { + LOGS(""); return NULL; } // get_domain_pid API pid_t get_domain_pid(const char * /*name*/, const char * /*target*/) { + LOGS(""); return -1; } -// mainloop_add_watch -int mainloop_add_watch(struct mainloop * /*mainloop*/, int /*fd*/, mainloop_event /*event*/, mainloop_callback /*callback*/, void * /*data*/) { - return 0; -} -// mainloop_cleanup -int mainloop_cleanup(struct mainloop * /*mainloop*/) { - return 0; -} -// mainloop_create -struct mainloop *mainloop_create(void) { - struct mainloop *mainloop = (struct mainloop *)malloc(sizeof(struct mainloop)); - mainloop->epfd = -1; // epoll_create(2); - pthread_mutex_init(&mainloop->ml_mutex, NULL); - pthread_rwlock_init(&mainloop->lock, NULL); - adt_init_list(&mainloop->watches); - return mainloop; -} -// mainloop_dispatch -int mainloop_dispatch(struct mainloop * /*mainloop*/, int /*timeout*/) { - return 0; -} -// mainloop_remove_watch -int mainloop_remove_watch(struct mainloop * /*mainloop*/, int /*fd*/) { - return 0; -} -// mainloop_run -int mainloop_run(struct mainloop * /*mainloop*/, int /*timeout*/) { - return 0; -} -// mxe_alloc_endpoint -struct mxe_endpoint *mxe_alloc_endpoint(struct mxe_engine * /*engine*/, int /*fd*/, mainloop_callback /*callback*/, int /*type*/) { - return NULL; -} -// mxe_broadcast -int mxe_broadcast(struct mxe_engine * /*engine*/, struct mxe_emple * /*emple*/, ...) { - return 0; -} -// mxe_create_client -struct mxe_endpoint *mxe_create_client(struct mxe_engine *engine, const char * /*addr*/) { - struct mxe_endpoint *ep = (struct mxe_endpoint *)malloc(sizeof(struct mxe_endpoint)); - ep->type = 1; //MXE_EPT_SLAVE - ep->fd = -1; //sock_connect(addr); - ep->engine = engine; - pthread_rwlock_init(&ep->queue_lock, NULL); - pthread_mutex_init(&ep->rd_mutex, NULL); - pthread_mutex_init(&ep->wr_mutex, NULL); - adt_init_list(&ep->queue); - adt_init_list(&ep->list); - return ep; -} -// mxe_create_server -struct mxe_endpoint *mxe_create_server(struct mxe_engine * /*engine*/, const char * /*addr*/) { - return NULL; -} -// mxe_emple_factory -struct mxe_emple *mxe_emple_factory(struct mxe_proxy * /*proxy*/) { - return NULL; -} -// mxe_finalize_engine -int mxe_finalize_engine(struct mxe_engine * /*engine*/) { - return 0; -} -// mxe_free_endpoint -int mxe_free_endpoint(struct mxe_endpoint * /*ep*/) { - return 0; -} -// mxe_invoke -int mxe_invoke(struct mxe_endpoint * /*ep*/, struct mxe_emple * /*emple*/, ...) { - return 0; -} -// mxe_lookup_emple -struct mxe_emple *mxe_lookup_emple(struct mxe_endpoint * /*ep*/, int /*signature*/) { - return NULL; -} -// mxe_lookup_proxy -struct mxe_proxy *mxe_lookup_proxy(struct mxe_engine * /*engine*/, int /*id*/) { - return NULL; -} -// mxe_pop_integer -int mxe_pop_integer(struct mxe_message * /*msg*/) { - return 0; -} -// mxe_pop_string -char *mxe_pop_string(struct mxe_message * /*msg*/) { - return NULL; -} -// mxe_prepare_engine -struct mxe_engine *mxe_prepare_engine(struct mainloop *mainloop, void *data) { - struct mxe_engine *engine = (struct mxe_engine *)malloc(sizeof(struct mxe_engine)); - engine->data = data; - engine->mainloop = mainloop; - pthread_rwlock_init(&engine->endpoint_lock, NULL); - adt_init_list(&engine->endpoints); - - return engine; -} -// mxe_push_integer -int mxe_push_integer(struct mxe_message * /*msg*/, int /*value*/) { - return 0; -} -// mxe_push_string -int mxe_push_string(struct mxe_message * /*msg*/, const char * /*str*/) { - return 0; -} -// mxe_register_proxy -int mxe_register_proxy(struct mxe_engine * /*engine*/, struct mxe_proxy * /*proxy*/) { - return 0; -} -// mxe_reply_message (intenal) -int mxe_reply_message(struct mxe_endpoint * /*ep*/, struct mxe_message * /*origin*/, ...) { - return 0; -} -// mxe_reset_payload -void mxe_reset_payload(struct mxe_message * /*msg*/) { -} -// mxe_wait_for_event -int mxe_wait_for_event(struct mxe_endpoint * /*ep*/, struct mxe_emple * /*emple*/) { - return 0; -} -// sock_close_socket (intern) -int sock_close_socket(int /*fd*/) { +// sock_close_socket +API int sock_close_socket(int /*fd*/) { + LOGS(""); return 0; } // sock_connect API int sock_connect(const char * /*path*/) { - return 0; + LOGS(""); + return -1; } // sock_create_socket API int sock_create_socket(const char * /*path*/, int /*type*/, int /*flags*/) { - return 0; + LOGS(""); + return -1; } // sock_monitor_address API int sock_monitor_address(char * /*buffer*/, int /*len*/, const char * /*lxcpath*/) { + LOGS(""); return 0; } // sock_recv_fd (intern) API int sock_recv_fd(int /*fd*/, int * /*recvfd*/, void * /*data*/, size_t /*size*/) { + LOGS(""); return 0; } // sock_send_fd API int sock_send_fd(int /*fd*/, int /*sendfd*/, void * /*data*/, size_t /*size*/) { + LOGS(""); return 0; } // vasum_log -API void vasum_log(int /*type*/, const char * /*tag*/, const char * /*fmt*/ , ...) { +API void vasum_log(int type, const char *tag, const char *fmt, ...) { + va_list arg_ptr; + char buf[100]; + va_start(arg_ptr, fmt); + vsnprintf(buf, sizeof(buf), fmt, arg_ptr); + va_end(arg_ptr); + LOGS("type=" << type << " tag=" << tag << " msg=" << buf); } #define MAX_ERROR_MSG 0x1000 @@ -222,6 +121,7 @@ const char *const fso_type_strtab[] = { API const char *fso_type_to_string(vsm_fso_type_t fso) { + LOGS(""); if (fso < 0 || fso > VSM_FSO_MAX_TYPE) { return NULL; } @@ -231,6 +131,7 @@ API const char *fso_type_to_string(vsm_fso_type_t fso) API int wait_for_pid_status(pid_t pid) { + LOGS(""); int status, ret; again: @@ -239,8 +140,7 @@ API int wait_for_pid_status(pid_t pid) if (errno == EINTR) { goto again; } else { - ERROR("waitpid- pid : %d error : %s", pid, - strerror(errno)); + ERROR("waitpid pid : %d error : %s", pid, strerror(errno)); return -1; } } @@ -251,6 +151,7 @@ API int wait_for_pid_status(pid_t pid) API vsm_fso_type_t fso_string_to_type(char *str) { + LOGS(""); int len; int i; for (i = 0; i <= VSM_FSO_MAX_TYPE; i++) { @@ -264,6 +165,7 @@ API vsm_fso_type_t fso_string_to_type(char *str) API int mkdir_p(const char *dir, mode_t mode) { + LOGS(""); const char *tmp = dir; const char *orig = dir; char *makeme; @@ -286,6 +188,7 @@ API int mkdir_p(const char *dir, mode_t mode) API int lock_fd(int fd, int wait) { + LOGS(""); int ret; struct flock f; @@ -309,6 +212,7 @@ API int lock_fd(int fd, int wait) API int unlock_fd(int fd) { + LOGS(""); struct flock f; f.l_type = F_UNLCK; f.l_whence = SEEK_SET; @@ -319,11 +223,13 @@ API int unlock_fd(int fd) API int copy_smacklabel(const char * /*source*/, const char * /*dest*/) { + LOGS(""); return 0; } API int remove_file(char *path) { + LOGS(""); struct stat path_stat; DIR *dp; struct dirent *d; @@ -376,6 +282,7 @@ API int remove_file(char *path) API int copy_file(const char *source, const char *dest, int /*flags*/) { + LOGS(""); int ret; FILE *sfp, *dfp; size_t nread, nwritten, size = BUF_SIZE; @@ -426,6 +333,7 @@ API int copy_file(const char *source, const char *dest, int /*flags*/) API int regex_compile(regex_t * r, const char *regex_text) { + LOGS(""); int status = regcomp(r, regex_text, REG_EXTENDED | REG_NEWLINE); if (status != 0) { @@ -442,6 +350,7 @@ API int regex_compile(regex_t * r, const char *regex_text) API int regex_match(regex_t * r, const char *to_match) { + LOGS(""); const char *p = to_match; const int n_matches = 10; regmatch_t m[n_matches]; @@ -485,6 +394,7 @@ API int regex_match(regex_t * r, const char *to_match) API int get_peer_pid(int fd) { + LOGS(""); struct ucred cred; socklen_t cr_len = sizeof(cred); if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &cr_len) < 0) { @@ -495,23 +405,25 @@ API int get_peer_pid(int fd) API pid_t gettid(void) { + LOGS(""); return syscall(__NR_gettid); } API int set_smacklabel_fd(int fd, const char *xattr_name, const char *label) { + LOGS(""); size_t len; int ret; - if(fd < 0) + if (fd < 0) return -1; len = strnlen(label, SMACK_LABEL_LEN + 1); if (len > SMACK_LABEL_LEN) return -1; - ret = fsetxattr(fd, xattr_name, label, len+1, 0); - if(ret != 0) { + ret = fsetxattr(fd, xattr_name, label, len + 1, 0); + if (ret != 0) { ERROR("Set Smack lable error : %s", strerror(errno)); } return ret; @@ -519,52 +431,55 @@ API int set_smacklabel_fd(int fd, const char *xattr_name, const char *label) API int set_smacklabel(const char *path, const char *xattr_name, const char *label) { + LOGS(""); size_t len; int ret; - if(path == NULL) + if (path == NULL) return -1; len = strnlen(label, SMACK_LABEL_LEN + 1); if (len > SMACK_LABEL_LEN) return -1; - ret = lsetxattr(path, xattr_name, label, len+1, 0); - if(ret != 0) { + ret = lsetxattr(path, xattr_name, label, len + 1, 0); + if (ret != 0) { ERROR("Set Smack lable error : %s", strerror(errno)); } return ret; } API char *get_self_smacklabel(void) { + LOGS(""); int ret; int fd; const char *attr_path = "/proc/self/attr/current"; - char buffer[SMACK_LABEL_LEN+1]; + char buffer[SMACK_LABEL_LEN + 1]; - bzero(buffer, SMACK_LABEL_LEN+1); + bzero(buffer, SMACK_LABEL_LEN + 1); fd = open(attr_path, O_RDONLY); - if( fd < 0) { + if (fd < 0) { return NULL; } - ret = read(fd, buffer, SMACK_LABEL_LEN+1); + ret = read(fd, buffer, SMACK_LABEL_LEN + 1); close(fd); if (ret < 0) { return NULL; } - if( ret > SMACK_LABEL_LEN) { + if (ret > SMACK_LABEL_LEN) { //return NULL; } - buffer[SMACK_LABEL_LEN]=0; + buffer[SMACK_LABEL_LEN] = 0; return strdup(buffer); } API int get_self_cpuset(char *name, int buf_sz) { + LOGS(""); int fd; int lxc_len, ret; char cpuset_path[] = "/proc/self/cpuset"; @@ -585,7 +500,7 @@ API int get_self_cpuset(char *name, int buf_sz) close(fd); lxc_len = sizeof("/lxc"); - if( ret < lxc_len) { + if (ret < lxc_len) { name[0] = '/'; name[1] = 0; return 1; @@ -593,14 +508,14 @@ API int get_self_cpuset(char *name, int buf_sz) char *p; p = current_name + lxc_len; - while(*p != '\0') { - if(*p == '/') { + while (*p != '\0') { + if (*p == '/') { *p = '\0'; break; } p++; } - snprintf(name, buf_sz, "%s", current_name+lxc_len); + snprintf(name, buf_sz, "%s", current_name + lxc_len); } return ret - lxc_len; @@ -609,6 +524,7 @@ API int get_self_cpuset(char *name, int buf_sz) API char * get_pid_cpuset(int pid) { + LOGS(""); int fd; int ret; char cpuset_path[PATH_MAX]; @@ -617,7 +533,7 @@ API char * get_pid_cpuset(int pid) snprintf(cpuset_path, PATH_MAX, "/proc/%d/cpuset", pid); ret = access(cpuset_path, F_OK | R_OK); - if( ret != 0 ) + if (ret != 0) return NULL; fd = open(cpuset_path, O_RDONLY); @@ -641,6 +557,7 @@ API char * get_pid_cpuset(int pid) API char * read_namespace_link(const char *ns, int pid) { + LOGS(""); char ns_path[PATH_MAX]; char buf[NAME_MAX]; int ret; @@ -648,11 +565,11 @@ API char * read_namespace_link(const char *ns, int pid) snprintf(ns_path, PATH_MAX, "/proc/%d/ns/%s", pid, ns); ret = access(ns_path, F_OK); - if(ret != 0) + if (ret != 0) return NULL; ret = readlink(ns_path, buf, NAME_MAX); - if( ret == -1 ) { + if (ret == -1) { ERROR("Failed to readlink ns file - [%s]", ns_path); return NULL; } @@ -669,6 +586,7 @@ API char * read_namespace_link(const char *ns, int pid) API int dev_enumerate_nodes(const char *cname, dev_enumerator enumerator, void *data) { + LOGS(""); int ret; FILE *fp;; char path[PATH_MAX], entry[64]; @@ -706,6 +624,7 @@ API int dev_enumerate_nodes(const char *cname, dev_enumerator enumerator, API int dev_terminal_enumerator(int type, int major, int minor, void *data) { + LOGS(""); int *dev = (int*)data; *dev = minor; @@ -720,6 +639,7 @@ API int dev_terminal_enumerator(int type, int major, int minor, void *data) // libs/namespace.c API pid_t get_init_pid(const char *name) { + LOGS(""); char filename[PATH_MAX]; FILE *fp; pid_t ret = -1; @@ -746,6 +666,7 @@ API pid_t get_init_pid(const char *name) API pid_t get_zone_pid(const char *name, const char *target) { + LOGS(""); char path[PATH_MAX]; char cmd[PATH_MAX]; int res = 0, len; @@ -823,6 +744,7 @@ API pid_t get_zone_pid(const char *name, const char *target) API int open_ns(pid_t pid, const char *name) { + LOGS(""); int fd, ret; char path[PATH_MAX]; @@ -846,6 +768,7 @@ API int open_ns(pid_t pid, const char *name) #include static int is_console(int fd) { + LOGS(""); char arg; return (isatty(fd) && @@ -873,6 +796,7 @@ static int open_console(const char *path) API int get_console_fd(const char *path) { + LOGS(""); int fd; if (path) { @@ -905,6 +829,7 @@ API int get_console_fd(const char *path) API int vt_switch_terminal(int id) { + LOGS(""); int fd, ret = -1; fd = get_console_fd(NULL); @@ -928,6 +853,7 @@ API int vt_switch_terminal(int id) API int vt_find_unused_terminal(void) { + LOGS(""); int fd, nr = -1; fd = get_console_fd(NULL); @@ -949,6 +875,7 @@ API int vt_find_unused_terminal(void) API int vt_query_active_terminal(void) { + LOGS(""); int fd, ret = -1; struct vt_stat vtstat; @@ -1189,6 +1116,7 @@ static int parse_statement(struct parser_context *ctx, int argc, char **argv, API int parse_stream_core(struct parser_context *ctx, char *s) { + LOGS(""); struct unit_keyword_callback *kw; struct parser_state state; char *args[PARSER_MAXARGS]; @@ -1270,6 +1198,7 @@ static char *open_stream(const char *name, unsigned int *_sz) API int parse_stream(const char *name, struct unit_parser *parser) { + LOGS(""); char *stream; struct parser_context *ctx; @@ -1294,6 +1223,13 @@ API int parse_stream(const char *name, struct unit_parser *parser) return 0; } +API struct vsm_netdev *alloc_netdev(struct vsm_zone * /*zone*/, vsm_netdev_type_t /*type*/, const char * /*netdev_name*/) { + LOGS(""); + return NULL; +} +API void enter_to_ns(pid_t /*pid*/, char * /*name*/) { + LOGS(""); +} // dummy-ops static int dummy_create_zone(vsm_context_h /*ctx*/, const char * /*zone_name*/, @@ -1350,7 +1286,7 @@ static vsm_zone_h dummy_get_foreground(vsm_context_h ctx) static int dummy_iterate_zone(vsm_context_h ctx, vsm_zone_iter_cb callback, void *user_data) { - if( callback) { + if (callback) { callback(ctx->root_zone, user_data); } return VSM_ERROR_NONE; @@ -1440,7 +1376,7 @@ static int dummy_attach_zone_wait(vsm_context_h ctx, const char *zone_name, vsm_attach_command_s * command, vsm_attach_options_s * opts) { - pid_t pid=0; + pid_t pid = 0; int ret, status; ret = dummy_attach_zone(ctx, zone_name, command, opts, &pid); @@ -1482,7 +1418,7 @@ static int dummy_is_equivalent_zone(vsm_context_h /*ctx*/, pid_t /*pid*/) static int dummy_get_host_pid(vsm_zone_h zone, pid_t pid) { - if(zone == zone->parent) + if (zone == zone->parent) return pid; return -VSM_ERROR_NO_OBJECT; @@ -1517,7 +1453,7 @@ static int dummy_declare_link(vsm_context_h /*ctx*/, const char *source, } struct vasum_ops dummy_ops; -static int dummy_ops_init(){ +static int dummy_ops_init() { dummy_ops.create_zone = dummy_create_zone; dummy_ops.destroy_zone = dummy_destroy_zone; dummy_ops.start_zone = dummy_start_zone; @@ -1542,4 +1478,5 @@ static int dummy_ops_init(){ } int dummy_ops_init_i = dummy_ops_init(); + } //extern "C" diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 9483a87..4fc0c60 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -57,10 +57,6 @@ static struct int glib_stop; } wrap; -extern "C" { -API void vsm_string_free(VsmString string); -API void vsm_array_string_free(VsmArrayString astring); -} #ifndef offsetof #define offsetof(type, memb) ((size_t)&((type *)0)->memb) @@ -77,7 +73,6 @@ API void vsm_array_string_free(VsmArrayString astring); #define vsm_attach_command_t vsm_attach_command_s #define vsm_attach_options_t vsm_attach_options_s -#define vsm_zone_state_cb vsm_zone_state_changed_cb void __attribute__ ((constructor)) wrapper_load(void); void __attribute__ ((destructor)) wrapper_unload(void); @@ -108,9 +103,9 @@ static void callcheck() void init_wrapper() { if (wrap.done) return ; - memset(&wrap,0,sizeof(wrap)); + memset(&wrap, 0, sizeof(wrap)); wrap.done = 1; - LOGS("WRAP:"); + LOGS(""); } static struct vsm_zone* wrap_vsm_zone(WrappedContext *w, VsmZone zone, bool create = false) @@ -129,6 +124,7 @@ static struct vsm_zone* wrap_vsm_zone(WrappedContext *w, VsmZone zone, bool crea zw.client = w->client; zw.zone = zone; zw.vz.name = zone->id; + zw.vz.id = 0; zw.vz.type = NULL; zw.vz.user_data = NULL; zw.vz.rootfs_path = zone->rootfs_path; @@ -143,7 +139,7 @@ static struct vsm_zone* wrap_vsm_zone(WrappedContext *w, VsmZone zone, bool crea static int wrap_error(VsmStatus st, const Client *c) { if (st == VSMCLIENT_SUCCESS) LOGI("return success " << st); - else LOGE("return error " << st << "m=" << (c ? c->vsm_get_status_message() : "n/a")); + else LOGE("return error=" << st << ", msg=" << (c ? c->vsm_get_status_message() : "n/a")); switch (st) { case VSMCLIENT_SUCCESS: return VSM_ERROR_NONE; case VSMCLIENT_CUSTOM_ERROR: return -VSM_ERROR_GENERIC; @@ -171,7 +167,7 @@ static void init_context_wrap(WrappedContext *w) //init root_zone ctx->root_zone = &w->hq_root; ctx->root_zone->name = (char*)""; - ctx->root_zone->id=0; + ctx->root_zone->id = 0; ctx->root_zone->rootfs_path = (char*)"/"; ctx->root_zone->terminal = -1; @@ -201,9 +197,13 @@ static void init_context_wrap(WrappedContext *w) //ctx->data = ep; } +extern "C" { +API void vsm_string_free(VsmString string); +API void vsm_array_string_free(VsmArrayString astring); + API vsm_context_h vsm_create_context(void) { - LOGS("WRAP:"); + LOGS(""); callcheck(); WrappedContext *w = new WrappedContext(); init_context_wrap(w); @@ -214,7 +214,7 @@ API vsm_context_h vsm_create_context(void) API int vsm_cleanup_context(vsm_context_h ctx) { - LOGS("WRAP:"); + LOGS(""); callcheck(); WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx); if (w->client != NULL) { @@ -225,6 +225,7 @@ API int vsm_cleanup_context(vsm_context_h ctx) zw.netdevs.clear(); } w->zones.clear(); + pthread_rwlock_destroy(&ctx->lock); delete w; return VSM_ERROR_NONE; } @@ -260,7 +261,7 @@ API vsm_error_e vsm_last_error(struct vsm_context *ctx) API int vsm_get_poll_fd(struct vsm_context *ctx) { - LOGS("WRAP:"); + LOGS(""); callcheck(); WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx); UNUSED(w); @@ -271,7 +272,7 @@ API int vsm_get_poll_fd(struct vsm_context *ctx) } API int vsm_enter_eventloop(struct vsm_context *ctx, int flags, int timeout) { - LOGS("WRAP:"); + LOGS(""); callcheck(); UNUSED(flags); UNUSED(timeout); @@ -285,7 +286,7 @@ API int vsm_enter_eventloop(struct vsm_context *ctx, int flags, int timeout) API int vsm_create_zone(struct vsm_context *ctx, const char *zone_name, const char *template_name, int flag) { - LOGS("WRAP:create_zone " << zone_name); + LOGS("create_zone " << zone_name); callcheck(); WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx); UNUSED(flag); @@ -300,7 +301,7 @@ API int vsm_create_zone(struct vsm_context *ctx, const char *zone_name, const ch API int vsm_destroy_zone(struct vsm_context *ctx, const char *zone_name, int force) { - LOGS("WRAP:zone=" << zone_name); + LOGS("zone=" << zone_name); callcheck(); WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx); UNUSED(force); @@ -316,7 +317,7 @@ API int vsm_destroy_zone(struct vsm_context *ctx, const char *zone_name, int for API int vsm_start_zone(struct vsm_context *ctx, const char *zone_name) { - LOGS("WRAP:zone=" << zone_name); + LOGS("zone=" << zone_name); callcheck(); WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx); if (!w->client) return VSM_ERROR_GENERIC; @@ -326,7 +327,7 @@ API int vsm_start_zone(struct vsm_context *ctx, const char *zone_name) API int vsm_shutdown_zone(struct vsm_context *ctx, const char *zone_name, int force) { - LOGS("WRAP:zone=" << zone_name); + LOGS("zone=" << zone_name); callcheck(); WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx); UNUSED(force); @@ -337,7 +338,7 @@ API int vsm_shutdown_zone(struct vsm_context *ctx, const char *zone_name, int fo API int vsm_lock_zone(struct vsm_context *ctx, const char *zone_name, int shutdown) { - LOGS("WRAP:zone=" << zone_name); + LOGS("zone=" << zone_name); callcheck(); WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx); UNUSED(shutdown); @@ -348,7 +349,7 @@ API int vsm_lock_zone(struct vsm_context *ctx, const char *zone_name, int shutdo API int vsm_unlock_zone(struct vsm_context *ctx, const char *zone_name) { - LOGS("WRAP:zone=" << zone_name); + LOGS("zone=" << zone_name); callcheck(); WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx); if (!w->client) return VSM_ERROR_GENERIC; @@ -358,7 +359,7 @@ API int vsm_unlock_zone(struct vsm_context *ctx, const char *zone_name) API int vsm_set_foreground(struct vsm_zone *zone) { - LOGS("WRAP:"); + LOGS(""); callcheck(); WrappedZone *w = container_of(zone, WrappedZone, vz); if (!w->client) return VSM_ERROR_GENERIC; @@ -388,12 +389,13 @@ API int vsm_attach_zone_wait(struct vsm_context *ctx, API int vsm_iterate_zone(struct vsm_context *ctx, void (*callback)(struct vsm_zone *zone, void *user_data), void *user_data) { - LOGS("WRAP:"); + LOGS(""); callcheck(); WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx); if (!w->client) return -VSM_ERROR_GENERIC; callback(ctx->root_zone, user_data); for (auto& z : w->zones) { + LOGI("iterate callback zone: " << z.zone->id); callback(&z.vz, user_data); } return 0; @@ -401,7 +403,7 @@ API int vsm_iterate_zone(struct vsm_context *ctx, void (*callback)(struct vsm_zo API struct vsm_zone *vsm_lookup_zone_by_name(struct vsm_context *ctx, const char *path) { - LOGS("WRAP:name=" << path); + LOGS("name=" << path); callcheck(); WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx); VsmZone zone; @@ -415,16 +417,18 @@ API struct vsm_zone *vsm_lookup_zone_by_name(struct vsm_context *ctx, const char //supposed return ref to internal struct API struct vsm_zone *vsm_lookup_zone_by_pid(struct vsm_context *ctx, pid_t pid) { - LOGS("WRAP: pid=" << pid); + LOGS("pid=" << pid); callcheck(); WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx); VsmZone zone; VsmString id; + VsmStatus st; if (!w->client) return NULL; - if (w->client->vsm_lookup_zone_by_pid(pid, &id) != VSMCLIENT_SUCCESS) { - LOGE("vsm_lookup_zone_by_pid(" << pid << ") error"); + if ((st = w->client->vsm_lookup_zone_by_pid(pid, &id)) != VSMCLIENT_SUCCESS) { + wrap_error(st, w->client); return NULL; } + LOGI("found zone(pid=" << pid << ")='" << id << "'"); if (::strcmp(id, "host") == 0) { return w->hq_ctx.root_zone; } @@ -432,9 +436,9 @@ API struct vsm_zone *vsm_lookup_zone_by_pid(struct vsm_context *ctx, pid_t pid) return wrap_vsm_zone(w, zone); } -API int vsm_add_state_changed_callback(struct vsm_context *ctx, vsm_zone_state_cb callback, void *user_data) +API int vsm_add_state_changed_callback(struct vsm_context *ctx, vsm_zone_state_changed_cb callback, void *user_data) { - LOGS("WRAP:"); + LOGS(""); callcheck(); WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx); VsmSubscriptionId subscriptionId; @@ -443,7 +447,7 @@ API int vsm_add_state_changed_callback(struct vsm_context *ctx, vsm_zone_state_c void { VsmZone zone; //TODO what are valid state, event - vsm_zone_state_t t=VSM_ZONE_STATE_RUNNING; + vsm_zone_state_t t = VSM_ZONE_STATE_RUNNING; UNUSED(dbusAddress); w->client->vsm_lookup_zone_by_id(id, &zone); callback(wrap_vsm_zone(w, zone), t, data); @@ -454,7 +458,7 @@ API int vsm_add_state_changed_callback(struct vsm_context *ctx, vsm_zone_state_c API int vsm_del_state_changed_callback(struct vsm_context *ctx, int handle) { - LOGS("WRAP:"); + LOGS(""); callcheck(); WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx); VsmSubscriptionId subscriptionId = (VsmSubscriptionId)handle; @@ -464,7 +468,7 @@ API int vsm_del_state_changed_callback(struct vsm_context *ctx, int handle) API int vsm_grant_device(struct vsm_zone *dom, const char *name, uint32_t flags) { - LOGS("WRAP:"); + LOGS(""); callcheck(); WrappedZone *w = container_of(dom, WrappedZone, vz); const char *id = dom->name; @@ -476,7 +480,7 @@ API int vsm_grant_device(struct vsm_zone *dom, const char *name, uint32_t flags) API int vsm_revoke_device(struct vsm_zone *dom, const char *name) { - LOGS("WRAP:"); + LOGS(""); callcheck(); WrappedZone *w = container_of(dom, WrappedZone, vz); const char *id = dom->name; @@ -486,7 +490,7 @@ API int vsm_revoke_device(struct vsm_zone *dom, const char *name) API struct vsm_netdev *vsm_create_netdev(struct vsm_zone *zone, vsm_netdev_type_t type, const char *target, const char *netdev) { - LOGS("WRAP:"); + LOGS(""); callcheck(); UNUSED(zone); UNUSED(type); @@ -521,26 +525,15 @@ API struct vsm_netdev *vsm_create_netdev(struct vsm_zone *zone, vsm_netdev_type_ return &w->netdevs.back(); //pointer to struct on vector } -API int vsm_destroy_netdev(struct vsm_zone *zone, struct vsm_netdev *netdev) +API int vsm_destroy_netdev(vsm_netdev_h) { - LOGS("WRAP:"); - callcheck(); - WrappedZone *w = container_of(zone, WrappedZone, vz); - - VsmStatus st = w->client->vsm_destroy_netdev(zone->name, netdev->name); - if (st == VSMCLIENT_SUCCESS) { - auto devbyname = [netdev](const vsm_netdev& v) {return ::strcmp(v.name, netdev->name) == 0;}; - auto devlist = std::find_if(w->netdevs.begin(), w->netdevs.end(), devbyname); - if (devlist != w->netdevs.end()) { - w->netdevs.erase(devlist); - } - } - return wrap_error(st, w->client); + LOGS(""); + return 0; } API int vsm_iterate_netdev(struct vsm_zone *zone, void (*callback)(struct vsm_netdev *, void *user_data), void *user_data) { - LOGS("WRAP:"); + LOGS(""); callcheck(); WrappedZone *w = container_of(zone, WrappedZone, vz); for (auto nd : w->netdevs) { @@ -551,7 +544,7 @@ API int vsm_iterate_netdev(struct vsm_zone *zone, void (*callback)(struct vsm_ne API struct vsm_netdev *vsm_lookup_netdev_by_name(struct vsm_zone *zone, const char *name) { - LOGS("WRAP:"); + LOGS(""); callcheck(); WrappedZone *w = container_of(zone, WrappedZone, vz); VsmNetdev nd; @@ -568,7 +561,7 @@ API struct vsm_netdev *vsm_lookup_netdev_by_name(struct vsm_zone *zone, const ch API int vsm_declare_file(struct vsm_context *ctx, vsm_fso_type_t ftype, const char *path, int flags, vsm_mode_t mode) { - LOGS("WRAP:"); + LOGS(""); callcheck(); /* Old implementation is following: (but implemented in server) args.oldpath = oldpath; @@ -610,7 +603,7 @@ API int vsm_declare_file(struct vsm_context *ctx, vsm_fso_type_t ftype, const ch API int vsm_declare_link(struct vsm_context *ctx, const char *source, const char *target) { - LOGS("WRAP:src=" << source << ", dst=" << target); + LOGS("src=" << source << ", dst=" << target); callcheck(); /* Old implementation is following: (but implemented in server) args.oldpath = oldpath; @@ -637,7 +630,7 @@ API int vsm_declare_mount(struct vsm_context *ctx, unsigned long flags, const void *data) { - LOGS("WRAP:"); + LOGS(""); callcheck(); /* Old implementation is following: (but implemented in server) args.oldpath = oldpath; @@ -659,72 +652,53 @@ API int vsm_declare_mount(struct vsm_context *ctx, return VSM_ERROR_NONE; } -API const char * vsm_get_zone_rootpath(vsm_zone_h /*zone*/) +API const char * vsm_get_zone_rootpath(vsm_zone_h zone) { - LOGS("WRAP:"); - return NULL; + LOGS(""); + return zone == NULL ? NULL : zone->rootfs_path; } -API const char * vsm_get_zone_name(vsm_zone_h /*zone*/) +API const char * vsm_get_zone_name(vsm_zone_h zone) { - LOGS("WRAP:"); - return NULL; + LOGS(""); + return zone == NULL ? NULL : zone->name; } -API int vsm_is_host_zone(vsm_zone_h /*zone*/) +API int vsm_is_host_zone(vsm_zone_h zone) { - LOGS("WRAP:"); - return VSM_ERROR_NONE; + LOGS(""); + if (zone == NULL) + return -VSM_ERROR_INVALID; + + return zone->parent == zone ? 1 : 0; } API vsm_zone_h vsm_join_zone(vsm_zone_h /*zone*/) { - LOGS("WRAP:"); + LOGS(""); return NULL; } -API int vsm_canonicalize_path(const char * /*input_path*/, char ** /*output_path*/) -{ - LOGS("WRAP:"); - return VSM_ERROR_NONE; -} - -static int is_valid_context(void * /*v*/) -{ - return 1; -} -static const char *vsm_error_string_v0_34(struct vsm_context *ctx) -{ - vsm_error_e error = ctx->error; - if (error < 0 || error > VSM_MAX_ERROR) { - return NULL; - } - return vsm_error_strtab[error]; -} -static const char *vsm_error_string_v0_3_1(vsm_error_e error) +API int vsm_canonicalize_path(const char *input_path, char **output_path) { - if (error < 0 || error > VSM_MAX_ERROR) { - return NULL; - } - return vsm_error_strtab[error]; + LOGS(""< VSM_MAX_ERROR) { + return NULL; } + return vsm_error_strtab[error]; } API struct vsm_zone *vsm_lookup_zone_by_terminal_id(struct vsm_context *ctx, int terminal) { - LOGS("WRAP:terminal=" << terminal); + LOGS("terminal=" << terminal); callcheck(); WrappedContext *w = container_of(ctx, WrappedContext, hq_ctx); VsmZone zone; @@ -752,4 +726,97 @@ API void vsm_string_free(VsmString string) free(string); } +API int vsm_add_event_callback(vsm_context_h, vsm_zone_event_cb, void*) { + LOGS(""); + return 0; +} +API int vsm_del_event_callback(vsm_context_h, int) { + LOGS(""); + return 0; +} +API int vsm_add_state_callback(vsm_context_h , vsm_zone_state_cb , void *) { + LOGS(""); + return 0; +} +API int vsm_del_state_callback(vsm_context_h , int ) { + LOGS(""); + return 0; +} +API int vsm_down_netdev(vsm_netdev_h) { + LOGS(""); + return 0; +} +API vsm_zone* vsm_get_foreground(vsm_context_h ctx) { + LOGS(""); + //return ((struct vasum_ops *)(ctx->vsm_ops))->get_foreground(ctx); + return dummy_ops.get_foreground(ctx); +} +API int vsm_get_host_pid(vsm_zone_h, pid_t) { + LOGS(""); + return 0; +} +API int vsm_get_ip_addr_netdev(vsm_netdev_h, vsm_netdev_addr_t, char*, int) { + LOGS(""); + return 0; +} +API void* vsm_get_userdata(vsm_zone_h) { + LOGS(""); + return NULL; +} +API int vsm_get_zone_id(vsm_zone_h zone) { + LOGS(""); + if (zone == NULL) + return -VSM_ERROR_INVALID; + return zone->id; +} +API vsm_zone_state_t vsm_get_zone_state(vsm_zone_h zone) { + LOGS(""); + if (zone == NULL) + return static_cast(-VSM_ERROR_INVALID); + return zone->state; +} +API int vsm_get_zone_terminal(vsm_zone_h) { + LOGS(""); + return -VSM_ERROR_NOT_SUPPORTED; +} +API const char *vsm_get_zone_type(vsm_zone_h zone) { + LOGS(""); + return zone == NULL ? NULL : zone->type; +} +API int vsm_is_equivalent_zone(vsm_context_h, pid_t) { + LOGS(""); + return 0; +} +API int vsm_is_virtualized() { + LOGS(""); + return 0; /* Running in Host */ +} +// libs/network.c +API int vsm_set_ip_addr_netdev(vsm_netdev_h, vsm_netdev_addr_t, const char*, int) { + LOGS(""); + return 0; +} +API int vsm_up_netdev(vsm_netdev_h) { + LOGS(""); + return 0; +} +// libs/zone.c +API int vsm_set_userdata(vsm_zone_h, void*) { + LOGS(""); + return 0; +} +API int vsm_state_change_watch_callback(struct vsm_context * /*ctx*/, char * /*name*/, + int /*state*/, int /*event*/) { + LOGS(""); + return 0; +} +// libs/vsm_signal.c +API int vsm_signal_state_broadcast(struct mxe_engine * /*engine*/, const char * /*zone_name*/, int /*state*/) { + LOGS(""); + return 0; +} +API int vsm_signal_event_broadcast(struct mxe_engine * /*engine*/, const char * /*zone_name*/, int /*event*/) { + LOGS(""); + return 0; +} } // extern "C" -- 2.7.4 From a8e270d21722cb019cb6ccdf46926921c3e2e53d Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Thu, 21 May 2015 17:25:22 +0200 Subject: [PATCH 08/16] Fix SocketSuite/SystemdSocket [Bug] Prevent from run vasum-socket-test.service in qemu [Cause] N/A [Solution] Remove ConditionVirtualization=no [Verification] Build, install on emulator, run SocketSuite/SystemdSocket test Change-Id: I4fc0c9da2a4ca55878acec6203caab3674d94d02 --- tests/unit_tests/configs/systemd/vasum-socket-test.service | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/unit_tests/configs/systemd/vasum-socket-test.service b/tests/unit_tests/configs/systemd/vasum-socket-test.service index 1d43529..23c6d3a 100644 --- a/tests/unit_tests/configs/systemd/vasum-socket-test.service +++ b/tests/unit_tests/configs/systemd/vasum-socket-test.service @@ -1,6 +1,5 @@ [Unit] Description=Vasum Socket tests mini-service -ConditionVirtualization=no [Service] Type=simple -- 2.7.4 From aa1f5f7317a73b7063b7ca4cc4872cc6271c79d2 Mon Sep 17 00:00:00 2001 From: Mateusz Malicki Date: Tue, 19 May 2015 18:38:11 +0200 Subject: [PATCH 09/16] Fix GetZoneIdByPidTestMultiple, GrantRevoke [Feature] GetZoneIdByPidTestMultiple, GrantRevoke some times fails [Cause] Timeout was too small [Solution] Increase timeout [Verification] Build, install, run tests Change-Id: Id191c1a6443e19f729dfc90c9a3c8c34dc4166e3 --- common/utils/fd-utils.hpp | 4 ++-- libs/config/fdstore.hpp | 4 ++-- libs/ipc/client.hpp | 2 +- libs/ipc/internals/processor.hpp | 2 +- libs/ipc/service.hpp | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/common/utils/fd-utils.hpp b/common/utils/fd-utils.hpp index 151eb1c..209de2c 100644 --- a/common/utils/fd-utils.hpp +++ b/common/utils/fd-utils.hpp @@ -42,7 +42,7 @@ void close(int fd); * @param size size of data to write * @param timeoutMS timeout in milliseconds */ -void write(int fd, const void* bufferPtr, const size_t size, int timeoutMS = 500); +void write(int fd, const void* bufferPtr, const size_t size, int timeoutMS = 5000); /** * Read from a file descriptor, throw on error. @@ -52,7 +52,7 @@ void write(int fd, const void* bufferPtr, const size_t size, int timeoutMS = 500 * @param size size of the data to read * @param timeoutMS timeout in milliseconds */ -void read(int fd, void* bufferPtr, const size_t size, int timeoutMS = 500); +void read(int fd, void* bufferPtr, const size_t size, int timeoutMS = 5000); /** * @return the max number of file descriptors for this process. diff --git a/libs/config/fdstore.hpp b/libs/config/fdstore.hpp index d34ea14..d76fc5f 100644 --- a/libs/config/fdstore.hpp +++ b/libs/config/fdstore.hpp @@ -50,7 +50,7 @@ public: * @param size size of the buffer * @param timeoutMS timeout in milliseconds */ - void write(const void* bufferPtr, const size_t size, const unsigned int timeoutMS = 500); + void write(const void* bufferPtr, const size_t size, const unsigned int timeoutMS = 5000); /** * Reads a value of the given type. @@ -59,7 +59,7 @@ public: * @param size size of the buffer * @param timeoutMS timeout in milliseconds */ - void read(void* bufferPtr, const size_t size, const unsigned int timeoutMS = 500); + void read(void* bufferPtr, const size_t size, const unsigned int timeoutMS = 5000); private: int mFD; diff --git a/libs/ipc/client.hpp b/libs/ipc/client.hpp index c76a817..fe3345a 100644 --- a/libs/ipc/client.hpp +++ b/libs/ipc/client.hpp @@ -125,7 +125,7 @@ public: template std::shared_ptr callSync(const MethodID methodID, const std::shared_ptr& data, - unsigned int timeoutMS = 500); + unsigned int timeoutMS = 5000); /** * Asynchronous method call. The return callback will be called on diff --git a/libs/ipc/internals/processor.hpp b/libs/ipc/internals/processor.hpp index b1b0a5f..121978c 100644 --- a/libs/ipc/internals/processor.hpp +++ b/libs/ipc/internals/processor.hpp @@ -262,7 +262,7 @@ public: std::shared_ptr callSync(const MethodID methodID, const PeerID peerID, const std::shared_ptr& data, - unsigned int timeoutMS = 500); + unsigned int timeoutMS = 5000); /** * Asynchronous method call diff --git a/libs/ipc/service.hpp b/libs/ipc/service.hpp index 8f6f62b..5b6297c 100644 --- a/libs/ipc/service.hpp +++ b/libs/ipc/service.hpp @@ -130,7 +130,7 @@ public: std::shared_ptr callSync(const MethodID methodID, const PeerID peerID, const std::shared_ptr& data, - unsigned int timeoutMS = 500); + unsigned int timeoutMS = 5000); /** * Asynchronous method call. The return callback will be called on -- 2.7.4 From 8de79321e3f62336cf2cdbd72ee355ae0af4bf22 Mon Sep 17 00:00:00 2001 From: Lukasz Kostyra Date: Wed, 6 May 2015 12:16:49 +0200 Subject: [PATCH 10/16] Remove libcap_ng and replace it with syscalls [Feature] libcap_ng is removed [Cause] N/A [Solution] Replace libcap_ng with syscalls [Verification] Build, install, run vasum-server without root and check if all needed capabilities were kept by the process. Change-Id: Idab4c7b579c6541d941e8c9e9c792427428f8fe5 --- client/CMakeLists.txt | 2 +- common/utils/environment.cpp | 206 ++++++++++++++++++++++++++++++++++++++-- common/utils/environment.hpp | 2 +- packaging/vasum.spec | 1 - server/CMakeLists.txt | 2 +- server/server.cpp | 2 +- tests/unit_tests/CMakeLists.txt | 2 +- zone-daemon/CMakeLists.txt | 2 +- 8 files changed, 202 insertions(+), 17 deletions(-) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index c1fdd19..c9f4c17 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -44,7 +44,7 @@ SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES ## Link libraries ############################################################## FIND_PACKAGE(Boost COMPONENTS system filesystem) -PKG_CHECK_MODULES(LIB_DEPS REQUIRED gio-2.0 libcap-ng) +PKG_CHECK_MODULES(LIB_DEPS REQUIRED gio-2.0) INCLUDE_DIRECTORIES(SYSTEM ${LIB_DEPS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) INCLUDE_DIRECTORIES(${COMMON_FOLDER}) INCLUDE_DIRECTORIES(${LIBS_FOLDER}) diff --git a/common/utils/environment.cpp b/common/utils/environment.cpp index 57b6e2a..9614cfa 100644 --- a/common/utils/environment.cpp +++ b/common/utils/environment.cpp @@ -31,7 +31,6 @@ #include "base-exception.hpp" #include "logger/logger.hpp" -#include #include #include #include @@ -42,12 +41,15 @@ #include #include #include +#include #include #include +#include +#include +#include -#if !__GLIBC_PREREQ(2, 14) -#include +#if !__GLIBC_PREREQ(2, 14) #ifdef __NR_setns static inline int setns(int fd, int nstype) @@ -61,10 +63,37 @@ static inline int setns(int fd, int nstype) #endif +#ifdef __NR_capset +static inline int capset(cap_user_header_t header, const cap_user_data_t data) +{ + return syscall(__NR_capset, header, data); +} +#else +#error "capset syscall isn't available" +#endif + +#ifdef __NR_capget +static inline int capget(cap_user_header_t header, cap_user_data_t data) +{ + return syscall(__NR_capget, header, data); +} +#else +#error "capget syscall isn't available" +#endif + using namespace utils; namespace { +#define CAP_SET_INHERITABLE (1 << 0) +#define CAP_SET_PERMITTED (1 << 1) +#define CAP_SET_EFFECTIVE (1 << 2) + +// number of __user_cap_data_struct elements needed +#define CAP_DATA_ELEMENT_COUNT 2 + +typedef unsigned int CapSet; + const std::map NAMESPACES = { {CLONE_NEWIPC, "ipc"}, {CLONE_NEWNET, "net"}, @@ -125,6 +154,75 @@ bool fdSend(int socket, int fd) return true; } +inline bool isValidCap(unsigned int cap) +{ + return cap <= CAP_LAST_CAP; +} + +// hasCap assumes that "set" variable will refer to only one set of capabilities +inline bool hasCap(unsigned int cap, const cap_user_data_t data, CapSet set) +{ + // calculate which half of data we need to update + int dataInd = 0; + if (cap > 31) { + dataInd = cap >> 5; + cap %= 32; + } + + switch (set) { + case CAP_SET_INHERITABLE: + return CAP_TO_MASK(cap) & data[dataInd].inheritable ? true : false; + case CAP_SET_PERMITTED: + return CAP_TO_MASK(cap) & data[dataInd].permitted ? true : false; + case CAP_SET_EFFECTIVE: + return CAP_TO_MASK(cap) & data[dataInd].effective ? true : false; + default: + return false; + }; +} + +// these inlines work in-place and update provided "data" array +// in these inlines, "set" can refer to mulitple sets of capabilities +inline void addCap(unsigned int cap, cap_user_data_t data, CapSet set) +{ + // calculate which half of data we need to update + int dataInd = 0; + if (cap > 31) { + dataInd = cap >> 5; + cap %= 32; + } + + if ((set & CAP_SET_INHERITABLE) == CAP_SET_INHERITABLE) { + data[dataInd].inheritable |= CAP_TO_MASK(cap); + } + if ((set & CAP_SET_PERMITTED) == CAP_SET_PERMITTED) { + data[dataInd].permitted |= CAP_TO_MASK(cap); + } + if ((set & CAP_SET_EFFECTIVE) == CAP_SET_EFFECTIVE) { + data[dataInd].effective |= CAP_TO_MASK(cap); + } +} + +inline void removeCap(unsigned int cap, cap_user_data_t data, CapSet set) +{ + // calculate which half of data we need to update + int dataInd = 0; + if (cap > 31) { + dataInd = cap >> 5; + cap %= 32; + } + + if ((set & CAP_SET_INHERITABLE) == CAP_SET_INHERITABLE) { + data[dataInd].inheritable &= ~(CAP_TO_MASK(cap)); + } + if ((set & CAP_SET_PERMITTED) == CAP_SET_PERMITTED) { + data[dataInd].permitted &= ~(CAP_TO_MASK(cap)); + } + if ((set & CAP_SET_EFFECTIVE) == CAP_SET_EFFECTIVE) { + data[dataInd].effective &= ~(CAP_TO_MASK(cap)); + } +} + } // namespace namespace utils { @@ -156,19 +254,107 @@ bool setSuppGroups(const std::vector& groups) bool dropRoot(uid_t uid, gid_t gid, const std::vector& caps) { - ::capng_clear(CAPNG_SELECT_BOTH); + ::__user_cap_header_struct header; + ::__user_cap_data_struct data[CAP_DATA_ELEMENT_COUNT]; + + // initial setup - equivalent to capng_clear + header.version = _LINUX_CAPABILITY_VERSION_3; + header.pid = ::getpid(); + memset(data, 0, CAP_DATA_ELEMENT_COUNT*sizeof(__user_cap_data_struct)); + // update cap sets - equivalent to capng_update for (const auto cap : caps) { - if (::capng_update(CAPNG_ADD, static_cast(CAPNG_EFFECTIVE | - CAPNG_PERMITTED | - CAPNG_INHERITABLE), cap)) { - LOGE("Failed to set capability: " << ::capng_capability_to_name(cap)); + if (!isValidCap(cap)) { + LOGE("Capability " << cap << " is invalid."); return false; } + + addCap(cap, data, CAP_SET_INHERITABLE | CAP_SET_PERMITTED | CAP_SET_EFFECTIVE); } - if (::capng_change_id(uid, gid, static_cast(CAPNG_CLEAR_BOUNDING))) { - LOGE("Failed to change process user"); + // perform some checks and cap updates + bool updatedSetUid, updatedSetGid; + // check if we are capable of switching our UID + if (hasCap(CAP_SETUID, data, CAP_SET_EFFECTIVE)) { + // we want to keep CAP_SETUID after change + updatedSetUid = false; + } else { + // we don't have CAP_SETUID and switch is needed - add SETUID to effective and permitted set + updatedSetUid = true; + addCap(CAP_SETUID, data, CAP_SET_PERMITTED | CAP_SET_EFFECTIVE); + } + + // do the same routine for CAP_SETGID + if (hasCap(CAP_SETGID, data, CAP_SET_EFFECTIVE)) { + updatedSetGid = false; + } else { + updatedSetGid = true; + addCap(CAP_SETGID, data, CAP_SET_PERMITTED | CAP_SET_EFFECTIVE); + } + + // we need CAP_SETPCAP as well to clear bounding caps + if (!hasCap(CAP_SETPCAP, data, CAP_SET_EFFECTIVE)) { + addCap(CAP_SETPCAP, data, CAP_SET_PERMITTED | CAP_SET_EFFECTIVE); + } + + // now we can work - first, use prctl to tell system we want to keep our caps when changing UID + if (::prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) { + LOGE("prctl failed while trying to enable keepcaps: " << strerror(errno)); + return false; + } + + LOGD("Setting temporary caps to process -" << std::hex << std::setfill('0') + << " inh:" << std::setw(8) << data[1].inheritable << std::setw(8) << data[0].inheritable + << " prm:" << std::setw(8) << data[1].permitted << std::setw(8) << data[0].permitted + << " eff:" << std::setw(8) << data[1].effective << std::setw(8) << data[0].effective); + + // set our modified caps before UID/GID change + if (::capset(&header, data)) { + LOGE("capset failed: " << strerror(errno)); + return false; + } + + // CAP_SETPCAP is available, drop bounding caps + for (int i = 0; i <= CAP_LAST_CAP; ++i) { + if (::prctl(PR_CAPBSET_DROP, i, 0, 0, 0)) { + LOGE("prctl failed while dropping bounding caps: " << strerror(errno)); + return false; + } + } + + // set up GID and UID + if (::setresgid(gid, gid, gid)) { + LOGE("setresgid failed: " << strerror(errno)); + return false; + } + if (::setresuid(uid, uid, uid)) { + LOGE("setresuid failed: " << strerror(errno)); + return false; + } + + // we are after switch now - disable PR_SET_KEEPCAPS + if (::prctl(PR_SET_KEEPCAPS, 0, 0, 0, 0)) { + LOGE("prctl failed while trying to disable keepcaps: " << strerror(errno)); + return false; + } + + // disable rendundant caps + if (updatedSetUid) { + removeCap(CAP_SETUID, data, CAP_SET_PERMITTED | CAP_SET_EFFECTIVE); + } + if (updatedSetGid) { + removeCap(CAP_SETGID, data, CAP_SET_PERMITTED | CAP_SET_EFFECTIVE); + } + removeCap(CAP_SETPCAP, data, CAP_SET_PERMITTED | CAP_SET_EFFECTIVE); + + LOGD("Setting final caps to process -" << std::hex << std::setfill('0') + << " inh:" << std::setw(8) << data[1].inheritable << std::setw(8) << data[0].inheritable + << " prm:" << std::setw(8) << data[1].permitted << std::setw(8) << data[0].permitted + << " eff:" << std::setw(8) << data[1].effective << std::setw(8) << data[0].effective); + + // finally, apply correct caps + if (::capset(&header, data)) { + LOGE("capset failed: " << strerror(errno)); return false; } diff --git a/common/utils/environment.hpp b/common/utils/environment.hpp index 9039239..8c99dd4 100644 --- a/common/utils/environment.hpp +++ b/common/utils/environment.hpp @@ -40,7 +40,7 @@ namespace utils { bool setSuppGroups(const std::vector& groups); /** - * Set effective and permited capabilities on the current process and drop root privileges. + * Set effective and permitted capabilities on the current process and drop root privileges. */ bool dropRoot(uid_t uid, gid_t gid, const std::vector& caps); diff --git a/packaging/vasum.spec b/packaging/vasum.spec index 3b241df..82a859e 100644 --- a/packaging/vasum.spec +++ b/packaging/vasum.spec @@ -20,7 +20,6 @@ Summary: Daemon for managing zones BuildRequires: cmake BuildRequires: boost-devel BuildRequires: libjson-devel >= 0.10 -BuildRequires: libcap-ng-devel BuildRequires: lxc-devel BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(sqlite3) diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index f9ce867..9a1985c 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -30,7 +30,7 @@ ADD_EXECUTABLE(${SERVER_CODENAME} ${project_SRCS} ${common_SRCS}) ## Link libraries ############################################################## FIND_PACKAGE(Boost COMPONENTS program_options system filesystem regex) -PKG_CHECK_MODULES(SERVER_DEPS REQUIRED lxc json gio-2.0 libcap-ng) +PKG_CHECK_MODULES(SERVER_DEPS REQUIRED lxc json gio-2.0) INCLUDE_DIRECTORIES(${COMMON_FOLDER}) INCLUDE_DIRECTORIES(${LIBS_FOLDER}) diff --git a/server/server.cpp b/server/server.cpp index 95f22a0..936db28 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -42,10 +42,10 @@ #include #include #include -#include #include #include #include +#include #ifndef VASUM_USER diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index 2b5a09e..484e810 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -47,7 +47,7 @@ ADD_EXECUTABLE(${SOCKET_TEST_CODENAME} ${socket_test_SRCS} ${common_SRCS} ${clie ## Link libraries ############################################################## FIND_PACKAGE (Boost COMPONENTS unit_test_framework system filesystem regex) -PKG_CHECK_MODULES(UT_SERVER_DEPS REQUIRED lxc json gio-2.0 libcap-ng) +PKG_CHECK_MODULES(UT_SERVER_DEPS REQUIRED lxc json gio-2.0) INCLUDE_DIRECTORIES(${COMMON_FOLDER} ${SERVER_FOLDER} ${UNIT_TESTS_FOLDER} ${CLIENT_FOLDER} ${LIBS_FOLDER} ${SOCKET_TEST_FOLDER}) INCLUDE_DIRECTORIES(SYSTEM ${UT_SERVER_DEPS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) diff --git a/zone-daemon/CMakeLists.txt b/zone-daemon/CMakeLists.txt index 4d48141..4944dfb 100644 --- a/zone-daemon/CMakeLists.txt +++ b/zone-daemon/CMakeLists.txt @@ -31,7 +31,7 @@ ADD_EXECUTABLE(${ZONE_DAEMON_CODENAME} ${project_SRCS} ${common_SRCS}) ## Link libraries ############################################################## FIND_PACKAGE (Boost COMPONENTS program_options system filesystem) -PKG_CHECK_MODULES(ZONE_DAEMON_DEPS REQUIRED gio-2.0 libcap-ng) +PKG_CHECK_MODULES(ZONE_DAEMON_DEPS REQUIRED gio-2.0) INCLUDE_DIRECTORIES(${COMMON_FOLDER}) INCLUDE_DIRECTORIES(${LIBS_FOLDER}) -- 2.7.4 From 9bc344d7c4b3e6b73aeabef1488393c409796490 Mon Sep 17 00:00:00 2001 From: Krzysztof Dynowski Date: Mon, 25 May 2015 13:13:32 +0200 Subject: [PATCH 11/16] Vasum wrapper #8: implement socket related functions, obsolete vasum-daemon [Bug/Feature] socket not opens, rpm install conflict [Cause] N/A [Solution] #8 implement socket creation, etc. [Verification] Build, install on target, check journal Change-Id: I2c6dd5e40a08bda3722167c4e1f06b60bb53e7dc --- packaging/vasum.spec | 1 + wrapper/CMakeLists.txt | 3 +- wrapper/wrapper-compatibility.cpp | 216 +++++++++++++++++++++++++++++++++++--- wrapper/wrapper.cpp | 5 +- 4 files changed, 206 insertions(+), 19 deletions(-) diff --git a/packaging/vasum.spec b/packaging/vasum.spec index 82a859e..8f10a1c 100644 --- a/packaging/vasum.spec +++ b/packaging/vasum.spec @@ -26,6 +26,7 @@ BuildRequires: pkgconfig(sqlite3) Requires(post): libcap-tools Requires: iproute2 Requires: libjson >= 0.10 +Obsoletes: vasum-daemon < 1:0 %description This package provides a daemon used to manage zones - start, stop and switch diff --git a/wrapper/CMakeLists.txt b/wrapper/CMakeLists.txt index a75bfa9..a8aa173 100644 --- a/wrapper/CMakeLists.txt +++ b/wrapper/CMakeLists.txt @@ -42,6 +42,7 @@ SET(PC_FILE "${PROJECT_NAME}.pc") ## libraries, produce more optimized code, provide near-perfect API export ## and prevent symbol clashes ADD_DEFINITIONS(-fvisibility=hidden) +ADD_DEFINITIONS(-D__STDC_FORMAT_MACROS) ADD_LIBRARY(${PROJECT_NAME} SHARED ${wrapper_SRCS} ${common_SRCS}) SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES @@ -51,7 +52,7 @@ SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES ## Link libraries ############################################################## FIND_PACKAGE(Boost COMPONENTS system filesystem) -PKG_CHECK_MODULES(LIB_DEPS REQUIRED gio-2.0 libcap-ng) +PKG_CHECK_MODULES(LIB_DEPS REQUIRED gio-2.0) INCLUDE_DIRECTORIES(SYSTEM ${LIB_DEPS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) INCLUDE_DIRECTORIES(${COMMON_FOLDER}) INCLUDE_DIRECTORIES(${LIBS_FOLDER}) diff --git a/wrapper/wrapper-compatibility.cpp b/wrapper/wrapper-compatibility.cpp index 303fcfe..942c5f6 100644 --- a/wrapper/wrapper-compatibility.cpp +++ b/wrapper/wrapper-compatibility.cpp @@ -32,16 +32,18 @@ #include #include #include +#include +#include +#include +#include //PRIx64 #include #include #include #include #include -#include -#include -#include #include #include +#include #include "logger/logger.hpp" #include "logger/logger-scope.hpp" @@ -62,43 +64,227 @@ API pid_t get_domain_pid(const char * /*name*/, const char * /*target*/) { } // sock_close_socket -API int sock_close_socket(int /*fd*/) { +API int sock_close_socket(int fd) { LOGS(""); + struct sockaddr_un addr; + socklen_t addrlen = sizeof(addr); + + if (!getsockname(fd, (struct sockaddr *)&addr, &addrlen) && addr.sun_path[0]) { + unlink(addr.sun_path); + } + + close(fd); + return 0; } // sock_connect -API int sock_connect(const char * /*path*/) { +API int sock_connect(const char *path) { LOGS(""); - return -1; + size_t len; + int fd, idx = 0; + struct sockaddr_un addr; + + fd = socket(PF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + return -1; + } + + memset(&addr, 0, sizeof(addr)); + + addr.sun_family = AF_UNIX; + + /* Is it abstract address */ + if (path[0] == '\0') { + idx++; + } + LOGD("socket path=" << &path[idx]); + len = strlen(&path[idx]) + idx; + if (len >= sizeof(addr.sun_path)) { + close(fd); + errno = ENAMETOOLONG; + return -1; + } + + strncpy(&addr.sun_path[idx], &path[idx], strlen(&path[idx])); + if (connect + (fd, (struct sockaddr *)&addr, + offsetof(struct sockaddr_un, sun_path) + len)) { + close(fd); + return -1; + } + + return fd; } + // sock_create_socket -API int sock_create_socket(const char * /*path*/, int /*type*/, int /*flags*/) { +API int sock_create_socket(const char *path, int type, int flags) { LOGS(""); - return -1; + size_t len; + int fd, idx = 0; + struct sockaddr_un addr; + + if (!path) + return -1; + + if (flags & O_TRUNC) + unlink(path); + + fd = socket(PF_UNIX, type, 0); + if (fd < 0) { + return -1; + } + + memset(&addr, 0, sizeof(addr)); + + addr.sun_family = AF_UNIX; + + /* Is it abstract address */ + if (path[0] == '\0') { + idx++; + } + LOGD("socket path=" << &path[idx]); + len = strlen(&path[idx]) + idx; + if (len >= sizeof(addr.sun_path)) { + close(fd); + errno = ENAMETOOLONG; + return -1; + } + + strncpy(&addr.sun_path[idx], &path[idx], strlen(&path[idx])); + + if (bind (fd, (struct sockaddr *)&addr, offsetof(struct sockaddr_un, sun_path) + len)) { + close(fd); + return -1; + } + + if (type == SOCK_STREAM && listen(fd, 100)) { + close(fd); + return -1; + } + + return fd; } + +// "Fowler–Noll–Vo hash function" implementation (taken from old API source) +#define FNV1A_64_INIT ((uint64_t)0xcbf29ce484222325ULL) +static uint64_t hash_fnv_64a(void *buf, size_t len, uint64_t hval) +{ + unsigned char *bp; + + for (bp = (unsigned char *)buf; bp < (unsigned char *)buf + len; bp++) { + hval ^= (uint64_t) * bp; + hval += (hval << 1) + (hval << 4) + (hval << 5) + + (hval << 7) + (hval << 8) + (hval << 40); + } + + return hval; +} + // sock_monitor_address -API int sock_monitor_address(char * /*buffer*/, int /*len*/, const char * /*lxcpath*/) { +API int sock_monitor_address(char *buffer, int len, const char *lxcpath) { LOGS(""); + int ret; + uint64_t hash; + char *sockname; + char path[PATH_MAX]; + + memset(buffer, 0, len); + sockname = &buffer[1]; + + ret = snprintf(path, sizeof(path), "lxc/%s/monitor-sock", lxcpath); + if (ret < 0) { + errno = ENAMETOOLONG; + return -1; + } + + hash = hash_fnv_64a(path, ret, FNV1A_64_INIT); + ret = snprintf(sockname, len, "lxc/%016" PRIx64 "/%s", hash, lxcpath); + if (ret < 0) { + errno = ENAMETOOLONG; + return -1; + } + return 0; } // sock_recv_fd (intern) -API int sock_recv_fd(int /*fd*/, int * /*recvfd*/, void * /*data*/, size_t /*size*/) { +API int sock_recv_fd(int fd, int *recvfd, void *data, size_t size) { LOGS(""); - return 0; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsg; + char cmsgbuf[CMSG_SPACE(sizeof(int))]; + char buf[1]; + int ret, *val; + + memset(&msg, 0, sizeof(msg)); + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = cmsgbuf; + msg.msg_controllen = sizeof(cmsgbuf); + + iov.iov_base = data ? data : buf; + iov.iov_len = data ? size : sizeof(buf); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + ret = recvmsg(fd, &msg, 0); + if (ret <= 0) + goto out; + + cmsg = CMSG_FIRSTHDR(&msg); + + *recvfd = -1; + + if (cmsg && cmsg->cmsg_len == CMSG_LEN(sizeof(int)) && + cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { + val = (int *)CMSG_DATA(cmsg); + *recvfd = *val; + } + out: + return ret; + } // sock_send_fd -API int sock_send_fd(int /*fd*/, int /*sendfd*/, void * /*data*/, size_t /*size*/) { +API int sock_send_fd(int fd, int sendfd, void *data, size_t size) { LOGS(""); - return 0; + struct msghdr msg; + struct iovec iov; + struct cmsghdr *cmsg; + char cmsgbuf[CMSG_SPACE(sizeof(int))]; + char buf[1]; + int *val; + + memset(&msg, 0, sizeof(msg)); + msg.msg_control = cmsgbuf; + msg.msg_controllen = sizeof(cmsgbuf); + + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + val = (int *)(CMSG_DATA(cmsg)); + *val = sendfd; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + + iov.iov_base = data ? data : buf; + iov.iov_len = data ? size : sizeof(buf); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + + return sendmsg(fd, &msg, MSG_NOSIGNAL); } // vasum_log API void vasum_log(int type, const char *tag, const char *fmt, ...) { va_list arg_ptr; - char buf[100]; + char buf[255]; + LOGS("type=" << type << " tag=" << tag); va_start(arg_ptr, fmt); vsnprintf(buf, sizeof(buf), fmt, arg_ptr); va_end(arg_ptr); - LOGS("type=" << type << " tag=" << tag << " msg=" << buf); + buf[sizeof(buf)-1]=0; + LOGD("msg=" << buf); } #define MAX_ERROR_MSG 0x1000 diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 4fc0c60..5623263 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -668,6 +668,7 @@ API int vsm_is_host_zone(vsm_zone_h zone) if (zone == NULL) return -VSM_ERROR_INVALID; + LOGI("zone->parent == zone is " << (zone->parent == zone ? 1 : 0)); return zone->parent == zone ? 1 : 0; } API vsm_zone_h vsm_join_zone(vsm_zone_h /*zone*/) @@ -683,9 +684,7 @@ API int vsm_canonicalize_path(const char *input_path, char **output_path) return len; } -// Note: incomaptible API, support newer -// API(v0.34) const char *vsm_error_string(struct vsm_context *ctx) -// API(v0.3.1) const char *vsm_error_string(vsm_error_e error) +// Note: support the newer API (incomaptible with older) API const char *vsm_error_string(vsm_error_e error) { LOGS(""); -- 2.7.4 From 8312cde30ab9a4aa689d34fce39f573cdeca8712 Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Wed, 27 May 2015 15:30:33 +0200 Subject: [PATCH 12/16] Fix configuration script permissions [Feature] N/A [Cause] N/A [Solution] LXC templates have x permission [Verification] Build, run all tests Change-Id: I6a2486a588f8a28dfe84f187a4889f0f9500e2a6 --- server/configs/CMakeLists.txt | 9 ++++++--- tests/unit_tests/configs/CMakeLists.txt | 7 +++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/server/configs/CMakeLists.txt b/server/configs/CMakeLists.txt index 0e7be41..278a9fc 100644 --- a/server/configs/CMakeLists.txt +++ b/server/configs/CMakeLists.txt @@ -19,8 +19,8 @@ MESSAGE(STATUS "Installing configs to " ${VSM_CONFIG_INSTALL_DIR}) -FILE(GLOB template_CONF templates/*.conf - templates/*.sh) +FILE(GLOB zone_templates_CONF templates/*.conf) +FILE(GLOB lxc_templates_CONF templates/*.sh) ## Generate #################################################################### CONFIGURE_FILE(systemd/vasum.service.in @@ -43,7 +43,10 @@ INSTALL(FILES ${CMAKE_BINARY_DIR}/dbus-1/system.d/org.tizen.vasum.host.con INSTALL(DIRECTORY DESTINATION ${VSM_CONFIG_INSTALL_DIR}/zones) #TODO temporary solution -INSTALL(PROGRAMS ${template_CONF} +INSTALL(FILES ${zone_templates_CONF} + DESTINATION ${VSM_CONFIG_INSTALL_DIR}/templates) + +INSTALL(PROGRAMS ${lxc_templates_CONF} DESTINATION ${VSM_CONFIG_INSTALL_DIR}/templates) INSTALL(FILES diff --git a/tests/unit_tests/configs/CMakeLists.txt b/tests/unit_tests/configs/CMakeLists.txt index 04aabda..a18914e 100644 --- a/tests/unit_tests/configs/CMakeLists.txt +++ b/tests/unit_tests/configs/CMakeLists.txt @@ -20,8 +20,8 @@ MESSAGE(STATUS "Installing configs for the Unit Tests to " ${VSM_TEST_CONFIG_INSTALL_DIR}) FILE(GLOB ut_zone_CONF *.conf) -FILE(GLOB ut_zone_templates_CONF templates/*.conf - templates/*.sh) +FILE(GLOB ut_zone_templates_CONF templates/*.conf) +FILE(GLOB ut_lxc_templates_CONF templates/*.sh) ## Generate #################################################################### CONFIGURE_FILE(test-daemon.conf.in @@ -44,6 +44,9 @@ INSTALL(FILES ${ut_zone_templates_CONF} ${ut_zone_templates_CONF_GEN} DESTINATION ${VSM_TEST_TEMPLATES_INSTALL_DIR}) +INSTALL(PROGRAMS ${ut_lxc_templates_CONF} + DESTINATION ${VSM_TEST_TEMPLATES_INSTALL_DIR}) + INSTALL(FILES dbus/ut-dbus.conf dbus/ut-dbus-system.conf DESTINATION ${VSM_TEST_CONFIG_INSTALL_DIR}/dbus) -- 2.7.4 From bdad02ae0c2da1eeeabbd3f96185a09aa964d8ce Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Wed, 27 May 2015 18:48:47 +0200 Subject: [PATCH 13/16] Small documentation for github [Feature] N/A [Cause] N/A [Solution] N/A [Verification] N/A Change-Id: Ia7beba020ae92619e3639ee70af65794d2b662a1 --- README | 18 ------------------ README.md | 27 +++++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 18 deletions(-) delete mode 100644 README create mode 100644 README.md diff --git a/README b/README deleted file mode 100644 index d194922..0000000 --- a/README +++ /dev/null @@ -1,18 +0,0 @@ -# Documentation - -Generate documentation by executing command generate_documentation.sh -from doc directory. Documentation will be generated in doc/html directory. -There is also GUI tool named doxywizard. - - cd ./doc - ./generate_documentation.sh - - -# Code formatting - -We use astyle for code formatting. -Get the latest version from http://sourceforge.net/projects/astyle/files/astyle/ -(at least v2.04). You can find the options file in the root of the project. -For example to format all .cpp and .hpp files run in the project directory: - - astyle --options=./astylerc --recursive ./*.cpp ./*.hpp diff --git a/README.md b/README.md new file mode 100644 index 0000000..9ccd43c --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# Vasum +[Vasum](https://wiki.tizen.org/wiki/Security:Vasum) is a Linux daemon and a set of utilities used for managing para-virtualization. It uses Linux Containers to create separate, graphical environments called *zones*. One can concurrently run several zones on one physical device. Vasum exports a rich C/Dbus API that the application frameworks can use to interact with zones. + +For now Vasum uses [LXC](https://linuxcontainers.org/lxc/introduction/) for Linux Containers management. The project is mostly written in modern C++, is [well tested](https://wiki.tizen.org/wiki/Weekly_test_results_for_Tizen_3.X_security_framework). + +Vasum's development takes place on [review.tizen.org/gerrit/](http://review.tizen.org/gerrit/) (registration on [tizen.org](http://tizen.org) is required). + +## Installation and usage +The installation process and simple verification is described [here](https://wiki.tizen.org/wiki/Security:Vasum:Usage). + +## Client interface +Vasum daemon can be accessed via C API or Dbus. You can find the API documentation [here](https://wiki.tizen.org/wiki/Security:Vasum:API). Be aware that the API will most likely change in the near future. + +## Documentation +More comprehensive documentation is kept [here](https://wiki.tizen.org/wiki/Security:Vasum). You can generate the code documentation by executing *generate_documentation.sh* script from *doc* directory. Documentation will be generated in doc/html directory. + + cd ./doc + ./generate_documentation.sh + + +## Code formatting +We use [astyle](http://astyle.sourceforge.net/) for code formatting (Use the latest version) +You can find the options file in the root of the project. + +For example to format all .cpp and .hpp files run in the project directory: + + astyle --options=./astylerc --recursive ./*.cpp ./*.hpp \ No newline at end of file -- 2.7.4 From 7c6e79b69e1a39c1c033ffb4891ec3ca21e4f309 Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Tue, 2 Jun 2015 14:16:43 +0200 Subject: [PATCH 14/16] Removed Glib connected functions from API [Feature] N/A [Cause] N/A [Solution] N/A [Verification] Build, run all tests Change-Id: I3fe5e789535fcb53ee5d223172cb63bd44fb962c --- cli/command-line-interface.cpp | 6 ------ client/vasum-client-impl.cpp | 12 ------------ client/vasum-client-impl.hpp | 9 --------- client/vasum-client.cpp | 11 ----------- client/vasum-client.h | 25 ------------------------- wrapper/wrapper.cpp | 5 ----- 6 files changed, 68 deletions(-) diff --git a/cli/command-line-interface.cpp b/cli/command-line-interface.cpp index 2ae3778..2393ce1 100644 --- a/cli/command-line-interface.cpp +++ b/cli/command-line-interface.cpp @@ -58,11 +58,6 @@ void one_shot(const function& fun) VsmStatus status; VsmClient client; - status = vsm_start_glib_loop(); - if (VSMCLIENT_SUCCESS != status) { - throw runtime_error("Can't start glib loop"); - } - client = vsm_client_create(); if (NULL == client) { msg = "Can't create client"; @@ -83,7 +78,6 @@ void one_shot(const function& fun) finish: vsm_client_free(client); - vsm_stop_glib_loop(); if (! msg.empty()) { throw runtime_error(msg); } diff --git a/client/vasum-client-impl.cpp b/client/vasum-client-impl.cpp index 38e4c5a..f87e9a0 100644 --- a/client/vasum-client-impl.cpp +++ b/client/vasum-client-impl.cpp @@ -127,18 +127,6 @@ bool readFirstLineOfFile(const string& path, string& ret) } //namespace -VsmStatus Client::vsm_start_glib_loop() noexcept -{ - // TPDP: Remove vsm_start_glib_loop from API - return VSMCLIENT_SUCCESS; -} - -VsmStatus Client::vsm_stop_glib_loop() noexcept -{ - // TPDP: Remove vsm_stop_glib_loop from API - return VSMCLIENT_SUCCESS; -} - Client::Status::Status() : mVsmStatus(VSMCLIENT_SUCCESS), mMsg() { diff --git a/client/vasum-client-impl.hpp b/client/vasum-client-impl.hpp index 86f7a5e..5a1d2fd 100644 --- a/client/vasum-client-impl.hpp +++ b/client/vasum-client-impl.hpp @@ -336,15 +336,6 @@ public: */ VsmStatus vsm_del_notification_callback(VsmSubscriptionId subscriptionId) noexcept; - /** - * @see ::vsm_start_glib_loop - */ - static VsmStatus vsm_start_glib_loop() noexcept; - - /** - * @see ::vsm_stop_glib_loop - */ - static VsmStatus vsm_stop_glib_loop() noexcept; private: typedef vasum::client::HostIPCConnection HostConnection; struct Status { diff --git a/client/vasum-client.cpp b/client/vasum-client.cpp index b1028e2..1d5664c 100644 --- a/client/vasum-client.cpp +++ b/client/vasum-client.cpp @@ -45,17 +45,6 @@ Client& getClient(VsmClient client) } // namespace -/* external */ -API VsmStatus vsm_start_glib_loop() -{ - return Client::vsm_start_glib_loop(); -} - -API VsmStatus vsm_stop_glib_loop() -{ - return Client::vsm_stop_glib_loop(); -} - API VsmClient vsm_client_create() { Client* clientPtr = new(nothrow) Client(); diff --git a/client/vasum-client.h b/client/vasum-client.h index 6c68fe2..7a98fa7 100644 --- a/client/vasum-client.h +++ b/client/vasum-client.h @@ -34,12 +34,6 @@ int main(int argc, char** argv) VsmArrayString values = NULL; int ret = 0; - status = vsm_start_glib_loop(); // start glib loop (if not started any yet) - if (VSMCLIENT_SUCCESS != status) { - // error! - return 1; - } - client = vsm_client_create(); // create client handle if (NULL == client) { // error! @@ -69,7 +63,6 @@ int main(int argc, char** argv) finish: vsm_array_string_free(values); // free memory vsm_client_free(client); // destroy client handle - vsm_stop_glib_loop(); // stop the glib loop (use only with vsm_start_glib_loop) return ret; } @endcode @@ -188,24 +181,6 @@ typedef enum { } VsmFileType; #ifndef __VASUM_WRAPPER_SOURCE__ -/** - * Start glib loop. - * - * Do not call this function if an application creates a glib loop itself. - * Otherwise, call it before any other function from this library. - * - * @return status of this function call - */ -VsmStatus vsm_start_glib_loop(); - -/** - * Stop glib loop. - * - * Call only if vsm_start_glib_loop() was called. - * - * @return status of this function call - */ -VsmStatus vsm_stop_glib_loop(); /** * Create a new vasum-server's client. diff --git a/wrapper/wrapper.cpp b/wrapper/wrapper.cpp index 5623263..8b890cf 100644 --- a/wrapper/wrapper.cpp +++ b/wrapper/wrapper.cpp @@ -54,7 +54,6 @@ struct WrappedContext static struct { int done; - int glib_stop; } wrap; @@ -90,8 +89,6 @@ void wrapper_load(void) void wrapper_unload(void) { - if (wrap.glib_stop) Client::vsm_stop_glib_loop(); - wrap.glib_stop = 0; LOGI("wrapper_unload"); } @@ -153,8 +150,6 @@ static int wrap_error(VsmStatus st, const Client *c) static void init_context_wrap(WrappedContext *w) { - Client::vsm_start_glib_loop(); - wrap.glib_stop = 1; w->client = new Client(); VsmStatus st = w->client->createSystem(); wrap_error(st, w->client); -- 2.7.4 From 1c1c682dacd05c0824d4fcf7d18b95eeff20cfc4 Mon Sep 17 00:00:00 2001 From: Jan Olszak Date: Mon, 1 Jun 2015 16:11:54 +0200 Subject: [PATCH 15/16] File descriptor passing via IPC [Feature] FD passing via Unix socket [Cause] N/A [Solution] N/A [Verification] Build, run all tests Change-Id: I1683a7e99a104d5dbdd5c0c56913753c9bdd3cf2 --- libs/config/fdstore.cpp | 178 +++++++++++++++++++++++++++++++---- libs/config/fdstore.hpp | 12 ++- libs/config/fields.hpp | 2 + libs/config/from-fdstore-visitor.hpp | 6 ++ libs/config/to-fdstore-visitor.hpp | 6 ++ libs/config/types.hpp | 44 +++++++++ libs/ipc/internals/socket.cpp | 10 +- libs/ipc/internals/socket.hpp | 4 +- tests/unit_tests/ipc/ut-ipc.cpp | 60 +++++++++++- 9 files changed, 291 insertions(+), 31 deletions(-) create mode 100644 libs/config/types.hpp diff --git a/libs/config/fdstore.cpp b/libs/config/fdstore.cpp index c0b7d08..cc0b903 100644 --- a/libs/config/fdstore.cpp +++ b/libs/config/fdstore.cpp @@ -32,6 +32,7 @@ #include #include #include +#include namespace config { @@ -102,24 +103,28 @@ FDStore::~FDStore() void FDStore::write(const void* bufferPtr, const size_t size, const unsigned int timeoutMS) { - std::chrono::high_resolution_clock::time_point deadline = std::chrono::high_resolution_clock::now() + - std::chrono::milliseconds(timeoutMS); + std::chrono::high_resolution_clock::time_point deadline = + std::chrono::high_resolution_clock::now() + + std::chrono::milliseconds(timeoutMS); size_t nTotal = 0; for (;;) { - int n = ::write(mFD, - reinterpret_cast(bufferPtr) + nTotal, - size - nTotal); - if (n >= 0) { + ssize_t n = ::write(mFD, + reinterpret_cast(bufferPtr) + nTotal, + size - nTotal); + if (n < 0) { + // Handle errors + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { + // Neglected errors + } else { + throw ConfigException("Error during writing: " + getSystemErrorMessage()); + } + } else { nTotal += n; if (nTotal == size) { - // All data is written, break loop + // All data is read, break loop break; } - } else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { - // Neglected errors - } else { - throw ConfigException("Error during writing: " + getSystemErrorMessage()); } waitForEvent(mFD, POLLOUT, deadline); @@ -128,15 +133,23 @@ void FDStore::write(const void* bufferPtr, const size_t size, const unsigned int void FDStore::read(void* bufferPtr, const size_t size, const unsigned int timeoutMS) { - std::chrono::high_resolution_clock::time_point deadline = std::chrono::high_resolution_clock::now() + - std::chrono::milliseconds(timeoutMS); + std::chrono::high_resolution_clock::time_point deadline = + std::chrono::high_resolution_clock::now() + + std::chrono::milliseconds(timeoutMS); size_t nTotal = 0; for (;;) { - int n = ::read(mFD, - reinterpret_cast(bufferPtr) + nTotal, - size - nTotal); - if (n >= 0) { + ssize_t n = ::read(mFD, + reinterpret_cast(bufferPtr) + nTotal, + size - nTotal); + if (n < 0) { + // Handle errors + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { + // Neglected errors + } else { + throw ConfigException("Error during reading: " + getSystemErrorMessage()); + } + } else { nTotal += n; if (nTotal == size) { // All data is read, break loop @@ -145,13 +158,138 @@ void FDStore::read(void* bufferPtr, const size_t size, const unsigned int timeou if (n == 0) { throw ConfigException("Peer disconnected"); } - } else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { - // Neglected errors + } + + waitForEvent(mFD, POLLIN, deadline); + } +} + + +void FDStore::sendFD(int fd, const unsigned int timeoutMS) +{ + std::chrono::high_resolution_clock::time_point deadline = + std::chrono::high_resolution_clock::now() + + std::chrono::milliseconds(timeoutMS); + + // Space for the file descriptor + union { + struct cmsghdr cmh; + char control[CMSG_SPACE(sizeof(int))]; + } controlUnion; + + // Ensure at least 1 byte is transmited via the socket + struct iovec iov; + char buf = '!'; + iov.iov_base = &buf; + iov.iov_len = sizeof(char); + + // Fill the message to send: + // The socket has to be connected, so we don't need to specify the name + struct msghdr msgh; + ::memset(&msgh, 0, sizeof(msgh)); + + // Only iovec to transmit one element + msgh.msg_iov = &iov; + msgh.msg_iovlen = 1; + + // Ancillary data buffer + msgh.msg_control = controlUnion.control; + msgh.msg_controllen = sizeof(controlUnion.control); + + // Describe the data that we want to send + struct cmsghdr *cmhp; + cmhp = CMSG_FIRSTHDR(&msgh); + cmhp->cmsg_len = CMSG_LEN(sizeof(int)); + cmhp->cmsg_level = SOL_SOCKET; + cmhp->cmsg_type = SCM_RIGHTS; + *(reinterpret_cast(CMSG_DATA(cmhp))) = fd; + + // Send + for(;;) { + ssize_t ret = ::sendmsg(mFD, &msgh, MSG_NOSIGNAL); + if (ret < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { + // Neglected errors, retry + } else { + throw ConfigException("Error during sendmsg: " + getSystemErrorMessage()); + } + } else if (ret == 0) { + // Retry the sending } else { - throw ConfigException("Error during reading: " + getSystemErrorMessage()); + // We send only 1 byte of data. No need to repeat + break; + } + + waitForEvent(mFD, POLLOUT, deadline); + } +} + + +int FDStore::receiveFD(const unsigned int timeoutMS) +{ + std::chrono::high_resolution_clock::time_point deadline = + std::chrono::high_resolution_clock::now() + + std::chrono::milliseconds(timeoutMS); + + // Space for the file descriptor + union { + struct cmsghdr cmh; + char control[CMSG_SPACE(sizeof(int))]; + } controlUnion; + + // Describe the data that we want to recive + controlUnion.cmh.cmsg_len = CMSG_LEN(sizeof(int)); + controlUnion.cmh.cmsg_level = SOL_SOCKET; + controlUnion.cmh.cmsg_type = SCM_RIGHTS; + + // Setup the input buffer + // Ensure at least 1 byte is transmited via the socket + char buf; + struct iovec iov; + iov.iov_base = &buf; + iov.iov_len = sizeof(char); + + // Set the ancillary data buffer + // The socket has to be connected, so we don't need to specify the name + struct msghdr msgh; + ::memset(&msgh, 0, sizeof(msgh)); + + msgh.msg_iov = &iov; + msgh.msg_iovlen = 1; + + msgh.msg_control = controlUnion.control; + msgh.msg_controllen = sizeof(controlUnion.control); + + // Receive + for(;;) { + ssize_t ret = ::recvmsg(mFD, &msgh, MSG_WAITALL); + if (ret < 0) { + if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) { + // Neglected errors, retry + } else { + throw ConfigException("Error during recvmsg: " + getSystemErrorMessage()); + } + } else if (ret == 0) { + throw ConfigException("Peer disconnected"); + } else { + // We receive only 1 byte of data. No need to repeat + break; } waitForEvent(mFD, POLLIN, deadline); } + + struct cmsghdr *cmhp; + cmhp = CMSG_FIRSTHDR(&msgh); + if (cmhp == NULL || cmhp->cmsg_len != CMSG_LEN(sizeof(int))) { + throw ConfigException("Bad cmsg length"); + } else if (cmhp->cmsg_level != SOL_SOCKET) { + throw ConfigException("cmsg_level != SOL_SOCKET"); + } else if (cmhp->cmsg_type != SCM_RIGHTS) { + throw ConfigException("cmsg_type != SCM_RIGHTS"); + } + + return *(reinterpret_cast(CMSG_DATA(cmhp))); } + } // namespace config diff --git a/libs/config/fdstore.hpp b/libs/config/fdstore.hpp index d76fc5f..d6e30aa 100644 --- a/libs/config/fdstore.hpp +++ b/libs/config/fdstore.hpp @@ -27,6 +27,10 @@ #include +namespace { +const unsigned int maxTimeout = 5000; +} // namespace + namespace config { class FDStore { @@ -50,7 +54,7 @@ public: * @param size size of the buffer * @param timeoutMS timeout in milliseconds */ - void write(const void* bufferPtr, const size_t size, const unsigned int timeoutMS = 5000); + void write(const void* bufferPtr, const size_t size, const unsigned int timeoutMS = maxTimeout); /** * Reads a value of the given type. @@ -59,7 +63,11 @@ public: * @param size size of the buffer * @param timeoutMS timeout in milliseconds */ - void read(void* bufferPtr, const size_t size, const unsigned int timeoutMS = 5000); + void read(void* bufferPtr, const size_t size, const unsigned int timeoutMS = maxTimeout); + + void sendFD(int fd, const unsigned int timeoutMS = maxTimeout); + + int receiveFD(const unsigned int timeoutMS = maxTimeout); private: int mFD; diff --git a/libs/config/fields.hpp b/libs/config/fields.hpp index cba5a67..8169cb4 100644 --- a/libs/config/fields.hpp +++ b/libs/config/fields.hpp @@ -28,6 +28,8 @@ #include #include +#include "config/types.hpp" + #if BOOST_PP_VARIADICS != 1 #error variadic macros not supported #endif diff --git a/libs/config/from-fdstore-visitor.hpp b/libs/config/from-fdstore-visitor.hpp index 9b9df42..3863f7f 100644 --- a/libs/config/from-fdstore-visitor.hpp +++ b/libs/config/from-fdstore-visitor.hpp @@ -27,6 +27,7 @@ #include "config/is-visitable.hpp" #include "config/fdstore.hpp" +#include "config/types.hpp" #include @@ -60,6 +61,11 @@ private: mStore.read(&value.front(), size); } + void readInternal(config::FileDescriptor& fd) + { + fd = mStore.receiveFD(); + } + template::value, int>::type = 0> void readInternal(T& value) { diff --git a/libs/config/to-fdstore-visitor.hpp b/libs/config/to-fdstore-visitor.hpp index 50756c1..1eedddb 100644 --- a/libs/config/to-fdstore-visitor.hpp +++ b/libs/config/to-fdstore-visitor.hpp @@ -27,6 +27,7 @@ #include "config/is-visitable.hpp" #include "config/fdstore.hpp" +#include "config/types.hpp" #include @@ -59,6 +60,11 @@ private: mStore.write(value.c_str(), value.size()); } + void writeInternal(const config::FileDescriptor& fd) + { + mStore.sendFD(fd.value); + } + template::value, int>::type = 0> void writeInternal(const T& value) { diff --git a/libs/config/types.hpp b/libs/config/types.hpp new file mode 100644 index 0000000..3355f8f --- /dev/null +++ b/libs/config/types.hpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved + * + * Contact: Jan Olszak + * + * 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 Types declarations + */ + +#ifndef COMMON_CONFIG_TYPES_HPP +#define COMMON_CONFIG_TYPES_HPP + +namespace config { + +/** + * Whenever possible, this type will be serialized using Linux file descriptor passing. + */ +struct FileDescriptor { + int value; + FileDescriptor(int fd = -1): value(fd) {} + FileDescriptor& operator=(const int fd) { + value = fd; + return *this; + } +}; + +}// config + +#endif //COMMON_CONFIG_TYPES_HPP \ No newline at end of file diff --git a/libs/ipc/internals/socket.cpp b/libs/ipc/internals/socket.cpp index 0654a4e..690bd43 100644 --- a/libs/ipc/internals/socket.cpp +++ b/libs/ipc/internals/socket.cpp @@ -56,7 +56,7 @@ void setFdOptions(int fd) } } -} +} // namespace Socket::Socket(int socketFD) : mFD(socketFD) @@ -112,7 +112,7 @@ void Socket::read(void* bufferPtr, const size_t size) const utils::read(mFD, bufferPtr, size); } -int Socket::getSystemdSocket(const std::string& path) +int Socket::getSystemdSocketInternal(const std::string& path) { int n = ::sd_listen_fds(-1 /*Block further calls to sd_listen_fds*/); if (n < 0) { @@ -132,7 +132,7 @@ int Socket::getSystemdSocket(const std::string& path) return -1; } -int Socket::createZoneSocket(const std::string& path) +int Socket::createSocketInternal(const std::string& path) { // Isn't the path too long? if (path.size() >= sizeof(sockaddr_un::sun_path)) { @@ -178,8 +178,8 @@ int Socket::createZoneSocket(const std::string& path) Socket Socket::createSocket(const std::string& path) { // Initialize a socket - int fd = getSystemdSocket(path); - fd = fd != -1 ? fd : createZoneSocket(path); + int fd = getSystemdSocketInternal(path); + fd = fd != -1 ? fd : createSocketInternal(path); return Socket(fd); } diff --git a/libs/ipc/internals/socket.hpp b/libs/ipc/internals/socket.hpp index 65f574d..c8f0a2d 100644 --- a/libs/ipc/internals/socket.hpp +++ b/libs/ipc/internals/socket.hpp @@ -108,8 +108,8 @@ private: int mFD; mutable std::recursive_mutex mCommunicationMutex; - static int createZoneSocket(const std::string& path); - static int getSystemdSocket(const std::string& path); + static int createSocketInternal(const std::string& path); + static int getSystemdSocketInternal(const std::string& path); }; } // namespace ipc diff --git a/tests/unit_tests/ipc/ut-ipc.cpp b/tests/unit_tests/ipc/ut-ipc.cpp index 958f1f2..ab920fe 100644 --- a/tests/unit_tests/ipc/ut-ipc.cpp +++ b/tests/unit_tests/ipc/ut-ipc.cpp @@ -44,17 +44,24 @@ #include "config/fields.hpp" #include "logger/logger.hpp" +#include +#include #include #include #include #include #include #include +#include +#include +#include + using namespace ipc; using namespace epoll; using namespace utils; using namespace std::placeholders; +namespace fs = boost::filesystem; // Timeout for sending one message const int TIMEOUT = 1000 /*ms*/; @@ -67,6 +74,7 @@ const int LONG_OPERATION_TIME = 1000 + TIMEOUT; const std::string TEST_DIR = "/tmp/ut-ipc"; const std::string SOCKET_PATH = TEST_DIR + "/test.socket"; +const std::string TEST_FILE = TEST_DIR + "/file.txt"; struct FixtureBase { ScopedDir mTestPathGuard; @@ -80,14 +88,18 @@ struct FixtureBase { struct ThreadedFixture : FixtureBase { ThreadDispatcher dispatcher; - EventPoll& getPoll() { return dispatcher.getPoll(); } + EventPoll& getPoll() { + return dispatcher.getPoll(); + } }; struct GlibFixture : FixtureBase { ScopedGlibLoop glibLoop; GlibDispatcher dispatcher; - EventPoll& getPoll() { return dispatcher.getPoll(); } + EventPoll& getPoll() { + return dispatcher.getPoll(); + } }; struct SendData { @@ -110,6 +122,16 @@ struct RecvData { ) }; +struct FDData { + config::FileDescriptor fd; + FDData(int fd = -1): fd(fd) {} + + CONFIG_REGISTER + ( + fd + ) +}; + struct LongSendData { LongSendData(int i, int waitTime): mSendData(i), mWaitTime(waitTime), intVal(i) {} @@ -710,6 +732,40 @@ MULTI_FIXTURE_TEST_CASE(MixOperations, F, ThreadedFixture, GlibFixture) BOOST_CHECK(l.wait(TIMEOUT)); } +MULTI_FIXTURE_TEST_CASE(FDSendReceive, F, ThreadedFixture, GlibFixture) +{ + const char DATA[] = "Content of the file"; + { + // Fill the file + fs::remove(TEST_FILE); + std::ofstream file(TEST_FILE); + file << DATA; + file.close(); + } + + auto methodHandler = [&](const PeerID, std::shared_ptr&, MethodResult::Pointer methodResult) { + int fd = ::open(TEST_FILE.c_str(), O_RDONLY); + auto returnData = std::make_shared(fd); + methodResult->set(returnData); + }; + + Service s(F::getPoll(), SOCKET_PATH); + s.setMethodHandler(1, methodHandler); + + Client c(F::getPoll(), SOCKET_PATH); + connect(s, c); + + std::shared_ptr fdData; + std::shared_ptr sentData(new EmptyData()); + fdData = c.callSync(1, sentData, TIMEOUT); + + // Use the file descriptor + char buffer[sizeof(DATA)]; + BOOST_REQUIRE(::read(fdData->fd.value, buffer, sizeof(buffer))>0); + BOOST_REQUIRE(strncmp(DATA, buffer, strlen(DATA))==0); + ::close(fdData->fd.value); +} + // MULTI_FIXTURE_TEST_CASE(ConnectionLimit, F, ThreadedFixture, GlibFixture) // { // unsigned oldLimit = ipc::getMaxFDNumber(); -- 2.7.4 From 314f5334d5fa3cf8d7dfe6207fc5e7aa10acccdc Mon Sep 17 00:00:00 2001 From: Dariusz Michaluk Date: Fri, 29 May 2015 14:44:12 +0200 Subject: [PATCH 16/16] Various changes relating to build on Fedora Linux. [Bug/Feature] Support different versions of json-c. Unify installation paths. Fix compiler warnings. Support different platform type in RPM spec file. Small changes in deamon and service configuration. [Cause] N/A [Solution] N/A [Verification] Build, run tests, run server on Tizen and Fedora. Select platform type with --define 'platform_type FEDORA or TIZEN' Change-Id: I6ef85e9605d2069701ee68dd8e8946f0346387f5 --- CMakeLists.txt | 18 ++++---- client/CMakeLists.txt | 2 +- libs/config/CMakeLists.txt | 6 ++- libs/config/from-json-visitor.hpp | 5 +++ libs/config/from-kvjson-visitor.hpp | 5 +++ libs/config/to-json-visitor.hpp | 9 ++++ libs/logger/ccolor.cpp | 2 +- packaging/vasum.spec | 48 ++++++++++++++++++---- server/CMakeLists.txt | 2 +- server/configs/daemon.conf.in | 6 +-- server/configs/systemd/vasum.service.in | 1 - server/configs/templates/tizen-common-wayland.sh | 2 + .../network_tests/network_common.py | 2 +- tests/unit_tests/CMakeLists.txt | 2 +- tests/unit_tests/configs/CMakeLists.txt | 5 ++- ...t-test.service => vasum-socket-test.service.in} | 2 +- wrapper/CMakeLists.txt | 2 +- 17 files changed, 88 insertions(+), 31 deletions(-) rename tests/unit_tests/configs/systemd/{vasum-socket-test.service => vasum-socket-test.service.in} (72%) diff --git a/CMakeLists.txt b/CMakeLists.txt index d42f496..e865117 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -91,6 +91,11 @@ ADD_DEFINITIONS(-DPROJECT_SOURCE_DIR="${PROJECT_SOURCE_DIR}") ADD_DEFINITIONS(-DUSE_EXEC) ADD_DEFINITIONS(-D__STDC_LIMIT_MACROS) +PKG_SEARCH_MODULE(JSON_C REQUIRED json json-c) +IF(JSON_C_VERSION GREATER 0.11) + ADD_DEFINITIONS(-DJSON_C_VERSION_NEW) +ENDIF(JSON_C_VERSION GREATER 0.11) + IF("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") # Warn about documentation problems ADD_DEFINITIONS("-Wdocumentation") @@ -151,32 +156,29 @@ SET(TESTS_FOLDER ${PROJECT_SOURCE_DIR}/tests) SET(CLI_FOLDER ${PROJECT_SOURCE_DIR}/cli) SET(WRAPPER_FOLDER ${PROJECT_SOURCE_DIR}/wrapper) + IF(NOT DEFINED SYSCONF_INSTALL_DIR) SET(SYSCONF_INSTALL_DIR "/etc") ENDIF(NOT DEFINED SYSCONF_INSTALL_DIR) IF(NOT DEFINED LIB_INSTALL_DIR) - SET(LIB_INSTALL_DIR "${CMAKE_INSTALL_FULL_LIBDIR}") + SET(LIB_INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/lib") ENDIF(NOT DEFINED LIB_INSTALL_DIR) IF(NOT DEFINED INCLUDE_INSTALL_DIR) - SET(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_FULL_INCLUDEDIR}") + SET(INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}") ENDIF(NOT DEFINED INCLUDE_INSTALL_DIR) IF(NOT DEFINED SCRIPT_INSTALL_DIR) - SET(SCRIPT_INSTALL_DIR "${CMAKE_INSTALL_FULL_SBINDIR}") + SET(SCRIPT_INSTALL_DIR "${CMAKE_INSTALL_SBINDIR}") ENDIF(NOT DEFINED SCRIPT_INSTALL_DIR) -IF(NOT DEFINED SHARE_INSTALL_PREFIX) - SET(SHARE_INSTALL_PREFIX "${CMAKE_INSTALL_FULL_DATAROOTDIR}") -ENDIF(NOT DEFINED SHARE_INSTALL_PREFIX) - IF(NOT DEFINED SYSTEMD_UNIT_DIR) SET(SYSTEMD_UNIT_DIR "${LIB_INSTALL_DIR}/systemd/system") ENDIF(NOT DEFINED SYSTEMD_UNIT_DIR) IF(NOT DEFINED DATA_DIR) - SET(DATA_DIR "${CMAKE_INSTALL_FULL_DATAROOTDIR}") + SET(DATA_DIR "${CMAKE_INSTALL_PREFIX}/share") ENDIF(NOT DEFINED DATA_DIR) SET(VSM_CONFIG_INSTALL_DIR ${SYSCONF_INSTALL_DIR}/vasum) diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index c9f4c17..3fa44fd 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -62,7 +62,7 @@ INSTALL(FILES ${CMAKE_BINARY_DIR}/${PC_FILE} DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) INSTALL(TARGETS ${PROJECT_NAME} - DESTINATION ${CMAKE_INSTALL_LIBDIR} + DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) INSTALL(FILES vasum-client.h diff --git a/libs/config/CMakeLists.txt b/libs/config/CMakeLists.txt index 87c2af1..fcc5e23 100644 --- a/libs/config/CMakeLists.txt +++ b/libs/config/CMakeLists.txt @@ -38,9 +38,11 @@ SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES ## Link libraries ############################################################## PKG_CHECK_MODULES(CONFIG_DEPS REQUIRED sqlite3 glib-2.0) +PKG_SEARCH_MODULE(JSON_C json json-c) + INCLUDE_DIRECTORIES(${LIBS_FOLDER}) -INCLUDE_DIRECTORIES(SYSTEM ${CONFIG_DEPS_INCLUDE_DIRS}) -TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} ${CONFIG_DEPS_LIBRARIES}) +INCLUDE_DIRECTORIES(SYSTEM ${CONFIG_DEPS_INCLUDE_DIRS} ${JSON_C_INCLUDE_DIRS}) +TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${pkgs_LDFLAGS} ${CONFIG_DEPS_LIBRARIES} ${JSON_C_LIBRARIES}) ## Generate the pc file ######################################################## CONFIGURE_FILE(${PC_FILE}.in ${CMAKE_CURRENT_BINARY_DIR}/${PC_FILE} @ONLY) diff --git a/libs/config/from-json-visitor.hpp b/libs/config/from-json-visitor.hpp index 2934adf..8831ef6 100644 --- a/libs/config/from-json-visitor.hpp +++ b/libs/config/from-json-visitor.hpp @@ -28,7 +28,12 @@ #include "config/is-visitable.hpp" #include "config/exception.hpp" +#ifdef JSON_C_VERSION_NEW +#include +#else //JSON_C_VERSION_NEW #include +#endif //JSON_C_VERSION_NEW + #include #include diff --git a/libs/config/from-kvjson-visitor.hpp b/libs/config/from-kvjson-visitor.hpp index 35e1bf7..f9c11ef 100644 --- a/libs/config/from-kvjson-visitor.hpp +++ b/libs/config/from-kvjson-visitor.hpp @@ -28,7 +28,12 @@ #include "config/from-kvstore-visitor.hpp" #include "config/is-union.hpp" + +#ifdef JSON_C_VERSION_NEW +#include +#else //JSON_C_VERSION_NEW #include +#endif //JSON_C_VERSION_NEW namespace config { diff --git a/libs/config/to-json-visitor.hpp b/libs/config/to-json-visitor.hpp index f524900..1b68438 100644 --- a/libs/config/to-json-visitor.hpp +++ b/libs/config/to-json-visitor.hpp @@ -28,7 +28,12 @@ #include "config/is-visitable.hpp" #include "config/exception.hpp" +#ifdef JSON_C_VERSION_NEW +#include +#else //JSON_C_VERSION_NEW #include +#endif //JSON_C_VERSION_NEW + #include #include @@ -108,7 +113,11 @@ private: static json_object* toJsonObject(double value) { +#ifdef JSON_C_VERSION_NEW + return json_object_new_double_s(value, std::to_string(value).c_str()); +#else //JSON_C_VERSION_NEW return json_object_new_double(value); +#endif //JSON_C_VERSION_NEW } static json_object* toJsonObject(const std::string& value) diff --git a/libs/logger/ccolor.cpp b/libs/logger/ccolor.cpp index 7424044..9cc652d 100644 --- a/libs/logger/ccolor.cpp +++ b/libs/logger/ccolor.cpp @@ -34,7 +34,7 @@ std::string getConsoleEscapeSequence(Attributes attr, Color color) char command[10]; // Command is the control command to the terminal - snprintf(command, sizeof(command), "%c[%d;%dm", 0x1B, attr, color); + snprintf(command, sizeof(command), "%c[%u;%um", 0x1B, (unsigned int)attr, (unsigned int)color); return std::string(command); } diff --git a/packaging/vasum.spec b/packaging/vasum.spec index 8f10a1c..bd7346c 100644 --- a/packaging/vasum.spec +++ b/packaging/vasum.spec @@ -8,6 +8,8 @@ %define disk_group disk # The group that has write access to /dev/tty* devices. %define tty_group tty +# Default platform is Tizen, setup Fedora with --define 'platform_type FEDORA' +%{!?platform_type:%define platform_type "TIZEN"} Name: vasum Epoch: 1 @@ -19,13 +21,16 @@ Group: Security/Other Summary: Daemon for managing zones BuildRequires: cmake BuildRequires: boost-devel -BuildRequires: libjson-devel >= 0.10 -BuildRequires: lxc-devel BuildRequires: pkgconfig(glib-2.0) -BuildRequires: pkgconfig(sqlite3) -Requires(post): libcap-tools +BuildRequires: lxc-devel +Requires: lxc +%if %{platform_type} == "TIZEN" Requires: iproute2 -Requires: libjson >= 0.10 +Requires(post): libcap-tools +%else +Requires: iproute +Requires(post): libcap +%endif Obsoletes: vasum-daemon < 1:0 %description @@ -34,11 +39,12 @@ between them. A process from inside a zone can request a switch of context (display, input devices) to the other zone. %files +%if %{platform_type} == "TIZEN" %manifest packaging/vasum.manifest +%endif %defattr(644,root,root,755) %attr(755,root,root) %{_bindir}/vasum-server %dir /etc/vasum -%dir /etc/vasum/zones %dir /etc/vasum/templates %config /etc/vasum/daemon.conf %attr(755,root,root) /etc/vasum/templates/*.sh @@ -47,7 +53,7 @@ between them. A process from inside a zone can request a switch of context %{_unitdir}/vasum.socket %{_unitdir}/multi-user.target.wants/vasum.service %config /etc/dbus-1/system.d/org.tizen.vasum.host.conf -%dir %{_datadir}/.zones +%dir %{_datadir}/zones %prep %setup -q @@ -77,7 +83,7 @@ make -k %{?jobs:-j%jobs} %make_install mkdir -p %{buildroot}/%{_unitdir}/multi-user.target.wants ln -s ../vasum.service %{buildroot}/%{_unitdir}/multi-user.target.wants/vasum.service -mkdir -p %{buildroot}/%{_datadir}/.zones +mkdir -p %{buildroot}/%{_datadir}/zones %clean rm -rf %{buildroot} @@ -127,7 +133,9 @@ Library interface to the vasum daemon %postun -n vasum-client -p /sbin/ldconfig %files client +%if %{platform_type} == "TIZEN" %manifest packaging/libvasum-client.manifest +%endif %defattr(644,root,root,755) %attr(755,root,root) %{_libdir}/libvasum-client.so.%{version} %{_libdir}/libvasum-client.so.0 @@ -146,7 +154,9 @@ Requires: vasum-client = %{epoch}:%{version}-%{release} Development package including the header files for the client library %files devel +%if %{platform_type} == "TIZEN" %manifest packaging/vasum.manifest +%endif %defattr(644,root,root,755) %{_libdir}/libvasum-client.so %{_libdir}/libvasum.so @@ -164,7 +174,9 @@ Group: Security/Other Zones support installed inside every zone. %files zone-support +%if %{platform_type} == "TIZEN" %manifest packaging/vasum-zone-support.manifest +%endif %defattr(644,root,root,755) %config /etc/dbus-1/system.d/org.tizen.vasum.zone.conf @@ -179,7 +191,9 @@ Requires: vasum-zone-support = %{epoch}:%{version}-%{release} Daemon running inside every zone. %files zone-daemon +%if %{platform_type} == "TIZEN" %manifest packaging/vasum-zone-daemon.manifest +%endif %defattr(644,root,root,755) %attr(755,root,root) %{_bindir}/vasum-zone-daemon %config /etc/dbus-1/system.d/org.tizen.vasum.zone.daemon.conf @@ -217,7 +231,9 @@ Group: Development/Libraries Requires: vasum = %{epoch}:%{version}-%{release} Requires: vasum-client = %{epoch}:%{version}-%{release} Requires: python +%if %{platform_type} == "TIZEN" Requires: python-xml +%endif Requires: boost-test %description tests @@ -236,7 +252,9 @@ systemctl disable vasum-socket-test.socket systemctl daemon-reload %files tests +%if %{platform_type} == "TIZEN" %manifest packaging/vasum-server-tests.manifest +%endif %defattr(644,root,root,755) %attr(755,root,root) %{_bindir}/vasum-server-unit-tests %attr(755,root,root) %{_bindir}/vasum-socket-test @@ -327,6 +345,14 @@ The package provides libSimpleDbus development tools and libs. %package -n libConfig Summary: Config library Group: Security/Other +BuildRequires: pkgconfig(sqlite3) +%if %{platform_type} == "TIZEN" +BuildRequires: libjson-devel >= 0.10 +Requires: libjson >= 0.10 +%else +BuildRequires: json-c-devel +Requires: json-c +%endif Requires(post): /sbin/ldconfig Requires(postun): /sbin/ldconfig @@ -348,7 +374,11 @@ Group: Development/Libraries Requires: libConfig = %{epoch}:%{version}-%{release} Requires: boost-devel Requires: pkgconfig(libLogger) -Requires: libjson-devel +%if %{platform_type} == "TIZEN" +Requires: libjson-devel >= 0.10 +%else +Requires: json-c-devel +%endif %description -n libConfig-devel The package provides libConfig development tools and libs. diff --git a/server/CMakeLists.txt b/server/CMakeLists.txt index 9a1985c..92672c1 100644 --- a/server/CMakeLists.txt +++ b/server/CMakeLists.txt @@ -30,7 +30,7 @@ ADD_EXECUTABLE(${SERVER_CODENAME} ${project_SRCS} ${common_SRCS}) ## Link libraries ############################################################## FIND_PACKAGE(Boost COMPONENTS program_options system filesystem regex) -PKG_CHECK_MODULES(SERVER_DEPS REQUIRED lxc json gio-2.0) +PKG_CHECK_MODULES(SERVER_DEPS REQUIRED lxc glib-2.0 gio-2.0) INCLUDE_DIRECTORIES(${COMMON_FOLDER}) INCLUDE_DIRECTORIES(${LIBS_FOLDER}) diff --git a/server/configs/daemon.conf.in b/server/configs/daemon.conf.in index b94eb29..f3dd9fd 100644 --- a/server/configs/daemon.conf.in +++ b/server/configs/daemon.conf.in @@ -1,13 +1,13 @@ { - "dbPath" : "/usr/dbspace/vasum.db", + "dbPath" : "/etc/vasum/vasum.db", "zoneIds" : [], - "zonesPath" : "${DATA_DIR}/.zones", + "zonesPath" : "${DATA_DIR}/zones", "zoneImagePath" : "", "zoneTemplateDir" : "/etc/vasum/templates/", "runMountPointPrefix" : "/var/run/zones", "defaultId" : "", "availableVTs" : [3, 4, 5, 6], - "inputConfig" : {"enabled" : true, + "inputConfig" : {"enabled" : false, "device" : "gpio_keys.6", "code" : 116, "numberOfEvents" : 2, diff --git a/server/configs/systemd/vasum.service.in b/server/configs/systemd/vasum.service.in index 29ebbc8..1b6284f 100644 --- a/server/configs/systemd/vasum.service.in +++ b/server/configs/systemd/vasum.service.in @@ -1,6 +1,5 @@ [Unit] Description=Vasum Server -ConditionVirtualization=no [Service] Type=simple diff --git a/server/configs/templates/tizen-common-wayland.sh b/server/configs/templates/tizen-common-wayland.sh index 5c57aff..30b90cd 100755 --- a/server/configs/templates/tizen-common-wayland.sh +++ b/server/configs/templates/tizen-common-wayland.sh @@ -122,6 +122,8 @@ ${path}/systemd/user /bin/ln -s /dev/null ${path}/systemd/system/systemd-udevd.service /bin/ln -s /dev/null ${path}/systemd/system/systemd-udevd-kernel.socket /bin/ln -s /dev/null ${path}/systemd/system/systemd-udevd-control.socket +/bin/ln -s /dev/null ${path}/systemd/system/vasum.service +/bin/ln -s /dev/null ${path}/systemd/system/vasum.socket /bin/ln -s /dev/null ${path}/systemd/system/vconf-setup.service /bin/ln -s /usr/lib/systemd/system/tlm.service ${path}/systemd/system/multi-user.target.wants/tlm.service /bin/ln -s /dev/null ${path}/systemd/user/media-server-user.service diff --git a/tests/integration_tests/network_tests/network_common.py b/tests/integration_tests/network_tests/network_common.py index acb120c..98e85b5 100755 --- a/tests/integration_tests/network_tests/network_common.py +++ b/tests/integration_tests/network_tests/network_common.py @@ -31,7 +31,7 @@ TEST_URL_INTERNET=["www.samsung.com", "www.google.com", "www.oracle.com"] #TODO read path from config (daemon.conf) # Path to test zone -TEST_ZONE_PATH="/usr/share/.zones" +TEST_ZONE_PATH="/usr/share/zones" # Device Ethernet device ETHERNET_DEVICE="usb0" diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt index 484e810..46a9a3b 100644 --- a/tests/unit_tests/CMakeLists.txt +++ b/tests/unit_tests/CMakeLists.txt @@ -47,7 +47,7 @@ ADD_EXECUTABLE(${SOCKET_TEST_CODENAME} ${socket_test_SRCS} ${common_SRCS} ${clie ## Link libraries ############################################################## FIND_PACKAGE (Boost COMPONENTS unit_test_framework system filesystem regex) -PKG_CHECK_MODULES(UT_SERVER_DEPS REQUIRED lxc json gio-2.0) +PKG_CHECK_MODULES(UT_SERVER_DEPS REQUIRED lxc gio-2.0) INCLUDE_DIRECTORIES(${COMMON_FOLDER} ${SERVER_FOLDER} ${UNIT_TESTS_FOLDER} ${CLIENT_FOLDER} ${LIBS_FOLDER} ${SOCKET_TEST_FOLDER}) INCLUDE_DIRECTORIES(SYSTEM ${UT_SERVER_DEPS_INCLUDE_DIRS} ${Boost_INCLUDE_DIRS}) diff --git a/tests/unit_tests/configs/CMakeLists.txt b/tests/unit_tests/configs/CMakeLists.txt index a18914e..6bffac4 100644 --- a/tests/unit_tests/configs/CMakeLists.txt +++ b/tests/unit_tests/configs/CMakeLists.txt @@ -34,6 +34,9 @@ CONFIGURE_FILE(templates/console-ipc.conf.in ${CMAKE_BINARY_DIR}/templates/console-ipc.conf @ONLY) FILE(GLOB ut_zone_templates_CONF_GEN ${CMAKE_BINARY_DIR}/templates/*.conf) +CONFIGURE_FILE(systemd/vasum-socket-test.service.in + ${CMAKE_BINARY_DIR}/systemd/vasum-socket-test.service) + ## Install ##################################################################### INSTALL(FILES ${ut_zone_CONF} @@ -58,7 +61,7 @@ INSTALL(FILES utils/file.txt DESTINATION ${VSM_TEST_CONFIG_INSTALL_DIR}/utils) INSTALL(FILES systemd/vasum-socket-test.socket - systemd/vasum-socket-test.service + ${CMAKE_BINARY_DIR}/systemd/vasum-socket-test.service DESTINATION ${SYSTEMD_UNIT_DIR}) INSTALL(FILES dbus-1/system.d/org.tizen.vasum.tests.conf diff --git a/tests/unit_tests/configs/systemd/vasum-socket-test.service b/tests/unit_tests/configs/systemd/vasum-socket-test.service.in similarity index 72% rename from tests/unit_tests/configs/systemd/vasum-socket-test.service rename to tests/unit_tests/configs/systemd/vasum-socket-test.service.in index 23c6d3a..b5da48b 100644 --- a/tests/unit_tests/configs/systemd/vasum-socket-test.service +++ b/tests/unit_tests/configs/systemd/vasum-socket-test.service.in @@ -3,7 +3,7 @@ Description=Vasum Socket tests mini-service [Service] Type=simple -ExecStart=/usr/bin/vasum-socket-test +ExecStart=${CMAKE_INSTALL_PREFIX}/bin/vasum-socket-test Sockets=vasum-socket-test.socket StartLimitInterval=0 StartLimitBurst=0 diff --git a/wrapper/CMakeLists.txt b/wrapper/CMakeLists.txt index a8aa173..23fdba6 100644 --- a/wrapper/CMakeLists.txt +++ b/wrapper/CMakeLists.txt @@ -70,7 +70,7 @@ INSTALL(FILES ${CMAKE_BINARY_DIR}/${PC_FILE} DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) INSTALL(TARGETS ${PROJECT_NAME} - DESTINATION ${CMAKE_INSTALL_LIBDIR} + DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) INSTALL(FILES vasum.h vasum_list.h -- 2.7.4