summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonrad Lipinski <k.lipinski2@samsung.com>2022-07-13 16:46:48 +0200
committerKonrad Lipinski <k.lipinski2@samsung.com>2022-07-22 15:37:53 +0200
commit0c84562f06028a1f624d5f5bc4bc62d9545f5b9c (patch)
tree13ef5826f6b71298d107ea4e68d0d188323af44a
parent6971fdaa527bfc3ba86ad77ebb5c7c7c2ab47848 (diff)
downloadsecurity-manager-0c84562f06028a1f624d5f5bc4bc62d9545f5b9c.tar.gz
security-manager-0c84562f06028a1f624d5f5bc4bc62d9545f5b9c.tar.bz2
security-manager-0c84562f06028a1f624d5f5bc4bc62d9545f5b9c.zip
Prioritize requests based on cpu boosting level
There are three boosting levels at present, hence three distinct priorities are introduced. Since the priority space is small, the priority queue is implemented via an array of FIFO queues. CPU priority inheritance from client to server is also included. The boosting level and priority inheritance facilities are provided by the capi-system-resource module. According to said facilities' designers, querying the boosting level is most efficient when done directly in the queried thread. Thus, when making a security manager client request, the boosting level is obtained and prepended to the request payload. This is also makes requests atomic and mitigates the potential for priority races. Change-Id: Icc10fb5e40fa74eafe16726d28ac66cd8b560810
-rw-r--r--packaging/security-manager.spec1
-rw-r--r--src/client/CMakeLists.txt3
-rw-r--r--src/client/include/client-request.h32
-rw-r--r--src/common/include/protocols.h14
-rw-r--r--src/common/include/utils.h7
-rw-r--r--src/common/protocols.cpp7
-rw-r--r--src/server/CMakeLists.txt3
-rw-r--r--src/server/main/include/service-thread.h35
-rw-r--r--src/server/main/server-main.cpp12
-rw-r--r--src/server/main/socket-manager.cpp18
-rw-r--r--src/server/rules-loader/security-manager-rules-loader.cpp5
11 files changed, 103 insertions, 34 deletions
diff --git a/packaging/security-manager.spec b/packaging/security-manager.spec
index c89efa1c..563c5596 100644
--- a/packaging/security-manager.spec
+++ b/packaging/security-manager.spec
@@ -29,6 +29,7 @@ BuildRequires: cmake
BuildRequires: zip
BuildRequires: pkgconfig(dlog)
BuildRequires: libattr-devel
+BuildRequires: pkgconfig(capi-system-resource)
BuildRequires: pkgconfig(libsmack)
BuildRequires: pkgconfig(libcap)
BuildRequires: pkgconfig(libsystemd)
diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt
index f0df161e..c8db9388 100644
--- a/src/client/CMakeLists.txt
+++ b/src/client/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2014-2020 Samsung Electronics Co., Ltd. All rights reserved.
+# Copyright (c) 2014-2022 Samsung Electronics Co., Ltd. All rights reserved
#
# This file is licensed under the terms of MIT License or the Apache License
# Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -21,6 +21,7 @@
PKG_CHECK_MODULES(CLIENT_DEP
REQUIRED
+ capi-system-resource
cynara-client-async
libsmack
libcap
diff --git a/src/client/include/client-request.h b/src/client/include/client-request.h
index a83e9cd7..2d61d2f3 100644
--- a/src/client/include/client-request.h
+++ b/src/client/include/client-request.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2016-2022 Samsung Electronics Co., Ltd. All rights reserved
*
* This file is licensed under the terms of MIT License or the Apache License
* Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -29,20 +29,45 @@
#pragma once
#include <stdexcept>
+#include <cpu-boosting.h>
#include <connection.h>
#include <dpl/log/log.h>
#include <message-buffer.h>
#include <protocols.h>
#include <security-manager-types.h>
+#include <utils.h>
namespace SecurityManager {
class ClientRequest {
+
+ static Priority getPriority() {
+ auto priority = Priority::LOW;
+ resource_pid_t proc_data;
+ cpu_boosting_level_info_t info;
+ proc_data.tid = nullptr;
+ proc_data.pid = 0; // query for current TID - array tid_level gets allocated
+ if (resource_get_cpu_boosting_level(proc_data, &info) != 0) {
+ LogError("resource_get_cpu_boosting_level failed");
+ } else {
+ switch (info.tid_level[0]) {
+ case CPU_BOOSTING_LEVEL_STRONG:
+ priority = Priority::HIGH;
+ break;
+ case CPU_BOOSTING_LEVEL_MEDIUM:
+ priority = Priority::MEDIUM;
+ break;
+ }
+ free(info.tid_level);
+ }
+ return priority;
+ }
public:
ClientRequest(SecurityModuleCall action)
{
m_buffer.InitForStreaming();
+ Serialization::Serialize(m_buffer, underlying(getPriority()));
Serialization::Serialize(m_buffer, static_cast<int>(action));
}
@@ -64,7 +89,12 @@ public:
m_sent = true;
+ const auto tid = gettid();
+ if (resource_set_cpu_inheritance(tid, RESOURCE_CPU_DEST_NAME, -1) != 0)
+ LogError("resource_set_cpu_inheritance failed");
m_status = sendToServer(SERVICE_SOCKET, m_buffer);
+ if (resource_clear_cpu_inheritance(tid, RESOURCE_CPU_DEST_NAME) != 0)
+ LogError("resource_clear_cpu_inheritance failed");
if (!failed())
Deserialization::Deserialize(m_buffer, m_status);
else
diff --git a/src/common/include/protocols.h b/src/common/include/protocols.h
index fdc3c6a3..03bcc201 100644
--- a/src/common/include/protocols.h
+++ b/src/common/include/protocols.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2014-2022 Samsung Electronics Co., Ltd. All rights reserved
*
* This file is licensed under the terms of MIT License or the Apache License
* Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -106,7 +106,17 @@ struct path_req {
namespace SecurityManager {
-extern char const * const SERVICE_SOCKET;
+#define SOCKET_PATH_PREFIX "/run/"
+
+inline constexpr auto SERVICE_SOCKET = SOCKET_PATH_PREFIX "security-manager.socket";
+inline constexpr auto RESOURCE_CPU_DEST_NAME = "SECURITY_MANAGER_DEST";
+
+enum Priority : unsigned char {
+ HIGH,
+ MEDIUM,
+ LOW,
+ END,
+};
enum class SecurityModuleCall
{
diff --git a/src/common/include/utils.h b/src/common/include/utils.h
index 099a9fdd..b4998880 100644
--- a/src/common/include/utils.h
+++ b/src/common/include/utils.h
@@ -136,5 +136,10 @@ constexpr auto max(const T &a, const U &b) {
template <class E>
constexpr auto underlying(const E &e) {
- return typename std::underlying_type<E>::type(e);
+ return std::underlying_type_t<E>(e);
+}
+
+template <class T, size_t S>
+constexpr size_t arraySize(T (&)[S]) {
+ return S;
}
diff --git a/src/common/protocols.cpp b/src/common/protocols.cpp
index f31f76e0..b7a8e777 100644
--- a/src/common/protocols.cpp
+++ b/src/common/protocols.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2014-2022 Samsung Electronics Co., Ltd. All rights reserved
*
* This file is licensed under the terms of MIT License or the Apache License
* Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -32,11 +32,6 @@
namespace SecurityManager {
-#define SOCKET_PATH_PREFIX "/run/"
-
-char const * const SERVICE_SOCKET =
- SOCKET_PATH_PREFIX "security-manager.socket";
-
#define SM_CODE_DESCRIBE(name) case name: return #name
const char * SecurityModuleCallToString(SecurityModuleCall call_num) {
switch (call_num) {
diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt
index e19f8eec..5dac5653 100644
--- a/src/server/CMakeLists.txt
+++ b/src/server/CMakeLists.txt
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013-2020 Samsung Electronics Co., Ltd. All rights reserved.
+# Copyright (c) 2013-2022 Samsung Electronics Co., Ltd. All rights reserved
#
# This file is licensed under the terms of MIT License or the Apache License
# Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -21,6 +21,7 @@
PKG_CHECK_MODULES(SERVER_DEP
REQUIRED
+ capi-system-resource
libsystemd
cynara-client
mount
diff --git a/src/server/main/include/service-thread.h b/src/server/main/include/service-thread.h
index 82d319bf..2818a655 100644
--- a/src/server/main/include/service-thread.h
+++ b/src/server/main/include/service-thread.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2014-2022 Samsung Electronics Co., Ltd. All rights reserved
*
* This file is licensed under the terms of MIT License or the Apache License
* Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -30,18 +30,21 @@
#include <cassert>
#include <condition_variable>
-#include <dpl/exception.h>
#include <mutex>
#include <queue>
#include <thread>
+#include <dpl/exception.h>
+#include <protocols.h> // Priority
+#include <utils.h>
+
namespace SecurityManager {
template <class DerivedService, class Event>
class ServiceThread {
std::thread m_thread;
std::mutex m_eventQueueMutex;
- std::queue<Event *> m_eventQueue;
+ std::queue<Event *> m_eventQueues[Priority::END];
std::condition_variable m_waitCondition;
bool m_quit = false;
@@ -57,18 +60,20 @@ public:
m_thread.join();
// clear the event queue
- while (!m_eventQueue.empty()) {
- delete m_eventQueue.front();
- m_eventQueue.pop();
- }
+ for (auto &queue: m_eventQueues)
+ while (!queue.empty()) {
+ delete queue.front();
+ queue.pop();
+ }
}
template <class...T>
- void PutEvent(T&&...arg) {
+ void PutEvent(Priority priority, T&&...arg) {
+ assert(priority < arraySize(m_eventQueues));
const auto event = new Event{ std::forward<T>(arg)... };
{
std::lock_guard<std::mutex> lock(m_eventQueueMutex);
- m_eventQueue.emplace(event);
+ m_eventQueues[priority].emplace(event);
}
m_waitCondition.notify_one();
}
@@ -82,15 +87,17 @@ private:
for (;;) {
if (m_quit)
return;
- if (!m_eventQueue.empty()) {
- event = m_eventQueue.front();
- m_eventQueue.pop();
- break;
- }
+ for (auto &queue: m_eventQueues)
+ if (!queue.empty()) {
+ event = queue.front();
+ queue.pop();
+ goto handleOneEvent;
+ }
m_waitCondition.wait(ulock);
}
}
+ handleOneEvent:
UNHANDLED_EXCEPTION_HANDLER_BEGIN
{
const auto eventGuard = makeUnique(event);
diff --git a/src/server/main/server-main.cpp b/src/server/main/server-main.cpp
index e6a37e14..2a98a9ab 100644
--- a/src/server/main/server-main.cpp
+++ b/src/server/main/server-main.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2014-2022 Samsung Electronics Co., Ltd. All rights reserved
*
* This file is licensed under the terms of MIT License or the Apache License
* Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -31,6 +31,7 @@
#include <dpl/log/log.h>
#include <dpl/singleton.h>
+#include <cpu-boosting.h>
#include <iostream>
#include <channel.h>
@@ -83,12 +84,21 @@ int security_manager(Channel channel)
LogInfo("Start!");
SecurityManager::SocketManager manager;
+ resource_pid_t self_data;
+ self_data.pid = getpid();
+
+ if (resource_register_cpu_inheritance_destination(RESOURCE_CPU_DEST_NAME, self_data) != 0)
+ LogError("resource_register_cpi_inheritance_destination failed");
+
if (!REGISTER_SOCKET_SERVICE(manager, SecurityManager::Service, std::move(channel))) {
LogError("Unable to create socket service. Exiting.");
return EXIT_FAILURE;
}
manager.MainLoop();
+
+ if(resource_unregister_cpu_inheritance_destination(RESOURCE_CPU_DEST_NAME) != 0)
+ LogError("resource_unregister_cpu_inheritance_destination failed");
return 0;
}
diff --git a/src/server/main/socket-manager.cpp b/src/server/main/socket-manager.cpp
index 08f89cb2..c7623412 100644
--- a/src/server/main/socket-manager.cpp
+++ b/src/server/main/socket-manager.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2022 Samsung Electronics Co., Ltd. All rights reserved.
+ * Copyright (c) 2013-2022 Samsung Electronics Co., Ltd. All rights reserved
*
* This file is licensed under the terms of MIT License or the Apache License
* Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details.
@@ -42,6 +42,7 @@
#include <time.h>
#include <unistd.h>
+#include <cpu-boosting.h>
#include <systemd/sd-daemon.h>
#include <dpl/log/log.h>
@@ -196,8 +197,21 @@ void SocketManager::ReadyForRead(int sock) {
break;
case MessageBuffer::InputResult::Done:
buffer.ModeStreaming();
+
+ if (buffer.DeserializationDone()) {
+ LogError("No priority, closing socket");
+ goto close;
+ }
+ std::underlying_type_t<Priority> priority;
+ Deserialization::Deserialize(buffer, priority);
+ if (priority >= Priority::END) {
+ LogError("Invalid priority: " << priority);
+ goto close;
+ }
+
FD_CLR(sock, &m_readSet); // the one and only call on this socket is complete
- m_service->PutEvent(ConnectionID{sock, desc.counter},
+ m_service->PutEvent(static_cast<Priority>(priority),
+ ConnectionID{sock, desc.counter},
Credentials::getCredentialsFromSocket(sock),
std::move(buffer));
break;
diff --git a/src/server/rules-loader/security-manager-rules-loader.cpp b/src/server/rules-loader/security-manager-rules-loader.cpp
index b0dc3893..dd3eea46 100644
--- a/src/server/rules-loader/security-manager-rules-loader.cpp
+++ b/src/server/rules-loader/security-manager-rules-loader.cpp
@@ -58,11 +58,6 @@ namespace {
// constexpr const char *dbUpdateScript[dbVersion];
#include "../gen/db.h"
-template <class T, size_t S>
-constexpr size_t arraySize(T (&)[S]) {
- return S;
-}
-
static_assert(dbSchema);
// this ensures that parsing the sql files was done correctly and we have proper
// number of update scripts