* negative on error
* @retval #TRUST_ANCHOR_ERROR_NONE Successful
* @retval #TRUST_ANCHOR_ERROR_OUT_OF_MEMORY Out of memory error
+ * @retval #TRUST_ANCHOR_ERROR_INVALID_PARAMETER Invalid parameter error
+ * @retval #TRUST_ANCHOR_ERROR_PERMISSION_DENIED Permission denied error
+ * @retval #TRUST_ANCHOR_ERROR_NO_SUCH_FILE No such file or directory error
* @retval #TRUST_ANCHOR_ERROR_INTERNAL Internal error
* @see trust_anchor_global_launch()
* @see trust_anchor_global_uninstall()
* negative on error
* @retval #TRUST_ANCHOR_ERROR_NONE Successful
* @retval #TRUST_ANCHOR_ERROR_OUT_OF_MEMORY Out of memory error
+ * @retval #TRUST_ANCHOR_ERROR_INVALID_PARAMETER Invalid parameter error
+ * @retval #TRUST_ANCHOR_ERROR_PERMISSION_DENIED Permission denied error
+ * @retval #TRUST_ANCHOR_ERROR_NO_SUCH_FILE No such file or directory error
* @retval #TRUST_ANCHOR_ERROR_INTERNAL Internal error
* @see trust_anchor_usr_launch()
* @see trust_anchor_usr_uninstall()
* negative on error
* @retval #TRUST_ANCHOR_ERROR_NONE Successful
* @retval #TRUST_ANCHOR_ERROR_OUT_OF_MEMORY Out of memory error
+ * @retval #TRUST_ANCHOR_ERROR_INVALID_PARAMETER Invalid parameter error
+ * @retval #TRUST_ANCHOR_ERROR_PERMISSION_DENIED Permission denied error
+ * @retval #TRUST_ANCHOR_ERROR_NO_SUCH_FILE No such file or directory error
* @retval #TRUST_ANCHOR_ERROR_INTERNAL Internal error
* @see trust_anchor_global_install()
*/
* negative on error
* @retval #TRUST_ANCHOR_ERROR_NONE Successful
* @retval #TRUST_ANCHOR_ERROR_OUT_OF_MEMORY Out of memory error
+ * @retval #TRUST_ANCHOR_ERROR_INVALID_PARAMETER Invalid parameter error
+ * @retval #TRUST_ANCHOR_ERROR_PERMISSION_DENIED Permission denied error
+ * @retval #TRUST_ANCHOR_ERROR_NO_SUCH_FILE No such file or directory error
* @retval #TRUST_ANCHOR_ERROR_INTERNAL Internal error
* @see trust_anchor_usr_install()
*/
*/
#include "exception.hxx"
-#include <exception>
-
#include <klay/exception.h>
-#include <klay/audit/logger.h>
namespace tanchor {
int exceptionGuard(const std::function<int()> &func)
{
- // TODO add custom error code
try {
return func();
- } catch (runtime::Exception &e) {
+ } catch (const tanchor::Exception &e) {
+ std::string errStr;
+ switch (e.error()) {
+ case ENOENT:
+ errStr = "No such file or directory.";
+ break;
+ case ENOMEM:
+ errStr = "Out of memory.";
+ break;
+ case EACCES:
+ case EPERM:
+ errStr = "Permission denied.";
+ break;
+ default:
+ errStr = "Internal error.";
+ break;
+ }
+ ERROR(errStr + e.what());
+ return e.error();
+ } catch (const runtime::Exception &e) {
ERROR(e.what());
- return -1;
+ return TRUST_ANCHOR_ERROR_INTERNAL;
} catch (const std::invalid_argument &e) {
- ERROR("Invalid argument: " << e.what());
- return -1;
+ ERROR(e.what());
+ return TRUST_ANCHOR_ERROR_INVALID_PARAMETER;
+ } catch (const std::logic_error &e) {
+ ERROR(e.what());
+ return TRUST_ANCHOR_ERROR_INTERNAL;
} catch (const std::exception &e) {
ERROR(e.what());
- return -1;
+ return TRUST_ANCHOR_ERROR_INTERNAL;
} catch (...) {
ERROR("Unknown exception occurred.");
- return -1;
+ return TRUST_ANCHOR_ERROR_INTERNAL;
}
}
+Exception::Exception(int ec, const char *file, const char *function,
+ unsigned int line, const std::string &message) noexcept :
+ m_ec(ec),
+ m_message(FORMAT("[" << file << ":" << line << " " <<
+ function << "()]" << message))
+{
+ ERROR(this->m_message);
+}
+
+const char *Exception::what() const noexcept
+{
+ return this->m_message.c_str();
+}
+
+int Exception::error(void) const noexcept
+{
+ return this->m_ec;
+}
+
} // namespace tanchor
*/
#pragma once
+#include "tanchor/error.h"
+
#include <functional>
+#include <string>
+#include <exception>
+
+#include <klay/audit/logger.h>
#define EXCEPTION_GUARD_START return tanchor::exceptionGuard([&]() {
#define EXCEPTION_GUARD_END });
int exceptionGuard(const std::function<int()> &);
+class Exception : public std::exception {
+public:
+ Exception(int ec, const char *file, const char *function,
+ unsigned int line, const std::string &message) noexcept;
+ virtual ~Exception() = default;
+ virtual const char* what() const noexcept override;
+
+ int error(void) const noexcept;
+
+protected:
+ int m_ec;
+ std::string m_message;
+};
+
} // namespace tanchor
+
+#define __TANCHOR_THROW(ec, MESSAGE) \
+ throw tanchor::Exception(ec, __FILE__, __FUNCTION__, \
+ __LINE__, FORMAT(MESSAGE))
+
+#define ThrowExc(ec, MESSAGE) __TANCHOR_THROW(ec, MESSAGE)
+
+#define ThrowErrno(ec, MESSAGE) \
+ do { \
+ switch (ec) { \
+ case ENOENT: \
+ ThrowExc(TRUST_ANCHOR_ERROR_NO_SUCH_FILE, MESSAGE); \
+ case ENOMEM: \
+ ThrowExc(TRUST_ANCHOR_ERROR_OUT_OF_MEMORY, MESSAGE); \
+ case EACCES: \
+ case EPERM: \
+ ThrowExc(TRUST_ANCHOR_ERROR_PERMISSION_DENIED, MESSAGE); \
+ default: \
+ ThrowExc(TRUST_ANCHOR_ERROR_INTERNAL, MESSAGE); \
+ } \
+ } while (0)
std::string getUniqueHashName(const std::string &hashName) const;
std::string getBundleName(void) const;
bool isSystemCertsModified(void) const;
+ void checkFileValidity(const runtime::File &file) const;
std::string m_packageId;
std::string m_appCertsPath;
errno = 0;
int ret = ::symlink(src.c_str(), dst.c_str());
if (ret != 0)
- throw std::logic_error("Fail to link " + src + " -> " + dst +
- "[" + std::to_string(errno) + "]");
+ ThrowErrno(errno, "Failed to link " + src + " -> " + dst);
}
void TrustAnchor::Impl::preInstall(void) const
customBundleDir.makeDirectory();
runtime::File appCertsDir(this->m_appCertsPath);
- if (!appCertsDir.exists() || !appCertsDir.isDirectory())
- throw std::invalid_argument("App custom certs path is wrong. : " +
- m_appCertsPath);
+ this->checkFileValidity(appCertsDir);
+ if (!appCertsDir.isDirectory())
+ throw std::invalid_argument("[" + this->m_appCertsPath +
+ "] should be directory.");
DEBUG("Success to pre-install stage.");
}
INFO("Success to install[" << this->m_packageId <<
"] to " << this->m_customBasePath);
- return 0;
+ return TRUST_ANCHOR_ERROR_NONE;
EXCEPTION_GUARD_END
}
runtime::File customBaseDir(this->m_customBasePath);
if (!customBaseDir.exists() && !isRollback)
- throw std::invalid_argument("There is no installed anchor previous.");
+ throw std::logic_error("There is no installed anchor previous.");
if (customBaseDir.exists())
customBaseDir.remove(true);
INFO("Success to uninstall. : " << this->m_packageId);
- return 0;
+ return TRUST_ANCHOR_ERROR_NONE;
EXCEPTION_GUARD_END
}
+void TrustAnchor::Impl::checkFileValidity(const runtime::File &file) const
+{
+ if (!file.exists())
+ ThrowExc(TRUST_ANCHOR_ERROR_NO_SUCH_FILE,
+ "File [" << file.getPath() << "] does not exist.");
+
+ if (!file.canRead())
+ ThrowExc(TRUST_ANCHOR_ERROR_PERMISSION_DENIED,
+ "No permission to read [" << file.getPath() << "]");
+}
+
bool TrustAnchor::Impl::isSystemCertsModified(void) const
{
struct stat systemAttr, customAttr;
- stat(SYS_BUNDLE_PATH.c_str(), &systemAttr);
- DEBUG("System bundle mtime : " << ::ctime(&systemAttr.st_mtime));
+ errno = 0;
+ if (::stat(SYS_BUNDLE_PATH.c_str(), &systemAttr))
+ ThrowErrno(errno, SYS_BUNDLE_PATH);
auto customBundle = this->m_customBundlePath + "/" + this->getBundleName();
- stat(customBundle.c_str(), &customAttr);
- DEBUG("Custom bundle mtime : " << ::ctime(&customAttr.st_mtime));
+ if (::stat(customBundle.c_str(), &customAttr))
+ ThrowErrno(errno, customBundle);
+
+ DEBUG("System bundle mtime : " << ::ctime(&systemAttr.st_mtime) << ", " <<
+ "Custom bundle mtime : " << ::ctime(&customAttr.st_mtime));
return systemAttr.st_mtime > customAttr.st_mtime;
}
errno = 0;
// disassociate from the parent namespace
if (::unshare(CLONE_NEWNS))
- throw std::logic_error("Failed to unshare namespace > " +
- std::to_string(errno));
+ ThrowErrno(errno, "Failed to unshare.");
// convert it to a slave for preventing propagation
if (::mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL))
- throw std::logic_error("Failed to disconnect root fs.");
+ ThrowErrno(errno, "Failed to mount.");
if (::mount(this->m_customCertsPath.c_str(),
MOUNT_POINT_CERTS.c_str(),
NULL,
MS_BIND,
NULL))
- throw std::logic_error("Failed to mount certs.");
+ ThrowErrno(errno, "Failed to mount. src[" +
+ this->m_customCertsPath + "] to dst[" +
+ MOUNT_POINT_CERTS + "]");
auto bundle = this->m_customBundlePath + "/" + this->getBundleName();
if (::mount(bundle.c_str(),
NULL,
MS_BIND,
NULL))
- throw std::logic_error("Failed to mount bundle.");
+ ThrowErrno(errno, "Failed to mount. src[" + bundle +
+ "] to dst[" + MOUNT_POINT_BUNDLE + "]");
INFO("Success to launch. : " << this->m_packageId);
- return 0;
+ return TRUST_ANCHOR_ERROR_NONE;
EXCEPTION_GUARD_END
}
DEBUG("Start to migrate previous bundle.");
if (withSystemCerts) {
runtime::File sysBundle(SYS_BUNDLE_PATH);
- if (!sysBundle.exists())
- throw std::logic_error("There is no system bundle file.");
+ this->checkFileValidity(sysBundle);
sysBundle.copyTo(this->m_customBundlePath);
} else {
runtime::File tanchorBundle(TANCHOR_BUNDLE_PATH);
- if (!tanchorBundle.exists())
- throw std::logic_error("There is no tanchor bundle file.");
+ this->checkFileValidity(tanchorBundle);
tanchorBundle.copyTo(this->m_customBundlePath);
}
DEBUG("Finish migrating previous bundle.");
m_pImpl(new Impl(packageId, certsDir, uid)) {}
TrustAnchor::TrustAnchor(const std::string &packageId,
- const std::string &certsDir) noexcept :
+ const std::string &certsDir) noexcept :
m_pImpl(new Impl(packageId, certsDir)) {}
TrustAnchor::~TrustAnchor(void) = default;
int TrustAnchor::install(bool withSystemCerts) noexcept
{
if (this->m_pImpl == nullptr)
- return -1;
+ return TRUST_ANCHOR_ERROR_OUT_OF_MEMORY;
int ret = this->m_pImpl->install(withSystemCerts);
- if (ret != 0) {
+ if (ret != TRUST_ANCHOR_ERROR_NONE) {
ERROR("Failed to intall ACTA. Remove custom directory for rollback.");
this->m_pImpl->uninstall(true);
}
int TrustAnchor::uninstall(void) noexcept
{
if (this->m_pImpl == nullptr)
- return -1;
+ return TRUST_ANCHOR_ERROR_OUT_OF_MEMORY;
return this->m_pImpl->uninstall();
}
int TrustAnchor::launch(bool withSystemCerts) noexcept
{
if (this->m_pImpl == nullptr)
- return -1;
+ return TRUST_ANCHOR_ERROR_OUT_OF_MEMORY;
return this->m_pImpl->launch(withSystemCerts);
}