Bitdefender Hypervisor Memory Introspection
lixcred.c File Reference
#include "lixcred.h"
#include "alerts.h"
#include "crc32.h"
#include "guests.h"
#include "lixfiles.h"
#include "lixmm.h"
#include "lixprocess.h"
#include "lixstack.h"
#include "kernvm.h"

Go to the source code of this file.

Data Structures

struct  _INTERNAL_CRED
 The beginning of the cred structure as defined by linux kernel. More...
 

Typedefs

typedef struct _INTERNAL_CRED INTERNAL_CRED
 The beginning of the cred structure as defined by linux kernel. More...
 

Functions

static void IntLixCredUninitMap (void)
 Unmaps the cred structure previously mapped by IntLixCredInitMap. More...
 
static INTSTATUS IntLixCredInitMap (QWORD CredGva)
 Maps a cred structure in order to calculate the checksum in a faster manner. More...
 
static void IntLixCredsDump (const LIX_CREDS *Creds)
 Logs information about a cred structure. More...
 
static void IntLixTaskSendCredViolationEvent (const LIX_TASK_OBJECT *Task)
 Sends an EVENT_INTEGRITY_VIOLATION event. More...
 
static DWORD IntLixCredCalculateCrc32Region (DWORD Offset, DWORD Size, DWORD InitialCrc)
 Calculates the CRC32 checksum for a memory region representing a slice of the cred structure. More...
 
static INTSTATUS IntLixCredCalculateChecksum (QWORD CredGva, DWORD *Checksum)
 Calculates the CRC32 checksum for a cred structure. More...
 
INTSTATUS IntLixCredAdd (QWORD CredsGva, LIX_CREDS **Creds)
 Adds a cred structure in the integrity protected credentials list. More...
 
void IntLixCredRemove (LIX_CREDS **Creds)
 Removes the integrity protection for the credentials set that belong to a process. More...
 
static INTSTATUS IntLixCredCheckIntegrity (LIX_CREDS *Creds, BOOLEAN Update, BOOLEAN *Valid)
 Checks if the credentials have been altered. More...
 
void IntLixCredsVerify (LIX_TASK_OBJECT *Task)
 Verifies whether the credentials of a process has been altered or not. More...
 
static void IntLixCredAnalyzeStack (LIX_TASK_OBJECT *Task, INTRO_ACTION *Action, INTRO_ACTION_REASON *Reason)
 Analyze the user mode stack of a process that is patching it's credentials. More...
 
INTSTATUS IntLixCommitCredsHandle (void *Detour)
 Detour handler for "commit_creds" function. More...
 

Variables

static LIST_HEAD gCreds = LIST_HEAD_INIT(gCreds)
 The list head of the credentials structures protected by introcore. More...
 
static QWORD gCredGva = 0
 The guest virtual address of the "struct cred" that is currently being mapped. More...
 
static void * gCredMap1 = NULL
 The mapping point of the cred structure. More...
 
static void * gCredMap2 = NULL
 The secondary mapping point of the cred structure. More...
 
char * gLibPaths []
 Directories where libraries changing credentials should be located. More...
 
char * gLibFiles []
 Libraries allowed to change process credentials. More...
 

Typedef Documentation

◆ INTERNAL_CRED

typedef struct _INTERNAL_CRED INTERNAL_CRED

The beginning of the cred structure as defined by linux kernel.

Subject to change, but these fields are the same since 2.6.32 (maybe older too...)

Function Documentation

◆ IntLixCommitCredsHandle()

INTSTATUS IntLixCommitCredsHandle ( void *  Detour)

Detour handler for "commit_creds" function.

Because a process is able to change it's credentials (by calling setuid(), setgid(), etc) we have to keep track of these changes. The kernel is nice and creates a new "cred" structure for any change, then calls "commit_creds" to install the new credentials set on the current task. However, this new credentials set is based on the previous one which may have been already altered. So, in order to avoid registering an altered credentials set as a clean one, we make one last integrity check on the current set.

This function also checks if the syscall that triggered this change was performed from a known user mode library. Otherwise, a feedback only alert will be sent.

Parameters
[in]DetourUnused.
Returns
INT_STATUS_SUCCESS on success.

Definition at line 694 of file lixcred.c.

◆ IntLixCredAdd()

INTSTATUS IntLixCredAdd ( QWORD  CredsGva,
LIX_CREDS **  Creds 
)

