[PATCH v3 0/3] audit: add support for openat2
by Richard Guy Briggs
The openat2(2) syscall was added in v5.6. Add support for openat2 to the
audit syscall classifier and for recording openat2 parameters that cannot
be captured in the syscall parameters of the SYSCALL record.
Supporting userspace code can be found in
https://github.com/rgbriggs/audit-userspace/tree/ghau-openat2
Supporting test case can be found in
https://github.com/linux-audit/audit-testsuite/pull/103
Changelog:
v3:
- re-add commit descriptions that somehow got dropped
- add new file to MAINTAINERS
v2:
- add include/linux/auditscm.h for audit syscall class macros due to syscall redefinition warnings:
arch/x86/ia32/audit.c:3:
./include/linux/audit.h:12,
./include/linux/sched.h:22,
./include/linux/seccomp.h:21,
./arch/x86/include/asm/seccomp.h:5,
./arch/x86/include/asm/unistd.h:20,
./arch/x86/include/generated/uapi/asm/unistd_64.h:4: warning: "__NR_read" redefined #define __NR_read 0
...
./arch/x86/include/generated/uapi/asm/unistd_64.h:338: warning: "__NR_rseq" redefined #define __NR_rseq 334
previous:
arch/x86/ia32/audit.c:2:
./arch/x86/include/generated/uapi/asm/unistd_32.h:7: note: this is the location of the previous definition #define __NR_read 3
...
./arch/x86/include/generated/uapi/asm/unistd_32.h:386: note: this is the location of the previous definition #define __NR_rseq 386
Richard Guy Briggs (3):
audit: replace magic audit syscall class numbers with macros
audit: add support for the openat2 syscall
audit: add OPENAT2 record to list how
MAINTAINERS | 1 +
arch/alpha/kernel/audit.c | 10 ++++++----
arch/ia64/kernel/audit.c | 10 ++++++----
arch/parisc/kernel/audit.c | 10 ++++++----
arch/parisc/kernel/compat_audit.c | 11 +++++++----
arch/powerpc/kernel/audit.c | 12 +++++++-----
arch/powerpc/kernel/compat_audit.c | 13 ++++++++-----
arch/s390/kernel/audit.c | 12 +++++++-----
arch/s390/kernel/compat_audit.c | 13 ++++++++-----
arch/sparc/kernel/audit.c | 12 +++++++-----
arch/sparc/kernel/compat_audit.c | 13 ++++++++-----
arch/x86/ia32/audit.c | 13 ++++++++-----
arch/x86/kernel/audit_64.c | 10 ++++++----
fs/open.c | 2 ++
include/linux/audit.h | 11 +++++++++++
include/linux/auditscm.h | 24 +++++++++++++++++++++++
include/uapi/linux/audit.h | 1 +
kernel/audit.h | 2 ++
kernel/auditsc.c | 31 ++++++++++++++++++++++++------
lib/audit.c | 14 +++++++++-----
lib/compat_audit.c | 15 ++++++++++-----
21 files changed, 169 insertions(+), 71 deletions(-)
create mode 100644 include/linux/auditscm.h
--
2.27.0
3 years, 5 months
[PATCH V1] audit: log xattr args not covered by syscall record
by Richard Guy Briggs
The *setxattr syscalls take 5 arguments. The SYSCALL record only lists
four arguments and only lists pointers of string values. The xattr name
string, value string and flags (5th arg) are needed by audit given the
syscall's main purpose.
Add the auxiliary record AUDIT_XATTR (1336) to record the details not
available in the SYSCALL record including the name string, value string
and flags.
Notes about field names:
- name is too generic, use xattr precedent from ima
- val is already generic value field name
- flags used by mmap, xflags new name
Sample event with new record:
type=PROCTITLE msg=audit(05/07/2021 12:58:42.176:189) : proctitle=filecap /tmp/ls dac_override
type=PATH msg=audit(05/07/2021 12:58:42.176:189) : item=0 name=(null) inode=25 dev=00:1e mode=file,755 ouid=root ogid=root rdev=00:00 obj=unconfined_u:object_r:user_tmp_t:s0 nametype=NORMAL cap_fp=none cap_fi=none cap_fe=0 cap_fver=0 cap_frootid=0
type=CWD msg=audit(05/07/2021 12:58:42.176:189) : cwd=/root
type=XATTR msg=audit(05/07/2021 12:58:42.176:189) : xattr="security.capability" val=01 xflags=0x0
type=SYSCALL msg=audit(05/07/2021 12:58:42.176:189) : arch=x86_64 syscall=fsetxattr success=yes exit=0 a0=0x3 a1=0x7fc2f055905f a2=0x7ffebd58ebb0 a3=0x14 items=1 ppid=526 pid=554 auid=root uid=root gid=root euid=root suid=root fsuid=root egid=root sgid=root fsgid=root tty=ttyS0 ses=1 comm=filecap exe=/usr/bin/filecap subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=cap-test
Link: https://github.com/linux-audit/audit-kernel/issues/39
Link: https://lore.kernel.org/r/604ceafd516b0785fea120f552d6336054d196af.162041...
Suggested-by: Steve Grubb <sgrubb(a)redhat.com>
Signed-off-by: Richard Guy Briggs <rgb(a)redhat.com>
---
fs/xattr.c | 2 ++
include/linux/audit.h | 10 +++++++++
include/uapi/linux/audit.h | 1 +
kernel/audit.h | 5 +++++
kernel/auditsc.c | 45 ++++++++++++++++++++++++++++++++++++++
5 files changed, 63 insertions(+)
diff --git a/fs/xattr.c b/fs/xattr.c
index b3444e06cded..f2b6af1719fd 100644
--- a/fs/xattr.c
+++ b/fs/xattr.c
@@ -570,6 +570,7 @@ setxattr(struct user_namespace *mnt_userns, struct dentry *d,
posix_acl_fix_xattr_from_user(mnt_userns, kvalue, size);
}
+ audit_xattr(name, value, flags);
error = vfs_setxattr(mnt_userns, d, kname, kvalue, size, flags);
out:
kvfree(kvalue);
@@ -816,6 +817,7 @@ removexattr(struct user_namespace *mnt_userns, struct dentry *d,
if (error < 0)
return error;
+ audit_xattr(name, "(null)", 0);
return vfs_removexattr(mnt_userns, d, kname);
}
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 82b7c1116a85..784d34888c8a 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -404,6 +404,7 @@ extern void __audit_tk_injoffset(struct timespec64 offset);
extern void __audit_ntp_log(const struct audit_ntp_data *ad);
extern void __audit_log_nfcfg(const char *name, u8 af, unsigned int nentries,
enum audit_nfcfgop op, gfp_t gfp);
+extern void __audit_xattr(const char *name, const char *value, int flags);
static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
{
@@ -547,6 +548,12 @@ static inline void audit_log_nfcfg(const char *name, u8 af,
__audit_log_nfcfg(name, af, nentries, op, gfp);
}
+static inline void audit_xattr(const char *name, const char *value, int flags)
+{
+ if (!audit_dummy_context())
+ __audit_xattr(name, value, flags);
+}
+
extern int audit_n_rules;
extern int audit_signals;
#else /* CONFIG_AUDITSYSCALL */
@@ -677,6 +684,9 @@ static inline void audit_log_nfcfg(const char *name, u8 af,
enum audit_nfcfgop op, gfp_t gfp)
{ }
+static inline void audit_xattr(const char *name, const char *value, int flags)
+{ }
+
#define audit_n_rules 0
#define audit_signals 0
#endif /* CONFIG_AUDITSYSCALL */
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index cd2d8279a5e4..4477ff80a24d 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -118,6 +118,7 @@
#define AUDIT_TIME_ADJNTPVAL 1333 /* NTP value adjustment */
#define AUDIT_BPF 1334 /* BPF subsystem */
#define AUDIT_EVENT_LISTENER 1335 /* Task joined multicast read socket */
+#define AUDIT_XATTR 1336 /* xattr arguments */
#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
diff --git a/kernel/audit.h b/kernel/audit.h
index 1522e100fd17..9544284fce57 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -191,6 +191,11 @@ struct audit_context {
struct {
char *name;
} module;
+ struct {
+ char *name;
+ char *value;
+ int flags;
+ } xattr;
};
int fds[2];
struct audit_proctitle proctitle;
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 8bb9ac84d2fb..7f2b56136fa4 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -884,6 +884,7 @@ static inline void audit_free_module(struct audit_context *context)
context->module.name = NULL;
}
}
+
static inline void audit_free_names(struct audit_context *context)
{
struct audit_names *n, *next;
@@ -915,6 +916,16 @@ static inline void audit_free_aux(struct audit_context *context)
}
}
+static inline void audit_free_xattr(struct audit_context *context)
+{
+ if (context->type == AUDIT_XATTR) {
+ kfree(context->xattr.name);
+ context->xattr.name = NULL;
+ kfree(context->xattr.value);
+ context->xattr.value = NULL;
+ }
+}
+
static inline struct audit_context *audit_alloc_context(enum audit_state state)
{
struct audit_context *context;
@@ -969,6 +980,7 @@ int audit_alloc(struct task_struct *tsk)
static inline void audit_free_context(struct audit_context *context)
{
+ audit_free_xattr(context);
audit_free_module(context);
audit_free_names(context);
unroll_tree_refs(context, NULL, 0);
@@ -1317,6 +1329,20 @@ static void show_special(struct audit_context *context, int *call_panic)
} else
audit_log_format(ab, "(null)");
+ break;
+ case AUDIT_XATTR:
+ audit_log_format(ab, "xattr=");
+ if (context->xattr.name)
+ audit_log_untrustedstring(ab, context->xattr.name);
+ else
+ audit_log_format(ab, "(null)");
+ audit_log_format(ab, " val=");
+ if (context->xattr.value)
+ audit_log_untrustedstring(ab, context->xattr.value);
+ else
+ audit_log_format(ab, "(null)");
+ audit_log_format(ab, " xflags=0x%x", context->xattr.flags);
+
break;
}
audit_log_end(ab);
@@ -1742,6 +1768,7 @@ void __audit_syscall_exit(int success, long return_code)
context->in_syscall = 0;
context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0;
+ audit_free_xattr(context);
audit_free_module(context);
audit_free_names(context);
unroll_tree_refs(context, NULL, 0);
@@ -2536,6 +2563,24 @@ void __audit_log_kern_module(char *name)
context->type = AUDIT_KERN_MODULE;
}
+void __audit_xattr(const char *name, const char *value, int flags)
+{
+ struct audit_context *context = audit_context();
+
+ context->type = AUDIT_XATTR;
+ context->xattr.flags = flags;
+ context->xattr.name = kstrdup(name, GFP_KERNEL);
+ if (!context->xattr.name)
+ goto out;
+ context->xattr.value = kstrdup(value, GFP_KERNEL);
+ if (!context->xattr.value)
+ goto out;
+ return;
+out:
+ kfree(context->xattr.name);
+ audit_log_lost("out of memory in __audit_xattr");
+}
+
void __audit_fanotify(unsigned int response)
{
audit_log(audit_context(), GFP_KERNEL,
--
2.27.0
3 years, 5 months
[PATCH] audit: add blank line after variable declarations
by Roni Nevalainen
Fix the following checkpatch warning in auditsc.c:
WARNING: Missing a blank line after declarations
Signed-off-by: Roni Nevalainen <kitten(a)kittenz.dev>
---
kernel/auditsc.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 175ef6f3ea4e..0a9a1569f1ea 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -160,6 +160,7 @@ static const struct audit_nfcfgop_tab audit_nfcfgs[] = {
static int audit_match_perm(struct audit_context *ctx, int mask)
{
unsigned n;
+
if (unlikely(!ctx))
return 0;
n = ctx->major;
@@ -239,6 +240,7 @@ static int put_tree_ref(struct audit_context *ctx, struct audit_chunk *chunk)
{
struct audit_tree_refs *p = ctx->trees;
int left = ctx->tree_count;
+
if (likely(left)) {
p->c[--left] = chunk;
ctx->tree_count = left;
@@ -259,6 +261,7 @@ static int put_tree_ref(struct audit_context *ctx, struct audit_chunk *chunk)
static int grow_tree_refs(struct audit_context *ctx)
{
struct audit_tree_refs *p = ctx->trees;
+
ctx->trees = kzalloc(sizeof(struct audit_tree_refs), GFP_KERNEL);
if (!ctx->trees) {
ctx->trees = p;
@@ -277,6 +280,7 @@ static void unroll_tree_refs(struct audit_context *ctx,
{
struct audit_tree_refs *q;
int n;
+
if (!p) {
/* we started with empty chain */
p = ctx->first_trees;
@@ -303,6 +307,7 @@ static void unroll_tree_refs(struct audit_context *ctx,
static void free_tree_refs(struct audit_context *ctx)
{
struct audit_tree_refs *p, *q;
+
for (p = ctx->first_trees; p; p = q) {
q = p->next;
kfree(p);
@@ -313,6 +318,7 @@ static int match_tree_refs(struct audit_context *ctx, struct audit_tree *tree)
{
struct audit_tree_refs *p;
int n;
+
if (!tree)
return 0;
/* full ones */
@@ -1225,6 +1231,7 @@ static void show_special(struct audit_context *context, int *call_panic)
switch (context->type) {
case AUDIT_SOCKETCALL: {
int nargs = context->socketcall.nargs;
+
audit_log_format(ab, "nargs=%d", nargs);
for (i = 0; i < nargs; i++)
audit_log_format(ab, " a%d=%lx", i,
@@ -1240,6 +1247,7 @@ static void show_special(struct audit_context *context, int *call_panic)
if (osid) {
char *ctx = NULL;
u32 len;
+
if (security_secid_to_secctx(osid, &ctx, &len)) {
audit_log_format(ab, " osid=%u", osid);
*call_panic = 1;
@@ -1289,6 +1297,7 @@ static void show_special(struct audit_context *context, int *call_panic)
break;
case AUDIT_MQ_GETSETATTR: {
struct mq_attr *attr = &context->mq_getsetattr.mqstat;
+
audit_log_format(ab,
"mqdes=%d mq_flags=0x%lx mq_maxmsg=%ld mq_msgsize=%ld "
"mq_curmsgs=%ld ",
@@ -1325,6 +1334,7 @@ static void show_special(struct audit_context *context, int *call_panic)
static inline int audit_proctitle_rtrim(char *proctitle, int len)
{
char *end = proctitle + len - 1;
+
while (end > proctitle && !isprint(*end))
end--;
@@ -1513,6 +1523,7 @@ static void audit_log_exit(void)
case AUDIT_BPRM_FCAPS: {
struct audit_aux_data_bprm_fcaps *axs = (void *)aux;
+
audit_log_format(ab, "fver=%x", axs->fcap_ver);
audit_log_cap(ab, "fp", &axs->fcap.permitted);
audit_log_cap(ab, "fi", &axs->fcap.inheritable);
@@ -1765,6 +1776,7 @@ static inline void handle_one(const struct inode *inode)
struct audit_tree_refs *p;
struct audit_chunk *chunk;
int count;
+
if (likely(!inode->i_fsnotify_marks))
return;
context = audit_context();
@@ -1806,8 +1818,10 @@ static void handle_path(const struct dentry *dentry)
seq = read_seqbegin(&rename_lock);
for(;;) {
struct inode *inode = d_backing_inode(d);
+
if (inode && unlikely(inode->i_fsnotify_marks)) {
struct audit_chunk *chunk;
+
chunk = audit_tree_lookup(inode);
if (chunk) {
if (unlikely(!put_tree_ref(context, chunk))) {
@@ -2285,6 +2299,7 @@ void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification)
void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
{
struct audit_context *context = audit_context();
+
context->mq_getsetattr.mqdes = mqdes;
context->mq_getsetattr.mqstat = *mqstat;
context->type = AUDIT_MQ_GETSETATTR;
@@ -2298,6 +2313,7 @@ void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat)
void __audit_ipc_obj(struct kern_ipc_perm *ipcp)
{
struct audit_context *context = audit_context();
+
context->ipc.uid = ipcp->uid;
context->ipc.gid = ipcp->gid;
context->ipc.mode = ipcp->mode;
@@ -2362,6 +2378,7 @@ int __audit_socketcall(int nargs, unsigned long *args)
void __audit_fd_pair(int fd1, int fd2)
{
struct audit_context *context = audit_context();
+
context->fds[0] = fd1;
context->fds[1] = fd2;
}
@@ -2379,6 +2396,7 @@ int __audit_sockaddr(int len, void *a)
if (!context->sockaddr) {
void *p = kmalloc(sizeof(struct sockaddr_storage), GFP_KERNEL);
+
if (!p)
return -ENOMEM;
context->sockaddr = p;
@@ -2510,6 +2528,7 @@ int __audit_log_bprm_fcaps(struct linux_binprm *bprm,
void __audit_log_capset(const struct cred *new, const struct cred *old)
{
struct audit_context *context = audit_context();
+
context->capset.pid = task_tgid_nr(current);
context->capset.cap.effective = new->cap_effective;
context->capset.cap.inheritable = new->cap_effective;
@@ -2521,6 +2540,7 @@ void __audit_log_capset(const struct cred *new, const struct cred *old)
void __audit_mmap_fd(int fd, int flags)
{
struct audit_context *context = audit_context();
+
context->mmap.fd = fd;
context->mmap.flags = flags;
context->type = AUDIT_MMAP;
@@ -2686,6 +2706,7 @@ void audit_seccomp_actions_logged(const char *names, const char *old_names,
struct list_head *audit_killed_trees(void)
{
struct audit_context *ctx = audit_context();
+
if (likely(!ctx || !ctx->in_syscall))
return NULL;
return &ctx->killed_trees;
--
2.30.2
3 years, 5 months