How to Use Libaudit

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



Leave a reply



Submit