be4e3f21e4
In C++11, destructors are `noexcept` by default. However, some of the destructors in paludis throw. Annotate these functions as `noexcept(false)`.
267 lines
8.6 KiB
C++
267 lines
8.6 KiB
C++
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
|
|
|
|
/*
|
|
* Copyright (c) 2006 Stephen Bennett
|
|
*
|
|
* This file is part of the Paludis package manager. Paludis is free software;
|
|
* you can redistribute it and/or modify it under the terms of the GNU General
|
|
* Public License, version 2, as published by the Free Software Foundation.
|
|
*
|
|
* Paludis is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* this program; if not, write to the Free Software Foundation, Inc., 59 Temple
|
|
* Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#include <paludis/util/log.hh>
|
|
#include <paludis/util/stringify.hh>
|
|
#include <paludis/util/singleton-impl.hh>
|
|
#include <paludis/util/pimp-impl.hh>
|
|
#include <paludis/selinux/security_context.hh>
|
|
|
|
#include "config.h"
|
|
#include <stdint.h>
|
|
#include <dlfcn.h>
|
|
|
|
// I think the name explains it. C++ is picky about casting to function pointers.
|
|
#define STUPID_CAST(type, val) reinterpret_cast<type>(reinterpret_cast<uintptr_t>(val))
|
|
|
|
using namespace paludis;
|
|
|
|
namespace
|
|
{
|
|
// Declared here to remove dep on <selinux/selinux.h>
|
|
typedef char *security_context_t;
|
|
|
|
class LibSELinux
|
|
{
|
|
private:
|
|
void *_handle;
|
|
|
|
void (*_freecon)(security_context_t);
|
|
int (*_getcon)(security_context_t*);
|
|
int (*_getfscreatecon)(security_context_t*);
|
|
int (*_setfscreatecon)(security_context_t);
|
|
int (*_matchpathcon)(const char *, mode_t, security_context_t*);
|
|
int (*_matchpathcon_init)(const char *);
|
|
int (*_setfilecon)(const char *, security_context_t);
|
|
int (*_is_selinux_enabled)(void);
|
|
|
|
public:
|
|
LibSELinux() :
|
|
_handle(nullptr), _freecon(nullptr), _getcon(nullptr),
|
|
_getfscreatecon(nullptr), _setfscreatecon(nullptr),
|
|
_matchpathcon(nullptr), _matchpathcon_init(nullptr),
|
|
_is_selinux_enabled(nullptr)
|
|
{
|
|
_handle = dlopen("libselinux.so", RTLD_LAZY | RTLD_LOCAL);
|
|
if (nullptr != _handle)
|
|
{
|
|
_freecon = STUPID_CAST(void (*)(security_context_t), dlsym(_handle, "freecon"));
|
|
_getcon = STUPID_CAST(int (*)(security_context_t*), dlsym(_handle, "getcon"));
|
|
_getfscreatecon = STUPID_CAST(int (*) (security_context_t*),
|
|
dlsym(_handle, "getfscreatecon"));
|
|
_setfscreatecon = STUPID_CAST(int (*) (security_context_t),
|
|
dlsym(_handle, "setfscreatecon"));
|
|
_matchpathcon = STUPID_CAST(int (*) (const char *, mode_t, security_context_t *),
|
|
dlsym(_handle, "matchpathcon"));
|
|
_matchpathcon_init = STUPID_CAST(int (*) (const char *),
|
|
dlsym(_handle, "matchpathcon_init"));
|
|
_setfilecon = STUPID_CAST(int (*) (const char *, security_context_t),
|
|
dlsym(_handle, "lsetfilecon"));
|
|
_is_selinux_enabled = STUPID_CAST(int (*)(void),
|
|
dlsym(_handle, "is_selinux_enabled"));
|
|
}
|
|
}
|
|
|
|
~LibSELinux()
|
|
{
|
|
if (nullptr != _handle)
|
|
dlclose(_handle);
|
|
}
|
|
|
|
void freecon(security_context_t c)
|
|
{
|
|
if (nullptr != _freecon && is_selinux_enabled())
|
|
_freecon(c);
|
|
}
|
|
|
|
int getcon(security_context_t *c)
|
|
{
|
|
if (nullptr != _getcon && is_selinux_enabled())
|
|
return _getcon(c);
|
|
return 0;
|
|
}
|
|
|
|
int getfscreatecon(security_context_t *c)
|
|
{
|
|
if (nullptr != _getfscreatecon && is_selinux_enabled())
|
|
return _getfscreatecon(c);
|
|
return 0;
|
|
}
|
|
|
|
int setfscreatecon(security_context_t c)
|
|
{
|
|
if (nullptr != _setfscreatecon && is_selinux_enabled())
|
|
return _setfscreatecon(c);
|
|
return 0;
|
|
}
|
|
|
|
int matchpathcon(const char *path, mode_t mode, security_context_t *con)
|
|
{
|
|
if (nullptr != _matchpathcon && is_selinux_enabled())
|
|
return _matchpathcon(path, mode, con);
|
|
return 0;
|
|
}
|
|
|
|
int setfilecon(const char *path, security_context_t con)
|
|
{
|
|
if (nullptr != _setfilecon && is_selinux_enabled())
|
|
return _setfilecon(path, con);
|
|
return 0;
|
|
}
|
|
|
|
int matchpathcon_init(const char *path)
|
|
{
|
|
if (nullptr != _matchpathcon_init && is_selinux_enabled())
|
|
return _matchpathcon_init(path);
|
|
return 0;
|
|
}
|
|
|
|
int is_selinux_enabled()
|
|
{
|
|
// Assume that if this returns an error we can't effectively use selinux.
|
|
if (nullptr != _is_selinux_enabled)
|
|
return _is_selinux_enabled() > 0 ? 1 : 0;
|
|
return 0;
|
|
}
|
|
} libselinux;
|
|
}
|
|
|
|
namespace paludis
|
|
{
|
|
template<>
|
|
struct Imp<SecurityContext>
|
|
{
|
|
security_context_t _context;
|
|
|
|
Imp(security_context_t con)
|
|
: _context(con)
|
|
{ }
|
|
|
|
~Imp()
|
|
{
|
|
if (nullptr != _context)
|
|
libselinux.freecon(_context);
|
|
}
|
|
|
|
void set(security_context_t newcon)
|
|
{
|
|
if (nullptr != _context)
|
|
libselinux.freecon(_context);
|
|
|
|
_context = newcon;
|
|
}
|
|
};
|
|
}
|
|
|
|
SecurityContext::SecurityContext() :
|
|
_imp(security_context_t(nullptr))
|
|
{
|
|
}
|
|
|
|
SecurityContext::~SecurityContext() = default;
|
|
|
|
std::shared_ptr<const SecurityContext> SecurityContext::current_context()
|
|
{
|
|
std::shared_ptr<SecurityContext> p(std::make_shared<SecurityContext>());
|
|
security_context_t con;
|
|
if (0 != libselinux.getcon(&con))
|
|
throw SELinuxException("Couldn't get current security context.");
|
|
p->_imp->set(con);
|
|
return p;
|
|
}
|
|
|
|
std::shared_ptr<const SecurityContext> SecurityContext::fs_create_context()
|
|
{
|
|
std::shared_ptr<SecurityContext> p(std::make_shared<SecurityContext>());
|
|
security_context_t con;
|
|
if (0 != libselinux.getfscreatecon(&con))
|
|
throw SELinuxException("Couldn't get current filesystem creation context.");
|
|
p->_imp->set(con);
|
|
return p;
|
|
}
|
|
|
|
std::ostream & paludis::operator<<(std::ostream & os, const SecurityContext & context)
|
|
{
|
|
os << static_cast<const char *>(context._imp->_context);
|
|
return os;
|
|
}
|
|
|
|
FSCreateCon::FSCreateCon(const std::shared_ptr<const SecurityContext> & newfscreatecon)
|
|
: _context(newfscreatecon), _prev_context(SecurityContext::fs_create_context())
|
|
{
|
|
if (0 != libselinux.setfscreatecon(_context->_imp->_context))
|
|
throw SELinuxException("Couldn't set filesystem creation context to '" + stringify(*_context) + "'.");
|
|
}
|
|
|
|
FSCreateCon::~FSCreateCon() noexcept(false)
|
|
{
|
|
if (0 != libselinux.setfscreatecon(_prev_context->_imp->_context))
|
|
throw SELinuxException("Couldn't reset filesystem creation context to '" + stringify(*_prev_context) + "'.");
|
|
}
|
|
|
|
MatchPathCon::MatchPathCon()
|
|
{
|
|
if (0 != libselinux.matchpathcon_init(nullptr))
|
|
{
|
|
_good=false;
|
|
// throw SELinuxException("Failed running matchpathcon_init.");
|
|
}
|
|
else
|
|
_good=true;
|
|
}
|
|
|
|
MatchPathCon::~MatchPathCon() = default;
|
|
|
|
bool MatchPathCon::good() const
|
|
{
|
|
return _good;
|
|
}
|
|
|
|
std::shared_ptr<const SecurityContext> MatchPathCon::match(const std::string & path, mode_t mode) const
|
|
{
|
|
std::shared_ptr<SecurityContext> p(std::make_shared<SecurityContext>());
|
|
security_context_t context;
|
|
if (0 != libselinux.matchpathcon(path.c_str(), mode, &context))
|
|
{
|
|
Log::get_instance()->message("selinux.get_context", ll_warning, lc_no_context) <<
|
|
"Couldn't get default security context for '" << path << "'.";
|
|
// throw SELinuxException("Couldn't get default security context for '" + path + "'.");
|
|
}
|
|
else
|
|
{
|
|
p->_imp->set(context);
|
|
}
|
|
return p;
|
|
}
|
|
|
|
int paludis::setfilecon(const FSPath & path, const std::shared_ptr<const SecurityContext> & con)
|
|
{
|
|
return libselinux.setfilecon(stringify(path).c_str(), con->_imp->_context);
|
|
}
|
|
|
|
bool paludis::is_selinux_enabled()
|
|
{
|
|
return libselinux.is_selinux_enabled() == 1;
|
|
}
|
|
|
|
namespace paludis
|
|
{
|
|
template class Singleton<MatchPathCon>;
|
|
}
|