Changeset View
Standalone View
tests/sys/auditpipe/auditpipe_test.c
Show All 26 Lines | |||||
#include <sys/ioctl.h> | #include <sys/ioctl.h> | ||||
#include <bsm/audit.h> | #include <bsm/audit.h> | ||||
#include <security/audit/audit_ioctl.h> | #include <security/audit/audit_ioctl.h> | ||||
#include <atf-c.h> | #include <atf-c.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <limits.h> | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
static int filedesc; | static int filedesc; | ||||
static FILE *fileptr; | static FILE *fileptr; | ||||
ATF_TC(auditpipe_get_qlen); | ATF_TC(auditpipe_get_qlen); | ||||
ATF_TC_HEAD(auditpipe_get_qlen, tc) | ATF_TC_HEAD(auditpipe_get_qlen, tc) | ||||
Show All 36 Lines | atf_tc_set_md_var(tc, "descr", "Verifies whether the auditpipe ioctl, " | ||||
"AUDITPIPE_SET_QLIMIT works properly"); | "AUDITPIPE_SET_QLIMIT works properly"); | ||||
} | } | ||||
ATF_TC_BODY(auditpipe_set_qlimit, tc) | ATF_TC_BODY(auditpipe_set_qlimit, tc) | ||||
{ | { | ||||
int test_qlimit, curr_qlimit, recv_qlimit; | int test_qlimit, curr_qlimit, recv_qlimit; | ||||
ATF_REQUIRE((filedesc = open("/dev/auditpipe", O_RDONLY)) != -1); | ATF_REQUIRE((filedesc = open("/dev/auditpipe", O_RDONLY)) != -1); | ||||
/* Retreive the current QLIMIT value and store it in a file */ | /* Retrieve the current QLIMIT value and store it in a file */ | ||||
ATF_REQUIRE_EQ(0, ioctl(filedesc, AUDITPIPE_GET_QLIMIT, &curr_qlimit)); | ATF_REQUIRE_EQ(0, ioctl(filedesc, AUDITPIPE_GET_QLIMIT, &curr_qlimit)); | ||||
ATF_REQUIRE((fileptr = fopen("qlimit_store", "a")) != NULL); | ATF_REQUIRE((fileptr = fopen("qlimit_store", "a")) != NULL); | ||||
ATF_REQUIRE_EQ(sizeof(curr_qlimit), | ATF_REQUIRE_EQ(sizeof(curr_qlimit), | ||||
fprintf(fileptr, "%d\n", curr_qlimit)); | fprintf(fileptr, "%d\n", curr_qlimit)); | ||||
/* | /* | ||||
* Set QLIMIT different from the current system value to confirm | * Set QLIMIT different from the current system value to confirm | ||||
* proper functioning of AUDITPIPE_SET_QLIMIT ioctl. | * proper functioning of AUDITPIPE_SET_QLIMIT ioctl. | ||||
▲ Show 20 Lines • Show All 54 Lines • ▼ Show 20 Lines | ATF_TC_BODY(auditpipe_get_qlimit_max, tc) | ||||
int qlim_max = -1; | int qlim_max = -1; | ||||
ATF_REQUIRE((filedesc = open("/dev/auditpipe", O_RDONLY)) != -1); | ATF_REQUIRE((filedesc = open("/dev/auditpipe", O_RDONLY)) != -1); | ||||
ATF_REQUIRE_EQ(0, ioctl(filedesc, AUDITPIPE_GET_QLIMIT_MAX, &qlim_max)); | ATF_REQUIRE_EQ(0, ioctl(filedesc, AUDITPIPE_GET_QLIMIT_MAX, &qlim_max)); | ||||
ATF_REQUIRE(qlim_max != -1); | ATF_REQUIRE(qlim_max != -1); | ||||
close(filedesc); | close(filedesc); | ||||
} | } | ||||
ATF_TC(auditpipe_qlimit_more_than_qlimit_min); | |||||
ATF_TC_HEAD(auditpipe_qlimit_more_than_qlimit_min, tc) | |||||
{ | |||||
atf_tc_set_md_var(tc, "descr", "Verifies that limit for audit records " | |||||
"in auditpipe cannot be less than QLIMIT_MIN "); | |||||
} | |||||
ATF_TC_BODY(auditpipe_qlimit_more_than_qlimit_min, tc) | |||||
{ | |||||
int qlim_min; | |||||
ATF_REQUIRE((filedesc = open("/dev/auditpipe", O_RDONLY)) != -1); | |||||
ATF_REQUIRE_EQ(0, ioctl(filedesc, AUDITPIPE_GET_QLIMIT_MIN, &qlim_min)); | |||||
qlim_min -= 1; | |||||
ATF_REQUIRE_EQ(-1, ioctl(filedesc, AUDITPIPE_SET_QLIMIT, &qlim_min)); | |||||
close(filedesc); | |||||
} | |||||
ATF_TC(auditpipe_qlimit_less_than_qlimit_max); | |||||
ATF_TC_HEAD(auditpipe_qlimit_less_than_qlimit_max, tc) | |||||
{ | |||||
atf_tc_set_md_var(tc, "descr", "Verifies that limit for audit records " | |||||
"in auditpipe cannot be more than QLIMIT_MAX "); | |||||
} | |||||
ATF_TC_BODY(auditpipe_qlimit_less_than_qlimit_max, tc) | |||||
{ | |||||
int qlim_max; | |||||
ATF_REQUIRE((filedesc = open("/dev/auditpipe", O_RDONLY)) != -1); | |||||
ATF_REQUIRE_EQ(0, ioctl(filedesc, AUDITPIPE_GET_QLIMIT_MAX, &qlim_max)); | |||||
qlim_max += 1; | |||||
ATF_REQUIRE_EQ(-1, ioctl(filedesc, AUDITPIPE_SET_QLIMIT, &qlim_max)); | |||||
close(filedesc); | |||||
} | |||||
ATF_TC(auditpipe_get_maxauditdata); | ATF_TC(auditpipe_get_maxauditdata); | ||||
ATF_TC_HEAD(auditpipe_get_maxauditdata, tc) | ATF_TC_HEAD(auditpipe_get_maxauditdata, tc) | ||||
{ | { | ||||
atf_tc_set_md_var(tc, "descr", "Verifies whether the auditpipe ioctl, " | atf_tc_set_md_var(tc, "descr", "Verifies whether the auditpipe ioctl, " | ||||
"AUDITPIPE_GET_MAXAUDITDATA works properly"); | "AUDITPIPE_GET_MAXAUDITDATA works properly"); | ||||
} | } | ||||
ATF_TC_BODY(auditpipe_get_maxauditdata, tc) | ATF_TC_BODY(auditpipe_get_maxauditdata, tc) | ||||
{ | { | ||||
int audata = -1; | int audata = -1; | ||||
ATF_REQUIRE((filedesc = open("/dev/auditpipe", O_RDONLY)) != -1); | ATF_REQUIRE((filedesc = open("/dev/auditpipe", O_RDONLY)) != -1); | ||||
ATF_REQUIRE_EQ(0, ioctl(filedesc, AUDITPIPE_GET_MAXAUDITDATA, &audata)); | ATF_REQUIRE_EQ(0, ioctl(filedesc, AUDITPIPE_GET_MAXAUDITDATA, &audata)); | ||||
ATF_REQUIRE(audata != -1); | ATF_REQUIRE(audata != -1); | ||||
close(filedesc); | close(filedesc); | ||||
} | } | ||||
ATF_TC(auditpipe_flush); | |||||
ATF_TC_HEAD(auditpipe_flush, tc) | |||||
{ | |||||
atf_tc_set_md_var(tc, "descr", "Verifies whether the auditpipe ioctl, " | |||||
"AUDITPIPE_FLUSH works properly"); | |||||
} | |||||
ATF_TC_BODY(auditpipe_flush, tc) | |||||
{ | |||||
int qlen, aucond; | |||||
int aupause = AUC_NOAUDIT; | |||||
int auresume = AUC_AUDITING; | |||||
ATF_REQUIRE((filedesc = open("/dev/auditpipe", O_RDONLY)) != -1); | |||||
/* | |||||
asomers: This test isn't going to be reliable. You have no way to be sure that more auditable events… | |||||
* If auditing is enabled, stop it to make sure no events are emitted | |||||
* in auditpipe between calling AUDITPIPE_FLUSH and AUDITPIPE_GET_QLEN. | |||||
*/ | |||||
Not Done Inline ActionsWhat happens if aucond was anything else? Then the test will be pointless, because there won't be anything in the audit trail. In that case, you should skip it. Or, start auditd just like you do in the audit tests. asomers: What happens if `aucond` was anything else? Then the test will be pointless, because there… | |||||
ATF_REQUIRE_EQ(0, auditon(A_GETCOND, &aucond, sizeof(int))); | |||||
if (aucond == AUC_AUDITING) | |||||
Not Done Inline ActionsNope. In order for this technique to work, you need to stop auditing _before_ AUDITPIPE_FLUSH. asomers: Nope. In order for this technique to work, you need to stop auditing _before_… | |||||
ATF_REQUIRE_EQ(0, auditon(A_SETCOND, &aupause, sizeof(int))); | |||||
Not Done Inline ActionsThis won't work either. By opening the auditpipe after pausing auditing, you're guaranteeing that the queue will be empty even before AUDITPIPE_FLUSH. You need to:
asomers: This won't work either. By opening the auditpipe after pausing auditing, you're guaranteeing… | |||||
asomersUnsubmitted Not Done Inline ActionsDoes this statement (or the one two lines above) cause an audit entry? If not, then the queue still may be empty before you flush it. asomers: Does this statement (or the one two lines above) cause an audit entry? If not, then the queue… | |||||
else { | |||||
/* Start & stop auditd(8) to emit startup and closeup events */ | |||||
ATF_REQUIRE_EQ(0, auditon(A_SETCOND, &auresume, sizeof(int))); | |||||
ATF_REQUIRE_EQ(0, auditon(A_SETCOND, &aupause, sizeof(int))); | |||||
} | |||||
ATF_REQUIRE_EQ(0, ioctl(filedesc, AUDITPIPE_FLUSH)); | |||||
Not Done Inline ActionsThis needs to happen in the cleanup step, not in the body. asomers: This needs to happen in the cleanup step, not in the body. | |||||
Not Done Inline ActionsBut I've changed ATF_REQUIRE_EQ(0, ioctl(filedesc, AUDITPIPE_GET_QLEN, &qlen)); ATF_REQUIRE_EQ(0, qlen); to ATF_CHECK_EQ(0, ioctl(filedesc, AUDITPIPE_GET_QLEN, &qlen)); ATF_CHECK_EQ(0, qlen); for the same reason that the test case won't stop even if the require condition fails aniketp: But I've changed
```
ATF_REQUIRE_EQ(0, ioctl(filedesc, AUDITPIPE_GET_QLEN, &qlen))… | |||||
Not Done Inline ActionsOk, I guess that's fine. Not universally, but it should be ok for this test. I say not universally, because something like a segfault could always prevent the tests's body from completing. But in this case I don't think there's anyway for the test to crash that wouldn't also be a possibility for the cleanup step. asomers: Ok, I guess that's fine. Not universally, but it should be ok for this test. I say not… | |||||
/* AUDITPIPE_FLUSH clears any outstanding record in auditpipe */ | |||||
ATF_CHECK_EQ(0, ioctl(filedesc, AUDITPIPE_GET_QLEN, &qlen)); | |||||
ATF_CHECK_EQ(0, qlen); | |||||
/* Restore the earlier state of auditing, if it was enabled */ | |||||
if (aucond == AUC_AUDITING) | |||||
ATF_REQUIRE_EQ(0, auditon(A_SETCOND, &auresume, sizeof(int))); | |||||
close(filedesc); | |||||
} | |||||
ATF_TC(auditpipe_get_preselect_mode); | |||||
ATF_TC_HEAD(auditpipe_get_preselect_mode, tc) | |||||
{ | |||||
atf_tc_set_md_var(tc, "descr", "Verifies whether the auditpipe ioctl, " | |||||
"AUDITPIPE_GET_PRESELECT_MODE works properly"); | |||||
} | |||||
ATF_TC_BODY(auditpipe_get_preselect_mode, tc) | |||||
{ | |||||
int mode = -1; | |||||
ATF_REQUIRE((filedesc = open("/dev/auditpipe", O_RDONLY)) != -1); | |||||
ATF_REQUIRE_EQ(0, ioctl(filedesc, AUDITPIPE_GET_PRESELECT_MODE, &mode)); | |||||
ATF_REQUIRE(mode != -1); | |||||
close(filedesc); | |||||
} | |||||
ATF_TC(auditpipe_set_preselect_mode); | |||||
ATF_TC_HEAD(auditpipe_set_preselect_mode, tc) | |||||
{ | |||||
atf_tc_set_md_var(tc, "descr", "Verifies whether the auditpipe ioctl, " | |||||
"AUDITPIPE_SET_PRESELECT_MODE works properly"); | |||||
} | |||||
ATF_TC_BODY(auditpipe_set_preselect_mode, tc) | |||||
{ | |||||
int recv_mode; | |||||
int mode = AUDITPIPE_PRESELECT_MODE_LOCAL; | |||||
ATF_REQUIRE((filedesc = open("/dev/auditpipe", O_RDONLY)) != -1); | |||||
ATF_REQUIRE_EQ(0, ioctl(filedesc, AUDITPIPE_SET_PRESELECT_MODE, &mode)); | |||||
ATF_REQUIRE_EQ(0, ioctl(filedesc, | |||||
AUDITPIPE_GET_PRESELECT_MODE, &recv_mode)); | |||||
ATF_REQUIRE_EQ(mode, recv_mode); | |||||
close(filedesc); | |||||
} | |||||
ATF_TC(auditpipe_get_preselect_flags); | |||||
ATF_TC_HEAD(auditpipe_get_preselect_flags, tc) | |||||
{ | |||||
atf_tc_set_md_var(tc, "descr", "Verifies whether the auditpipe ioctl, " | |||||
"AUDITPIPE_GET_PRESELECT_FLAGS works properly"); | |||||
} | |||||
ATF_TC_BODY(auditpipe_get_preselect_flags, tc) | |||||
{ | |||||
au_mask_t fmask = { | |||||
.am_success = UINT_MAX, | |||||
.am_failure = UINT_MAX | |||||
}; | |||||
ATF_REQUIRE((filedesc = open("/dev/auditpipe", O_RDONLY)) != -1); | |||||
ATF_REQUIRE_EQ(0, ioctl(filedesc, | |||||
AUDITPIPE_GET_PRESELECT_FLAGS, &fmask)); | |||||
/* Check if both success and failure bits are set by this ioctl */ | |||||
ATF_REQUIRE(fmask.am_success != UINT_MAX); | |||||
ATF_REQUIRE(fmask.am_failure != UINT_MAX); | |||||
close(filedesc); | |||||
} | |||||
ATF_TC(auditpipe_set_preselect_flags); | |||||
ATF_TC_HEAD(auditpipe_set_preselect_flags, tc) | |||||
{ | |||||
atf_tc_set_md_var(tc, "descr", "Verifies whether the auditpipe ioctl, " | |||||
"AUDITPIPE_SET_PRESELECT_FLAGS works properly"); | |||||
} | |||||
ATF_TC_BODY(auditpipe_set_preselect_flags, tc) | |||||
{ | |||||
int mode = AUDITPIPE_PRESELECT_MODE_LOCAL; | |||||
au_mask_t fmask, gmask; | |||||
bzero(&fmask, sizeof(fmask)); | |||||
ATF_REQUIRE((filedesc = open("/dev/auditpipe", O_RDONLY)) != -1); | |||||
/* Set local mode auditing to not alter the system wide audit mask */ | |||||
ATF_REQUIRE_EQ(0, ioctl(filedesc, AUDITPIPE_SET_PRESELECT_MODE, &mode)); | |||||
ATF_REQUIRE_EQ(0, ioctl(filedesc, | |||||
AUDITPIPE_SET_PRESELECT_FLAGS, &fmask)); | |||||
ATF_REQUIRE_EQ(0, ioctl(filedesc, | |||||
AUDITPIPE_GET_PRESELECT_FLAGS, &gmask)); | |||||
/* Check if both success and failure bits are set by this ioctl */ | |||||
ATF_REQUIRE_EQ(fmask.am_success, gmask.am_success); | |||||
ATF_REQUIRE_EQ(fmask.am_failure, gmask.am_failure); | |||||
close(filedesc); | |||||
} | |||||
ATF_TC(auditpipe_get_preselect_naflags); | |||||
ATF_TC_HEAD(auditpipe_get_preselect_naflags, tc) | |||||
{ | |||||
atf_tc_set_md_var(tc, "descr", "Verifies whether the auditpipe ioctl, " | |||||
"AUDITPIPE_GET_PRESELECT_NAFLAGS works properly"); | |||||
} | |||||
ATF_TC_BODY(auditpipe_get_preselect_naflags, tc) | |||||
{ | |||||
au_mask_t fmask = { | |||||
.am_success = UINT_MAX, | |||||
.am_failure = UINT_MAX | |||||
}; | |||||
ATF_REQUIRE((filedesc = open("/dev/auditpipe", O_RDONLY)) != -1); | |||||
ATF_REQUIRE_EQ(0, ioctl(filedesc, | |||||
AUDITPIPE_GET_PRESELECT_NAFLAGS, &fmask)); | |||||
/* Check if both success and failure bits are set by this ioctl */ | |||||
ATF_REQUIRE(fmask.am_success != UINT_MAX); | |||||
ATF_REQUIRE(fmask.am_failure != UINT_MAX); | |||||
close(filedesc); | |||||
} | |||||
ATF_TC(auditpipe_set_preselect_naflags); | |||||
ATF_TC_HEAD(auditpipe_set_preselect_naflags, tc) | |||||
{ | |||||
atf_tc_set_md_var(tc, "descr", "Verifies whether the auditpipe ioctl, " | |||||
"AUDITPIPE_SET_PRESELECT_NAFLAGS works properly"); | |||||
} | |||||
ATF_TC_BODY(auditpipe_set_preselect_naflags, tc) | |||||
{ | |||||
int mode = AUDITPIPE_PRESELECT_MODE_LOCAL; | |||||
au_mask_t fmask, gmask; | |||||
bzero(&fmask, sizeof(fmask)); | |||||
ATF_REQUIRE((filedesc = open("/dev/auditpipe", O_RDONLY)) != -1); | |||||
/* Set local mode auditing to not alter the system wide audit mask */ | |||||
ATF_REQUIRE_EQ(0, ioctl(filedesc, AUDITPIPE_SET_PRESELECT_MODE, &mode)); | |||||
ATF_REQUIRE_EQ(0, ioctl(filedesc, | |||||
AUDITPIPE_SET_PRESELECT_NAFLAGS, &fmask)); | |||||
ATF_REQUIRE_EQ(0, ioctl(filedesc, | |||||
AUDITPIPE_GET_PRESELECT_NAFLAGS, &gmask)); | |||||
/* Check if both success and failure bits are set correctly */ | |||||
ATF_REQUIRE_EQ(fmask.am_success, gmask.am_success); | |||||
ATF_REQUIRE_EQ(fmask.am_failure, gmask.am_failure); | |||||
close(filedesc); | |||||
} | |||||
ATF_TP_ADD_TCS(tp) | ATF_TP_ADD_TCS(tp) | ||||
{ | { | ||||
ATF_TP_ADD_TC(tp, auditpipe_get_qlen); | ATF_TP_ADD_TC(tp, auditpipe_get_qlen); | ||||
ATF_TP_ADD_TC(tp, auditpipe_get_qlimit); | ATF_TP_ADD_TC(tp, auditpipe_get_qlimit); | ||||
ATF_TP_ADD_TC(tp, auditpipe_set_qlimit); | ATF_TP_ADD_TC(tp, auditpipe_set_qlimit); | ||||
ATF_TP_ADD_TC(tp, auditpipe_get_qlimit_min); | ATF_TP_ADD_TC(tp, auditpipe_get_qlimit_min); | ||||
ATF_TP_ADD_TC(tp, auditpipe_get_qlimit_max); | ATF_TP_ADD_TC(tp, auditpipe_get_qlimit_max); | ||||
ATF_TP_ADD_TC(tp, auditpipe_qlimit_more_than_qlimit_min); | |||||
ATF_TP_ADD_TC(tp, auditpipe_qlimit_less_than_qlimit_max); | |||||
ATF_TP_ADD_TC(tp, auditpipe_get_maxauditdata); | ATF_TP_ADD_TC(tp, auditpipe_get_maxauditdata); | ||||
ATF_TP_ADD_TC(tp, auditpipe_flush); | |||||
ATF_TP_ADD_TC(tp, auditpipe_get_preselect_mode); | |||||
ATF_TP_ADD_TC(tp, auditpipe_set_preselect_mode); | |||||
ATF_TP_ADD_TC(tp, auditpipe_get_preselect_flags); | |||||
ATF_TP_ADD_TC(tp, auditpipe_set_preselect_flags); | |||||
ATF_TP_ADD_TC(tp, auditpipe_get_preselect_naflags); | |||||
ATF_TP_ADD_TC(tp, auditpipe_set_preselect_naflags); | |||||
return (atf_no_error()); | return (atf_no_error()); | ||||
} | } |
This test isn't going to be reliable. You have no way to be sure that more auditable events didn't arrive after the flush but before AUDITPIPE_GET_QLEN.