Merge tizen_4.0 into tizen 26/199226/2 submit/tizen/20190311.143210 submit/tizen/20190312.095229 submit/tizen/20190315.105214 submit/tizen_5.0/20190311.143405 submit/tizen_5.0/20190312.095251 submit/tizen_5.0/20190314.052825 submit/tizen_5.0/20190315.105239
authorKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 7 Feb 2019 10:16:12 +0000 (11:16 +0100)
committerKrzysztof Jackiewicz <k.jackiewicz@samsung.com>
Thu, 7 Feb 2019 10:35:32 +0000 (11:35 +0100)
Change-Id: Ibc4f1105aad26c5df9a640775e81bfc761403c5a

32 files changed:
CMakeLists.txt
fota/500.ode_upgrade.sh [new file with mode: 0755]
fota/CMakeLists.txt
fota/fota.cpp
fota/ode_softreset.sh [new file with mode: 0755]
lib/internal-encryption.cpp
lib/internal-encryption.h
lib/ode/common.h
lib/ode/internal-encryption.cpp
lib/ode/internal-encryption.h
packaging/ode.spec
rmi/external-encryption.h
rmi/internal-encryption.h
server/CMakeLists.txt
server/app-bundle.cpp [deleted file]
server/app-bundle.h [deleted file]
server/engine/encryption/dmcrypt-engine.cpp
server/engine/encryption/dmcrypt-engine.h
server/external-encryption.cpp
server/file-footer.cpp
server/file-sink.cpp [new file with mode: 0644]
server/file-sink.h [moved from server/launchpad.h with 52% similarity]
server/internal-encryption.cpp
server/internal-encryption.h
server/key-manager/key-generator.cpp
server/key-server.cpp
server/key-server.h
server/launchpad.cpp [deleted file]
server/server.cpp
server/systemd/ode.service.in
server/upgrade-support.cpp
server/upgrade-support.h

index 2a6e621..620abf2 100755 (executable)
@@ -92,6 +92,10 @@ IF(NOT DEFINED SYSTEMD_UNIT_DIR)
        SET(SYSTEMD_UNIT_DIR "${CMAKE_INSTALL_PREFIX}/lib/systemd/system")
 ENDIF(NOT DEFINED SYSTEMD_UNIT_DIR)
 
+IF(NOT DEFINED SOFTRESET_DIR)
+       SET(SOFTRESET_DIR "/usr/system/RestoreDir/softreset")
+ENDIF(NOT DEFINED SOFTRESET_DIR)
+
 IF(NOT DEFINED KEY_STORAGE_PLUGIN_DIR)
        SET(KEY_STORAGE_PLUGIN_DIR "${CMAKE_INSTALL_LIBDIR}/ode-key-storage-plugin")
 ENDIF(NOT DEFINED KEY_STORAGE_PLUGIN_DIR)
diff --git a/fota/500.ode_upgrade.sh b/fota/500.ode_upgrade.sh
new file mode 100755 (executable)
index 0000000..f8c40c0
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/bash
+# RW Update Script for 3.0 -> 4.0 and 4.0 -> 4.0
+# Update ode status whenever doing FOTA
+PATH=/bin:/usr/bin:/sbin:/usr/sbin
+source /usr/share/upgrade/rw-update-macro.inc
+get_version_info
+
+ODE_STATE=`vconftool get -t string db/ode/crypto_state`
+ODE_STATE=${ODE_STATE#*=}
+ODE_STATE=${ODE_STATE%(*}
+
+if [ $ODE_STATE = "notsupported" ]; then
+vconftool set -f -t string db/ode/crypto_state "unencrypted"
+elif [ $ODE_STATE = "mounted" ]; then
+vconftool set -f -t string db/ode/crypto_state "encrypted"
+fi
+
+if [ -e /opt/etc/ode_footer ]; then
+       touch /opt/etc/.ode_upgrade_started
+       rm -f /opt/etc/ode_footer
+fi
index f839bf2..e7d41a0 100755 (executable)
@@ -16,7 +16,7 @@
 
 SET(PROJECT_NAME "ode-fota")
 
-PKG_CHECK_MODULES(FOTA_DEPS REQUIRED klay)
+PKG_CHECK_MODULES(FOTA_DEPS REQUIRED klay-static blkid)
 
 SET(SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/fota.cpp
                        ${ODE_SERVER}/upgrade-support.cpp
@@ -38,4 +38,6 @@ TARGET_LINK_LIBRARIES(${PROJECT_NAME} ${FOTA_DEPS_LIBRARIES} dl)
 SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES COMPILE_FLAGS "-fPIE")
 SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES LINK_FLAGS "-pie")
 
-INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${SBIN_DIR})
\ No newline at end of file
+INSTALL(TARGETS ${PROJECT_NAME} DESTINATION ${SBIN_DIR})
+INSTALL(FILES ode_softreset.sh DESTINATION ${SOFTRESET_DIR})
+INSTALL(FILES 500.ode_upgrade.sh DESTINATION ${UPGRADE_SCRIPT_DIR})
index ccbdafe..a81cfa3 100644 (file)
  *  See the License for the specific language governing permissions and
  *  limitations under the License
  */
-
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
 #include <stdlib.h>
+#include <strings.h>
+#include <blkid.h>
 
 #include <string>
 #include <iostream>
