2018-11-14 01:11:13 +00:00
|
|
|
#if defined(__linux__)
|
|
|
|
|
2018-11-14 01:59:32 +00:00
|
|
|
#include "hasLinuxCapability.h"
|
|
|
|
|
2018-11-14 01:11:13 +00:00
|
|
|
#include <syscall.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <linux/capability.h>
|
|
|
|
#include <linux/netlink.h>
|
|
|
|
#include <Common/Exception.h>
|
|
|
|
|
|
|
|
|
|
|
|
namespace DB
|
|
|
|
{
|
2018-11-14 01:59:32 +00:00
|
|
|
|
2018-11-14 01:11:13 +00:00
|
|
|
namespace ErrorCodes
|
|
|
|
{
|
|
|
|
extern const int NETLINK_ERROR;
|
|
|
|
}
|
|
|
|
|
2018-11-14 01:59:32 +00:00
|
|
|
static __user_cap_data_struct getCapabilities()
|
2018-11-14 01:11:13 +00:00
|
|
|
{
|
2018-11-14 01:59:32 +00:00
|
|
|
/// See man getcap.
|
|
|
|
__user_cap_header_struct request{};
|
|
|
|
request.version = _LINUX_CAPABILITY_VERSION_1; /// It's enough to check just single CAP_NET_ADMIN capability we are interested.
|
|
|
|
request.pid = getpid();
|
2018-11-14 01:11:13 +00:00
|
|
|
|
2018-11-14 01:59:32 +00:00
|
|
|
__user_cap_data_struct response{};
|
2018-11-14 01:11:13 +00:00
|
|
|
|
2018-11-14 01:59:32 +00:00
|
|
|
/// Avoid dependency on 'libcap'.
|
|
|
|
if (0 != syscall(SYS_capget, &request, &response))
|
|
|
|
throwFromErrno("Cannot do 'capget' syscall", ErrorCodes::NETLINK_ERROR);
|
2018-11-14 01:11:13 +00:00
|
|
|
|
2018-11-14 01:59:32 +00:00
|
|
|
return response;
|
2018-11-14 01:11:13 +00:00
|
|
|
}
|
|
|
|
|
2018-11-14 01:59:32 +00:00
|
|
|
bool hasLinuxCapability(int cap)
|
2018-11-14 01:11:13 +00:00
|
|
|
{
|
2018-11-14 01:59:32 +00:00
|
|
|
static __user_cap_data_struct capabilities = getCapabilities();
|
|
|
|
return (1 << cap) & capabilities.effective;
|
2018-11-14 01:11:13 +00:00
|
|
|
}
|
2018-11-14 01:59:32 +00:00
|
|
|
|
2018-11-14 01:11:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|