Adds a cred structure in the integrity protected credentials list.

Parameters
[in]CredsGvaThe guest virtual address of the cred structure.
[in]CredsWill contain upon success the reference to the LIX_CRED structure.
Returns
INT_STATUS_SUCCESS On success.
INT_STATUS_NOT_NEEDED_HINT If tokens protection is not activated.
INT_STATUS_INVALID_PARAMETER_1 If the given creds GVA is not a kernel pointer.
INT_STATUS_INVALID_PARAMETER_2 If the Creds parameter does not point to a valid memory region.
INT_STATUS_INSUFFICIENT_RESOURCES If there was not enough memory available.

Definition at line 365 of file lixcred.c.

Referenced by IntLixCommitCredsHandle(), IntLixTaskCreate(), and IntLixTaskCreateFromBinprm().

◆ IntLixCredAnalyzeStack()

static void IntLixCredAnalyzeStack ( LIX_TASK_OBJECT Task,
INTRO_ACTION Action,
INTRO_ACTION_REASON Reason 
)
static

Analyze the user mode stack of a process that is patching it's credentials.

This function will check if the transition from user to kernel was triggered from a known user mode library. See gLibFiles for the list of libraries allowed to perform this action.

Parameters
[in]TaskThe Linux process.
[out]ActionThe action that should be further taken for this event.
[out]ReasonThe reason for the taken action.

Definition at line 578 of file lixcred.c.

◆ IntLixCredCalculateChecksum()

static INTSTATUS IntLixCredCalculateChecksum ( QWORD  CredGva,
DWORD Checksum 
)
static

Calculates the CRC32 checksum for a cred structure.

Will calculate the checksum only for structure regions that actually represent credentials and will ignore fields that may change such as usage, rcu. Thus, we were able to identify three regions:

  1. [0, min(UsageOffset, RcuOffset))
  2. [(min(UsageOffset, RcuOffset) as X) + sizeof(X), max(UsageOffset, RcuOffset))
  3. [(max(UsageOffset, RcuOffset) as X) + sizeof(X), sizeof(cred))

We assume that sizeof(struct cred.usage) is 4 and sizeof(struct cred.rcu) is 16.

Parameters
[in]CredGvaThe guest virtual address of the cred structure.
[out]ChecksumUpon successful return will contain the checksum of the structure.
Returns
INT_STATUS_SUCCESS On success.

Definition at line 295 of file lixcred.c.

Referenced by IntLixCredAdd(), and IntLixCredCheckIntegrity().

◆ IntLixCredCalculateCrc32Region()

static DWORD IntLixCredCalculateCrc32Region ( DWORD  Offset,
DWORD  Size,
DWORD  InitialCrc 
)
static

Calculates the CRC32 checksum for a memory region representing a slice of the cred structure.

The given region may not fit in a single page so we must check the page limits in order to determine where the requested region is mapped. There are three cases:

  1. Whole region is in the first page
  2. Region is split in two pages
  3. Whole region is in second page
Parameters
[in]OffsetThe offset in cred structure where the region begins.
[in]SizeThe size of the region.
[in]InitialCrcThe initial crc32 checksum.
Returns
The CRC32 checksum of the region.

Definition at line 252 of file lixcred.c.

Referenced by IntLixCredCalculateChecksum().

◆ IntLixCredCheckIntegrity()

static INTSTATUS IntLixCredCheckIntegrity ( LIX_CREDS Creds,
BOOLEAN  Update,
BOOLEAN Valid 
)
static

Checks if the credentials have been altered.

Parameters
[in]CredsThe credentials set.
[in]UpdateWhether the checksum should be updated if changed or not.
[out]ValidWill contain upon successful return the check result.
Returns
INT_STATUS_SUCCESS On success.
INT_STATUS_NOT_NEEDED_HINT If tokens protection is not enabled.
INT_STATUS_INVALID_PARAMETER_1 If the Creds parameter does not point to a valid LIX_CREDS object.
INT_STATUS_INVALID_PARAMETER_2 If the Valid parameter does not represent a valid memory region.

Definition at line 477 of file lixcred.c.

Referenced by IntLixCredsVerify().

◆ IntLixCredInitMap()

static INTSTATUS IntLixCredInitMap ( QWORD  CredGva)
static

Maps a cred structure in order to calculate the checksum in a faster manner.