@@ -29,6 +34,77 @@ audit::LogSink *SINK = nullptr;
 
 namespace ode {
 
+struct AbstractDevice {
+       AbstractDevice() {}
+       virtual ~AbstractDevice() {}
+       virtual std::string findNode(const std::string &name) = 0;
+};
+
+struct MmcDevice : public AbstractDevice {
+public:
+       MmcDevice(int id) : device("/dev/mmcblk" + std::to_string(id)), deviceHandle(-1)
+       {
+               deviceHandle = ::open(device.c_str(), O_RDONLY);
+               if (deviceHandle == -1)
+                       throw std::runtime_error("Invalid device: " + device);
+       }
+
+       virtual ~MmcDevice()
+       {
+               if (deviceHandle != -1)
+                       ::close(deviceHandle);
+       }
+
+       virtual std::string findNode(const std::string &name)
+       {
+               blkid_partlist partlist;
+               blkid_probe probe;
+               int partno = 0;
+
+               probe = ::blkid_new_probe();
+               if (!probe) {
+                       throw std::runtime_error("Failed to call blkid_new_probe");
+               }
+
+               if (::blkid_probe_set_device(probe, deviceHandle, 0, 0) < 0) {
+                       ::blkid_free_probe(probe);
+                       throw std::runtime_error("Failed to set prove device: " + device);
+               }
+
+               partlist = ::blkid_probe_get_partitions(probe);
+               if (!partlist) {
+                       ::blkid_free_probe(probe);
+                       throw std::runtime_error("Failed to get partition list in device: " + device);
+               }
+
+               int num = ::blkid_partlist_numof_partitions(partlist);
+               for (int i = 1; i <= num; i++) {
+                       blkid_partition par = ::blkid_partlist_get_partition(partlist, i);
+
+                       const char *n = ::blkid_partition_get_name(par);
+                       if (!n)
+                               break;
+
+                       if (::strcasecmp(n, name.c_str()) == 0) {
+                               partno = ::blkid_partition_get_partno(par);
+                               break;
+                       }
+               }
+
+               ::blkid_free_probe(probe);
+
+               if (partno <= 0) {
+                       throw std::runtime_error("Failed to get partition number with " +  name);
+               }
+
+               return device + "p" + std::to_string(partno);
+       }
+
+private:
+       std::string device;
+       int deviceHandle;
+};
+
 // dummy implementation
 ProgressBar::ProgressBar(UpdateFunc const&) : updateValue(0) {}
 ProgressBar::~ProgressBar() {}
@@ -41,18 +117,18 @@ void ProgressBar::done(void) {}
 namespace {
 
 const std::string MOUNT = "mount";
+const std::string UMOUNT = "umount";
 const std::string REMOVE = "remove";
 
-const std::string DEV_PATH = ode::findDevPath();
-
 void usage()
 {
        std::cout <<
                "Usage: ode-fota [Operation]" << std::endl <<
                std::endl <<
                "Operations :" << std::endl <<
-               "  mount   Mount internal memory using stored master key" << std::endl <<
-               "  remove  Remove stored internal memory master key" << std::endl;
+               "  mount [path]   Mount internal memory using stored master key" << std::endl <<
+               "  umount [path]  Unmount internal memory" << std::endl <<
+               "  remove         Remove stored internal memory master key" << std::endl;
 }
 
 } // anonymous namespace
@@ -62,20 +138,34 @@ int main(int argc, char* argv[])
        try {
                using namespace ode;
 
-               if (argc < 2) {
+               if (argc < 2 || argc > 3) {
                        usage();
                        return EXIT_FAILURE;
                }
 
+               MmcDevice dev(0);
+               std::string devpath = dev.findNode("user");
+
                if (MOUNT == argv[1]) {
-                       auto masterKey = UpgradeSupport::loadMasterKey(DEV_PATH);
+                       auto masterKey = UpgradeSupport::loadMasterKey(devpath);
+                       std::string path = INTERNAL_PATH;
+                       if (argc == 3)
+                               path = argv[2];
 
-                       DMCryptEngine dmcrypt(DEV_PATH, INTERNAL_PATH, ProgressBar([](unsigned){}));
+                       DMCryptEngine dmcrypt(devpath, path, ProgressBar([](unsigned){}));
 
                        // mount options are ignored by mount()
                        dmcrypt.mount(masterKey, 0);
+                       UpgradeSupport::createUpgradeFlag();
+               } else if (UMOUNT == argv[1]) {
+                       std::string path = INTERNAL_PATH;
+                       if (argc == 3)
+                               path = argv[2];
+
+                       DMCryptEngine dmcrypt(devpath, path, ProgressBar([](int){}));
+                       dmcrypt.umount();
                } else if (REMOVE == argv[1]) {
-                       UpgradeSupport::removeMasterKey(DEV_PATH);
+                       UpgradeSupport::removeMasterKey(devpath);
                } else {
                        usage();
                        return EXIT_FAILURE;
diff --git a/fota/ode_softreset.sh b/fota/ode_softreset.sh
new file mode 100755 (executable)
index 0000000..f81b902
--- /dev/null
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+# ode footer and key tokens
+METAFILE=`ls /opt/etc/.ode_*`
+
+# vconf keys required by ode
+VCONFKEYS="db/ode/crypto_blkdev db/ode/crypto_state db/ode/crypto_type db/ode/encrypt_progress db/ode/fast_encryption"
+
+for file in $METAFILE; do
+/usr/bin/pkg -k $file
+done
+
+for key in $VCONFKEYS; do
+/usr/bin/pkg -v $key
+done
index 123c8f3..fa918ae 100644 (file)
@@ -36,10 +36,19 @@ int InternalEncryptionClient::setMountPassword(const std::string& password)
        }
 }
 
-int InternalEncryptionClient::mount()
+int InternalEncryptionClient::mount(const std::vector<unsigned char> &mk, unsigned int options)
 {
        try {
-               return context->methodCall<int>("InternalEncryptionServer::mount");
+               return context->methodCall<int>("InternalEncryptionServer::mount", mk, options);
+       } catch (runtime::Exception& e) {
+               return error::Unknown;
+       }
+}
+
+int InternalEncryptionClient::isMounted()
+{
+       try {
+               return context->methodCall<int>("InternalEncryptionServer::isMounted");
        } catch (runtime::Exception& e) {
                return error::Unknown;
        }
index 882a464..ccedd04 100644 (file)
@@ -18,6 +18,7 @@
 #define __INTERNAL_ENCRYPTION_CLIENT_H__
 
 #include <string>
+#include <vector>
 
 #include "rmi/internal-encryption.h"
 #include "client.h"
@@ -31,8 +32,9 @@ public:
 
        int setMountPassword(const std::string& password);
 
-       int mount();
+       int mount(const std::vector<unsigned char> &mk, unsigned int options);
        int umount();
+       int isMounted();
 
        int encrypt(const std::string& password, unsigned int options);
        int decrypt(const std::string& password);
index b84a848..5f23338 100644 (file)
@@ -68,9 +68,10 @@ typedef enum {
  * @since_tizen 4.0
  */
 typedef enum {
-    ODE_STATE_UNENCRYPTED   = 0x00, /**< Device is not encrypted */
-    ODE_STATE_ENCRYPTED     = 0x01, /**< Device is encrypted  */
-    ODE_STATE_CORRUPTED     = 0x02, /**< Device is corrupted because of encryption error */
+    ODE_STATE_NOT_SUPPORTED = -1,
+    ODE_STATE_UNENCRYPTED   = 0, /**< Device is not encrypted */
+    ODE_STATE_ENCRYPTED     = 1, /**< Device is encrypted  */
+    ODE_STATE_CORRUPTED     = 2, /**< Device is corrupted because of encryption error */
 } ode_state_e;
 
 /**
index 4935d07..90c5358 100644 (file)
@@ -43,7 +43,32 @@ int ode_internal_encryption_mount()
        RET_ON_FAILURE(client.connect() == 0, ODE_ERROR_CONNECTION_REFUSED);
        InternalEncryptionClient internal = client.createInterface<InternalEncryptionClient>();
 
-       return toApiError(internal.mount());
+       return toApiError(internal.mount(std::vector<unsigned char>(), 0));
+}
+
+int ode_internal_encryption_mount_ex(const unsigned char *mk, unsigned int options)
+{
+       size_t key_len = options == 0 ? 32 : 64;
+       std::vector<unsigned char> key(mk, mk + key_len);
+       ClientContext client;
+       RET_ON_FAILURE(client.connect() == 0, ODE_ERROR_CONNECTION_REFUSED);
+       InternalEncryptionClient internal = client.createInterface<InternalEncryptionClient>();
+
+       return toApiError(internal.mount(key, options));
+}
+
+int ode_internal_encryption_is_mounted(bool *result)
+{
+       ClientContext client;
+       RET_ON_FAILURE(client.connect() == 0, ODE_ERROR_CONNECTION_REFUSED);
+       InternalEncryptionClient internal = client.createInterface<InternalEncryptionClient>();
+       int ret = internal.isMounted();
+       if (ret < 0)
+               return toApiError(ret);
+
+       *result = ret == 1 ? true : false;
+
+       return ODE_ERROR_NONE;
 }
 
 int ode_internal_encryption_umount()
index c55f531..3c1d074 100644 (file)
@@ -71,6 +71,41 @@ ODE_API int ode_internal_encryption_set_mount_password(const char* password);
 ODE_API int ode_internal_encryption_mount();
 
 /**
+ * @brief       Mount internal storage with encryption
+ * @details     Administrator can use this API to mount encrypted internal
+ *              storage.
+ * @since_tizen 4.0
+ * @param[in]   mk Master key used to mount internal storage
+ * @param[in]   options Mount options
+ * @return      #ODE_ERROR_NONE on success, otherwise a negative value
+ * @retval      #ODE_ERROR_NONE Successful
+ * @retval      #ODE_ERROR_NO_SUCH_DEVICE Internal storage is not encrypted
+ * @retval      #ODE_ERROR_NO_DATA Password isn't set
+ * @retval      #ODE_ERROR_PERMISSION_DENIED The application does not have
+ *              the privilege to call this API
+ * @retval      #ODE_ERROR_CONNECTION_REFUSED Connection to the server failed
+ * @retval      #ODE_ERROR_UNKNOWN Unknown error
+ * @see         ode_internal_encryption_umount()
+ */
+
+ODE_API int ode_internal_encryption_mount_ex(const unsigned char *mk, unsigned int option);
+
+/**
+ * @brief       Check whether the encrypted internal storage is mounted
+ * @details     Administrator can use this API to get the current mount state
+ *              of encrypted internal storage.
+ * @since_tizen 4.0
+ * @param[out]  result Whether the encrypted internal storage is mounted
+ * @return      #ODE_ERROR_NONE on success, otherwise a negative value
+ * @retval      #ODE_ERROR_NONE Successful
+ * @retval      #ODE_ERROR_INVALID_PARAMETER Invalid parameter
+ * @retval      #ODE_ERROR_CONNECTION_REFUSED Connection to the server failed
+ * @retval      #ODE_ERROR_UNKNOWN Unknown error
+ * @see         ode_internal_encryption_mount()
+ */
+ODE_API int ode_internal_encryption_is_mounted(bool *result);
+
+/**
  * @brief       Umount internal storage
  * @details     Administrator can use this API to unmount internal storage.
  * @since_tizen 4.0
@@ -330,7 +365,6 @@ ODE_API int ode_internal_encryption_unset_mount_event_cb();
  * @retval      #ODE_ERROR_UNKNOWN Unknown error
  */
 ODE_API int ode_internal_encryption_get_device_path(char** device);
-
 /*
  * @}
  */
index 3fbc762..dde5b9c 100755 (executable)
@@ -11,16 +11,20 @@ BuildRequires: gcc
 BuildRequires: cmake
 BuildRequires: gettext-tools
 BuildRequires: pkgconfig(klay)
+BuildRequires: pkgconfig(vconf)
 BuildRequires: pkgconfig(glib-2.0)
-BuildRequires: pkgconfig(aul)
-BuildRequires: pkgconfig(bundle)
 BuildRequires: pkgconfig(libtzplatform-config)
 BuildRequires: pkgconfig(cynara-client)
 BuildRequires: pkgconfig(libcrypto)
 BuildRequires: pkgconfig(libsmack)
+BuildRequires: pkgconfig(blkid)
+BuildRequires: pkgconfig(capi-system-device)
+BuildRequires: pkgconfig(libsystemd)
 Requires: cryptsetup
 
 %global key_storage_plugin_dir %{_libdir}/ode-key-storage-plugin/
+%global softreset_dir /usr/system/RestoreDir/softreset/
+%define upgrade_script_dir /usr/share/upgrade/scripts/
 
 %description
 The ode package provides a daemon which is responsible for encrypting/decryption storages and secure erasing.
@@ -32,9 +36,11 @@ The ode package provides a daemon which is responsible for encrypting/decryption
 %{_unitdir}/ode.service
 %{_unitdir}/multi-user.target.wants/ode.service
 %attr(700,root,root) %{TZ_SYS_SBIN}/ode-admin-cli
-%attr(700,root,root) %{TZ_SYS_SBIN}/ode-fota
+%attr(700,root,root) %{softreset_dir}/ode_softreset.sh
+%attr(750,root,system_share) %{TZ_SYS_SBIN}/ode-fota
 %{_datadir}/%{name}
 %dir %{key_storage_plugin_dir}
+%attr(755,root,root) %{upgrade_script_dir}/500.ode_upgrade.sh
 
 %prep
 %setup -q
@@ -55,7 +61,9 @@ The ode package provides a daemon which is responsible for encrypting/decryption
          -DSYSTEMD_UNIT_DIR=%{_unitdir} \
          -DAPP_INSTALL_PREFIX="%{TZ_SYS_RO_APP}" \
          -DAPP_SHARE_PACKAGES_DIR="%{TZ_SYS_RO_PACKAGES}" \
-         -DKEY_STORAGE_PLUGIN_DIR="%{key_storage_plugin_dir}"
+         -DSOFTRESET_DIR="%{softreset_dir}" \
+         -DKEY_STORAGE_PLUGIN_DIR="%{key_storage_plugin_dir}" \
+         -DUPGRADE_SCRIPT_DIR="%{upgrade_script_dir}"
 
 make %{?jobs:-j%jobs}
 
index b944090..cc904c9 100644 (file)
@@ -47,10 +47,10 @@ public:
        virtual int verifyPassword(const std::string& password) = 0;
 
        enum State {
-               Unencrypted = 0x00,
-               Encrypted   = 0x01,
-               Corrupted   = 0x02,
-               Invalid     = 0x03,
+               NotSupported = -1,
+               Unencrypted  = 0,
+               Encrypted    = 1,
+               Corrupted    = 2,
        };
 
        virtual int getState() = 0;
index c20f7f9..a38e25a 100644 (file)
@@ -18,6 +18,7 @@
 #define __INTERNAL_ENCRYPTION_H__
 
 #include <string>
+#include <vector>
 
 namespace ode {
 
@@ -31,8 +32,9 @@ public:
 
        virtual int setMountPassword(const std::string& password) = 0;
 
-       virtual int mount() = 0;
+       virtual int mount(const std::vector<unsigned char>& mk, unsigned int options) = 0;
        virtual int umount() = 0;
+       virtual int isMounted() = 0;
 
        virtual int encrypt(const std::string& password, unsigned int options) = 0;
        virtual int decrypt(const std::string& password) = 0;
@@ -46,10 +48,10 @@ public:
        virtual int verifyPassword(const std::string& password) = 0;
 
        enum State {
-               Unencrypted = 0x00,
-               Encrypted   = 0x01,
-               Corrupted   = 0x02,
-               Invalid     = 0x03,
+               NotSupported = -1,
+               Unencrypted  = 0,
+               Encrypted    = 1,
+               Corrupted    = 2,
        };
 
        virtual int getState() = 0;
index 9811434..395027f 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+# Copyright (c) 2015-2019 Samsung Electronics Co., Ltd All Rights Reserved
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 #
 SET(SERVER_SRCS        main.cpp
                                server.cpp
-                               launchpad.cpp
                                misc.cpp
                                ext4-tool.cpp
-                               app-bundle.cpp
                                file-footer.cpp
+                               file-sink.cpp
                                secure-erase.cpp
                                progress-bar.cpp
                                kernel-keyring.cpp
@@ -42,14 +41,15 @@ SET(SERVER_SRCS     main.cpp
 )
 
 SET(DEPENDENCY klay
+                               vconf
                                glib-2.0
                                gio-2.0
-                               aul
-                               bundle
                                libtzplatform-config
                                cynara-client
                                libcrypto
                                libsmack
+                               capi-system-device
+                               libsystemd
 )
 
 SET(SERVER_NAME ${PROJECT_NAME}d)
diff --git a/server/app-bundle.cpp b/server/app-bundle.cpp
deleted file mode 100644 (file)
index e4e9ea9..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
- *
- *  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
- */
-#include <memory>
-
-#include <klay/exception.h>
-
-#include "app-bundle.h"
-
-AppBundle::AppBundle() :
-       handle(nullptr)
-{
-       handle = ::bundle_create();
-       if (handle == nullptr) {
-               throw runtime::Exception("Failed to create bundle");
-       }
-}
-
-AppBundle::~AppBundle()
-{
-       ::bundle_free(handle);
-}
-
-void AppBundle::addInternal(const std::string& key, const std::string& value)
-{
-       ::bundle_add_str(handle, key.c_str(), value.c_str());
-}
-
-void AppBundle::addArrayInternal(const std::string& key, const std::vector<std::string>& array)
-{
-       std::unique_ptr<const char*[]> arrayptr(new const char*[array.size()]);
-
-       int index = 0;
-       for (const std::string& data : array) {
-               arrayptr.get()[index++] = data.c_str();
-       }
-
-       ::bundle_add_str_array(handle, key.c_str(), arrayptr.get(), array.size());
-}
diff --git a/server/app-bundle.h b/server/app-bundle.h
deleted file mode 100644 (file)
index 09fb8c8..0000000
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
- *
- *  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
- */
-
-#ifndef __DPM_APP_BUNDLE_H__
-#define __DPM_APP_BUNDLE_H__
-
-#include <string>
-#include <vector>
-
-#include <bundle.h>
-
-class AppBundle {
-public:
-       AppBundle();
-       ~AppBundle();
-
-       template<typename T>
-       void add(const std::string& key, const std::vector<T>& value)
-       {
-               addArrayInternal(key, value);
-       }
-
-       template<typename T>
-       void add(const std::string& key, const T& value)
-       {
-               addInternal(key, value);
-       }
-
-       bundle* get() const
-       {
-               return handle;
-       }
-
-private:
-       void addInternal(const std::string& key, const std::string& value);
-       void addArrayInternal(const std::string& key, const std::vector<std::string>& array);
-
-private:
-       bundle* handle;
-};
-
-#endif //__DPM_APP_BUNDLE_H__
index b0a5eae..c65e9db 100644 (file)
@@ -115,7 +115,7 @@ const std::string createCryptoBlkDev(const std::string &realBlkDev,
 
        // Create Device (mount_name)
        initDMIoctl(dmBuf, DM_MAX_BUFFER_SIZE, mountName, 0);
-       if (ioctl(fd, DM_DEV_CREATE, dmBuf)) {
+       if (ioctl(fd, DM_DEV_CREATE, dmBuf) && errno != EBUSY) {
                throw runtime::Exception("Cannot create dm-crypt device");
        }
 
@@ -285,7 +285,7 @@ void copyInPlace(const std::string &source, const std::string &destination,
 } // namepsace
 
 DMCryptEngine::DMCryptEngine(const std::string &src, const std::string &dest, const ProgressBar &prgsBar) :
-       source(src), destination(dest), progress(prgsBar)
+       source(src), destination(dest), progress(prgsBar), start(false)
 {
 }
 
@@ -304,7 +304,7 @@ void DMCryptEngine::mount(const BinaryData &key, unsigned int options)
 
 void DMCryptEngine::umount()
 {
-       if (::umount(destination.c_str()) && errno != EINVAL)
+       if (::umount(destination.c_str()) && errno != EINVAL && errno != ENOENT)
                throw runtime::Exception(runtime::GetSystemErrorMessage());
 
        destroyCryptoBlkDev(DM_DEFAULT_LABEL_NAME);
@@ -344,6 +344,7 @@ void DMCryptEngine::encrypt(const BinaryData &key, unsigned int options)
        // create crypto type device mapping layer to mount the plain partition
        // should be encrypted here.
        auto cryptoBlkDev = createCryptoBlkDev(source, DM_DEFAULT_LABEL_NAME, sanitizeKey(key), DM_DEFAULT_CRYPTO_NAME);
+       start = true;
 
        // We always do In-place encryption
        copyInPlace(source, cryptoBlkDev, options, progress);
@@ -364,6 +365,8 @@ void DMCryptEngine::decrypt(const BinaryData &key, unsigned int options)
        // Force filesystem check via fcsf might be able to avoid fail situation during decryption.
        Ext4Tool ext4CryptoBlkDev(cryptoBlkDev);
 
+       start = true;
+
        for (int retry = 0; retry < 32; retry++) {
                try {
                        ext4CryptoBlkDev.forceCleanUp();
index 1761598..a93260b 100644 (file)
@@ -44,6 +44,11 @@ public:
                return destination;
        }
 
+       bool isStarted()
+       {
+               return start;
+       }
+
        void mount(const BinaryData &key, unsigned int options);
        void umount();
        bool isMounted();
@@ -56,6 +61,7 @@ public:
 private:
        std::string source, destination;
        ProgressBar progress;
+       bool start;
 };
 
 } // namespace ode
index 261a097..82f9f30 100644 (file)
@@ -28,8 +28,6 @@
 
 #include "misc.h"
 #include "logger.h"
-#include "launchpad.h"
-#include "app-bundle.h"
 #include "progress-bar.h"
 #include "rmi/common.h"
 #include "file-footer.h"
@@ -50,11 +48,14 @@ void spawnUI()
 {
        INFO(SINK, "Launching SD card password popup.");
        try {
-               AppBundle bundle;
-               bundle.add("viewtype", "SD_CARD_PASSWORD");
-
-               Launchpad launchpad(::tzplatform_getuid(TZ_SYS_DEFAULT_USER));
-               launchpad.launch("org.tizen.ode", bundle);
+               dbus::Connection &systemDBus = dbus::Connection::getSystem();
+               std::string unit("ode-password@external.service");
+
+               systemDBus.methodcall("org.freedesktop.systemd1",
+                                                               "/org/freedesktop/systemd1",
+                                                               "org.freedesktop.systemd1.Manager",
+                                                               "StartUnit",
+                                                               -1, "", "(ss)", unit.c_str(), "replace");
        } catch (runtime::Exception &e) {
                ERROR(SINK, "Failed to launch SD card password popup: " + std::string(e.what()));
        }
@@ -135,8 +136,8 @@ void externalAddEventReceiver()
                                                                externalCallback);
 
        systemDBus.subscribeSignal("",
-                                                               "/Org/Tizen/System/Pass/Core",
-                                                               "org.tizen.system.pass.core",
+                                                               "/Org/Tizen/System/DeviceD/Core",
+                                                               "org.tizen.system.deviced.core",
                                                                "BootingDone",
                                                                bootCompletionCallback);
 }
@@ -429,7 +430,7 @@ int ExternalEncryptionServer::getState()
        else if (valueStr == "error_partially_encrypted" || valueStr == "error_partially_decrypted")
                return State::Corrupted;
 
-       return State::Invalid;
+       return State::NotSupported;
 }
 
 unsigned int ExternalEncryptionServer::getSupportedOptions()
index b81c14f..7531db4 100644 (file)
@@ -79,7 +79,12 @@ void FileFooter::write(const std::string &key, const BinaryData &value)
 
        runtime::File file(fileName);
 
-       file.create(S_IRUSR | S_IWUSR);
+       if (!file.exists()) {
+               file.create(S_IRUSR | S_IWUSR);
+       } else {
+               file.open(O_RDWR);
+       }
+
        file.write(value.data(), value.size());
 }
 
diff --git a/server/file-sink.cpp b/server/file-sink.cpp
new file mode 100644 (file)
index 0000000..091b69b
--- /dev/null
@@ -0,0 +1,158 @@
+/*
+ *  Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ *  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
+ */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <iostream>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <chrono>
+#include <errno.h>
+
+#include "file-sink.h"
+
+namespace ode {
+
+#define MAX_LOG_LEN 16
+
+namespace {
+std::string getFileName(const std::string &path)
+{
+       std::string name;
+       auto pos = path.rfind('/');
+       pos = (pos == std::string::npos) ? 0 : pos + 1;
+       name = path.substr(pos, path.size());
+       return name;
+}
+} //namespace
+
+FileLogSink::FileLogSink(const std::string& name)
+       : path("/opt/var/log/"), fd(-1)
+{
+       path.append(getFileName(name));
+       fd = ::open(path.c_str(), O_CREAT | O_RDWR | O_APPEND | O_SYNC, 0664);
+}
+
+FileLogSink::~FileLogSink()
+{
+       ::close(fd);
+}
+
+void FileLogSink::resize()
+{
+       std::lock_guard<std::recursive_mutex> lock(mtx);
+       struct stat st;
+       int ret = 0;
+       int blkcnt = MAX_LOG_LEN;
+       size_t blksize = 0;
+
+       if (::lstat(path.c_str(), &st) < 0) {
+               std::cerr << "Invalid log file" << std::endl;
+               return;
+       }
+
+       blksize = st.st_blksize;
+       if (blksize > 0)
+               blkcnt = (st.st_size / blksize) + 1;
+
+       if (blkcnt <= MAX_LOG_LEN)
+               return;
+
+       ret = ::fallocate(fd, FALLOC_FL_COLLAPSE_RANGE, 0, blksize*(blkcnt-MAX_LOG_LEN));
+       if (ret < 0)
+               std::cerr << "Failed to collapse the log file : " << errno << std::endl;
+}
+
+void FileLogSink::write(const std::string &message)
+{
+       std::lock_guard<std::recursive_mutex> lock(mtx);
+       resize();
+
+       auto now = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now());
+       std::tm tm = {
+               .tm_sec = 0,
+               .tm_min = 0,
+               .tm_hour = 0,
+               .tm_mday = 1,
+               .tm_mon = 1,
+               .tm_year = 0,
+               .tm_wday = 0,
+               .tm_yday = 0,
+               .tm_isdst = 1,
+       };
+
+       if (::localtime_r(&now, &tm) == nullptr)
+               std::cerr << "Failed to get local time" << std::endl;
+
+       std::string log("[" + std::to_string(tm.tm_hour)
+                       + ":"
+                       + std::to_string(tm.tm_min)
+                       + ":"
+                       + std::to_string(tm.tm_sec) + "] ");
+
+       log.append(message);
+
+       size_t written = 0, size = log.size();
+       const char *data = log.c_str();
+
+       while (written < size) {
+               int bytes = ::write(fd, data + written, size-written);
+               if (bytes >= 0) {
+                       written += bytes;
+               } else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) {
+                       continue;
+               } else {
+                       std::cerr << "Failed to write log" << std::endl;
+                       break;
+               }
+       }
+       ::sync();
+}
+
+void FileLogSink::sink(const std::string &message)
+{
+       auto level = message.substr(0, message.find('<'));
+       auto subMsg = message.substr(message.find(':') + 1);
+       std::string log;
+
+       switch (audit::StringToLogLevel(level)) {
+       case audit::LogLevel::Error:
+               log.append("[ERROR] : " + subMsg);
+               break;
+       case audit::LogLevel::Warning:
+               log.append("[WARN] : " + subMsg);
+               break;
+       case audit::LogLevel::Debug:
+               log.append("[DEBUG] : " + subMsg);
+               break;
+       case audit::LogLevel::Info:
+               log.append("[INFO] : " + subMsg);
+               break;
+       case audit::LogLevel::Trace:
+               log.append("[TRACE] : " + subMsg);
+               break;
+       default:
+               log.append("[SILENT] : " + subMsg);
+               break;
+       }
+
+       write(log);
+}
+
+} //namespace ode
similarity index 52%
rename from server/launchpad.h
rename to server/file-sink.h
index 3726ee3..9fac15e 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2018 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
  *  limitations under the License
  */
 
-#ifndef __DPM_LAUNCHPAD_H__
-#define __DPM_LAUNCHPAD_H__
+#ifndef __ODE_FILE_LOGSINK_H__
+#define __ODE_FILE_LOGSINK_H__
 
 #include <string>
+#include <memory>
+#include <mutex>
 
-#include "app-bundle.h"
+#include <klay/filesystem.h>
+#include <klay/audit/logger.h>
 
-class Launchpad {
+namespace ode {
+
+class FileLogSink : public audit::LogSink {
 public:
-       Launchpad(const uid_t uid = 0);
-       Launchpad(const Launchpad&) = delete;
-       Launchpad(Launchpad&&) = delete;
+       explicit FileLogSink(const std::string& tag);
+       ~FileLogSink();
+       void sink(const std::string& message) override;
 
-       void launch(const std::string& appid);
-       void launch(const std::string& appid, const AppBundle& bundle);
-       void resume(const std::string& appid);
-       bool isRunning(const std::string& appid);
-       void terminate(const std::string& appid);
+private:
+       void resize();
+       void write(const std::string &message);
 
 private:
-       uid_t user;
+       std::string path;
+       int fd;
+       std::recursive_mutex mtx;
 };
 
-#endif //__DPM_LAUNCHPAD_H__
+} //namespace ode
+
+#endif //__ODE_FILE_LOGSINK_H__
index 0abbf17..4861738 100644 (file)
@@ -1,5 +1,5 @@
 /*
- *  Copyright (c) 2015-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ *  Copyright (c) 2015-2019 Samsung Electronics Co., Ltd All Rights Reserved
  *
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
 #include <unistd.h>
 #include <sys/mount.h>
 #include <sys/reboot.h>
+#include <sys/wait.h>
 #include <limits.h>
 #include <stdlib.h>
 #include <string.h>
 
 #include <vconf.h>
 #include <tzplatform_config.h>
+#include <device/power.h>
 #include <klay/process.h>
 #include <klay/file-user.h>
 #include <klay/filesystem.h>
 #include <klay/dbus/connection.h>
+#include <klay/dbus/signal.h>
 #include <klay/error.h>
+#include <systemd/sd-bus.h>
 
 #include "misc.h"
 #include "logger.h"
@@ -46,6 +50,8 @@
 #include "ext4-tool.h"
 #include "internal-encryption.h"
 #include "internal-encryption-common.h"
+#include "upgrade-support.h"
+#include "file-footer.h"
 
 namespace ode {
 
@@ -53,6 +59,16 @@ namespace {
 
 const char *PRIVILEGE_PLATFORM = "http://tizen.org/privilege/internal/default/platform";
 const mode_t MODE_0640 = S_IRUSR | S_IWUSR | S_IRGRP;
+const std::string ODE_OBJECT_PATH = "/Org/Tizen/OnDeviceEncryption";
+const std::string ODE_INTERFACE_EVENT = "org.tizen.OnDeviceEncryption.Event";
+const std::string ODE_SIGNAL_NAME = "unmount";
+const std::string manifest =
+       "<node>"
+       "       <interface name='" + ODE_INTERFACE_EVENT + "'>"
+       "       <signal name='" + ODE_SIGNAL_NAME + "'>"
+       "       </signal>"
+       "       </interface>"
+       "</node>";
 
 // watches systemd jobs
 class JobWatch {
@@ -102,7 +118,19 @@ JobWatch::~JobWatch() {
 bool JobWatch::waitForJob(const std::string& job) {
        while(true) {
                std::unique_lock<std::mutex> lock(jobsMutex);
-               jobsCv.wait(lock, [this]{ return !removedJobs.empty(); });
+               bool timeout = true;
+               auto sec = std::chrono::seconds(1);
+               jobsCv.wait_for(lock, 5*sec, [this, &timeout]{
+                               if (!removedJobs.empty()) {
+                                       timeout = false;
+                                       return true;
+                               }
+                               return false;});
+
+               if (timeout) {
+                       ERROR(SINK, "job: " + job + ", result: time out");
+                       return false;
+               }
 
                while(!removedJobs.empty()) {
                        bool match = (removedJobs.front().job == job);
@@ -121,7 +149,7 @@ void JobWatch::jobRemoved(const dbus::Variant& parameters)
        const char* unit;
        const char* result;
        parameters.get("(uoss)", &id, &job, &unit, &result);
-       INFO(SINK, "id:" + std::to_string(id) + " job:" + job + " unit:" + unit + " result:" + result);
+       WARN(SINK, "id:" + std::to_string(id) + " job:" + job + " unit:" + unit + " result:" + result);
 
        {
                std::lock_guard<std::mutex> guard(jobsMutex);
@@ -130,94 +158,112 @@ void JobWatch::jobRemoved(const dbus::Variant& parameters)
        jobsCv.notify_one();
 }
 
-void stopKnownSystemdUnits()
+void stopSystemdUnits()
 {
-       std::vector<std::string> knownSystemdUnits;
        dbus::Connection& systemDBus = dbus::Connection::getSystem();
        dbus::VariantIterator iter;
+       std::vector<std::string> preprocessUnits;
+       std::set<std::string> unitsToStop;
 
-       systemDBus.methodcall("org.freedesktop.systemd1",
-                                                       "/org/freedesktop/systemd1",
-                                                       "org.freedesktop.systemd1.Manager",
-                                                       "ListUnits",
-                                                       -1, "(a(ssssssouso))", "")
-                                                               .get("(a(ssssssouso))", &iter);
+       try {
+               systemDBus.emitSignal("",
+                                               ODE_OBJECT_PATH,
+                                               ODE_INTERFACE_EVENT,
+                                               ODE_SIGNAL_NAME, "()", nullptr);
+       } catch (runtime::Exception &e) {
+               ERROR(SINK, "Failed to emit signal : " + std::string(e.what()));
+       }
+
+       auto stopUnit = [&systemDBus](const std::string &unit) {
+               JobWatch watch(systemDBus);
+               WARN(SINK, "Stopping unit: " + unit);
+               const char* job = NULL;
+               try {
+                       systemDBus.methodcall("org.freedesktop.systemd1",
+                                                                       "/org/freedesktop/systemd1",
+                                                                       "org.freedesktop.systemd1.Manager",
+                                                                       "StopUnit",
+                                                                       -1, "(o)", "(ss)", unit.c_str(), "flush").get("(o)", &job);
+                       WARN(SINK, "Waiting for job: " + std::string(job));
+                       if (!watch.waitForJob(job))
+                               ERROR(SINK, "Stopping unit: " + unit + " failed");
+               } catch (runtime::Exception &e) {
+                       ERROR(SINK, std::string(e.what()));
+               }
+       };
+
+       try {
+               systemDBus.methodcall("org.freedesktop.systemd1",
+                                                               "/org/freedesktop/systemd1",
+                                                               "org.freedesktop.systemd1.Manager",
+                                                               "ListUnits",
+                                                               -1, "(a(ssssssouso))", "").get("(a(ssssssouso))", &iter);
+       } catch (runtime::Exception &e) {
+               ERROR(SINK, "Get list of systemd unit : " + std::string(e.what()));
+       }
 
        while (1) {
-               unsigned int dataUint;
+               unsigned int dataUnit;
                char *dataStr[9];
                int ret;
-
                ret = iter.get("(ssssssouso)", dataStr, dataStr + 1, dataStr + 2,
                                                dataStr + 3, dataStr + 4, dataStr + 5,
-                                               dataStr + 6, &dataUint, dataStr + 7,
-                                               dataStr + 8);
-
-               if (!ret) {
+                                               dataStr + 6, &dataUnit, dataStr + 7, dataStr + 8);
+               if (!ret)
                        break;
-               }
 
-               std::string unit(dataStr[0]);
-               if (unit == "security-manager.socket") {
-                       knownSystemdUnits.insert(knownSystemdUnits.begin(), unit);
-               } else if (unit.compare(0, 5, "user@") == 0 ||
-                       unit == "tlm.service" ||
-                       unit == "resourced.service" ||
-                       unit == "security-manager.service") {
-                       knownSystemdUnits.push_back(unit);
+               std::string unitName(dataStr[0]);
+               if (unitName == "security-manager.socket" ||
+                               unitName == "connman.socket" ||
+                               unitName == "msg-server.socket") {
+                       preprocessUnits.insert(preprocessUnits.begin(), unitName);
+               } else if (unitName.compare(0, 5, "user@") == 0 ||
+                               unitName == "tlm.service" ||
+                               unitName == "resourced.service" ||
+                               unitName == "security-manager.service") {
+                       preprocessUnits.push_back(unitName);
                }
        }
 
-       JobWatch watch(systemDBus);
-
-       for (const std::string& unit : knownSystemdUnits) {
-               INFO(SINK, "Stopping unit: " + unit);
-               const char* job = NULL;
-               systemDBus.methodcall("org.freedesktop.systemd1",
-                                                               "/org/freedesktop/systemd1",
-                                                               "org.freedesktop.systemd1.Manager",
-                                                               "StopUnit",
-                                                               -1, "(o)", "(ss)", unit.c_str(), "flush").get("(o)", &job);
-               INFO(SINK, "Waiting for job: " + std::string(job));
-               if (!watch.waitForJob(job))
-                       throw runtime::Exception("Stopping unit: " + unit + " failed");
+       for (auto unit : preprocessUnits) {
+               stopUnit(unit);
        }
-}
-
-void stopDependedSystemdUnits()
-{
-       dbus::Connection& systemDBus = dbus::Connection::getSystem();
-       std::set<std::string> unitsToStop;
 
        for (pid_t pid : runtime::FileUser::getList(INTERNAL_PATH, true)) {
+               auto pgid = ::getpgid(pid);
+               if (pgid > 0 && pid != pgid) {
+                       WARN(SINK, "PGID doesn't match - pgid : " + std::to_string(pgid) + ", pid : " + std::to_string(pid));
+                       continue;
+               }
+
                try {
-                       char *unit;
+                       char *unit = nullptr;
                        systemDBus.methodcall("org.freedesktop.systemd1",
                                                                        "/org/freedesktop/systemd1",
                                                                        "org.freedesktop.systemd1.Manager",
                                                                        "GetUnitByPID",
                                                                        -1, "(o)", "(u)", (unsigned int)pid)
                                                                                .get("(o)", &unit);
-                       unitsToStop.insert(unit);
+
+                       char* tmp  = NULL;
+                       int err = sd_bus_path_decode(unit, "/org/freedesktop/systemd1/unit", &tmp);
+                       if (err <= 0 || tmp == NULL) {
+                               ERROR(SINK, "Failed to decode unit name: " + std::string(unit) + " error: " +
+                                           std::to_string(err));
+                               continue;
+                       }
+                       std::string unescapedName(tmp);
+                       free(tmp);
+
+                       unitsToStop.insert(unescapedName);
                } catch (runtime::Exception &e) {
-                       INFO(SINK, "Killing process: " + std::to_string(pid));
+                       ERROR(SINK, "Killing process: " + std::to_string(pid));
                        ::kill(pid, SIGKILL);
                }
        }
 
-       JobWatch watch(systemDBus);
-
-       for (const std::string& unit : unitsToStop) {
-               INFO(SINK, "Stopping unit: " + unit);
-               const char* job = NULL;
-               systemDBus.methodcall("org.freedesktop.systemd1",
-                                                               unit,
-                                                               "org.freedesktop.systemd1.Unit",
-                                                               "Stop",
-                                                               -1, "(o)", "(s)", "flush").get("(o)", &job);
-               INFO(SINK, "Waiting for job: " + std::string(job));
-               if (!watch.waitForJob(job))
-                       throw runtime::Exception("Stopping unit: " + unit + " failed");
+       for (auto unit : unitsToStop) {
+               stopUnit(unit);
        }
 }
 
@@ -238,7 +284,7 @@ void showProgressUI(const std::string type)
 
        INFO(SINK, "Waiting for job: " + std::string(job));
        if (!watch.waitForJob(job))
-               throw runtime::Exception("Starting unit: " + unit + " failed");
+               ERROR(SINK, "Starting unit: " + unit + " failed");
 }
 
 unsigned int getOptions()
@@ -267,38 +313,128 @@ void setOptions(unsigned int options)
        ::vconf_set_bool(VCONFKEY_ODE_FAST_ENCRYPTION, value);
 }
 
-void unmountInternalStorage(const std::string& source)
+void killProcesses(std::vector<const char*> &args)
 {
-       while(true) {
-               auto mntPaths = findMountPointsByDevice(source);
-               if(mntPaths.empty())
-                       break;
+       int pipeFd[2] = {0, };
+       pid_t pid = 0;
 
-               bool unmounted = true;
-               for(const auto& path : mntPaths) {
-                       INFO(SINK, "Unmounting " + path);
-                       if (::umount(path.c_str()) == -1) {
-                               // If it's busy or was already unmounted ignore the error
-                               if (errno != EBUSY && errno != EINVAL) {
-                                       throw runtime::Exception("umount() error: " + runtime::GetSystemErrorMessage());
-                               }
-                               unmounted = false;
-                       }
+       if (::pipe(pipeFd) < 0)
+               throw runtime::Exception("Failed to create pipe");
+
+       pid = ::fork();
+       if (pid < 0) {
+               ::close(pipeFd[0]);
+               ::close(pipeFd[1]);
+               throw runtime::Exception("Failed to fork");
+       }
+
+       if (pid == 0) {
+               ::close(pipeFd[0]);
+               if (::dup2(pipeFd[1], STDOUT_FILENO) < 0)
+                       ERROR(SINK, "Failed to copy STDOUT_FILENO");
+
+               if (::dup2(STDOUT_FILENO, STDERR_FILENO) < 0)
+                       ERROR(SINK, "Failed to copy STDERR_FILENO");
+
+               ::close(pipeFd[1]);
+
+               if (::execv(args[0], const_cast<char* const*>(args.data())) < 0)
+                       ERROR(SINK, "Failed to execute : " + std::to_string(errno));
+
+               std::quick_exit(EXIT_FAILURE);
+       }
+
+       ::close(pipeFd[1]);
+
+       for (int status = 0; ::waitpid(pid, &status, 0) == -1;) {
+               if (errno != EINTR) {
+                       ::close(pipeFd[0]);
+                       throw runtime::Exception("Failed to wait child process");
+               }
+       }
+
+       auto closeFile = [](FILE *fp) { ::fclose(fp); };
+       std::unique_ptr<FILE, decltype(closeFile)> fp(::fdopen(pipeFd[0], "r"), closeFile);
+       if (fp == nullptr) {
+               ::close(pipeFd[0]);
+               throw runtime::Exception("Failed to open pipe descriptor");
+       }
+
+       char *line = nullptr;
+       size_t len = 0;
+       try {
+               while ((::getline(&line, &len, fp.get())) != -1) {
+                       std::string log(line);
+                       log.erase(std::find_if(log.rbegin(), log.rend(),
+                                               std::ptr_fun<int, int>(std::isgraph)).base(), log.end());
+                       WARN(SINK, log);
                }
-               if (!unmounted)
-                       stopDependedSystemdUnits();
+       } catch (std::exception &e) {
+               ERROR(SINK, e.what());
        }
+       ::free(line);
+       ::close(pipeFd[0]);
 }
 
+bool isPartitionTerminated(const std::string &partition)
+{
+       bool ret = true;
+       const std::string cmd("fuser -m " + partition + " | grep -o '[0-9]*'");
+       char *line = nullptr;
+       size_t len = 0;
+
+       FILE *fp = ::popen(cmd.c_str(), "r");
+       if (fp == nullptr) {
+               ERROR(SINK, "Failed to get processes on partition");
+               return false;
+       }
+
+       if (::getline(&line, &len, fp) != -1)
+               ret = false;
+
+       ::free(line);
+       ::pclose(fp);
+
+       return ret;
 }
 
-InternalEncryptionServer::InternalEncryptionServer(ServerContext& srv, KeyServer& key) :
+void unmountInternalStorage(const std::string& source)
+{
+       if (::umount2("/opt/usr", MNT_DETACH) == -1) {
+               if (errno != EBUSY && errno != EINVAL) {
+                       throw runtime::Exception("umount() error : " + runtime::GetSystemErrorMessage());
+               }
+       }
+
+       do {
+               ::sync();
+               std::vector<const char*> args = {
+                       "/usr/bin/fuser", "-m", "-k", "-v", "-SIGTERM", source.c_str(), nullptr
+               };
+               try {
+                       killProcesses(args);
+                       ::usleep((useconds_t)((unsigned int)(500)*1000));
+
+                       args[4] = "-SIGKILL";
+                       killProcesses(args);
+                       ::usleep((useconds_t)((unsigned int)(200)*1000));
+               } catch (runtime::Exception &e) {
+                       ERROR(e.what());
+               }
+       } while (!isPartitionTerminated(source));
+}
+
+}
+
+InternalEncryptionServer::InternalEncryptionServer(ServerContext& srv,
+                                                                                                  KeyServer& key) :
        server(srv),
        keyServer(key)
 {
        server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::setMountPassword)(std::string));
-       server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::mount)());
+       server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::mount)(std::vector<unsigned char>, unsigned int));
        server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::umount)());
+       server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::isMounted)());
        server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::encrypt)(std::string, unsigned int));
        server.expose(this, PRIVILEGE_PLATFORM, (int)(InternalEncryptionServer::decrypt)(std::string));
        server.expose(this, "", (int)(InternalEncryptionServer::isPasswordInitialized)());
@@ -315,6 +451,14 @@ InternalEncryptionServer::InternalEncryptionServer(ServerContext& srv, KeyServer
 
        std::string source = findDevPath();
 
+       if (getState() == State::Encrypted) {
+               //"error_partially_encrypted"
+               if (!FileFooter::exist(source) && !UpgradeSupport::checkUpgradeFlag()) {
+                       // Trigger key migration process
+                       UpgradeSupport::createUpgradeFlag();
+               }
+       }
+
        engine.reset(new INTERNAL_ENGINE(
                source, INTERNAL_PATH,
                ProgressBar([](unsigned v) {
@@ -322,34 +466,67 @@ InternalEncryptionServer::InternalEncryptionServer(ServerContext& srv, KeyServer
                                                        std::to_string(v).c_str());
                })
        ));
+
+       try {
+               dbus::Connection &systemDBus = dbus::Connection::getSystem();
+               systemDBus.registerObject(ODE_OBJECT_PATH, manifest, nullptr, nullptr);
+       } catch (runtime::Exception &e) {
+               ERROR(SINK, e.what());
+       }
 }
 
 InternalEncryptionServer::~InternalEncryptionServer()
 {
 }
 
+int InternalEncryptionServer::migrateMasterKey(const std::string& dev, const std::string& password)
+{
+       try {
+               BinaryData masterKey = UpgradeSupport::loadMasterKey(dev);
+
+               // encrypt the master key with given password
+               return keyServer.changePassword2(dev, masterKey, password);
+       } catch (const runtime::Exception&) {
+               ERROR(SINK, "Failed to load the master key stored during upgrade.");
+       }
+
+       return error::Unknown;
+}
+
 int InternalEncryptionServer::setMountPassword(const std::string& password)
 {
-       return keyServer.get(engine->getSource(), password, mountKey);
+       const std::string& dev = engine->getSource();
+
+       // check if upgrade flag exists
+       if (UpgradeSupport::checkUpgradeFlag()) {
+               INFO(SINK, "Upgrade flag detected.");
+
+               int rc = migrateMasterKey(dev, password);
+               if (rc != error::None)
+                       return rc;
+               UpgradeSupport::removeUpgradeFlag();
+       }
+
+       return keyServer.get(dev, password, mountKey);
 }
 
-int InternalEncryptionServer::mount()
+int InternalEncryptionServer::mount(const std::vector<unsigned char> &mk, unsigned int options)
 {
-       if (mountKey.empty()) {
-               ERROR(SINK, "You need to call set_mount_password() first.");
+       if (mountKey.empty() && mk.empty()) {
+               ERROR(SINK, "You need to set master key first.");
                return error::NoData;
        }
 
-       BinaryData key = mountKey;
+       BinaryData key = mk.empty() ? mountKey : mk;
        mountKey.clear();
 
        if (getState() != State::Encrypted) {
-               INFO(SINK, "Cannot mount, SD partition's state incorrect.");
+               ERROR(SINK, "Cannot mount, SD partition's state incorrect.");
                return error::NoSuchDevice;
        }
 
        if (engine->isMounted()) {
-               INFO(SINK, "Partition already mounted.");
+               ERROR(SINK, "Partition already mounted.");
                return error::None;
        }
 
@@ -358,6 +535,9 @@ int InternalEncryptionServer::mount()
                engine->mount(key, getOptions());
 
                server.notify("InternalEncryptionServer::mount");
+
+               runtime::File("/tmp/.lazy_mount").create(O_WRONLY);
+               runtime::File("/tmp/.unlock_mnt").create(O_WRONLY);
        } catch (runtime::Exception &e) {
                ERROR(SINK, "Mount failed: " + std::string(e.what()));
                return error::Unknown;
@@ -366,6 +546,18 @@ int InternalEncryptionServer::mount()
        return error::None;
 }
 
+int InternalEncryptionServer::isMounted()
+{
+       int ret = 0;
+       try {
+               ret = engine->isMounted() ? 1 : 0;
+       } catch (runtime::Exception &e) {
+               ERROR(SINK, "Failed to access the mount flag");
+               return error::Unknown;
+       }
+       return ret;
+}
+
 int InternalEncryptionServer::umount()
 {
        if (getState() != State::Encrypted) {
@@ -374,14 +566,15 @@ int InternalEncryptionServer::umount()
        }
 
        if (!engine->isMounted()) {
-               INFO(SINK, "Partition already umounted.");
+               ERROR(SINK, "Partition already umounted.");
                return error::None;
        }
 
        INFO(SINK, "Closing all processes using internal storage.");
        try {
-               stopDependedSystemdUnits();
+               stopSystemdUnits();
                INFO(SINK, "Umounting internal storage.");
+               unmountInternalStorage("/dev/mapper/userdata");
                engine->umount();
        } catch (runtime::Exception &e) {
                ERROR(SINK, "Umount failed: " + std::string(e.what()));
@@ -405,21 +598,21 @@ int InternalEncryptionServer::encrypt(const std::string& password, unsigned int
 
        auto encryptWorker = [masterKey, options, this]() {
                try {
+                       if (::device_power_request_lock(POWER_LOCK_DISPLAY, 0) != 0)
+                               ERROR(SINK, "Failed to request to lock display");
+
                        showProgressUI("encrypt");
                        ::sleep(1);
 
                        runtime::File file("/opt/etc/.odeprogress");
                        file.create(MODE_0640);
 
-                       INFO(SINK, "Closing all known systemd services that might be using internal storage.");
-                       stopKnownSystemdUnits();
-
                        std::string source = engine->getSource();
                        auto mntPaths = findMountPointsByDevice(source);
 
                        if (!mntPaths.empty()) {
                                INFO(SINK, "Closing all processes using internal storage.");
-                               stopDependedSystemdUnits();
+                               stopSystemdUnits();
 
                                INFO(SINK, "Unmounting internal storage.");
                                unmountInternalStorage(source);
@@ -427,7 +620,17 @@ int InternalEncryptionServer::encrypt(const std::string& password, unsigned int
 
                        INFO(SINK, "Encryption started.");
                        ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "error_partially_encrypted");
-                       engine->encrypt(masterKey, options);
+                       try {
+                               engine->encrypt(masterKey, options);
+                       } catch (runtime::Exception &e) {
+                               ERROR(SINK, e.what());
+                               if (!engine->isStarted()) {
+                                       ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "unencrypted");
+                                       file.remove();
+                               }
+                               ::sync();
+                               ::reboot(RB_AUTOBOOT);
+                       }
                        setOptions(options & getSupportedOptions());
 
                        INFO(SINK, "Encryption completed.");
@@ -457,6 +660,15 @@ int InternalEncryptionServer::decrypt(const std::string& password)
                return error::NoSuchDevice;
        }
 
+       // check if key migration is needed
+       if (UpgradeSupport::checkUpgradeFlag()) {
+               INFO(SINK, "Upgrade flag detected.");
+               const std::string& dev = engine->getSource();
+               int rc = migrateMasterKey(dev, password);
+               if (rc == error::None)
+                       UpgradeSupport::removeUpgradeFlag();
+       }
+
        BinaryData masterKey;
        int ret = keyServer.get(engine->getSource(), password, masterKey);
        if (ret != error::None)
@@ -464,6 +676,9 @@ int InternalEncryptionServer::decrypt(const std::string& password)
 
        auto decryptWorker = [masterKey, this]() {
                try {
+                       if (::device_power_request_lock(POWER_LOCK_DISPLAY, 0) != 0)
+                               ERROR(SINK, "Failed to request to lock display");
+
                        showProgressUI("decrypt");
                        ::sleep(1);
 
@@ -471,25 +686,27 @@ int InternalEncryptionServer::decrypt(const std::string& password)
                        file.create(MODE_0640);
 
                        if (engine->isMounted()) {
-                               INFO(SINK, "Closing all known systemd services that might be using internal storage.");
-                               stopKnownSystemdUnits();
                                INFO(SINK, "Closing all processes using internal storage.");
-                               stopDependedSystemdUnits();
+                               stopSystemdUnits();
 
                                INFO(SINK, "Umounting internal storage.");
-                               while (1) {
-                                       try {
-                                               engine->umount();
-                                               break;
-                                       } catch (runtime::Exception& e) {
-                                               stopDependedSystemdUnits();
-                                       }
-                               }
+                               unmountInternalStorage("/dev/mapper/userdata");
+                               engine->umount();
                        }
 
                        INFO(SINK, "Decryption started.");
                        ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "error_partially_decrypted");
-                       engine->decrypt(masterKey, getOptions());
+                       try {
+                               engine->decrypt(masterKey, getOptions());
+                       } catch (runtime::Exception &e) {
+                               ERROR(SINK, e.what());
+                               if (!engine->isStarted()) {
+                                       ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "encrypted");
+                                       file.remove();
+                               }
+                               ::sync();
+                               ::reboot(RB_AUTOBOOT);
+                       }
 
                        INFO(SINK, "Decryption complete.");
                        ::vconf_set_str(VCONFKEY_ODE_CRYPTO_STATE, "unencrypted");
@@ -517,9 +734,6 @@ int InternalEncryptionServer::recovery()
        if (state == State::Unencrypted)
                return error::NoSuchDevice;
 
-       if (state == State::Corrupted)
-               Ext4Tool::mkfs(engine->getSource());
-
        runtime::File file("/opt/.factoryreset");
        file.create(MODE_0640);
 
@@ -580,7 +794,7 @@ int InternalEncryptionServer::getState()
        else if (valueStr == "error_partially_encrypted" || valueStr == "error_partially_decrypted")
                return State::Corrupted;
 
-       return State::Invalid;
+       return State::NotSupported;
 }
 
 unsigned int InternalEncryptionServer::getSupportedOptions()
index f5e59ef..488fac9 100644 (file)
@@ -36,8 +36,9 @@ public:
 
        int setMountPassword(const std::string& password);
 
-       int mount();
+       int mount(const std::vector<unsigned char> &mk, unsigned int options);
        int umount();
+       int isMounted();
 
        int encrypt(const std::string& password, unsigned int options);
        int decrypt(const std::string& password);
@@ -57,6 +58,9 @@ public:
        std::string getDevicePath() const;
 
 private:
+       int migrateMasterKey(const std::string& dev, const std::string& password);
+
+private:
        ServerContext& server;
 
        std::unique_ptr<INTERNAL_ENGINE> engine;
index 3c5816f..2e2abc0 100644 (file)
@@ -76,10 +76,12 @@ BinaryData AESEncrypt(const BinaryData& in,
                                          const BinaryData& iv)
 {
        BinaryData ret(in.size(), 0);
-       EVP_CIPHER_CTX* ctx;
+       EVP_CIPHER_CTX* ctx = nullptr;
        int outLen, len;
 
        ctx = ::EVP_CIPHER_CTX_new();
+       if (ctx == nullptr)
+               throw runtime::Exception("Failed to allocate memory for chipher context");
 
        ::EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key.data(), iv.data());
 
@@ -100,11 +102,13 @@ BinaryData AESDecrypt(const BinaryData& in,
                                          const BinaryData& iv)
 {
        BinaryData ret(in.size(), 0);
-       EVP_CIPHER_CTX* ctx;
+       EVP_CIPHER_CTX* ctx = nullptr;
 
        int len, len1;
 
        ctx = ::EVP_CIPHER_CTX_new();
+       if (ctx == nullptr)
+               throw runtime::Exception("Failed to allocate memory for chipher context");
 
        ::EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key.data(), iv.data());
        ::EVP_CIPHER_CTX_set_padding(ctx, 0);
index 4ab6541..0a07ea5 100644 (file)
@@ -114,6 +114,7 @@ int KeyServer::changePassword(const std::string& dev,
                                                          const std::string& curPassword,
                                                          const std::string& newPassword)
 {
+
        if (dev.empty() || curPassword.empty() || newPassword.empty())
                return error::InvalidParameter;
 
@@ -134,6 +135,23 @@ int KeyServer::changePassword(const std::string& dev,
        ek.encrypt(key, newPassword);
 
        FileFooter::write(dev, ek.serialize());
+
+       UpgradeSupport::removeUpgradeFlag();
+
+       return error::None;
+}
+
+int KeyServer::changePassword2(const std::string& dev,
+                                                          const BinaryData& masterKey,
+                                                          const std::string& newPassword)
+{
+       if (dev.empty() || masterKey.empty() || newPassword.empty())
+               return error::InvalidParameter;
+
+       std::lock_guard<std::mutex> lock(footerLock);
+       EncryptedKey ek(masterKey, newPassword);
+
+       FileFooter::write(dev, ek.serialize());
        return error::None;
 }
 
@@ -214,6 +232,8 @@ int KeyServer::internalGet(const std::string& dev,
                return error::NoSuchFile;
        }
 
+       UpgradeSupport::removeUpgradeFlag();
+
        EncryptedKey ek(FileFooter::read(dev));
 
        key = ek.decrypt(password);
index a37f442..fbe7dde 100644 (file)
@@ -40,6 +40,9 @@ public:
        int changePassword(const std::string& dev,
                                           const std::string& curPW,
                                           const std::string& newPW);
+       int changePassword2(const std::string& dev,
+                                               const BinaryData& masterKey,
+                                               const std::string& newPW);
        int verifyPassword(const std::string& dev, const std::string& password);
        int get(const std::string& dev,
                        const std::string& password,
diff --git a/server/launchpad.cpp b/server/launchpad.cpp
deleted file mode 100644 (file)
index a41ea29..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- *  Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
- *
- *  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
- */
-#include <unistd.h>
-#include <signal.h>
-#include <sys/types.h>
-
-#include <aul.h>
-#include <klay/exception.h>
-
-#include "logger.h"
-#include "launchpad.h"
-
-Launchpad::Launchpad(const uid_t uid) :
-       user(uid)
-{
-       if (user == 0) {
-               throw runtime::Exception("No logined user for launching app");
-       }
-}
-
-bool Launchpad::isRunning(const std::string& appid)
-{
-       return ::aul_app_is_running_for_uid(appid.c_str(), user);
-}
-
-void Launchpad::launch(const std::string& appid)
-{
-       launch(appid, AppBundle());
-}
-
-void Launchpad::launch(const std::string& appid, const AppBundle& bundle)
-{
-       if (::aul_launch_app_for_uid(appid.c_str(), bundle.get(), user) < 0) {
-               throw runtime::Exception("Failed to launch app " + appid);
-       }
-}
-
-void Launchpad::resume(const std::string& appid)
-{
-       if (::aul_resume_app_for_uid(appid.c_str(), user) < 0) {
-               throw runtime::Exception("Failed to resume app " + appid);
-       }
-}
-
-void Launchpad::terminate(const std::string& appid)
-{
-       int pid = ::aul_app_get_pid_for_uid(appid.c_str(), user);
-       if (pid > 0) {
-               if (::aul_terminate_pid_for_uid(pid, user) < 0) {
-                       WARN(SINK, "Failed to terminate app PID=" + std::to_string(pid));
-                       ::kill(pid, SIGKILL);
-               }
-       }
-}
index 3a374e4..33537cf 100644 (file)
@@ -16,9 +16,8 @@
 #include <cynara-client.h>
 #include <sys/smack.h>
 
-#include <klay/audit/dlog-sink.h>
-
 #include "logger.h"
+#include "file-sink.h"
 #include "secure-erase.h"
 #include "internal-encryption.h"
 #include "external-encryption.h"
@@ -36,13 +35,13 @@ namespace ode {
 namespace {
 
 const std::string ODE_MANAGER_ADDRESS = "/tmp/.ode.sock";
-std::unique_ptr<audit::DlogLogSink> _sink = nullptr;
+std::unique_ptr<FileLogSink> _sink = nullptr;
 
 } // namespace
 
 ServerContext::ServerContext() : rmi::Service(ODE_MANAGER_ADDRESS)
 {
-       _sink.reset(new audit::DlogLogSink("ODE"));
+       _sink.reset(new FileLogSink("ode.log"));
        SINK = _sink.get();
 
        INFO(SINK, "ODE server starting.");
index 85e19c6..02aca38 100644 (file)
@@ -4,6 +4,7 @@ Before=deviced.service
 
 [Service]
 Type=simple
+Group=system_share
 SmackProcessLabel=System::Privileged
 ExecStart=@BIN_DIR@/@PROJECT_NAME@d
 Restart=on-failure
index 27c9aac..1cb33d4 100644 (file)
@@ -46,6 +46,8 @@ typedef int(*KeyStoragePluginLoadFn)(const unsigned char*, size_t,
 typedef int(*KeyStoragePluginRemoveFn)(const unsigned char*, size_t);
 }
 
+const std::string UPGRADE_FLAG_PATH = "/opt/etc/.ode_upgrade_started";
+
 std::mutex opGuard;
 
 // not thread-safe because of static member
@@ -184,7 +186,7 @@ void writeToken(runtime::File &file, const BinaryData& token)
 {
        size_t tokenSize(token.size());
 
-       file.create(S_IRUSR | S_IWUSR);
+       file.create(S_IRUSR | S_IWUSR | S_IRGRP);
 
        file.write(&tokenSize, sizeof(tokenSize));
        file.write(token.data(), token.size());
@@ -225,9 +227,6 @@ BinaryData loadMasterKey(const std::string &device)
        runtime::File file(getTokenFileName(device));
        readToken(file, token);
 
-       if (token.empty())
-               throw runtime::Exception("Token opening failed");
-
        auto& up = KeyStoragePlugin::Instance();
        return up.load(token);
 }
@@ -241,16 +240,34 @@ void removeMasterKey(const std::string &device)
        runtime::File file(getTokenFileName(device));
        readToken(file, token);
 
-       // already removed
-       if (token.empty()) {
-               INFO(SINK, "Token for " + device + " does not exist. Ignoring.");
-               return;
-       }
-
        auto& up = KeyStoragePlugin::Instance();
        up.remove(token);
 
-       file.remove();
+       try {
+               file.remove();
+       } catch (runtime::Exception &e) {
+               ERROR(SINK, "Failed to remove token: " + std::string(e.what()));
+       }
+}
+
+void createUpgradeFlag()
+{
+       runtime::File file(UPGRADE_FLAG_PATH);
+       file.create(S_IRUSR | S_IWUSR); // 0600
+}
+
+void removeUpgradeFlag()
+{
+       runtime::File file(UPGRADE_FLAG_PATH);
+       bool exists = file.exists();
+       if (exists)
+               file.remove();
+}
+
+bool checkUpgradeFlag()
+{
+       runtime::File file(UPGRADE_FLAG_PATH);
+       return file.exists();
 }
 
 } // namespace UpgradeSupport
index 4a029b8..ad47acf 100644 (file)
@@ -28,6 +28,9 @@ namespace UpgradeSupport {
 void storeMasterKey(const std::string &device, const BinaryData& key);
 BinaryData loadMasterKey(const std::string &device);
 void removeMasterKey(const std::string &device);
+void createUpgradeFlag();
+void removeUpgradeFlag();
+bool checkUpgradeFlag();
 
 } // namespace UpgradeSupport