Using the system programs Klog and KlogStorage to perform a security audit
To perform a security audit, the system program Klog receives audit data from the KasperskyOS kernel by using the libkos library, decodes this data and forwards it via IPC to the system program KlogStorage, which acts as the server in this IPC interaction. The KlogStorage program sends audit data to standard output (or standard error) or saves it to a file by using VFS. The KlogStorage program can also forward file-written audit data to other programs via IPC.
The executable files of the Klog and KlogStorage programs are not provided in the KasperskyOS SDK. You will need to create them based on the provided static libraries.
Example of adding the system program Klog to a solution
Source code of the program
einit/src/klog_entity.c
#include<klog/system_audit.h>#include<klog_storage/client.h>#include<ping/KlogEntity.edl.h>intmain(int argc, char *argv[]){
/* This function call creates a thread
* that receives audit data from the kernel, decodes it and forwards it
* via IPC to the KlogStorage program.
* (The constant ping_KlogEntity_klog_audit_iid is defined in the header
* file KlogEntity.edl.h, which contains the automatically generated
* transport code.) */returnklog_system_audit_run(KLOG_SERVER_CONNECTION_ID ":
" KLOG_STORAGE_SERVER_CONNECTION_ID,
ping_KlogEntity_klog_audit_iid);
}
Building a program
einit/CMakeLists.txt
...
# Import Klog libraries from the# KasperskyOS SDKfind_package (klog REQUIRED)
include_directories (${klog_INCLUDE})
# Generate transport code based on the formal specification of the# Klog program
nk_build_edl_files (klog_edl_files
NK_MODULE "ping"# The KlogEntity.edl file and other files# in the formal specification of the Klog program# are provided in the KasperskyOS SDK.
EDL "${RESOURCES}/edl/KlogEntity.edl")
# Create the executable file of the Klog program for the hardware platformadd_executable (KlogEntityHw "src/klog_entity.c")
target_link_libraries (KlogEntityHw ${klog_SYSTEM_AUDIT_LIB})
add_dependencies (KlogEntityHw klog_edl_files)
# Create the executable file of the Klog program for QEMU.# (Identical to creating the executable file of the Klog program for# the hardware platform, except for the build target name.# Requires two build targets for the executable file of the# Klog program with different names because the KLOG_ENTITY parameter of the# CMake commands build_kos_hw_image() and build_kos_qemu_image()# must specify different build targets.)add_executable (KlogEntityQemu "src/klog_entity.c")
target_link_libraries (KlogEntityQemu ${klog_SYSTEM_AUDIT_LIB})
add_dependencies (KlogEntityQemu klog_edl_files)
# The Klog program does not need to be specified together with other programs# to be included in the solution image. To include the Klog program# in a solution, you must define the name of the build target for the executable file of this# program via the KLOG_ENTITY parameter of the CMake commands# build_kos_hw_image() and build_kos_qemu_image().set (ENTITIES Client Server KlogStorageEntity FileVfs)
...
# The INIT_KlogEntity_PATH variable is used in the init.yaml.in file# to define the name of the Klog program executable file. (The executable# files of the Klog program for QEMU and for the hardware platform have# different names that match the names of the build targets# of these files by default.)set (INIT_KlogEntity_PATH "KlogEntityHw")
# You must define the KLOG_ENTITY parameter
build_kos_hw_image (kos-image
EINIT_ENTITY EinitHw
...
KLOG_ENTITY KlogEntityHw
IMAGE_FILES ${ENTITIES})
# The INIT_KlogEntity_PATH variable is used in the init.yaml.in file# to define the name of the Klog program executable file. (The executable# files of the Klog program for QEMU and for the hardware platform have# different names that match the names of the build targets# of these files by default.)set (INIT_KlogEntity_PATH "KlogEntityQemu")
# You must define the KLOG_ENTITY parameter
build_kos_qemu_image (kos-qemu-image
EINIT_ENTITY EinitQemu
...
KLOG_ENTITY KlogEntityQemu
IMAGE_FILES ${ENTITIES})
Program process dictionary in the init description template
einit/src/init.yaml.in
...-name:ping.KlogEntity# The variable INIT_KlogEntity_PATH is defined in the file einit/CMakeLists.txt.path:@INIT_KlogEntity_PATH@connections:-target:ping.KlogStorageEntityid: {var:KLOG_STORAGE_SERVER_CONNECTION_ID, include:klog_storage/client.h}
...
Policy description for the program
einit/src/security.psl.in
...
use nk.base._
...
use EDL kl.core.Core
...
use EDL ping.KlogEntity
use EDL ping.KlogStorageEntity
...
use audit_profile._
use core._
...
/* Interaction with the KlogStorage program */
request dst=ping.KlogStorageEntity {
match endpoint=klogStorage.storage {
match method=write {
match src=ping.KlogEntity { grant () }
}
}
}
response src=ping.KlogStorageEntity {
match endpoint=klogStorage.storage {
match method=write {
match dst=ping.KlogEntity { grant () }
}
}
}
error src=ping.KlogStorageEntity {
match endpoint=klogStorage.storage {
match method=write {
match dst=ping.KlogEntity { grant () }
}
}
}
...
einit/src/core.psl
...
/* Interaction with the kernel */
request dst=kl.core.Core {
match endpoint=sync.Sync {
match method=Wake {
...
match src=ping.KlogEntity { grant () }
...
}
match method=Wait {
...
match src=ping.KlogEntity { grant () }
...
}
}
match endpoint=task.Task {
match method=FreeSelfEnv {
...
match src=ping.KlogEntity { grant () }
...
}
match method=GetPath {
...
match src=ping.KlogEntity { grant () }
...
}
match method=GetName {
...
match src=ping.KlogEntity { grant () }
...
}
match method=Exit {
...
match src=ping.KlogEntity { grant () }
...
}
}
match endpoint=vmm.VMM {
match method=Allocate {
...
match src=ping.KlogEntity { grant () }
...
}
match method=Commit {
...
match src=ping.KlogEntity { grant () }
...
}
match method=Protect {
...
match src=ping.KlogEntity { grant () }
...
}
match method=Free {
...
match src=ping.KlogEntity { grant () }
...
}
}
match endpoint=thread.Thread {
match method=SetTls {
...
match src=ping.KlogEntity { grant () }
...
}
match method=Create {
...
match src=ping.KlogEntity { grant () }
...
}
match method=Resume {
...
match src=ping.KlogEntity { grant () }
...
}
match method=Attach {
...
match src=ping.KlogEntity { grant () }
...
}
match method=Exit {
...
match src=ping.KlogEntity { grant () }
...
}
match method=GetSchedPolicy {
...
match src=ping.KlogEntity { grant () }
...
}
match method=SetSchedPolicy {
...
match src=ping.KlogEntity { grant () }
...
}
}
match endpoint=hal.HAL {
match method=GetEntropy {
...
match src=ping.KlogEntity { grant () }
...
}
match method=DebugWrite {
...
match src=ping.KlogEntity { grant () }
...
}
match method=GetEnv {
...
match src=ping.KlogEntity { grant () }
...
}
}
match endpoint=handle.Handle {
match method=Close {
...
match src=ping.KlogEntity { grant () }
...
}
}
match endpoint=audit.Audit {
match src=ping.KlogEntity { grant () }
}
}
response src=kl.core.Core {
...
match dst=ping.KlogEntity { grant () }
...
}
error src=kl.core.Core {
...
match dst=ping.KlogEntity { grant () }
...
}
...
Example of adding the system program KlogStorage to a solution to forward audit data to standard error
Source code of the program
klog_storage/src/klog_storage_entity.c
#include<klog_storage/server.h>#include<ping/KlogStorageEntity.edl.h>#include<stdio.h>/* Define the data type for a fictitious context.
* Required for defining functions that implement
* interface methods, and for dispatcher configuration. */structContext
{
int some_data;
};
/* Define the function that forwards audit data to
* standard error. (Use of the ctx parameter is not required, but a
* void* type parameter must be the first parameter in the function signature to
* match the type of pointer that is used by the dispatcher
* to call this function.) */staticint _write(struct Context *ctx, conststruct kl_KlogStorage_Entry *entry)
{
fprintf(stderr, "%s\n", entry->msg);
return0;
}
/* Define a fictitious function for reading audit data.
* (Required for dispatcher configuration to avoid errors
* if the interface method for reading audit data is called.) */staticint _read_range(struct Context *ctx, nk_uint64_t first_id,
nk_uint64_t last_id, struct kl_KlogStorage_Entry *entries)
{
return0;
}
/* Define a fictitious function for reading audit data.
* (Required for dispatcher configuration to avoid errors
* if the interface method for reading audit data is called.) */staticint _read(struct Context *ctx, nk_uint32_t num_entries,
struct kl_KlogStorage_Entry *entries)
{
return0;
}
intmain(int argc, char *argv[]){
/* Declaration of a fictitious context */staticstructContext ctx;
/* Configure the dispatcher so that when IPC requests
* containing audit data are received from the Klog program, the dispatcher calls the function that forwards
* this data to standard error. (The functions for reading audit data
* and the context are fictitious.However, you can create your own
* implementations of the _write(), _read() and _read_range() functions for working with
* audit data storage.In this case, the context may be
* used to store the storage state.) */structkl_KlogStorage *iface =
klog_storage_IKlog_storage_dispatcher(&ctx,
(kl_KlogStorage_write_func)_write,
(kl_KlogStorage_read_func)_read,
(kl_KlogStorage_read_range_func)_read_range);
structkl_KlogStorage_component *comp =klog_storage_storage_component(iface);
/* This function call starts the IPC request processing loop.
* (The constants ping_KlogStorageEntity_klogStorage_iidOffset and
* ping_KlogStorageEntity_klogStorage_storage_iid are defined in the header file
* KlogStorageEntity.edl.h, which contains the automatically generated
* transport code.) */returnklog_storage_run(KLOG_STORAGE_SERVER_CONNECTION_ID,
ping_KlogStorageEntity_klogStorage_iidOffset,
ping_KlogStorageEntity_klogStorage_storage_iid,
comp);
}
Building a program
klog_storage/CMakeLists.txt
# Import KlogStorage libraries from the# KasperskyOS SDKfind_package (klog_storage REQUIRED)
include_directories (${klog_storage_INCLUDE})
# Generate transport code based on the formal specification of the# KlogStorage program
nk_build_edl_files (klog_storage_edl_files
NK_MODULE "ping"# The KlogStorageEntity.edl file and other files# in the formal specification of the KlogStorage program# are provided in the KasperskyOS SDK.
EDL "${RESOURCES}/edl/KlogStorageEntity.edl")
# Create the executable file of the KlogStorage programadd_executable (KlogStorageEntity "src/klog_storage_entity.c")
target_link_libraries (KlogStorageEntity ${klog_storage_SERVER_LIB})
add_dependencies (KlogStorageEntity klog_edl_files klog_storage_edl_files)
Program process dictionary in the init description template
einit/src/init.yaml.in
...-name:ping.KlogStorageEntity...
Policy description for the program
einit/src/security.psl.in
...
use nk.base._
...
use EDL kl.core.Core
...
use EDL ping.KlogEntity
use EDL ping.KlogStorageEntity
...
use audit_profile._
use core._
...
/* Interaction with the Klog program */
request dst=ping.KlogStorageEntity {
match endpoint=klogStorage.storage {
match method=write {
match src=ping.KlogEntity { grant () }
}
}
}
response src=ping.KlogStorageEntity {
match endpoint=klogStorage.storage {
match method=write {
match dst=ping.KlogEntity { grant () }
}
}
}
error src=ping.KlogStorageEntity {
match endpoint=klogStorage.storage {
match method=write {
match dst=ping.KlogEntity { grant () }
}
}
}
...
einit/src/core.psl
...
/* Interaction with the kernel */
request dst=kl.core.Core {
match endpoint=sync.Sync {
match method=Wake {
...
match src=ping.KlogStorageEntity { grant () }
...
}
match method=Wait {
...
match src=ping.KlogStorageEntity { grant () }
...
}
}
match endpoint=task.Task {
match method=FreeSelfEnv {
...
match src=ping.KlogStorageEntity { grant () }
...
}
match method=GetPath {
...
match src=ping.KlogStorageEntity { grant () }
...
}
match method=GetName {
...
match src=ping.KlogStorageEntity { grant () }
...
}
match method=Exit {
...
match src=ping.KlogStorageEntity { grant () }
...
}
}
match endpoint=vmm.VMM {
match method=Allocate {
...
match src=ping.KlogStorageEntity { grant () }
...
}
match method=Commit {
...
match src=ping.KlogStorageEntity { grant () }
...
}
match method=Protect {
...
match src=ping.KlogStorageEntity { grant () }
...
}
match method=Free {
...
match src=ping.KlogStorageEntity { grant () }
...
}
}
match endpoint=thread.Thread {
match method=SetTls {
...
match src=ping.KlogStorageEntity { grant () }
...
}
match method=Create {
...
match src=ping.KlogStorageEntity { grant () }
...
}
match method=Resume {
...
match src=ping.KlogStorageEntity { grant () }
...
}
}
match endpoint=hal.HAL {
match method=GetEntropy {
...
match src=ping.KlogStorageEntity { grant () }
...
}
match method=DebugWrite {
...
match src=ping.KlogStorageEntity { grant () }
...
}
match method=GetEnv {
...
match src=ping.KlogStorageEntity { grant () }
...
}
}
match endpoint=handle.Handle {
match method=Close {
...
match src=ping.KlogStorageEntity { grant () }
...
}
}
}
response src=kl.core.Core {
...
match dst=ping.KlogStorageEntity { grant () }
...
}
error src=kl.core.Core {
...
match dst=ping.KlogStorageEntity { grant () }
...
}
...
Example of adding the system program KlogStorage to a solution to write audit data to a file
Source code of the program
klog_storage/src/klog_storage_entity.c
#include<klog_storage/server.h>#include<klog_storage/file_storage.h>#include<ping/KlogStorageEntity.edl.h>intmain(int argc, char *argv[]){
/* This function call starts the IPC request processing loop.
* The audit data will be written to the file /etc/klog_storage.log, which can
* hold no more than 100 entries. When the file is completely full, the previous
* entries will be replaced by new entries starting at the beginning of the file. If the last parameter
* of the function has a value other than 1, the KlogStorage program at startup
* opens the existing file and begins to write audit data at the specific position
* that was set in the file after the previous write operation. If the last
* parameter of the function has a value of 1, a new empty file will be created.
* (The constants ping_KlogStorageEntity_klogStorage_iidOffset and
* ping_KlogStorageEntity_klogStorage_storage_iid are defined in the header
* file KlogStorageEntity.edl.h, which contains the automatically generated
* transport code.) */returnklog_storage_file_storage_run(KLOG_STORAGE_SERVER_CONNECTION_ID,
"/etc/klog_storage.log",
ping_KlogStorageEntity_klogStorage_iidOffset,
ping_KlogStorageEntity_klogStorage_storage_iid,
100,
0);
}
Building a program
The difference between the CMake commands for building the KlogStorage program that writes audit data to a file and the CMake commands for building the version of this program that sends audit data to standard error comprises the following modification:
klog_storage/CMakeLists.txt
...
# When creating the executable file of the KlogStorage program, you must# link it to the klog_storage_file_storage library.target_link_libraries (KlogStorageEntity ${klog_storage_FILE_STORAGE_LIB})
...
Program process dictionary in the init description template
The difference between a policy description for a KlogStorage program that writes audit data to a file and a policy description for a version of this program that sends audit data to standard error comprises the following addition:
einit/src/security.psl.in
...
use EDL file_vfs.FileVfs
...
use vfs._
...
einit/src/vfs.psl
...
/* Interaction with the VFS program */
request dst=file_vfs.FileVfs {
match src=ping.KlogStorageEntity { grant () }
}
response src=file_vfs.FileVfs {
match dst=ping.KlogStorageEntity { grant () }
}
error src=file_vfs.FileVfs {
match dst=ping.KlogStorageEntity { grant () }
}
...
Forwarding audit data to other programs
To forward file-written audit data via IPC, the KlogStorage program provides the read and readRange interface methods defined in the file sysroot-*-kos/include/kl/KlogStorage.idl from the KasperskyOS SDK.
The executable file of the program that needs to receive the audit data must be linked to the client library of the KlogStorage program:
klog_reader/CMakeLists.txt
# Import KlogStorage libraries from the# KasperskyOS SDKfind_package (klog_storage REQUIRED)
include_directories (${klog_storage_INCLUDE})
...
# Create the executable file of the program that needs to# receive audit data from the KlogStorage program.add_executable (KlogReader "src/klog_reader.c")
target_link_libraries (KlogReader ${klog_storage_CLIENT_LIB})
...
Source code for receiving audit data from the KlogStorage program:
klog_reader/src/klog_reader.c
#include<klog_storage/client.h>
...
intmain(int argc, char *argv[]){
...
structKlog_storage_ctx *storage =
klog_storage_init(KLOG_STORAGE_SERVER_CONNECTION_ID);
structkl_KlogStorage_Entry first_entries[10], latest_entries [10];
/* Read the first ten entries */int f_count = klog_storage_read_range(klog_storage_IKlog_storage(storage),
1,
10,
first_entries);
/* Read the last ten entries */int l_count = klog_storage_read(klog_storage_IKlog_storage(storage),
10,
latest_entries);
...
}