Parameters
[in]CredGvaThe guest virtual address of the creds structure to be mapped.
Returns
INT_STATUS_SUCCESS On success.

Definition at line 117 of file lixcred.c.

Referenced by IntLixCredCalculateChecksum().

◆ IntLixCredRemove()

void IntLixCredRemove ( LIX_CREDS **  Creds)

Removes the integrity protection for the credentials set that belong to a process.

This function will decrement the credentials refcount and will completely remove them when the refcount reaches 0.

Parameters
[in]CredsThe credentials to be unprotected.

Definition at line 441 of file lixcred.c.

Referenced by IntLixCommitCredsHandle(), IntLixTaskDestroy(), and IntLixTaskRemoveEntry().

◆ IntLixCredsDump()

static void IntLixCredsDump ( const LIX_CREDS Creds)
static

Logs information about a cred structure.

Parameters
[in]CredsThe LIX_CREDS structure associated with the credentials.

Definition at line 159 of file lixcred.c.

Referenced by IntLixTaskSendCredViolationEvent().

◆ IntLixCredsVerify()

void IntLixCredsVerify ( LIX_TASK_OBJECT Task)

Verifies whether the credentials of a process has been altered or not.

Parameters
[in]TaskThe Linux process.

Definition at line 534 of file lixcred.c.

Referenced by IntLixCommitCredsHandle(), IntLixTaskAdd(), IntLixTaskDestroy(), and IntLixTaskHandleExec().

◆ IntLixCredUninitMap()

static void IntLixCredUninitMap ( void  )
static

Unmaps the cred structure previously mapped by IntLixCredInitMap.

Definition at line 90 of file lixcred.c.

Referenced by IntLixCredCalculateChecksum(), and IntLixCredInitMap().

◆ IntLixTaskSendCredViolationEvent()

static void IntLixTaskSendCredViolationEvent ( const LIX_TASK_OBJECT Task)
static

Sends an EVENT_INTEGRITY_VIOLATION event.

Parameters
[in]TaskThe process accused of credential violence.

Definition at line 191 of file lixcred.c.

Referenced by IntLixCredsVerify().

Variable Documentation

◆ gCredGva

QWORD gCredGva = 0
static

The guest virtual address of the "struct cred" that is currently being mapped.

Definition at line 44 of file lixcred.c.

Referenced by IntLixCredCalculateCrc32Region(), IntLixCredInitMap(), and IntLixCredUninitMap().

◆ gCredMap1

void* gCredMap1 = NULL
static

The mapping point of the cred structure.

Definition at line 49 of file lixcred.c.

Referenced by IntLixCredCalculateCrc32Region(), IntLixCredInitMap(), and IntLixCredUninitMap().

◆ gCredMap2

void* gCredMap2 = NULL
static

The secondary mapping point of the cred structure.

The mapping point of second page if the cred structure that is currently mapped doesn't fit in one single page.The second mapping point of the cred structure if it doesn't fit in the f

Definition at line 57 of file lixcred.c.

Referenced by IntLixCredCalculateCrc32Region(), IntLixCredInitMap(), and IntLixCredUninitMap().

◆ gCreds

LIST_HEAD gCreds = LIST_HEAD_INIT(gCreds)
static

The list head of the credentials structures protected by introcore.

Definition at line 39 of file lixcred.c.

◆ gLibFiles

char* gLibFiles[]
Initial value:
=
{
"libc-2.??.so",
"libpthread-2.??.so",
}

Libraries allowed to change process credentials.

Definition at line 82 of file lixcred.c.

Referenced by IntLixCredAnalyzeStack().

◆ gLibPaths

char* gLibPaths[]
Initial value:
=
{
"/lib/*",
"/lib64/*",
"/lib32/*",
"/usr/lib/*",
"/usr/lib32/*",
"/usr/lib64/*",
"/@/.snapshots/*/snapshots/lib64/*",
"/@/.snapshots/*/snapshots/lib32/*",
"/@/.snapshots/*/snapshots/lib/*",
"/@/.snapshots/*/snapshot/lib64/*",
"/@/.snapshots/*/snapshot/lib32/*",
"/@/.snapshots/*/snapshot/lib/*",
}

Directories where libraries changing credentials should be located.

Definition at line 62 of file lixcred.c.

Referenced by IntLixCredAnalyzeStack().