audit 1.7.8 released
by Steve Grubb
Hi,
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:
- Fix strict aliasing compiler warnings
- Interpret TTY audit data in auparse (Miloslav TrmaÄ)
- Extract terminal from USER_AVC events for ausearch/report (Peng Haitao)
- Makefile cleanup (Philipp Hahn)
- Add USER_AVCs to aureport's avc reporting (Peng Haitao)
- Get auparse test suites working better
- When apps started by audispd die, restart them if their type is always
- Short circuit hostname resolution in libaudit if host is empty
- Remove selinux policy for zos-remote
- Update libauparse capabilities table
- If log_group and user are not root, don't check dispatcher perms
- Fix a bug when executing "ausearch -te today PM"
- Add --exit search option to ausearch
- Delete root user tests in auparse/test dir
- Improve performance of ausearch/report and drop dead code
- More code cleanups
- Fix parsing config file when kerberos is disabled
- Add new kernel capability event record types
This release fixes a bunch of little bugs in the Makefile, test suites, and
programs. A couple bug fixes to call out are, when you use log_group as
non-root user, it tried to open and fstat the event dispatcher, but if you
are non root, that is usually EPERM and if you have audit rules for EPERM,
you create audit events everytime you use ausearch.
When GSSAPI support was disabled, it was not able to parse the given config
file, so that was fixed to parse but ignore the settings.
The performance of ausearch/report should be better now. I think my testing
showed about 5%-10% improvement. This needs careful testing, though.
And lastly, I added a new option to ausearch to look for exit codes. If for
example, you needed to find any syscall with EPERM exit, you can now
do "ausearch --start today --exit -EPERM".
Please let me know if you run across any problems with this release.
-Steve
16 years
ausearch on aggregation - syscall difference
by LC Bruzenak
I have a test (virtual) machine running a 32-bit F9 OS.
My aggregating machine is a 64-bit F9 box.
source (32-bit machine) :
[root@v1 ~]# ausearch -ts today -i -a 10038
----
node=v1 type=SYSCALL msg=audit(10/24/2008 11:11:59.162:10038) : arch=i386 syscall=socketcall(recv) success=yes exit=5 a0=a a1=bfcc1f80 a2=25b0c4 a3=0 items=0 ppid=1 pid=11761 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=1 comm=prelude-manager exe=/usr/bin/prelude-manager subj=system_u:system_r:prelude_t:s0-s15:c0.c1023 key=(null)
node=v1 type=AVC msg=audit(10/24/2008 11:11:59.162:10038) : avc: denied { read } for pid=11761 comm=prelude-manager laddr=127.0.0.1 lport=4690 faddr=127.0.0.1 fport=36291 scontext=system_u:system_r:prelude_t:s0-s15:c0.c1023 tcontext=system_u:system_r:prelude_t:s15:c0.c1023 tclass=tcp_socket
aggregating machine (64-bit) :
[root@dell1 ~]# ausearch -ts today -i -a 10038
----
node=v1 type=SYSCALL msg=audit(10/24/2008 11:11:59.162:10038) : arch=i386 syscall=getuid success=yes exit=5 a0=a a1=bfcc1f80 a2=25b0c4 a3=0 items=0 ppid=1 pid=11761 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=(none) ses=1 comm=prelude-manager exe=/usr/bin/prelude-manager subj=system_u:system_r:prelude_t:s0-s15:c0.c1023 key=(null)
node=v1 type=AVC msg=audit(10/24/2008 11:11:59.162:10038) : avc: denied { read } for pid=11761 comm=prelude-manager laddr=127.0.0.1 lport=4690 faddr=127.0.0.1 fport=36291 scontext=system_u:system_r:prelude_t:s0-s15:c0.c1023 tcontext=system_u:system_r:prelude_t:s15:c0.c1023 tclass=tcp_socket
Note that the syscall is listed differently.
This is using the 1.7.7 code (on F9), I have not yet moved over to 1.7.8
in case it may be fixed there.
Also, (at the latest) after F10 GA release I'll be migrating there.
Thx,
LCB.
--
LC (Lenny) Bruzenak
lenny(a)magitekltd.com
16 years
Note to anyone shipping audit 1.7.8
by Steve Grubb
Hi,
If you are shipping audit 1.7.8, I wanted to mention that I found 2 bugs today
that are now fixed in svn. I recommend you pull them and patch up. The bugs
are not severe enough to warrant a new release but enough of a hassle that I
want people to know about them.
https://fedorahosted.org/audit/changeset/153
https://fedorahosted.org/audit/changeset/154
These fix a segfault when GSSAPI is not enabled and aureport is reading from a
file rather than a log. And quieten the messages that are printed to the
console when you use aureport and GSSAPI is not supported. Both of these are
fixed in the next rawhide push.
-Steve
16 years
audisp-remote question
by LC Bruzenak
If in /etc/audisp/audisp-remote.conf I set the
network_failure_action=suspend, can I later tell the app to resume
somehow?
Thx,
LCB.
--
LC (Lenny) Bruzenak
lenny(a)magitekltd.com
16 years
audisp plugin policy question(s)
by LC Bruzenak
In the audisp plugin sources (and audit.spec), the zos-remote plugin has
a policy section, the others do not. Will those pieces be added
similarly? Should prelude/prelude-plugin/remote-plugin policy go here or
in the system policy rpm?
Also some MLS prelude-related questions:
I realize this is technically a prelude policy question vice audit, but
I'm not certain how many selinux/MLS folks are on that list. Dan Walsh
suggested I ask on this list first. And it is due to the prelude plugin
to audit that this comes up, so at least the plugin is germane.
Right now my prelude-manager runs ranged SystemLow-SystemHigh.
Should this be only SystemHigh? I'm not exactly certain how this is done
now to run ranged. Here is the process listing:
ps -edaflZ | grep prelude
system_u:system_r:prelude_t:SystemLow-SystemHigh 1 S root 2432 1 0 80 0 - 33187 epoll_ Oct20 ? 00:00:04 prelude-manager -d
system_u:system_r:prelude_audisp_t:SystemHigh 0 S root 2664 2662 0 76 -4 - 10392 unix_s Oct20 ? 00:00:03 /sbin/audisp-prelude
There are some spool files not set accordingly which cause AVCs.
I guess these need file contexts?
As I said, there are many AVCs and those can probably be eliminated with
audit2allow exercises and review of the issue (like the labels on the
spool files).
Then there is a prelude-manager<->prelude-lml question, but I won't get
into that in case I hear "take it up with the prelude guys" from the
above.
Thx,
LCB.
--
LC (Lenny) Bruzenak
lenny(a)magitekltd.com
16 years
PATH records show fcaps
by Eric Paris
type=SYSCALL msg=audit(1224342849.465:43): arch=c000003e syscall=59 success=yes exit=0 a0=25b6a00 a1=2580410 a2=2580140 a3=8 items=2 ppid=2219 pid=2266 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=1 comm="ping" exe="/bin/ping" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null)
type=EXECVE msg=audit(1224342849.465:43): argc=2 a0="ping" a1="127.0.0.1"
type=CWD msg=audit(1224342849.465:43): cwd="/root"
type=PATH msg=audit(1224342849.465:43): item=0 name="/bin/ping" inode=49227 dev=fd:00 mode=0100755 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:ping_exec_t:s0 cap_permitted=0000000000002000 cap_inheritable=0000000000000000
type=PATH msg=audit(1224342849.465:43): item=1 name=(null) inode=507963 dev=fd:00 mode=0100755 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:ld_so_t:s0
This good? If either cap_permitted or cap_inheritable have anything set
I show them both. In the above example would you rather I only showed
cap_permitted and dropped cap_inheritable? Did I see correctly that
it's possible to set a cap_effective on a file? Does it do anything? I
didn't see that getting used or read in the kernel, so I didn't put any
way to display it in kernel....
-Eric
---
include/linux/capability.h | 11 ++++
kernel/auditsc.c | 68 ++++++++++++++++++++++++--
security/commoncap.c | 115 +++++++++++++++++++++++++-------------------
3 files changed, 140 insertions(+), 54 deletions(-)
diff --git a/include/linux/capability.h b/include/linux/capability.h
index 9d1fe30..a3785e7 100644
--- a/include/linux/capability.h
+++ b/include/linux/capability.h
@@ -96,6 +96,13 @@ typedef struct kernel_cap_struct {
__u32 cap[_KERNEL_CAPABILITY_U32S];
} kernel_cap_t;
+/* exact same as vfs_cap_data but in cpu endian and always filled completely */
+struct cpu_vfs_cap_data {
+ __u32 magic_etc;
+ kernel_cap_t permitted;
+ kernel_cap_t inheritable;
+};
+
#define _USER_CAP_HEADER_SIZE (sizeof(struct __user_cap_header_struct))
#define _KERNEL_CAP_T_SIZE (sizeof(kernel_cap_t))
@@ -517,6 +524,10 @@ kernel_cap_t cap_set_effective(const kernel_cap_t pE_new);
extern int capable(int cap);
+/* audit system wants to get cap info from files as well */
+struct dentry;
+extern int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps);
+
#endif /* __KERNEL__ */
#endif /* !_LINUX_CAPABILITY_H */
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index cf5bc2f..800fc55 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -65,6 +65,7 @@
#include <linux/highmem.h>
#include <linux/syscalls.h>
#include <linux/inotify.h>
+#include <linux/capability.h>
#include "audit.h"
@@ -100,6 +101,8 @@ struct audit_names {
gid_t gid;
dev_t rdev;
u32 osid;
+ kernel_cap_t cap_permitted;
+ kernel_cap_t cap_inheritable;
};
struct audit_aux_data {
@@ -1171,6 +1174,33 @@ static void audit_log_execve_info(struct audit_context *context,
kfree(buf);
}
+static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
+{
+ int i;
+ int print = 0;
+ kernel_cap_t *perm = &name->cap_permitted;
+ kernel_cap_t *inh = &name->cap_inheritable;
+
+ CAP_FOR_EACH_U32(i) {
+ if (perm->cap[i] || inh->cap[i]) {
+ print = 1;
+ break;
+ }
+ }
+
+ if (likely(!print))
+ return;
+
+ audit_log_format(ab, " %s", "cap_permitted=");
+ CAP_FOR_EACH_U32(i) {
+ audit_log_format(ab, "%08x", perm->cap[(_KERNEL_CAPABILITY_U32S-1) - i]);
+ }
+ audit_log_format(ab, " %s", "cap_inheritable=");
+ CAP_FOR_EACH_U32(i) {
+ audit_log_format(ab, "%08x", inh->cap[(_KERNEL_CAPABILITY_U32S-1) - i]);
+ }
+}
+
static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
{
int i, call_panic = 0;
@@ -1421,6 +1451,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
}
}
+ audit_log_fcaps(ab, n);
+
audit_log_end(ab);
}
@@ -1787,8 +1819,33 @@ static int audit_inc_name_count(struct audit_context *context,
return 0;
}
+
+static inline int audit_copy_fcaps(struct audit_names *name, const struct dentry *dentry)
+{
+ struct cpu_vfs_cap_data caps;
+ int rc, i;
+
+ memset(&name->cap_permitted, 0, sizeof(kernel_cap_t));
+ memset(&name->cap_inheritable, 0, sizeof(kernel_cap_t));
+
+ if (!dentry)
+ return 0;
+
+ rc = get_vfs_caps_from_disk(dentry, &caps);
+ if (rc)
+ return rc;
+
+ CAP_FOR_EACH_U32(i) {
+ name->cap_permitted.cap[i] = caps.permitted.cap[i];
+ name->cap_inheritable.cap[i] = caps.inheritable.cap[i];
+ }
+ return 0;
+}
+
+
/* Copy inode data into an audit_names. */
-static void audit_copy_inode(struct audit_names *name, const struct inode *inode)
+static void audit_copy_inode(struct audit_names *name, const struct dentry *dentry,
+ const struct inode *inode)
{
name->ino = inode->i_ino;
name->dev = inode->i_sb->s_dev;
@@ -1797,6 +1854,7 @@ static void audit_copy_inode(struct audit_names *name, const struct inode *inode
name->gid = inode->i_gid;
name->rdev = inode->i_rdev;
security_inode_getsecid(inode, &name->osid);
+ audit_copy_fcaps(name, dentry);
}
/**
@@ -1831,7 +1889,7 @@ void __audit_inode(const char *name, const struct dentry *dentry)
context->names[idx].name = NULL;
}
handle_path(dentry);
- audit_copy_inode(&context->names[idx], inode);
+ audit_copy_inode(&context->names[idx], dentry, inode);
}
/**
@@ -1892,7 +1950,7 @@ void __audit_inode_child(const char *dname, const struct dentry *dentry,
if (!strcmp(dname, n->name) ||
!audit_compare_dname_path(dname, n->name, &dirlen)) {
if (inode)
- audit_copy_inode(n, inode);
+ audit_copy_inode(n, NULL, inode);
else
n->ino = (unsigned long)-1;
found_child = n->name;
@@ -1906,7 +1964,7 @@ add_names:
return;
idx = context->name_count - 1;
context->names[idx].name = NULL;
- audit_copy_inode(&context->names[idx], parent);
+ audit_copy_inode(&context->names[idx], NULL, parent);
}
if (!found_child) {
@@ -1927,7 +1985,7 @@ add_names:
}
if (inode)
- audit_copy_inode(&context->names[idx], inode);
+ audit_copy_inode(&context->names[idx], NULL, inode);
else
context->names[idx].ino = (unsigned long)-1;
}
diff --git a/security/commoncap.c b/security/commoncap.c
index 399bfdb..9f109b9 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -202,17 +202,70 @@ int cap_inode_killpriv(struct dentry *dentry)
return inode->i_op->removexattr(dentry, XATTR_NAME_CAPS);
}
-static inline int cap_from_disk(struct vfs_cap_data *caps,
- struct linux_binprm *bprm, unsigned size)
+static inline int bprm_caps_from_vfs_caps(struct cpu_vfs_cap_data *caps,
+ struct linux_binprm *bprm)
{
+ unsigned i;
+ int ret = 0;
+
+ if (caps->magic_etc & VFS_CAP_FLAGS_EFFECTIVE)
+ bprm->cap_effective = true;
+ else
+ bprm->cap_effective = false;
+
+ CAP_FOR_EACH_U32(i) {
+ __u32 permitted = caps->permitted.cap[i];
+ __u32 inheritable = caps->inheritable.cap[i];
+
+ /*
+ * pP' = (X & fP) | (pI & fI)
+ */
+ bprm->cap_post_exec_permitted.cap[i] =
+ (current->cap_bset.cap[i] & permitted) |
+ (current->cap_inheritable.cap[i] & inheritable);
+
+ if (permitted & ~bprm->cap_post_exec_permitted.cap[i]) {
+ /*
+ * insufficient to execute correctly
+ */
+ ret = -EPERM;
+ }
+ }
+
+ /*
+ * For legacy apps, with no internal support for recognizing they
+ * do not have enough capabilities, we return an error if they are
+ * missing some "forced" (aka file-permitted) capabilities.
+ */
+ return bprm->cap_effective ? ret : 0;
+}
+
+int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data *cpu_caps)
+{
+ struct inode *inode = dentry->d_inode;
__u32 magic_etc;
unsigned tocopy, i;
- int ret;
+ int size;
+ struct vfs_cap_data caps;
+
+ memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data));
+
+ if (!inode || !inode->i_op || !inode->i_op->getxattr)
+ return 0;
+
+ size = inode->i_op->getxattr((struct dentry *)dentry, XATTR_NAME_CAPS, &caps,
+ XATTR_CAPS_SZ);
+ if (size == -ENODATA || size == -EOPNOTSUPP) {
+ /* no data, that's ok */
+ return 0;
+ }
+ if (size < 0)
+ return size;
if (size < sizeof(magic_etc))
return -EINVAL;
- magic_etc = le32_to_cpu(caps->magic_etc);
+ cpu_caps->magic_etc = magic_etc = le32_to_cpu(caps.magic_etc);
switch ((magic_etc & VFS_CAP_REVISION_MASK)) {
case VFS_CAP_REVISION_1:
@@ -229,46 +282,16 @@ static inline int cap_from_disk(struct vfs_cap_data *caps,
return -EINVAL;
}
- if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE) {
- bprm->cap_effective = true;
- } else {
- bprm->cap_effective = false;
- }
-
- ret = 0;
-
CAP_FOR_EACH_U32(i) {
- __u32 value_cpu;
-
- if (i >= tocopy) {
- /*
- * Legacy capability sets have no upper bits
- */
- bprm->cap_post_exec_permitted.cap[i] = 0;
+ if (i > tocopy) {
+ cpu_caps->permitted.cap[i] = 0;
+ cpu_caps->inheritable.cap[i] = 0;
continue;
}
- /*
- * pP' = (X & fP) | (pI & fI)
- */
- value_cpu = le32_to_cpu(caps->data[i].permitted);
- bprm->cap_post_exec_permitted.cap[i] =
- (current->cap_bset.cap[i] & value_cpu) |
- (current->cap_inheritable.cap[i] &
- le32_to_cpu(caps->data[i].inheritable));
- if (value_cpu & ~bprm->cap_post_exec_permitted.cap[i]) {
- /*
- * insufficient to execute correctly
- */
- ret = -EPERM;
- }
+ cpu_caps->permitted.cap[i] = le32_to_cpu(caps.data[i].permitted);
+ cpu_caps->inheritable.cap[i] = le32_to_cpu(caps.data[i].inheritable);
}
-
- /*
- * For legacy apps, with no internal support for recognizing they
- * do not have enough capabilities, we return an error if they are
- * missing some "forced" (aka file-permitted) capabilities.
- */
- return bprm->cap_effective ? ret : 0;
+ return 0;
}
/* Locate any VFS capabilities: */
@@ -276,7 +299,7 @@ static int get_file_caps(struct linux_binprm *bprm)
{
struct dentry *dentry;
int rc = 0;
- struct vfs_cap_data vcaps;
+ struct cpu_vfs_cap_data vcaps;
struct inode *inode;
if (bprm->file->f_vfsmnt->mnt_flags & MNT_NOSUID) {
@@ -289,17 +312,11 @@ static int get_file_caps(struct linux_binprm *bprm)
if (!inode->i_op || !inode->i_op->getxattr)
goto out;
- rc = inode->i_op->getxattr(dentry, XATTR_NAME_CAPS, &vcaps,
- XATTR_CAPS_SZ);
- if (rc == -ENODATA || rc == -EOPNOTSUPP) {
- /* no data, that's ok */
- rc = 0;
- goto out;
- }
+ rc = get_vfs_caps_from_disk(dentry, &vcaps);
if (rc < 0)
goto out;
- rc = cap_from_disk(&vcaps, bprm, rc);
+ rc = bprm_caps_from_vfs_caps(&vcaps, bprm);
if (rc == -EINVAL)
printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
__func__, rc, bprm->filename);
16 years
[PATCH 0/4] Series short description
by Eric Paris
The following series implements...
---
Eric Paris (4):
AUDIT: emit new record type showing all capset information
AUDIT: audit when fcaps increase the permitted or inheritable capabilities
AUDIT: output permitted and inheritable fcaps in PATH records
CAPABILITIES: add cpu endian vfs caps structure
include/linux/audit.h | 22 +++++
include/linux/capability.h | 12 +++
kernel/auditsc.c | 201 +++++++++++++++++++++++++++++++++++++++++++-
kernel/capability.c | 3 +
security/commoncap.c | 131 ++++++++++++++++-------------
5 files changed, 308 insertions(+), 61 deletions(-)
--
Signature
16 years
Add a new record which shows when fcaps escalate permissions
by Eric Paris
type=SYSCALL msg=audit(1224363342.919:60): arch=c000003e syscall=59 success=yes exit=0 a0=9f7460 a1=9fe7c0 a2=a059e0 a3=3445170a70 items=2 ppid=2328 pid=2356 auid=0 uid=500 gid=500 euid=500 suid=500 fsuid=500 egid=500 sgid=500 fsgid=500 tty=pts0 ses=1 comm="ping" exe="/bin/ping" subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=(null)
type=EXECVE msg=audit(1224363342.919:60): argc=2 a0="ping" a1="127.0.0.1"
type=UNKNOWN[1321] msg=audit(1224363342.919:60): file_permitted=0000000000003000 file_inheritable=0000000000003000 task_permitted=0000000000000000 task_inheritable=0000000000000000 task_effective=0000000000000000 bprm_effective=0000000000003000
type=CWD msg=audit(1224363342.919:60): cwd="/home/test"
type=PATH msg=audit(1224363342.919:60): item=0 name="/bin/ping" inode=49227 dev=fd:00 mode=0100755 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:ping_exec_t:s0 cap_permitted=0000000000003000 cap_inheritable=0000000000003000
type=PATH msg=audit(1224363342.919:60): item=1 name=(null) inode=507963 dev=fd:00 mode=0100755 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:ld_so_t:s0
So here's an example of my new record which shows a process getting new
capabilities. This record will only be created
if !(cap_issubset(bprm->cap_post_exec_permitted, tsk->cap_effective)).
So if a file has caps and but we already have those in our effective set
we will not generate this record. So 'root' executing ping would look
the same only there would be no record of type 1321....
Does this show the type of information you guys think would be useful?
-Eric
---
include/linux/audit.h | 4 +++
kernel/auditsc.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++
security/commoncap.c | 3 ++
3 files changed, 60 insertions(+)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 6272a39..ba62b3e 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -99,6 +99,7 @@
#define AUDIT_OBJ_PID 1318 /* ptrace target */
#define AUDIT_TTY 1319 /* Input on an administrative TTY */
#define AUDIT_EOE 1320 /* End of multi-record event */
+#define AUDIT_BPRM_FCAPS 1321 /* Information about fcaps increasing perms */
#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
@@ -569,6 +570,8 @@ extern void audit_log_d_path(struct audit_buffer *ab,
extern void audit_log_lost(const char *message);
extern int audit_update_lsm_rules(void);
+extern int audit_log_bprm_fcaps(struct linux_binprm *bprm, struct cpu_vfs_cap_data *caps);
+
/* Private API (for audit.c only) */
extern int audit_filter_user(struct netlink_skb_parms *cb);
extern int audit_filter_type(int type);
@@ -588,6 +591,7 @@ extern int audit_enabled;
#define audit_log_n_untrustedstring(a,n,s) do { ; } while (0)
#define audit_log_untrustedstring(a,s) do { ; } while (0)
#define audit_log_d_path(b, p, d) do { ; } while (0)
+#define audit_log_bprm_fcaps(b, c) 0
#define audit_enabled 0
#endif
#endif
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index d8eb36b..5809c6f 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -187,6 +187,16 @@ struct audit_aux_data_pids {
int pid_count;
};
+struct audit_aux_data_bprm_fcaps {
+ struct audit_aux_data d;
+ kernel_cap_t file_permitted;
+ kernel_cap_t file_inheritable;
+ kernel_cap_t task_permitted;
+ kernel_cap_t task_inheritable;
+ kernel_cap_t task_effective;
+ kernel_cap_t bprm_effective;
+};
+
struct audit_tree_refs {
struct audit_tree_refs *next;
struct audit_chunk *c[31];
@@ -1205,6 +1215,39 @@ static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name)
audit_log_cap(ab, "cap_inheritable", inh);
}
+int audit_log_bprm_fcaps(struct linux_binprm *bprm, struct cpu_vfs_cap_data *caps)
+{
+ struct audit_aux_data_bprm_fcaps *ax;
+ struct audit_context *context = current->audit_context;
+ struct task_struct *tsk = current;
+
+ if (likely(!audit_enabled || !context || context->dummy))
+ return 0;
+
+ /* find out if bprm has a new cap */
+ if (cap_issubset(bprm->cap_post_exec_permitted, tsk->cap_effective))
+ return 0;
+
+ ax = kmalloc(sizeof(*ax), GFP_KERNEL);
+ if (!ax)
+ return -ENOMEM;
+
+ ax->d.type = AUDIT_BPRM_FCAPS;
+ ax->d.next = context->aux;
+ context->aux = (void *)ax;
+
+ ax->file_permitted = caps->permitted;
+ ax->file_inheritable = caps->inheritable;
+
+ ax->task_permitted = tsk->cap_permitted;
+ ax->task_inheritable = tsk->cap_inheritable;
+ ax->task_effective = tsk->cap_effective;
+
+ ax->bprm_effective = bprm->cap_post_exec_permitted;
+
+ return 0;
+}
+
static void audit_log_exit(struct audit_context *context, struct task_struct *tsk)
{
int i, call_panic = 0;
@@ -1368,6 +1411,16 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
audit_log_format(ab, "fd0=%d fd1=%d", axs->fd[0], axs->fd[1]);
break; }
+ case AUDIT_BPRM_FCAPS: {
+ struct audit_aux_data_bprm_fcaps *axs = (void *)aux;
+ audit_log_cap(ab, "file_permitted", &axs->file_permitted);
+ audit_log_cap(ab, "file_inheritable", &axs->file_inheritable);
+ audit_log_cap(ab, "task_permitted", &axs->task_permitted);
+ audit_log_cap(ab, "task_inheritable", &axs->task_inheritable);
+ audit_log_cap(ab, "task_effective", &axs->task_effective);
+ audit_log_cap(ab, "bprm_effective", &axs->bprm_effective);
+ break; }
+
}
audit_log_end(ab);
}
diff --git a/security/commoncap.c b/security/commoncap.c
index 9f109b9..f1e6801 100644
--- a/security/commoncap.c
+++ b/security/commoncap.c
@@ -8,6 +8,7 @@
*/
#include <linux/capability.h>
+#include <linux/audit.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
@@ -321,6 +322,8 @@ static int get_file_caps(struct linux_binprm *bprm)
printk(KERN_NOTICE "%s: cap_from_disk returned %d for %s\n",
__func__, rc, bprm->filename);
+ audit_log_bprm_fcaps(bprm, &vcaps);
+
out:
dput(dentry);
if (rc)
16 years
A modular auditd
by Matthew Booth
I was going over the reasons recently why I changed austream from being
an auditd dispatcher to being a replacement audit daemon. They amounted to:
1. No nice way to prevent a dispatcher from generating audit events
2. Additional context switching becomes significant under load
3. Not possible to run auditd at real time priority
4. The config file is ugly if you don't want to write to disk
(1) is very bad, as it can cause a feedback loop which will eventually
kill the machine. If you stare at it hard enough there are ways round
it, but they're not pretty.
(2) When you really hammer it, the dispatcher interface overhead becomes
significant. In addition to the context switching you're also losing
message separation, so you need to do your own buffering.
(3) This is a problem if an application running at high priority
generates a significant burst of audited events. No matter how big you
make your buffers, if you produce faster than you consume you will
eventually run out of space. In my testing the performance of the system
when this happened was exceptionally poor (to the point of requiring a
hard reset).
(4) is not a strong reason in itself, but it highlights that auditd was
designed for writing to disk above all other use cases.
A while back I looked at Solaris's BSM, initially with a view to porting
austream to Solaris. I noted that BSM has 'plugins' which are
implemented as loadable modules[1]. It occurs to me that if auditd had
the same, this would address points (1) and (2). (3) also becomes
simpler and more robust once implemented, because you only have a single
real time process.
Point (4) can be addressed by refactoring existing output methods into
plugins. I believe this would currently amount to a 'file' plugin and a
'dispatcher' plugin. If they aren't loaded, they wouldn't need to be
unconfigured.
Thoughts?
Matt
[1] See man audit_control(4) and audit_syslog(5) on a Solaris system.
--
Matthew Booth, RHCA, RHCSS
Red Hat, Global Professional Services
M: +44 (0)7977 267231
GPG ID: D33C3490
GPG FPR: 3733 612D 2D05 5458 8A8A 1600 3441 EA19 D33C 3490
16 years
[PATCH] Fix a bug of executing "ausearch -te today PM"
by Peng Haitao
Hello steve,
executing "ausearch -te today PM" should be report error, but its result is equal to the result of executing "ausearch -te today" in audit > 1.7.4.
Signed-off-by: Peng Haitao <penght(a)cn.fujitsu.com>
---
src/ausearch-time.c | 45 +++++++++++++++++++++------------------------
1 files changed, 21 insertions(+), 24 deletions(-)
diff --git a/src/ausearch-time.c b/src/ausearch-time.c
index 5fc6d48..a9537d4 100644
--- a/src/ausearch-time.c
+++ b/src/ausearch-time.c
@@ -259,7 +259,6 @@ int ausearch_time_start(const char *da, const char *ti)
{
/* If da == NULL, use current date */
/* If ti == NULL, then use midnight 00:00:00 */
- int rc = 0;
struct tm d, t;
char *ret;
int keyword=-1;
@@ -282,8 +281,13 @@ int ausearch_time_start(const char *da, const char *ti)
}
} else {
keyword=lookup_time(da);
- if (keyword == T_RECENT || keyword == T_NOW)
- goto set_it;
+ if (keyword == T_RECENT || keyword == T_NOW) {
+ start_time = mktime(&d);
+ if (start_time == -1) {
+ fprintf(stderr, "Error converting start time\n");
+ return -1;
+ }
+ }
}
}
@@ -315,20 +319,14 @@ int ausearch_time_start(const char *da, const char *ti)
fprintf(stderr, "Error - year is %d\n", d.tm_year+1900);
return -1;
}
-set_it:
- start_time = mktime(&d);
- if (start_time == -1) {
- fprintf(stderr, "Error converting start time\n");
- rc = -1;
- }
- return rc;
+
+ return 0;
}
int ausearch_time_end(const char *da, const char *ti)
{
/* If date == NULL, use current date */
/* If ti == NULL, use current time */
- int rc = 0;
struct tm d, t;
char *ret;
@@ -348,12 +346,16 @@ int ausearch_time_end(const char *da, const char *ti)
}
} else {
int keyword=lookup_time(da);
- if (keyword == T_RECENT || keyword == T_NOW)
- goto set_it;
- // Special case today
- if (keyword == T_TODAY) {
- set_tm_now(&d);
- goto set_it;
+ if (keyword == T_RECENT || keyword == T_NOW || keyword == T_TODAY) {
+ // Special case today
+ if (keyword == T_TODAY) {
+ set_tm_now(&d);
+ }
+ end_time = mktime(&d);
+ if (end_time == -1) {
+ fprintf(stderr, "Error converting end time\n");
+ return -1;
+ }
}
}
}
@@ -390,12 +392,7 @@ int ausearch_time_end(const char *da, const char *ti)
fprintf(stderr, "Error - year is %d\n", d.tm_year+1900);
return -1;
}
-set_it:
- end_time = mktime(&d);
- if (end_time == -1) {
- fprintf(stderr, "Error converting end time\n");
- rc = -1;
- }
- return rc;
+
+ return 0;
}
--
1.5.3
--
Regards
Peng Haitao
16 years