[PATCH] audit: unswing cap_* fields in PATH records
by Richard Guy Briggs
The cap_* fields swing in and out of PATH records.
If no capabilities are set, the cap_* fields are completely missing and when
one of the cap_fi or cap_fp values is empty, that field is omitted.
Original:
type=PATH msg=audit(04/20/2017 12:17:11.222:193) : item=1 name=/lib64/ld-linux-x86-64.so.2 inode=787694 dev=08:03 mode=file,755 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:ld_so_t:s0 nametype=NORMAL
type=PATH msg=audit(04/20/2017 12:17:11.222:193) : item=0 name=/home/sleep inode=1319469 dev=08:03 mode=file,suid,755 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:bin_t:s0 nametype=NORMAL cap_fp=sys_admin cap_fe=1 cap_fver=2
Normalize the PATH record by always printing all 4 cap_* fields.
Fixed:
type=PATH msg=audit(04/20/2017 13:01:31.679:201) : item=1 name=/lib64/ld-linux-x86-64.so.2 inode=787694 dev=08:03 mode=file,755 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:ld_so_t:s0 nametype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0
type=PATH msg=audit(04/20/2017 13:01:31.679:201) : item=0 name=/home/sleep inode=1319469 dev=08:03 mode=file,suid,755 ouid=root ogid=root rdev=00:00 obj=system_u:object_r:bin_t:s0 nametype=NORMAL cap_fp=sys_admin cap_fi=none cap_fe=1 cap_fver=2
See: https://github.com/linux-audit/audit-kernel/issues/42
Signed-off-by: Richard Guy Briggs <rgb(a)redhat.com>
---
kernel/audit.c | 20 ++++----------------
1 files changed, 4 insertions(+), 16 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 10bc2ba..de264d1 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1956,22 +1956,10 @@ void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap)
static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
{
- kernel_cap_t *perm = &name->fcap.permitted;
- kernel_cap_t *inh = &name->fcap.inheritable;
- int log = 0;
-
- if (!cap_isclear(*perm)) {
- audit_log_cap(ab, "cap_fp", perm);
- log = 1;
- }
- if (!cap_isclear(*inh)) {
- audit_log_cap(ab, "cap_fi", inh);
- log = 1;
- }
-
- if (log)
- audit_log_format(ab, " cap_fe=%d cap_fver=%x",
- name->fcap.fE, name->fcap_ver);
+ audit_log_cap(ab, "cap_fp", &name->fcap.permitted);
+ audit_log_cap(ab, "cap_fi", &name->fcap.inheritable);
+ audit_log_format(ab, " cap_fe=%d cap_fver=%x",
+ name->fcap.fE, name->fcap_ver);
}
static inline int audit_copy_fcaps(struct audit_names *name,
--
1.7.1
7 years, 7 months
[PATCH] errormsg: use descriptive macros for error numbers
by Richard Guy Briggs
Convert all the numerical error return codes in comparison option and field
option parsing routines audit_rule_interfield_comp_data() and
audit_rule_fieldpair_data() to descriptive macros for easier code navigation
and verification.
See: https://github.com/linux-audit/audit-userspace/issues/11
Signed-off-by: Richard Guy Briggs <rgb(a)redhat.com>
---
lib/errormsg.h | 29 +++++++++++++++++++
lib/libaudit.c | 84 ++++++++++++++++++++++++++++----------------------------
2 files changed, 71 insertions(+), 42 deletions(-)
diff --git a/lib/errormsg.h b/lib/errormsg.h
index 9524697..17ff767 100644
--- a/lib/errormsg.h
+++ b/lib/errormsg.h
@@ -68,4 +68,33 @@ static const struct msg_tab err_msgtab[] = {
{ -30, 2, "Field option not supported by kernel:" },
{ -31, 1, "must be used with exclude, user, or exit filter" },
};
+#define EAU_OPMISSING 1
+#define EAU_FIELDUNKNOWN 2
+#define EAU_ARCHMISPLACED 3
+#define EAU_ARCHUNKNOWN 4
+#define EAU_ELFUNKNOWN 5
+#define EAU_ARCHNOBIT 6
+#define EAU_EXITONLY 7
+#define EAU_MSGTYPEUNKNOWN 8
+#define EAU_MSGTYPEEXCLUDE 9
+#define EAU_UPGRADEFAIL 10
+#define EAU_STRTOOLONG 11
+#define EAU_MSGTYPECREDEXCLUDE 12
+#define EAU_OPEQNOTEQ 13
+#define EAU_PERMRWXA 14
+#define EAU_ERRUNKNOWN 15
+#define EAU_FILETYPEUNKNOWN 16
+#define EAU_EXITENTRYONLY 17
+#define EAU_KEYDEP 19
+#define EAU_FIELDVALMISSING 20
+#define EAU_FIELDVALNUM 21
+#define EAU_FIELDNAME 22
+#define EAU_COMPFIELDNAME 24
+#define EAU_COMPVAL 25
+#define EAU_COMPFIELDUNKNOWN 26
+#define EAU_COMPVALUNKNOWN 27
+#define EAU_FIELDTOOMANY 28
+#define EAU_OPEQ 29
+#define EAU_FIELDNOSUPPORT 30
+#define EAU_FIELDNOFILTER 31
#endif
diff --git a/lib/libaudit.c b/lib/libaudit.c
index 002dd89..a3b4261 100644
--- a/lib/libaudit.c
+++ b/lib/libaudit.c
@@ -520,7 +520,7 @@ int audit_reset_lost(int fd)
struct audit_status s;
if ((audit_get_features() & AUDIT_FEATURE_BITMAP_LOST_RESET) == 0)
- return -30;
+ return -EAU_FIELDNOSUPPORT;
memset(&s, 0, sizeof(s));
s.mask = AUDIT_STATUS_LOST;
@@ -979,7 +979,7 @@ int audit_rule_interfield_comp_data(struct audit_rule_data **rulep,
return -1;
if (rule->field_count >= (AUDIT_MAX_FIELDS - 1))
- return -28;
+ return -EAU_FIELDTOOMANY;
/* look for 2-char operators first
then look for 1-char operators afterwards
@@ -994,24 +994,24 @@ int audit_rule_interfield_comp_data(struct audit_rule_data **rulep,
*v++ = '\0';
op = AUDIT_EQUAL;
} else {
- return -13;
+ return -EAU_OPEQNOTEQ;
}
if (*f == 0)
- return -24;
+ return -EAU_COMPFIELDNAME;
if (*v == 0)
- return -25;
+ return -EAU_COMPVAL;
if ((field1 = audit_name_to_field(f)) < 0)
- return -26;
+ return -EAU_COMPFIELDUNKNOWN;
if ((field2 = audit_name_to_field(v)) < 0)
- return -27;
+ return -EAU_COMPVALUNKNOWN;
/* Interfield comparison can only be in exit filter */
if (flags != AUDIT_FILTER_EXIT)
- return -7;
+ return -EAU_EXITONLY;
// It should always be AUDIT_FIELD_COMPARE
rule->fields[rule->field_count] = AUDIT_FIELD_COMPARE;
@@ -1392,7 +1392,7 @@ int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char *pair,
return -1;
if (rule->field_count >= (AUDIT_MAX_FIELDS - 1))
- return -28;
+ return -EAU_FIELDTOOMANY;
/* look for 2-char operators first
then look for 1-char operators afterwards
@@ -1430,23 +1430,23 @@ int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char *pair,
}
if (v == NULL)
- return -1;
+ return -EAU_OPMISSING;
if (*f == 0)
- return -22;
+ return -EAU_FIELDNAME;
if (*v == 0)
- return -20;
+ return -EAU_FIELDVALMISSING;
if ((field = audit_name_to_field(f)) < 0)
- return -2;
+ return -EAU_FIELDUNKNOWN;
/* Exclude filter can be used only with MSGTYPE and cred fields */
if (flags == AUDIT_FILTER_EXCLUDE) {
uint32_t features = audit_get_features();
if ((features & AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND) == 0) {
if (field != AUDIT_MSGTYPE)
- return -30;
+ return -EAU_FIELDNOSUPPORT;
} else {
switch(field) {
case AUDIT_PID:
@@ -1461,7 +1461,7 @@ int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char *pair,
case AUDIT_SUBJ_CLR:
break;
default:
- return -12;
+ return -EAU_MSGTYPECREDEXCLUDE;
}
}
}
@@ -1529,13 +1529,13 @@ int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char *pair,
rule->values[rule->field_count] =
audit_name_to_errno(v);
if (rule->values[rule->field_count] == 0)
- return -15;
+ return -EAU_ERRUNKNOWN;
}
break;
case AUDIT_MSGTYPE:
if (flags != AUDIT_FILTER_EXCLUDE &&
flags != AUDIT_FILTER_USER)
- return -9;
+ return -EAU_MSGTYPEEXCLUDE;
if (isdigit((char)*(v)))
rule->values[rule->field_count] =
@@ -1545,7 +1545,7 @@ int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char *pair,
rule->values[rule->field_count] =
audit_name_to_msg_type(v);
else
- return -8;
+ return -EAU_MSGTYPEUNKNOWN;
break;
/* These next few are strings */
case AUDIT_OBJ_USER:
@@ -1558,7 +1558,7 @@ int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char *pair,
/* Watch & object filtering is invalid on anything
* but exit */
if (flags != AUDIT_FILTER_EXIT)
- return -7;
+ return -EAU_EXITONLY;
if (field == AUDIT_WATCH || field == AUDIT_DIR)
_audit_permadded = 1;
@@ -1573,21 +1573,21 @@ int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char *pair,
if (field == AUDIT_EXE) {
uint32_t features = audit_get_features();
if ((features & AUDIT_FEATURE_BITMAP_EXECUTABLE_PATH) == 0)
- return -30;
+ return -EAU_FIELDNOSUPPORT;
if (op != AUDIT_EQUAL)
- return -29;
+ return -EAU_OPEQ;
_audit_exeadded = 1;
}
if (field == AUDIT_FILTERKEY &&
!(_audit_syscalladded || _audit_permadded ||
_audit_exeadded))
- return -19;
+ return -EAU_KEYDEP;
vlen = strlen(v);
if (field == AUDIT_FILTERKEY &&
vlen > AUDIT_MAX_KEY_LEN)
- return -11;
+ return -EAU_STRTOOLONG;
else if (vlen > PATH_MAX)
- return -11;
+ return -EAU_STRTOOLONG;
rule->values[rule->field_count] = vlen;
offset = rule->buflen;
rule->buflen += vlen;
@@ -1604,21 +1604,21 @@ int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char *pair,
break;
case AUDIT_ARCH:
if (_audit_syscalladded)
- return -3;
+ return -EAU_ARCHMISPLACED;
if (!(op == AUDIT_NOT_EQUAL || op == AUDIT_EQUAL))
- return -13;
+ return -EAU_OPEQNOTEQ;
if (isdigit((char)*(v))) {
int machine;
errno = 0;
_audit_elf = strtoul(v, NULL, 0);
if (errno)
- return -5;
+ return -EAU_ELFUNKNOWN;
// Make sure we have a valid mapping
machine = audit_elf_to_machine(_audit_elf);
if (machine < 0)
- return -5;
+ return -EAU_ELFUNKNOWN;
}
else {
const char *arch=v;
@@ -1628,7 +1628,7 @@ int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char *pair,
to elf. */
elf = audit_machine_to_elf(machine);
if (elf == 0)
- return -5;
+ return -EAU_ELFUNKNOWN;
_audit_elf = elf;
}
@@ -1637,15 +1637,15 @@ int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char *pair,
break;
case AUDIT_PERM:
if (flags != AUDIT_FILTER_EXIT)
- return -7;
+ return -EAU_EXITONLY;
else if (op != AUDIT_EQUAL)
- return -13;
+ return -EAU_OPEQNOTEQ;
else {
unsigned int i, len, val = 0;
len = strlen(v);
if (len > 4)
- return -11;
+ return -EAU_STRTOOLONG;
for (i = 0; i < len; i++) {
switch (tolower(v[i])) {
@@ -1662,7 +1662,7 @@ int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char *pair,
val |= AUDIT_PERM_ATTR;
break;
default:
- return -14;
+ return -EAU_PERMRWXA;
}
}
rule->values[rule->field_count] = val;
@@ -1670,11 +1670,11 @@ int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char *pair,
break;
case AUDIT_FILETYPE:
if (!(flags == AUDIT_FILTER_EXIT))
- return -17;
+ return -EAU_EXITENTRYONLY;
rule->values[rule->field_count] =
audit_name_to_ftype(v);
if ((int)rule->values[rule->field_count] < 0) {
- return -16;
+ return -EAU_FILETYPEUNKNOWN;
}
break;
case AUDIT_ARG0...AUDIT_ARG3:
@@ -1687,16 +1687,16 @@ int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char *pair,
rule->values[rule->field_count] =
strtol(v, NULL, 0);
else
- return -21;
+ return -EAU_FIELDVALNUM;
break;
case AUDIT_SESSIONID:
if ((audit_get_features() &
AUDIT_FEATURE_BITMAP_SESSIONID_FILTER) == 0)
- return -30;
+ return -EAU_FIELDNOSUPPORT;
if (flags != AUDIT_FILTER_EXCLUDE &&
flags != AUDIT_FILTER_USER &&
flags != AUDIT_FILTER_EXIT)
- return -31;
+ return -EAU_FIELDNOFILTER;
// Do positive & negative separate for 32 bit systems
vlen = strlen(v);
if (isdigit((char)*(v)))
@@ -1712,20 +1712,20 @@ int audit_rule_fieldpair_data(struct audit_rule_data **rulep, const char *pair,
case AUDIT_DEVMAJOR...AUDIT_INODE:
case AUDIT_SUCCESS:
if (flags != AUDIT_FILTER_EXIT)
- return -7;
+ return -EAU_EXITONLY;
/* fallthrough */
default:
if (field == AUDIT_INODE) {
if (!(op == AUDIT_NOT_EQUAL ||
op == AUDIT_EQUAL))
- return -13;
+ return -EAU_OPEQNOTEQ;
}
if (field == AUDIT_PPID && !(flags==AUDIT_FILTER_EXIT))
- return -17;
+ return -EAU_EXITENTRYONLY;
if (!isdigit((char)*(v)))
- return -21;
+ return -EAU_FIELDVALNUM;
if (field == AUDIT_INODE)
rule->values[rule->field_count] =
--
1.7.1
7 years, 7 months
What fields should be used for reporting shared memory?
by Martin Kletzander
Hi,
I am going through the fields in the dictionary and I can't find any
name to use for the following scenario.
We (libvirt) are running virtual machines and there's a thing nowadays,
that people like to use, called ivshmem (Inter-VM SHared MEMory). From
host's point of view this is just a shared memory region accessed by
multiple VMs (and possibly to host as well). The machine maps the
shared memory given a name (e.g. name "asdf" results in /dev/shm/asdf to
be mapped) *or* it can communicate with a server over UNIX socket and
that server handles interrupts and also tells the client which shared
memory region to map. Talking about information we have; in server-less
setup it's the shared memory region that is shared, in the server
scenario it is the socket. That's information we can output.
So my question is, when starting a domain or hot-(un)plugging, what
naming should we use for this kind of device and what are the things
that we should describe about it? Basically, how would you like the
message to look?
Thanks in advance for any info.
Have a nice day,
Martin
7 years, 7 months
[PATCH v3 0/4] Improved seccomp logging
by Tyler Hicks
This patch set is the third revision of the following two previously
submitted patch sets:
v1: http://lkml.kernel.org/r/1483375990-14948-1-git-send-email-tyhicks@canoni...
v1: http://lkml.kernel.org/r/1483377999-15019-2-git-send-email-tyhicks@canoni...
v2: http://lkml.kernel.org/r/1486100262-32391-1-git-send-email-tyhicks@canoni...
The patch set aims to address some known deficiencies in seccomp's current
logging capabilities:
1. Inability to log all filter actions.
2. Inability to selectively enable filtering; e.g. devs want noisy logging,
users want relative quiet.
3. Consistent behavior with audit enabled and disabled.
4. Inability to easily develop a filter due to the lack of a
permissive/complain mode.
Changes since v2 to address feedback from Kees:
- Patch 1
+ Log a warning when sysctl registration fails
+ Move comment describing SECCOMP_RET_*_NAME from PATCH 2
+ Document the actions_avail sysctl
- Patch 2
+ Inline seccomp_log()
+ Optimize logging for RET_ALLOW hot path
+ Use "{ }" for name buffer initialization
+ Make a copy of the ctl_table and only modify the copy
+ Rename max_action_to_log sysctl to log_max_action
+ Document the log_max_action sysctl
- Patch 3
+ Put some space between RET_LOG and RET_ALLOW for future actions
+ Separate the RET_ALLOW and RET_LOG cases in __seccomp_filter()
- Patch 4
+ Adjust the selftests for the updated RET_LOG value
Tyler
Tyler Hicks (4):
seccomp: Add sysctl to display available actions
seccomp: Add sysctl to configure actions that should be logged
seccomp: Create an action to log before allowing
seccomp: Add tests for SECCOMP_RET_LOG
Documentation/prctl/seccomp_filter.txt | 43 ++++++
Documentation/sysctl/kernel.txt | 1 +
include/linux/audit.h | 6 +-
include/uapi/linux/seccomp.h | 1 +
kernel/seccomp.c | 185 +++++++++++++++++++++++++-
tools/testing/selftests/seccomp/seccomp_bpf.c | 94 +++++++++++++
6 files changed, 322 insertions(+), 8 deletions(-)
--
2.7.4
7 years, 7 months
[RFC PATCH] audit: the fix RCU locking for the auditd_connection structure
by Paul Moore
From: Paul Moore <paul(a)paul-moore.com>
Cong Wang correctly pointed out that the RCU read locking of the
auditd_connection struct was wrong, this patch correct this by
adopting a more traditional, and correct RCU locking model.
This patch is heavily based on an earlier prototype by Cong Wang.
[XXX: Cong Wang, as mentioned previously, I'd like to add your
sign-off; please let me know if that is okay with you.]
Cc: <stable(a)vger.kernel.org> # 4.11.x-: 264d509637d9
Reported-by: Cong Wang <xiyou.wangcong(a)gmail.com>
??!! -> Signed-off-by: Cong Wang <xiyou.wangcong(a)gmail.com>
Signed-off-by: Paul Moore <paul(a)paul-moore.com>
---
kernel/audit.c | 157 ++++++++++++++++++++++++++++++++++++--------------------
1 file changed, 100 insertions(+), 57 deletions(-)
diff --git a/kernel/audit.c b/kernel/audit.c
index 10bc2bad2adf..a7c6a50477aa 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -112,18 +112,19 @@ struct audit_net {
* @pid: auditd PID
* @portid: netlink portid
* @net: the associated network namespace
- * @lock: spinlock to protect write access
+ * @rcu: RCU head
*
* Description:
* This struct is RCU protected; you must either hold the RCU lock for reading
- * or the included spinlock for writing.
+ * or the associated spinlock for writing.
*/
static struct auditd_connection {
struct pid *pid;
u32 portid;
struct net *net;
- spinlock_t lock;
-} auditd_conn;
+ struct rcu_head rcu;
+} *auditd_conn = NULL;
+static DEFINE_SPINLOCK(auditd_conn_lock);
/* If audit_rate_limit is non-zero, limit the rate of sending audit records
* to that number per second. This prevents DoS attacks, but results in
@@ -215,9 +216,11 @@ struct audit_reply {
int auditd_test_task(struct task_struct *task)
{
int rc;
+ struct auditd_connection *ac;
rcu_read_lock();
- rc = (auditd_conn.pid && auditd_conn.pid == task_tgid(task) ? 1 : 0);
+ ac = rcu_dereference(auditd_conn);
+ rc = (ac && ac->pid == task_tgid(task) ? 1 : 0);
rcu_read_unlock();
return rc;
@@ -225,22 +228,21 @@ int auditd_test_task(struct task_struct *task)
/**
* auditd_pid_vnr - Return the auditd PID relative to the namespace
- * @auditd: the auditd connection
*
* Description:
- * Returns the PID in relation to the namespace, 0 on failure. This function
- * takes the RCU read lock internally, but if the caller needs to protect the
- * auditd_connection pointer it should take the RCU read lock as well.
+ * Returns the PID in relation to the namespace, 0 on failure.
*/
-static pid_t auditd_pid_vnr(const struct auditd_connection *auditd)
+static pid_t auditd_pid_vnr(void)
{
pid_t pid;
+ const struct auditd_connection *ac;
rcu_read_lock();
- if (!auditd || !auditd->pid)
+ ac = rcu_dereference(auditd_conn);
+ if (!ac || !ac->pid)
pid = 0;
else
- pid = pid_vnr(auditd->pid);
+ pid = pid_vnr(ac->pid);
rcu_read_unlock();
return pid;
@@ -434,6 +436,24 @@ static int audit_set_failure(u32 state)
}
/**
+ * auditd_conn_free - RCU helper to release an auditd connection struct
+ * @rcu: RCU head
+ *
+ * Description:
+ * Drop any references inside the auditd connection tracking struct and free
+ * the memory.
+ */
+ static void auditd_conn_free(struct rcu_head *rcu)
+ {
+ struct auditd_connection *ac;
+
+ ac = container_of(rcu, struct auditd_connection, rcu);
+ put_pid(ac->pid);
+ put_net(ac->net);
+ kfree(ac);
+ }
+
+/**
* auditd_set - Set/Reset the auditd connection state
* @pid: auditd PID
* @portid: auditd netlink portid
@@ -441,27 +461,33 @@ static int audit_set_failure(u32 state)
*
* Description:
* This function will obtain and drop network namespace references as
- * necessary.
+ * necessary. Returns zero on success, negative values on failure.
*/
-static void auditd_set(struct pid *pid, u32 portid, struct net *net)
+static int auditd_set(struct pid *pid, u32 portid, struct net *net)
{
unsigned long flags;
+ struct auditd_connection *ac_old, *ac_new;
- spin_lock_irqsave(&auditd_conn.lock, flags);
- if (auditd_conn.pid)
- put_pid(auditd_conn.pid);
- if (pid)
- auditd_conn.pid = get_pid(pid);
- else
- auditd_conn.pid = NULL;
- auditd_conn.portid = portid;
- if (auditd_conn.net)
- put_net(auditd_conn.net);
- if (net)
- auditd_conn.net = get_net(net);
- else
- auditd_conn.net = NULL;
- spin_unlock_irqrestore(&auditd_conn.lock, flags);
+ if (!pid || !net)
+ return -EINVAL;
+
+ ac_new = kzalloc(sizeof(*ac_new), GFP_KERNEL);
+ if (!ac_new)
+ return -ENOMEM;
+ ac_new->pid = get_pid(pid);
+ ac_new->portid = portid;
+ ac_new->net = get_net(net);
+
+ spin_lock_irqsave(&auditd_conn_lock, flags);
+ ac_old = rcu_dereference_protected(auditd_conn,
+ lockdep_is_held(&auditd_conn_lock));
+ rcu_assign_pointer(auditd_conn, ac_new);
+ spin_unlock_irqrestore(&auditd_conn_lock, flags);
+
+ if (ac_old)
+ call_rcu(&ac_old->rcu, auditd_conn_free);
+
+ return 0;
}
/**
@@ -556,13 +582,19 @@ static void kauditd_retry_skb(struct sk_buff *skb)
*/
static void auditd_reset(void)
{
+ unsigned long flags;
struct sk_buff *skb;
+ struct auditd_connection *ac_old;
/* if it isn't already broken, break the connection */
- rcu_read_lock();
- if (auditd_conn.pid)
- auditd_set(0, 0, NULL);
- rcu_read_unlock();
+ spin_lock_irqsave(&auditd_conn_lock, flags);
+ ac_old = rcu_dereference_protected(auditd_conn,
+ lockdep_is_held(&auditd_conn_lock));
+ rcu_assign_pointer(auditd_conn, NULL);
+ spin_unlock_irqrestore(&auditd_conn_lock, flags);
+
+ if (ac_old)
+ call_rcu(&ac_old->rcu, auditd_conn_free);
/* flush all of the main and retry queues to the hold queue */
while ((skb = skb_dequeue(&audit_retry_queue)))
@@ -588,6 +620,7 @@ static int auditd_send_unicast_skb(struct sk_buff *skb)
u32 portid;
struct net *net;
struct sock *sk;
+ struct auditd_connection *ac;
/* NOTE: we can't call netlink_unicast while in the RCU section so
* take a reference to the network namespace and grab local
@@ -597,15 +630,15 @@ static int auditd_send_unicast_skb(struct sk_buff *skb)
* section netlink_unicast() should safely return an error */
rcu_read_lock();
- if (!auditd_conn.pid) {
+ ac = rcu_dereference(auditd_conn);
+ if (!ac) {
rcu_read_unlock();
rc = -ECONNREFUSED;
goto err;
}
- net = auditd_conn.net;
- get_net(net);
+ net = get_net(ac->net);
sk = audit_get_sk(net);
- portid = auditd_conn.portid;
+ portid = ac->portid;
rcu_read_unlock();
rc = netlink_unicast(sk, skb, portid, 0);
@@ -740,6 +773,7 @@ static int kauditd_thread(void *dummy)
u32 portid = 0;
struct net *net = NULL;
struct sock *sk = NULL;
+ struct auditd_connection *ac;
#define UNICAST_RETRIES 5
@@ -747,14 +781,14 @@ static int kauditd_thread(void *dummy)
while (!kthread_should_stop()) {
/* NOTE: see the lock comments in auditd_send_unicast_skb() */
rcu_read_lock();
- if (!auditd_conn.pid) {
+ ac = rcu_dereference(auditd_conn);
+ if (!ac) {
rcu_read_unlock();
goto main_queue;
}
- net = auditd_conn.net;
- get_net(net);
+ net = get_net(ac->net);
sk = audit_get_sk(net);
- portid = auditd_conn.portid;
+ portid = ac->portid;
rcu_read_unlock();
/* attempt to flush the hold queue */
@@ -1117,7 +1151,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
s.failure = audit_failure;
/* NOTE: use pid_vnr() so the PID is relative to the current
* namespace */
- s.pid = auditd_pid_vnr(&auditd_conn);
+ s.pid = auditd_pid_vnr();
s.rate_limit = audit_rate_limit;
s.backlog_limit = audit_backlog_limit;
s.lost = atomic_read(&audit_lost);
@@ -1160,7 +1194,7 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
/* test the auditd connection */
audit_replace(req_pid);
- auditd_pid = auditd_pid_vnr(&auditd_conn);
+ auditd_pid = auditd_pid_vnr();
/* only the current auditd can unregister itself */
if ((!new_pid) && (new_pid != auditd_pid)) {
audit_log_config_change("audit_pid", new_pid,
@@ -1174,19 +1208,30 @@ static int audit_receive_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
return -EEXIST;
}
- if (audit_enabled != AUDIT_OFF)
- audit_log_config_change("audit_pid", new_pid,
- auditd_pid, 1);
-
if (new_pid) {
/* register a new auditd connection */
- auditd_set(req_pid, NETLINK_CB(skb).portid,
- sock_net(NETLINK_CB(skb).sk));
+ err = auditd_set(req_pid,
+ NETLINK_CB(skb).portid,
+ sock_net(NETLINK_CB(skb).sk));
+ if (audit_enabled != AUDIT_OFF)
+ audit_log_config_change("audit_pid",
+ new_pid,
+ auditd_pid,
+ err ? 0 : 1);
+ if (err)
+ return err;
+
/* try to process any backlog */
wake_up_interruptible(&kauditd_wait);
- } else
+ } else {
+ if (audit_enabled != AUDIT_OFF)
+ audit_log_config_change("audit_pid",
+ new_pid,
+ auditd_pid, 1);
+
/* unregister the auditd connection */
auditd_reset();
+ }
}
if (s.mask & AUDIT_STATUS_RATE_LIMIT) {
err = audit_set_rate_limit(s.rate_limit);
@@ -1454,10 +1499,11 @@ static void __net_exit audit_net_exit(struct net *net)
{
struct audit_net *aunet = net_generic(net, audit_net_id);
- rcu_read_lock();
- if (net == auditd_conn.net)
- auditd_reset();
- rcu_read_unlock();
+ /* NOTE: you would think that we would want to check the auditd
+ * connection and potentially reset it here if it lives in this
+ * namespace, but since the auditd connection tracking struct holds a
+ * reference to this namespace (see auditd_set()) we are only ever
+ * going to get here after that connection has been released */
netlink_kernel_release(aunet->sk);
}
@@ -1481,9 +1527,6 @@ static int __init audit_init(void)
sizeof(struct audit_buffer),
0, SLAB_PANIC, NULL);
- memset(&auditd_conn, 0, sizeof(auditd_conn));
- spin_lock_init(&auditd_conn.lock);
-
skb_queue_head_init(&audit_queue);
skb_queue_head_init(&audit_retry_queue);
skb_queue_head_init(&audit_hold_queue);
7 years, 7 months
Re: audit su - access
by Maria Tsiolakki
Hello,
Many thanks for your answer. I will try your suggestion but what if a user makes a copy of the su executable to let's say under /tmp and execute /tmp/su . Will this be audited using the rule you suggest?
Best regardsMaria
Sent from my Samsung device
-------- Original message --------
From: Steve Grubb <sgrubb(a)redhat.com>
Date: 23/04/2017 11:48 (GMT+02:00)
To: Maria Tsiolakki <tmaria(a)cs.ucy.ac.cy>
Cc: linux-audit(a)redhat.com
Subject: Re: audit su - access
Hello,
On Fri, 21 Apr 2017 16:00:54 +0300
Maria Tsiolakki <tmaria(a)cs.ucy.ac.cy> wrote:
> We have setup the audit log on a Redhat linux 7.3 machine
> We have setup various rules, so far successfully. Our last
> requirement is to have audit log, when a user execute the su - or su
> - root, or sudo su I write the following rule , but it does not work
> -a always,exit -S su
This ^^^ is the problem. The -S switch is for system calls. To see a
list of system calls you can run "ausyscall --dump". Su is a
program and not a syscall. So, you would place a watch on it like this:
-a always,exit -F path=/usr/bin/su -F perm=x -F auid>=200 -F
auid!=4294967295 -F key=su-execution
-Steve
> -F auid>=200 -F auid!=4294967295 -F
> key=su-execution How can I audit log the execution of the su command?
>
> Best regards
> Maria
>
7 years, 8 months
audit su - access
by Maria Tsiolakki
Hello,
We have setup the audit log on a Redhat linux 7.3 machine
We have setup various rules, so far successfully. Our last requirement
is to have audit log, when a user execute the su - or su - root, or sudo su
I write the following rule , but it does not work
-a always,exit -S su -F auid>=200 -F auid!=4294967295 -F key=su-execution
How can I audit log the execution of the su command?
Best regards
Maria
--
**
7 years, 8 months
audit 2.7.6 released
by Steve Grubb
Hello,
I've just released a new version of the audit daemon. It can be downloaded
from http://people.redhat.com/sgrubb/audit. It will also be in rawhide
soon. The ChangeLog is:
- In auparse_nomalize, assign user-login as the event kind for AUDIT_LOGIN
- In auparse_normalize, move GRP_AUTH to its own event kind, group-change
- In auparse_normalize, assign obj_kind values for some group events
- In auparse_normalize, assign obj_kind values to some MAC events
- In auparse_normalize, try harder to find object for CONFIG_CHANGE events
- In auparse_normalize, correct the primary subject field for USER_LOGIN
events
- In auparse_normalize, correct the primary object field for USER_LOGIN events
- Make string lookup tables more robust against bad input
- In auparse, make printing lists more robust against bad input
- In auparse, make unescaping more robust against bad input
- Make ausearch/report a little more robust to bad input
- Fix a memory leak in auparse when extracting a buggy date
- In ausearch --format mode, load interpretations for enriched events
- In auparse, load interpretations for feed events
- In audisp-remote, check for stop if stdin is a pipe (#1443107)
This release continues adjusting the normalizer mappings. I also spent some
time fuzzing the logs and making the utilities more robust. This in theory
should never be a problem because the logs are supposed to be well formed from
the beginning. But just in case...its batter now.
I did find a problem where events that were coming in through the feed API of
auparse were not getting the enriched event information loaded. That is now
fixed. And we had a report of the audisp-remote plugin getting into an
infinite loop if the remote server filled its disk and the remote plugin was
supposed to stop on disk full.
SHA256: fa65289cffdc95a25bfbdba541f43ee1b12c707090a38fd027dcf9354b9014e7
Please let me know if you run across any problems with this release.
-Steve
7 years, 8 months
[PATCH 00/19] Kernel subsystem refcounter conversions
by Elena Reshetova
Now when new refcount_t type and API are finally merged
(see include/linux/refcount.h), the following
patches convert various refcounters in the kernel susystem from atomic_t
to refcount_t. By doing this we prevent intentional or accidental
underflows or overflows that can led to use-after-free vulnerabilities.
The below patches are fully independent and can be cherry-picked separately.
Since we convert all kernel subsystems in the same fashion, resulting
in about 300 patches, we have to group them for sending at least in some
fashion to be manageable. Please excuse the long cc list.
Elena Reshetova (19):
kernel: convert sighand_struct.count from atomic_t to refcount_t
kernel: convert signal_struct.sigcnt from atomic_t to refcount_t
kernel: convert user_struct.__count from atomic_t to refcount_t
kernel: convert task_struct.usage from atomic_t to refcount_t
kernel: convert task_struct.stack_refcount from atomic_t to refcount_t
kernel: convert perf_event_context.refcount from atomic_t to
refcount_t
kernel: convert ring_buffer.refcount from atomic_t to refcount_t
kernel: convert ring_buffer.aux_refcount from atomic_t to refcount_t
kernel: convert uprobe.ref from atomic_t to refcount_t
kernel: convert nsproxy.count from atomic_t to refcount_t
kernel: convert cgroup_namespace.count from atomic_t to refcount_t
kernel: convert css_set.refcount from atomic_t to refcount_t
kernel: convert group_info.usage from atomic_t to refcount_t
kernel: convert cred.usage from atomic_t to refcount_t
kernel: convert audit_tree.count from atomic_t to refcount_t
kernel: convert audit_watch.count from atomic_t to refcount_t
kernel: convert numa_group.refcount from atomic_t to refcount_t
kernel: convert futex_pi_state.refcount from atomic_t to refcount_t
kernel: convert kcov.refcount from atomic_t to refcount_t
fs/exec.c | 4 ++--
include/linux/cgroup-defs.h | 3 ++-
include/linux/cgroup.h | 7 ++++---
include/linux/cred.h | 13 ++++++------
include/linux/init_task.h | 7 ++++---
include/linux/nsproxy.h | 6 +++---
include/linux/perf_event.h | 3 ++-
include/linux/sched.h | 19 +++++++++--------
kernel/audit_tree.c | 8 +++----
kernel/audit_watch.c | 8 +++----
kernel/cgroup/cgroup-internal.h | 10 ++++++---
kernel/cgroup/cgroup-v1.c | 4 ++--
kernel/cgroup/cgroup.c | 10 ++++-----
kernel/cgroup/namespace.c | 2 +-
kernel/cred.c | 46 ++++++++++++++++++++---------------------
kernel/events/core.c | 18 ++++++++--------
kernel/events/internal.h | 5 +++--
kernel/events/ring_buffer.c | 8 +++----
kernel/events/uprobes.c | 8 +++----
kernel/fork.c | 24 ++++++++++-----------
kernel/futex.c | 15 +++++++-------
kernel/groups.c | 2 +-
kernel/kcov.c | 9 ++++----
kernel/nsproxy.c | 6 +++---
kernel/sched/fair.c | 8 +++----
kernel/user.c | 8 +++----
26 files changed, 137 insertions(+), 124 deletions(-)
--
2.7.4
7 years, 8 months
signed tarballs
by Christian Rebischke
Hello,
I am the maintainer of 'audit' in the official Arch Linux Repositories.
Is there a reason why you don't provide a signature file for the
releases nor a checksum or am I just stupid and can't find it on your
website: https://people.redhat.com/sgrubb/audit/ ?
Best regards,
chris
7 years, 8 months