How to use libaudit?
I found a solution. Here is an example of the minimum working code.
The libaudit provides an interface for adding/removing rules:
int fd = audit_open();
struct audit_rule_data *rule = new audit_rule_data();
// what directory we will follow.
audit_add_watch_dir(AUDIT_DIR,
&rule,
"/etc");
// setting rule.
audit_add_rule_data(fd,
rule,
AUDIT_FILTER_EXIT,
AUDIT_ALWAYS);
// or removing rule.
audit_delete_rule_data(fd,
rule,
AUDIT_FILTER_EXIT,
AUDIT_ALWAYS);
audit_close(fd);
To set some specific event and set an additional filter you need to do something like this:
int fd = audit_open();
audit_rule_syscallbyname_data(rule_new, "open");
audit_rule_syscallbyname_data(rule_new, "close");
// Set extra filter, for example, follow the user with id=1000.
char pair[] = "uid=1000";
audit_rule_fieldpair_data(&rule_new, pair, AUDIT_FILTER_EXIT);
audit_add_rule_data(fd, rule_new, AUDIT_FILTER_EXIT, AUDIT_ALWAYS);
audit_close(fd);
To make an exception to the rules you need:
audit_rule_syscallbyname_data(rule, "mkdir");
char pair[] = "path=/etc";
audit_rule_fieldpair_data(&rule,
pair,
AUDIT_FILTER_EXIT);
audit_add_rule_data(fd,
rule,
AUDIT_FILTER_EXIT,
AUDIT_NEVER);
To receive messages from the audit:
void monitoring(struct ev_loop *loop, struct ev_io *io, int revents)
{
struct audit_reply reply;
audit_get_reply(fd, &reply, GET_REPLY_NONBLOCKING, 0);
if (reply.type != AUDIT_EOE &&
reply.type != AUDIT_PROCTITLE &&
reply.type != AUDIT_PATH)
{
char *buf = new char[MAX_AUDIT_MESSAGE_LENGTH];
snprintf(buf,
MAX_AUDIT_MESSAGE_LENGTH,
"Type=%s Message=%.*s",
audit_msg_type_to_name(reply.type),
reply.len,
reply.message);
printf("EVENT: %s\n", buf);
}
}
int main()
{
struct ev_io monitor;
fd = audit_open();
audit_set_pid(fd, getpid(), WAIT_YES);
loop = ev_default_loop(EVFLAG_NOENV);
ev_io_init(&monitor, monitoring, fd, EV_READ);
ev_io_start(loop, &monitor);
ev_loop(loop, 0);
audit_close(fd);
return 0;
}
UPD.
Your audit will not work if you do not write:
audit_set_enabled(audit_fd, 1);
how to use audit in linux to monitor a file using libaudit
It turns out I forgot to run with sudo, this can only be run with root permission but it did not crash, just nothing was reported.
Why dynamic linked binary shows hard coded SO name?
All right, I find the cause.
It's due to some reference of "_edata" and "_end" in my code.
In libpam.so, it is not found but libaudit.so which is needed for libpam.so, it was found and linker resolved it, then add libaudit as "NEEDED".
And _end is exposed as follows from linker scripts –
_end = .; PROVIDE (end = .);
This means, we should be using “end” and not “_end” unless we PROVIDE “_end” with our own linker scripts.
So, the fix is to change _end (and all such related symbols like _etext and _edata) to end (and etext, edata) so that they will be resolved correctly from standard libc, avoiding any dependency on other shared objects like libaudit.so.
Monitor chattr changes
struct ev_loop* loop = nullptr;
int fd = 0;
void
sig_handler(int signo)
{
if (signo == SIGINT)
printf("received SIGINT\n");
else if (signo == SIGTERM)
printf("received SIGTERM\n");
else if (signo == SIGBUS)
printf("received SIGBUS\n");
else if (signo == SIGABRT)
printf("received SIGABRT\n");
if (loop != nullptr) {
std::cout << "Stopping event loop" << std::endl;
ev_break(EV_A_ EVBREAK_ONE);
}
}
void
monitoring(struct ev_loop* loop, struct ev_io* io, int revents)
{
struct audit_reply reply;
audit_get_reply(fd, &reply, GET_REPLY_NONBLOCKING, 0);
if (reply.type != AUDIT_EOE && reply.type != AUDIT_PROCTITLE &&
reply.type != AUDIT_PATH) {
char* buf = new char[MAX_AUDIT_MESSAGE_LENGTH];
snprintf(buf,
MAX_AUDIT_MESSAGE_LENGTH,
"Type=%s Message=%.*s",
audit_msg_type_to_name(reply.type),
reply.len,
reply.message);
printf("EVENT: %s\n", buf);
}
}
int
main()
{
std::cout << "Starting up..." << std::endl;
if (signal(SIGINT, sig_handler) == SIG_ERR) {
printf("can't catch SIGINT\n");
}
if (signal(SIGTERM, sig_handler) == SIG_ERR) {
printf("can't catch SIGTERM\n");
}
if (signal(SIGBUS, sig_handler) == SIG_ERR) {
printf("can't catch SIGBUS\n");
}
if (signal(SIGABRT, sig_handler) == SIG_ERR) {
printf("can't catch SIGABRT\n");
}
struct ev_io monitor;
fd = audit_open();
audit_set_pid(fd, getpid(), WAIT_YES);
struct audit_rule_data* rule = new audit_rule_data();
std::cout << "Add watch dir..." << std::endl;
audit_add_watch_dir(AUDIT_DIR, &rule, "test");
// setting rule.
audit_add_rule_data(fd, rule, AUDIT_FILTER_EXIT, AUDIT_ALWAYS);
loop = EV_DEFAULT;
ev_io_init(&monitor, monitoring, fd, EV_READ);
std::cout << "Enable audit..." << std::endl;
audit_set_enabled(fd, 1);
std::cout << "Start io monitor..." << std::endl;
ev_io_start(loop, &monitor);
std::cout << "Start event loop..." << std::endl;
// now wait for events to arrive
ev_run(loop, 0);
std::cout << "Closing audit..." << std::endl;
audit_close(fd);
delete rule;
std::cout << "Bye" << std::endl;
return 0;
}
selinux: How to programmatically log to audit log?
If you are using C/C++ you can interact with auditd (the one responsible for writing to audit.log) with the library "audit-libs" by including "libaudit.h".
If you have the development library installed read the manual page of audit_open (man audit_open), or take a look here: http://linux.die.net/man/3/audit_open
I gathered most information from the following sites:
http://www.mail-archive.com/linux-audit@redhat.com/msg01093.html
http://www.linuxquestions.org/questions/linux-kernel-70/interfacing-with-the-auditd-737239/
Related Topics
Hello World Python Extension in C++ Using Boost
Headers Including Each Other in C++
Problems with Std::Stoi, Not Working on Mingw Gcc 4.7.2
Create a Directory If It Doesn't Exist
Porting Clock_Gettime to Windows
What Is the Default Constructor for C++ Pointer
Best Documentation for Boost:Asio
Difference Between Std::System_Clock and Std::Steady_Clock
Checking for an Empty File in C++
Send Mail Using Smtp in C++ on Linux
How to Write Log Base(2) in C/C++
How to Access the Underlying Container of Stl Container Adaptors
Start Windows Service from Application Without Admin Right(C++)
Convert Mat to Array/Vector in Opencv
Converting Multidimensional Arrays to Pointers in C++
Is It Smart to Replace Boost::Thread and Boost::Mutex with C++11 Equivalents