mirror of https://github.com/OISF/suricata
Libcap-ng support by Gurvinder Singh and myself. Basic support for per thread caps is added, but not activated as it doesn't seem to work yet. Work around for incompatibility between libnet 1.1 and libcap-ng added.
parent
e0c2c86342
commit
070ed778b8
@ -0,0 +1,205 @@
|
||||
/* Copyright (c) 2010 Open Infomation Security Foundation */
|
||||
|
||||
/**
|
||||
* \file
|
||||
* \author Gurvinder Singh <gurvindersinghdahiya@gmail.com>
|
||||
*
|
||||
* \brief File to drop the engine capabilities using libcap-ng by
|
||||
* Steve Grubb
|
||||
*/
|
||||
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include "util-debug.h"
|
||||
#include "suricata-common.h"
|
||||
|
||||
#ifdef HAVE_LIBCAP_NG
|
||||
|
||||
#include <cap-ng.h>
|
||||
#include <sys/prctl.h>
|
||||
#include "threadvars.h"
|
||||
#include "util-cpu.h"
|
||||
#include "util-privs.h"
|
||||
|
||||
/** flag indicating if we'll be using caps */
|
||||
extern int sc_set_caps;
|
||||
|
||||
/**
|
||||
* \brief Drop all the previliges of the given thread
|
||||
*/
|
||||
void SCDropAllCaps()
|
||||
{
|
||||
capng_clear(CAPNG_SELECT_BOTH);
|
||||
if (capng_apply(CAPNG_SELECT_BOTH) < 0) {
|
||||
SCLogError(SC_ERR_CHANGING_CAPS_FAILED, "failed in dropping the caps");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Drop the previliges of the main thread
|
||||
*/
|
||||
void SCDropMainThreadCaps(uint32_t userid, uint32_t groupid)
|
||||
{
|
||||
if (sc_set_caps == FALSE)
|
||||
return;
|
||||
|
||||
capng_clear(CAPNG_SELECT_BOTH);
|
||||
capng_updatev(CAPNG_ADD, CAPNG_EFFECTIVE|CAPNG_PERMITTED,
|
||||
CAP_NET_RAW, /* needed for pcap live mode */
|
||||
#ifdef NFQ
|
||||
CAP_NET_ADMIN, /* needed for nfqueue inline mode */
|
||||
#endif
|
||||
-1);
|
||||
if (capng_change_id(userid, groupid, CAPNG_DROP_SUPP_GRP |
|
||||
CAPNG_CLEAR_BOUNDING) < 0)
|
||||
{
|
||||
SCLogError(SC_ERR_CHANGING_CAPS_FAILED, "capng_change_id for main thread"
|
||||
" failed");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
SCLogInfo("dropped the caps for main thread");
|
||||
}
|
||||
|
||||
void SCDropCaps(ThreadVars *tv) {
|
||||
#if 0
|
||||
capng_clear(CAPNG_SELECT_BOTH);
|
||||
capng_apply(CAPNG_SELECT_BOTH);
|
||||
if (tv->cap_flags & SC_CAP_IPC_LOCK) {
|
||||
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_IPC_LOCK);
|
||||
capng_apply(CAPNG_SELECT_CAPS);
|
||||
SCLogDebug("For thread \"%s\" CAP_IPC_LOCK has been set", tv->name);
|
||||
}
|
||||
if (tv->cap_flags & SC_CAP_NET_ADMIN) {
|
||||
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_ADMIN);
|
||||
capng_apply(CAPNG_SELECT_CAPS);
|
||||
SCLogDebug("For thread \"%s\" CAP_NET_ADMIN has been set", tv->name);
|
||||
}
|
||||
if (tv->cap_flags & SC_CAP_NET_BIND_SERVICE) {
|
||||
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_BIND_SERVICE);
|
||||
capng_apply(CAPNG_SELECT_CAPS);
|
||||
SCLogDebug("For thread \"%s\" CAP_NET_BIND_SERVICE has been set", tv->name);
|
||||
}
|
||||
if (tv->cap_flags & SC_CAP_NET_BROADCAST) {
|
||||
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_BROADCAST);
|
||||
capng_apply(CAPNG_SELECT_CAPS);
|
||||
SCLogDebug("For thread \"%s\" CAP_NET_BROADCAST has been set", tv->name);
|
||||
}
|
||||
if (tv->cap_flags & SC_CAP_NET_RAW) {
|
||||
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_RAW);
|
||||
capng_apply(CAPNG_SELECT_CAPS);
|
||||
SCLogDebug("For thread \"%s\" CAP_NET_RAW has been set", tv->name);
|
||||
}
|
||||
if (tv->cap_flags & SC_CAP_SYS_ADMIN) {
|
||||
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_SYS_ADMIN);
|
||||
capng_apply(CAPNG_SELECT_CAPS);
|
||||
SCLogDebug("For thread \"%s\" CAP_SYS_ADMIN has been set", tv->name);
|
||||
}
|
||||
if (tv->cap_flags & SC_CAP_SYS_RAW_IO) {
|
||||
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_SYS_RAWIO);
|
||||
capng_apply(CAPNG_SELECT_CAPS);
|
||||
SCLogDebug("For thread \"%s\" CAP_SYS_RAWIO has been set", tv->name);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* HAVE_LIBCAP_NG */
|
||||
|
||||
/**
|
||||
* \brief Function to get the user and group ID from the specified user name
|
||||
*
|
||||
* \param user_name pointer to the given user name
|
||||
* \param uid pointer to the user id in which result will be stored
|
||||
* \param gid pointer to the group id in which result will be stored
|
||||
*
|
||||
* \retval upon success it return 0
|
||||
*/
|
||||
int SCGetUserID(char *user_name, char *group_name, uint32_t *uid, uint32_t *gid)
|
||||
{
|
||||
uint32_t userid = 0;
|
||||
uint32_t groupid = 0;
|
||||
struct passwd *pw;
|
||||
|
||||
/* Get the user ID */
|
||||
if (isdigit(user_name[0]) != 0) {
|
||||
userid = atoi(user_name);
|
||||
pw = getpwuid(userid);
|
||||
if (pw == NULL) {
|
||||
SCLogError(SC_ERR_UID_FAILED, "unable to get the user ID, "
|
||||
"check if user exist!!");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else {
|
||||
pw = getpwnam(user_name);
|
||||
if (pw == NULL) {
|
||||
SCLogError(SC_ERR_UID_FAILED, "unable to get the user ID, "
|
||||
"check if user exist!!");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
userid = pw->pw_uid;
|
||||
}
|
||||
|
||||
/* Get the group ID */
|
||||
if (group_name != NULL) {
|
||||
struct group *gp;
|
||||
|
||||
if (isdigit(group_name[0]) != 0) {
|
||||
groupid = atoi(group_name);
|
||||
} else {
|
||||
gp = getgrnam(group_name);
|
||||
if (gp == NULL) {
|
||||
SCLogError(SC_ERR_GID_FAILED, "unable to get the group"
|
||||
" ID, check if group exist!!");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
groupid = gp->gr_gid;
|
||||
}
|
||||
} else {
|
||||
groupid = pw->pw_gid;
|
||||
}
|
||||
|
||||
/* close the group database */
|
||||
endgrent();
|
||||
/* close the user database */
|
||||
endpwent();
|
||||
|
||||
*uid = userid;
|
||||
*gid = groupid;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Function to get the group ID from the specified group name
|
||||
*
|
||||
* \param group_name pointer to the given group name
|
||||
* \param gid pointer to the group id in which result will be stored
|
||||
*
|
||||
* \retval upon success it return 0
|
||||
*/
|
||||
int SCGetGroupID(char *group_name, uint32_t *gid)
|
||||
{
|
||||
uint32_t grpid = 0;
|
||||
struct group *gp;
|
||||
|
||||
/* Get the group ID */
|
||||
if (isdigit(group_name[0]) != 0) {
|
||||
grpid = atoi(group_name);
|
||||
} else {
|
||||
gp = getgrnam(group_name);
|
||||
if (gp == NULL) {
|
||||
SCLogError(SC_ERR_GID_FAILED, "unable to get the group ID,"
|
||||
" check if group exist!!");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
grpid = gp->gr_gid;
|
||||
}
|
||||
|
||||
/* close the group database */
|
||||
endgrent();
|
||||
|
||||
*gid = grpid;
|
||||
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
/* Copyright (c) 2010 Open Infomation Security Foundation */
|
||||
|
||||
/**
|
||||
* \author Gurvinder Singh <gurvindersinghdahiya@gmail.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _UTIL_PRIVS_H
|
||||
#define _UTIL_PRIVS_H
|
||||
|
||||
#define SC_CAP_NONE 0x01
|
||||
#define SC_CAP_SYS_ADMIN 0x02
|
||||
#define SC_CAP_SYS_RAW_IO 0x04
|
||||
#define SC_CAP_IPC_LOCK 0x08
|
||||
#define SC_CAP_NET_ADMIN 0x10
|
||||
#define SC_CAP_NET_RAW 0x20
|
||||
#define SC_CAP_NET_BIND_SERVICE 0x40
|
||||
#define SC_CAP_NET_BROADCAST 0x80
|
||||
|
||||
#ifndef HAVE_LIBCAP_NG
|
||||
#define SCDropCaps(...)
|
||||
#define SCDropMainThreadCaps(...)
|
||||
#else
|
||||
#include "threadvars.h"
|
||||
#include "util-debug.h"
|
||||
#include <cap-ng.h>
|
||||
|
||||
/**Drop the previliges of the given thread tv, based on the thread cap_flags
|
||||
* which implies the capability requirement of the given thread. Initially all
|
||||
* caps are dropped and later, the required caps are set for the given thread
|
||||
*/
|
||||
void SCDropCaps(ThreadVars *tv);
|
||||
/*
|
||||
#define SCDropCaps(tv) ({ \
|
||||
capng_clear(CAPNG_SELECT_BOTH); \
|
||||
capng_apply(CAPNG_SELECT_BOTH); \
|
||||
if (tv->cap_flags & SC_CAP_IPC_LOCK) { \
|
||||
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_IPC_LOCK); \
|
||||
capng_apply(CAPNG_SELECT_CAPS); \
|
||||
SCLogDebug("For thread \"%s\" CAP_IPC_LOCK has been set", tv->name); \
|
||||
} \
|
||||
if (tv->cap_flags & SC_CAP_NET_ADMIN) { \
|
||||
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_ADMIN); \
|
||||
capng_apply(CAPNG_SELECT_CAPS); \
|
||||
SCLogDebug("For thread \"%s\" CAP_NET_ADMIN has been set", tv->name); \
|
||||
} \
|
||||
if (tv->cap_flags & SC_CAP_NET_BIND_SERVICE) { \
|
||||
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_BIND_SERVICE); \
|
||||
capng_apply(CAPNG_SELECT_CAPS); \
|
||||
SCLogDebug("For thread \"%s\" CAP_NET_BIND_SERVICE has been set", tv->name); \
|
||||
} \
|
||||
if (tv->cap_flags & SC_CAP_NET_BROADCAST) { \
|
||||
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_BROADCAST); \
|
||||
capng_apply(CAPNG_SELECT_CAPS); \
|
||||
SCLogDebug("For thread \"%s\" CAP_NET_BROADCAST has been set", tv->name); \
|
||||
} \
|
||||
if (tv->cap_flags & SC_CAP_NET_RAW) { \
|
||||
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_NET_RAW); \
|
||||
capng_apply(CAPNG_SELECT_CAPS); \
|
||||
SCLogDebug("For thread \"%s\" CAP_NET_RAW has been set", tv->name); \
|
||||
} \
|
||||
if (tv->cap_flags & SC_CAP_SYS_ADMIN) { \
|
||||
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_SYS_ADMIN); \
|
||||
capng_apply(CAPNG_SELECT_CAPS); \
|
||||
SCLogDebug("For thread \"%s\" CAP_SYS_ADMIN has been set", tv->name); \
|
||||
} \
|
||||
if (tv->cap_flags & SC_CAP_SYS_RAW_IO) { \
|
||||
capng_update(CAPNG_ADD, (capng_type_t) (CAPNG_EFFECTIVE | CAPNG_PERMITTED), CAP_SYS_RAWIO); \
|
||||
capng_apply(CAPNG_SELECT_CAPS); \
|
||||
SCLogDebug("For thread \"%s\" CAP_SYS_RAWIO has been set", tv->name); \
|
||||
} \
|
||||
})
|
||||
*/
|
||||
void SCDropMainThreadCaps(uint32_t , uint32_t );
|
||||
|
||||
#endif /* HAVE_LIBCAP_NG */
|
||||
|
||||
int SCGetUserID(char *, char *, uint32_t *, uint32_t *);
|
||||
int SCGetGroupID(char *, uint32_t *);
|
||||
|
||||
#endif /* _UTIL_PRIVS_H */
|
||||
|
Loading…
Reference in New Issue