[PATCH RESEND 1/2] audit: introduce a struct to represent an audit timestamp

2022-12-19 Thread Ondrej Mosnacek
Join the two fields that comprise an audit timestamp into a common
structure. This will be used further in later commits.

Signed-off-by: Ondrej Mosnacek 
---
 include/linux/audit.h |  5 +
 kernel/audit.c| 16 
 kernel/audit.h|  4 ++--
 kernel/auditsc.c  |  9 -
 4 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 3608992848d3..788ab93c3be4 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -84,6 +84,11 @@ enum audit_ntp_type {
AUDIT_NTP_NVALS /* count */
 };
 
+struct audit_timestamp {
+   struct timespec64 t;
+   unsigned int serial;
+};
+
 #ifdef CONFIG_AUDITSYSCALL
 struct audit_ntp_val {
long long oldval, newval;
diff --git a/kernel/audit.c b/kernel/audit.c
index 9bc0b0301198..aded2d69ea69 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1818,11 +1818,11 @@ unsigned int audit_serial(void)
 }
 
 static inline void audit_get_stamp(struct audit_context *ctx,
-  struct timespec64 *t, unsigned int *serial)
+  struct audit_timestamp *ts)
 {
-   if (!ctx || !auditsc_get_stamp(ctx, t, serial)) {
-   ktime_get_coarse_real_ts64(t);
-   *serial = audit_serial();
+   if (!ctx || !auditsc_get_stamp(ctx, ts)) {
+   ktime_get_coarse_real_ts64(>t);
+   ts->serial = audit_serial();
}
 }
 
@@ -1845,8 +1845,7 @@ struct audit_buffer *audit_log_start(struct audit_context 
*ctx, gfp_t gfp_mask,
 int type)
 {
struct audit_buffer *ab;
-   struct timespec64 t;
-   unsigned int serial;
+   struct audit_timestamp ts;
 
if (audit_initialized != AUDIT_INITIALIZED)
return NULL;
@@ -1901,12 +1900,13 @@ struct audit_buffer *audit_log_start(struct 
audit_context *ctx, gfp_t gfp_mask,
return NULL;
}
 
-   audit_get_stamp(ab->ctx, , );
+   audit_get_stamp(ab->ctx, );
/* cancel dummy context to enable supporting records */
if (ctx)
ctx->dummy = 0;
audit_log_format(ab, "audit(%llu.%03lu:%u): ",
-(unsigned long long)t.tv_sec, t.tv_nsec/100, 
serial);
+(unsigned long long)ts.t.tv_sec, ts.t.tv_nsec/100,
+ts.serial);
 
return ab;
 }
diff --git a/kernel/audit.h b/kernel/audit.h
index c57b008b9914..e3ea00ea399a 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -262,7 +262,7 @@ extern void audit_put_tty(struct tty_struct *tty);
 #ifdef CONFIG_AUDITSYSCALL
 extern unsigned int audit_serial(void);
 extern int auditsc_get_stamp(struct audit_context *ctx,
- struct timespec64 *t, unsigned int *serial);
+struct audit_timestamp *ts);
 
 extern void audit_put_watch(struct audit_watch *watch);
 extern void audit_get_watch(struct audit_watch *watch);
@@ -303,7 +303,7 @@ extern void audit_filter_inodes(struct task_struct *tsk,
struct audit_context *ctx);
 extern struct list_head *audit_killed_trees(void);
 #else /* CONFIG_AUDITSYSCALL */
-#define auditsc_get_stamp(c, t, s) 0
+#define auditsc_get_stamp(c, ts) 0
 #define audit_put_watch(w) do { } while (0)
 #define audit_get_watch(w) do { } while (0)
 #define audit_to_watch(k, p, l, o) (-EINVAL)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 9f8c05228d6d..061009ba9959 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2513,16 +2513,15 @@ EXPORT_SYMBOL_GPL(__audit_inode_child);
  *
  * Also sets the context as auditable.
  */
-int auditsc_get_stamp(struct audit_context *ctx,
-  struct timespec64 *t, unsigned int *serial)
+int auditsc_get_stamp(struct audit_context *ctx, struct audit_timestamp *ts)
 {
if (ctx->context == AUDIT_CTX_UNUSED)
return 0;
if (!ctx->serial)
ctx->serial = audit_serial();
-   t->tv_sec  = ctx->ctime.tv_sec;
-   t->tv_nsec = ctx->ctime.tv_nsec;
-   *serial= ctx->serial;
+   ts->t.tv_sec  = ctx->ctime.tv_sec;
+   ts->t.tv_nsec = ctx->ctime.tv_nsec;
+   ts->serial= ctx->serial;
if (!ctx->prio) {
ctx->prio = 1;
ctx->current_state = AUDIT_STATE_RECORD;
-- 
2.38.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://listman.redhat.com/mailman/listinfo/linux-audit



[PATCH RESEND 0/2] Provide matching audit timestamp in the SELinux AVC trace event

2022-12-19 Thread Ondrej Mosnacek
(Resending due to an error on the first attempt.)

This series allows to match the SELinux AVC trace events to the
corresponding audit events via the audit event timestamp. This
will help with troubleshooting SELinux denials.

Ondrej Mosnacek (2):
  audit: introduce a struct to represent an audit timestamp
  selinux: provide matching audit timestamp in the AVC trace event

 include/linux/audit.h  | 13 +
 include/trace/events/avc.h | 25 +
 kernel/audit.c | 23 +++
 kernel/audit.h |  4 ++--
 kernel/auditsc.c   |  9 -
 security/selinux/avc.c |  4 +++-
 6 files changed, 54 insertions(+), 24 deletions(-)

-- 
2.38.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://listman.redhat.com/mailman/listinfo/linux-audit



[PATCH RESEND 2/2] selinux: provide matching audit timestamp in the AVC trace event

2022-12-19 Thread Ondrej Mosnacek
In order to make it possible for the users and tooling to associate an
SELinux AVC trace event with the corresponding audit event, make it
include the audit timestamp (including the "serial number") of the
event.

First make audit_log_start() include the timestamp in the audit_buffer
struct and add a public helper to retrieve it from an audit_buffer
instance. Then retrieve it in SELinux's avc_audit_post_callback() and
include it in the "avc:selinux_audited" trace event.

After this patch the even includes the numeric fields that make up the
timestamp and the text representation includes the timestamp in the same
format as used in the audit log - e.g. "audit_ts=1671454430.092:1671".

Signed-off-by: Ondrej Mosnacek 
---
 include/linux/audit.h  |  8 
 include/trace/events/avc.h | 25 +
 kernel/audit.c | 15 +++
 security/selinux/avc.c |  4 +++-
 4 files changed, 39 insertions(+), 13 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 788ab93c3be4..d6d7acc1b623 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -162,6 +162,9 @@ extern __printf(4, 5)
 void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
   const char *fmt, ...);
 
+extern void audit_buffer_get_timestamp(struct audit_buffer *ab,
+  struct audit_timestamp *ts);
+
 extern struct audit_buffer *audit_log_start(struct audit_context *ctx, gfp_t 
gfp_mask, int type);
 extern __printf(2, 3)
 void audit_log_format(struct audit_buffer *ab, const char *fmt, ...);
@@ -218,6 +221,11 @@ static inline __printf(4, 5)
 void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
   const char *fmt, ...)
 { }
+static inline void audit_buffer_get_timestamp(struct audit_buffer *ab,
+ struct audit_timestamp *ts)
+{
+   *ts = (struct audit_timestamp){};
+}
 static inline struct audit_buffer *audit_log_start(struct audit_context *ctx,
   gfp_t gfp_mask, int type)
 {
diff --git a/include/trace/events/avc.h b/include/trace/events/avc.h
index b55fda2e0773..8cac14ae22ae 100644
--- a/include/trace/events/avc.h
+++ b/include/trace/events/avc.h
@@ -16,34 +16,43 @@ TRACE_EVENT(selinux_audited,
TP_PROTO(struct selinux_audit_data *sad,
char *scontext,
char *tcontext,
-   const char *tclass
+   const char *tclass,
+   const struct audit_timestamp *ts
),
 
-   TP_ARGS(sad, scontext, tcontext, tclass),
+   TP_ARGS(sad, scontext, tcontext, tclass, ts),
 
TP_STRUCT__entry(
__field(u32, requested)
__field(u32, denied)
__field(u32, audited)
__field(int, result)
+   __field(u64, audit_stamp_sec)
+   __field(u32, audit_stamp_msec)
+   __field(u32, audit_stamp_serial)
__string(scontext, scontext)
__string(tcontext, tcontext)
__string(tclass, tclass)
),
 
TP_fast_assign(
-   __entry->requested  = sad->requested;
-   __entry->denied = sad->denied;
-   __entry->audited= sad->audited;
-   __entry->result = sad->result;
+   __entry->requested  = sad->requested;
+   __entry->denied = sad->denied;
+   __entry->audited= sad->audited;
+   __entry->result = sad->result;
+   __entry->audit_stamp_sec= ts->t.tv_sec;
+   __entry->audit_stamp_msec   = ts->t.tv_nsec / 100;
+   __entry->audit_stamp_serial = ts->serial;
__assign_str(tcontext, tcontext);
__assign_str(scontext, scontext);
__assign_str(tclass, tclass);
),
 
-   TP_printk("requested=0x%x denied=0x%x audited=0x%x result=%d 
scontext=%s tcontext=%s tclass=%s",
+   TP_printk("requested=0x%x denied=0x%x audited=0x%x result=%d 
scontext=%s tcontext=%s tclass=%s audit_ts=%llu.%03u:%u",
__entry->requested, __entry->denied, __entry->audited, 
__entry->result,
-   __get_str(scontext), __get_str(tcontext), __get_str(tclass)
+   __get_str(scontext), __get_str(tcontext), __get_str(tclass),
+   __entry->audit_stamp_sec, __entry->audit_stamp_msec,
+   __entry->audit_stamp_serial
)
 );
 
diff --git a/kernel/audit.c b/kernel/audit.c
index aded2d69ea69..ad21d148704a 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -199,6 +199,7 @@ static struct audit_ctl_mutex {
 struct audit_buffer {
struct sk_buff  

[PATCH 1/2] audit: introduce a struct to represent an audit timestamp

2022-12-19 Thread Ondrej Mosnacek
Join the two fields that comprise an audit timestamp into a common
structure. This will be used further in later commits.

Signed-off-by: Ondrej Mosnacek 
---
 include/linux/audit.h |  5 +
 kernel/audit.c| 16 
 kernel/audit.h|  4 ++--
 kernel/auditsc.c  |  9 -
 4 files changed, 19 insertions(+), 15 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 3608992848d3..788ab93c3be4 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -84,6 +84,11 @@ enum audit_ntp_type {
AUDIT_NTP_NVALS /* count */
 };
 
+struct audit_timestamp {
+   struct timespec64 t;
+   unsigned int serial;
+};
+
 #ifdef CONFIG_AUDITSYSCALL
 struct audit_ntp_val {
long long oldval, newval;
diff --git a/kernel/audit.c b/kernel/audit.c
index 9bc0b0301198..aded2d69ea69 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -1818,11 +1818,11 @@ unsigned int audit_serial(void)
 }
 
 static inline void audit_get_stamp(struct audit_context *ctx,
-  struct timespec64 *t, unsigned int *serial)
+  struct audit_timestamp *ts)
 {
-   if (!ctx || !auditsc_get_stamp(ctx, t, serial)) {
-   ktime_get_coarse_real_ts64(t);
-   *serial = audit_serial();
+   if (!ctx || !auditsc_get_stamp(ctx, ts)) {
+   ktime_get_coarse_real_ts64(>t);
+   ts->serial = audit_serial();
}
 }
 
@@ -1845,8 +1845,7 @@ struct audit_buffer *audit_log_start(struct audit_context 
*ctx, gfp_t gfp_mask,
 int type)
 {
struct audit_buffer *ab;
-   struct timespec64 t;
-   unsigned int serial;
+   struct audit_timestamp ts;
 
if (audit_initialized != AUDIT_INITIALIZED)
return NULL;
@@ -1901,12 +1900,13 @@ struct audit_buffer *audit_log_start(struct 
audit_context *ctx, gfp_t gfp_mask,
return NULL;
}
 
-   audit_get_stamp(ab->ctx, , );
+   audit_get_stamp(ab->ctx, );
/* cancel dummy context to enable supporting records */
if (ctx)
ctx->dummy = 0;
audit_log_format(ab, "audit(%llu.%03lu:%u): ",
-(unsigned long long)t.tv_sec, t.tv_nsec/100, 
serial);
+(unsigned long long)ts.t.tv_sec, ts.t.tv_nsec/100,
+ts.serial);
 
return ab;
 }
diff --git a/kernel/audit.h b/kernel/audit.h
index c57b008b9914..e3ea00ea399a 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -262,7 +262,7 @@ extern void audit_put_tty(struct tty_struct *tty);
 #ifdef CONFIG_AUDITSYSCALL
 extern unsigned int audit_serial(void);
 extern int auditsc_get_stamp(struct audit_context *ctx,
- struct timespec64 *t, unsigned int *serial);
+struct audit_timestamp *ts);
 
 extern void audit_put_watch(struct audit_watch *watch);
 extern void audit_get_watch(struct audit_watch *watch);
@@ -303,7 +303,7 @@ extern void audit_filter_inodes(struct task_struct *tsk,
struct audit_context *ctx);
 extern struct list_head *audit_killed_trees(void);
 #else /* CONFIG_AUDITSYSCALL */
-#define auditsc_get_stamp(c, t, s) 0
+#define auditsc_get_stamp(c, ts) 0
 #define audit_put_watch(w) do { } while (0)
 #define audit_get_watch(w) do { } while (0)
 #define audit_to_watch(k, p, l, o) (-EINVAL)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 9f8c05228d6d..061009ba9959 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2513,16 +2513,15 @@ EXPORT_SYMBOL_GPL(__audit_inode_child);
  *
  * Also sets the context as auditable.
  */
-int auditsc_get_stamp(struct audit_context *ctx,
-  struct timespec64 *t, unsigned int *serial)
+int auditsc_get_stamp(struct audit_context *ctx, struct audit_timestamp *ts)
 {
if (ctx->context == AUDIT_CTX_UNUSED)
return 0;
if (!ctx->serial)
ctx->serial = audit_serial();
-   t->tv_sec  = ctx->ctime.tv_sec;
-   t->tv_nsec = ctx->ctime.tv_nsec;
-   *serial= ctx->serial;
+   ts->t.tv_sec  = ctx->ctime.tv_sec;
+   ts->t.tv_nsec = ctx->ctime.tv_nsec;
+   ts->serial= ctx->serial;
if (!ctx->prio) {
ctx->prio = 1;
ctx->current_state = AUDIT_STATE_RECORD;
-- 
2.38.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://listman.redhat.com/mailman/listinfo/linux-audit



[PATCH 0/2] Provide matching audit timestamp in the SELinux AVC trace event

2022-12-19 Thread Ondrej Mosnacek
This series allows to match the SELinux AVC trace events to the
corresponding audit events via the audit event timestamp. This
will help with troubleshooting SELinux denials.

Ondrej Mosnacek (2):
  audit: introduce a struct to represent an audit timestamp
  selinux: provide matching audit timestamp in the AVC trace event

 include/linux/audit.h  | 13 +
 include/trace/events/avc.h | 25 +
 kernel/audit.c | 23 +++
 kernel/audit.h |  4 ++--
 kernel/auditsc.c   |  9 -
 security/selinux/avc.c |  4 +++-
 6 files changed, 54 insertions(+), 24 deletions(-)

-- 
2.38.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://listman.redhat.com/mailman/listinfo/linux-audit



[PATCH] lsm_audit: avoid overloading the "key" audit field

2021-09-14 Thread Ondrej Mosnacek
The "key" field is used to associate records with the rule that
triggered them, os it's not a good idea to overload it with an
additional IPC key semantic. Moreover, as the classic "key" field is a
text field, while the IPC key is numeric, AVC records containing the IPC
key info actually confuse audit userspace, which tries to interpret the
number as a hex-encoded string, thus showing garbage for example in the
ausearch "interpret" output mode.

Hence, change it to "ipc_key" to fix both issues and also make the
meaning of this field more clear.

Signed-off-by: Ondrej Mosnacek 
---
 security/lsm_audit.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index 5a5016ef43b0..1897cbf6fc69 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -224,7 +224,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
case LSM_AUDIT_DATA_NONE:
return;
case LSM_AUDIT_DATA_IPC:
-   audit_log_format(ab, " key=%d ", a->u.ipc_id);
+   audit_log_format(ab, " ipc_key=%d ", a->u.ipc_id);
break;
case LSM_AUDIT_DATA_CAP:
audit_log_format(ab, " capability=%d ", a->u.cap);
-- 
2.31.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://listman.redhat.com/mailman/listinfo/linux-audit



[PATCH v2] lsm_audit,selinux: pass IB device name by reference

2021-05-12 Thread Ondrej Mosnacek
While trying to address a Coverity warning that the dev_name string
might end up unterminated when strcpy'ing it in
selinux_ib_endport_manage_subnet(), I realized that it is possible (and
simpler) to just pass the dev_name pointer directly, rather than copying
the string to a buffer.

The ibendport variable goes out of scope at the end of the function
anyway, so the lifetime of the dev_name pointer will never be shorter
than that of ibendport, thus we can safely just pass the dev_name
pointer and be done with it.

Signed-off-by: Ondrej Mosnacek 
---
 include/linux/lsm_audit.h | 8 
 security/selinux/hooks.c  | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

v2: just pass the dev_name pointer and avoid the string copy

v1:
https://lore.kernel.org/selinux/20210507130445.145457-1-omosn...@redhat.com/T/

diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
index cd23355d2271..17d02eda9538 100644
--- a/include/linux/lsm_audit.h
+++ b/include/linux/lsm_audit.h
@@ -48,13 +48,13 @@ struct lsm_ioctlop_audit {
 };
 
 struct lsm_ibpkey_audit {
-   u64 subnet_prefix;
-   u16 pkey;
+   u64 subnet_prefix;
+   u16 pkey;
 };
 
 struct lsm_ibendport_audit {
-   chardev_name[IB_DEVICE_NAME_MAX];
-   u8  port;
+   const char *dev_name;
+   u8 port;
 };
 
 /* Auxiliary data to use in generating the audit record. */
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 92f909a2e8f7..4d9764dad18f 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -6864,7 +6864,7 @@ static int selinux_ib_endport_manage_subnet(void *ib_sec, 
const char *dev_name,
return err;
 
ad.type = LSM_AUDIT_DATA_IBENDPORT;
-   strncpy(ibendport.dev_name, dev_name, sizeof(ibendport.dev_name));
+   ibendport.dev_name = dev_name;
ibendport.port = port_num;
ad.u.ibendport = 
return avc_has_perm(_state,
-- 
2.31.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://listman.redhat.com/mailman/listinfo/linux-audit



Re: Additional parameter in PROCTITLE.proctitle when executing rm

2021-03-18 Thread Ondrej Mosnacek
On Thu, Mar 18, 2021 at 8:32 PM Alan Evangelista  wrote:
> I'm trying to audit commands run in bash, including the commands arguments. 
> The proctitle parameter in the PROCTITLE record seems to be the most reliable 
> source to get that, but it does not contain exactly the "rm" command I have 
> typed on bash. Example:
>
> 1) rm /data/test2,txt -f
>
> type=SYSCALL msg=audit(1616095201.302:40381): arch=c03e syscall=263 
> success=yes exit=0 a0=ff9c a1=1b1f0c0 a2=0 a3=7fff3677a720 
> items=3 ppid=15954 pid=3398 auid=201327714 uid=0 gid=0 euid=0 suid=0 fsuid=0 
> egid=0 sgid=0 fsgid=0 tty=pts0 ses=2663 comm="rm" exe="/usr/bin/rm" 
> key="filesystem_op"
> type=CWD msg=audit(1616095201.302:40381):  cwd="/home/aevangelista"
> type=PATH msg=audit(1616095201.302:40381): item=0 name="/data/test2.txt" 
> inode=38030531 dev=08:11 mode=0100644 ouid=0 ogid=0 rdev=00:00 objtype=NORMAL 
> cap_fp= cap_fi= cap_fe=0 cap_fver=0
> type=PATH msg=audit(1616095201.302:40381): item=1 name="/data/" inode=64 
> dev=08:11 mode=040755 ouid=0 ogid=0 rdev=00:00 objtype=PARENT 
> cap_fp= cap_fi= cap_fe=0 cap_fver=0
> type=PATH msg=audit(1616095201.302:40381): item=2 name="/data/test2.txt" 
> inode=38030531 dev=08:11 mode=0100644 ouid=0 ogid=0 rdev=00:00 objtype=DELETE 
> cap_fp= cap_fi= cap_fe=0 cap_fver=0
> type=PROCTITLE msg=audit(1616095201.302:40381): 
> proctitle=726D002D69002F646174612F74657374322E747874002D66
>
> The proctitle value  726D002D69002F646174612F74657374322E747874002D66 is 
> equal to "rm-i /data/test2.txt -f" in ASCII. Where did this -i come from? Is 
> it expected?

Perhaps a shell alias? What does `type rm` say?

-- 
Ondrej Mosnacek
Software Engineer, Linux Security - SELinux kernel
Red Hat, Inc.


--
Linux-audit mailing list
Linux-audit@redhat.com
https://listman.redhat.com/mailman/listinfo/linux-audit



Re: renameat2 syscall is not recorded

2021-03-10 Thread Ondrej Mosnacek
On Tue, Mar 9, 2021 at 7:44 PM Alan Evangelista  wrote:
> I have the following audit rule:
>
> -a exit,always -F dir=/data -F arch=b64 -S open -S unlink -S unlinkat -S link 
> -S rename
> -S renameat S renameat2 -S chmod

Not sure if this is it, but there is a "-" missing before the "S"
before "renameat2".

> -S fchmod -S fchmodat -S chown -S fchown -S fchownat -S mkdir -S rmdir -S 
> setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S 
> fremovexattr -k filesystem_op
>
> I straced the "mv" command to be sure it's implemented using the renameat2 
> syscall:
>
> # strace mv /data/test5.txt /data/test6.txt
> execve("/bin/mv", ["mv", "/data/test5.txt", "/data/test6.txt"], 
> 0x7ffdf760a210 /* 23 vars */) = 0
> (...)
> renameat2(AT_FDCWD, "/data/test5.txt", AT_FDCWD, "/data/test6.txt", 0) = 0
> (...)
>
> However, I don't see any events recorded in the auditd log file when I move 
> files using the "mv" command. Am I doing something wrong?
>
>
> Thanks in advance.
> --
> Linux-audit mailing list
> Linux-audit@redhat.com
> https://listman.redhat.com/mailman/listinfo/linux-audit

-- 
Ondrej Mosnacek
Software Engineer, Linux Security - SELinux kernel
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://listman.redhat.com/mailman/listinfo/linux-audit



Re: [PATCH 1/2] audit: show user land backtrace as part of audit context messages

2021-02-02 Thread Ondrej Mosnacek
On Tue, Feb 2, 2021 at 10:46 PM Paul Moore  wrote:
> On Tue, Feb 2, 2021 at 4:44 PM Daniel Walker (danielwa)
>  wrote:
> > On Tue, Feb 02, 2021 at 04:35:42PM -0500, Paul Moore wrote:
> > > On Tue, Feb 2, 2021 at 4:29 PM Daniel Walker  wrote:
> > > > From: Victor Kamensky 
> > > >
> > > > To efficiently find out where SELinux AVC denial is comming from
> > > > take backtrace of user land process and display it as type=UBACKTRACE
> > > > message that comes as audit context for SELinux AVC and other audit
> > > > messages ...
> > >
> > > Have you tried the new perf tracepoint for SELinux AVC decisions that
> > > trigger an audit event?  It's a new feature for v5.10 and looks to
> > > accomplish most of what you are looking for with this patch.
> > >
> > > * https://www.paul-moore.com/blog/d/2020/12/linux_v510.html
> >
> > We haven't tried it, but I can look into it. We're not using v5.10 
> > extensively
> > yet.
>
> Let us know if that works for you, and if it doesn't, let us know what
> might be missing.  I hate seeing the kernel grow multiple features
> which do the same thing.

I agree - I played around with this new tracepoint recently and you
can use it to achieve what you want quite easily:

# collect traces for denials (just interrupt/kill the sleep process
when done) - will create a perf.data file you can analyze later
perf record -a -e avc:selinux_audited -g --call-graph=dwarf sleep infinity
# dump all collected backtraces from the perf.data file
perf script

It's a bit complicated if you want to have it running in the
background permanently as a service (you need to tell perf to dump the
recorded data before you can read it), but perf already has some
command-line options to help with that use case.

--
Ondrej Mosnacek
Software Engineer, Linux Security - SELinux kernel
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit



Re: [PATCH v2] kernel: audit.c: Add __rcu notation to RCU pointer

2020-04-15 Thread Ondrej Mosnacek
On Wed, Apr 15, 2020 at 6:15 PM Richard Guy Briggs  wrote:
> On 2020-04-15 12:06, Paul Moore wrote:
> > On Wed, Apr 15, 2020 at 11:34 AM Richard Guy Briggs  wrote:
> > > On 2019-11-29 21:07, Joel Fernandes wrote:
> > > > On Thu, Nov 28, 2019 at 09:02:03PM +0530, Amol Grover wrote:
> > > > > add __rcu notation to RCU protected global pointer auditd_conn
> > > >
> > > > Again, please use proper punctuation and captilization. This is 
> > > > unacceptable.
> > > > Please put more effort into changelog.
> > > >
> > > > Otherwise the patch diff itself looks good to me, with the above nit
> > > > corrected, you could add my tag to the next revision:
> > > >
> > > > Reviewed-by: Joel Fernandes (Google) 
> > > >
> > > > thanks,
> > > >
> > > >  - Joel
> > > >
> > > > >
> > > > > Fixes multiple instances of sparse error:
> > > > > error: incompatible types in comparison expression
> > > > > (different address spaces)
> > >
> > > Amol or Joel: Is there a reproducer recipe for this?
> >
> > The commit which was merged has a slightly better description which may 
> > help.
>
> I've already seen this.  Perhaps I should have replied to this message
> instead to make that evident.  What really needed was Amol's original
> message sent to this list, but it was Joel who included this list in his
> reply (all 3 versions).
>
> I'm looking for the specific setup and commands that produced this error.

You can run make with "C=1", which will run sparse on all files that
are rebuilt during that make run. For example, if I fully build the
kernel and then revert commit
cb5172d96d16df72db8b55146b0ec00bfd97f079, I get:

$ make [...] C=1
[...]
  CHECK   [...]/kernel/audit.c
[...]/kernel/audit.c:218:14: error: incompatible types in comparison
expression (different address spaces):
[...]/kernel/audit.c:218:14:struct auditd_connection [noderef]  *
[...]/kernel/audit.c:218:14:struct auditd_connection *
(...and a lot more errors like this + 2 different warnings)

And when I un-revert it again, I get only the 2 warnings.

-- 
Ondrej Mosnacek 
Software Engineer, Security Technologies
Red Hat, Inc.


--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit



Re: [PATCH ghak57 V1] selinux: format all invalid context as untrusted

2019-06-14 Thread Ondrej Mosnacek
tps://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/selinux.git/commit/?h=stable-5.2=aff7ed4851680d0d28ad9f52cd2f99213e1371b2


> +   ab = audit_log_start(audit_context(),
> +GFP_ATOMIC,
> +AUDIT_SELINUX_ERR);
> +       audit_log_format(ab, 
> "op=security_sid_mls_copy invalid_context=");
> +   audit_log_n_untrustedstring(ab, s, 
> audit_size);
> +   audit_log_end(ab);
> kfree(s);
> }
> goto out_unlock;
> --
> 1.8.3.1
>

--
Ondrej Mosnacek 
Software Engineer, Security Technologies
Red Hat, Inc.


Re: [PATCH] selinux: log raw contexts as untrusted strings

2019-06-12 Thread Ondrej Mosnacek
On Wed, Jun 12, 2019 at 12:56 AM Paul Moore  wrote:
> On Tue, Jun 11, 2019 at 4:07 AM Ondrej Mosnacek  wrote:
> > These strings may come from untrusted sources (e.g. file xattrs) so they
> > need to be properly escaped.
> >
> > Reproducer:
> > # setenforce 0
> > # touch /tmp/test
> > # setfattr -n security.selinux -v 'kuřecí řízek' /tmp/test
> > # runcon system_u:system_r:sshd_t:s0 cat /tmp/test
> > (look at the generated AVCs)
> >
> > Actual result:
> > type=AVC [...] trawcon=kuřecí řízek
> >
> > Expected result:
> > type=AVC [...] trawcon=6B75C5996563C3AD20C599C3AD7A656B
> >
> > Fixes: fede148324c3 ("selinux: log invalid contexts in AVCs")
> > Cc: sta...@vger.kernel.org # v5.1+
> > Signed-off-by: Ondrej Mosnacek 
> > ---
> >  security/selinux/avc.c | 10 --
> >  1 file changed, 8 insertions(+), 2 deletions(-)
>
> Thanks, the patch looks fine to me, but it is borderline -stable
> material in my opinion.  I'll add it to the stable-5.2 branch, but in
> the future I would prefer if you left the stable marking off patches
> and sent a reply discussing *why* this should go to stable so we can
> discuss it.  I realize Greg likes to pull a lot of stuff into stable,
> but I try to be a bit more conservative about what gets marked.  Even
> the simplest fix can still break things :)

OK, I was a bit unsure whether to mark it as stable or not and
eventually inclined to do so... I'll try be more careful about it in
the future.

>
> I'm going to start building a test kernel now with this fix, but I
> might hold off on sending this up to Linus for a couple of days to see
> if I can catch Gen Zhang's patches in the same PR.
>
> > diff --git a/security/selinux/avc.c b/security/selinux/avc.c
> > index 8346a4f7c5d7..a99be508f93d 100644
> > --- a/security/selinux/avc.c
> > +++ b/security/selinux/avc.c
> > @@ -739,14 +739,20 @@ static void avc_audit_post_callback(struct 
> > audit_buffer *ab, void *a)
> > rc = security_sid_to_context_inval(sad->state, sad->ssid, ,
> >_len);
> > if (!rc && scontext) {
> > -   audit_log_format(ab, " srawcon=%s", scontext);
> > +   if (scontext_len && scontext[scontext_len - 1] == '\0')
> > +   scontext_len--;
> > +   audit_log_format(ab, " srawcon=");
> > +   audit_log_n_untrustedstring(ab, scontext, scontext_len);
> > kfree(scontext);
> > }
> >
> > rc = security_sid_to_context_inval(sad->state, sad->tsid, ,
> >_len);
> > if (!rc && scontext) {
> > -   audit_log_format(ab, " trawcon=%s", scontext);
> > +   if (scontext_len && scontext[scontext_len - 1] == '\0')
> > +   scontext_len--;
> > +   audit_log_format(ab, " trawcon=");
> > +   audit_log_n_untrustedstring(ab, scontext, scontext_len);
> > kfree(scontext);
> > }
> >  }
> > --
> > 2.20.1
>
> --
> paul moore
> www.paul-moore.com



-- 
Ondrej Mosnacek 
Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit

[PATCH] selinux: log raw contexts as untrusted strings

2019-06-11 Thread Ondrej Mosnacek
These strings may come from untrusted sources (e.g. file xattrs) so they
need to be properly escaped.

Reproducer:
# setenforce 0
# touch /tmp/test
# setfattr -n security.selinux -v 'kuřecí řízek' /tmp/test
# runcon system_u:system_r:sshd_t:s0 cat /tmp/test
(look at the generated AVCs)

Actual result:
type=AVC [...] trawcon=kuřecí řízek

Expected result:
type=AVC [...] trawcon=6B75C5996563C3AD20C599C3AD7A656B

Fixes: fede148324c3 ("selinux: log invalid contexts in AVCs")
Cc: sta...@vger.kernel.org # v5.1+
Signed-off-by: Ondrej Mosnacek 
---
 security/selinux/avc.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 8346a4f7c5d7..a99be508f93d 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -739,14 +739,20 @@ static void avc_audit_post_callback(struct audit_buffer 
*ab, void *a)
rc = security_sid_to_context_inval(sad->state, sad->ssid, ,
   _len);
if (!rc && scontext) {
-   audit_log_format(ab, " srawcon=%s", scontext);
+   if (scontext_len && scontext[scontext_len - 1] == '\0')
+   scontext_len--;
+   audit_log_format(ab, " srawcon=");
+   audit_log_n_untrustedstring(ab, scontext, scontext_len);
kfree(scontext);
}
 
rc = security_sid_to_context_inval(sad->state, sad->tsid, ,
   _len);
if (!rc && scontext) {
-   audit_log_format(ab, " trawcon=%s", scontext);
+   if (scontext_len && scontext[scontext_len - 1] == '\0')
+   scontext_len--;
+   audit_log_format(ab, " trawcon=");
+   audit_log_n_untrustedstring(ab, scontext, scontext_len);
kfree(scontext);
}
 }
-- 
2.20.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit

Re: [PATCH ghak90 V6 04/10] audit: log container info of syscalls

2019-05-30 Thread Ondrej Mosnacek
On Thu, May 30, 2019 at 12:16 AM Paul Moore  wrote:
> On Mon, Apr 8, 2019 at 11:40 PM Richard Guy Briggs  wrote:
> >
> > Create a new audit record AUDIT_CONTAINER_ID to document the audit
> > container identifier of a process if it is present.
> >
> > Called from audit_log_exit(), syscalls are covered.
> >
> > A sample raw event:
> > type=SYSCALL msg=audit(1519924845.499:257): arch=c03e syscall=257 
> > success=yes exit=3 a0=ff9c a1=56374e1cef30 a2=241 a3=1b6 items=2 
> > ppid=606 pid=635 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 
> > fsgid=0 tty=pts0 ses=3 comm="bash" exe="/usr/bin/bash" 
> > subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 
> > key="tmpcontainerid"
> > type=CWD msg=audit(1519924845.499:257): cwd="/root"
> > type=PATH msg=audit(1519924845.499:257): item=0 name="/tmp/" inode=13863 
> > dev=00:27 mode=041777 ouid=0 ogid=0 rdev=00:00 
> > obj=system_u:object_r:tmp_t:s0 nametype= PARENT cap_fp=0 cap_fi=0 cap_fe=0 
> > cap_fver=0
> > type=PATH msg=audit(1519924845.499:257): item=1 name="/tmp/tmpcontainerid" 
> > inode=17729 dev=00:27 mode=0100644 ouid=0 ogid=0 rdev=00:00 
> > obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=0 cap_fi=0 
> > cap_fe=0 cap_fver=0
> > type=PROCTITLE msg=audit(1519924845.499:257): 
> > proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964
> > type=CONTAINER_ID msg=audit(1519924845.499:257): contid=123458
> >
> > Please see the github audit kernel issue for the main feature:
> >   https://github.com/linux-audit/audit-kernel/issues/90
> > Please see the github audit userspace issue for supporting additions:
> >   https://github.com/linux-audit/audit-userspace/issues/51
> > Please see the github audit testsuiite issue for the test case:
> >   https://github.com/linux-audit/audit-testsuite/issues/64
> > Please see the github audit wiki for the feature overview:
> >   https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > Signed-off-by: Richard Guy Briggs 
> > Acked-by: Serge Hallyn 
> > Acked-by: Steve Grubb 
> > Acked-by: Neil Horman 
> > Reviewed-by: Ondrej Mosnacek 
> > ---
> >  include/linux/audit.h  |  5 +
> >  include/uapi/linux/audit.h |  1 +
> >  kernel/audit.c | 20 
> >  kernel/auditsc.c   | 20 ++--
> >  4 files changed, 40 insertions(+), 6 deletions(-)
>
> ...
>
> > diff --git a/kernel/audit.c b/kernel/audit.c
> > index 182b0f2c183d..3e0af53f3c4d 100644
> > --- a/kernel/audit.c
> > +++ b/kernel/audit.c
> > @@ -2127,6 +2127,26 @@ void audit_log_session_info(struct audit_buffer *ab)
> > audit_log_format(ab, "auid=%u ses=%u", auid, sessionid);
> >  }
> >
> > +/*
> > + * audit_log_contid - report container info
> > + * @context: task or local context for record
> > + * @contid: container ID to report
> > + */
> > +void audit_log_contid(struct audit_context *context, u64 contid)
> > +{
> > +   struct audit_buffer *ab;
> > +
> > +   if (!audit_contid_valid(contid))
> > +   return;
> > +   /* Generate AUDIT_CONTAINER_ID record with container ID */
> > +   ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER_ID);
> > +   if (!ab)
> > +   return;
> > +   audit_log_format(ab, "contid=%llu", (unsigned long long)contid);
>
> We have a consistency problem regarding how to output the u64 contid
> values; this function uses an explicit cast, others do not.  According
> to Documentation/core-api/printk-formats.rst the recommendation for
> u64 is %llu (or %llx, if you want hex).  Looking quickly through the
> printk code this appears to still be correct.  I suggest we get rid of
> the cast (like it was in v5).

IIRC it was me who suggested to add the casts. I didn't realize that
the kernel actually guarantees that "%llu" will always work with u64.
Taking that into account I rescind my request to add the cast. Sorry
for the false alarm.

>
> > +   audit_log_end(ab);
> > +}
> > +EXPORT_SYMBOL(audit_log_contid);
>
> --
> paul moore
> www.paul-moore.com

--
Ondrej Mosnacek 
Software Engineer, Security Technologies
Red Hat, Inc.


Re: [RFC PATCH ghak73 V1] audit: re-structure audit field valid checks

2019-05-07 Thread Ondrej Mosnacek
On Mon, May 6, 2019 at 4:48 PM Richard Guy Briggs  wrote:
> Multiple checks were being done in one switch case statement that
> started to cause some redundancies and awkward exceptions.  Separate the
> valid field and op check from the select valid values checks.
>
> Enforce the elimination of meaningless bitwise and greater/lessthan
> checks on string fields and other fields with unrelated scalar values.
>
> Please see the github issue
> https://github.com/linux-audit/audit-kernel/issues/73
>
> Signed-off-by: Richard Guy Briggs 
> ---
> Passes audit-testsuite on f30.
> Note: This does not necessarily completely resolve ghak73, but enables
> ghak64.
>
>  kernel/auditfilter.c | 42 +++---
>  1 file changed, 27 insertions(+), 15 deletions(-)
>
> diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
> index 1bc6410413e6..17cfccd9ee27 100644
> --- a/kernel/auditfilter.c
> +++ b/kernel/auditfilter.c
> @@ -358,9 +358,16 @@ static int audit_field_valid(struct audit_entry *entry, 
> struct audit_field *f)
> }
> }
>
> +   /* Check for valid field type and op */
> switch(f->type) {
> -   default:
> -   return -EINVAL;
> +   case AUDIT_ARG0:
> +   case AUDIT_ARG1:
> +   case AUDIT_ARG2:
> +   case AUDIT_ARG3:
> +   case AUDIT_PERS: /*  */
> +   case AUDIT_DEVMINOR:
> +   /* all ops are valid */
> +   break;
> case AUDIT_UID:
> case AUDIT_EUID:
> case AUDIT_SUID:
> @@ -373,11 +380,9 @@ static int audit_field_valid(struct audit_entry *entry, 
> struct audit_field *f)
> case AUDIT_FSGID:
> case AUDIT_OBJ_GID:
> case AUDIT_PID:
> -   case AUDIT_PERS:
> case AUDIT_MSGTYPE:
> case AUDIT_PPID:
> case AUDIT_DEVMAJOR:
> -   case AUDIT_DEVMINOR:

The fact that AUDIT_DEVMAJOR and AUDIT_DEVMINOR support different set
of operators irks me a bit, but I understand the motivation (minor
numbers are allocated in a more "ordered" fashion than major numbers),
so I'm neutral about it.

> case AUDIT_EXIT:
> case AUDIT_SUCCESS:
> case AUDIT_INODE:
> @@ -386,10 +391,6 @@ static int audit_field_valid(struct audit_entry *entry, 
> struct audit_field *f)
> if (f->op == Audit_bitmask || f->op == Audit_bittest)
> return -EINVAL;
> break;
> -   case AUDIT_ARG0:
> -   case AUDIT_ARG1:
> -   case AUDIT_ARG2:
> -   case AUDIT_ARG3:
> case AUDIT_SUBJ_USER:
> case AUDIT_SUBJ_ROLE:
> case AUDIT_SUBJ_TYPE:
> @@ -403,16 +404,28 @@ static int audit_field_valid(struct audit_entry *entry, 
> struct audit_field *f)
> case AUDIT_WATCH:
> case AUDIT_DIR:
> case AUDIT_FILTERKEY:
> -   break;
> case AUDIT_LOGINUID_SET:
> -   if ((f->val != 0) && (f->val != 1))
> -   return -EINVAL;
> -   /* FALL THROUGH */
> case AUDIT_ARCH:
> case AUDIT_FSTYPE:
> +   case AUDIT_PERM:
> +   case AUDIT_FILETYPE:

Looking at [1], it seems that f->op is actually ignored for AUDIT_PERM
and AUDIT_FILETYPE... This is probably out of scope for this patch,
but maybe AUDIT_PERM should be fixed to properly support bitmask
operators (and the allowed ops should be only bitmask, bittest, equal,
and not_equal) and AUDIT_FILETYPE to distinguish between the equal and
not_equal operator. (Maybe you have already filed an issue for this,
I'm losing track of all the ghaks :)

Other than that the patch looks good to me.

[1] https://elixir.bootlin.com/linux/v5.1/source/kernel/auditsc.c#L685

> +   case AUDIT_FIELD_COMPARE:
> +   case AUDIT_EXE:
> +   /* only equal and not equal valid ops */
> if (f->op != Audit_not_equal && f->op != Audit_equal)
> return -EINVAL;
> break;
> +   default:
> +   /* field not recognized */
> +   return -EINVAL;
> +   }
> +
> +   /* Check for select valid field values */
> +   switch(f->type) {
> +   case AUDIT_LOGINUID_SET:
> +   if ((f->val != 0) && (f->val != 1))
> +   return -EINVAL;
> +   break;
> case AUDIT_PERM:
> if (f->val & ~15)
> return -EINVAL;
> @@ -425,11 +438,10 @@ static int audit_field_valid(struct audit_entry *entry, 
> struct audit_field *f)
> if (f->val > AUDIT_MAX_FIELD_COMPARE)
>   

[PATCH ghak10 v8 2/2] ntp: Audit NTP parameters adjustment

2019-04-10 Thread Ondrej Mosnacek
Emit an audit record every time selected NTP parameters are modified
from userspace (via adjtimex(2) or clock_adjtime(2)). These parameters
may be used to indirectly change system clock, and thus their
modifications should be audited.

Such events will now generate records of type AUDIT_TIME_ADJNTPVAL
containing the following fields:
  - op -- which value was adjusted:
- offset -- corresponding to the time_offset variable
- freq   -- corresponding to the time_freq variable
- status -- corresponding to the time_status variable
- adjust -- corresponding to the time_adjust variable
- tick   -- corresponding to the tick_usec variable
- tai-- corresponding to the timekeeping's TAI offset
  - old -- the old value
  - new -- the new value

Example records:

type=TIME_ADJNTPVAL msg=audit(1530616044.507:7): op=status old=64 new=8256
type=TIME_ADJNTPVAL msg=audit(1530616044.511:11): op=freq old=0 
new=49180377088000

The records of this type will be associated with the corresponding
syscall records.

An overview of parameter changes that can be done via do_adjtimex()
(based on information from Miroslav Lichvar) and whether they are
audited:
  __timekeeping_set_tai_offset() -- sets the offset from the
International Atomic Time
(AUDITED)
  NTP variables:
time_offset -- can adjust the clock by up to 0.5 seconds per call
   and also speed it up or slow down by up to about
   0.05% (43 seconds per day) (AUDITED)
time_freq -- can speed up or slow down by up to about 0.05%
 (AUDITED)
time_status -- can insert/delete leap seconds and it also enables/
   disables synchronization of the hardware real-time
   clock (AUDITED)
time_maxerror, time_esterror -- change error estimates used to
inform userspace applications
(NOT AUDITED)
time_constant -- controls the speed of the clock adjustments that
 are made when time_offset is set (NOT AUDITED)
time_adjust -- can temporarily speed up or slow down the clock by up
   to 0.05% (AUDITED)
tick_usec -- a more extreme version of time_freq; can speed up or
 slow down the clock by up to 10% (AUDITED)

Signed-off-by: Ondrej Mosnacek 
Reviewed-by: Richard Guy Briggs 
Reviewed-by: Thomas Gleixner 
---
 include/linux/audit.h  | 61 ++
 include/uapi/linux/audit.h |  1 +
 kernel/auditsc.c   | 22 ++
 kernel/time/ntp.c  | 22 --
 kernel/time/ntp_internal.h |  4 ++-
 kernel/time/timekeeping.c  |  7 -
 6 files changed, 112 insertions(+), 5 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 2c62c046..43a23e28ba23 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -86,6 +86,29 @@ struct audit_field {
u32 op;
 };
 
+enum audit_ntp_type {
+   AUDIT_NTP_OFFSET,
+   AUDIT_NTP_FREQ,
+   AUDIT_NTP_STATUS,
+   AUDIT_NTP_TAI,
+   AUDIT_NTP_TICK,
+   AUDIT_NTP_ADJUST,
+
+   AUDIT_NTP_NVALS /* count */
+};
+
+#ifdef CONFIG_AUDITSYSCALL
+struct audit_ntp_val {
+   long long oldval, newval;
+};
+
+struct audit_ntp_data {
+   struct audit_ntp_val vals[AUDIT_NTP_NVALS];
+};
+#else
+struct audit_ntp_data {};
+#endif
+
 extern int is_audit_feature_set(int which);
 
 extern int __init audit_register_class(int class, unsigned *list);
@@ -366,6 +389,7 @@ extern void __audit_mmap_fd(int fd, int flags);
 extern void __audit_log_kern_module(char *name);
 extern void __audit_fanotify(unsigned int response);
 extern void __audit_tk_injoffset(struct timespec64 offset);
+extern void __audit_ntp_log(const struct audit_ntp_data *ad);
 
 static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
 {
@@ -478,6 +502,29 @@ static inline void audit_tk_injoffset(struct timespec64 
offset)
__audit_tk_injoffset(offset);
 }
 
+static inline void audit_ntp_init(struct audit_ntp_data *ad)
+{
+   memset(ad, 0, sizeof(*ad));
+}
+
+static inline void audit_ntp_set_old(struct audit_ntp_data *ad,
+enum audit_ntp_type type, long long val)
+{
+   ad->vals[type].oldval = val;
+}
+
+static inline void audit_ntp_set_new(struct audit_ntp_data *ad,
+enum audit_ntp_type type, long long val)
+{
+   ad->vals[type].newval = val;
+}
+
+static inline void audit_ntp_log(const struct audit_ntp_data *ad)
+{
+   if (!audit_dummy_context())
+   __audit_ntp_log(ad);
+}
+
 extern int audit_n_rules;
 extern int audit_signals;
 #else /* CONFIG_AUDITSYSCALL */
@@ -594,6 +641,20 @@ static inline void audit_fanotify(unsigned int response)
 static inline void audit_tk_injoffset(struct timespec64 offset)
 { }
 
+static inlin

[PATCH ghak10 v8 1/2] timekeeping: Audit clock adjustments

2019-04-10 Thread Ondrej Mosnacek
Emit an audit record whenever the system clock is changed (i.e. shifted
by a non-zero offset) by a syscall from userspace. The syscalls than can
(at the time of writing) trigger such record are:
  - settimeofday(2), stime(2), clock_settime(2) -- via
do_settimeofday64()
  - adjtimex(2), clock_adjtime(2) -- via do_adjtimex()

The new records have type AUDIT_TIME_INJOFFSET and contain the following
fields:
  - sec -- the 'seconds' part of the offset
  - nsec -- the 'nanoseconds' part of the offset

Example record (time was shifted backwards by ~15.875 seconds):

type=TIME_INJOFFSET msg=audit(1530616049.652:13): sec=-16 nsec=124887145

The records of this type will be associated with the corresponding
syscall records.

Signed-off-by: Ondrej Mosnacek 
Reviewed-by: Richard Guy Briggs 
Reviewed-by: Thomas Gleixner 
---
 include/linux/audit.h  | 14 ++
 include/uapi/linux/audit.h |  1 +
 kernel/auditsc.c   |  6 ++
 kernel/time/timekeeping.c  |  6 ++
 4 files changed, 27 insertions(+)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 1e69d9fe16da..2c62c046 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -365,6 +365,7 @@ extern void __audit_log_capset(const struct cred *new, 
const struct cred *old);
 extern void __audit_mmap_fd(int fd, int flags);
 extern void __audit_log_kern_module(char *name);
 extern void __audit_fanotify(unsigned int response);
+extern void __audit_tk_injoffset(struct timespec64 offset);
 
 static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
 {
@@ -467,6 +468,16 @@ static inline void audit_fanotify(unsigned int response)
__audit_fanotify(response);
 }
 
+static inline void audit_tk_injoffset(struct timespec64 offset)
+{
+   /* ignore no-op events */
+   if (offset.tv_sec == 0 && offset.tv_nsec == 0)
+   return;
+
+   if (!audit_dummy_context())
+   __audit_tk_injoffset(offset);
+}
+
 extern int audit_n_rules;
 extern int audit_signals;
 #else /* CONFIG_AUDITSYSCALL */
@@ -580,6 +591,9 @@ static inline void audit_log_kern_module(char *name)
 static inline void audit_fanotify(unsigned int response)
 { }
 
+static inline void audit_tk_injoffset(struct timespec64 offset)
+{ }
+
 static inline void audit_ptrace(struct task_struct *t)
 { }
 #define audit_n_rules 0
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 3901c51c0b93..ab58d67baf4d 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -114,6 +114,7 @@
 #define AUDIT_REPLACE  1329/* Replace auditd if this packet 
unanswerd */
 #define AUDIT_KERN_MODULE  1330/* Kernel Module events */
 #define AUDIT_FANOTIFY 1331/* Fanotify access decision */
+#define AUDIT_TIME_INJOFFSET   1332/* Timekeeping offset injected */
 
 #define AUDIT_AVC  1400/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR  1401/* Internal SE Linux Errors */
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 51a2ceb3a1ca..80dfe0cdc636 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2512,6 +2512,12 @@ void __audit_fanotify(unsigned int response)
AUDIT_FANOTIFY, "resp=%u", response);
 }
 
+void __audit_tk_injoffset(struct timespec64 offset)
+{
+   audit_log(audit_context(), GFP_KERNEL, AUDIT_TIME_INJOFFSET,
+ "sec=%lli nsec=%li", (long long)offset.tv_sec, 
offset.tv_nsec);
+}
+
 static void audit_log_task(struct audit_buffer *ab)
 {
kuid_t auid, uid;
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index f986e1918d12..3d24be4cd607 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "tick-internal.h"
 #include "ntp_internal.h"
@@ -1250,6 +1251,9 @@ out:
/* signal hrtimers about time change */
clock_was_set();
 
+   if (!ret)
+   audit_tk_injoffset(ts_delta);
+
return ret;
 }
 EXPORT_SYMBOL(do_settimeofday64);
@@ -2322,6 +2326,8 @@ int do_adjtimex(struct __kernel_timex *txc)
ret = timekeeping_inject_offset();
if (ret)
return ret;
+
+   audit_tk_injoffset(delta);
}
 
ktime_get_real_ts64();
-- 
2.20.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


[PATCH ghak10 v8 0/2] audit: Log changes that can affect the system clock

2019-04-10 Thread Ondrej Mosnacek
This patchset implements auditing of (syscall-triggered) changes that
can modify or indirectly affect the system clock. Some of these
changes can already be detected by simply logging relevant syscalls,
but this has some disadvantages:
  a) It is usually not possible to find out from the syscall records
 the amount by which the time was shifted.
  b) Syscalls like adjtimex(2) or clock_adjtime(2) can be used also
 for read-only operations, which might flood the audit log with
 false positives. (Note that these patches don't solve this
 problem yet due to the limitations of current record filtering
 capabilities.)

The main motivation is to provide better reliability of timestamps
on the system as mandated by the FPT_STM.1 security functional
requirement from Common Criteria. This requirement apparently demands
that it is possible to reconstruct from audit trail the old and new
values of the time when it is adjusted (see [1]).

The current version of the patchset logs the following changes:
  - direct setting of system time to a given value
  - direct injection of timekeeping offset
  - adjustment of timekeeping's TAI offset
  - NTP value adjustments (may affect system time indirectly):
- time_offset
- time_freq
- time_status
- time_adjust
- tick_usec

Changes to the following NTP values are not logged, as they are not
important for security:
  - time_maxerror
  - time_esterror
  - time_constant

Audit kernel GitHub issue: https://github.com/linux-audit/audit-kernel/issues/10
Audit kernel RFE page: 
https://github.com/linux-audit/audit-kernel/wiki/RFE-More-detailed-auditing-of-changes-to-system-clock

Audit userspace PR: https://github.com/linux-audit/audit-userspace/pull/89
Audit testsuite PR: https://github.com/linux-audit/audit-testsuite/pull/82

Testing: Passed audit-testuite (including new functional test from PR#82)

Changes in v8:
  - Switched AUDIT_NTP_* macros to an enum
  - Fixed mistakes in commit messages
  - Added missing s64 -> long long conversion (forgot to commit it in v7)

v7: https://www.redhat.com/archives/linux-audit/2019-April/msg00044.html
Changes in v7:
  - Removed #include  from audit.h, since it is not
needed
  - Moved audit_log() calls out of locked sections and switched audit
allocations to GFP_KERNEL
  - Rebased onto latest audit/next
  - Switched the general NTP value type to long long (was s64),
which corresponds better with the actual timex field types
  - Simplified commit log messages

v6: https://www.redhat.com/archives/linux-audit/2019-March/msg00016.html
Changes in v6:
  - Reorganized the patches to group changes by record type, not
kernel subsytem, as suggested in earlier discussions
  - Added checks to ignore no-change events (new value == old value)
  - Added TIME_INJOFFSET logging also to do_settimeofday64() to cover
syscalls such as settimeofday(2), stime(2), clock_settime(2)
  - Created an RFE page on audit-kernel GitHub

v5: https://www.redhat.com/archives/linux-audit/2018-August/msg00039.html
Changes in v5:
  - Dropped logging of some less important changes and update commit messages
  - No longer mark the patchset as RFC

v4: https://www.redhat.com/archives/linux-audit/2018-August/msg00023.html
Changes in v4:
  - Squashed first two patches into one
  - Renamed ADJNTPVAL's "type" field to "op" to align with audit record
conventions
  - Minor commit message editing
  - Cc timekeeping/NTP people for feedback

v3: https://www.redhat.com/archives/linux-audit/2018-July/msg1.html
Changes in v3:
  - Switched to separate records for each variable
  - Both old and new value is now reported for each change
  - Injecting offset is reported via a separate record (since this
offset consists of two values and is added directly to the clock,
i.e. it doesn't make sense to log old and new value)
  - Added example records produced by chronyd -q (see the commit message
of the last patch)

v2: https://www.redhat.com/archives/linux-audit/2018-June/msg00114.html
Changes in v2:
  - The audit_adjtime() function has been modified to only log those
fields that contain values that are actually used, resulting in more
compact records.
  - The audit_adjtime() call has been moved to do_adjtimex() in
timekeeping.c
  - Added an additional patch (for review) that simplifies the detection
if the syscall is read-only.

v1: https://www.redhat.com/archives/linux-audit/2018-June/msg00095.html

[1] https://www.niap-ccevs.org/MMO/PP/pp_ca_v2.1.pdf -- section 5.1,
table 4

Ondrej Mosnacek (2):
  timekeeping: Audit clock adjustments
  ntp: Audit NTP parameters adjustment

 include/linux/audit.h  | 75 ++
 include/uapi/linux/audit.h |  2 +
 kernel/auditsc.c   | 28 ++
 kernel/time/ntp.c  | 22 +--
 kernel/time/ntp_internal.h |  4 +-
 kernel/time/timekeeping.c  | 13 ++-
 6 files changed, 139 insertions(+), 5 d

Re: [PATCH ghak10 v7 2/2] ntp: Audit NTP parameters adjustment

2019-04-10 Thread Ondrej Mosnacek
On Wed, Apr 10, 2019 at 9:03 AM Thomas Gleixner  wrote:
> On Tue, 9 Apr 2019, Ondrej Mosnacek wrote:
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index 2c62c046..1c372ad7ebe9 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -86,6 +86,26 @@ struct audit_field {
> >   u32 op;
> >  };
> >
> > +#define AUDIT_NTP_OFFSET 0
> > +#define AUDIT_NTP_FREQ   1
> > +#define AUDIT_NTP_STATUS 2
> > +#define AUDIT_NTP_TAI3
> > +#define AUDIT_NTP_TICK   4
> > +#define AUDIT_NTP_ADJUST 5
> > +#define AUDIT_NTP_NVALS  6 /* count */
>
> That should be an named enum and the id argument should be the same type.

I kind of instinctively went for macros to be consistent with the rest
of the file, but on second thought that's really not a good reason to
keep doing the wrong thing... I'll change it to enum in v8.

>
> > @@ -720,14 +721,29 @@ int __do_adjtimex(struct __kernel_timex *txc, const 
> > struct timespec64 *ts,
> >   /* adjtime() is independent from ntp_adjtime() */
> >   time_adjust = txc->offset;
> >   ntp_update_frequency();
> > +
> > + audit_ntp_set_old(ad, AUDIT_NTP_ADJUST, save_adjust);
> > + audit_ntp_set_new(ad, AUDIT_NTP_ADJUST, time_adjust);
> >   }
> >   txc->offset = save_adjust;
> >   } else {
> > -
> >   /* If there are input parameters, then process them: */
> > - if (txc->modes)
> > + if (txc->modes) {
> > + audit_ntp_set_old(ad, AUDIT_NTP_OFFSET, time_offset);
> > + audit_ntp_set_old(ad, AUDIT_NTP_FREQ,   time_freq);
> > + audit_ntp_set_old(ad, AUDIT_NTP_STATUS, time_status);
> > + audit_ntp_set_old(ad, AUDIT_NTP_TAI,*time_tai);
> > + audit_ntp_set_old(ad, AUDIT_NTP_TICK,   tick_usec);
> > +
> >   process_adjtimex_modes(txc, time_tai);
> >
> > + audit_ntp_set_new(ad, AUDIT_NTP_OFFSET, time_offset);
> > + audit_ntp_set_new(ad, AUDIT_NTP_FREQ,   time_freq);
> > + audit_ntp_set_new(ad, AUDIT_NTP_STATUS, time_status);
> > + audit_ntp_set_new(ad, AUDIT_NTP_TAI,*time_tai);
> > + audit_ntp_set_new(ad, AUDIT_NTP_TICK,   tick_usec);
> > + }
>
> Yes, that looks much more palatable! Nice work!
>
> With the above addressed:
>
> Reviewed-by: Thomas Gleixner 
>
>

Thanks!

-- 
Ondrej Mosnacek 
Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [PATCH ghak10 v7 2/2] ntp: Audit NTP parameters adjustment

2019-04-09 Thread Ondrej Mosnacek
On Tue, Apr 9, 2019 at 4:40 PM Richard Guy Briggs  wrote:
> On 2019-04-09 14:31, Ondrej Mosnacek wrote:
> > Emit an audit record every time selected NTP parameters are modified
> > from userspace (via adjtimex(2) or clock_adjtime(2)). These parameters
> > may be used to indirectly change system clock, and thus their
> > modifications should be audited.
> >
> > Such events will now generate records of type AUDIT_TIME_ADJNTPVAL
> > containing the following fields:
> >   - op -- which value was adjusted:
> > - offset -- corresponding to the time_offset variable
> > - freq   -- corresponding to the time_freq variable
> > - status -- corresponding to the time_status variable
> > - adjust -- corresponding to the time_adjust variable
> > - tick   -- corresponding to the tick_usec variable
> > - tai-- corresponding to the timekeeping's TAI offset
> >   - old -- the old value
> >   - new -- the new value
> >
> > Example records:
> >
> > type=TIME_ADJNTPVAL msg=audit(1530616044.507:7): op=status old=64 new=8256
> > type=TIME_ADJNTPVAL msg=audit(1530616044.511:11): op=freq old=0 
> > new=49180377088000
> >
> > The records of this type will be associated with the corresponding
> > syscall records.
> >
> > An overview of parameter changes that can be done via do_adjtimex()
> > (based on information from Miroslav Lichvar) and whether they are
> > audited:
> >   __timekeeping_set_tai_offset() -- sets the offset from the
> > International Atomic Time
> > (AUDITED)
> >   NTP variables:
> > time_offset -- can adjust the clock by up to 0.5 seconds per call
> >and also speed it up or slow down by up to about
> >0.05% (43 seconds per day) (AUDITED)
> > time_freq -- can speed up or slow down by up to about 0.05%
>
> (I think you want an "(AUDITED)" at the end of the "time_freq" line.)

Argh, yeah... Paul, would you be OK with fixing up these nits manually
or should I rather send an updated v8 (if there are no change requests
from the timekeeping folks)?

>
> > time_status -- can insert/delete leap seconds and it also enables/
> >disables synchronization of the hardware real-time
> >clock (AUDITED)
> > time_maxerror, time_esterror -- change error estimates used to
> > inform userspace applications
> > (NOT AUDITED)
> > time_constant -- controls the speed of the clock adjustments that
> >  are made when time_offset is set (NOT AUDITED)
> > time_adjust -- can temporarily speed up or slow down the clock by up
> >to 0.05% (AUDITED)
> > tick_usec -- a more extreme version of time_freq; can speed up or
> >  slow down the clock by up to 10% (AUDITED)
> >
> > Signed-off-by: Ondrej Mosnacek 
>
> Reviewed-by: Richard Guy Briggs 
>
> > ---
> >  include/linux/audit.h  | 54 ++
> >  include/uapi/linux/audit.h |  1 +
> >  kernel/auditsc.c   | 23 
> >  kernel/time/ntp.c  | 22 +---
> >  kernel/time/ntp_internal.h |  4 ++-
> >  kernel/time/timekeeping.c  |  7 -
> >  6 files changed, 106 insertions(+), 5 deletions(-)
> >
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index 2c62c046..1c372ad7ebe9 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -86,6 +86,26 @@ struct audit_field {
> >   u32 op;
> >  };
> >
> > +#define AUDIT_NTP_OFFSET 0
> > +#define AUDIT_NTP_FREQ   1
> > +#define AUDIT_NTP_STATUS 2
> > +#define AUDIT_NTP_TAI3
> > +#define AUDIT_NTP_TICK   4
> > +#define AUDIT_NTP_ADJUST 5
> > +#define AUDIT_NTP_NVALS  6 /* count */
> > +
> > +#ifdef CONFIG_AUDITSYSCALL
> > +struct audit_ntp_val {
> > + s64 oldval, newval;
> > +};
> > +
> > +struct audit_ntp_data {
> > + struct audit_ntp_val vals[AUDIT_NTP_NVALS];
> > +};
> > +#else
> > +struct audit_ntp_data {};
> > +#endif
> > +
> >  extern int is_audit_feature_set(int which);
> >
> >  extern int __init audit_register_class(int class, unsigned *list);
> > @@ -366,6 +386,7 @@ extern void __audit_mmap_fd(int fd, int flags);
> >  exter

Re: [PATCH ghak10 v7 1/2] timekeeping: Audit clock adjustments

2019-04-09 Thread Ondrej Mosnacek
On Tue, Apr 9, 2019 at 4:26 PM Richard Guy Briggs  wrote:
> On 2019-04-09 14:31, Ondrej Mosnacek wrote:
> > Emit an audit record whenever the system clock is changed (i.e. shifted
> > by a non-zero offset) by a syscall from userspace. The syscalls than can
> > (at the time of writing) trigger such record are:
> >   - settimeofday(2), stime(2), clock_settime(2) -- via
> > do_settimeofday64()
> >   - adjtimex(2), clock_adjtime(2) -- via do_adjtimex()
> >
> > The new records have type AUDIT_TIME_INJOFFSET and contain the following
> > fields:
> >   - sec -- the 'seconds' part of the offset
> >   - nsec -- the 'nanoseconds' part of the offset
> >
> > Example record (time was shifted backwards by ~16.125 seconds):
> >
> > type=TIME_INJOFFSET msg=audit(1530616049.652:13): sec=-16 nsec=124887145
>
> I have a minor nit about the interpretation of these values.  I realize
> the values printed are the ones that are supplied.  When the sec
> value is negative, does that imply that the nsec value has the same
> sign?  IOW, are the two values added with a multiplier to the nsec
> value, or are they concatenated with a decimal in the middle?  I expect
> the latter.  In the current userspace support, there is no explicit type
> support included yet for interpreted fields.  This is just a minor
> documentation issue to me.

Good point! I wrote the sentence too quickly without thinking about
it... I actually had to find this out for the tests (and looking at it
again, I got it wrong there as well, although in a different way...) -
it is actually the former variant (multiplier + addition). So the
"~16.125" should actually be "~15.875" (and I need to fix the
testsuite pull request...).

> > The records of this type will be associated with the corresponding
> > syscall records.
> >
> > Signed-off-by: Ondrej Mosnacek 
>
> Reviewed-by: Richard Guy Briggs 
>
> > ---
> >  include/linux/audit.h  | 14 ++
> >  include/uapi/linux/audit.h |  1 +
> >  kernel/auditsc.c   |  6 ++
> >  kernel/time/timekeeping.c  |  6 ++
> >  4 files changed, 27 insertions(+)
> >
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index 1e69d9fe16da..2c62c046 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -365,6 +365,7 @@ extern void __audit_log_capset(const struct cred *new, 
> > const struct cred *old);
> >  extern void __audit_mmap_fd(int fd, int flags);
> >  extern void __audit_log_kern_module(char *name);
> >  extern void __audit_fanotify(unsigned int response);
> > +extern void __audit_tk_injoffset(struct timespec64 offset);
> >
> >  static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
> >  {
> > @@ -467,6 +468,16 @@ static inline void audit_fanotify(unsigned int 
> > response)
> >   __audit_fanotify(response);
> >  }
> >
> > +static inline void audit_tk_injoffset(struct timespec64 offset)
> > +{
> > + /* ignore no-op events */
> > + if (offset.tv_sec == 0 && offset.tv_nsec == 0)
> > + return;
> > +
> > + if (!audit_dummy_context())
> > + __audit_tk_injoffset(offset);
> > +}
> > +
> >  extern int audit_n_rules;
> >  extern int audit_signals;
> >  #else /* CONFIG_AUDITSYSCALL */
> > @@ -580,6 +591,9 @@ static inline void audit_log_kern_module(char *name)
> >  static inline void audit_fanotify(unsigned int response)
> >  { }
> >
> > +static inline void audit_tk_injoffset(struct timespec64 offset)
> > +{ }
> > +
> >  static inline void audit_ptrace(struct task_struct *t)
> >  { }
> >  #define audit_n_rules 0
> > diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> > index 3901c51c0b93..ab58d67baf4d 100644
> > --- a/include/uapi/linux/audit.h
> > +++ b/include/uapi/linux/audit.h
> > @@ -114,6 +114,7 @@
> >  #define AUDIT_REPLACE1329/* Replace auditd if this 
> > packet unanswerd */
> >  #define AUDIT_KERN_MODULE1330/* Kernel Module events */
> >  #define AUDIT_FANOTIFY   1331/* Fanotify access decision */
> > +#define AUDIT_TIME_INJOFFSET 1332/* Timekeeping offset injected */
> >
> >  #define AUDIT_AVC1400/* SE Linux avc denial or grant */
> >  #define AUDIT_SELINUX_ERR1401/* Internal SE Linux Errors */
> > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > index 51a2ceb3a1ca..80dfe0cdc636 100644
> > --- a/kernel/auditsc.c
> > +++ b/kernel/auditsc.c
> > @

Re: [PATCH ghak90 V6 05/10] audit: add contid support for signalling the audit daemon

2019-04-09 Thread Ondrej Mosnacek
On Tue, Apr 9, 2019 at 3:49 PM Neil Horman  wrote:
> On Tue, Apr 09, 2019 at 09:40:58AM -0400, Paul Moore wrote:
> > On Tue, Apr 9, 2019 at 8:58 AM Ondrej Mosnacek  wrote:
> > >
> > > On Tue, Apr 9, 2019 at 5:40 AM Richard Guy Briggs  wrote:
> > > > Add audit container identifier support to the action of signalling the
> > > > audit daemon.
> > > >
> > > > Since this would need to add an element to the audit_sig_info struct,
> > > > a new record type AUDIT_SIGNAL_INFO2 was created with a new
> > > > audit_sig_info2 struct.  Corresponding support is required in the
> > > > userspace code to reflect the new record request and reply type.
> > > > An older userspace won't break since it won't know to request this
> > > > record type.
> > > >
> > > > Signed-off-by: Richard Guy Briggs 
> > >
> > > This looks good to me.
> > >
> > > Reviewed-by: Ondrej Mosnacek 
> > >
> > > Although I'm wondering if we shouldn't try to future-proof the
> > > AUDIT_SIGNAL_INFO2 format somehow, so that we don't need to add
> > > another AUDIT_SIGNAL_INFO3 when the need arises to add yet-another
> > > identifier to it... The simplest solution I can come up with is to add
> > > a "version" field at the beginning (set to 2 initially), then v_len
> > > at the beginning of data for version . But maybe this is too
> > > complicated for too little gain...
> >
> > FWIW, I believe the long term solution to this is the fabled netlink
> > attribute approach that we haven't talked about in some time, but I
> > keep dreaming about (it has been mostly on the back burner becasue 1)
> > time and 2) didn't want to impact the audit container ID work).  While
> > I'm not opposed to trying to make things like this a bit more robust
> > by adding version fields and similar things, there are still so many
> > (so very many) problems with the audit kernel/userspace interface that
> > still need to be addressed.
> >
>
> Agreed, this change as-is is in keeping with the message structure that audit
> has today, and so is ok with me, but the long term goal should be a conversion
> to netlink attributes for all audit messages.  Thats a big undertaking and
> should be addressed separately though.

Yeah, you both have a good point that doing it now and only for this
message is not necessarily better than not doing it at all. And doing
a general overhaul is out of scope for this series, obviously. I
didn't really mind the current solution before and I mind it even less
now, so consider me satisfied :) I was really just thinking out
loud...

-- 
Ondrej Mosnacek 
Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [PATCH ghak90 V6 05/10] audit: add contid support for signalling the audit daemon

2019-04-09 Thread Ondrej Mosnacek
On Tue, Apr 9, 2019 at 5:40 AM Richard Guy Briggs  wrote:
> Add audit container identifier support to the action of signalling the
> audit daemon.
>
> Since this would need to add an element to the audit_sig_info struct,
> a new record type AUDIT_SIGNAL_INFO2 was created with a new
> audit_sig_info2 struct.  Corresponding support is required in the
> userspace code to reflect the new record request and reply type.
> An older userspace won't break since it won't know to request this
> record type.
>
> Signed-off-by: Richard Guy Briggs 

This looks good to me.

Reviewed-by: Ondrej Mosnacek 

Although I'm wondering if we shouldn't try to future-proof the
AUDIT_SIGNAL_INFO2 format somehow, so that we don't need to add
another AUDIT_SIGNAL_INFO3 when the need arises to add yet-another
identifier to it... The simplest solution I can come up with is to add
a "version" field at the beginning (set to 2 initially), then v_len
at the beginning of data for version . But maybe this is too
complicated for too little gain...

> ---
>  include/linux/audit.h   |  7 +++
>  include/uapi/linux/audit.h  |  1 +
>  kernel/audit.c  | 27 +++
>  kernel/audit.h  |  1 +
>  kernel/auditsc.c|  1 +
>  security/selinux/nlmsgtab.c |  1 +
>  6 files changed, 38 insertions(+)
>
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 43438192ca2a..c2dec9157463 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -37,6 +37,13 @@ struct audit_sig_info {
> charctx[0];
>  };
>
> +struct audit_sig_info2 {
> +   uid_t   uid;
> +   pid_t   pid;
> +   u64 cid;
> +   charctx[0];
> +};
> +
>  struct audit_buffer;
>  struct audit_context;
>  struct inode;
> diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> index 55fde9970762..10cc67926cf1 100644
> --- a/include/uapi/linux/audit.h
> +++ b/include/uapi/linux/audit.h
> @@ -72,6 +72,7 @@
>  #define AUDIT_SET_FEATURE  1018/* Turn an audit feature on or off */
>  #define AUDIT_GET_FEATURE  1019/* Get which features are enabled */
>  #define AUDIT_CONTAINER_OP 1020/* Define the container id and info */
> +#define AUDIT_SIGNAL_INFO2 1021/* Get info auditd signal sender */
>
>  #define AUDIT_FIRST_USER_MSG   1100/* Userspace messages mostly 
> uninteresting to kernel */
>  #define AUDIT_USER_AVC 1107/* We filter this differently */
> diff --git a/kernel/audit.c b/kernel/audit.c
> index 3e0af53f3c4d..87e1d367f98c 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -138,6 +138,7 @@ struct audit_net {
>  kuid_t audit_sig_uid = INVALID_UID;
>  pid_t  audit_sig_pid = -1;
>  u32audit_sig_sid = 0;
> +u64audit_sig_cid = AUDIT_CID_UNSET;
>
>  /* Records can be lost in several ways:
> 0) [suppressed in audit_alloc]
> @@ -1097,6 +1098,7 @@ static int audit_netlink_ok(struct sk_buff *skb, u16 
> msg_type)
> case AUDIT_ADD_RULE:
> case AUDIT_DEL_RULE:
> case AUDIT_SIGNAL_INFO:
> +   case AUDIT_SIGNAL_INFO2:
> case AUDIT_TTY_GET:
> case AUDIT_TTY_SET:
> case AUDIT_TRIM:
> @@ -1260,6 +1262,7 @@ static int audit_receive_msg(struct sk_buff *skb, 
> struct nlmsghdr *nlh)
> struct audit_buffer *ab;
> u16 msg_type = nlh->nlmsg_type;
> struct audit_sig_info   *sig_data;
> +   struct audit_sig_info2  *sig_data2;
> char*ctx = NULL;
> u32 len;
>
> @@ -1519,6 +1522,30 @@ static int audit_receive_msg(struct sk_buff *skb, 
> struct nlmsghdr *nlh)
>  sig_data, sizeof(*sig_data) + len);
> kfree(sig_data);
> break;
> +   case AUDIT_SIGNAL_INFO2:
> +   len = 0;
> +   if (audit_sig_sid) {
> +   err = security_secid_to_secctx(audit_sig_sid, , 
> );
> +   if (err)
> +   return err;
> +   }
> +   sig_data2 = kmalloc(sizeof(*sig_data2) + len, GFP_KERNEL);
> +   if (!sig_data2) {
> +   if (audit_sig_sid)
> +   security_release_secctx(ctx, len);
> +   return -ENOMEM;
> +   }
> +   sig_data2->uid = from_kuid(_user_ns, audit_sig_uid);
> +   sig_data2->pid = audit_sig_pid;
> +   if (audit_sig_sid) {
> +   memcpy(sig_data2->ctx, ctx, len);

[PATCH ghak10 v7 2/2] ntp: Audit NTP parameters adjustment

2019-04-09 Thread Ondrej Mosnacek
Emit an audit record every time selected NTP parameters are modified
from userspace (via adjtimex(2) or clock_adjtime(2)). These parameters
may be used to indirectly change system clock, and thus their
modifications should be audited.

Such events will now generate records of type AUDIT_TIME_ADJNTPVAL
containing the following fields:
  - op -- which value was adjusted:
- offset -- corresponding to the time_offset variable
- freq   -- corresponding to the time_freq variable
- status -- corresponding to the time_status variable
- adjust -- corresponding to the time_adjust variable
- tick   -- corresponding to the tick_usec variable
- tai-- corresponding to the timekeeping's TAI offset
  - old -- the old value
  - new -- the new value

Example records:

type=TIME_ADJNTPVAL msg=audit(1530616044.507:7): op=status old=64 new=8256
type=TIME_ADJNTPVAL msg=audit(1530616044.511:11): op=freq old=0 
new=49180377088000

The records of this type will be associated with the corresponding
syscall records.

An overview of parameter changes that can be done via do_adjtimex()
(based on information from Miroslav Lichvar) and whether they are
audited:
  __timekeeping_set_tai_offset() -- sets the offset from the
International Atomic Time
(AUDITED)
  NTP variables:
time_offset -- can adjust the clock by up to 0.5 seconds per call
   and also speed it up or slow down by up to about
   0.05% (43 seconds per day) (AUDITED)
time_freq -- can speed up or slow down by up to about 0.05%
time_status -- can insert/delete leap seconds and it also enables/
   disables synchronization of the hardware real-time
   clock (AUDITED)
time_maxerror, time_esterror -- change error estimates used to
inform userspace applications
(NOT AUDITED)
time_constant -- controls the speed of the clock adjustments that
 are made when time_offset is set (NOT AUDITED)
time_adjust -- can temporarily speed up or slow down the clock by up
   to 0.05% (AUDITED)
tick_usec -- a more extreme version of time_freq; can speed up or
 slow down the clock by up to 10% (AUDITED)

Signed-off-by: Ondrej Mosnacek 
---
 include/linux/audit.h  | 54 ++
 include/uapi/linux/audit.h |  1 +
 kernel/auditsc.c   | 23 
 kernel/time/ntp.c  | 22 +---
 kernel/time/ntp_internal.h |  4 ++-
 kernel/time/timekeeping.c  |  7 -
 6 files changed, 106 insertions(+), 5 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 2c62c046..1c372ad7ebe9 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -86,6 +86,26 @@ struct audit_field {
u32 op;
 };
 
+#define AUDIT_NTP_OFFSET   0
+#define AUDIT_NTP_FREQ 1
+#define AUDIT_NTP_STATUS   2
+#define AUDIT_NTP_TAI  3
+#define AUDIT_NTP_TICK 4
+#define AUDIT_NTP_ADJUST   5
+#define AUDIT_NTP_NVALS6 /* count */
+
+#ifdef CONFIG_AUDITSYSCALL
+struct audit_ntp_val {
+   s64 oldval, newval;
+};
+
+struct audit_ntp_data {
+   struct audit_ntp_val vals[AUDIT_NTP_NVALS];
+};
+#else
+struct audit_ntp_data {};
+#endif
+
 extern int is_audit_feature_set(int which);
 
 extern int __init audit_register_class(int class, unsigned *list);
@@ -366,6 +386,7 @@ extern void __audit_mmap_fd(int fd, int flags);
 extern void __audit_log_kern_module(char *name);
 extern void __audit_fanotify(unsigned int response);
 extern void __audit_tk_injoffset(struct timespec64 offset);
+extern void __audit_ntp_log(const struct audit_ntp_data *ad);
 
 static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
 {
@@ -478,6 +499,27 @@ static inline void audit_tk_injoffset(struct timespec64 
offset)
__audit_tk_injoffset(offset);
 }
 
+static inline void audit_ntp_init(struct audit_ntp_data *ad)
+{
+   memset(ad, 0, sizeof(*ad));
+}
+
+static inline void audit_ntp_set_old(struct audit_ntp_data *ad, int id, s64 
val)
+{
+   ad->vals[id].oldval = val;
+}
+
+static inline void audit_ntp_set_new(struct audit_ntp_data *ad, int id, s64 
val)
+{
+   ad->vals[id].newval = val;
+}
+
+static inline void audit_ntp_log(const struct audit_ntp_data *ad)
+{
+   if (!audit_dummy_context())
+   __audit_ntp_log(ad);
+}
+
 extern int audit_n_rules;
 extern int audit_signals;
 #else /* CONFIG_AUDITSYSCALL */
@@ -594,6 +636,18 @@ static inline void audit_fanotify(unsigned int response)
 static inline void audit_tk_injoffset(struct timespec64 offset)
 { }
 
+static inline void audit_ntp_init(struct audit_ntp_data *ad)
+{ }
+
+static inline void audit_ntp_set_old(struct audit_ntp_data *ad, int id, s64 
val)
+{ }
+
+static inlin

[PATCH ghak10 v7 1/2] timekeeping: Audit clock adjustments

2019-04-09 Thread Ondrej Mosnacek
Emit an audit record whenever the system clock is changed (i.e. shifted
by a non-zero offset) by a syscall from userspace. The syscalls than can
(at the time of writing) trigger such record are:
  - settimeofday(2), stime(2), clock_settime(2) -- via
do_settimeofday64()
  - adjtimex(2), clock_adjtime(2) -- via do_adjtimex()

The new records have type AUDIT_TIME_INJOFFSET and contain the following
fields:
  - sec -- the 'seconds' part of the offset
  - nsec -- the 'nanoseconds' part of the offset

Example record (time was shifted backwards by ~16.125 seconds):

type=TIME_INJOFFSET msg=audit(1530616049.652:13): sec=-16 nsec=124887145

The records of this type will be associated with the corresponding
syscall records.

Signed-off-by: Ondrej Mosnacek 
---
 include/linux/audit.h  | 14 ++
 include/uapi/linux/audit.h |  1 +
 kernel/auditsc.c   |  6 ++
 kernel/time/timekeeping.c  |  6 ++
 4 files changed, 27 insertions(+)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 1e69d9fe16da..2c62c046 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -365,6 +365,7 @@ extern void __audit_log_capset(const struct cred *new, 
const struct cred *old);
 extern void __audit_mmap_fd(int fd, int flags);
 extern void __audit_log_kern_module(char *name);
 extern void __audit_fanotify(unsigned int response);
+extern void __audit_tk_injoffset(struct timespec64 offset);
 
 static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
 {
@@ -467,6 +468,16 @@ static inline void audit_fanotify(unsigned int response)
__audit_fanotify(response);
 }
 
+static inline void audit_tk_injoffset(struct timespec64 offset)
+{
+   /* ignore no-op events */
+   if (offset.tv_sec == 0 && offset.tv_nsec == 0)
+   return;
+
+   if (!audit_dummy_context())
+   __audit_tk_injoffset(offset);
+}
+
 extern int audit_n_rules;
 extern int audit_signals;
 #else /* CONFIG_AUDITSYSCALL */
@@ -580,6 +591,9 @@ static inline void audit_log_kern_module(char *name)
 static inline void audit_fanotify(unsigned int response)
 { }
 
+static inline void audit_tk_injoffset(struct timespec64 offset)
+{ }
+
 static inline void audit_ptrace(struct task_struct *t)
 { }
 #define audit_n_rules 0
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 3901c51c0b93..ab58d67baf4d 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -114,6 +114,7 @@
 #define AUDIT_REPLACE  1329/* Replace auditd if this packet 
unanswerd */
 #define AUDIT_KERN_MODULE  1330/* Kernel Module events */
 #define AUDIT_FANOTIFY 1331/* Fanotify access decision */
+#define AUDIT_TIME_INJOFFSET   1332/* Timekeeping offset injected */
 
 #define AUDIT_AVC  1400/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR  1401/* Internal SE Linux Errors */
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 51a2ceb3a1ca..80dfe0cdc636 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2512,6 +2512,12 @@ void __audit_fanotify(unsigned int response)
AUDIT_FANOTIFY, "resp=%u", response);
 }
 
+void __audit_tk_injoffset(struct timespec64 offset)
+{
+   audit_log(audit_context(), GFP_KERNEL, AUDIT_TIME_INJOFFSET,
+ "sec=%lli nsec=%li", (long long)offset.tv_sec, 
offset.tv_nsec);
+}
+
 static void audit_log_task(struct audit_buffer *ab)
 {
kuid_t auid, uid;
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index f986e1918d12..3d24be4cd607 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "tick-internal.h"
 #include "ntp_internal.h"
@@ -1250,6 +1251,9 @@ out:
/* signal hrtimers about time change */
clock_was_set();
 
+   if (!ret)
+   audit_tk_injoffset(ts_delta);
+
return ret;
 }
 EXPORT_SYMBOL(do_settimeofday64);
@@ -2322,6 +2326,8 @@ int do_adjtimex(struct __kernel_timex *txc)
ret = timekeeping_inject_offset();
if (ret)
return ret;
+
+   audit_tk_injoffset(delta);
}
 
ktime_get_real_ts64();
-- 
2.20.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


[PATCH ghak10 v7 0/2] audit: Log changes that can affect the system clock

2019-04-09 Thread Ondrej Mosnacek
This patchset implements auditing of (syscall-triggered) changes that
can modify or indirectly affect the system clock. Some of these
changes can already be detected by simply logging relevant syscalls,
but this has some disadvantages:
  a) It is usually not possible to find out from the syscall records
 the amount by which the time was shifted.
  b) Syscalls like adjtimex(2) or clock_adjtime(2) can be used also
 for read-only operations, which might flood the audit log with
 false positives. (Note that these patches don't solve this
 problem yet due to the limitations of current record filtering
 capabilities.)

The main motivation is to provide better reliability of timestamps
on the system as mandated by the FPT_STM.1 security functional
requirement from Common Criteria. This requirement apparently demands
that it is possible to reconstruct from audit trail the old and new
values of the time when it is adjusted (see [1]).

The current version of the patchset logs the following changes:
  - direct setting of system time to a given value
  - direct injection of timekeeping offset
  - adjustment of timekeeping's TAI offset
  - NTP value adjustments (may affect system time indirectly):
- time_offset
- time_freq
- time_status
- time_adjust
- tick_usec

Changes to the following NTP values are not logged, as they are not
important for security:
  - time_maxerror
  - time_esterror
  - time_constant

Audit kernel GitHub issue: https://github.com/linux-audit/audit-kernel/issues/10
Audit kernel RFE page: 
https://github.com/linux-audit/audit-kernel/wiki/RFE-More-detailed-auditing-of-changes-to-system-clock

Audit userspace PR: https://github.com/linux-audit/audit-userspace/pull/89
Audit testsuite PR: https://github.com/linux-audit/audit-testsuite/pull/82

Testing: Passed audit-testuite (including new functional test from PR#82)

Changes in v7:
  - Removed #include  from audit.h, since it is not
needed
  - Moved audit_log() calls out of locked sections and switched audit
allocations to GFP_KERNEL
  - Rebased onto latest audit/next
  - Switched the general NTP value type to long long (was s64),
which corresponds better with the actual timex field types
  - Simplified commit log messages

v6: https://www.redhat.com/archives/linux-audit/2019-March/msg00016.html
Changes in v6:
  - Reorganized the patches to group changes by record type, not
kernel subsytem, as suggested in earlier discussions
  - Added checks to ignore no-change events (new value == old value)
  - Added TIME_INJOFFSET logging also to do_settimeofday64() to cover
syscalls such as settimeofday(2), stime(2), clock_settime(2)
  - Created an RFE page on audit-kernel GitHub

v5: https://www.redhat.com/archives/linux-audit/2018-August/msg00039.html
Changes in v5:
  - Dropped logging of some less important changes and update commit messages
  - No longer mark the patchset as RFC

v4: https://www.redhat.com/archives/linux-audit/2018-August/msg00023.html
Changes in v4:
  - Squashed first two patches into one
  - Renamed ADJNTPVAL's "type" field to "op" to align with audit record
conventions
  - Minor commit message editing
  - Cc timekeeping/NTP people for feedback

v3: https://www.redhat.com/archives/linux-audit/2018-July/msg1.html
Changes in v3:
  - Switched to separate records for each variable
  - Both old and new value is now reported for each change
  - Injecting offset is reported via a separate record (since this
offset consists of two values and is added directly to the clock,
i.e. it doesn't make sense to log old and new value)
  - Added example records produced by chronyd -q (see the commit message
of the last patch)

v2: https://www.redhat.com/archives/linux-audit/2018-June/msg00114.html
Changes in v2:
  - The audit_adjtime() function has been modified to only log those
fields that contain values that are actually used, resulting in more
compact records.
  - The audit_adjtime() call has been moved to do_adjtimex() in
timekeeping.c
  - Added an additional patch (for review) that simplifies the detection
if the syscall is read-only.

v1: https://www.redhat.com/archives/linux-audit/2018-June/msg00095.html

[1] https://www.niap-ccevs.org/MMO/PP/pp_ca_v2.1.pdf -- section 5.1,
table 4

Ondrej Mosnacek (2):
  timekeeping: Audit clock adjustments
  ntp: Audit NTP parameters adjustment

 include/linux/audit.h  | 68 ++
 include/uapi/linux/audit.h |  2 ++
 kernel/auditsc.c   | 29 
 kernel/time/ntp.c  | 22 ++--
 kernel/time/ntp_internal.h |  4 ++-
 kernel/time/timekeeping.c  | 13 +++-
 6 files changed, 133 insertions(+), 5 deletions(-)

-- 
2.20.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [RFC PATCH ghak10 v6 2/2] ntp: Audit NTP parameters adjustment

2019-04-02 Thread Ondrej Mosnacek
On Tue, Apr 2, 2019 at 11:33 AM Thomas Gleixner  wrote:
> On Mon, 1 Apr 2019, Ondrej Mosnacek wrote:
> > On Thu, Mar 28, 2019 at 1:02 AM Thomas Gleixner  wrote:
> > > On Thu, 7 Mar 2019, Ondrej Mosnacek wrote:
> > > >   /* adjtime() is independent from ntp_adjtime() */
> > > >   time_adjust = txc->offset;
> > > >   ntp_update_frequency();
> > > > +
> > > > + audit_ntp_adjust("adjust", save_adjust, 
> > > > txc->offset);
> > > >   }
> > > >   txc->offset = save_adjust;
> > > >   } else {
> > >
> > > Not going to happen. We are not reshuffling all that code just to
> > > accomodate random audit log invocations in a critical section plus having 
> > > a
> > > gazillion of GFP_ATOMIC allocation in the critical section just because.
> >
> > OK, seems I underestimated the consequences of putting the logging
> > calls directly in there. While I was offline over the weekend I
> > already came up with a cleaner version that collects the changes in a
> > structure and does the logging outside of the critical section. I
> > currently does a few unnecessary writes into memory under
> > CONFIG_AUDIT=n, but if that is an issue I can boost the abstraction or
> > just add some #ifdefs to avoid that.
>
> No ifdefs please.

Yep, no worries, I already found a clean way to make all the audit
operations a no-op under CONFIG_AUDITSYSCALL=n that keeps all the
#ifdefs contained within .

> Aside of that, why do you need all those details of the
> ntp internals in the first place? The changelog does not give me an answer
> to that.

Yeah, the changelog should be more explanatory, I'll try to improve
that in the next revision. I actually stated the justification in the
RFE page [1] (paragraphs 3-4) linked from the cover letter (I don't
blame you for not finding it...). The idea is that it is (or at least
seems) possible to do some evil changes to the clock indirectly by
modifying these parameters as well. Maybe it is a bit overkill, but
it's better to be safe than sorry... If anyone doesn't want the extra
records, they can be easily filtered out by adding a simple audit
rule.

[1] 
https://github.com/linux-audit/audit-kernel/wiki/RFE-More-detailed-auditing-of-changes-to-system-clock#feature-design

-- 
Ondrej Mosnacek 
Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [RFC PATCH ghak10 v6 0/2] audit: Log changes that can affect the system clock

2019-04-01 Thread Ondrej Mosnacek
On Thu, Mar 28, 2019 at 12:00 AM Paul Moore  wrote:
> On Mon, Mar 25, 2019 at 10:50 AM Paul Moore  wrote:
> > On Thu, Mar 7, 2019 at 7:33 AM Ondrej Mosnacek  wrote:
> > > This patchset implements auditing of (syscall-triggered) changes that
> > > can modify or indirectly affect the system clock. Some of these
> > > changes can already be detected by simply logging relevant syscalls,
> > > but this has some disadvantages:
> > >   a) It is usually not possible to find out from the syscall records
> > >  the amount by which the time was shifted.
> > >   b) Syscalls like adjtimex(2) or clock_adjtime(2) can be used also
> > >  for read-only operations, which might flood the audit log with
> > >  false positives. (Note that these patches don't solve this
> > >  problem yet due to the limitations of current record filtering
> > >  capabilities.)
> > >
> > > The main motivation is to provide better reliability of timestamps
> > > on the system as mandated by the FPT_STM.1 security functional
> > > requirement from Common Criteria. This requirement apparently demands
> > > that it is possible to reconstruct from audit trail the old and new
> > > values of the time when it is adjusted (see [1]).
> > >
> > > The current version of the patchset logs the following changes:
> > >   - direct setting of system time to a given value
> > >   - direct injection of timekeeping offset
> > >   - adjustment of timekeeping's TAI offset
> > >   - NTP value adjustments:
> > > - time_offset
> > > - time_freq
> > > - time_status
> > > - time_adjust
> > > - tick_usec
> > >
> > > Changes to the following NTP values are not logged, as they are not
> > > important for security:
> > >   - time_maxerror
> > >   - time_esterror
> > >   - time_constant
> > >
> > > Audit kernel GitHub issue: 
> > > https://github.com/linux-audit/audit-kernel/issues/10
> > > Audit kernel RFE page: 
> > > https://github.com/linux-audit/audit-kernel/wiki/RFE-More-detailed-auditing-of-changes-to-system-clock
> > >
> > > Testing: Passed audit-testuite; functional tests TBD
> > >
> > > Changes in v6:
> > >   - Reorganized the patches to group changes by record type, not
> > > kernel subsytem, as suggested in earlier discussions
> > >   - Added checks to ignore no-change events (new value == old value)
> > >   - Added TIME_INJOFFSET logging also to do_settimeofday64() to cover
> > > syscalls such as settimeofday(2), stime(2), clock_settime(2)
> > >   - Created an RFE page on audit-kernel GitHub
> > > TODO:
> > >   - tests for audit-testsuite
> > >
> > > v5: https://www.redhat.com/archives/linux-audit/2018-August/msg00039.html
> > > Changes in v5:
> > >   - Dropped logging of some less important changes and update commit 
> > > messages
> > >   - No longer mark the patchset as RFC
> > >
> > > v4: https://www.redhat.com/archives/linux-audit/2018-August/msg00023.html
> > > Changes in v4:
> > >   - Squashed first two patches into one
> > >   - Renamed ADJNTPVAL's "type" field to "op" to align with audit record
> > > conventions
> > >   - Minor commit message editing
> > >   - Cc timekeeping/NTP people for feedback
> > >
> > > v3: https://www.redhat.com/archives/linux-audit/2018-July/msg1.html
> > > Changes in v3:
> > >   - Switched to separate records for each variable
> > >   - Both old and new value is now reported for each change
> > >   - Injecting offset is reported via a separate record (since this
> > > offset consists of two values and is added directly to the clock,
> > > i.e. it doesn't make sense to log old and new value)
> > >   - Added example records produced by chronyd -q (see the commit message
> > > of the last patch)
> > >
> > > v2: https://www.redhat.com/archives/linux-audit/2018-June/msg00114.html
> > > Changes in v2:
> > >   - The audit_adjtime() function has been modified to only log those
> > > fields that contain values that are actually used, resulting in more
> > > compact records.
> > >   - The audit_adjtime() call has been moved to do_adjtimex() in
> > > timekeeping.c
> > >   - Added an additional patch (for review) that simplifies the detection
> > > if the syscall is read-only.

Re: [RFC PATCH ghak10 v6 1/2] timekeeping: Audit clock adjustments

2019-04-01 Thread Ondrej Mosnacek
On Thu, Mar 28, 2019 at 1:09 AM Thomas Gleixner  wrote:
> On Thu, 7 Mar 2019, Ondrej Mosnacek wrote:
> > --- a/kernel/auditsc.c
> > +++ b/kernel/auditsc.c
> > @@ -2512,6 +2512,14 @@ void __audit_fanotify(unsigned int response)
> >   AUDIT_FANOTIFY, "resp=%u", response);
> >  }
> >
> > +/* We need to allocate with GFP_ATOMIC here, since these two functions 
> > will be
> > + * called while holding the timekeeping lock: */
>
> Audit is no justification for doing ATOMIC allocations just because it's
> convenient in the middle of code which blocks every concurrent reader.
>
> Please find a place outside of the timekeeper lock to do that audit
> logging. Either that or allocate your buffer upfront in a preemptible
> section and commit after the critical section.
>
> /*
>  * Aside of that please use proper multiline comment style and not this
>  * horrible other one.
>  */

Oh, sorry, I wrote that code last summer, when I didn't quite have the
kernel coding style in my blood yet :) But fortunately I shouldn't
need that comment at all in the next version...

>
> > +void __audit_tk_injoffset(struct timespec64 offset)
> > +{
> > + audit_log(audit_context(), GFP_ATOMIC, AUDIT_TIME_INJOFFSET,
> > +   "sec=%lli nsec=%li", (long long)offset.tv_sec, 
> > offset.tv_nsec);
> > +}
> > +
> > @@ -1250,6 +1251,9 @@ out:
> >   /* signal hrtimers about time change */
> >   clock_was_set();
> >
> > + if (!ret)
> > + audit_tk_injoffset(ts_delta);
>
> This one does not need GFP_ATOMIC at all.
>
> > +
> >   return ret;
> >  }
> >  EXPORT_SYMBOL(do_settimeofday64);
> > @@ -2322,6 +2326,8 @@ int do_adjtimex(struct timex *txc)
> >   ret = timekeeping_inject_offset();
> >   if (ret)
> >   return ret;
> > +
> > + audit_tk_injoffset(delta);
> >   }
> >
> >   ktime_get_real_ts64();
>
> This can be done at the end of do_adjtimex() quite nicely in preemptible
> context.

But wait, isn't this call outside of the critical section as well? (I
must have been moving the call around when I was writing the code and
didn't realize that this function actually doesn't need GFP_ATOMIC at
all...) Or am I missing something?


--
Ondrej Mosnacek 
Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [RFC PATCH ghak10 v6 1/2] timekeeping: Audit clock adjustments

2019-04-01 Thread Ondrej Mosnacek
On Thu, Mar 28, 2019 at 12:27 AM John Stultz  wrote:
> On Thu, Mar 7, 2019 at 4:33 AM Ondrej Mosnacek  wrote:
> >
> > Emit an audit record whenever the system clock is changed (i.e. shifted
> > by a non-zero offset) by a syscall from userspace. The syscalls than can
> > (at the time of writing) trigger such record are:
> >   - settimeofday(2), stime(2), clock_settime(2) -- via
> > do_settimeofday64()
> >   - adjtimex(2), clock_adjtime(2) -- via do_adjtimex()
> >
> > The new records have type AUDIT_TIME_INJOFFSET and contain the following
> > fields:
> >   - sec -- the 'seconds' part of the offset
> >   - nsec -- the 'nanoseconds' part of the offset
> >
> > For reference, running the following commands:
> >
> > auditctl -D
> > auditctl -a exit,always -F arch=b64 -S adjtimex
> > chronyd -q
> >
> > triggers (among others) a syscall that produces audit records like this:
> >
> > type=TIME_INJOFFSET msg=audit(1530616049.652:13): sec=-16 nsec=124887145
> > type=SYSCALL msg=audit(1530616049.652:13): arch=c03e syscall=159 
> > success=yes exit=5 a0=7fff57e78270 a1=1 a2=fff0 
> > a3=137b828205ca12 items=0 ppid=626 pid=629 auid=0 uid=385 gid=382 euid=385 
> > suid=385 fsuid=385 egid=382 sgid=382 fsgid=382 tty=(none) ses=1 
> > comm="chronyd" exe="/usr/sbin/chronyd" subj=system_u:system_r:kernel_t:s0 
> > key=(null)
> > type=PROCTITLE msg=audit(1530616049.652:13): proctitle=6368726F6E7964002D71 
> > cd /home/omosnace/Dokumenty/Kernel/worktrees/audit/src/kernel/time
> > s
>
> Hrm.  Ugly log spam aside (I get it sort of goes with the territory
> :), I could imagine someone looking at this and wanting to also know
> when the injection was applied. Obviously the whole point of the
> offset injection is we don't really care about the when, we only want
> a fixed offset to be made atomically.  That said, if someone did try
> to add such a timestamp on the log, there's the problem of trying to
> calculate the time while holding the timekeeping locks.   So, are you
> certain the next request won't be to try to to also calculate a
> timestamp and push it into the audit_log() call as well?

Well, __audit_syscall_entry() already logs the timestamp of the
syscall entry (this is what ends up also in the TIME_INJOFFSET
syscall-associated record as the timestamp, actually), so even though
it is not precisely the moment when the change happened, it should be
good enough in most cases. I'm not sure if it is worth it to add
another slightly duplicit but exact timestamp... Steve Grubb is our
local expert on certifications, so unless he tells me this is likely
required, I don't feel like adding that extra information there right
now...

>
> Also, we have to be careful with anything we call from the timekeeping
> code, its really easy for some corner case to trip something that then
> tries to read the time and we deadlock, particularly with rare cases
> like time adjustments.  I'm not familiar with the audit subsystem, but
> from a maintenance point of view, can we make sure there's enough
> documentation so that audit_log() and everything it calls will never
> in the future call back into the timekeeping code?   I suspect this is
> already covered, so apologies for the boilerplate concern, but I want
> to be sure.

Yes, this turns out to be a bigger issue than I'd thought, see my
reply to Thomas in the thread for 2/2.



>
>
> > The above records have been produced by the following syscall from
> > chronyd (as per strace output):
> >
> > adjtimex({modes=ADJ_SETOFFSET|ADJ_NANO, offset=0, freq=750433, 
> > maxerror=1600, esterror=1600, status=STA_UNSYNC|STA_NANO, 
> > constant=2, precision=1, tolerance=32768000, time={tv_sec=1530616033, 
> > tv_usec=778717675}, tick=1, ppsfreq=0, jitter=0, shift=0, stabil=0, 
> > jitcnt=0, calcnt=0, errcnt=0, stbcnt=0, tai=0}) = 5 (TIME_ERROR)
> >
> > (The struct timex fields above are from *after* the syscall was
> > executed, so they contain the current (new) values as set from the
> > kernel, except of the 'modes' field, which contains the original value
> > sent by the caller.)
> >
> > Signed-off-by: Ondrej Mosnacek 
> > ---
> >  include/linux/audit.h  | 15 +++
> >  include/uapi/linux/audit.h |  1 +
> >  kernel/auditsc.c   |  8 
> >  kernel/time/timekeeping.c  |  6 ++
> >  4 files changed, 30 insertions(+)
> >
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index 1e69d9fe16da..43a60fbe74be 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -27,6 

Re: [RFC PATCH ghak10 v6 2/2] ntp: Audit NTP parameters adjustment

2019-04-01 Thread Ondrej Mosnacek
On Thu, Mar 28, 2019 at 1:02 AM Thomas Gleixner  wrote:
> On Thu, 7 Mar 2019, Ondrej Mosnacek wrote:
>
> > Emit an audit record every time selected NTP parameters are modified
> > from userspace (via adjtimex(2) or clock_adjtime(2)).
> >
> > Such events will now generate records of type AUDIT_TIME_ADJNTPVAL
> > containing the following fields:
> >   - op -- which value was adjusted:
> > - offset -- corresponding to the time_offset variable
> > - freq   -- corresponding to the time_freq variable
> > - status -- corresponding to the time_status variable
> > - adjust -- corresponding to the time_adjust variable
> > - tick   -- corresponding to the tick_usec variable
> > - tai-- corresponding to the timekeeping's TAI offset
> >   - old -- the old value
> >   - new -- the new value
> >
> > For reference, running the following commands:
> >
> > auditctl -D
> > auditctl -a exit,always -F arch=b64 -S adjtimex
> > chronyd -q
> >
> > produces audit records like this:
> >
> > type=SYSCALL msg=audit(1530616044.507:5): arch=c03e syscall=159 
> > success=yes exit=5 a0=7fff57e78c00 a1=0 a2=4 a3=7f754ae28c0a items=0 
> > ppid=626 pid=629 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 
> > fsgid=0 tty=(none) ses=1 comm="chronyd" exe="/usr/sbin/chronyd" 
> > subj=system_u:system_r:kernel_t:s0 key=(null)
>
> 
>
> Is it really necessary to put this into the changelog?

Yeah, sorry, I went a bit overboard with the record examples... I'll
try to provide simpler and less verbose examples in the next version.

>
> >
> > +void __audit_ntp_adjust(const char *type, s64 oldval, s64 newval)
> > +{
> > + audit_log(audit_context(), GFP_ATOMIC, AUDIT_TIME_ADJNTPVAL,
>
> No.
>
> > +   "op=%s old=%lli new=%lli", type,
> > +   (long long)oldval, (long long)newval);
> > +}
> > +
> >  static void audit_log_task(struct audit_buffer *ab)
> >  {
> >   kuid_t auid, uid;
> > diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
> > index 36a2bef00125..5f456a84151a 100644
> > --- a/kernel/time/ntp.c
> > +++ b/kernel/time/ntp.c
> > @@ -17,6 +17,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >
> >  #include "ntp_internal.h"
> >  #include "timekeeping_internal.h"
> > @@ -293,6 +294,8 @@ static inline s64 ntp_update_offset_fll(s64 offset64, 
> > long secs)
> >
> >  static void ntp_update_offset(long offset)
> >  {
> > + s64 old_offset = time_offset;
> > + s64 old_freq = time_freq;
> >   s64 freq_adj;
> >   s64 offset64;
> >   long secs;
> > @@ -341,6 +344,9 @@ static void ntp_update_offset(long offset)
> >   time_freq   = max(freq_adj, -MAXFREQ_SCALED);
> >
> >   time_offset = div_s64(offset64 << NTP_SCALE_SHIFT, NTP_INTERVAL_FREQ);
> > +
> > + audit_ntp_adjust("offset", old_offset, time_offset);
> > + audit_ntp_adjust("freq", old_freq, time_freq);
> >  }
> >
> >  /**
> > @@ -658,21 +664,31 @@ static inline void process_adj_status(const struct 
> > timex *txc)
> >
> >  static inline void process_adjtimex_modes(const struct timex *txc, s32 
> > *time_tai)
> >  {
> > - if (txc->modes & ADJ_STATUS)
> > - process_adj_status(txc);
> > + if (txc->modes & (ADJ_STATUS | ADJ_NANO | ADJ_MICRO)) {
> > + int old_status = time_status;
> > +
> > + if (txc->modes & ADJ_STATUS)
> > + process_adj_status(txc);
> > - if (txc->modes & ADJ_NANO)
> > - time_status |= STA_NANO;
> > + if (txc->modes & ADJ_NANO)
> > + time_status |= STA_NANO;
> >
> > - if (txc->modes & ADJ_MICRO)
> > - time_status &= ~STA_NANO;
> > + if (txc->modes & ADJ_MICRO)
> > + time_status &= ~STA_NANO;
> > +
> > + audit_ntp_adjust("status", old_status, time_status);
> > + }
> >
> >   if (txc->modes & ADJ_FREQUENCY) {
> > + s64 old_freq = time_freq;
> > +
> >   time_freq = txc->freq * PPM_SCALE;
> >   time_freq = min(time_freq, MAXFREQ_SCALED);
> >   time_freq = max(time_freq, -MAXFREQ_SCALED);
> >   /* update pps_freq */
> >

Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces

2019-03-28 Thread Ondrej Mosnacek
On Thu, Mar 28, 2019 at 2:12 AM Richard Guy Briggs  wrote:
> On 2019-03-27 23:42, Ondrej Mosnacek wrote:
> > On Fri, Mar 15, 2019 at 7:35 PM Richard Guy Briggs  wrote:
> > > Audit events could happen in a network namespace outside of a task
> > > context due to packets received from the net that trigger an auditing
> > > rule prior to being associated with a running task.  The network
> > > namespace could be in use by multiple containers by association to the
> > > tasks in that network namespace.  We still want a way to attribute
> > > these events to any potential containers.  Keep a list per network
> > > namespace to track these audit container identifiiers.
> > >
> > > Add/increment the audit container identifier on:
> > > - initial setting of the audit container identifier via /proc
> > > - clone/fork call that inherits an audit container identifier
> > > - unshare call that inherits an audit container identifier
> > > - setns call that inherits an audit container identifier
> > > Delete/decrement the audit container identifier on:
> > > - an inherited audit container identifier dropped when child set
> > > - process exit
> > > - unshare call that drops a net namespace
> > > - setns call that drops a net namespace
> > >
> > > See: https://github.com/linux-audit/audit-kernel/issues/92
> > > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > > See: 
> > > https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > > Signed-off-by: Richard Guy Briggs 
> > > ---
> > >  include/linux/audit.h | 19 
> > >  kernel/audit.c| 86 
> > > +--
> > >  kernel/nsproxy.c  |  4 +++
> > >  3 files changed, 106 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > > index fa19fa408931..70255c2dfb9f 100644
> > > --- a/include/linux/audit.h
> > > +++ b/include/linux/audit.h
> > > @@ -27,6 +27,7 @@
> > >  #include 
> > >  #include   /* LOOKUP_* */
> > >  #include 
> > > +#include 
> > >
> > >  #define AUDIT_INO_UNSET ((unsigned long)-1)
> > >  #define AUDIT_DEV_UNSET ((dev_t)-1)
> > > @@ -99,6 +100,13 @@ struct audit_task_info {
> > >
> > >  extern struct audit_task_info init_struct_audit;
> > >
> > > +struct audit_contid {
> > > +   struct list_headlist;
> > > +   u64 id;
> > > +   refcount_t  refcount;
> >
> > Hm, since we only ever touch the refcount under a spinlock, I wonder
> > if we could just make it a regular unsigned int (we don't need the
> > atomicity guarantees). OTOH, refcount_t comes with some extra overflow
> > checking, so it's probably better to leave it as is...
>
> Since the update is done using rcu-safe methods, do we even need the
> spin_lock?  Neil?  Paul?
>
> > > +   struct rcu_head rcu;
> > > +};
> > > +
> > >  extern int is_audit_feature_set(int which);
> > >
> > >  extern int __init audit_register_class(int class, unsigned *list);
> > > @@ -202,6 +210,10 @@ static inline u64 audit_get_contid(struct 
> > > task_struct *tsk)
> > >  }
> > >
> > >  extern void audit_log_contid(struct audit_context *context, u64 contid);
> > > +extern void audit_netns_contid_add(struct net *net, u64 contid);
> > > +extern void audit_netns_contid_del(struct net *net, u64 contid);
> > > +extern void audit_switch_task_namespaces(struct nsproxy *ns,
> > > +struct task_struct *p);
> > >
> > >  extern u32 audit_enabled;
> > >  #else /* CONFIG_AUDIT */
> > > @@ -271,6 +283,13 @@ static inline u64 audit_get_contid(struct 
> > > task_struct *tsk)
> > >
> > >  static inline void audit_log_contid(struct audit_context *context, u64 
> > > contid)
> > >  { }
> > > +static inline void audit_netns_contid_add(struct net *net, u64 contid)
> > > +{ }
> > > +static inline void audit_netns_contid_del(struct net *net, u64 contid)
> > > +{ }
> > > +static inline void audit_switch_task_namespaces(struct nsproxy *ns,
> > > +   struct task_struct *p)
> > > +{ }
> > >
> > >  #define audit_enabled AUDIT_OFF
> > >  #endif /* CONFIG_AUDIT */
> >

Re: [PATCH ghak90 V5 10/10] audit: NETFILTER_PKT: record each container ID associated with a netNS

2019-03-27 Thread Ondrej Mosnacek
On Fri, Mar 15, 2019 at 7:35 PM Richard Guy Briggs  wrote:
> Add audit container identifier auxiliary record(s) to NETFILTER_PKT
> event standalone records.  Iterate through all potential audit container
> identifiers associated with a network namespace.
>
> Signed-off-by: Richard Guy Briggs 

Reviewed-by: Ondrej Mosnacek 

(Just note another "%llu"/u64 occurence, in case you plan to add the casts.)

> ---
>  include/linux/audit.h|  5 +
>  kernel/audit.c   | 41 +
>  net/netfilter/nft_log.c  | 11 +--
>  net/netfilter/xt_AUDIT.c | 11 +--
>  4 files changed, 64 insertions(+), 4 deletions(-)
>
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 70255c2dfb9f..723e2d020228 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -214,6 +214,8 @@ static inline u64 audit_get_contid(struct task_struct 
> *tsk)
>  extern void audit_netns_contid_del(struct net *net, u64 contid);
>  extern void audit_switch_task_namespaces(struct nsproxy *ns,
>  struct task_struct *p);
> +extern void audit_log_netns_contid_list(struct net *net,
> +   struct audit_context *context);
>
>  extern u32 audit_enabled;
>  #else /* CONFIG_AUDIT */
> @@ -290,6 +292,9 @@ static inline void audit_netns_contid_del(struct net 
> *net, u64 contid)
>  static inline void audit_switch_task_namespaces(struct nsproxy *ns,
> struct task_struct *p)
>  { }
> +static inline void audit_log_netns_contid_list(struct net *net,
> +  struct audit_context *context)
> +{ }
>
>  #define audit_enabled AUDIT_OFF
>  #endif /* CONFIG_AUDIT */
> diff --git a/kernel/audit.c b/kernel/audit.c
> index 7fa3194f5342..80ed323feeb5 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -451,6 +451,47 @@ void audit_switch_task_namespaces(struct nsproxy *ns, 
> struct task_struct *p)
> audit_netns_contid_add(new->net_ns, contid);
>  }
>
> +/**
> + * audit_log_netns_contid_list - List contids for the given network namespace
> + * @net: the network namespace of interest
> + * @context: the audit context to use
> + *
> + * Description:
> + * Issues a CONTAINER_ID record with a CSV list of contids associated
> + * with a network namespace to accompany a NETFILTER_PKT record.
> + */
> +void audit_log_netns_contid_list(struct net *net, struct audit_context 
> *context)
> +{
> +   struct audit_buffer *ab = NULL;
> +   struct audit_contid *cont;
> +   bool first = true;
> +   struct audit_net *aunet;
> +
> +   /* Generate AUDIT_CONTAINER_ID record with container ID CSV list */
> +   rcu_read_lock();
> +   aunet = net_generic(net, audit_net_id);
> +   if (!aunet)
> +   goto out;
> +   list_for_each_entry_rcu(cont, >contid_list, list) {
> +   if (first) {
> +   ab = audit_log_start(context, GFP_ATOMIC,
> +AUDIT_CONTAINER_ID);
> +   if (!ab) {
> +   audit_log_lost("out of memory in 
> audit_log_netns_contid_list");
> +   goto out;
> +   }
> +   audit_log_format(ab, "contid=");
> +   } else
> +   audit_log_format(ab, ",");
> +   audit_log_format(ab, "%llu", cont->id);
> +   first = false;
> +   }
> +   audit_log_end(ab);
> +out:
> +   rcu_read_unlock();
> +}
> +EXPORT_SYMBOL(audit_log_netns_contid_list);
> +
>  void audit_panic(const char *message)
>  {
> switch (audit_failure) {
> diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c
> index 655187bed5d8..bdb1ec2368a7 100644
> --- a/net/netfilter/nft_log.c
> +++ b/net/netfilter/nft_log.c
> @@ -69,13 +69,16 @@ static void nft_log_eval_audit(const struct nft_pktinfo 
> *pkt)
> struct sk_buff *skb = pkt->skb;
> struct audit_buffer *ab;
> int fam = -1;
> +   struct audit_context *context;
> +   struct net *net;
>
> if (!audit_enabled)
> return;
>
> -   ab = audit_log_start(NULL, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
> +   context = audit_alloc_local(GFP_ATOMIC);
> +   ab = audit_log_start(context, GFP_ATOMIC, AUDIT_NETFILTER_PKT);
> if (!ab)
> -   return;
> +   goto errout;
>
> audit_log_format(ab, "mark=%#x", skb->m

Re: [PATCH ghak90 V5 09/10] audit: add support for containerid to network namespaces

2019-03-27 Thread Ondrej Mosnacek
 long flags, struct 
> task_struct *tsk)
> struct nsproxy *old_ns = tsk->nsproxy;
> struct user_namespace *user_ns = task_cred_xxx(tsk, user_ns);
> struct nsproxy *new_ns;
> +   u64 contid = audit_get_contid(tsk);
>
> if (likely(!(flags & (CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC |
>   CLONE_NEWPID | CLONE_NEWNET |
> @@ -167,6 +169,7 @@ int copy_namespaces(unsigned long flags, struct 
> task_struct *tsk)
> return  PTR_ERR(new_ns);
>
> tsk->nsproxy = new_ns;
> +   audit_netns_contid_add(new_ns->net_ns, contid);
> return 0;
>  }
>
> @@ -224,6 +227,7 @@ void switch_task_namespaces(struct task_struct *p, struct 
> nsproxy *new)
> ns = p->nsproxy;
> p->nsproxy = new;
> task_unlock(p);
> +   audit_switch_task_namespaces(ns, p);

Since we call audit_switch_task_namespaces() after task_unlock(),
could there be a potential race condition? I'm not going to dive too
much into this now, because it's getting late here, but on first look
it seems like p->nsproxy could change under our hands before we fetch
it in audit_switch_task_namespaces()...

>
> if (ns && atomic_dec_and_test(>count))
> free_nsproxy(ns);
> --
> 1.8.3.1
>

-- 
Ondrej Mosnacek 
Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [PATCH ghak90 V5 08/10] audit: add containerid filtering

2019-03-27 Thread Ondrej Mosnacek
On Tue, Mar 19, 2019 at 12:47 AM Richard Guy Briggs  wrote:
> On 2019-03-18 21:02, Ondrej Mosnacek wrote:
> > On Fri, Mar 15, 2019 at 7:35 PM Richard Guy Briggs  wrote:
> > >
> > > Implement audit container identifier filtering using the AUDIT_CONTID
> > > field name to send an 8-character string representing a u64 since the
> > > value field is only u32.
> > >
> > > Sending it as two u32 was considered, but gathering and comparing two
> > > fields was more complex.
> > >
> > > The feature indicator is AUDIT_FEATURE_BITMAP_CONTAINERID.
> > >
> > > See: https://github.com/linux-audit/audit-kernel/issues/91
> > > See: https://github.com/linux-audit/audit-userspace/issues/40
> > > See: https://github.com/linux-audit/audit-testsuite/issues/64
> > > See: 
> > > https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> > > Signed-off-by: Richard Guy Briggs 
> > > Acked-by: Serge Hallyn 
> > > ---
> > >  include/linux/audit.h  |  1 +
> > >  include/uapi/linux/audit.h |  5 -
> > >  kernel/audit.h |  1 +
> > >  kernel/auditfilter.c   | 47 
> > > ++
> > >  kernel/auditsc.c   |  3 +++
> > >  5 files changed, 56 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > > index 6db5aba7cc01..fa19fa408931 100644
> > > --- a/include/linux/audit.h
> > > +++ b/include/linux/audit.h
> > > @@ -77,6 +77,7 @@ struct audit_field {
> > > u32 type;
> > > union {
> > > u32 val;
> > > +   u64 val64;
> > > kuid_t  uid;
> > > kgid_t  gid;
> > > struct {
> > > diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> > > index a6383e28b2c8..741ab6f38294 100644
> > > --- a/include/uapi/linux/audit.h
> > > +++ b/include/uapi/linux/audit.h
> > > @@ -265,6 +265,7 @@
> > >  #define AUDIT_LOGINUID_SET 24
> > >  #define AUDIT_SESSIONID25  /* Session ID */
> > >  #define AUDIT_FSTYPE   26  /* FileSystem Type */
> > > +#define AUDIT_CONTID   27  /* Container ID */
> > >
> > > /* These are ONLY useful when checking
> > >  * at syscall exit time (AUDIT_AT_EXIT). 
> > > */
> > > @@ -345,6 +346,7 @@ enum {
> > >  #define AUDIT_FEATURE_BITMAP_SESSIONID_FILTER  0x0010
> > >  #define AUDIT_FEATURE_BITMAP_LOST_RESET0x0020
> > >  #define AUDIT_FEATURE_BITMAP_FILTER_FS 0x0040
> > > +#define AUDIT_FEATURE_BITMAP_CONTAINERID   0x0080
> > >
> > >  #define AUDIT_FEATURE_BITMAP_ALL (AUDIT_FEATURE_BITMAP_BACKLOG_LIMIT | \
> > >   AUDIT_FEATURE_BITMAP_BACKLOG_WAIT_TIME 
> > > | \
> > > @@ -352,7 +354,8 @@ enum {
> > >   AUDIT_FEATURE_BITMAP_EXCLUDE_EXTEND | \
> > >   AUDIT_FEATURE_BITMAP_SESSIONID_FILTER | 
> > > \
> > >   AUDIT_FEATURE_BITMAP_LOST_RESET | \
> > > - AUDIT_FEATURE_BITMAP_FILTER_FS)
> > > + AUDIT_FEATURE_BITMAP_FILTER_FS | \
> > > + AUDIT_FEATURE_BITMAP_CONTAINERID)
> > >
> > >  /* deprecated: AUDIT_VERSION_* */
> > >  #define AUDIT_VERSION_LATEST   AUDIT_FEATURE_BITMAP_ALL
> > > diff --git a/kernel/audit.h b/kernel/audit.h
> > > index 2a1a8b8a8019..3a40b608bf8d 100644
> > > --- a/kernel/audit.h
> > > +++ b/kernel/audit.h
> > > @@ -230,6 +230,7 @@ static inline int audit_hash_ino(u32 ino)
> > >
> > >  extern int audit_match_class(int class, unsigned syscall);
> > >  extern int audit_comparator(const u32 left, const u32 op, const u32 
> > > right);
> > > +extern int audit_comparator64(const u64 left, const u32 op, const u64 
> > > right);
> > >  extern int audit_uid_comparator(kuid_t left, u32 op, kuid_t right);
> > >  extern int audit_gid_comparator(kgid_t left, u32 op, kgid_t right);
> > >  extern int parent_len(const char *path);
> > > diff --git a/kernel/auditfilter.c b/kernel/au

Re: [PATCH ghak90 V5 07/10] audit: add containerid support for user records

2019-03-27 Thread Ondrej Mosnacek
On Fri, Mar 15, 2019 at 7:34 PM Richard Guy Briggs  wrote:
> Add audit container identifier auxiliary record to user event standalone
> records.
>
> Signed-off-by: Richard Guy Briggs 

Reviewed-by: Ondrej Mosnacek 

> ---
>  kernel/audit.c | 13 ++---
>  1 file changed, 6 insertions(+), 7 deletions(-)
>
> diff --git a/kernel/audit.c b/kernel/audit.c
> index cfa659b3f6c4..cf448599ef34 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -1142,12 +1142,6 @@ static void audit_log_common_recv_msg(struct 
> audit_context *context,
> audit_log_task_context(*ab);
>  }
>
> -static inline void audit_log_user_recv_msg(struct audit_buffer **ab,
> -  u16 msg_type)
> -{
> -   audit_log_common_recv_msg(NULL, ab, msg_type);
> -}
> -
>  int is_audit_feature_set(int i)
>  {
> return af.features & AUDIT_FEATURE_TO_MASK(i);
> @@ -1409,13 +1403,16 @@ static int audit_receive_msg(struct sk_buff *skb, 
> struct nlmsghdr *nlh)
>
> err = audit_filter(msg_type, AUDIT_FILTER_USER);
> if (err == 1) { /* match or error */
> +   struct audit_context *context;
> +
> err = 0;
> if (msg_type == AUDIT_USER_TTY) {
> err = tty_audit_push();
> if (err)
> break;
> }
> -   audit_log_user_recv_msg(, msg_type);
> +   context = audit_alloc_local(GFP_KERNEL);
> +   audit_log_common_recv_msg(context, , msg_type);
> if (msg_type != AUDIT_USER_TTY)
> audit_log_format(ab, " msg='%.*s'",
>  AUDIT_MESSAGE_TEXT_MAX,
> @@ -1431,6 +1428,8 @@ static int audit_receive_msg(struct sk_buff *skb, 
> struct nlmsghdr *nlh)
> audit_log_n_untrustedstring(ab, data, size);
> }
> audit_log_end(ab);
> +   audit_log_contid(context, audit_get_contid(current));
> +   audit_free_context(context);
> }
> break;
> case AUDIT_ADD_RULE:
> --
> 1.8.3.1
>


-- 
Ondrej Mosnacek 
Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [PATCH ghak90 V5 06/10] audit: add support for non-syscall auxiliary records

2019-03-27 Thread Ondrej Mosnacek
On Fri, Mar 15, 2019 at 7:34 PM Richard Guy Briggs  wrote:
> Standalone audit records have the timestamp and serial number generated
> on the fly and as such are unique, making them standalone.  This new
> function audit_alloc_local() generates a local audit context that will
> be used only for a standalone record and its auxiliary record(s).  The
> context is discarded immediately after the local associated records are
> produced.
>
> Signed-off-by: Richard Guy Briggs 
> Acked-by: Serge Hallyn 

Reviewed-by: Ondrej Mosnacek 

> ---
>  include/linux/audit.h |  8 
>  kernel/audit.h|  1 +
>  kernel/auditsc.c  | 35 ++-
>  3 files changed, 39 insertions(+), 5 deletions(-)
>
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index ebd6625ca80e..6db5aba7cc01 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -285,6 +285,8 @@ static inline void audit_log_contid(struct audit_context 
> *context, u64 contid)
>
>  /* These are defined in auditsc.c */
> /* Public API */
> +extern struct audit_context *audit_alloc_local(gfp_t gfpflags);
> +extern void audit_free_context(struct audit_context *context);
>  extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long 
> a1,
>   unsigned long a2, unsigned long a3);
>  extern void __audit_syscall_exit(int ret_success, long ret_value);
> @@ -512,6 +514,12 @@ static inline void audit_fanotify(unsigned int response)
>  extern int audit_n_rules;
>  extern int audit_signals;
>  #else /* CONFIG_AUDITSYSCALL */
> +static inline struct audit_context *audit_alloc_local(gfp_t gfpflags)
> +{
> +   return NULL;
> +}
> +static inline void audit_free_context(struct audit_context *context)
> +{ }
>  static inline void audit_syscall_entry(int major, unsigned long a0,
>unsigned long a1, unsigned long a2,
>unsigned long a3)
> diff --git a/kernel/audit.h b/kernel/audit.h
> index c5ac6436317e..2a1a8b8a8019 100644
> --- a/kernel/audit.h
> +++ b/kernel/audit.h
> @@ -111,6 +111,7 @@ struct audit_proctitle {
>  struct audit_context {
> int dummy;  /* must be the first element */
> int in_syscall; /* 1 if task is in a syscall */
> +   boollocal;  /* local context needed */
> enum audit_statestate, current_state;
> unsigned intserial; /* serial number for record */
> int major;  /* syscall number */
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index f04e115df5dc..aa5d13b4fbbb 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -872,11 +872,13 @@ static inline void audit_free_aux(struct audit_context 
> *context)
> }
>  }
>
> -static inline struct audit_context *audit_alloc_context(enum audit_state 
> state)
> +static inline struct audit_context *audit_alloc_context(enum audit_state 
> state,
> +   gfp_t gfpflags)
>  {
> struct audit_context *context;
>
> -   context = kzalloc(sizeof(*context), GFP_KERNEL);
> +   /* We can be called in atomic context via audit_tg() */
> +   context = kzalloc(sizeof(*context), gfpflags);
> if (!context)
> return NULL;
> context->state = state;
> @@ -912,7 +914,8 @@ int audit_alloc_syscall(struct task_struct *tsk)
> return 0;
> }
>
> -   if (!(context = audit_alloc_context(state))) {
> +   context = audit_alloc_context(state, GFP_KERNEL);
> +   if (!context) {
> kfree(key);
> audit_log_lost("out of memory in audit_alloc_syscall");
> return -ENOMEM;
> @@ -924,8 +927,29 @@ int audit_alloc_syscall(struct task_struct *tsk)
> return 0;
>  }
>
> -static inline void audit_free_context(struct audit_context *context)
> +struct audit_context *audit_alloc_local(gfp_t gfpflags)
>  {
> +   struct audit_context *context = NULL;
> +
> +   if (!audit_ever_enabled)
> +   goto out; /* Return if not auditing. */
> +   context = audit_alloc_context(AUDIT_RECORD_CONTEXT, gfpflags);
> +   if (!context) {
> +   audit_log_lost("out of memory in audit_alloc_local");
> +   goto out;
> +   }
> +   context->serial = audit_serial();
> +   ktime_get_coarse_real_ts64(>ctime);
> +   context->local = true;
> +out:
> +   return context;
> +}
> +EXPORT_SYMBOL(audit_alloc_lo

Re: [PATCH ghak90 V5 05/10] audit: add containerid support for ptrace and signals

2019-03-27 Thread Ondrej Mosnacek
 context->target_sessionid,
> - context->target_sid, context->target_comm))
> +   if (context->target_pid) {
> +   if (audit_log_pid_context(context, context->target_pid,
> + context->target_auid,
> + context->target_uid,
> + context->target_sessionid,
> + context->target_sid,
> + context->target_comm))
> call_panic = 1;
> +   audit_log_contid(context, context->target_cid);
> +   }
>
> if (context->pwd.dentry && context->pwd.mnt) {
> ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
> @@ -2360,6 +2367,7 @@ void __audit_ptrace(struct task_struct *t)
> context->target_uid = task_uid(t);
> context->target_sessionid = audit_get_sessionid(t);
> security_task_getsecid(t, >target_sid);
> +   context->target_cid = audit_get_contid(t);
> memcpy(context->target_comm, t->comm, TASK_COMM_LEN);
>  }
>
> @@ -2387,6 +2395,7 @@ int audit_signal_info(int sig, struct task_struct *t)
> else
> audit_sig_uid = uid;
> security_task_getsecid(current, _sig_sid);
> +   audit_sig_cid = audit_get_contid(current);
> }
>
> if (!audit_signals || audit_dummy_context())
> @@ -2400,6 +2409,7 @@ int audit_signal_info(int sig, struct task_struct *t)
> ctx->target_uid = t_uid;
> ctx->target_sessionid = audit_get_sessionid(t);
> security_task_getsecid(t, >target_sid);
> +   ctx->target_cid = audit_get_contid(t);
> memcpy(ctx->target_comm, t->comm, TASK_COMM_LEN);
> return 0;
> }
> @@ -2421,6 +2431,7 @@ int audit_signal_info(int sig, struct task_struct *t)
> axp->target_uid[axp->pid_count] = t_uid;
> axp->target_sessionid[axp->pid_count] = audit_get_sessionid(t);
> security_task_getsecid(t, >target_sid[axp->pid_count]);
> +   axp->target_cid[axp->pid_count] = audit_get_contid(t);
> memcpy(axp->target_comm[axp->pid_count], t->comm, TASK_COMM_LEN);
> axp->pid_count++;
>
> --
> 1.8.3.1
>


-- 
Ondrej Mosnacek 
Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [PATCH ghak90 V5 04/10] audit: log container info of syscalls

2019-03-27 Thread Ondrej Mosnacek
On Fri, Mar 15, 2019 at 7:34 PM Richard Guy Briggs  wrote:
> Create a new audit record AUDIT_CONTAINER_ID to document the audit
> container identifier of a process if it is present.
>
> Called from audit_log_exit(), syscalls are covered.
>
> A sample raw event:
> type=SYSCALL msg=audit(1519924845.499:257): arch=c03e syscall=257 
> success=yes exit=3 a0=ff9c a1=56374e1cef30 a2=241 a3=1b6 items=2 ppid=606 
> pid=635 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 
> tty=pts0 ses=3 comm="bash" exe="/usr/bin/bash" 
> subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 
> key="tmpcontainerid"
> type=CWD msg=audit(1519924845.499:257): cwd="/root"
> type=PATH msg=audit(1519924845.499:257): item=0 name="/tmp/" inode=13863 
> dev=00:27 mode=041777 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:tmp_t:s0 
> nametype= PARENT cap_fp=0 cap_fi=0 cap_fe=0 cap_fver=0
> type=PATH msg=audit(1519924845.499:257): item=1 name="/tmp/tmpcontainerid" 
> inode=17729 dev=00:27 mode=0100644 ouid=0 ogid=0 rdev=00:00 
> obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE cap_fp=0 cap_fi=0 
> cap_fe=0 cap_fver=0
> type=PROCTITLE msg=audit(1519924845.499:257): 
> proctitle=62617368002D6300736C65657020313B206563686F2074657374203E202F746D702F746D70636F6E7461696E65726964
> type=CONTAINER_ID msg=audit(1519924845.499:257): contid=123458
>
> See: https://github.com/linux-audit/audit-kernel/issues/90
> See: https://github.com/linux-audit/audit-userspace/issues/51
> See: https://github.com/linux-audit/audit-testsuite/issues/64
> See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
> Signed-off-by: Richard Guy Briggs 
> Acked-by: Serge Hallyn 
> Acked-by: Steve Grubb 
> Signed-off-by: Richard Guy Briggs 

Barring one minor nit below,

Reviewed-by: Ondrej Mosnacek 

> ---
>  include/linux/audit.h  |  5 +
>  include/uapi/linux/audit.h |  1 +
>  kernel/audit.c | 21 +
>  kernel/auditsc.c   |  2 ++
>  4 files changed, 29 insertions(+)
>
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 301337776193..43438192ca2a 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -199,6 +199,8 @@ static inline u64 audit_get_contid(struct task_struct 
> *tsk)
> return tsk->audit->contid;
>  }
>
> +extern void audit_log_contid(struct audit_context *context, u64 contid);
> +
>  extern u32 audit_enabled;
>  #else /* CONFIG_AUDIT */
>  static inline int audit_alloc(struct task_struct *task)
> @@ -265,6 +267,9 @@ static inline u64 audit_get_contid(struct task_struct 
> *tsk)
> return AUDIT_CID_UNSET;
>  }
>
> +static inline void audit_log_contid(struct audit_context *context, u64 
> contid)
> +{ }
> +
>  #define audit_enabled AUDIT_OFF
>  #endif /* CONFIG_AUDIT */
>
> diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> index d475cf3b4d7f..a6383e28b2c8 100644
> --- a/include/uapi/linux/audit.h
> +++ b/include/uapi/linux/audit.h
> @@ -115,6 +115,7 @@
>  #define AUDIT_REPLACE  1329/* Replace auditd if this packet 
> unanswerd */
>  #define AUDIT_KERN_MODULE  1330/* Kernel Module events */
>  #define AUDIT_FANOTIFY 1331/* Fanotify access decision */
> +#define AUDIT_CONTAINER_ID 1332/* Container ID */
>
>  #define AUDIT_AVC  1400/* SE Linux avc denial or grant */
>  #define AUDIT_SELINUX_ERR  1401/* Internal SE Linux Errors */
> diff --git a/kernel/audit.c b/kernel/audit.c
> index b5c702abeb42..8cc0e88d7f2a 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -2127,6 +2127,27 @@ void audit_log_session_info(struct audit_buffer *ab)
> audit_log_format(ab, "auid=%u ses=%u", auid, sessionid);
>  }
>
> +/*
> + * audit_log_contid - report container info
> + * @context: task or local context for record
> + * @contid: container ID to report
> + */
> +void audit_log_contid(struct audit_context *context, u64 contid)
> +{
> +   struct audit_buffer *ab;
> +
> +   if (!audit_contid_valid(contid))
> +   return;
> +   /* Generate AUDIT_CONTAINER_ID record with container ID */
> +   ab = audit_log_start(context, GFP_KERNEL, AUDIT_CONTAINER_ID);
> +   if (!ab)
> +   return;
> +   audit_log_format(ab, "contid=%llu", contid);

Just realized that you *might* get a compiler/static checker warning
since u64 could technically be something else than unsigned long long
on some arches... maybe this is not case in the kernel, but might be
safer to cast it to unsigned long long before passing to
audit_log_form

Re: [PATCH ghak90 V5 02/10] audit: add container id

2019-03-27 Thread Ondrej Mosnacek
On Fri, Mar 15, 2019 at 7:33 PM Richard Guy Briggs  wrote:
> Implement the proc fs write to set the audit container identifier of a
> process, emitting an AUDIT_CONTAINER_OP record to document the event.
>
> This is a write from the container orchestrator task to a proc entry of
> the form /proc/PID/audit_containerid where PID is the process ID of the
> newly created task that is to become the first task in a container, or
> an additional task added to a container.
>
> The write expects up to a u64 value (unset: 18446744073709551615).
>
> The writer must have capability CAP_AUDIT_CONTROL.
>
> This will produce a record such as this:
>   type=CONTAINER_OP msg=audit(2018-06-06 12:39:29.636:26949) : op=set 
> opid=2209 old-contid=18446744073709551615 contid=123456 pid=628 auid=root 
> uid=root tty=ttyS0 ses=1 
> subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 comm=bash 
> exe=/usr/bin/bash res=yes
>
> The "op" field indicates an initial set.  The "pid" to "ses" fields are
> the orchestrator while the "opid" field is the object's PID, the process
> being "contained".  Old and new audit container identifier values are
> given in the "contid" fields, while res indicates its success.
>
> It is not permitted to unset the audit container identifier.
> A child inherits its parent's audit container identifier.
>
> See: https://github.com/linux-audit/audit-kernel/issues/90
> See: https://github.com/linux-audit/audit-userspace/issues/51
> See: https://github.com/linux-audit/audit-testsuite/issues/64
> See: https://github.com/linux-audit/audit-kernel/wiki/RFE-Audit-Container-ID
>
> Signed-off-by: Richard Guy Briggs 
> Acked-by: Serge Hallyn 
> Acked-by: Steve Grubb 
> Signed-off-by: Richard Guy Briggs 

Note that you have duplicate Signed-off here ^^

Took me a while to understand the flow in audit_set_contid(), but once
understood it all made perfect sense, so:

Reviewed-by: Ondrej Mosnacek 


> ---
>  fs/proc/base.c | 36 
>  include/linux/audit.h  | 25 +
>  include/uapi/linux/audit.h |  2 ++
>  kernel/audit.c | 68 
> ++
>  4 files changed, 131 insertions(+)
>
> diff --git a/fs/proc/base.c b/fs/proc/base.c
> index a23651ce6960..2505c46c8701 100644
> --- a/fs/proc/base.c
> +++ b/fs/proc/base.c
> @@ -1294,6 +1294,40 @@ static ssize_t proc_sessionid_read(struct file * file, 
> char __user * buf,
> .read   = proc_sessionid_read,
> .llseek = generic_file_llseek,
>  };
> +
> +static ssize_t proc_contid_write(struct file *file, const char __user *buf,
> +  size_t count, loff_t *ppos)
> +{
> +   struct inode *inode = file_inode(file);
> +   u64 contid;
> +   int rv;
> +   struct task_struct *task = get_proc_task(inode);
> +
> +   if (!task)
> +   return -ESRCH;
> +   if (*ppos != 0) {
> +   /* No partial writes. */
> +   put_task_struct(task);
> +   return -EINVAL;
> +   }
> +
> +   rv = kstrtou64_from_user(buf, count, 10, );
> +   if (rv < 0) {
> +   put_task_struct(task);
> +   return rv;
> +   }
> +
> +   rv = audit_set_contid(task, contid);
> +   put_task_struct(task);
> +   if (rv < 0)
> +   return rv;
> +   return count;
> +}
> +
> +static const struct file_operations proc_contid_operations = {
> +   .write  = proc_contid_write,
> +   .llseek = generic_file_llseek,
> +};
>  #endif
>
>  #ifdef CONFIG_FAULT_INJECTION
> @@ -3005,6 +3039,7 @@ static int proc_stack_depth(struct seq_file *m, struct 
> pid_namespace *ns,
>  #ifdef CONFIG_AUDIT
> REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
> REG("sessionid",  S_IRUGO, proc_sessionid_operations),
> +   REG("audit_containerid", S_IWUSR, proc_contid_operations),
>  #endif
>  #ifdef CONFIG_FAULT_INJECTION
> REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
> @@ -3393,6 +3428,7 @@ static int proc_tid_comm_permission(struct inode 
> *inode, int mask)
>  #ifdef CONFIG_AUDIT
> REG("loginuid",  S_IWUSR|S_IRUGO, proc_loginuid_operations),
> REG("sessionid",  S_IRUGO, proc_sessionid_operations),
> +   REG("audit_containerid", S_IWUSR, proc_contid_operations),
>  #endif
>  #ifdef CONFIG_FAULT_INJECTION
> REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
> diff --git a/incl

Re: [PATCH ghak90 V5 01/10] audit: collect audit task parameters

2019-03-27 Thread Ondrej Mosnacek
On Fri, Mar 15, 2019 at 7:33 PM Richard Guy Briggs  wrote:
> The audit-related parameters in struct task_struct should ideally be
> collected together and accessed through a standard audit API.
>
> Collect the existing loginuid, sessionid and audit_context together in a
> new struct audit_task_info called "audit" in struct task_struct.
>
> Use kmem_cache to manage this pool of memory.
> Un-inline audit_free() to be able to always recover that memory.
>
> Please see the upstream github issue
> https://github.com/linux-audit/audit-kernel/issues/81
> but that issue has been closed with this patch included with
> https://github.com/linux-audit/audit-kernel/issues/90
>
> Signed-off-by: Richard Guy Briggs 

Reviewed-by: Ondrej Mosnacek 


> ---
>  include/linux/audit.h | 49 +++
>  include/linux/sched.h |  7 +
>  init/init_task.c  |  3 +--
>  init/main.c   |  2 ++
>  kernel/audit.c| 71 
> +--
>  kernel/audit.h|  5 
>  kernel/auditsc.c  | 26 ++-
>  kernel/fork.c |  1 -
>  8 files changed, 124 insertions(+), 40 deletions(-)
>
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 1e69d9fe16da..bde346e73f0c 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -86,6 +86,16 @@ struct audit_field {
> u32 op;
>  };
>
> +struct audit_task_info {
> +   kuid_t  loginuid;
> +   unsigned intsessionid;
> +#ifdef CONFIG_AUDITSYSCALL
> +   struct audit_context*ctx;
> +#endif
> +};
> +
> +extern struct audit_task_info init_struct_audit;
> +
>  extern int is_audit_feature_set(int which);
>
>  extern int __init audit_register_class(int class, unsigned *list);
> @@ -122,6 +132,9 @@ struct audit_field {
>  #ifdef CONFIG_AUDIT
>  /* These are defined in audit.c */
> /* Public API */
> +extern int  audit_alloc(struct task_struct *task);
> +extern void audit_free(struct task_struct *task);
> +extern void __init audit_task_init(void);
>  extern __printf(4, 5)
>  void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
>const char *fmt, ...);
> @@ -164,16 +177,28 @@ extern void   audit_log_key(struct 
> audit_buffer *ab,
>
>  static inline kuid_t audit_get_loginuid(struct task_struct *tsk)
>  {
> -   return tsk->loginuid;
> +   if (!tsk->audit)
> +   return INVALID_UID;
> +   return tsk->audit->loginuid;
>  }
>
>  static inline unsigned int audit_get_sessionid(struct task_struct *tsk)
>  {
> -   return tsk->sessionid;
> +   if (!tsk->audit)
> +   return AUDIT_SID_UNSET;
> +   return tsk->audit->sessionid;
>  }
>
>  extern u32 audit_enabled;
>  #else /* CONFIG_AUDIT */
> +static inline int audit_alloc(struct task_struct *task)
> +{
> +   return 0;
> +}
> +static inline void audit_free(struct task_struct *task)
> +{ }
> +static inline void __init audit_task_init(void)
> +{ }
>  static inline __printf(4, 5)
>  void audit_log(struct audit_context *ctx, gfp_t gfp_mask, int type,
>const char *fmt, ...)
> @@ -239,8 +264,6 @@ static inline unsigned int audit_get_sessionid(struct 
> task_struct *tsk)
>
>  /* These are defined in auditsc.c */
> /* Public API */
> -extern int  audit_alloc(struct task_struct *task);
> -extern void __audit_free(struct task_struct *task);
>  extern void __audit_syscall_entry(int major, unsigned long a0, unsigned long 
> a1,
>   unsigned long a2, unsigned long a3);
>  extern void __audit_syscall_exit(int ret_success, long ret_value);
> @@ -263,12 +286,14 @@ extern void audit_seccomp_actions_logged(const char 
> *names,
>
>  static inline void audit_set_context(struct task_struct *task, struct 
> audit_context *ctx)
>  {
> -   task->audit_context = ctx;
> +   task->audit->ctx = ctx;
>  }
>
>  static inline struct audit_context *audit_context(void)
>  {
> -   return current->audit_context;
> +   if (!current->audit)
> +   return NULL;
> +   return current->audit->ctx;
>  }
>
>  static inline bool audit_dummy_context(void)
> @@ -276,11 +301,7 @@ static inline bool audit_dummy_context(void)
> void *p = audit_context();
> return !p || *(int *)p;
>  }
> -static inline void audit_free(struct task_struct *task)
> -{
> -   if (unlikely(task->audit_context))
> -   __audi

Re: [PATCH ghak90 V5 08/10] audit: add containerid filtering

2019-03-18 Thread Ondrej Mosnacek
f (IS_ERR(str))
> +   goto exit_free;
> +   f->val64 = ((u64 *)str)[0];
> +   break;
> }
> }
>
> @@ -664,6 +673,11 @@ static struct audit_rule_data 
> *audit_krule_to_data(struct audit_krule *krule)
> data->buflen += data->values[i] =
> audit_pack_string(, 
> audit_mark_path(krule->exe));
> break;
> +   case AUDIT_CONTID:
> +   data->buflen += data->values[i] = sizeof(u64);
> +   for (i = 0; i < sizeof(u64); i++)
> +   ((char *)bufp)[i] = ((char *)>val64)[i];

How about just:

memcpy(bufp, >val64, sizeof(u64));

instead of the awkward for loop? It is simpler and also more in line
with the code in audit_pack_string().

Also, doesn't this loop interfere with the outer loop that also uses
'i' as the control variable?

> +   break;
> case AUDIT_LOGINUID_SET:
> if (krule->pflags & AUDIT_LOGINUID_LEGACY && !f->val) 
> {
> data->fields[i] = AUDIT_LOGINUID;
> @@ -750,6 +764,10 @@ static int audit_compare_rule(struct audit_krule *a, 
> struct audit_krule *b)
> if (!gid_eq(a->fields[i].gid, b->fields[i].gid))
> return 1;
> break;
> +   case AUDIT_CONTID:
> +   if (a->fields[i].val64 != b->fields[i].val64)
> +   return 1;
> +   break;
> default:
> if (a->fields[i].val != b->fields[i].val)
> return 1;
> @@ -1206,6 +1224,31 @@ int audit_comparator(u32 left, u32 op, u32 right)
> }
>  }
>
> +int audit_comparator64(u64 left, u32 op, u64 right)
> +{
> +   switch (op) {
> +   case Audit_equal:
> +   return (left == right);
> +   case Audit_not_equal:
> +   return (left != right);
> +   case Audit_lt:
> +   return (left < right);
> +   case Audit_le:
> +   return (left <= right);
> +   case Audit_gt:
> +   return (left > right);
> +   case Audit_ge:
> +   return (left >= right);
> +   case Audit_bitmask:
> +   return (left & right);
> +   case Audit_bittest:
> +   return ((left & right) == right);
> +   default:
> +   BUG();
> +   return 0;
> +   }
> +}
> +
>  int audit_uid_comparator(kuid_t left, u32 op, kuid_t right)
>  {
> switch (op) {
> @@ -1344,6 +1387,10 @@ int audit_filter(int msgtype, unsigned int listtype)
> result = 
> audit_comparator(audit_loginuid_set(current),
>   f->op, f->val);
> break;
> +   case AUDIT_CONTID:
> +   result = 
> audit_comparator64(audit_get_contid(current),
> + f->op, 
> f->val64);
> +   break;
> case AUDIT_MSGTYPE:
> result = audit_comparator(msgtype, f->op, 
> f->val);
> break;
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index aa5d13b4fbbb..2d74238e9638 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -616,6 +616,9 @@ static int audit_filter_rules(struct task_struct *tsk,
> case AUDIT_LOGINUID_SET:
> result = audit_comparator(audit_loginuid_set(tsk), 
> f->op, f->val);
> break;
> +   case AUDIT_CONTID:
> +   result = audit_comparator64(audit_get_contid(tsk), 
> f->op, f->val64);
> +   break;
> case AUDIT_SUBJ_USER:
> case AUDIT_SUBJ_ROLE:
> case AUDIT_SUBJ_TYPE:
> --
> 1.8.3.1
>


-- 
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [RFC PATCH ghak10 v6 0/2] audit: Log changes that can affect the system clock

2019-03-11 Thread Ondrej Mosnacek
On Fri, Mar 8, 2019 at 9:26 PM Richard Guy Briggs  wrote:
> On 2019-03-07 13:32, Ondrej Mosnacek wrote:
> > This patchset implements auditing of (syscall-triggered) changes that
> > can modify or indirectly affect the system clock. Some of these
> > changes can already be detected by simply logging relevant syscalls,
> > but this has some disadvantages:
> >   a) It is usually not possible to find out from the syscall records
> >  the amount by which the time was shifted.
> >   b) Syscalls like adjtimex(2) or clock_adjtime(2) can be used also
> >  for read-only operations, which might flood the audit log with
> >  false positives. (Note that these patches don't solve this
> >  problem yet due to the limitations of current record filtering
> >  capabilities.)
> >
> > The main motivation is to provide better reliability of timestamps
> > on the system as mandated by the FPT_STM.1 security functional
> > requirement from Common Criteria. This requirement apparently demands
> > that it is possible to reconstruct from audit trail the old and new
> > values of the time when it is adjusted (see [1]).
> >
> > The current version of the patchset logs the following changes:
> >   - direct setting of system time to a given value
> >   - direct injection of timekeeping offset
> >   - adjustment of timekeeping's TAI offset
> >   - NTP value adjustments:
> > - time_offset
> > - time_freq
> > - time_status
> > - time_adjust
> > - tick_usec
> >
> > Changes to the following NTP values are not logged, as they are not
> > important for security:
> >   - time_maxerror
> >   - time_esterror
> >   - time_constant
> >
> > Audit kernel GitHub issue: 
> > https://github.com/linux-audit/audit-kernel/issues/10
> > Audit kernel RFE page: 
> > https://github.com/linux-audit/audit-kernel/wiki/RFE-More-detailed-auditing-of-changes-to-system-clock
> >
> > Testing: Passed audit-testuite; functional tests TBD
>
> Reviewed-by: Richard Guy Briggs 
>
> How do you plan to test this in the audit-testsuite?

My plan is to add a new subtest which will use a short C program that
calls the relevant syscalls (they are listed in patch 1/2) directly
and will check if they produce the expected records. I outlined some
specific things to be tested in the RFE page.

>
> > Changes in v6:
> >   - Reorganized the patches to group changes by record type, not
> > kernel subsytem, as suggested in earlier discussions
> >   - Added checks to ignore no-change events (new value == old value)
> >   - Added TIME_INJOFFSET logging also to do_settimeofday64() to cover
> > syscalls such as settimeofday(2), stime(2), clock_settime(2)
> >   - Created an RFE page on audit-kernel GitHub
> > TODO:
> >   - tests for audit-testsuite
> >
> > v5: https://www.redhat.com/archives/linux-audit/2018-August/msg00039.html
> > Changes in v5:
> >   - Dropped logging of some less important changes and update commit 
> > messages
> >   - No longer mark the patchset as RFC
> >
> > v4: https://www.redhat.com/archives/linux-audit/2018-August/msg00023.html
> > Changes in v4:
> >   - Squashed first two patches into one
> >   - Renamed ADJNTPVAL's "type" field to "op" to align with audit record
> > conventions
> >   - Minor commit message editing
> >   - Cc timekeeping/NTP people for feedback
> >
> > v3: https://www.redhat.com/archives/linux-audit/2018-July/msg1.html
> > Changes in v3:
> >   - Switched to separate records for each variable
> >   - Both old and new value is now reported for each change
> >   - Injecting offset is reported via a separate record (since this
> > offset consists of two values and is added directly to the clock,
> > i.e. it doesn't make sense to log old and new value)
> >   - Added example records produced by chronyd -q (see the commit message
> > of the last patch)
> >
> > v2: https://www.redhat.com/archives/linux-audit/2018-June/msg00114.html
> > Changes in v2:
> >   - The audit_adjtime() function has been modified to only log those
> > fields that contain values that are actually used, resulting in more
> > compact records.
> >   - The audit_adjtime() call has been moved to do_adjtimex() in
> > timekeeping.c
> >   - Added an additional patch (for review) that simplifies the detection
> > if the syscall is read-only.
> >
> > v1: https://www.redhat.com/archives/linux-audit/2018-June/msg00095.html
> >
> > [1] http

[RFC PATCH ghak10 v6 2/2] ntp: Audit NTP parameters adjustment

2019-03-07 Thread Ondrej Mosnacek
ap seconds and it also enables/
   disables synchronization of the hardware real-time
   clock (AUDITED)
time_maxerror, time_esterror -- change error estimates used to
inform userspace applications
(NOT AUDITED)
time_constant -- controls the speed of the clock adjustments that
 are made when time_offset is set (NOT AUDITED)
time_adjust -- can temporarily speed up or slow down the clock by up
   to 0.05% (AUDITED)
tick_usec -- a more extreme version of time_freq; can speed up or
 slow down the clock by up to 10% (AUDITED)

Signed-off-by: Ondrej Mosnacek 
---
 include/linux/audit.h  | 14 ++
 include/uapi/linux/audit.h |  1 +
 kernel/auditsc.c   |  7 +++
 kernel/time/ntp.c  | 38 ++
 4 files changed, 52 insertions(+), 8 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 43a60fbe74be..0f67964544cc 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -367,6 +367,7 @@ extern void __audit_mmap_fd(int fd, int flags);
 extern void __audit_log_kern_module(char *name);
 extern void __audit_fanotify(unsigned int response);
 extern void __audit_tk_injoffset(struct timespec64 offset);
+extern void __audit_ntp_adjust(const char *type, s64 oldval, s64 newval);
 
 static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
 {
@@ -479,6 +480,16 @@ static inline void audit_tk_injoffset(struct timespec64 
offset)
__audit_tk_injoffset(offset);
 }
 
+static inline void audit_ntp_adjust(const char *type, s64 oldval, s64 newval)
+{
+   /* ignore no-op events */
+   if (newval == oldval)
+   return;
+
+   if (!audit_dummy_context())
+   __audit_ntp_adjust(type, oldval, newval);
+}
+
 extern int audit_n_rules;
 extern int audit_signals;
 #else /* CONFIG_AUDITSYSCALL */
@@ -595,6 +606,9 @@ static inline void audit_fanotify(unsigned int response)
 static inline void audit_tk_injoffset(struct timespec64 offset)
 { }
 
+static inline void audit_ntp_adjust(const char *type, s64 oldval, s64 newval)
+{ }
+
 static inline void audit_ptrace(struct task_struct *t)
 { }
 #define audit_n_rules 0
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 2167d55bc800..e9781f0385eb 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -115,6 +115,7 @@
 #define AUDIT_KERN_MODULE  1330/* Kernel Module events */
 #define AUDIT_FANOTIFY 1331/* Fanotify access decision */
 #define AUDIT_TIME_INJOFFSET   1332/* Timekeeping offset injected */
+#define AUDIT_TIME_ADJNTPVAL   1333/* NTP value adjustment */
 
 #define AUDIT_AVC  1400/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR  1401/* Internal SE Linux Errors */
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 781336d0f2de..946806174cd9 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2520,6 +2520,13 @@ void __audit_tk_injoffset(struct timespec64 offset)
  "sec=%lli nsec=%li", (long long)offset.tv_sec, 
offset.tv_nsec);
 }
 
+void __audit_ntp_adjust(const char *type, s64 oldval, s64 newval)
+{
+   audit_log(audit_context(), GFP_ATOMIC, AUDIT_TIME_ADJNTPVAL,
+ "op=%s old=%lli new=%lli", type,
+ (long long)oldval, (long long)newval);
+}
+
 static void audit_log_task(struct audit_buffer *ab)
 {
kuid_t auid, uid;
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 36a2bef00125..5f456a84151a 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -17,6 +17,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "ntp_internal.h"
 #include "timekeeping_internal.h"
@@ -293,6 +294,8 @@ static inline s64 ntp_update_offset_fll(s64 offset64, long 
secs)
 
 static void ntp_update_offset(long offset)
 {
+   s64 old_offset = time_offset;
+   s64 old_freq = time_freq;
s64 freq_adj;
s64 offset64;
long secs;
@@ -341,6 +344,9 @@ static void ntp_update_offset(long offset)
time_freq   = max(freq_adj, -MAXFREQ_SCALED);
 
time_offset = div_s64(offset64 << NTP_SCALE_SHIFT, NTP_INTERVAL_FREQ);
+
+   audit_ntp_adjust("offset", old_offset, time_offset);
+   audit_ntp_adjust("freq", old_freq, time_freq);
 }
 
 /**
@@ -658,21 +664,31 @@ static inline void process_adj_status(const struct timex 
*txc)
 
 static inline void process_adjtimex_modes(const struct timex *txc, s32 
*time_tai)
 {
-   if (txc->modes & ADJ_STATUS)
-   process_adj_status(txc);
+   if (txc->modes & (ADJ_STATUS | ADJ_NANO | ADJ_MICRO)) {
+   int old_status = time_status;
+
+   if (txc->modes & ADJ_STATUS)
+   process_adj_status(txc);
 
-   if (txc->modes & ADJ_NANO

[RFC PATCH ghak10 v6 0/2] audit: Log changes that can affect the system clock

2019-03-07 Thread Ondrej Mosnacek
This patchset implements auditing of (syscall-triggered) changes that
can modify or indirectly affect the system clock. Some of these
changes can already be detected by simply logging relevant syscalls,
but this has some disadvantages:
  a) It is usually not possible to find out from the syscall records
 the amount by which the time was shifted.
  b) Syscalls like adjtimex(2) or clock_adjtime(2) can be used also
 for read-only operations, which might flood the audit log with
 false positives. (Note that these patches don't solve this
 problem yet due to the limitations of current record filtering
 capabilities.)

The main motivation is to provide better reliability of timestamps
on the system as mandated by the FPT_STM.1 security functional
requirement from Common Criteria. This requirement apparently demands
that it is possible to reconstruct from audit trail the old and new
values of the time when it is adjusted (see [1]).

The current version of the patchset logs the following changes:
  - direct setting of system time to a given value
  - direct injection of timekeeping offset
  - adjustment of timekeeping's TAI offset
  - NTP value adjustments:
- time_offset
- time_freq
- time_status
- time_adjust
- tick_usec

Changes to the following NTP values are not logged, as they are not
important for security:
  - time_maxerror
  - time_esterror
  - time_constant

Audit kernel GitHub issue: https://github.com/linux-audit/audit-kernel/issues/10
Audit kernel RFE page: 
https://github.com/linux-audit/audit-kernel/wiki/RFE-More-detailed-auditing-of-changes-to-system-clock

Testing: Passed audit-testuite; functional tests TBD

Changes in v6:
  - Reorganized the patches to group changes by record type, not
kernel subsytem, as suggested in earlier discussions
  - Added checks to ignore no-change events (new value == old value)
  - Added TIME_INJOFFSET logging also to do_settimeofday64() to cover
syscalls such as settimeofday(2), stime(2), clock_settime(2)
  - Created an RFE page on audit-kernel GitHub
TODO:
  - tests for audit-testsuite

v5: https://www.redhat.com/archives/linux-audit/2018-August/msg00039.html
Changes in v5:
  - Dropped logging of some less important changes and update commit messages
  - No longer mark the patchset as RFC

v4: https://www.redhat.com/archives/linux-audit/2018-August/msg00023.html
Changes in v4:
  - Squashed first two patches into one
  - Renamed ADJNTPVAL's "type" field to "op" to align with audit record
conventions
  - Minor commit message editing
  - Cc timekeeping/NTP people for feedback

v3: https://www.redhat.com/archives/linux-audit/2018-July/msg1.html
Changes in v3:
  - Switched to separate records for each variable
  - Both old and new value is now reported for each change
  - Injecting offset is reported via a separate record (since this
offset consists of two values and is added directly to the clock,
i.e. it doesn't make sense to log old and new value)
  - Added example records produced by chronyd -q (see the commit message
of the last patch)

v2: https://www.redhat.com/archives/linux-audit/2018-June/msg00114.html
Changes in v2:
  - The audit_adjtime() function has been modified to only log those
fields that contain values that are actually used, resulting in more
compact records.
  - The audit_adjtime() call has been moved to do_adjtimex() in
timekeeping.c
  - Added an additional patch (for review) that simplifies the detection
if the syscall is read-only.

v1: https://www.redhat.com/archives/linux-audit/2018-June/msg00095.html

[1] https://www.niap-ccevs.org/MMO/PP/pp_ca_v2.1.pdf -- section 5.1,
table 4

Ondrej Mosnacek (2):
  timekeeping: Audit clock adjustments
  ntp: Audit NTP parameters adjustment

 include/linux/audit.h  | 29 +
 include/uapi/linux/audit.h |  2 ++
 kernel/auditsc.c   | 15 +++
 kernel/time/ntp.c  | 38 ++
 kernel/time/timekeeping.c  |  6 ++
 5 files changed, 82 insertions(+), 8 deletions(-)

-- 
2.20.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


[RFC PATCH ghak10 v6 1/2] timekeeping: Audit clock adjustments

2019-03-07 Thread Ondrej Mosnacek
Emit an audit record whenever the system clock is changed (i.e. shifted
by a non-zero offset) by a syscall from userspace. The syscalls than can
(at the time of writing) trigger such record are:
  - settimeofday(2), stime(2), clock_settime(2) -- via
do_settimeofday64()
  - adjtimex(2), clock_adjtime(2) -- via do_adjtimex()

The new records have type AUDIT_TIME_INJOFFSET and contain the following
fields:
  - sec -- the 'seconds' part of the offset
  - nsec -- the 'nanoseconds' part of the offset

For reference, running the following commands:

auditctl -D
auditctl -a exit,always -F arch=b64 -S adjtimex
chronyd -q

triggers (among others) a syscall that produces audit records like this:

type=TIME_INJOFFSET msg=audit(1530616049.652:13): sec=-16 nsec=124887145
type=SYSCALL msg=audit(1530616049.652:13): arch=c03e syscall=159 
success=yes exit=5 a0=7fff57e78270 a1=1 a2=fff0 a3=137b828205ca12 
items=0 ppid=626 pid=629 auid=0 uid=385 gid=382 euid=385 suid=385 fsuid=385 
egid=382 sgid=382 fsgid=382 tty=(none) ses=1 comm="chronyd" 
exe="/usr/sbin/chronyd" subj=system_u:system_r:kernel_t:s0 key=(null)
type=PROCTITLE msg=audit(1530616049.652:13): proctitle=6368726F6E7964002D71 cd 
/home/omosnace/Dokumenty/Kernel/worktrees/audit/src/kernel/time
s

The above records have been produced by the following syscall from
chronyd (as per strace output):

adjtimex({modes=ADJ_SETOFFSET|ADJ_NANO, offset=0, freq=750433, 
maxerror=1600, esterror=1600, status=STA_UNSYNC|STA_NANO, constant=2, 
precision=1, tolerance=32768000, time={tv_sec=1530616033, tv_usec=778717675}, 
tick=1, ppsfreq=0, jitter=0, shift=0, stabil=0, jitcnt=0, calcnt=0, 
errcnt=0, stbcnt=0, tai=0}) = 5 (TIME_ERROR)

(The struct timex fields above are from *after* the syscall was
executed, so they contain the current (new) values as set from the
kernel, except of the 'modes' field, which contains the original value
sent by the caller.)

Signed-off-by: Ondrej Mosnacek 
---
 include/linux/audit.h  | 15 +++
 include/uapi/linux/audit.h |  1 +
 kernel/auditsc.c   |  8 
 kernel/time/timekeeping.c  |  6 ++
 4 files changed, 30 insertions(+)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 1e69d9fe16da..43a60fbe74be 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -27,6 +27,7 @@
 #include 
 #include   /* LOOKUP_* */
 #include 
+#include 
 
 #define AUDIT_INO_UNSET ((unsigned long)-1)
 #define AUDIT_DEV_UNSET ((dev_t)-1)
@@ -365,6 +366,7 @@ extern void __audit_log_capset(const struct cred *new, 
const struct cred *old);
 extern void __audit_mmap_fd(int fd, int flags);
 extern void __audit_log_kern_module(char *name);
 extern void __audit_fanotify(unsigned int response);
+extern void __audit_tk_injoffset(struct timespec64 offset);
 
 static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
 {
@@ -467,6 +469,16 @@ static inline void audit_fanotify(unsigned int response)
__audit_fanotify(response);
 }
 
+static inline void audit_tk_injoffset(struct timespec64 offset)
+{
+   /* ignore no-op events */
+   if (offset.tv_sec == 0 && offset.tv_nsec == 0)
+   return;
+
+   if (!audit_dummy_context())
+   __audit_tk_injoffset(offset);
+}
+
 extern int audit_n_rules;
 extern int audit_signals;
 #else /* CONFIG_AUDITSYSCALL */
@@ -580,6 +592,9 @@ static inline void audit_log_kern_module(char *name)
 static inline void audit_fanotify(unsigned int response)
 { }
 
+static inline void audit_tk_injoffset(struct timespec64 offset)
+{ }
+
 static inline void audit_ptrace(struct task_struct *t)
 { }
 #define audit_n_rules 0
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 36a7e3f18e69..2167d55bc800 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -114,6 +114,7 @@
 #define AUDIT_REPLACE  1329/* Replace auditd if this packet 
unanswerd */
 #define AUDIT_KERN_MODULE  1330/* Kernel Module events */
 #define AUDIT_FANOTIFY 1331/* Fanotify access decision */
+#define AUDIT_TIME_INJOFFSET   1332/* Timekeeping offset injected */
 
 #define AUDIT_AVC  1400/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR  1401/* Internal SE Linux Errors */
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index d1eab1d4a930..781336d0f2de 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2512,6 +2512,14 @@ void __audit_fanotify(unsigned int response)
AUDIT_FANOTIFY, "resp=%u", response);
 }
 
+/* We need to allocate with GFP_ATOMIC here, since these two functions will be
+ * called while holding the timekeeping lock: */
+void __audit_tk_injoffset(struct timespec64 offset)
+{
+   audit_log(audit_context(), GFP_ATOMIC, AUDIT_TIME_INJOFFSET,
+ "sec=%lli nsec=%li", (long long)offset.tv_sec, 
offset.tv_nsec);
+}
+
 static void audit_log_task(stru

Re: [PATCH v3 3/4] selinux: remove some useless BUG_ONs

2019-01-25 Thread Ondrej Mosnacek
On Fri, Jan 25, 2019 at 2:49 PM Stephen Smalley  wrote:
> On 1/25/19 5:06 AM, Ondrej Mosnacek wrote:
> > These BUG_ONs do not really protect from any catastrophic situation so
> > there is no need to have them there.
>
> They are to catch bugs in callers that pass requested==0.  That is
> always indicative of a bug in the caller (e.g. failed to correctly
> compute the permissions).  Otherwise, we will silently allow such calls
> and not notice them.
>
> At the least, they should be WARN_ONs.

OK, seems that switching to WARN_ON() will be a better choice.

Paul, you can apply the series without this patch and I will post a
corrected patch separately (if that's OK with you).

>
> >
> > Signed-off-by: Ondrej Mosnacek 
> > ---
> >   security/selinux/avc.c | 3 ---
> >   1 file changed, 3 deletions(-)
> >
> > diff --git a/security/selinux/avc.c b/security/selinux/avc.c
> > index 5ebad47391c9..478fa4213c25 100644
> > --- a/security/selinux/avc.c
> > +++ b/security/selinux/avc.c
> > @@ -1044,7 +1044,6 @@ int avc_has_extended_perms(struct selinux_state 
> > *state,
> >   int rc = 0, rc2;
> >
> >   xp_node = _xp_node;
> > - BUG_ON(!requested);
> >
> >   rcu_read_lock();
> >
> > @@ -1134,8 +1133,6 @@ inline int avc_has_perm_noaudit(struct selinux_state 
> > *state,
> >   int rc = 0;
> >   u32 denied;
> >
> > - BUG_ON(!requested);
> > -
> >   rcu_read_lock();
> >
> >   node = avc_lookup(state->avc, ssid, tsid, tclass);
> >
>

-- 
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


[PATCH v3 3/4] selinux: remove some useless BUG_ONs

2019-01-25 Thread Ondrej Mosnacek
These BUG_ONs do not really protect from any catastrophic situation so
there is no need to have them there.

Signed-off-by: Ondrej Mosnacek 
---
 security/selinux/avc.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 5ebad47391c9..478fa4213c25 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -1044,7 +1044,6 @@ int avc_has_extended_perms(struct selinux_state *state,
int rc = 0, rc2;
 
xp_node = _xp_node;
-   BUG_ON(!requested);
 
rcu_read_lock();
 
@@ -1134,8 +1133,6 @@ inline int avc_has_perm_noaudit(struct selinux_state 
*state,
int rc = 0;
u32 denied;
 
-   BUG_ON(!requested);
-
rcu_read_lock();
 
node = avc_lookup(state->avc, ssid, tsid, tclass);
-- 
2.20.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


[PATCH v3 2/4] selinux: replace some BUG_ON()s with a WARN_ON()

2019-01-25 Thread Ondrej Mosnacek
We don't need to crash the machine in these cases. Let's just detect the
buggy state early and error out with a warning.

Signed-off-by: Ondrej Mosnacek 
---
 security/selinux/avc.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 502162eeb3a0..5ebad47391c9 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -678,7 +678,6 @@ static void avc_audit_pre_callback(struct audit_buffer *ab, 
void *a)
return;
}
 
-   BUG_ON(!sad->tclass || sad->tclass >= ARRAY_SIZE(secclass_map));
perms = secclass_map[sad->tclass-1].perms;
 
audit_log_string(ab, " {");
@@ -731,7 +730,6 @@ static void avc_audit_post_callback(struct audit_buffer 
*ab, void *a)
kfree(scontext);
}
 
-   BUG_ON(!sad->tclass || sad->tclass >= ARRAY_SIZE(secclass_map));
audit_log_format(ab, " tclass=%s", secclass_map[sad->tclass-1].name);
 
if (sad->denied)
@@ -748,6 +746,9 @@ noinline int slow_avc_audit(struct selinux_state *state,
struct common_audit_data stack_data;
struct selinux_audit_data sad;
 
+   if (WARN_ON(!tclass || tclass >= ARRAY_SIZE(secclass_map)))
+   return -EINVAL;
+
if (!a) {
a = _data;
a->type = LSM_AUDIT_DATA_NONE;
-- 
2.20.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


[PATCH v3 0/4] Report raw context in AVCs + refactoring

2019-01-25 Thread Ondrej Mosnacek
Changes in v3:
- do some minor refactoring while there
- move new fields to the end of the record
- introduce a new security_sid_to_context_inval() function to get the raw
  context instead of (ab)using strcmp() to check if the raw context is
  different from the effective one

v2: 
https://lore.kernel.org/selinux/20190121153605.26847-1-omosn...@redhat.com/T/
Changes in v2:
- rename new fields to *rawcon

v1: 
https://lore.kernel.org/selinux/20190118100429.11703-1-omosn...@redhat.com/T/

Ondrej Mosnacek (4):
  selinux: inline some AVC functions used only once
  selinux: replace some BUG_ON()s with a WARN_ON()
  selinux: remove some useless BUG_ONs
  selinux: log invalid contexts in AVCs

 security/selinux/avc.c  | 159 +---
 security/selinux/include/security.h |   3 +
 security/selinux/ss/services.c  |  37 ++-
 3 files changed, 109 insertions(+), 90 deletions(-)

-- 
2.20.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


[PATCH v3 1/4] selinux: inline some AVC functions used only once

2019-01-25 Thread Ondrej Mosnacek
avc_dump_av() and avc_dump_query() are each used only in one place. Get
rid of them and open code their contents in the call sites.

Signed-off-by: Ondrej Mosnacek 
---
 security/selinux/avc.c | 140 +
 1 file changed, 58 insertions(+), 82 deletions(-)

diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 9b63d8ee1687..502162eeb3a0 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -129,75 +129,6 @@ static inline int avc_hash(u32 ssid, u32 tsid, u16 tclass)
return (ssid ^ (tsid<<2) ^ (tclass<<4)) & (AVC_CACHE_SLOTS - 1);
 }
 
-/**
- * avc_dump_av - Display an access vector in human-readable form.
- * @tclass: target security class
- * @av: access vector
- */
-static void avc_dump_av(struct audit_buffer *ab, u16 tclass, u32 av)
-{
-   const char **perms;
-   int i, perm;
-
-   if (av == 0) {
-   audit_log_format(ab, " null");
-   return;
-   }
-
-   BUG_ON(!tclass || tclass >= ARRAY_SIZE(secclass_map));
-   perms = secclass_map[tclass-1].perms;
-
-   audit_log_format(ab, " {");
-   i = 0;
-   perm = 1;
-   while (i < (sizeof(av) * 8)) {
-   if ((perm & av) && perms[i]) {
-   audit_log_format(ab, " %s", perms[i]);
-   av &= ~perm;
-   }
-   i++;
-   perm <<= 1;
-   }
-
-   if (av)
-   audit_log_format(ab, " 0x%x", av);
-
-   audit_log_format(ab, " }");
-}
-
-/**
- * avc_dump_query - Display a SID pair and a class in human-readable form.
- * @ssid: source security identifier
- * @tsid: target security identifier
- * @tclass: target security class
- */
-static void avc_dump_query(struct audit_buffer *ab, struct selinux_state 
*state,
-  u32 ssid, u32 tsid, u16 tclass)
-{
-   int rc;
-   char *scontext;
-   u32 scontext_len;
-
-   rc = security_sid_to_context(state, ssid, , _len);
-   if (rc)
-   audit_log_format(ab, "ssid=%d", ssid);
-   else {
-   audit_log_format(ab, "scontext=%s", scontext);
-   kfree(scontext);
-   }
-
-   rc = security_sid_to_context(state, tsid, , _len);
-   if (rc)
-   audit_log_format(ab, " tsid=%d", tsid);
-   else {
-   audit_log_format(ab, " tcontext=%s", scontext);
-   kfree(scontext);
-   }
-
-   BUG_ON(!tclass || tclass >= ARRAY_SIZE(secclass_map));
-   audit_log_format(ab, " tclass=%s", secclass_map[tclass-1].name);
-}
-
 /**
  * avc_init - Initialize the AVC.
  *
@@ -735,11 +666,37 @@ out:
 static void avc_audit_pre_callback(struct audit_buffer *ab, void *a)
 {
struct common_audit_data *ad = a;
-   audit_log_format(ab, "avc:  %s ",
-ad->selinux_audit_data->denied ? "denied" : "granted");
-   avc_dump_av(ab, ad->selinux_audit_data->tclass,
-   ad->selinux_audit_data->audited);
-   audit_log_format(ab, " for ");
+   struct selinux_audit_data *sad = ad->selinux_audit_data;
+   u32 av = sad->audited;
+   const char **perms;
+   int i, perm;
+
+   audit_log_format(ab, "avc:  %s ", sad->denied ? "denied" : "granted");
+
+   if (av == 0) {
+   audit_log_string(ab, " null");
+   return;
+   }
+
+   BUG_ON(!sad->tclass || sad->tclass >= ARRAY_SIZE(secclass_map));
+   perms = secclass_map[sad->tclass-1].perms;
+
+   audit_log_string(ab, " {");
+   i = 0;
+   perm = 1;
+   while (i < (sizeof(av) * 8)) {
+   if ((perm & av) && perms[i]) {
+   audit_log_format(ab, " %s", perms[i]);
+   av &= ~perm;
+   }
+   i++;
+   perm <<= 1;
+   }
+
+   if (av)
+   audit_log_format(ab, " 0x%x", av);
+
+   audit_log_string(ab, " } for ");
 }
 
 /**
@@ -751,15 +708,34 @@ static void avc_audit_pre_callback(struct audit_buffer 
*ab, void *a)
 static void avc_audit_post_callback(struct audit_buffer *ab, void *a)
 {
struct common_audit_data *ad = a;
-   audit_log_format(ab, " ");
-   avc_dump_query(ab, ad->selinux_audit_data->state,
-  ad->selinux_audit_data->ssid,
-  ad->selinux_audit_data->tsid,
-  ad->selinux_audit_data->tclass);
-   if (ad->selinux_audit_data->denied) {
-   audit_log_format(ab, " permissive=%u",
-ad->selinux_audit_data->result ? 0 : 1);
+

[PATCH v3 4/4] selinux: log invalid contexts in AVCs

2019-01-25 Thread Ondrej Mosnacek
In case a file has an invalid context set, in an AVC record generated
upon access to such file, the target context is always reported as
unlabeled. This patch adds new optional fields to the AVC record
(srawcon and trawcon) that report the actual context string if it
differs from the one reported in scontext/tcontext. This is useful for
diagnosing SELinux denials involving invalid contexts.

To trigger an AVC that illustrates this situation:

# setenforce 0
# touch /tmp/testfile
# setfattr -n security.selinux -v system_u:object_r:banana_t:s0 
/tmp/testfile
# runcon system_u:system_r:sshd_t:s0 cat /tmp/testfile

AVC before:

type=AVC msg=audit(1547801083.248:11): avc:  denied  { open } for  pid=1149 
comm="cat" path="/tmp/testfile" dev="tmpfs" ino=6608 
scontext=system_u:system_r:sshd_t:s0 
tcontext=system_u:object_r:unlabeled_t:s15:c0.c1023 tclass=file permissive=1

AVC after:

type=AVC msg=audit(1547801083.248:11): avc:  denied  { open } for  pid=1149 
comm="cat" path="/tmp/testfile" dev="tmpfs" ino=6608 
scontext=system_u:system_r:sshd_t:s0 
tcontext=system_u:object_r:unlabeled_t:s15:c0.c1023 tclass=file permissive=1 
trawcon=system_u:object_r:banana_t:s0

Note that it is also possible to encounter this situation with the
'scontext' field - e.g. when a new policy is loaded while a process is
running, whose context is not valid in the new policy.

Cc: Daniel Walsh 
Link: https://bugzilla.redhat.com/show_bug.cgi?id=1135683
Signed-off-by: Ondrej Mosnacek 
---
 security/selinux/avc.c  | 15 
 security/selinux/include/security.h |  3 +++
 security/selinux/ss/services.c  | 37 +
 3 files changed, 50 insertions(+), 5 deletions(-)

diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 478fa4213c25..047de65589bd 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -734,6 +734,21 @@ static void avc_audit_post_callback(struct audit_buffer 
*ab, void *a)
 
if (sad->denied)
audit_log_format(ab, " permissive=%u", sad->result ? 0 : 1);
+
+   /* in case of invalid context report also the actual context string */
+   rc = security_sid_to_context_inval(sad->state, sad->ssid, ,
+  _len);
+   if (!rc && scontext) {
+   audit_log_format(ab, " srawcon=%s", scontext);
+   kfree(scontext);
+   }
+
+   rc = security_sid_to_context_inval(sad->state, sad->tsid, ,
+  _len);
+   if (!rc && scontext) {
+   audit_log_format(ab, " trawcon=%s", scontext);
+   kfree(scontext);
+   }
 }
 
 /* This is the slow part of avc audit with big stack footprint */
diff --git a/security/selinux/include/security.h 
b/security/selinux/include/security.h
index ba8eedf42b90..f68fb25b5702 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -255,6 +255,9 @@ int security_sid_to_context(struct selinux_state *state, 
u32 sid,
 int security_sid_to_context_force(struct selinux_state *state,
  u32 sid, char **scontext, u32 *scontext_len);
 
+int security_sid_to_context_inval(struct selinux_state *state,
+ u32 sid, char **scontext, u32 *scontext_len);
+
 int security_context_to_sid(struct selinux_state *state,
const char *scontext, u32 scontext_len,
u32 *out_sid, gfp_t gfp);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index dd44126c8d14..9be05c3e99dc 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -1281,7 +1281,8 @@ const char *security_get_initial_sid_context(u32 sid)
 
 static int security_sid_to_context_core(struct selinux_state *state,
u32 sid, char **scontext,
-   u32 *scontext_len, int force)
+   u32 *scontext_len, int force,
+   int only_invalid)
 {
struct policydb *policydb;
struct sidtab *sidtab;
@@ -1326,8 +1327,14 @@ static int security_sid_to_context_core(struct 
selinux_state *state,
rc = -EINVAL;
goto out_unlock;
}
-   rc = context_struct_to_string(policydb, context, scontext,
- scontext_len);
+   if (only_invalid && !context->len) {
+   scontext = NULL;
+   scontext_len = 0;
+   rc = 0;
+   } else {
+   rc = context_struct_to_string(policydb, context, scontext,
+ scontext_len);
+   }
 out_unlock:
read_unlock(>ss->policy_rwlock);
 out:
@@ -1349,14

Re: [PATCH v2] selinux: log invalid contexts in AVCs

2019-01-25 Thread Ondrej Mosnacek
On Tue, Jan 22, 2019 at 8:42 PM Paul Moore  wrote:
> On Mon, Jan 21, 2019 at 10:36 AM Ondrej Mosnacek  wrote:
> > In case a file has an invalid context set, in an AVC record generated
> > upon access to such file, the target context is always reported as
> > unlabeled. This patch adds new optional fields to the AVC record
> > (srawcon and trawcon) that report the actual context string if it
> > differs from the one reported in scontext/tcontext. This is useful for
> > diagnosing SELinux denials involving invalid contexts.
> >
> > To trigger an AVC that illustrates this situation:
> >
> > # setenforce 0
> > # touch /tmp/testfile
> > # setfattr -n security.selinux -v system_u:object_r:banana_t:s0 
> > /tmp/testfile
> > # runcon system_u:system_r:sshd_t:s0 cat /tmp/testfile
> >
> > AVC before:
> >
> > type=AVC msg=audit(1547801083.248:11): avc:  denied  { open } for  pid=1149 
> > comm="cat" path="/tmp/testfile" dev="tmpfs" ino=6608 
> > scontext=system_u:system_r:sshd_t:s0 
> > tcontext=system_u:object_r:unlabeled_t:s15:c0.c1023 tclass=file permissive=1
> >
> > AVC after:
> >
> > type=AVC msg=audit(1547801083.248:11): avc:  denied  { open } for  pid=1149 
> > comm="cat" path="/tmp/testfile" dev="tmpfs" ino=6608 
> > scontext=system_u:system_r:sshd_t:s0 
> > tcontext=system_u:object_r:unlabeled_t:s15:c0.c1023 
> > trawcon=system_u:object_r:banana_t:s0 tclass=file permissive=1
>
> I would like us to add new fields at the end of existing records; the
> recent audit config changes are a bit of a special case as discussed
> previously.

Okay, I happened to find a way to do this a little differently (taking
a suggestion from Stephen about avoiding the need to do strcmp()) so
now it is actually easy to move them at the end. But I didn't expect
to get a more liberal reply from Steve (who is usually more strict
about this) than you :)

>
> Also, under what cases would we ever see a srawcon field?  This is
> only going to happen if we have a running process whose domain is
> removed during a policy reload, correct?  I'm find with including this
> for the sake of completeness, but I would mention this in the patch
> description for the next revision.

I tried to find a similar reproducer as for trawcon, but it doesn't
seem to be possible to do that without reloading the policy. I will
just add a note.

>
> > Cc: Daniel Walsh 
> > Link: https://bugzilla.redhat.com/show_bug.cgi?id=1135683
> > Signed-off-by: Ondrej Mosnacek 
> > ---
> >
> > v2: Rename fields to "(s|t)rawcon".
> >
> >  security/selinux/avc.c | 49 +-
> >  1 file changed, 29 insertions(+), 20 deletions(-)
> >
> > diff --git a/security/selinux/avc.c b/security/selinux/avc.c
> > index 9b63d8ee1687..df5490db575b 100644
> > --- a/security/selinux/avc.c
> > +++ b/security/selinux/avc.c
> > @@ -165,6 +165,32 @@ static void avc_dump_av(struct audit_buffer *ab, u16 
> > tclass, u32 av)
> > audit_log_format(ab, " }");
> >  }
> >
> > +static void avc_dump_sid(struct audit_buffer *ab, struct selinux_state 
> > *state,
> > +u32 sid, char type)
> > +{
> > +   int rc;
> > +   char *context, *rcontext;
> > +   u32 context_len, rcontext_len;
> > +
> > +   rc = security_sid_to_context(state, sid, , _len);
> > +   if (rc) {
> > +   audit_log_format(ab, "%csid=%d ", type, sid);
> > +   return;
> > +   }
> > +
> > +   audit_log_format(ab, "%ccontext=%s ", type, context);
> > +
> > +   /* in case of invalid context report also the actual context string 
> > */
> > +   rc = security_sid_to_context_force(state, sid, ,
> > +  _len);
> > +   if (!rc) {
> > +   if (strcmp(context, rcontext))
> > +   audit_log_format(ab, "%crawcon=%s ", type, 
> > rcontext);
> > +   kfree(rcontext);
> > +   }
> > +   kfree(context);
> > +}
> > +
> >  /**
> >   * avc_dump_query - Display a SID pair and a class in human-readable form.
> >   * @ssid: source security identifier
> > @@ -174,28 +200,11 @@ static void avc_dump_av(struct audit_buffer *ab, u16 
> > tclass, u32 av)
> >  static void avc_dump_query(struct audit_buffer *ab, struct selinux_state 
> > *state,
> >u32 ssid, u32 ts

[PATCH v2] selinux: log invalid contexts in AVCs

2019-01-21 Thread Ondrej Mosnacek
In case a file has an invalid context set, in an AVC record generated
upon access to such file, the target context is always reported as
unlabeled. This patch adds new optional fields to the AVC record
(srawcon and trawcon) that report the actual context string if it
differs from the one reported in scontext/tcontext. This is useful for
diagnosing SELinux denials involving invalid contexts.

To trigger an AVC that illustrates this situation:

# setenforce 0
# touch /tmp/testfile
# setfattr -n security.selinux -v system_u:object_r:banana_t:s0 
/tmp/testfile
# runcon system_u:system_r:sshd_t:s0 cat /tmp/testfile

AVC before:

type=AVC msg=audit(1547801083.248:11): avc:  denied  { open } for  pid=1149 
comm="cat" path="/tmp/testfile" dev="tmpfs" ino=6608 
scontext=system_u:system_r:sshd_t:s0 
tcontext=system_u:object_r:unlabeled_t:s15:c0.c1023 tclass=file permissive=1

AVC after:

type=AVC msg=audit(1547801083.248:11): avc:  denied  { open } for  pid=1149 
comm="cat" path="/tmp/testfile" dev="tmpfs" ino=6608 
scontext=system_u:system_r:sshd_t:s0 
tcontext=system_u:object_r:unlabeled_t:s15:c0.c1023 
trawcon=system_u:object_r:banana_t:s0 tclass=file permissive=1

Cc: Daniel Walsh 
Link: https://bugzilla.redhat.com/show_bug.cgi?id=1135683
Signed-off-by: Ondrej Mosnacek 
---

v2: Rename fields to "(s|t)rawcon".

 security/selinux/avc.c | 49 +-
 1 file changed, 29 insertions(+), 20 deletions(-)

diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 9b63d8ee1687..df5490db575b 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -165,6 +165,32 @@ static void avc_dump_av(struct audit_buffer *ab, u16 
tclass, u32 av)
audit_log_format(ab, " }");
 }
 
+static void avc_dump_sid(struct audit_buffer *ab, struct selinux_state *state,
+u32 sid, char type)
+{
+   int rc;
+   char *context, *rcontext;
+   u32 context_len, rcontext_len;
+
+   rc = security_sid_to_context(state, sid, , _len);
+   if (rc) {
+   audit_log_format(ab, "%csid=%d ", type, sid);
+   return;
+   }
+
+   audit_log_format(ab, "%ccontext=%s ", type, context);
+
+   /* in case of invalid context report also the actual context string */
+   rc = security_sid_to_context_force(state, sid, ,
+  _len);
+   if (!rc) {
+   if (strcmp(context, rcontext))
+   audit_log_format(ab, "%crawcon=%s ", type, rcontext);
+   kfree(rcontext);
+   }
+   kfree(context);
+}
+
 /**
  * avc_dump_query - Display a SID pair and a class in human-readable form.
  * @ssid: source security identifier
@@ -174,28 +200,11 @@ static void avc_dump_av(struct audit_buffer *ab, u16 
tclass, u32 av)
 static void avc_dump_query(struct audit_buffer *ab, struct selinux_state 
*state,
   u32 ssid, u32 tsid, u16 tclass)
 {
-   int rc;
-   char *scontext;
-   u32 scontext_len;
-
-   rc = security_sid_to_context(state, ssid, , _len);
-   if (rc)
-   audit_log_format(ab, "ssid=%d", ssid);
-   else {
-   audit_log_format(ab, "scontext=%s", scontext);
-   kfree(scontext);
-   }
-
-   rc = security_sid_to_context(state, tsid, , _len);
-   if (rc)
-   audit_log_format(ab, " tsid=%d", tsid);
-   else {
-   audit_log_format(ab, " tcontext=%s", scontext);
-   kfree(scontext);
-   }
+   avc_dump_sid(ab, state, ssid, 's');
+   avc_dump_sid(ab, state, tsid, 't');
 
BUG_ON(!tclass || tclass >= ARRAY_SIZE(secclass_map));
-   audit_log_format(ab, " tclass=%s", secclass_map[tclass-1].name);
+   audit_log_format(ab, "tclass=%s", secclass_map[tclass-1].name);
 }
 
 /**
-- 
2.20.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [RFC PATCH] selinux: log invalid contexts in AVCs

2019-01-21 Thread Ondrej Mosnacek
On Mon, Jan 21, 2019 at 11:26 AM Steve Grubb  wrote:
> On Mon, 21 Jan 2019 09:36:43 +0100
> Ondrej Mosnacek  wrote:
>
> > On Sat, Jan 19, 2019 at 2:23 PM Richard Guy Briggs 
> > wrote:
> > > On 2019-01-18 11:04, Ondrej Mosnacek wrote:
> > > > In case a file has an invalid context set, in an AVC record
> > > > generated upon access to such file, the target context is always
> > > > reported as unlabeled. This patch adds new optional fields to the
> > > > AVC record (slcon and tlcon) that report the actual context
> > > > string if it differs from the one reported in scontext/tcontext.
> > > > This is useful for diagnosing SELinux denials.
> > > >
> > > > To trigger an AVC that illustrates this situation:
> > > >
> > > > # setenforce 0
> > > > # touch /tmp/testfile
> > > > # setfattr -n security.selinux -v
> > > > system_u:object_r:banana_t:s0 /tmp/testfile # runcon
> > > > system_u:system_r:sshd_t:s0 cat /tmp/testfile
> > > >
> > > > AVC before:
> > > >
> > > > type=AVC msg=audit(1547801083.248:11): avc:  denied  { open }
> > > > for  pid=1149 comm="cat" path="/tmp/testfile" dev="tmpfs"
> > > > ino=6608 scontext=system_u:system_r:sshd_t:s0
> > > > tcontext=system_u:object_r:unlabeled_t:s15:c0.c1023 tclass=file
> > > > permissive=1
> > > >
> > > > AVC after:
> > > >
> > > > type=AVC msg=audit(1547801083.248:11): avc:  denied  { open }
> > > > for  pid=1149 comm="cat" path="/tmp/testfile" dev="tmpfs"
> > > > ino=6608 scontext=system_u:system_r:sshd_t:s0
> > > > tcontext=system_u:object_r:unlabeled_t:s15:c0.c1023
> > > > tlcon=system_u:object_r:banana_t:s0 tclass=file permissive=1
> > > >
> > > > Cc: Daniel Walsh 
> > > > Link: https://bugzilla.redhat.com/show_bug.cgi?id=1135683
> > > > Signed-off-by: Ondrej Mosnacek 
> > > > ---
> > > >  security/selinux/avc.c | 49
> > > > +- 1 file changed, 29
> > > > insertions(+), 20 deletions(-)
> > > >
> > > > I'm not entirely sure about the record format here, so I'm Cc'ing
> > > > linux-audit and Steve for feedback. I went for optional fields to
> > > > minimize the size of the record, but maybe a different format is
> > > > preferred. If so, let me know and I'll do a respin.
> > >
> > > My understanding is that optional fields can be a problem (but not
> > > if it is a non-searchable field?).
>
> Right. Searchable fields are where we can hit problems. And selinux
> contexts are a searchable field. We have 3 ways of searching: subject
> label, object label, and any label.
>
> > Yes, I hope Steve will eventually chime in and clarify what are the
> > exact boundaries I can operate within for this particular record and
> > fields. I could for example move the new fields at the end of the
> > record or make them always there, but set to "?" or "" if the value
> > would be the same as in the other fields, but I'm not sure if that is
> > necessary or sufficient for audit-userspace tools.
>
> You can leave it right where you have it now. My question is...are
> these always going to object labels? I'd need to know how to classify
> this as subject or object and if it can be either, then how to tell the
> difference. You can also keep this as optional. There is already wide
> spread usage of optional fields in AVC's.

Right, thanks for the reply!

There are two distinct new fields: "slcon" and "tlcon" (I plan to
change them to "srawcon" and "trawcon", though). You can tell whether
they refer to object or subject based on the first character of the
field name, just like with the existing scontext/tcontext fields.

>
> -Steve
>
> > > There is an existing "invalid_context"
> > > field whose position may help indicate which one it refers to, but
> > > this sounds pretty weak.
> > >
> > > Alternatively the best I could suggest would be a new auxiliary
> > > record.
> >
> > Hm, "invalid_context" seems to be part of the SELINUX_ERR record,
> > which is already use for a similar purpose (to report that an invalid
> > context has been encountered) in compute_sid_handle_invalid_context().
> > Perhaps I could reuse it here, but "error" sounds a

Re: [RFC PATCH] selinux: log invalid contexts in AVCs

2019-01-21 Thread Ondrej Mosnacek
On Sat, Jan 19, 2019 at 2:23 PM Richard Guy Briggs  wrote:
> On 2019-01-18 11:04, Ondrej Mosnacek wrote:
> > In case a file has an invalid context set, in an AVC record generated
> > upon access to such file, the target context is always reported as
> > unlabeled. This patch adds new optional fields to the AVC record (slcon
> > and tlcon) that report the actual context string if it differs from the
> > one reported in scontext/tcontext. This is useful for diagnosing SELinux
> > denials.
> >
> > To trigger an AVC that illustrates this situation:
> >
> > # setenforce 0
> > # touch /tmp/testfile
> > # setfattr -n security.selinux -v system_u:object_r:banana_t:s0 
> > /tmp/testfile
> > # runcon system_u:system_r:sshd_t:s0 cat /tmp/testfile
> >
> > AVC before:
> >
> > type=AVC msg=audit(1547801083.248:11): avc:  denied  { open } for  pid=1149 
> > comm="cat" path="/tmp/testfile" dev="tmpfs" ino=6608 
> > scontext=system_u:system_r:sshd_t:s0 
> > tcontext=system_u:object_r:unlabeled_t:s15:c0.c1023 tclass=file permissive=1
> >
> > AVC after:
> >
> > type=AVC msg=audit(1547801083.248:11): avc:  denied  { open } for  pid=1149 
> > comm="cat" path="/tmp/testfile" dev="tmpfs" ino=6608 
> > scontext=system_u:system_r:sshd_t:s0 
> > tcontext=system_u:object_r:unlabeled_t:s15:c0.c1023 
> > tlcon=system_u:object_r:banana_t:s0 tclass=file permissive=1
> >
> > Cc: Daniel Walsh 
> > Link: https://bugzilla.redhat.com/show_bug.cgi?id=1135683
> > Signed-off-by: Ondrej Mosnacek 
> > ---
> >  security/selinux/avc.c | 49 +-
> >  1 file changed, 29 insertions(+), 20 deletions(-)
> >
> > I'm not entirely sure about the record format here, so I'm Cc'ing
> > linux-audit and Steve for feedback. I went for optional fields to
> > minimize the size of the record, but maybe a different format is
> > preferred. If so, let me know and I'll do a respin.
>
> My understanding is that optional fields can be a problem (but not if
> it is a non-searchable field?).

Yes, I hope Steve will eventually chime in and clarify what are the
exact boundaries I can operate within for this particular record and
fields. I could for example move the new fields at the end of the
record or make them always there, but set to "?" or "" if the value
would be the same as in the other fields, but I'm not sure if that is
necessary or sufficient for audit-userspace tools.

> There is an existing "invalid_context"
> field whose position may help indicate which one it refers to, but this
> sounds pretty weak.
>
> Alternatively the best I could suggest would be a new auxiliary record.

Hm, "invalid_context" seems to be part of the SELINUX_ERR record,
which is already use for a similar purpose (to report that an invalid
context has been encountered) in compute_sid_handle_invalid_context().
Perhaps I could reuse it here, but "error" sounds a bit strong...
Maybe we need a SELINUX_WARN or SELINUX_INFO...

>
> > Also, I accept suggestions for better field names than "slcon"/"tlcon"
> > ("lcon" is meant as an acronym for "literal context", but I'm not sure
> > if that's a good name...).
> >
> > diff --git a/security/selinux/avc.c b/security/selinux/avc.c
> > index 9b63d8ee1687..4a181ed56e37 100644
> > --- a/security/selinux/avc.c
> > +++ b/security/selinux/avc.c
> > @@ -165,6 +165,32 @@ static void avc_dump_av(struct audit_buffer *ab, u16 
> > tclass, u32 av)
> >   audit_log_format(ab, " }");
> >  }
> >
> > +static void avc_dump_sid(struct audit_buffer *ab, struct selinux_state 
> > *state,
> > +  u32 sid, char type)
> > +{
> > + int rc;
> > + char *context, *lcontext;
> > + u32 context_len, lcontext_len;
> > +
> > + rc = security_sid_to_context(state, sid, , _len);
> > + if (rc) {
> > + audit_log_format(ab, "%csid=%d ", type, sid);
> > + return;
> > + }
> > +
> > + audit_log_format(ab, "%ccontext=%s ", type, context);
> > +
> > + /* in case of invalid context report also the actual context string */
> > + rc = security_sid_to_context_force(state, sid, ,
> > +_len);
> > + if (!rc) {
> > + if (strcmp(context, lcontext))
> > + audit_log_format(ab, "%clcon=%s ", type, lcontext);
> > +

[RFC PATCH] selinux: log invalid contexts in AVCs

2019-01-18 Thread Ondrej Mosnacek
In case a file has an invalid context set, in an AVC record generated
upon access to such file, the target context is always reported as
unlabeled. This patch adds new optional fields to the AVC record (slcon
and tlcon) that report the actual context string if it differs from the
one reported in scontext/tcontext. This is useful for diagnosing SELinux
denials.

To trigger an AVC that illustrates this situation:

# setenforce 0
# touch /tmp/testfile
# setfattr -n security.selinux -v system_u:object_r:banana_t:s0 
/tmp/testfile
# runcon system_u:system_r:sshd_t:s0 cat /tmp/testfile

AVC before:

type=AVC msg=audit(1547801083.248:11): avc:  denied  { open } for  pid=1149 
comm="cat" path="/tmp/testfile" dev="tmpfs" ino=6608 
scontext=system_u:system_r:sshd_t:s0 
tcontext=system_u:object_r:unlabeled_t:s15:c0.c1023 tclass=file permissive=1

AVC after:

type=AVC msg=audit(1547801083.248:11): avc:  denied  { open } for  pid=1149 
comm="cat" path="/tmp/testfile" dev="tmpfs" ino=6608 
scontext=system_u:system_r:sshd_t:s0 
tcontext=system_u:object_r:unlabeled_t:s15:c0.c1023 
tlcon=system_u:object_r:banana_t:s0 tclass=file permissive=1

Cc: Daniel Walsh 
Link: https://bugzilla.redhat.com/show_bug.cgi?id=1135683
Signed-off-by: Ondrej Mosnacek 
---
 security/selinux/avc.c | 49 +-
 1 file changed, 29 insertions(+), 20 deletions(-)

I'm not entirely sure about the record format here, so I'm Cc'ing
linux-audit and Steve for feedback. I went for optional fields to
minimize the size of the record, but maybe a different format is
preferred. If so, let me know and I'll do a respin.

Also, I accept suggestions for better field names than "slcon"/"tlcon"
("lcon" is meant as an acronym for "literal context", but I'm not sure
if that's a good name...).

diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index 9b63d8ee1687..4a181ed56e37 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -165,6 +165,32 @@ static void avc_dump_av(struct audit_buffer *ab, u16 
tclass, u32 av)
audit_log_format(ab, " }");
 }
 
+static void avc_dump_sid(struct audit_buffer *ab, struct selinux_state *state,
+u32 sid, char type)
+{
+   int rc;
+   char *context, *lcontext;
+   u32 context_len, lcontext_len;
+
+   rc = security_sid_to_context(state, sid, , _len);
+   if (rc) {
+   audit_log_format(ab, "%csid=%d ", type, sid);
+   return;
+   }
+
+   audit_log_format(ab, "%ccontext=%s ", type, context);
+
+   /* in case of invalid context report also the actual context string */
+   rc = security_sid_to_context_force(state, sid, ,
+  _len);
+   if (!rc) {
+   if (strcmp(context, lcontext))
+   audit_log_format(ab, "%clcon=%s ", type, lcontext);
+   kfree(lcontext);
+   }
+   kfree(context);
+}
+
 /**
  * avc_dump_query - Display a SID pair and a class in human-readable form.
  * @ssid: source security identifier
@@ -174,28 +200,11 @@ static void avc_dump_av(struct audit_buffer *ab, u16 
tclass, u32 av)
 static void avc_dump_query(struct audit_buffer *ab, struct selinux_state 
*state,
   u32 ssid, u32 tsid, u16 tclass)
 {
-   int rc;
-   char *scontext;
-   u32 scontext_len;
-
-   rc = security_sid_to_context(state, ssid, , _len);
-   if (rc)
-   audit_log_format(ab, "ssid=%d", ssid);
-   else {
-   audit_log_format(ab, "scontext=%s", scontext);
-   kfree(scontext);
-   }
-
-   rc = security_sid_to_context(state, tsid, , _len);
-   if (rc)
-   audit_log_format(ab, " tsid=%d", tsid);
-   else {
-   audit_log_format(ab, " tcontext=%s", scontext);
-   kfree(scontext);
-   }
+   avc_dump_sid(ab, state, ssid, 's');
+   avc_dump_sid(ab, state, tsid, 't');
 
BUG_ON(!tclass || tclass >= ARRAY_SIZE(secclass_map));
-   audit_log_format(ab, " tclass=%s", secclass_map[tclass-1].name);
+   audit_log_format(ab, "tclass=%s", secclass_map[tclass-1].name);
 }
 
 /**
-- 
2.20.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [RFC PATCH] audit-testsuite: improve our chances of losing records in lost_reset

2018-12-15 Thread Ondrej Mosnacek
On Fri, Dec 14, 2018 at 10:00 PM Richard Guy Briggs  wrote:
> On 2018-12-14 15:35, Paul Moore wrote:
> > On Fri, Dec 14, 2018 at 11:12 AM Richard Guy Briggs  wrote:
> > > On 2018-12-14 10:53, Paul Moore wrote:
> > > > On Thu, Dec 13, 2018 at 8:59 PM Richard Guy Briggs  
> > > > wrote:
> > > > > On 2018-12-13 18:23, Paul Moore wrote:
> > > > > > On Thu, Dec 13, 2018 at 6:17 PM Paul Moore  
> > > > > > wrote:
> >
> > ...
> >
> > > > As an aside, have you spent any time trying to debug that wrong PID
> > > > problem?  While not strictly audit related, that seems like a pretty
> > > > serious Bash bug.  Or maybe it's a problem with the test?  I vaguely
> > > > remember a discussion between you and Ondrej and some confusion around
> > > > which Bash variable to use to fetch PIDs, but I may be mistaken.
> > >
> > > I haven't spent much time trying to debug that bash PID increment issue,
> > > but it perplexed me since it was the identical technique used in
> > > multiple tests in the audit-testsuite that has never caused an issue
> > > previously on any of the same set of test machines.  This was for the
> > > missing mount umount2 hang bug test
> > > https://github.com/linux-audit/audit-testsuite/pull/76
> >
> > Ah, I think I see the problem.  Unless I'm mistaken, you are talking
> > about the shell/Bash command where the tests print the PID using "echo
> > $$" or similar, yes?  As you likely already know, in Bash (and likely
> > other shells as well), $$ is the PID of the running Bash process; in
> > the two places where I saw it used in the existing audit-testsuite $$
> > is being used to reference the Bash instance itself or something it
> > exec's (which ends up inheriting the PID).  It looks like you are
> > using $$ as a way to capture the PID of a child process being spawned
> > by the shell, yes?  This may explain why you sometimes get lucky and
> > $$+1 works for the PID.
>
> I was always getting lucky with $$+1, but understandably uncomfortable
> with it since others weren't so fortunate.
>
> In the code that's there, that process is backgrounded, but I'm fairly
> certain I tested without that and carefully checked the options (-f and
> -s) to ensure it wasn't daemonizing or multithreading.  I was pretty
> careful to set up exactly the same conditions for running that process
> as other tests use, but that looks like the first thing to check next
> time I try it.  It wouldn't be the first time I've missed something
> obvious.

Right, let me chime into the PID issue again :) I am pretty sure the
code to get the child PID in Richard's umount2 test is wrong. I didn't
get back to that thread eventually because I tried to simplify the
fixed code to something better (and still 100% reliable), but I
couldn't get it to a state I'd like and eventually I forgot about it
and switched to other things...

So, let me try to explain the problem again. This is the relevant
snippet of code:

system("cd $basedir/$clientdir; echo \$\$ > $stdout; exec ./$client -f
-s $tmpdir &");

Let's rewrite this into pseudocode so it is clear what's actually going on:
1. run "cd $basedir/$clientdir"
2. write the PID of this bash process into "$stdout"
3. fork a child and in that child, execve() this command: "./$client
-f -s $tmpdir"

So the problem is that you log the PID of the parent bash process and
not the child that exec's into the "$client" program. Since the child
gets forked away very quickly after the parent bash process is
created, in 99.9% of the cases it gets a PID exactly one greater -
that's why your +1 trick works. The reason why a similar pattern
("echo $$; exec ...") works elsewhere in the testsuite is that there
is no forking going on in those cases (IIRC).

I just looked at the code in the lost_reset test that actually deals
with the forking scenario, and it uses the "$!" variable, which is the
correct way to get the PID of the last process forked by bash. I admit
I didn't know about this variable when I was pointing out the problem
in Richard's patch, but now I realize this is what I should have
suggested back then...

So, in the umount2 test this:

system("cd $basedir/$clientdir; echo \$\$ > $stdout; exec ./$client -f
-s $tmpdir &");

should be replaced with this (along with dropping the "$pid_fuse += 1;" line):

system("cd $basedir/$clientdir; exec ./$client -f -s $tmpdir & echo
\$! > $stdout;");

That said, I think the code in the lost_reset test is doing the right
thing and I wouldn't expect it to get the ping PID wrong.

Hope that helps,

--
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [PATCH ghak95] audit: Do not log full CWD path on empty relative paths

2018-12-04 Thread Ondrej Mosnacek
On Sat, Dec 1, 2018 at 5:50 PM Steve Grubb  wrote:
> On Tuesday, November 13, 2018 11:30:55 AM EST Paul Moore wrote:
> > On Tue, Nov 13, 2018 at 10:25 AM Ondrej Mosnacek 
> wrote:
> > > On Tue, Nov 6, 2018 at 9:19 PM Paul Moore  wrote:
> > > > On Tue, Nov 6, 2018 at 3:09 AM Ondrej Mosnacek 
> wrote:
> > > > > On Tue, Nov 6, 2018 at 12:30 AM Paul Moore 
> wrote:
> > > > > > Let's reset this discussion a bit ... if we abolish relative paths
> > > > > > and make everything absolute, is there even a need to log PARENT?
>
> I believe that Al Viro has said that sometime paths are not resolvable in the
> future. For example process A opens a file. It passes the descriptor to
> another process using scm rights. Directory tree is deleted. Process B
> receives the descriptor. Process A exits. Process B is now accessing what?

Yes, this can happen, but even in cases where the path cannot be
determined any more, the PARENT records won't help you, because the
path in PARENT records is in fact based on the path of the child, the
code just cuts away the last component. See:
https://elixir.bootlin.com/linux/v4.19.6/source/kernel/auditsc.c#L1839

>
>
> > > > > If there ever was such need, then this won't change when we switch to
> > > > > absolute paths. The PATH records contain some fields (inode, dev,
> > > > > obj, that can be different for the child and parent and I would say
> > > > > these are the only new information that the PARENT records provide
> > > > > over the corresponding CREATE/DELETE records.
> > > >
> > > > Sigh.  Of course the inode information is going to be different
> > > > between the object in question and the parent, they are different
> > > > filesystem objects.  Ask your self the bigger question: does the
> > > > PARENT record provide me any security relevant information related to
> > > > the filesystem object that is being accessed?
> > >
> > > I would say it does. Consider e.g. the "mode" and "obj" fields. When
> > > you move (rename) a file from one directory to another (which is the
> > > main, if not the only, case when a PARENT record is emitted), then you
> > > are usually more interested in the values for the parent directory
> > > than the file itself (that's what determines if you can move the
> > > file).
> >
> > I disagree on the importance of the mode/obj of the parent in a rename
> > operation.  From my perspective I really only care about the
> > filesystem object that is being moved and if it succeeded or not.  The
> > idea that you care more about the parent than the object being moved
> > makes no sense to me at all.
>
> The mode is really not important.

All right, forget about the mode/context fields... I went in the wrong
direction there.

>
> > > For example, assume you have a rule that logs whenever some sensitive
> > > file gets moved. You do not expect that to happen because you set the
> > > file/directory permissions and labels so that it can't be done by
> > > anyone unauthorized. But something goes wrong, the permissions/labels
> > > get changed somehow ...
> >
> > In which case you should be watching for changes to the filesystem
> > metadata which affect access rights.  That is how you should catch
> > changes to permissions on a filesystem object as it gives you
> > information about the change as well as the subject information of the
> > user/process which made the change.
>
> Right. You would watch for attribute changes on a directory.
>
>
> > > ... and a bad actor leverages the situation to move
> > > the file. Then later you want to investigate this security incident
> > > and as part of it you want to know what permissions were set on the
> > > directories involved that had allowed the file to be moved, because
> > > this may give you a useful lead. With PARENT records, you get such
> > > information, without them you don't.
> >
> > If you only have that information in the parent record then you are
> > missing half the story, and it may be the important half as the
> > interesting bit of information in this example is the identity of the
> > user/process which was able to change permissions to enable the rename
> > to take place.
> >
> > Unless Steve provides evidence of some compelling certification
> > requirement which necessitates the need for a parent record, I see no
> > reason to keep it.
>
> Certification does not care about parent records. What is car

Re: [PATCH ghak95] audit: Do not log full CWD path on empty relative paths

2018-11-13 Thread Ondrej Mosnacek
On Tue, Nov 6, 2018 at 9:19 PM Paul Moore  wrote:
> On Tue, Nov 6, 2018 at 3:09 AM Ondrej Mosnacek  wrote:
> > On Tue, Nov 6, 2018 at 12:30 AM Paul Moore  wrote:
> > > Let's reset this discussion a bit ... if we abolish relative paths and
> > > make everything absolute, is there even a need to log PARENT?
> >
> > If there ever was such need, then this won't change when we switch to
> > absolute paths. The PATH records contain some fields (inode, dev, obj,
> > ...) that can be different for the child and parent and I would say
> > these are the only new information that the PARENT records provide
> > over the corresponding CREATE/DELETE records.
>
> Sigh.  Of course the inode information is going to be different
> between the object in question and the parent, they are different
> filesystem objects.  Ask your self the bigger question: does the
> PARENT record provide me any security relevant information related to
> the filesystem object that is being accessed?

I would say it does. Consider e.g. the "mode" and "obj" fields. When
you move (rename) a file from one directory to another (which is the
main, if not the only, case when a PARENT record is emitted), then you
are usually more interested in the values for the parent directory
than the file itself (that's what determines if you can move the
file).

For example, assume you have a rule that logs whenever some sensitive
file gets moved. You do not expect that to happen because you set the
file/directory permissions and labels so that it can't be done by
anyone unauthorized. But something goes wrong, the permissions/labels
get changed somehow and a bad actor leverages the situation to move
the file. Then later you want to investigate this security incident
and as part of it you want to know what permissions were set on the
directories involved that had allowed the file to be moved, because
this may give you a useful lead. With PARENT records, you get such
information, without them you don't.

>
> With the messed up state of path name auditing, the PARENT records are
> useful when trying to recreate the full path used by the process to
> access a given filesystem object (transient as it may be, the path
> name can still be useful after the fact).  If we switch to always
> recording absolute path names, why do we care about recording the
> PARENT filesystem object at all (both the path and the inode
> information)?

I disagree with your assumption that the PARENT record somehow helps
to determine the full path of the (child) filesystem object, in the
sense that it provides more information than what is already contained
in the corresponding CREATE/DELETE record. (Please correct me if
that's not what you were trying to say.) When we log the paths as we
do now, you either get a relative path in both PARENT and
CREATE/DELETE records (the PARENT path just being one element shorter)
or you get a full path in both records (again both will be the same
except the PARENT path will have the last component stripped),
depending on whether the user passed a relative or absolute path to
the syscall [*]. If we switch to always logging full paths, we simply
eliminate the first case (both paths will be always absolute).

Whether we switch to always logging absolute paths or not, the value
of the "path" field of the PARENT record is somewhat redundant (but I
don't see that as a problem).

[*] Disregarding the occasional glitch of getting the (full) path of
current directory as PARENT path when the child path is relative with
just a single component, a.k.a. GHAK #95...

--
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: stuck on ghak100 testsuite script

2018-11-12 Thread Ondrej Mosnacek
On Mon, Nov 12, 2018 at 12:32 PM Ondrej Mosnacek  wrote:
> On Sun, Nov 11, 2018 at 11:36 PM Richard Guy Briggs  wrote:
> > On 2018-11-11 17:24, Ondrej Mosnacek wrote:
> > > Hi Richard,
> > > On Fri, Nov 9, 2018 at 11:04 PM Richard Guy Briggs  
> > > wrote:
> > > > Hi Paul, Ondrej,
> > > >
> > > > I've got a couple of patches with two different approaches to address
> > > > ghak100:
> > > > https://github.com/linux-audit/audit-kernel/issues/100
> > > >
> > > > The patches work, but I've not posted them yet because I wanted to
> > > > update the audit-testsuite first to consistently test it.
> > > >
> > > > I've written a test to automate the regression test to add to
> > > > audit-testsuite based on the reproducer recipe provided in ghak100.  The
> > > > procedure in the description of ghak100 works, but I'm having some
> > > > trouble with the script.  In particular, it is hanging the script on the
> > > > "kill 'SIGSTOP' $pid_fuse" line.  Once it hangs, the main script, the
> > > > test subscript and both backgrounded processes (fuse and umount) are
> > > > still hanging around.
> > > >
> > > > Here's the script:
> > > > 
> > > > https://github.com/linux-audit/audit-testsuite/compare/master...rgbriggs:ghak100-missing-mount-hang
> > > >
> > > > Do either of you have any insight why this might be happenning and how
> > > > to fix or work around it?
> > > >
> > > > A couple of minor notes:
> > > > - The $pid_fuse += 1 is necessary since it forks from the PID reported
> > > >   to the shell.
> > >
> > > I don't understand... why do you expect the forked PID to be exactly
> > > one higher? This doesn't seem to be the case in general:
> > >
> > > $ (echo $$; exec bash -c 'echo $$' &)
> > > 10995
> > > 13693
> >
> > I was not happy with this hack, but this was the most expedient way to
> > try to get a first attempt working...  I suppose a better way might be
> > to spawn the client which forks, then use something like pgrep to find
> > all the instances and eliminate the PID that was returned by the launch.
>
> How about something like:
>
>   system("cd $basedir/$clientdir; mkfifo /tmp/fifo; sh -c 'echo $$ >
> /tmp/fifo; exec ./$client -f -s $tmpdir' & cat /tmp/fifo");
>
> That should always give you the right PID. You just need to tweak it
> to create the FIFO as a temporary file and clean it up afterwards. It
> is more complicated, but should be reliable.
>
> >
> > As far as I can tell, I was hitting the right task since hitting the
> > wrong or non-existant task didn't hang the test.
>
> Yes, when I fork from a fresh shell, I also get the forked PID one
> greater practically every time, so that will be a different problem...
> I didn't look at the hang problem yet, I will try it later in the
> afternoon.

I think I figured it out. When you send SIGTERM to the fuse process in
the cleanup section, it is still stopped, so it can't handle it. You
need to send it SIGCONT first (or kill it with SIGKILL):
[...]
###
# cleanup
kill 'SIGCONT', $pid_fuse;
kill 'SIGTERM', $pid_umnt;
kill 'SIGTERM', $pid_fuse;
system("auditctl -D >& /dev/null");

With the above tweak it no longer hangs for me.

>
> >
> > > > - The SIGSTOP is necessary to simulate the hung filesystem.
> > > >
> > > > - RGB
> > >
> > > Ondrej Mosnacek 
> >
> > - RGB
> >
> > --
> > Richard Guy Briggs 
> > Sr. S/W Engineer, Kernel Security, Base Operating Systems
> > Remote, Ottawa, Red Hat Canada
> > IRC: rgb, SunRaycer
> > Voice: +1.647.777.2635, Internal: (81) 32635
>
> --
> Ondrej Mosnacek 
> Associate Software Engineer, Security Technologies
> Red Hat, Inc.

-- 
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: stuck on ghak100 testsuite script

2018-11-12 Thread Ondrej Mosnacek
On Mon, Nov 12, 2018 at 2:32 PM Richard Guy Briggs  wrote:
> On 2018-11-12 12:32, Ondrej Mosnacek wrote:
> > On Sun, Nov 11, 2018 at 11:36 PM Richard Guy Briggs  wrote:
> > > On 2018-11-11 17:24, Ondrej Mosnacek wrote:
> > > > Hi Richard,
> > > > On Fri, Nov 9, 2018 at 11:04 PM Richard Guy Briggs  
> > > > wrote:
> > > > > Hi Paul, Ondrej,
> > > > >
> > > > > I've got a couple of patches with two different approaches to address
> > > > > ghak100:
> > > > > https://github.com/linux-audit/audit-kernel/issues/100
> > > > >
> > > > > The patches work, but I've not posted them yet because I wanted to
> > > > > update the audit-testsuite first to consistently test it.
> > > > >
> > > > > I've written a test to automate the regression test to add to
> > > > > audit-testsuite based on the reproducer recipe provided in ghak100.  
> > > > > The
> > > > > procedure in the description of ghak100 works, but I'm having some
> > > > > trouble with the script.  In particular, it is hanging the script on 
> > > > > the
> > > > > "kill 'SIGSTOP' $pid_fuse" line.  Once it hangs, the main script, the
> > > > > test subscript and both backgrounded processes (fuse and umount) are
> > > > > still hanging around.
> > > > >
> > > > > Here's the script:
> > > > > 
> > > > > https://github.com/linux-audit/audit-testsuite/compare/master...rgbriggs:ghak100-missing-mount-hang
> > > > >
> > > > > Do either of you have any insight why this might be happenning and how
> > > > > to fix or work around it?
> > > > >
> > > > > A couple of minor notes:
> > > > > - The $pid_fuse += 1 is necessary since it forks from the PID reported
> > > > >   to the shell.
> > > >
> > > > I don't understand... why do you expect the forked PID to be exactly
> > > > one higher? This doesn't seem to be the case in general:
> > > >
> > > > $ (echo $$; exec bash -c 'echo $$' &)
> > > > 10995
> > > > 13693
> > >
> > > I was not happy with this hack, but this was the most expedient way to
> > > try to get a first attempt working...  I suppose a better way might be
> > > to spawn the client which forks, then use something like pgrep to find
> > > all the instances and eliminate the PID that was returned by the launch.
> >
> > How about something like:
> >
> >   system("cd $basedir/$clientdir; mkfifo /tmp/fifo; sh -c 'echo $$ >
> > /tmp/fifo; exec ./$client -f -s $tmpdir' & cat /tmp/fifo");
> >
> > That should always give you the right PID. You just need to tweak it
> > to create the FIFO as a temporary file and clean it up afterwards. It
> > is more complicated, but should be reliable.
>
> I don't understand why all this extra?  It will still list the first
> PID of the newly forked task.  There are several examples of
> capturing the PID of a backgrounded process already in the
> audit-testsuite which all work fine:
> tests/filter_sessionid/test (touch)
> tests/login_tty/test (echo)
> tests/lost_reset/test (auditctl --reset-lost)
> tests/user_msg/test (auditctl -m ...)
>
> The problem here is that the client that is executed then forks, which
> isn't the case with any of the examples listed above.

Do you mean that the client itself forks, too? I thought you are only
trying to deal with the fork done by the shell via the '&' operator.
My solution of course handles only that (by forking a shell, reporting
its PID into a fifo and then exec'ing the fuse client). But shouldn't
the '-f' and '-s' option of fusexmp prevent it from forking on its
own?

>
> > > As far as I can tell, I was hitting the right task since hitting the
> > > wrong or non-existant task didn't hang the test.
> >
> > Yes, when I fork from a fresh shell, I also get the forked PID one
> > greater practically every time, so that will be a different problem...
> > I didn't look at the hang problem yet, I will try it later in the
> > afternoon.
> >
> > > > > - The SIGSTOP is necessary to simulate the hung filesystem.
> > > > >
> > > > > - RGB
> > > >
> > > > Ondrej Mosnacek 
> > >
> > > - RGB
> >
> > Ondrej Mosnacek 
>
> - RGB
>
> --
> Richard Guy Briggs 
> Sr. S/W Engineer, Kernel Security, Base Operating Systems
> Remote, Ottawa, Red Hat Canada
> IRC: rgb, SunRaycer
> Voice: +1.647.777.2635, Internal: (81) 32635

-- 
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: stuck on ghak100 testsuite script

2018-11-12 Thread Ondrej Mosnacek
On Sun, Nov 11, 2018 at 11:36 PM Richard Guy Briggs  wrote:
> On 2018-11-11 17:24, Ondrej Mosnacek wrote:
> > Hi Richard,
> > On Fri, Nov 9, 2018 at 11:04 PM Richard Guy Briggs  wrote:
> > > Hi Paul, Ondrej,
> > >
> > > I've got a couple of patches with two different approaches to address
> > > ghak100:
> > > https://github.com/linux-audit/audit-kernel/issues/100
> > >
> > > The patches work, but I've not posted them yet because I wanted to
> > > update the audit-testsuite first to consistently test it.
> > >
> > > I've written a test to automate the regression test to add to
> > > audit-testsuite based on the reproducer recipe provided in ghak100.  The
> > > procedure in the description of ghak100 works, but I'm having some
> > > trouble with the script.  In particular, it is hanging the script on the
> > > "kill 'SIGSTOP' $pid_fuse" line.  Once it hangs, the main script, the
> > > test subscript and both backgrounded processes (fuse and umount) are
> > > still hanging around.
> > >
> > > Here's the script:
> > > 
> > > https://github.com/linux-audit/audit-testsuite/compare/master...rgbriggs:ghak100-missing-mount-hang
> > >
> > > Do either of you have any insight why this might be happenning and how
> > > to fix or work around it?
> > >
> > > A couple of minor notes:
> > > - The $pid_fuse += 1 is necessary since it forks from the PID reported
> > >   to the shell.
> >
> > I don't understand... why do you expect the forked PID to be exactly
> > one higher? This doesn't seem to be the case in general:
> >
> > $ (echo $$; exec bash -c 'echo $$' &)
> > 10995
> > 13693
>
> I was not happy with this hack, but this was the most expedient way to
> try to get a first attempt working...  I suppose a better way might be
> to spawn the client which forks, then use something like pgrep to find
> all the instances and eliminate the PID that was returned by the launch.

How about something like:

  system("cd $basedir/$clientdir; mkfifo /tmp/fifo; sh -c 'echo $$ >
/tmp/fifo; exec ./$client -f -s $tmpdir' & cat /tmp/fifo");

That should always give you the right PID. You just need to tweak it
to create the FIFO as a temporary file and clean it up afterwards. It
is more complicated, but should be reliable.

>
> As far as I can tell, I was hitting the right task since hitting the
> wrong or non-existant task didn't hang the test.

Yes, when I fork from a fresh shell, I also get the forked PID one
greater practically every time, so that will be a different problem...
I didn't look at the hang problem yet, I will try it later in the
afternoon.

>
> > > - The SIGSTOP is necessary to simulate the hung filesystem.
> > >
> > > - RGB
> >
> > Ondrej Mosnacek 
>
> - RGB
>
> --
> Richard Guy Briggs 
> Sr. S/W Engineer, Kernel Security, Base Operating Systems
> Remote, Ottawa, Red Hat Canada
> IRC: rgb, SunRaycer
> Voice: +1.647.777.2635, Internal: (81) 32635

--
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: stuck on ghak100 testsuite script

2018-11-11 Thread Ondrej Mosnacek
Hi Richard,

On Fri, Nov 9, 2018 at 11:04 PM Richard Guy Briggs  wrote:
> Hi Paul, Ondrej,
>
> I've got a couple of patches with two different approaches to address
> ghak100:
> https://github.com/linux-audit/audit-kernel/issues/100
>
> The patches work, but I've not posted them yet because I wanted to
> update the audit-testsuite first to consistently test it.
>
> I've written a test to automate the regression test to add to
> audit-testsuite based on the reproducer recipe provided in ghak100.  The
> procedure in the description of ghak100 works, but I'm having some
> trouble with the script.  In particular, it is hanging the script on the
> "kill 'SIGSTOP' $pid_fuse" line.  Once it hangs, the main script, the
> test subscript and both backgrounded processes (fuse and umount) are
> still hanging around.
>
> Here's the script:
> 
> https://github.com/linux-audit/audit-testsuite/compare/master...rgbriggs:ghak100-missing-mount-hang
>
> Do either of you have any insight why this might be happenning and how
> to fix or work around it?
>
> A couple of minor notes:
> - The $pid_fuse += 1 is necessary since it forks from the PID reported
>   to the shell.

I don't understand... why do you expect the forked PID to be exactly
one higher? This doesn't seem to be the case in general:

$ (echo $$; exec bash -c 'echo $$' &)
10995
13693

> - The SIGSTOP is necessary to simulate the hung filesystem.
>
>
> - RGB
>
> --
> Richard Guy Briggs 
> Sr. S/W Engineer, Kernel Security, Base Operating Systems
> Remote, Ottawa, Red Hat Canada
> IRC: rgb, SunRaycer
> Voice: +1.647.777.2635, Internal: (81) 32635
>
> --
> Linux-audit mailing list
> Linux-audit@redhat.com
> https://www.redhat.com/mailman/listinfo/linux-audit

-- 
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [PATCH ghak95] audit: Do not log full CWD path on empty relative paths

2018-11-06 Thread Ondrej Mosnacek
On Tue, Nov 6, 2018 at 12:30 AM Paul Moore  wrote:
> On Wed, Oct 31, 2018 at 4:54 AM Ondrej Mosnacek  wrote:
> > On Wed, Sep 19, 2018 at 5:44 PM Paul Moore  wrote:
> > > On Wed, Sep 19, 2018 at 7:01 AM Ondrej Mosnacek  
> > > wrote:
> > > > On Wed, Sep 19, 2018 at 3:35 AM Paul Moore  wrote:
> > > > > On Thu, Sep 13, 2018 at 10:13 AM Paul Moore  
> > > > > wrote:
> > > > > > On Thu, Sep 13, 2018 at 9:58 AM Ondrej Mosnacek 
> > > > > >  wrote:
> > > > > > > Paul, could you please answer this question so I can move 
> > > > > > > forward? :)
> > > > > >
> > > > > > Yep, sorry for the delay ...
> > > > >
> > > > > I just went back over the original problem, your proposed fix, and all
> > > > > of the discussion in this thread.
> > > > >
> > > > > Sadly, I don't think the patch you have proposed is the right fix.
> > > > >
> > > > > As Steve has pointed out, the CWD path is the working directory from
> > > > > which the current process was executed.  I believe we should log the
> > > > > full path, or as complete a path as possible, in the nametype=CWD PATH
> > > > > records.  While the nametype=PARENT PATH records have a connection
> > > > > with some of the other PATH records (e.g. DELETE and CREATE), the
> > > > > nametype=PARENT PATH records are independent of the current working
> > > > > directory, although they sometimes may be the same; in the cases where
> > > > > they are the same, this is purely a coincidence and is due to
> > > > > operation being performed, not something that should be seen as a
> > > > > flaw.
> > > > >
> > > > > From what I can tell, there are issues involving the nametype=PARENT
> > > > > PATH records, especially when it comes to the *at() syscalls, but no
> > > > > issue where the nametype=CWD PATH records have been wrong, is that
> > > > > correct?
> > > >
> > > > Sorry, but I think you are completely misunderstanding the problem...
> > > > I tried to explain it several times in different ways, but apparently
> > > > I'm still not doing it right...
> > > >
> > > > First of all, there is no "nametype=CWD" PATH record. There is only
> > > > the classic CWD record that is associated to every syscall and I don't
> > > > touch that one at all. The information in the CWD record is perfectly
> > > > fine.
> > >
> > > Yes, that was a casualty of me looking at too many audit logs too late
> > > in the day, I mistakenly typed it as a nametype PATH record when CWD
> > > is its own record type.  My apologies.
> > >
> > > > Let me try to demonstrate it with some more verbose examples. (TL;DR:
> > > > The info in the CWD record is correct, but it is being abused in
> > > > audit_log_name().)
> > > >
> > > > EXAMPLE #1 (The non-edge case):
> > > > 1. A userspace process calls rename("dir1/file1", "dir2/file2") with
> > > > CWD set to "/home/user".
> > > > 2. The syscall causes four calls to __audit_inode(), which generate
> > > > four 'struct audit_names' objects with the following information
> > > > (maybe not in this specific order, but that doesn't matter):
> > > > .name = "dir1/file1", .type = AUDIT_TYPE_PARENT, .name_len = 5
> > > > .name = "dir1/file1", .type = AUDIT_TYPE_DELETE, .name_len = 
> > > > AUDIT_NAME_FULL
> > > > .name = "dir2/file2", .type = AUDIT_TYPE_PARENT, .name_len = 5
> > > > .name = "dir2/file2", .type = AUDIT_TYPE_CREATE, .name_len = 
> > > > AUDIT_NAME_FULL
> > > > 3. At the end of the syscall, audit_log_name()  is called on each of
> > > > these objects and produces the following PATH records (simplifed):
> > > > nametype=PARENT name="dir1/"
> > > > nametype=DELETE name="dir1/file1"
> > > > nametype=PARENT name="dir2/"
> > > > nametype=CREATE name="dir2/file2"
> > > >
> > > > Notice that for the PARENT objects the .name_len is truncated to only
> > > > the directory component.
> > > >
> > > > EXAMPLE #2 (The single-path-component case):
> > > > 1. A userspace process ca

Re: [PATCH ghak95] audit: Do not log full CWD path on empty relative paths

2018-10-31 Thread Ondrej Mosnacek
Sorry for the long-delayed reply, the SELinux world is keeping me
quite busy right now :)

On Wed, Sep 19, 2018 at 5:44 PM Paul Moore  wrote:
> On Wed, Sep 19, 2018 at 7:01 AM Ondrej Mosnacek  wrote:
> > On Wed, Sep 19, 2018 at 3:35 AM Paul Moore  wrote:
> > > On Thu, Sep 13, 2018 at 10:13 AM Paul Moore  wrote:
> > > > On Thu, Sep 13, 2018 at 9:58 AM Ondrej Mosnacek  
> > > > wrote:
> > > > > Paul, could you please answer this question so I can move forward? :)
> > > >
> > > > Yep, sorry for the delay ...
> > >
> > > I just went back over the original problem, your proposed fix, and all
> > > of the discussion in this thread.
> > >
> > > Sadly, I don't think the patch you have proposed is the right fix.
> > >
> > > As Steve has pointed out, the CWD path is the working directory from
> > > which the current process was executed.  I believe we should log the
> > > full path, or as complete a path as possible, in the nametype=CWD PATH
> > > records.  While the nametype=PARENT PATH records have a connection
> > > with some of the other PATH records (e.g. DELETE and CREATE), the
> > > nametype=PARENT PATH records are independent of the current working
> > > directory, although they sometimes may be the same; in the cases where
> > > they are the same, this is purely a coincidence and is due to
> > > operation being performed, not something that should be seen as a
> > > flaw.
> > >
> > > From what I can tell, there are issues involving the nametype=PARENT
> > > PATH records, especially when it comes to the *at() syscalls, but no
> > > issue where the nametype=CWD PATH records have been wrong, is that
> > > correct?
> >
> > Sorry, but I think you are completely misunderstanding the problem...
> > I tried to explain it several times in different ways, but apparently
> > I'm still not doing it right...
> >
> > First of all, there is no "nametype=CWD" PATH record. There is only
> > the classic CWD record that is associated to every syscall and I don't
> > touch that one at all. The information in the CWD record is perfectly
> > fine.
>
> Yes, that was a casualty of me looking at too many audit logs too late
> in the day, I mistakenly typed it as a nametype PATH record when CWD
> is its own record type.  My apologies.
>
> > Let me try to demonstrate it with some more verbose examples. (TL;DR:
> > The info in the CWD record is correct, but it is being abused in
> > audit_log_name().)
> >
> > EXAMPLE #1 (The non-edge case):
> > 1. A userspace process calls rename("dir1/file1", "dir2/file2") with
> > CWD set to "/home/user".
> > 2. The syscall causes four calls to __audit_inode(), which generate
> > four 'struct audit_names' objects with the following information
> > (maybe not in this specific order, but that doesn't matter):
> > .name = "dir1/file1", .type = AUDIT_TYPE_PARENT, .name_len = 5
> > .name = "dir1/file1", .type = AUDIT_TYPE_DELETE, .name_len = AUDIT_NAME_FULL
> > .name = "dir2/file2", .type = AUDIT_TYPE_PARENT, .name_len = 5
> > .name = "dir2/file2", .type = AUDIT_TYPE_CREATE, .name_len = AUDIT_NAME_FULL
> > 3. At the end of the syscall, audit_log_name()  is called on each of
> > these objects and produces the following PATH records (simplifed):
> > nametype=PARENT name="dir1/"
> > nametype=DELETE name="dir1/file1"
> > nametype=PARENT name="dir2/"
> > nametype=CREATE name="dir2/file2"
> >
> > Notice that for the PARENT objects the .name_len is truncated to only
> > the directory component.
> >
> > EXAMPLE #2 (The single-path-component case):
> > 1. A userspace process calls rename("file1", "file2") with CWD set to
> > "/home/user".
> > 2. The 'struct audit_names' objects will now be:
> > .name = "file1", .type = AUDIT_TYPE_PARENT, .name_len = 0
> > .name = "file1", .type = AUDIT_TYPE_DELETE, .name_len = AUDIT_NAME_FULL
> > .name = "file2", .type = AUDIT_TYPE_PARENT, .name_len = 0
> > .name = "file2", .type = AUDIT_TYPE_CREATE, .name_len = AUDIT_NAME_FULL
> > 3. At the end of the syscall, audit_log_name()  is called on each of
> > these objects and produces the following PATH records (simplifed):
> > nametype=PARENT name="/home/user"
> > nametype=DELETE name="file1"
> > nametype=PARENT name="/home/user"
> > nametype=CREATE name=&quo

Re: [PATCH ghak10 v5 1/2] audit: Add functions to log time adjustments

2018-09-21 Thread Ondrej Mosnacek
On Mon, Sep 17, 2018 at 4:51 PM Paul Moore  wrote:
> On Mon, Sep 17, 2018 at 8:38 AM Ondrej Mosnacek  wrote:
> >
> > On Fri, Sep 14, 2018 at 5:19 AM Paul Moore  wrote:
> > > On Fri, Aug 24, 2018 at 8:00 AM Ondrej Mosnacek  
> > > wrote:
> > > > This patch adds two auxiliary record types that will be used to annotate
> > > > the adjtimex SYSCALL records with the NTP/timekeeping values that have
> > > > been changed.
> > > >
> > > > Next, it adds two functions to the audit interface:
> > > >  - audit_tk_injoffset(), which will be called whenever a timekeeping
> > > >offset is injected by a syscall from userspace,
> > > >  - audit_ntp_adjust(), which will be called whenever an NTP internal
> > > >variable is changed by a syscall from userspace.
> > > >
> > > > Quick reference for the fields of the new records:
> > > > AUDIT_TIME_INJOFFSET
> > > > sec - the 'seconds' part of the offset
> > > > nsec - the 'nanoseconds' part of the offset
> > > > AUDIT_TIME_ADJNTPVAL
> > > > op - which value was adjusted:
> > > > offset - corresponding to the time_offset variable
> > > > freq   - corresponding to the time_freq variable
> > > > status - corresponding to the time_status variable
> > > > adjust - corresponding to the time_adjust variable
> > > > tick   - corresponding to the tick_usec variable
> > > > tai- corresponding to the timekeeping's TAI offset
> > >
> > > I understand that reusing "op" is tempting, but the above aren't
> > > really operations, they are state variables which are being changed.
> >
> > I remember Steve (or was it Richard?) convincing me at one of the
> > meetings that "op" is the right filed name to use, despite it not
> > being a name for an operation... But I don't really care, I'm okay
> > with changing it to e.g. "var" as Richard suggests later in this
> > thread.
>
> As I said before, this seems like an abuse of the "op" field.
>
> > > Using the CONFIG_CHANGE record as a basis, I wonder if we are better
> > > off with something like the following:
> > >
> > >  type=TIME_CHANGE = old=
> > >
> > > ... you might need to preface the variable names with something like
> > > "ntp_" or "offset_".  You'll notice I'm also suggesting we use a
> > > single record type here; is there any reason why two records types are
> > > required?
> >
> > There are actually two reasons:
> > 1. The injected offset is a timespec64, so it consists of two integer
> > values (and it would be weird to produce two records for it, since IMO
> > it is conceptually still a single variable).
> > 2. In all other cases the variable is reset to the (possibly
> > transformed) input value, while in this case the input value is added
> > directly to the system time. This can be viewed as a kind of variable
> > too, but it would be weird to report old and new value for it, since
> > its value flows with time.
> >
> > Plus, when I look at:
> > type=TIME_INJOFFSET [...]: sec=-16 nsec=124887145
> >
> > I can immediately see that the time was shifted back by 16-something
> > seconds, while when I look at something like:
> >
> > type=TIME_CHANGE [...]: var=time_sec new=1537185685 old=1537185701
> > type=TIME_CHANGE [...]: var=time_nsec new=664373417 old=789260562
> >
> > I can just see some big numbers that I need to do math with before I
> > get an idea of what is the magnitude (or sign) of the change.
>
> Okay, with that in mind, perhaps when recording the offset values we
> omit the "old" values (arguably that doesn't make much sense here) and
> keep the sec/nsec split:
>
> type=TIME_CHANGE [...]: offset_sec= offset_nsec=
>
> ... and for all others we stick with:
>
> type=TIME_CHANGE [...]: ntp_= old=

Alright, that format would work. However, I would still like to have a
separate type for the offset injection, since it has different field
structure and semantics (difference vs. new+old). I don't see any
reason to sacrifice the distinction for just one record type slot
(AFAIK we technically still have about 2 billion left...).

(Maybe you just duplicated the record type by mistake, in that case
please disregard the last sentence.)

>
> ... and if that results in multiple TIME_CHANGE records for a given
> event, that's fine with me.

Re: [PATCH ghak95] audit: Do not log full CWD path on empty relative paths

2018-09-19 Thread Ondrej Mosnacek
On Wed, Sep 19, 2018 at 3:35 AM Paul Moore  wrote:
> On Thu, Sep 13, 2018 at 10:13 AM Paul Moore  wrote:
> > On Thu, Sep 13, 2018 at 9:58 AM Ondrej Mosnacek  wrote:
> > > Paul, could you please answer this question so I can move forward? :)
> >
> > Yep, sorry for the delay ...
>
> I just went back over the original problem, your proposed fix, and all
> of the discussion in this thread.
>
> Sadly, I don't think the patch you have proposed is the right fix.
>
> As Steve has pointed out, the CWD path is the working directory from
> which the current process was executed.  I believe we should log the
> full path, or as complete a path as possible, in the nametype=CWD PATH
> records.  While the nametype=PARENT PATH records have a connection
> with some of the other PATH records (e.g. DELETE and CREATE), the
> nametype=PARENT PATH records are independent of the current working
> directory, although they sometimes may be the same; in the cases where
> they are the same, this is purely a coincidence and is due to
> operation being performed, not something that should be seen as a
> flaw.
>
> From what I can tell, there are issues involving the nametype=PARENT
> PATH records, especially when it comes to the *at() syscalls, but no
> issue where the nametype=CWD PATH records have been wrong, is that
> correct?

Sorry, but I think you are completely misunderstanding the problem...
I tried to explain it several times in different ways, but apparently
I'm still not doing it right...

First of all, there is no "nametype=CWD" PATH record. There is only
the classic CWD record that is associated to every syscall and I don't
touch that one at all. The information in the CWD record is perfectly
fine.

Let me try to demonstrate it with some more verbose examples. (TL;DR:
The info in the CWD record is correct, but it is being abused in
audit_log_name().)

EXAMPLE #1 (The non-edge case):
1. A userspace process calls rename("dir1/file1", "dir2/file2") with
CWD set to "/home/user".
2. The syscall causes four calls to __audit_inode(), which generate
four 'struct audit_names' objects with the following information
(maybe not in this specific order, but that doesn't matter):
.name = "dir1/file1", .type = AUDIT_TYPE_PARENT, .name_len = 5
.name = "dir1/file1", .type = AUDIT_TYPE_DELETE, .name_len = AUDIT_NAME_FULL
.name = "dir2/file2", .type = AUDIT_TYPE_PARENT, .name_len = 5
.name = "dir2/file2", .type = AUDIT_TYPE_CREATE, .name_len = AUDIT_NAME_FULL
3. At the end of the syscall, audit_log_name()  is called on each of
these objects and produces the following PATH records (simplifed):
nametype=PARENT name="dir1/"
nametype=DELETE name="dir1/file1"
nametype=PARENT name="dir2/"
nametype=CREATE name="dir2/file2"

Notice that for the PARENT objects the .name_len is truncated to only
the directory component.

EXAMPLE #2 (The single-path-component case):
1. A userspace process calls rename("file1", "file2") with CWD set to
"/home/user".
2. The 'struct audit_names' objects will now be:
.name = "file1", .type = AUDIT_TYPE_PARENT, .name_len = 0
.name = "file1", .type = AUDIT_TYPE_DELETE, .name_len = AUDIT_NAME_FULL
.name = "file2", .type = AUDIT_TYPE_PARENT, .name_len = 0
.name = "file2", .type = AUDIT_TYPE_CREATE, .name_len = AUDIT_NAME_FULL
3. At the end of the syscall, audit_log_name()  is called on each of
these objects and produces the following PATH records (simplifed):
nametype=PARENT name="/home/user"
nametype=DELETE name="file1"
nametype=PARENT name="/home/user"
nametype=CREATE name="file2"

Notice that in this case, the "clever" logic in audit_log_name()
wanted to avoid logging an empty path (name="") in the PARENT records,
so it instead put the CWD path in there ("/home/user"). In this case
this is perfectly valid (although could be a bit surprising that there
is suddenly a full path instead of a relative one), since the full
path of "file1" is actually "/home/user/file1".

EXAMPLE #3 (The non-edge renameat(2) case):
1. A userspace process calls the following syscalls (with CWD set to
"/home/user"):
int srcfd = open("/some/path1", O_DIRECTORY | O_PATH);
int dstfd = open("/another/path2", O_DIRECTORY | O_PATH);
renameat(srcfd, "dir1/file1", dstfd, "dir2/file2");
2. The 'name', 'type' and 'name_len' fields of the 'struct
audit_names' objects will now be exactly the same as in EXAMPLE #1:
.name = "dir1/file1", .type = AUDIT_TYPE_PARENT, .name_len = 5
.name = "dir1/file1", .type = AUDIT_TYPE_DELETE, .name_len = AUDIT_NAME_FULL
.name = "dir2/file2", .type = AUDIT_TYPE_PARENT, .name_len =

Re: [PATCH ghak10 v5 1/2] audit: Add functions to log time adjustments

2018-09-17 Thread Ondrej Mosnacek
On Fri, Sep 14, 2018 at 5:19 AM Paul Moore  wrote:
> On Fri, Aug 24, 2018 at 8:00 AM Ondrej Mosnacek  wrote:
> > This patch adds two auxiliary record types that will be used to annotate
> > the adjtimex SYSCALL records with the NTP/timekeeping values that have
> > been changed.
> >
> > Next, it adds two functions to the audit interface:
> >  - audit_tk_injoffset(), which will be called whenever a timekeeping
> >offset is injected by a syscall from userspace,
> >  - audit_ntp_adjust(), which will be called whenever an NTP internal
> >variable is changed by a syscall from userspace.
> >
> > Quick reference for the fields of the new records:
> > AUDIT_TIME_INJOFFSET
> > sec - the 'seconds' part of the offset
> > nsec - the 'nanoseconds' part of the offset
> > AUDIT_TIME_ADJNTPVAL
> > op - which value was adjusted:
> > offset - corresponding to the time_offset variable
> > freq   - corresponding to the time_freq variable
> > status - corresponding to the time_status variable
> > adjust - corresponding to the time_adjust variable
> > tick   - corresponding to the tick_usec variable
> > tai- corresponding to the timekeeping's TAI offset
>
> I understand that reusing "op" is tempting, but the above aren't
> really operations, they are state variables which are being changed.

I remember Steve (or was it Richard?) convincing me at one of the
meetings that "op" is the right filed name to use, despite it not
being a name for an operation... But I don't really care, I'm okay
with changing it to e.g. "var" as Richard suggests later in this
thread.

> Using the CONFIG_CHANGE record as a basis, I wonder if we are better
> off with something like the following:
>
>  type=TIME_CHANGE = old=
>
> ... you might need to preface the variable names with something like
> "ntp_" or "offset_".  You'll notice I'm also suggesting we use a
> single record type here; is there any reason why two records types are
> required?

There are actually two reasons:
1. The injected offset is a timespec64, so it consists of two integer
values (and it would be weird to produce two records for it, since IMO
it is conceptually still a single variable).
2. In all other cases the variable is reset to the (possibly
transformed) input value, while in this case the input value is added
directly to the system time. This can be viewed as a kind of variable
too, but it would be weird to report old and new value for it, since
its value flows with time.

Plus, when I look at:
type=TIME_INJOFFSET [...]: sec=-16 nsec=124887145

I can immediately see that the time was shifted back by 16-something
seconds, while when I look at something like:

type=TIME_CHANGE [...]: var=time_sec new=1537185685 old=1537185701
type=TIME_CHANGE [...]: var=time_nsec new=664373417 old=789260562

I can just see some big numbers that I need to do math with before I
get an idea of what is the magnitude (or sign) of the change.

>
> > old - the old value
> > new - the new value
> >
> > Signed-off-by: Ondrej Mosnacek 
> > ---
> >  include/linux/audit.h  | 21 +
> >  include/uapi/linux/audit.h |  2 ++
> >  kernel/auditsc.c   | 15 +++
> >  3 files changed, 38 insertions(+)
>
> A reminder that we need tests for these new records and a RFE page on the 
> wiki:
>
> * https://github.com/linux-audit/audit-testsuite

I was going to start working on this once the format issues are
settled. (Although I probably should have kept the RFC in the subject
until then...)

> * https://github.com/linux-audit/audit-kernel/wiki

I admit I forgot about this duty, but again I would like to wait for
the discussions to settle before writing that up.

>
> --
> paul moore
> www.paul-moore.com--
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [PATCH ghak10 v5 1/2] audit: Add functions to log time adjustments

2018-09-17 Thread Ondrej Mosnacek
On Fri, Sep 14, 2018 at 5:09 AM Paul Moore  wrote:
> On Thu, Sep 13, 2018 at 9:59 AM Ondrej Mosnacek  wrote:
> > On Mon, Aug 27, 2018 at 6:38 PM Steve Grubb  wrote:
> > > On Monday, August 27, 2018 5:13:17 AM EDT Ondrej Mosnacek wrote:
> > > > On Mon, Aug 27, 2018 at 9:50 AM Miroslav Lichvar 
> > > wrote:
> > > > > On Fri, Aug 24, 2018 at 02:00:00PM +0200, Ondrej Mosnacek wrote:
> > > > > > This patch adds two auxiliary record types that will be used to
> > > > > > annotate
> > > > > > the adjtimex SYSCALL records with the NTP/timekeeping values that 
> > > > > > have
> > > > > > been changed.
> > > > >
> > > > > It seems the "adjust" function intentionally logs also calls/modes
> > > > > that don't actually change anything. Can you please explain it a bit
> > > > > in the message?
> > > > >
> > > > > NTP/PTP daemons typically don't read the adjtimex values in a normal
> > > > > operation and overwrite them on each update, even if they don't
> > > > > change. If the audit function checked that oldval != newval, the
> > > > > number of messages would be reduced and it might be easier to follow.
> > > >
> > > > We actually want to log any attempt to change a value, as even an
> > > > intention to set/change something could be a hint that the process is
> > > > trying to do something bad (see discussion at [1]).
> > >
> > > One of the problems is that these applications can flood the logs very
> > > quickly. An attempt to change is not needed unless it fails for 
> > > permissions
> > > reasons. So, limiting to actual changes is probably a good thing.
> >
> > Well, Richard seemed to "violently" agree with the opposite, so now I
> > don't know which way to go... Paul, you are the official tie-breaker
> > here, which do you prefer?
>
> The general idea is that we only care about *changes* to the system
> state, so if a process is setting a variable to with a value that
> matches it's current value I see no reason why we need to generate a
> change record.
>
> Another thing to keep in mind, we can always change the behavior to be
> more verbose (*always* generate a record, regardless of value) without
> likely causing a regression, but limiting records is more difficult
> and more likely to cause regressions.

OK, that makes sense. I'll limit logging to actual changes in the next revision.

>
> --
> paul moore
> www.paul-moore.com

--
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [PATCH ghak10 v5 1/2] audit: Add functions to log time adjustments

2018-09-17 Thread Ondrej Mosnacek
On Thu, Sep 13, 2018 at 5:59 PM Richard Guy Briggs  wrote:
> On 2018-08-27 10:28, Ondrej Mosnacek wrote:
> > On Fri, Aug 24, 2018 at 8:33 PM John Stultz  wrote:
> > > On Fri, Aug 24, 2018 at 5:00 AM, Ondrej Mosnacek  
> > > wrote:
> > > > This patch adds two auxiliary record types that will be used to annotate
> > > > the adjtimex SYSCALL records with the NTP/timekeeping values that have
> > > > been changed.
> > > >
> > > > Next, it adds two functions to the audit interface:
> > > >  - audit_tk_injoffset(), which will be called whenever a timekeeping
> > > >offset is injected by a syscall from userspace,
> > > >  - audit_ntp_adjust(), which will be called whenever an NTP internal
> > > >variable is changed by a syscall from userspace.
> > > >
> > > > Quick reference for the fields of the new records:
> > > > AUDIT_TIME_INJOFFSET
> > > > sec - the 'seconds' part of the offset
> > > > nsec - the 'nanoseconds' part of the offset
> > > > AUDIT_TIME_ADJNTPVAL
> > > > op - which value was adjusted:
> > > > offset - corresponding to the time_offset variable
> > > > freq   - corresponding to the time_freq variable
> > > > status - corresponding to the time_status variable
> > > > adjust - corresponding to the time_adjust variable
> > > > tick   - corresponding to the tick_usec variable
> > > > tai- corresponding to the timekeeping's TAI offset
> > > > old - the old value
> > > > new - the new value
> > > >
> > > > Signed-off-by: Ondrej Mosnacek 
> > > > ---
> > > >  include/linux/audit.h  | 21 +
> > > >  include/uapi/linux/audit.h |  2 ++
> > > >  kernel/auditsc.c   | 15 +++
> > > >  3 files changed, 38 insertions(+)
> > > >
> > > > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > > > index 9334fbef7bae..0d084d4b4042 100644
> > > > --- a/include/linux/audit.h
> > > > +++ b/include/linux/audit.h
> > > > @@ -26,6 +26,7 @@
> > > >  #include 
> > > >  #include 
> > > >  #include 
> > > > +#include 
> > > >
> > > >  #define AUDIT_INO_UNSET ((unsigned long)-1)
> > > >  #define AUDIT_DEV_UNSET ((dev_t)-1)
> > > > @@ -356,6 +357,8 @@ extern void __audit_log_capset(const struct cred 
> > > > *new, const struct cred *old);
> > > >  extern void __audit_mmap_fd(int fd, int flags);
> > > >  extern void __audit_log_kern_module(char *name);
> > > >  extern void __audit_fanotify(unsigned int response);
> > > > +extern void __audit_tk_injoffset(struct timespec64 offset);
> > > > +extern void __audit_ntp_adjust(const char *type, s64 oldval, s64 
> > > > newval);
> > > >
> > > >  static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
> > > >  {
> > > > @@ -458,6 +461,18 @@ static inline void audit_fanotify(unsigned int 
> > > > response)
> > > > __audit_fanotify(response);
> > > >  }
> > > >
> > > > +static inline void audit_tk_injoffset(struct timespec64 offset)
> > > > +{
> > > > +   if (!audit_dummy_context())
> > > > +   __audit_tk_injoffset(offset);
> > > > +}
> > > > +
> > > > +static inline void audit_ntp_adjust(const char *type, s64 oldval, s64 
> > > > newval)
> > > > +{
> > > > +   if (!audit_dummy_context())
> > > > +   __audit_ntp_adjust(type, oldval, newval);
> > > > +}
> > > > +
> > > >  extern int audit_n_rules;
> > > >  extern int audit_signals;
> > > >  #else /* CONFIG_AUDITSYSCALL */
> > > > @@ -584,6 +599,12 @@ static inline void audit_log_kern_module(char 
> > > > *name)
> > > >  static inline void audit_fanotify(unsigned int response)
> > > >  { }
> > > >
> > > > +static inline void audit_tk_injoffset(struct timespec64 offset)
> > > > +{ }
> > > > +
> > > > +static inline void audit_ntp_adjust(const char *type, s64 oldval, s64 
> > > > newval)
> > > > +{ }
> > > > +
> > > >  static in

Re: [PATCH ghak10 v5 1/2] audit: Add functions to log time adjustments

2018-09-13 Thread Ondrej Mosnacek
On Mon, Aug 27, 2018 at 6:38 PM Steve Grubb  wrote:
> On Monday, August 27, 2018 5:13:17 AM EDT Ondrej Mosnacek wrote:
> > On Mon, Aug 27, 2018 at 9:50 AM Miroslav Lichvar 
> wrote:
> > > On Fri, Aug 24, 2018 at 02:00:00PM +0200, Ondrej Mosnacek wrote:
> > > > This patch adds two auxiliary record types that will be used to
> > > > annotate
> > > > the adjtimex SYSCALL records with the NTP/timekeeping values that have
> > > > been changed.
> > >
> > > It seems the "adjust" function intentionally logs also calls/modes
> > > that don't actually change anything. Can you please explain it a bit
> > > in the message?
> > >
> > > NTP/PTP daemons typically don't read the adjtimex values in a normal
> > > operation and overwrite them on each update, even if they don't
> > > change. If the audit function checked that oldval != newval, the
> > > number of messages would be reduced and it might be easier to follow.
> >
> > We actually want to log any attempt to change a value, as even an
> > intention to set/change something could be a hint that the process is
> > trying to do something bad (see discussion at [1]).
>
> One of the problems is that these applications can flood the logs very
> quickly. An attempt to change is not needed unless it fails for permissions
> reasons. So, limiting to actual changes is probably a good thing.

Well, Richard seemed to "violently" agree with the opposite, so now I
don't know which way to go... Paul, you are the official tie-breaker
here, which do you prefer?

>
> -Steve
>
> > There are valid
> > arguments both for and against this choice, but we have to pick one in
> > the end... Anyway, I should explain the reasoning in the commit
> > message better, right now it just states the fact without explanation
> > (in the second patch), thank you for pointing my attention to it.
> >
> > [1] https://www.redhat.com/archives/linux-audit/2018-July/msg00061.html
> >
> > --
> > Ondrej Mosnacek 
> > Associate Software Engineer, Security Technologies
> > Red Hat, Inc.
>
>
>
>

--
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [RFC PATCH ghak10 v4 0/2] audit: Log modifying adjtimex(2) calls

2018-09-13 Thread Ondrej Mosnacek
On Fri, Aug 24, 2018 at 4:56 PM Steve Grubb  wrote:
> On Wednesday, August 22, 2018 5:27:17 PM EDT Paul Moore wrote:
> > On Tue, Aug 21, 2018 at 3:21 AM Miroslav Lichvar 
> wrote:
> > > > On Mon, 20 Aug 2018, Ondrej Mosnacek wrote:
> > > > > @John or other timekeeping/NTP folks: We had a discussion on the
> > > > > audit
> > > > > ML on which of the internal timekeeping/NTP variables we should
> > > > > actually
> > > > > log changes for. We are only interested in variables that can
> > > > > (directly
> > > > > or indirectly) cause noticeable changes to the system clock, but
> > > > > since we
> > > > > have only limited understanding of the NTP code, we would like to ask
> > > > > you for advice on which variables are security relevant.
> > >
> > > I guess that mostly depends on whether you consider setting the clock
> > > to run faster or slower than real time to be an important event for
> > > the audit.
> > >
> > > > > - NTP value adjustments:
> > > > > - time_offset (probably important)
> > >
> > > This can adjust the clock by up to 0.5 seconds per call and also speed
> > > it up or slow down by up to about 0.05% (43 seconds per day).
> >
> > This seems worthwhile.
> >
> > > > > - time_freq (maybe not important?)
> > >
> > > This can speed up or slow down by up to about 0.05%.
> >
> > This too.
> >
> > > > > - time_status (likely important, can cause leap second injection)
> > >
> > > Yes, it can insert/delete leap seconds and it also enables/disables
> > > synchronization of the hardware real-time clock.
> >
> > This one as well.
> >
> > > > > - time_maxerror (maybe not important?)
> > > > > - time_esterror (maybe not important?)
> > >
> > > These two change the error estimates that are reported to applications
> > > using ntp_gettime()/adjtimex(). If an application was periodically
> > > checking that the clock is synchronized with some specified accuracy
> > > and setting the maxerror to a larger value would cause the application
> > > to abort, would it be an important event in the audit?
> >
> > Since these don't really affect the time, just the expected error, I'm
> > not sure this is important.
>
> I don't think so.

Sorry, just to make sure I understand it right - do you (also) not
think it is important or do you not think it is not important? :)

--
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [PATCH ghak95] audit: Do not log full CWD path on empty relative paths

2018-09-13 Thread Ondrej Mosnacek
On Mon, Aug 27, 2018 at 3:00 PM Ondrej Mosnacek  wrote:
> On Fri, Aug 24, 2018 at 4:09 PM Paul Moore  wrote:
> >
> > On Fri, Aug 3, 2018 at 3:08 AM Ondrej Mosnacek  wrote:
> > > On Fri, Aug 3, 2018 at 12:24 AM Paul Moore  wrote:
> > > > On Thu, Aug 2, 2018 at 7:45 AM Ondrej Mosnacek  
> > > > wrote:
> > > > >
> > > > > When a relative path has just a single component and we want to emit a
> > > > > nametype=PARENT record, the current implementation just reports the 
> > > > > full
> > > > > CWD path (which is alrady available in the audit context).
> > > > >
> > > > > This is wrong for three reasons:
> > > > > 1. Wasting log space for redundant data (CWD path is already in the 
> > > > > CWD
> > > > >record).
> > > > > 2. Inconsistency with other PATH records (if a relative PARENT 
> > > > > directory
> > > > >path contains at least one component, only the verbatim relative 
> > > > > path
> > > > >is logged).
> > > > > 3. In some syscalls (e.g. openat(2)) the relative path may not even be
> > > > >relative to the CWD, but to another directory specified as a file
> > > > >descriptor. In that case the logged path is simply plain wrong.
> > > > >
> > > > > This patch modifies this behavior to simply report "." in the
> > > > > aforementioned case, which is equivalent to an "empty" directory path
> > > > > and can be concatenated with the actual base directory path (CWD or
> > > > > dirfd from openat(2)-like syscall) once support for its logging is 
> > > > > added
> > > > > later. In the meantime, defaulting to CWD as base directory on 
> > > > > relative
> > > > > paths (as already done by the userspace tools) will be enough to 
> > > > > achieve
> > > > > results equivalent to the current behavior.
> > > > >
> > > > > See: https://github.com/linux-audit/audit-kernel/issues/95
> > > > >
> > > > > Fixes: 9c937dcc7102 ("[PATCH] log more info for directory entry 
> > > > > change events")
> > > > > Signed-off-by: Ondrej Mosnacek 
> > > > > ---
> > > > >  kernel/audit.c | 9 -
> > > > >  1 file changed, 4 insertions(+), 5 deletions(-)
> > > > >
> > > > > diff --git a/kernel/audit.c b/kernel/audit.c
> > > > > index 2a8058764aa6..4f18bd48eb4b 100644
> > > > > --- a/kernel/audit.c
> > > > > +++ b/kernel/audit.c
> > > > > @@ -2127,28 +2127,27 @@ void audit_log_name(struct audit_context 
> > > > > *context, struct audit_names *n,
> > > > >
> > > > > audit_log_format(ab, "item=%d", record_num);
> > > > >
> > > > > +   audit_log_format(ab, " name=");
> > > > > if (path)
> > > > > -   audit_log_d_path(ab, " name=", path);
> > > > > +   audit_log_d_path(ab, NULL, path);
> > > > > else if (n->name) {
> > > > > switch (n->name_len) {
> > > > > case AUDIT_NAME_FULL:
> > > > > /* log the full path */
> > > > > -   audit_log_format(ab, " name=");
> > > > > audit_log_untrustedstring(ab, n->name->name);
> > > > > break;
> > > > > case 0:
> > > > > /* name was specified as a relative path and 
> > > > > the
> > > > >  * directory component is the cwd */
> > > > > -   audit_log_d_path(ab, " name=", >pwd);
> > > > > +   audit_log_untrustedstring(ab, ".");
> > > >
> > > > This isn't a comprehensive review, I only gave this a quick look, but
> > > > considering you are only logging "." above we can safely use
> > > > audit_log_string() and safe a few cycles.
> > >
> > > I used audit_log_untrustedstring() to maintain the current norm that
> > > the name= field would always contain a quoted string (either in
> > > double-quotes or he

Re: [PATCH ghak95] audit: Do not log full CWD path on empty relative paths

2018-08-27 Thread Ondrej Mosnacek
On Fri, Aug 24, 2018 at 4:09 PM Paul Moore  wrote:
>
> On Fri, Aug 3, 2018 at 3:08 AM Ondrej Mosnacek  wrote:
> > On Fri, Aug 3, 2018 at 12:24 AM Paul Moore  wrote:
> > > On Thu, Aug 2, 2018 at 7:45 AM Ondrej Mosnacek  
> > > wrote:
> > > >
> > > > When a relative path has just a single component and we want to emit a
> > > > nametype=PARENT record, the current implementation just reports the full
> > > > CWD path (which is alrady available in the audit context).
> > > >
> > > > This is wrong for three reasons:
> > > > 1. Wasting log space for redundant data (CWD path is already in the CWD
> > > >record).
> > > > 2. Inconsistency with other PATH records (if a relative PARENT directory
> > > >path contains at least one component, only the verbatim relative path
> > > >is logged).
> > > > 3. In some syscalls (e.g. openat(2)) the relative path may not even be
> > > >relative to the CWD, but to another directory specified as a file
> > > >descriptor. In that case the logged path is simply plain wrong.
> > > >
> > > > This patch modifies this behavior to simply report "." in the
> > > > aforementioned case, which is equivalent to an "empty" directory path
> > > > and can be concatenated with the actual base directory path (CWD or
> > > > dirfd from openat(2)-like syscall) once support for its logging is added
> > > > later. In the meantime, defaulting to CWD as base directory on relative
> > > > paths (as already done by the userspace tools) will be enough to achieve
> > > > results equivalent to the current behavior.
> > > >
> > > > See: https://github.com/linux-audit/audit-kernel/issues/95
> > > >
> > > > Fixes: 9c937dcc7102 ("[PATCH] log more info for directory entry change 
> > > > events")
> > > > Signed-off-by: Ondrej Mosnacek 
> > > > ---
> > > >  kernel/audit.c | 9 -
> > > >  1 file changed, 4 insertions(+), 5 deletions(-)
> > > >
> > > > diff --git a/kernel/audit.c b/kernel/audit.c
> > > > index 2a8058764aa6..4f18bd48eb4b 100644
> > > > --- a/kernel/audit.c
> > > > +++ b/kernel/audit.c
> > > > @@ -2127,28 +2127,27 @@ void audit_log_name(struct audit_context 
> > > > *context, struct audit_names *n,
> > > >
> > > > audit_log_format(ab, "item=%d", record_num);
> > > >
> > > > +   audit_log_format(ab, " name=");
> > > > if (path)
> > > > -   audit_log_d_path(ab, " name=", path);
> > > > +   audit_log_d_path(ab, NULL, path);
> > > > else if (n->name) {
> > > > switch (n->name_len) {
> > > > case AUDIT_NAME_FULL:
> > > > /* log the full path */
> > > > -   audit_log_format(ab, " name=");
> > > > audit_log_untrustedstring(ab, n->name->name);
> > > > break;
> > > > case 0:
> > > > /* name was specified as a relative path and the
> > > >  * directory component is the cwd */
> > > > -   audit_log_d_path(ab, " name=", >pwd);
> > > > +   audit_log_untrustedstring(ab, ".");
> > >
> > > This isn't a comprehensive review, I only gave this a quick look, but
> > > considering you are only logging "." above we can safely use
> > > audit_log_string() and safe a few cycles.
> >
> > I used audit_log_untrustedstring() to maintain the current norm that
> > the name= field would always contain a quoted string (either in
> > double-quotes or hex-escaped). I don't know if such consistency is
> > important for parsing in userspace (it should probably be robust
> > enough to handle any format), but I wanted to be on the safe side.
>
> In this particular case there should be no visible difference in the
> resulting record and audit_log_string() is going to have less overhead
> in the kernel.

OK, so should I just replace it with:

audit_log_string(ab, ".");

or should I still escape the path manually:

audit_log_string(ab, "\".\"");

?

>
> > > Honestly, looking at the rest of th

Re: [PATCH ghak95] audit: Do not log full CWD path on empty relative paths

2018-08-27 Thread Ondrej Mosnacek
On Fri, Aug 24, 2018 at 5:14 PM Steve Grubb  wrote:
> On Friday, August 24, 2018 11:00:35 AM EDT Paul Moore wrote:
> > On Thu, Aug 2, 2018 at 8:03 PM Paul Moore  wrote:
> > > On Thu, Aug 2, 2018 at 7:45 AM Ondrej Mosnacek 
> wrote:
> > > > When a relative path has just a single component and we want to emit a
> > > > nametype=PARENT record, the current implementation just reports the
> > > > full CWD path (which is alrady available in the audit context).
>
> It is supposed to report the parent directory of the object (file). Never
> mind about CWD. That tells us where the command was issued from. Sometimes
> that is important even if it is already in a PATH record. It is more forensic
> information.

Yes, the problem is that if the path is just a file name (say,
"file.txt"), then the kernel assumes that the parent directory is the
CWD and puts its absolute path into the PATH record (probably because
putting in an empty path seemed weird or is not even valid). But with
*at(2) syscalls the parent directory can be some other directory
(specified by the dirfd argument of the syscall), so the assumption is
wrong. In both cases we really should report relative path to the
directory, which is always just ".". This is consistent with how other
relative paths are handled, e.g. "dir/subdir/file.txt" will produce a
parent PATH record with "dir/subdir" (the path stays relative) and a
child record with "file.txt".

>
> > > > This is wrong for three reasons:
> > > > 1. Wasting log space for redundant data (CWD path is already in the CWD
> > > > record).
>
> A CWD record is always expected for a file system operation. We are not
> missing any right now. Just don't want to lose them.
>
> > > > 2. Inconsistency with other PATH records (if a relative PARENT
> > > > directory path contains at least one component, only the verbatim
> > > > relative path is logged).
> > > > 3. In some syscalls (e.g. openat(2)) the relative path may not even be
> > > > relative to the CWD, but to another directory specified as a file
> > > > descriptor. In that case the logged path is simply plain wrong.
>
> This can be fixed in the reporting tools. The biggest problem is when we have
> several PATH records figuring our how they are all related.

Yes, but to enable fixing this, we need to keep relative paths
relative. Only then can we properly do the next step of:
a) adding sufficient information to specify what directory the path is
relative to (basically what GHAK #9 is about),
b) recognizing this information in userspace and converting relative
paths to absolute based on that information.

>
> > > > This patch modifies this behavior to simply report "." in the
> > > > aforementioned case, which is equivalent to an "empty" directory path
> > > > and can be concatenated with the actual base directory path (CWD or
> > > > dirfd from openat(2)-like syscall) once support for its logging is
> > > > added later. In the meantime, defaulting to CWD as base directory on
> > > > relative paths (as already done by the userspace tools) will be enough
> > > > to achieve results equivalent to the current behavior.
> > >
> > > I have to ask the obvious question, if we already have the necessary
> > > parent path in the CWD record, why do we need a nametype=parent PATH
> > > record anyway?
>
> CWD is where the command was issued from. Sometimes it can be used as a
> PARENT PATH record. But what if name resolution fails at the parent
> directory? That record turns out to be all we get.
>
> > > Can we safely remove it or will that cause problems for Steve's userspace
> > > tools?
>
> The PARENT records are used in figuring out what is really happening in
> certain cases.
>
> -Steve
>
>

--
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [PATCH ghak10 v5 2/2] timekeeping/ntp: Audit clock/NTP params adjustments

2018-08-27 Thread Ondrej Mosnacek
On Fri, Aug 24, 2018 at 9:51 PM Richard Guy Briggs  wrote:
> On 2018-08-24 14:00, Ondrej Mosnacek wrote:
> > This patch adds logging of all attempts to either inject an offset into
> > the clock (producing an AUDIT_TIME_INJOFFSET record) or adjust an NTP
> > parameter (producing an AUDIT_TIME_ADJNTPVAL record).
>
> I thought I saw it suggested earlier in one of the replies to a previous
> revision of the patchset to separate the two types of records with their
> calling circumstances.  The inj-offset bits could stand alone in their
> own patch leaving all the rest in its own patch.  The record numbers and
> examples are easier to offer when given together, but they aren't as
> clear they are indepnendent records and callers.  That way, each patch
> stands on its own.  (more below)

Well, the idea of current split-up is to separate changes in different
subsystems. I would argue that the two record types are related enough
(and the diffs short enough) that it is worth keeping them together.

>
> > For reference, running the following commands:
> >
> > auditctl -D
> > auditctl -a exit,always -F arch=b64 -S adjtimex
> > chronyd -q
> >
> > produces audit records like this:
> >
> > type=TIME_ADJNTPVAL msg=audit(1530616044.507:5): op=adjust old=0 new=0
> > type=SYSCALL msg=audit(1530616044.507:5): arch=c03e syscall=159 
> > success=yes exit=5 a0=7fff57e78c00 a1=0 a2=4 a3=7f754ae28c0a items=0 
> > ppid=626 pid=629 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 
> > fsgid=0 tty=(none) ses=1 comm="chronyd" exe="/usr/sbin/chronyd" 
> > subj=system_u:system_r:kernel_t:s0 key=(null)
> > type=PROCTITLE msg=audit(1530616044.507:5): proctitle=6368726F6E7964002D71
> > type=SYSCALL msg=audit(1530616044.507:6): arch=c03e syscall=159 
> > success=yes exit=5 a0=7fff57e78c00 a1=1 a2=1 a3=7f754ae28c0a items=0 
> > ppid=626 pid=629 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 
> > fsgid=0 tty=(none) ses=1 comm="chronyd" exe="/usr/sbin/chronyd" 
> > subj=system_u:system_r:kernel_t:s0 key=(null)
> > type=PROCTITLE msg=audit(1530616044.507:6): proctitle=6368726F6E7964002D71
> > type=TIME_INJOFFSET msg=audit(1530616044.507:7): sec=0 nsec=0
> > type=TIME_ADJNTPVAL msg=audit(1530616044.507:7): op=status old=64 new=8256
> > type=SYSCALL msg=audit(1530616044.507:7): arch=c03e syscall=159 
> > success=yes exit=5 a0=7fff57e78c00 a1=1 a2=1 a3=7f754ae28c0a items=0 
> > ppid=626 pid=629 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 
> > fsgid=0 tty=(none) ses=1 comm="chronyd" exe="/usr/sbin/chronyd" 
> > subj=system_u:system_r:kernel_t:s0 key=(null)
> > type=PROCTITLE msg=audit(1530616044.507:7): proctitle=6368726F6E7964002D71
> > type=TIME_ADJNTPVAL msg=audit(1530616044.507:8): op=status old=8256 new=8257
> > type=TIME_ADJNTPVAL msg=audit(1530616044.507:8): op=offset old=0 new=0
> > type=TIME_ADJNTPVAL msg=audit(1530616044.507:8): op=freq old=0 new=0
> > type=SYSCALL msg=audit(1530616044.507:8): arch=c03e syscall=159 
> > success=yes exit=5 a0=7fff57e78ab0 a1=0 a2=55e129c850c0 a3=7f754ae28c0a 
> > items=0 ppid=626 pid=629 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 
> > sgid=0 fsgid=0 tty=(none) ses=1 comm="chronyd" exe="/usr/sbin/chronyd" 
> > subj=system_u:system_r:kernel_t:s0 key=(null)
> > type=PROCTITLE msg=audit(1530616044.507:8): proctitle=6368726F6E7964002D71
> > type=TIME_ADJNTPVAL msg=audit(1530616044.507:9): op=status old=8257 new=64
> > type=SYSCALL msg=audit(1530616044.507:9): arch=c03e syscall=159 
> > success=yes exit=5 a0=7fff57e78ab0 a1=0 a2=55e129c850c0 a3=7f754ae28c0a 
> > items=0 ppid=626 pid=629 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 
> > sgid=0 fsgid=0 tty=(none) ses=1 comm="chronyd" exe="/usr/sbin/chronyd" 
> > subj=system_u:system_r:kernel_t:s0 key=(null)
> > type=PROCTITLE msg=audit(1530616044.507:9): proctitle=6368726F6E7964002D71
> > type=SYSCALL msg=audit(1530616044.507:10): arch=c03e syscall=159 
> > success=yes exit=5 a0=7fff57e78a70 a1=0 a2=55e129c850c0 a3=7f754ae28c0a 
> > items=0 ppid=626 pid=629 auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 
> > sgid=0 fsgid=0 tty=(none) ses=1 comm="chronyd" exe="/usr/sbin/chronyd" 
> > subj=system_u:system_r:kernel_t:s0 key=(null)
> > type=PROCTITLE msg=audit(1530616044.507:10): proctitle=6368726F6E7964002D71
> > type=TIME_ADJNTPVAL msg=audit(1530616044.511:11): op=freq old=0 
> > new=49180377088000
> > type=TIME_ADJNTPVAL msg=audit(1530616044.511:11): op=tick old=1 
> > new=1
> > type=SYSCALL 

Re: [PATCH ghak10 v5 1/2] audit: Add functions to log time adjustments

2018-08-27 Thread Ondrej Mosnacek
On Mon, Aug 27, 2018 at 9:50 AM Miroslav Lichvar  wrote:
> On Fri, Aug 24, 2018 at 02:00:00PM +0200, Ondrej Mosnacek wrote:
> > This patch adds two auxiliary record types that will be used to annotate
> > the adjtimex SYSCALL records with the NTP/timekeeping values that have
> > been changed.
>
> It seems the "adjust" function intentionally logs also calls/modes
> that don't actually change anything. Can you please explain it a bit
> in the message?
>
> NTP/PTP daemons typically don't read the adjtimex values in a normal
> operation and overwrite them on each update, even if they don't
> change. If the audit function checked that oldval != newval, the
> number of messages would be reduced and it might be easier to follow.

We actually want to log any attempt to change a value, as even an
intention to set/change something could be a hint that the process is
trying to do something bad (see discussion at [1]). There are valid
arguments both for and against this choice, but we have to pick one in
the end... Anyway, I should explain the reasoning in the commit
message better, right now it just states the fact without explanation
(in the second patch), thank you for pointing my attention to it.

[1] https://www.redhat.com/archives/linux-audit/2018-July/msg00061.html

--
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [PATCH ghak10 v5 1/2] audit: Add functions to log time adjustments

2018-08-27 Thread Ondrej Mosnacek
On Fri, Aug 24, 2018 at 8:33 PM John Stultz  wrote:
> On Fri, Aug 24, 2018 at 5:00 AM, Ondrej Mosnacek  wrote:
> > This patch adds two auxiliary record types that will be used to annotate
> > the adjtimex SYSCALL records with the NTP/timekeeping values that have
> > been changed.
> >
> > Next, it adds two functions to the audit interface:
> >  - audit_tk_injoffset(), which will be called whenever a timekeeping
> >offset is injected by a syscall from userspace,
> >  - audit_ntp_adjust(), which will be called whenever an NTP internal
> >variable is changed by a syscall from userspace.
> >
> > Quick reference for the fields of the new records:
> > AUDIT_TIME_INJOFFSET
> > sec - the 'seconds' part of the offset
> > nsec - the 'nanoseconds' part of the offset
> > AUDIT_TIME_ADJNTPVAL
> > op - which value was adjusted:
> > offset - corresponding to the time_offset variable
> > freq   - corresponding to the time_freq variable
> > status - corresponding to the time_status variable
> > adjust - corresponding to the time_adjust variable
> > tick   - corresponding to the tick_usec variable
> > tai- corresponding to the timekeeping's TAI offset
> > old - the old value
> > new - the new value
> >
> > Signed-off-by: Ondrej Mosnacek 
> > ---
> >  include/linux/audit.h  | 21 +
> >  include/uapi/linux/audit.h |  2 ++
> >  kernel/auditsc.c   | 15 +++
> >  3 files changed, 38 insertions(+)
> >
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index 9334fbef7bae..0d084d4b4042 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -26,6 +26,7 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> >
> >  #define AUDIT_INO_UNSET ((unsigned long)-1)
> >  #define AUDIT_DEV_UNSET ((dev_t)-1)
> > @@ -356,6 +357,8 @@ extern void __audit_log_capset(const struct cred *new, 
> > const struct cred *old);
> >  extern void __audit_mmap_fd(int fd, int flags);
> >  extern void __audit_log_kern_module(char *name);
> >  extern void __audit_fanotify(unsigned int response);
> > +extern void __audit_tk_injoffset(struct timespec64 offset);
> > +extern void __audit_ntp_adjust(const char *type, s64 oldval, s64 newval);
> >
> >  static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
> >  {
> > @@ -458,6 +461,18 @@ static inline void audit_fanotify(unsigned int 
> > response)
> > __audit_fanotify(response);
> >  }
> >
> > +static inline void audit_tk_injoffset(struct timespec64 offset)
> > +{
> > +   if (!audit_dummy_context())
> > +   __audit_tk_injoffset(offset);
> > +}
> > +
> > +static inline void audit_ntp_adjust(const char *type, s64 oldval, s64 
> > newval)
> > +{
> > +   if (!audit_dummy_context())
> > +   __audit_ntp_adjust(type, oldval, newval);
> > +}
> > +
> >  extern int audit_n_rules;
> >  extern int audit_signals;
> >  #else /* CONFIG_AUDITSYSCALL */
> > @@ -584,6 +599,12 @@ static inline void audit_log_kern_module(char *name)
> >  static inline void audit_fanotify(unsigned int response)
> >  { }
> >
> > +static inline void audit_tk_injoffset(struct timespec64 offset)
> > +{ }
> > +
> > +static inline void audit_ntp_adjust(const char *type, s64 oldval, s64 
> > newval)
> > +{ }
> > +
> >  static inline void audit_ptrace(struct task_struct *t)
> >  { }
> >  #define audit_n_rules 0
> > diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
> > index 4e3eaba84175..242ce562b41a 100644
> > --- a/include/uapi/linux/audit.h
> > +++ b/include/uapi/linux/audit.h
> > @@ -114,6 +114,8 @@
> >  #define AUDIT_REPLACE  1329/* Replace auditd if this packet 
> > unanswerd */
> >  #define AUDIT_KERN_MODULE  1330/* Kernel Module events */
> >  #define AUDIT_FANOTIFY 1331/* Fanotify access decision */
> > +#define AUDIT_TIME_INJOFFSET   1332/* Timekeeping offset injected */
> > +#define AUDIT_TIME_ADJNTPVAL   1333/* NTP value adjustment */
> >
> >  #define AUDIT_AVC  1400/* SE Linux avc denial or grant */
> >  #define AUDIT_SELINUX_ERR  1401/* Internal SE Linux Errors */
> > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > index fb207466e99b..d355d32d9765 100644
> > --- a

Re: [PATCH ghak95] audit: Do not log full CWD path on empty relative paths

2018-08-24 Thread Ondrej Mosnacek
On Thu, Aug 2, 2018 at 1:45 PM Ondrej Mosnacek  wrote:
> When a relative path has just a single component and we want to emit a
> nametype=PARENT record, the current implementation just reports the full
> CWD path (which is alrady available in the audit context).
>
> This is wrong for three reasons:
> 1. Wasting log space for redundant data (CWD path is already in the CWD
>record).
> 2. Inconsistency with other PATH records (if a relative PARENT directory
>path contains at least one component, only the verbatim relative path
>is logged).
> 3. In some syscalls (e.g. openat(2)) the relative path may not even be
>relative to the CWD, but to another directory specified as a file
>descriptor. In that case the logged path is simply plain wrong.
>
> This patch modifies this behavior to simply report "." in the
> aforementioned case, which is equivalent to an "empty" directory path
> and can be concatenated with the actual base directory path (CWD or
> dirfd from openat(2)-like syscall) once support for its logging is added
> later. In the meantime, defaulting to CWD as base directory on relative
> paths (as already done by the userspace tools) will be enough to achieve
> results equivalent to the current behavior.

I tested this patch a little bit with the libauparse library (it has
some functions for normalizing paths extracted from the records) and
it seems to behave as intended. The userspace functions seem to take a
rather crude approach and I think they won't always properly normalize
some paths, but that is a separate issue and this patch at least
definitely doesn't make it worse.

>
> See: https://github.com/linux-audit/audit-kernel/issues/95
>
> Fixes: 9c937dcc7102 ("[PATCH] log more info for directory entry change 
> events")
> Signed-off-by: Ondrej Mosnacek 
> ---
>  kernel/audit.c | 9 -
>  1 file changed, 4 insertions(+), 5 deletions(-)
>
> diff --git a/kernel/audit.c b/kernel/audit.c
> index 2a8058764aa6..4f18bd48eb4b 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -2127,28 +2127,27 @@ void audit_log_name(struct audit_context *context, 
> struct audit_names *n,
>
> audit_log_format(ab, "item=%d", record_num);
>
> +   audit_log_format(ab, " name=");
> if (path)
> -   audit_log_d_path(ab, " name=", path);
> +   audit_log_d_path(ab, NULL, path);
> else if (n->name) {
> switch (n->name_len) {
> case AUDIT_NAME_FULL:
> /* log the full path */
> -   audit_log_format(ab, " name=");
> audit_log_untrustedstring(ab, n->name->name);
> break;
> case 0:
> /* name was specified as a relative path and the
>  * directory component is the cwd */
> -   audit_log_d_path(ab, " name=", >pwd);
> +   audit_log_untrustedstring(ab, ".");
> break;
> default:
> /* log the name's directory component */
> -   audit_log_format(ab, " name=");
> audit_log_n_untrustedstring(ab, n->name->name,
>     n->name_len);
> }
> } else
> -   audit_log_format(ab, " name=(null)");
> +   audit_log_format(ab, "(null)");
>
> if (n->ino != AUDIT_INO_UNSET)
> audit_log_format(ab, " inode=%lu"
> --
> 2.17.1
>

--
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


[PATCH ghak10 v5 1/2] audit: Add functions to log time adjustments

2018-08-24 Thread Ondrej Mosnacek
This patch adds two auxiliary record types that will be used to annotate
the adjtimex SYSCALL records with the NTP/timekeeping values that have
been changed.

Next, it adds two functions to the audit interface:
 - audit_tk_injoffset(), which will be called whenever a timekeeping
   offset is injected by a syscall from userspace,
 - audit_ntp_adjust(), which will be called whenever an NTP internal
   variable is changed by a syscall from userspace.

Quick reference for the fields of the new records:
AUDIT_TIME_INJOFFSET
sec - the 'seconds' part of the offset
nsec - the 'nanoseconds' part of the offset
AUDIT_TIME_ADJNTPVAL
op - which value was adjusted:
offset - corresponding to the time_offset variable
freq   - corresponding to the time_freq variable
status - corresponding to the time_status variable
adjust - corresponding to the time_adjust variable
tick   - corresponding to the tick_usec variable
tai- corresponding to the timekeeping's TAI offset
old - the old value
new - the new value

Signed-off-by: Ondrej Mosnacek 
---
 include/linux/audit.h  | 21 +
 include/uapi/linux/audit.h |  2 ++
 kernel/auditsc.c   | 15 +++
 3 files changed, 38 insertions(+)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 9334fbef7bae..0d084d4b4042 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define AUDIT_INO_UNSET ((unsigned long)-1)
 #define AUDIT_DEV_UNSET ((dev_t)-1)
@@ -356,6 +357,8 @@ extern void __audit_log_capset(const struct cred *new, 
const struct cred *old);
 extern void __audit_mmap_fd(int fd, int flags);
 extern void __audit_log_kern_module(char *name);
 extern void __audit_fanotify(unsigned int response);
+extern void __audit_tk_injoffset(struct timespec64 offset);
+extern void __audit_ntp_adjust(const char *type, s64 oldval, s64 newval);
 
 static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
 {
@@ -458,6 +461,18 @@ static inline void audit_fanotify(unsigned int response)
__audit_fanotify(response);
 }
 
+static inline void audit_tk_injoffset(struct timespec64 offset)
+{
+   if (!audit_dummy_context())
+   __audit_tk_injoffset(offset);
+}
+
+static inline void audit_ntp_adjust(const char *type, s64 oldval, s64 newval)
+{
+   if (!audit_dummy_context())
+   __audit_ntp_adjust(type, oldval, newval);
+}
+
 extern int audit_n_rules;
 extern int audit_signals;
 #else /* CONFIG_AUDITSYSCALL */
@@ -584,6 +599,12 @@ static inline void audit_log_kern_module(char *name)
 static inline void audit_fanotify(unsigned int response)
 { }
 
+static inline void audit_tk_injoffset(struct timespec64 offset)
+{ }
+
+static inline void audit_ntp_adjust(const char *type, s64 oldval, s64 newval)
+{ }
+
 static inline void audit_ptrace(struct task_struct *t)
 { }
 #define audit_n_rules 0
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 4e3eaba84175..242ce562b41a 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -114,6 +114,8 @@
 #define AUDIT_REPLACE  1329/* Replace auditd if this packet 
unanswerd */
 #define AUDIT_KERN_MODULE  1330/* Kernel Module events */
 #define AUDIT_FANOTIFY 1331/* Fanotify access decision */
+#define AUDIT_TIME_INJOFFSET   1332/* Timekeeping offset injected */
+#define AUDIT_TIME_ADJNTPVAL   1333/* NTP value adjustment */
 
 #define AUDIT_AVC  1400/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR  1401/* Internal SE Linux Errors */
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index fb207466e99b..d355d32d9765 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2422,6 +2422,21 @@ void __audit_fanotify(unsigned int response)
AUDIT_FANOTIFY, "resp=%u", response);
 }
 
+/* We need to allocate with GFP_ATOMIC here, since these two functions will be
+ * called while holding the timekeeping lock: */
+void __audit_tk_injoffset(struct timespec64 offset)
+{
+   audit_log(audit_context(), GFP_ATOMIC, AUDIT_TIME_INJOFFSET,
+ "sec=%lli nsec=%li", (long long)offset.tv_sec, 
offset.tv_nsec);
+}
+
+void __audit_ntp_adjust(const char *type, s64 oldval, s64 newval)
+{
+   audit_log(audit_context(), GFP_ATOMIC, AUDIT_TIME_ADJNTPVAL,
+ "op=%s old=%lli new=%lli", type,
+ (long long)oldval, (long long)newval);
+}
+
 static void audit_log_task(struct audit_buffer *ab)
 {
kuid_t auid, uid;
-- 
2.17.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


[PATCH ghak10 v5 2/2] timekeeping/ntp: Audit clock/NTP params adjustments

2018-08-24 Thread Ondrej Mosnacek
  International Atomic Time
(AUDITED)
  NTP variables:
time_offset -- can adjust the clock by up to 0.5 seconds per call
   and also speed it up or slow down by up to about
   0.05% (43 seconds per day) (AUDITED)
time_freq -- can speed up or slow down by up to about 0.05%
time_status -- can insert/delete leap seconds and it also enables/
   disables synchronization of the hardware real-time
   clock (AUDITED)
time_maxerror, time_esterror -- change error estimates used to
inform userspace applications
(NOT AUDITED)
time_constant -- controls the speed of the clock adjustments that
 are made when time_offset is set (NOT AUDITED)
time_adjust -- can temporarily speed up or slow down the clock by up
       to 0.05% (AUDITED)
tick_usec -- a more extreme version of time_freq; can speed up or
 slow down the clock by up to 10% (AUDITED)

Cc: Miroslav Lichvar 
Signed-off-by: Ondrej Mosnacek 
---
 kernel/time/ntp.c | 38 ++
 kernel/time/timekeeping.c |  3 +++
 2 files changed, 33 insertions(+), 8 deletions(-)

diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index a09ded765f6c..f96c6d326aae 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "ntp_internal.h"
 #include "timekeeping_internal.h"
@@ -294,6 +295,8 @@ static inline s64 ntp_update_offset_fll(s64 offset64, long 
secs)
 
 static void ntp_update_offset(long offset)
 {
+   s64 old_offset = time_offset;
+   s64 old_freq = time_freq;
s64 freq_adj;
s64 offset64;
long secs;
@@ -342,6 +345,9 @@ static void ntp_update_offset(long offset)
time_freq   = max(freq_adj, -MAXFREQ_SCALED);
 
time_offset = div_s64(offset64 << NTP_SCALE_SHIFT, NTP_INTERVAL_FREQ);
+
+   audit_ntp_adjust("offset", old_offset, time_offset);
+   audit_ntp_adjust("freq", old_freq, time_freq);
 }
 
 /**
@@ -669,21 +675,31 @@ static inline void process_adjtimex_modes(struct timex 
*txc,
struct timespec64 *ts,
s32 *time_tai)
 {
-   if (txc->modes & ADJ_STATUS)
-   process_adj_status(txc, ts);
+   if (txc->modes & (ADJ_STATUS | ADJ_NANO | ADJ_MICRO)) {
+   int old_status = time_status;
+
+   if (txc->modes & ADJ_STATUS)
+   process_adj_status(txc, ts);
 
-   if (txc->modes & ADJ_NANO)
-   time_status |= STA_NANO;
+   if (txc->modes & ADJ_NANO)
+   time_status |= STA_NANO;
 
-   if (txc->modes & ADJ_MICRO)
-   time_status &= ~STA_NANO;
+   if (txc->modes & ADJ_MICRO)
+   time_status &= ~STA_NANO;
+
+   audit_ntp_adjust("status", old_status, time_status);
+   }
 
if (txc->modes & ADJ_FREQUENCY) {
+   s64 old_freq = time_freq;
+
time_freq = txc->freq * PPM_SCALE;
time_freq = min(time_freq, MAXFREQ_SCALED);
time_freq = max(time_freq, -MAXFREQ_SCALED);
/* update pps_freq */
pps_set_freq(time_freq);
+
+   audit_ntp_adjust("freq", old_freq, time_freq);
}
 
if (txc->modes & ADJ_MAXERROR)
@@ -700,14 +716,18 @@ static inline void process_adjtimex_modes(struct timex 
*txc,
time_constant = max(time_constant, 0l);
}
 
-   if (txc->modes & ADJ_TAI && txc->constant > 0)
+   if (txc->modes & ADJ_TAI && txc->constant > 0) {
+   audit_ntp_adjust("tai", *time_tai, txc->constant);
*time_tai = txc->constant;
+   }
 
if (txc->modes & ADJ_OFFSET)
ntp_update_offset(txc->offset);
 
-   if (txc->modes & ADJ_TICK)
+   if (txc->modes & ADJ_TICK) {
+   audit_ntp_adjust("tick", tick_usec, txc->tick);
tick_usec = txc->tick;
+   }
 
if (txc->modes & (ADJ_TICK|ADJ_FREQUENCY|ADJ_OFFSET))
ntp_update_frequency();
@@ -729,6 +749,8 @@ int __do_adjtimex(struct timex *txc, struct timespec64 *ts, 
s32 *time_tai)
/* adjtime() is independent from ntp_adjtime() */
time_adjust = txc->offset;
ntp_update_frequency();
+
+   audit_ntp_adjust("adjust", save_adjust, txc->offset);
}
txc->offset = save_adjust;
} 

[PATCH ghak10 v5 0/2] audit: Log modifying adjtimex(2) calls

2018-08-24 Thread Ondrej Mosnacek
This patchset implements more detailed auditing of the adjtimex(2)
syscall in order to make it possible to:
  a) distinguish modifying vs. read-only calls in the audit log
  b) reconstruct from the audit log what changes were made and how they
 have influenced the system clock

The main motivation is to be able to detect an adversary that tries to
confuse the audit timestamps by changing system time via adjtimex(2),
but at the same time avoid flooding the audit log with records of benign
read-only adjtimex(2) calls.

The current version of the patchset logs the following changes:
  - direct injection of timekeeping offset
  - adjustment of timekeeping's TAI offset
  - NTP value adjustments:
- time_offset
- time_freq
- time_status
- time_adjust
- tick_usec

Changes to the following NTP values are not logged, as they are not
important for security:
  - time_maxerror
  - time_esterror
  - time_constant

Audit kernel GitHub issue: https://github.com/linux-audit/audit-kernel/issues/10

Changes in v5:
  - Dropped logging of some less important changes and update commit messages
  - No longer mark the patchset as RFC

v4: https://www.redhat.com/archives/linux-audit/2018-August/msg00023.html
Changes in v4:
  - Squashed first two patches into one
  - Renamed ADJNTPVAL's "type" field to "op" to align with audit record
conventions
  - Minor commit message editing
  - Cc timekeeping/NTP people for feedback

v3: https://www.redhat.com/archives/linux-audit/2018-July/msg1.html
Changes in v3:
  - Switched to separate records for each variable
  - Both old and new value is now reported for each change
  - Injecting offset is reported via a separate record (since this
offset consists of two values and is added directly to the clock,
i.e. it doesn't make sense to log old and new value)
  - Added example records produced by chronyd -q (see the commit message
of the last patch)

v2: https://www.redhat.com/archives/linux-audit/2018-June/msg00114.html
Changes in v2:
  - The audit_adjtime() function has been modified to only log those
fields that contain values that are actually used, resulting in more
compact records.
  - The audit_adjtime() call has been moved to do_adjtimex() in
timekeeping.c
  - Added an additional patch (for review) that simplifies the detection
if the syscall is read-only.

v1: https://www.redhat.com/archives/linux-audit/2018-June/msg00095.html

Ondrej Mosnacek (2):
  audit: Add functions to log time adjustments
  timekeeping/ntp: Audit clock/NTP params adjustments

 include/linux/audit.h  | 21 +
 include/uapi/linux/audit.h |  2 ++
 kernel/auditsc.c   | 15 +++
 kernel/time/ntp.c  | 38 ++
 kernel/time/timekeeping.c  |  3 +++
 5 files changed, 71 insertions(+), 8 deletions(-)

-- 
2.17.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [RFC PATCH ghak10 v4 0/2] audit: Log modifying adjtimex(2) calls

2018-08-23 Thread Ondrej Mosnacek
On Wed, Aug 22, 2018 at 11:27 PM Paul Moore  wrote:
> On Tue, Aug 21, 2018 at 3:21 AM Miroslav Lichvar  wrote:
> > > On Mon, 20 Aug 2018, Ondrej Mosnacek wrote:
> > > > @John or other timekeeping/NTP folks: We had a discussion on the audit
> > > > ML on which of the internal timekeeping/NTP variables we should actually
> > > > log changes for. We are only interested in variables that can (directly
> > > > or indirectly) cause noticeable changes to the system clock, but since 
> > > > we
> > > > have only limited understanding of the NTP code, we would like to ask
> > > > you for advice on which variables are security relevant.
> >
> > I guess that mostly depends on whether you consider setting the clock
> > to run faster or slower than real time to be an important event for
> > the audit.
> >
> > > >   - NTP value adjustments:
> > > > - time_offset (probably important)
> >
> > This can adjust the clock by up to 0.5 seconds per call and also speed
> > it up or slow down by up to about 0.05% (43 seconds per day).
>
> This seems worthwhile.
>
> > > > - time_freq (maybe not important?)
> >
> > This can speed up or slow down by up to about 0.05%.
>
> This too.
>
> > > > - time_status (likely important, can cause leap second injection)
> >
> > Yes, it can insert/delete leap seconds and it also enables/disables
> > synchronization of the hardware real-time clock.
>
> This one as well.
>
> > > > - time_maxerror (maybe not important?)
> > > > - time_esterror (maybe not important?)
> >
> > These two change the error estimates that are reported to applications
> > using ntp_gettime()/adjtimex(). If an application was periodically
> > checking that the clock is synchronized with some specified accuracy
> > and setting the maxerror to a larger value would cause the application
> > to abort, would it be an important event in the audit?
>
> Since these don't really affect the time, just the expected error, I'm
> not sure this is important.
>
> > > > - time_constant (???)
> >
> > This controls the speed of the clock adjustments that are made when
> > time_offset is set. Probably not important for the audit.
>
> Agreed.  I think we can skip this.
>
> > > > - time_adjust (sounds important)
> >
> > This is similar to time_freq. It can temporarily speed up or slow down
> > the clock by up to 0.05%.
>
> Like time_freq, we should probably log this too.
>
> > > > - tick_usec (???)
> >
> > This is a more extreme version of time_freq. It can speed up or slow
> > down the clock by up to 10%.
>
> Let's audit this one too.

I agree with Paul on all counts. I will go ahead and prepare a
patchset that logs everything except maxerror, esterror, and constant.

Thank you, Miroslav, for the explanations!

--
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


[RFC PATCH ghak10 v4 1/2] audit: Add functions to log time adjustments

2018-08-20 Thread Ondrej Mosnacek
This patch adds two auxiliary record types that will be used to annotate
the adjtimex SYSCALL records with the NTP/timekeeping values that have
been changed.

Next, it adds two functions to the audit interface:
 - audit_tk_injoffset(), which will be called whenever a timekeeping
   offset is injected by a syscall from userspace,
 - audit_ntp_adjust(), which will be called whenever an NTP internal
   variable is changed by a syscall from userspace.

Quick reference for the fields of the new records:
AUDIT_TIME_INJOFFSET
sec - the 'seconds' part of the offset
nsec - the 'nanoseconds' part of the offset
AUDIT_TIME_ADJNTPVAL
op - which value was adjusted:
offset - corresponding to the time_offset variable
freq   - corresponding to the time_freq variable
status - corresponding to the time_status variable
maxerr - corresponding to the time_maxerror variable
esterr - corresponding to the time_esterror variable
const  - corresponding to the time_constant variable
adjust - corresponding to the time_adjust variable
tick   - corresponding to the tick_usec variable
tai- corresponding to the timekeeping's TAI offset
old - the old value
new - the new value

Signed-off-by: Ondrej Mosnacek 
---
 include/linux/audit.h  | 21 +
 include/uapi/linux/audit.h |  2 ++
 kernel/auditsc.c   | 15 +++
 3 files changed, 38 insertions(+)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 9334fbef7bae..0d084d4b4042 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -26,6 +26,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #define AUDIT_INO_UNSET ((unsigned long)-1)
 #define AUDIT_DEV_UNSET ((dev_t)-1)
@@ -356,6 +357,8 @@ extern void __audit_log_capset(const struct cred *new, 
const struct cred *old);
 extern void __audit_mmap_fd(int fd, int flags);
 extern void __audit_log_kern_module(char *name);
 extern void __audit_fanotify(unsigned int response);
+extern void __audit_tk_injoffset(struct timespec64 offset);
+extern void __audit_ntp_adjust(const char *type, s64 oldval, s64 newval);
 
 static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
 {
@@ -458,6 +461,18 @@ static inline void audit_fanotify(unsigned int response)
__audit_fanotify(response);
 }
 
+static inline void audit_tk_injoffset(struct timespec64 offset)
+{
+   if (!audit_dummy_context())
+   __audit_tk_injoffset(offset);
+}
+
+static inline void audit_ntp_adjust(const char *type, s64 oldval, s64 newval)
+{
+   if (!audit_dummy_context())
+   __audit_ntp_adjust(type, oldval, newval);
+}
+
 extern int audit_n_rules;
 extern int audit_signals;
 #else /* CONFIG_AUDITSYSCALL */
@@ -584,6 +599,12 @@ static inline void audit_log_kern_module(char *name)
 static inline void audit_fanotify(unsigned int response)
 { }
 
+static inline void audit_tk_injoffset(struct timespec64 offset)
+{ }
+
+static inline void audit_ntp_adjust(const char *type, s64 oldval, s64 newval)
+{ }
+
 static inline void audit_ptrace(struct task_struct *t)
 { }
 #define audit_n_rules 0
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 4e3eaba84175..242ce562b41a 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -114,6 +114,8 @@
 #define AUDIT_REPLACE  1329/* Replace auditd if this packet 
unanswerd */
 #define AUDIT_KERN_MODULE  1330/* Kernel Module events */
 #define AUDIT_FANOTIFY 1331/* Fanotify access decision */
+#define AUDIT_TIME_INJOFFSET   1332/* Timekeeping offset injected */
+#define AUDIT_TIME_ADJNTPVAL   1333/* NTP value adjustment */
 
 #define AUDIT_AVC  1400/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR  1401/* Internal SE Linux Errors */
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index fb207466e99b..d355d32d9765 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2422,6 +2422,21 @@ void __audit_fanotify(unsigned int response)
AUDIT_FANOTIFY, "resp=%u", response);
 }
 
+/* We need to allocate with GFP_ATOMIC here, since these two functions will be
+ * called while holding the timekeeping lock: */
+void __audit_tk_injoffset(struct timespec64 offset)
+{
+   audit_log(audit_context(), GFP_ATOMIC, AUDIT_TIME_INJOFFSET,
+ "sec=%lli nsec=%li", (long long)offset.tv_sec, 
offset.tv_nsec);
+}
+
+void __audit_ntp_adjust(const char *type, s64 oldval, s64 newval)
+{
+   audit_log(audit_context(), GFP_ATOMIC, AUDIT_TIME_ADJNTPVAL,
+ "op=%s old=%lli new=%lli", type,
+ (long long)oldval, (long long)newval);
+}
+
 static void audit_log_task(struct audit_buffer *ab)
 {
kuid_t auid, uid;
-- 
2.17.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


[RFC PATCH ghak10 v4 2/2] timekeeping/ntp: Audit clock/NTP params adjustments

2018-08-20 Thread Ondrej Mosnacek
ess=yes exit=5 a0=7fff57e78270 a1=1 a2=fff0 a3=137b828205ca12 
items=0 ppid=626 pid=629 auid=0 uid=385 gid=382 euid=385 suid=385 fsuid=385 
egid=382 sgid=382 fsgid=382 tty=(none) ses=1 comm="chronyd" 
exe="/usr/sbin/chronyd" subj=system_u:system_r:kernel_t:s0 key=(null)
type=PROCTITLE msg=audit(1530616049.652:13): proctitle=6368726F6E7964002D71
type=TIME_ADJNTPVAL msg=audit(1530616033.783:14): op=freq old=49180377088000 
new=49180377088000
type=TIME_ADJNTPVAL msg=audit(1530616033.783:14): op=tick old=1 new=1
type=SYSCALL msg=audit(1530616033.783:14): arch=c03e syscall=159 
success=yes exit=5 a0=7fff57e78bc0 a1=0 a2=2710 a3=0 items=0 ppid=626 pid=629 
auid=0 uid=385 gid=382 euid=385 suid=385 fsuid=385 egid=382 sgid=382 fsgid=382 
tty=(none) ses=1 comm="chronyd" exe="/usr/sbin/chronyd" 
subj=system_u:system_r:kernel_t:s0 key=(null)
type=PROCTITLE msg=audit(1530616033.783:14): proctitle=6368726F6E7964002D71

The chronyd command that produced the above records executed the
following adjtimex(2) syscalls (as per strace output):

adjtimex({modes=ADJ_OFFSET|0x8000, offset=0, freq=0, maxerror=1600, 
esterror=1600, status=STA_UNSYNC, constant=2, precision=1, 
tolerance=32768000, time={tv_sec=1530616044, tv_usec=507215}, tick=1, 
ppsfreq=0, jitter=0, shift=0, stabil=0, jitcnt=0, calcnt=0, errcnt=0, stbcnt=0, 
tai=0}) = 5 (TIME_ERROR)
adjtimex({modes=ADJ_MAXERROR, offset=0, freq=0, maxerror=0, esterror=1600, 
status=STA_UNSYNC, constant=2, precision=1, tolerance=32768000, 
time={tv_sec=1530616044, tv_usec=507438}, tick=1, ppsfreq=0, jitter=0, 
shift=0, stabil=0, jitcnt=0, calcnt=0, errcnt=0, stbcnt=0, tai=0}) = 5 
(TIME_ERROR)
adjtimex({modes=ADJ_SETOFFSET|ADJ_NANO, offset=0, freq=0, maxerror=1600, 
esterror=1600, status=STA_UNSYNC|STA_NANO, constant=2, precision=1, 
tolerance=32768000, time={tv_sec=1530616044, tv_usec=507604737}, tick=1, 
ppsfreq=0, jitter=0, shift=0, stabil=0, jitcnt=0, calcnt=0, errcnt=0, stbcnt=0, 
tai=0}) = 5 (TIME_ERROR)
adjtimex({modes=ADJ_OFFSET|ADJ_STATUS, offset=0, freq=0, maxerror=1600, 
esterror=1600, status=STA_PLL|STA_UNSYNC|STA_NANO, constant=2, precision=1, 
tolerance=32768000, time={tv_sec=1530616044, tv_usec=507698330}, tick=1, 
ppsfreq=0, jitter=0, shift=0, stabil=0, jitcnt=0, calcnt=0, errcnt=0, stbcnt=0, 
tai=0}) = 5 (TIME_ERROR)
adjtimex({modes=ADJ_STATUS, offset=0, freq=0, maxerror=1600, 
esterror=1600, status=STA_UNSYNC, constant=2, precision=1, 
tolerance=32768000, time={tv_sec=1530616044, tv_usec=507792}, tick=1, 
ppsfreq=0, jitter=0, shift=0, stabil=0, jitcnt=0, calcnt=0, errcnt=0, stbcnt=0, 
tai=0}) = 5 (TIME_ERROR)
adjtimex({modes=0, offset=0, freq=0, maxerror=1600, esterror=1600, 
status=STA_UNSYNC, constant=2, precision=1, tolerance=32768000, 
time={tv_sec=1530616044, tv_usec=508000}, tick=1, ppsfreq=0, jitter=0, 
shift=0, stabil=0, jitcnt=0, calcnt=0, errcnt=0, stbcnt=0, tai=0}) = 5 
(TIME_ERROR)
adjtimex({modes=ADJ_FREQUENCY|ADJ_TICK, offset=0, freq=750433, 
maxerror=1600, esterror=1600, status=STA_UNSYNC, constant=2, 
precision=1, tolerance=32768000, time={tv_sec=1530616044, tv_usec=512146}, 
tick=1, ppsfreq=0, jitter=0, shift=0, stabil=0, jitcnt=0, calcnt=0, 
errcnt=0, stbcnt=0, tai=0}) = 5 (TIME_ERROR)
adjtimex({modes=ADJ_MAXERROR|ADJ_ESTERROR|ADJ_STATUS, offset=0, freq=750433, 
maxerror=1600, esterror=1600, status=STA_UNSYNC, constant=2, 
precision=1, tolerance=32768000, time={tv_sec=1530616044, tv_usec=522506}, 
tick=1, ppsfreq=0, jitter=0, shift=0, stabil=0, jitcnt=0, calcnt=0, 
errcnt=0, stbcnt=0, tai=0}) = 5 (TIME_ERROR)
adjtimex({modes=ADJ_SETOFFSET|ADJ_NANO, offset=0, freq=750433, 
maxerror=1600, esterror=1600, status=STA_UNSYNC|STA_NANO, constant=2, 
precision=1, tolerance=32768000, time={tv_sec=1530616033, tv_usec=778717675}, 
tick=1, ppsfreq=0, jitter=0, shift=0, stabil=0, jitcnt=0, calcnt=0, 
errcnt=0, stbcnt=0, tai=0}) = 5 (TIME_ERROR)
adjtimex({modes=ADJ_FREQUENCY|ADJ_TICK, offset=0, freq=750433, 
maxerror=1600, esterror=1600, status=STA_UNSYNC|STA_NANO, constant=2, 
precision=1, tolerance=32768000, time={tv_sec=1530616033, tv_usec=784644657}, 
tick=1, ppsfreq=0, jitter=0, shift=0, stabil=0, jitcnt=0, calcnt=0, 
errcnt=0, stbcnt=0, tai=0}) = 5 (TIME_ERROR)

(The struct timex fields above are from *after* the syscall was
executed, so they contain the current (new) values as set from the
kernel, except of the 'modes' field, which contains the original value
sent by the caller.)

Note that the records are emitted even when the actual value does not
change (i.e. when there is an explicit attempt to change a value, but
the new value equals the old one).

Signed-off-by: Ondrej Mosnacek 
---
 kernel/time/ntp.c | 50 +++
 kernel/time/timekeeping.c |  3 +++
 2 files changed, 43 insertions(+), 10 deletions(-)

diff --git a/kernel/time/ntp

[RFC PATCH ghak10 v4 0/2] audit: Log modifying adjtimex(2) calls

2018-08-20 Thread Ondrej Mosnacek
Hi,

this patchset implements more detailed auditing of the adjtimex(2)
syscall in order to make it possible to:
  a) distinguish modifying vs. read-only calls in the audit log
  b) reconstruct from the audit log what changes were made and how they
 have influenced the system clock

The main motivation is to be able to detect an adversary that tries to
confuse the audit timestamps by changing system time via adjtimex(2),
but at the same time avoid flooding the audit log with records of benign
read-only adjtimex(2) calls.

@John or other timekeeping/NTP folks: We had a discussion on the audit
ML on which of the internal timekeeping/NTP variables we should actually
log changes for. We are only interested in variables that can (directly
or indirectly) cause noticeable changes to the system clock, but since we
have only limited understanding of the NTP code, we would like to ask
you for advice on which variables are security relevant.

Right now, the patchset is conservative and logs all changes that can be
done via adjtimex(2):
  - direct injection of timekeeping offset (obviously relevant)
  - adjustment of timekeeping's TAI offset
  - NTP value adjustments:
- time_offset (probably important)
- time_freq (maybe not important?)
- time_status (likely important, can cause leap second injection)
- time_maxerror (maybe not important?)
- time_esterror (maybe not important?)
- time_constant (???)
- time_adjust (sounds important)
- tick_usec (???)

Could you please give us some hints on the effect of changing these
variables and whether you think that it is important to log their
changes?

Thanks a lot!


GitHub issue: https://github.com/linux-audit/audit-kernel/issues/10

Changes in v4:
  - Squashed first two patches into one
  - Rename ADJNTPVAL's "type" field to "op" to align with audit record
conventions
  - Minor commit message editing
  - Cc timekeeping/NTP people for feedback

v3: https://www.redhat.com/archives/linux-audit/2018-July/msg1.html
Changes in v3:
  - Switched to separate records for each variable
  - Both old and new value is now reported for each change
  - Injecting offset is reported via a separate record (since this
offset consists of two values and is added directly to the clock,
i.e. it doesn't make sense to log old and new value)
  - Added example records produced by chronyd -q (see the commit message
of the last patch)

v2: https://www.redhat.com/archives/linux-audit/2018-June/msg00114.html
Changes in v2:
  - The audit_adjtime() function has been modified to only log those
fields that contain values that are actually used, resulting in more
compact records.
  - The audit_adjtime() call has been moved to do_adjtimex() in
timekeeping.c
  - Added an additional patch (for review) that simplifies the detection
if the syscall is read-only.

v1: https://www.redhat.com/archives/linux-audit/2018-June/msg00095.html

Ondrej Mosnacek (2):
  audit: Add functions to log time adjustments
  timekeeping/ntp: Audit clock/NTP params adjustments

 include/linux/audit.h  | 21 
 include/uapi/linux/audit.h |  2 ++
 kernel/auditsc.c   | 15 
 kernel/time/ntp.c  | 50 ++
 kernel/time/timekeeping.c  |  3 +++
 5 files changed, 81 insertions(+), 10 deletions(-)

-- 
2.17.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [PATCH ghak95] audit: Do not log full CWD path on empty relative paths

2018-08-05 Thread Ondrej Mosnacek
On Fri, Aug 3, 2018 at 12:24 AM Paul Moore  wrote:
> On Thu, Aug 2, 2018 at 7:45 AM Ondrej Mosnacek  wrote:
> >
> > When a relative path has just a single component and we want to emit a
> > nametype=PARENT record, the current implementation just reports the full
> > CWD path (which is alrady available in the audit context).
> >
> > This is wrong for three reasons:
> > 1. Wasting log space for redundant data (CWD path is already in the CWD
> >record).
> > 2. Inconsistency with other PATH records (if a relative PARENT directory
> >path contains at least one component, only the verbatim relative path
> >is logged).
> > 3. In some syscalls (e.g. openat(2)) the relative path may not even be
> >relative to the CWD, but to another directory specified as a file
> >descriptor. In that case the logged path is simply plain wrong.
> >
> > This patch modifies this behavior to simply report "." in the
> > aforementioned case, which is equivalent to an "empty" directory path
> > and can be concatenated with the actual base directory path (CWD or
> > dirfd from openat(2)-like syscall) once support for its logging is added
> > later. In the meantime, defaulting to CWD as base directory on relative
> > paths (as already done by the userspace tools) will be enough to achieve
> > results equivalent to the current behavior.
> >
> > See: https://github.com/linux-audit/audit-kernel/issues/95
> >
> > Fixes: 9c937dcc7102 ("[PATCH] log more info for directory entry change 
> > events")
> > Signed-off-by: Ondrej Mosnacek 
> > ---
> >  kernel/audit.c | 9 -
> >  1 file changed, 4 insertions(+), 5 deletions(-)
> >
> > diff --git a/kernel/audit.c b/kernel/audit.c
> > index 2a8058764aa6..4f18bd48eb4b 100644
> > --- a/kernel/audit.c
> > +++ b/kernel/audit.c
> > @@ -2127,28 +2127,27 @@ void audit_log_name(struct audit_context *context, 
> > struct audit_names *n,
> >
> > audit_log_format(ab, "item=%d", record_num);
> >
> > +   audit_log_format(ab, " name=");
> > if (path)
> > -   audit_log_d_path(ab, " name=", path);
> > +   audit_log_d_path(ab, NULL, path);
> > else if (n->name) {
> > switch (n->name_len) {
> > case AUDIT_NAME_FULL:
> > /* log the full path */
> > -   audit_log_format(ab, " name=");
> > audit_log_untrustedstring(ab, n->name->name);
> > break;
> > case 0:
> > /* name was specified as a relative path and the
> >  * directory component is the cwd */
> > -   audit_log_d_path(ab, " name=", >pwd);
> > +   audit_log_untrustedstring(ab, ".");
>
> This isn't a comprehensive review, I only gave this a quick look, but
> considering you are only logging "." above we can safely use
> audit_log_string() and safe a few cycles.

I used audit_log_untrustedstring() to maintain the current norm that
the name= field would always contain a quoted string (either in
double-quotes or hex-escaped). I don't know if such consistency is
important for parsing in userspace (it should probably be robust
enough to handle any format), but I wanted to be on the safe side.

> Honestly, looking at the rest of this function, why are we using
> audit_log_format() in the case where we are simply writing a string
> literal?  While I haven't tested it, simple code inspection would seem
> to indicate that audit_log_string() should be much quicker than
> audit_log_format()?  I realize this isn't strictly a problem from this
> patch, but we probably shouldn't be propagating this mistake any
> further.

Good point. If I happen to be sending a v2 of the patch, I will switch
to audit_log_string() where possible. Otherwise, I'll leave it to you
to fix up when applying (it will probably clash with your patch
anyway).

--
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [RFC PATCH ghak9 0/3] audit: Record the path of FDs passed to *at(2) syscalls

2018-08-03 Thread Ondrej Mosnacek
On Fri, Aug 3, 2018 at 1:58 AM Paul Moore  wrote:
> On Thu, Jul 26, 2018 at 5:13 AM Ondrej Mosnacek  wrote:
> > On Thu, Jul 26, 2018 at 10:12 AM Ondrej Mosnacek  
> > wrote:
> > > I think it should be possible to collect that information by putting
> > > hooks in the right places of the filesystem code (and fixing the
> > > current ones).
> >
> > Hm, after closer look, it seems this won't be doable (at least not
> > easily). The PATH record always logs the original path string from
> > userspace (and I think we need to preserve this behavior in case
> > someone relies on it). In case of PARENT records, it truncates away
> > the last component (because it wants to log inode information also for
> > the parent directory). If this truncated string ends up empty (i.e.
> > the original string had just one component), it just smashes in the
> > absolute path of the CWD (which is known), because it pretends no
> > *at() syscalls exist and all relative paths are relative to current
> > CWD.
> >
> > So to fix this, we need to do one of the following:
> > 1. Add a new field to the PATH records that would specify the path of
> > the directory that the value of name=... is relative to. If this is
> > CWD, we can just use some special value
> > ("(null)"/"(none)"/"(cwd)"/...) or omit the field completely. I prefer
> > this approach, because it will best solve the case of renameat(),
> > where different PATH records can have different base directories.
>
> It is worth calling extra attention to the fact that we would now be
> effectively recording two paths in a single record.  I'm not sure how
> much we care about that, but it does increase the chances we blow past
> the end of the netlink buffer; although it is worth noting that a
> single PATH_MAX entry would do that today.

Yes, but note that the two "paths" are actually just parts of a single
(full) path. The situation will be no different from when the user
would just specify a full path. But your comment just made me realize
that I will need to make sure that the new field is empty also when
dirfd != AT_FDCWD, but the path supplied to the syscall is absolute
(because then it would be just useless information).

> Also, would this new field remain empty for non-*at syscalls?

Yes, the emptiness (or some special value depending on the chosen
implementation) would indicate that dirfd is CWD (which can be looked
up in the CWD record).

> > 2. If adding fields is considered A Bad Thing, we could alternatively
> > provide this information in separate records (either PATH with special
> > nametype or a new record). However in such case we need to somehow
> > specify to which PATH records each base directory corresponds. For
> > PATH records this could be guessed from their order, but this is a
> > fragile thing (changes in filesystem code could change the order).
>
> While this may be a bit more difficult it seems like this is more in
> keeping with the current methodology, and would keep the overall audit
> logs smaller.  In the case of the *at syscalls I presume you would
> create PARENT records for the base directory, omitting it if AT_FDCWD
> was used?

Right now, the parent/child records are only emitted when a file is
moved, created, or removed (actually I'm not sure right now about the
latter two, but definitely for the first case). The PARENT record
always contains the (relative or absolute) path as given to the
syscall minus the last element and the corresponding CREATE/DELETE
record contains only the last element. I don't know what is the goal
of this splitting (probably to report details (inode, ...) also about
the containing directory or maybe to deduplicate PATH records if src
and dst directories are the same?), but I'm not sure it is a good idea
to overload the semantics of nametype=PARENT for yet another purpose
(one of the PARENTs would be parent for the other PARENT...). I'm
almost certain this would also confuse the current userspace code
(especially considering that for rename() the kernel generates both
PARENT records before the child records...).

That said, it seems to me this would actually make the logs *bigger*,
because you would also log the usual PATH record details (inode,
fcaps, ...) for the base directory (dirfd).

> I imagine this would also help the traditional rename() syscall?

I'm not sure how, given the facts above.

-- 
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [RFC PATCH] audit: minimize our use of audit_log_format()

2018-08-03 Thread Ondrej Mosnacek
On Fri, Aug 3, 2018 at 12:24 AM Paul Moore  wrote:
> WARNING: completely untested patch!
>
> There are several cases where we are using audit_log_format() when we
> could be using audit_log_string(), which should be quicker.  There are
> also some cases where we are making multiple audit_log_format() calls
> in a row, for no apparent reason.
>
> This patch fixes the problems above in the core audit code, the other
> kernel subsystems are left for another time.
>
> Signed-off-by: Paul Moore 

FWIW,

Reviewed-by: Ondrej Mosnacek 

> ---
>  kernel/audit.c  |   37 ++---
>  kernel/audit_fsnotify.c |2 +-
>  kernel/audit_tree.c |3 +--
>  kernel/audit_watch.c|2 +-
>  kernel/auditsc.c|   19 +--
>  5 files changed, 30 insertions(+), 33 deletions(-)
>
> diff --git a/kernel/audit.c b/kernel/audit.c
> index 160144f7e5f9..a0f57f4f9944 100644
> --- a/kernel/audit.c
> +++ b/kernel/audit.c
> @@ -1347,7 +1347,7 @@ static int audit_receive_msg(struct sk_buff *skb, 
> struct nlmsghdr *nlh)
> else {
> int size;
>
> -   audit_log_format(ab, " data=");
> +   audit_log_string(ab, " data=");
> size = nlmsg_len(nlh);
> if (size > 0 &&
> ((unsigned char *)data)[size - 1] == '\0')
> @@ -1375,7 +1375,7 @@ static int audit_receive_msg(struct sk_buff *skb, 
> struct nlmsghdr *nlh)
> case AUDIT_TRIM:
> audit_trim_trees();
> audit_log_common_recv_msg(, AUDIT_CONFIG_CHANGE);
> -   audit_log_format(ab, " op=trim res=1");
> +   audit_log_string(ab, " op=trim res=1");
> audit_log_end(ab);
> break;
> case AUDIT_MAKE_EQUIV: {
> @@ -1406,9 +1406,9 @@ static int audit_receive_msg(struct sk_buff *skb, 
> struct nlmsghdr *nlh)
>
> audit_log_common_recv_msg(, AUDIT_CONFIG_CHANGE);
>
> -   audit_log_format(ab, " op=make_equiv old=");
> +   audit_log_string(ab, " op=make_equiv old=");
> audit_log_untrustedstring(ab, old);
> -   audit_log_format(ab, " new=");
> +   audit_log_string(ab, " new=");
> audit_log_untrustedstring(ab, new);
> audit_log_format(ab, " res=%d", !err);
> audit_log_end(ab);
> @@ -2021,7 +2021,7 @@ void audit_log_d_path(struct audit_buffer *ab, const 
> char *prefix,
> char *p, *pathname;
>
> if (prefix)
> -   audit_log_format(ab, "%s", prefix);
> +   audit_log_string(ab, prefix);
>
> /* We will allow 11 spaces for ' (deleted)' to be appended */
> pathname = kmalloc(PATH_MAX+11, ab->gfp_mask);
> @@ -2048,11 +2048,11 @@ void audit_log_session_info(struct audit_buffer *ab)
>
>  void audit_log_key(struct audit_buffer *ab, char *key)
>  {
> -   audit_log_format(ab, " key=");
> +   audit_log_string(ab, " key=");
> if (key)
> audit_log_untrustedstring(ab, key);
> else
> -   audit_log_format(ab, "(null)");
> +   audit_log_string(ab, "(null)");
>  }
>
>  void audit_log_cap(struct audit_buffer *ab, char *prefix, kernel_cap_t *cap)
> @@ -2134,7 +2134,7 @@ void audit_log_name(struct audit_context *context, 
> struct audit_names *n,
> switch (n->name_len) {
> case AUDIT_NAME_FULL:
> /* log the full path */
> -   audit_log_format(ab, " name=");
> +   audit_log_string(ab, " name=");
> audit_log_untrustedstring(ab, n->name->name);
> break;
> case 0:
> @@ -2144,12 +2144,12 @@ void audit_log_name(struct audit_context *context, 
> struct audit_names *n,
> break;
> default:
> /* log the name's directory component */
> -   audit_log_format(ab, " name=");
> +   audit_log_string(ab, " name=");
> audit_log_n_untrustedstring(ab, n->name->name,
> n->name_len);
> }
> } else
> -   audit_log_format(ab, " name=(null)");
&

[PATCH ghak95] audit: Do not log full CWD path on empty relative paths

2018-08-02 Thread Ondrej Mosnacek
When a relative path has just a single component and we want to emit a
nametype=PARENT record, the current implementation just reports the full
CWD path (which is alrady available in the audit context).

This is wrong for three reasons:
1. Wasting log space for redundant data (CWD path is already in the CWD
   record).
2. Inconsistency with other PATH records (if a relative PARENT directory
   path contains at least one component, only the verbatim relative path
   is logged).
3. In some syscalls (e.g. openat(2)) the relative path may not even be
   relative to the CWD, but to another directory specified as a file
   descriptor. In that case the logged path is simply plain wrong.

This patch modifies this behavior to simply report "." in the
aforementioned case, which is equivalent to an "empty" directory path
and can be concatenated with the actual base directory path (CWD or
dirfd from openat(2)-like syscall) once support for its logging is added
later. In the meantime, defaulting to CWD as base directory on relative
paths (as already done by the userspace tools) will be enough to achieve
results equivalent to the current behavior.

See: https://github.com/linux-audit/audit-kernel/issues/95

Fixes: 9c937dcc7102 ("[PATCH] log more info for directory entry change events")
Signed-off-by: Ondrej Mosnacek 
---
 kernel/audit.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/kernel/audit.c b/kernel/audit.c
index 2a8058764aa6..4f18bd48eb4b 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -2127,28 +2127,27 @@ void audit_log_name(struct audit_context *context, 
struct audit_names *n,
 
audit_log_format(ab, "item=%d", record_num);
 
+   audit_log_format(ab, " name=");
if (path)
-   audit_log_d_path(ab, " name=", path);
+   audit_log_d_path(ab, NULL, path);
else if (n->name) {
switch (n->name_len) {
case AUDIT_NAME_FULL:
/* log the full path */
-   audit_log_format(ab, " name=");
audit_log_untrustedstring(ab, n->name->name);
break;
case 0:
/* name was specified as a relative path and the
 * directory component is the cwd */
-   audit_log_d_path(ab, " name=", >pwd);
+   audit_log_untrustedstring(ab, ".");
break;
default:
/* log the name's directory component */
-   audit_log_format(ab, " name=");
audit_log_n_untrustedstring(ab, n->name->name,
n->name_len);
}
} else
-   audit_log_format(ab, " name=(null)");
+   audit_log_format(ab, "(null)");
 
if (n->ino != AUDIT_INO_UNSET)
audit_log_format(ab, " inode=%lu"
-- 
2.17.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [RFC PATCH ghak9 0/3] audit: Record the path of FDs passed to *at(2) syscalls

2018-07-26 Thread Ondrej Mosnacek
On Thu, Jul 26, 2018 at 10:12 AM Ondrej Mosnacek  wrote:
> I think it should be possible to collect that information by putting
> hooks in the right places of the filesystem code (and fixing the
> current ones).

Hm, after closer look, it seems this won't be doable (at least not
easily). The PATH record always logs the original path string from
userspace (and I think we need to preserve this behavior in case
someone relies on it). In case of PARENT records, it truncates away
the last component (because it wants to log inode information also for
the parent directory). If this truncated string ends up empty (i.e.
the original string had just one component), it just smashes in the
absolute path of the CWD (which is known), because it pretends no
*at() syscalls exist and all relative paths are relative to current
CWD.

So to fix this, we need to do one of the following:
1. Add a new field to the PATH records that would specify the path of
the directory that the value of name=... is relative to. If this is
CWD, we can just use some special value
("(null)"/"(none)"/"(cwd)"/...) or omit the field completely. I prefer
this approach, because it will best solve the case of renameat(),
where different PATH records can have different base directories.
2. If adding fields is considered A Bad Thing, we could alternatively
provide this information in separate records (either PATH with special
nametype or a new record). However in such case we need to somehow
specify to which PATH records each base directory corresponds. For
PATH records this could be guessed from their order, but this is a
fragile thing (changes in filesystem code could change the order).

Let me give an example to illustrate better how it might look like:
=== renameat() with two FD arguments ===
openat(AT_FDCWD, "/tmp/tmp.SIMqhBS0eI/a", O_RDONLY|O_PATH|O_DIRECTORY) = 3
openat(AT_FDCWD, "/tmp/tmp.SIMqhBS0eI/b", O_RDONLY|O_PATH|O_DIRECTORY) = 4
renameat(3, "x/f", 4, "y/g")= 0
close(3)= 0
close(4)= 0

type=SYSCALL msg=audit(1532504483.814:5): [...]
type=CWD msg=audit(1532504483.814:5): cwd="/root/Dokumenty/Kernel"
type=PATH msg=audit(1532504483.814:5): item=0 name="x/" inode=2156
dev=00:1a mode=040755 ouid=0 ogid=0 rdev=00:00
obj=system_u:object_r:tmpfs_t:s0 nametype=PARENT
cap_fp= cap_fi= cap_fe=0 cap_fver=0
basedir="/tmp/tmp.SIMqhBS0eI/a"
type=PATH msg=audit(1532504483.814:5): item=1 name="y/" inode=2158
dev=00:1a mode=040755 ouid=0 ogid=0 rdev=00:00
obj=system_u:object_r:tmpfs_t:s0 nametype=PARENT
cap_fp= cap_fi= cap_fe=0 cap_fver=0
basedir="/tmp/tmp.SIMqhBS0eI/b"
type=PATH msg=audit(1532504483.814:5): item=2 name="x/f" inode=2159
dev=00:1a mode=0100644 ouid=0 ogid=0 rdev=00:00
obj=system_u:object_r:tmpfs_t:s0 nametype=DELETE
cap_fp= cap_fi= cap_fe=0 cap_fver=0
basedir="/tmp/tmp.SIMqhBS0eI/a"
type=PATH msg=audit(1532504483.814:5): item=3 name="y/g" inode=2159
dev=00:1a mode=0100644 ouid=0 ogid=0 rdev=00:00
obj=system_u:object_r:tmpfs_t:s0 nametype=CREATE
cap_fp= cap_fi= cap_fe=0 cap_fver=0
basedir="/tmp/tmp.SIMqhBS0eI/b"

=== renameat() with one CWD and one FD argument ===
openat(AT_FDCWD, "/tmp/tmp.SIMqhBS0eI/a", O_RDONLY|O_PATH|O_DIRECTORY) = 3
renameat(3, "x/f", AT_FDCWD, "y/g")= 0
close(3)= 0

type=SYSCALL msg=audit(1532504483.814:5): [...]
type=CWD msg=audit(1532504483.814:5): cwd="/root/Dokumenty/Kernel"
type=PATH msg=audit(1532504483.814:5): item=0 name="x/" inode=2156
dev=00:1a mode=040755 ouid=0 ogid=0 rdev=00:00
obj=system_u:object_r:tmpfs_t:s0 nametype=PARENT
cap_fp= cap_fi= cap_fe=0 cap_fver=0
basedir="/tmp/tmp.SIMqhBS0eI/a"
type=PATH msg=audit(1532504483.814:5): item=1 name="y/" inode=2158
dev=00:1a mode=040755 ouid=0 ogid=0 rdev=00:00
obj=system_u:object_r:tmpfs_t:s0 nametype=PARENT
cap_fp= cap_fi= cap_fe=0 cap_fver=0
basedir=(cwd)
type=PATH msg=audit(1532504483.814:5): item=2 name="x/f" inode=2159
dev=00:1a mode=0100644 ouid=0 ogid=0 rdev=00:00
obj=system_u:object_r:tmpfs_t:s0 nametype=DELETE
cap_fp= cap_fi= cap_fe=0 cap_fver=0
basedir="/tmp/tmp.SIMqhBS0eI/a"
type=PATH msg=audit(1532504483.814:5): item=3 name="y/g" inode=2159
dev=00:1a mode=0100644 ouid=0 ogid=0 rdev=00:00
obj=system_u:object_r:tmpfs_t:s0 nametype=CREATE
cap_fp= cap_fi= cap_fe=0 cap_fver=0
basedir=(cwd)

-- 
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [RFC PATCH ghak9 0/3] audit: Record the path of FDs passed to *at(2) syscalls

2018-07-26 Thread Ondrej Mosnacek
On Wed, Jul 25, 2018 at 3:11 PM Steve Grubb  wrote:
> On Wednesday, July 25, 2018 9:02:50 AM EDT Ondrej Mosnacek wrote:
> > On Wed, Jul 25, 2018 at 2:48 PM Steve Grubb  wrote:
> > > On Wednesday, July 25, 2018 3:44:07 AM EDT Ondrej Mosnacek wrote:
> > > > On Wed, Jul 25, 2018 at 3:11 AM Steve Grubb  wrote:
> > > > > On Tuesday, July 24, 2018 6:15:54 PM EDT Paul Moore wrote:
> > > > > > On Tue, Jul 24, 2018 at 10:12 AM Ondrej Mosnacek
> > > > > > 
> > > > > >
> > > > > > > Beyond that, there is really no information in the records that
> > > > > > > would
> > > > > > > allow reconstructing which PARENT path belongs to which
> > > > > > > CREATE/DELETE
> > > > > > > path... (Intuitively you can guess that src will come before dst,
> > > > > > > but
> > > > > > > that is not very reliable.) I think a "parent inode" field in the
> > > > > > > PATH
> > > > > > > records could fix this, but maybe there is a better solution...
> > > > > >
> > > > > > I have my suspicions, but I would be curious to hear from Steve how
> > > > > > the reconstruction is typically handled.
> > > > >
> > > > > For any *at function when the dirfd is not AT_FDCWD, it goes badly.
> > > > > If
> > > > > its a old style syscall without the dirfd, then if the first
> > > > > character
> > > > > is '/' use that. Otherwise concatonate cwd and path and pass it to
> > > > > realpath to sort out.
> > > >
> > > > In that case it seems the best fix for openat() et al. would be to
> > > > somehow always force outputting the full path when dirfd != AT_FDCWD.
> > > > Hopefully that won't require too much hacking around...
> > >
> > > What is asked for is the full path that dirfd was opened with. I can take
> > > care of everything else.
> >
> > But where/how should that path be logged? In case of renameat(), for
> > example, we have 6 (!) path components:
> > // and //
> >
> > (I am assuming the child paths always represent just the last path
> > component based on the observed inodes of the parent/child records.)
> >
> > Current record format can distinguish between PARENT and child
> > (DELETE/CREATE), but there is no nametype for the dirfd path. That's
> > why I am leaning towards just logging the full "<*_dir>/<*_parent>"
> > path in the PARENT record. Or do you prefer that we add a new nametype
> > for the dirfd path?
>
> You could make a new nametype so that we can make sense of it. But do you
> have all of the required information for a PATH record? I thought that you
> were making a new record type since you have abbreviated information.

I think it should be possible to collect that information by putting
hooks in the right places of the filesystem code (and fixing the
current ones).

To be honest, the reason why I had jumped right to making a new record
type was Paul's wording in the issue description ("We may need a new
auxiliary record type since this is neither the cwd or path." - the
second part of that sentence sounded like using the PATH record
wouldn't be a reasonable choice) and the fact that the purpose of the
PATH records was not clear to me at that time. Now that I spent some
time with them, they don't look that scary anymore :)

--
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [RFC PATCH ghak9 0/3] audit: Record the path of FDs passed to *at(2) syscalls

2018-07-25 Thread Ondrej Mosnacek
On Wed, Jul 25, 2018 at 2:48 PM Steve Grubb  wrote:
> On Wednesday, July 25, 2018 3:44:07 AM EDT Ondrej Mosnacek wrote:
> > On Wed, Jul 25, 2018 at 3:11 AM Steve Grubb  wrote:
> > > On Tuesday, July 24, 2018 6:15:54 PM EDT Paul Moore wrote:
> > > > On Tue, Jul 24, 2018 at 10:12 AM Ondrej Mosnacek 
> > > >
> > > > > Beyond that, there is really no information in the records that would
> > > > > allow reconstructing which PARENT path belongs to which CREATE/DELETE
> > > > > path... (Intuitively you can guess that src will come before dst, but
> > > > > that is not very reliable.) I think a "parent inode" field in the
> > > > > PATH
> > > > > records could fix this, but maybe there is a better solution...
> > > >
> > > > I have my suspicions, but I would be curious to hear from Steve how
> > > > the reconstruction is typically handled.
> > >
> > > For any *at function when the dirfd is not AT_FDCWD, it goes badly. If
> > > its a old style syscall without the dirfd, then if the first character
> > > is '/' use that. Otherwise concatonate cwd and path and pass it to
> > > realpath to sort out.
> >
> > In that case it seems the best fix for openat() et al. would be to
> > somehow always force outputting the full path when dirfd != AT_FDCWD.
> > Hopefully that won't require too much hacking around...
>
> What is asked for is the full path that dirfd was opened with. I can take
> care of everything else.

But where/how should that path be logged? In case of renameat(), for
example, we have 6 (!) path components:
// and //

(I am assuming the child paths always represent just the last path
component based on the observed inodes of the parent/child records.)

Current record format can distinguish between PARENT and child
(DELETE/CREATE), but there is no nametype for the dirfd path. That's
why I am leaning towards just logging the full "<*_dir>/<*_parent>"
path in the PARENT record. Or do you prefer that we add a new nametype
for the dirfd path?

-- 
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [RFC PATCH ghak9 0/3] audit: Record the path of FDs passed to *at(2) syscalls

2018-07-25 Thread Ondrej Mosnacek
On Wed, Jul 25, 2018 at 3:11 AM Steve Grubb  wrote:
> On Tuesday, July 24, 2018 6:15:54 PM EDT Paul Moore wrote:
> > On Tue, Jul 24, 2018 at 10:12 AM Ondrej Mosnacek 
> > > Beyond that, there is really no information in the records that would
> > > allow reconstructing which PARENT path belongs to which CREATE/DELETE
> > > path... (Intuitively you can guess that src will come before dst, but
> > > that is not very reliable.) I think a "parent inode" field in the PATH
> > > records could fix this, but maybe there is a better solution...
> >
> > I have my suspicions, but I would be curious to hear from Steve how
> > the reconstruction is typically handled.
>
> For any *at function when the dirfd is not AT_FDCWD, it goes badly. If its a
> old style syscall without the dirfd, then if the first character is '/' use
> that. Otherwise concatonate cwd and path and pass it to realpath to sort out.

In that case it seems the best fix for openat() et al. would be to
somehow always force outputting the full path when dirfd != AT_FDCWD.
Hopefully that won't require too much hacking around...

--
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [RFC PATCH ghak9 0/3] audit: Record the path of FDs passed to *at(2) syscalls

2018-07-24 Thread Ondrej Mosnacek
On Mon, Jul 23, 2018 at 10:49 PM Paul Moore  wrote:
> On Fri, Jul 20, 2018 at 6:12 AM Ondrej Mosnacek  wrote:
> > On Wed, Jul 18, 2018 at 10:41 PM Paul Moore  wrote:
> > > On Thu, Jul 12, 2018 at 7:36 AM Ondrej Mosnacek  
> > > wrote:
> > > > This patchset is a prototype implementation of the feature requested in 
> > > > GHAK issue #9 [1]. I decided for a simple auxiliary record with just 2 
> > > > fields (fd and path) that is emitted whenever we want to record the 
> > > > full path for a file descriptor passed to a syscall (e.g. the dirfd 
> > > > argument of openat(2)). I choose this approach because for some 
> > > > syscalls there is more than one file descriptor we might be interested 
> > > > in (a good example is the renameat(2) syscall).
> > > >
> > > > The motivation for this feature (as I understand it) is to avoid the 
> > > > need to reconstruct the paths corresponding to the file descriptors 
> > > > passed to syscalls, as this might be difficult and time consuming or 
> > > > even impossible in case not all of the right sycalls are being logged. 
> > > > Note that it is always possible to disable these records by simply 
> > > > adding an exclude filter rule matching all records of type FD_PATH.
> > > >
> > > > At this moment I only implement logging for a single syscall 
> > > > (openat(2)) to keep it simple. In the final version I plan to add 
> > > > support for other similar syscalls ()mkdirat, mknodeat, fchownat, ...).
> > > >
> > > > Please let me know if the general approach and the proposed record 
> > > > format make sense to you so I can improve/complete the solution.
> > > >
> > > > Thanks,
> > > > Ondrej
> > > >
> > > > [1] https://github.com/linux-audit/audit-kernel/issues/9
> > >
> > > While I recognize that the GH issue did raise the idea of possibly
> > > creating a new record type, looking at these patches I'm not sure a
> > > new record type is justified, I think reusing the existing PATH record
> > > type would be more beneficial.  I recognize that this proposed FD_PATH
> > > record also contains the file descriptor number, but that information
> > > should also be contained in the associated SYSCALL record and arguably
> > > the fd number is only useful if you are logging the SYSCALL
> > > information.
> >
> > To be honest, I'm not sure what is the exact semantic of the PATH
> > record... Is it simply "log information about files that the syscall
> > somehow touched"? Or "log information about any string syscall
> > argument that represents a file path"?
>
> The PATH record exists to record path name information about files
> related to the audit event, depending on the circumstances, both
> relative and absolute paths could be expected.  Look at the functions,
> and callers, that add to the audit_context->names_list to get a better
> understanding of where the path name information is collected.  I
> doubt you will be surprised at this, but fair warning, it's a bit ugly
> in places.
>
> > In the PATH record samples I
> > have seen, the name=... field sometimes contains just the last segment
> > of the path, other times it contains the full path (huh?).
>
> Depending on the syscall, the syscall arguments, and the "nametype" of
> the PATH record you could see either a full or partial path.  In the
> cases of a partial path, there *should* be additional PATH records
> which can help recreate a full path to the file for that particular
> event instance.
>
> > When we log
> > the full path in PATH, then I guess the FD_PATH record would be
> > (almost) redundant, but it seems that whenever openat(2) is called
> > with dirfd != AT_FDCWD, PATH name=... contains just the relative path
> > supplied to the syscall (thus FD_PATH actually provides the missing
> > directory path).
> >
> > So... assuming we would want to provide the missing information in the
> > existing PATH record, how should it look like? Should the name=...
> > field simply always contain the full path? Should there be another
> > PATH record for the directory?
>
> The only real hard requirement is that there be enough to information
> to determine the file full path(s) for any given audit event using
> one, or a combination, of PATH records associated with the event.
>
> > If so, how do we indicate the association between the two PATH records?
>
> Look at how the "nametype&q

Re: [RFC PATCH ghak9 0/3] audit: Record the path of FDs passed to *at(2) syscalls

2018-07-20 Thread Ondrej Mosnacek
On Wed, Jul 18, 2018 at 10:41 PM Paul Moore  wrote:
> On Thu, Jul 12, 2018 at 7:36 AM Ondrej Mosnacek  wrote:
> > This patchset is a prototype implementation of the feature requested in 
> > GHAK issue #9 [1]. I decided for a simple auxiliary record with just 2 
> > fields (fd and path) that is emitted whenever we want to record the full 
> > path for a file descriptor passed to a syscall (e.g. the dirfd argument of 
> > openat(2)). I choose this approach because for some syscalls there is more 
> > than one file descriptor we might be interested in (a good example is the 
> > renameat(2) syscall).
> >
> > The motivation for this feature (as I understand it) is to avoid the need 
> > to reconstruct the paths corresponding to the file descriptors passed to 
> > syscalls, as this might be difficult and time consuming or even impossible 
> > in case not all of the right sycalls are being logged. Note that it is 
> > always possible to disable these records by simply adding an exclude filter 
> > rule matching all records of type FD_PATH.
> >
> > At this moment I only implement logging for a single syscall (openat(2)) to 
> > keep it simple. In the final version I plan to add support for other 
> > similar syscalls ()mkdirat, mknodeat, fchownat, ...).
> >
> > Please let me know if the general approach and the proposed record format 
> > make sense to you so I can improve/complete the solution.
> >
> > Thanks,
> > Ondrej
> >
> > [1] https://github.com/linux-audit/audit-kernel/issues/9
>
> While I recognize that the GH issue did raise the idea of possibly
> creating a new record type, looking at these patches I'm not sure a
> new record type is justified, I think reusing the existing PATH record
> type would be more beneficial.  I recognize that this proposed FD_PATH
> record also contains the file descriptor number, but that information
> should also be contained in the associated SYSCALL record and arguably
> the fd number is only useful if you are logging the SYSCALL
> information.

To be honest, I'm not sure what is the exact semantic of the PATH
record... Is it simply "log information about files that the syscall
somehow touched"? Or "log information about any string syscall
argument that represents a file path"? In the PATH record samples I
have seen, the name=... field sometimes contains just the last segment
of the path, other times it contains the full path (huh?). When we log
the full path in PATH, then I guess the FD_PATH record would be
(almost) redundant, but it seems that whenever openat(2) is called
with dirfd != AT_FDCWD, PATH name=... contains just the relative path
supplied to the syscall (thus FD_PATH actually provides the missing
directory path).

So... assuming we would want to provide the missing information in the
existing PATH record, how should it look like? Should the name=...
field simply always contain the full path? Should there be another
PATH record for the directory? If so, how do we indicate the
association between the two PATH records?

> Can you explain what advantage the FS_PATH record type has over
> reusing the existing PATH record?  I know you mention multiple
> fd/paths as in the case of renameat(2), but we already have to deal
> with this in the non-at rename(2) case.

As I said above, I don't fully understand the PATH record so I can't
compare them right now. Multiple fd arguments was meant as more of a
justification for the presence of the fd=... field in the new FD_PATH
record.

--
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [RFC PATCH ghak10 v3 0/3] audit: Log modifying adjtimex(2) calls

2018-07-19 Thread Ondrej Mosnacek
On Wed, Jul 18, 2018 at 9:59 PM Paul Moore  wrote:
> On Wed, Jul 18, 2018 at 3:36 PM Steve Grubb  wrote:
> > On Wednesday, July 18, 2018 2:36:11 PM EDT Paul Moore wrote:
> > > > Changes in v2:
> > > > - The audit_adjtime() function has been modified to only log those
> > > > fields that contain values that are actually used, resulting in more
> > > > compact records.
> > > > - The audit_adjtime() call has been moved to do_adjtimex() in
> > > > timekeeping.c
> > > > - Added an additional patch (for review) that simplifies the detection
> > > > if the syscall is read-only.
> > >
> > > Looking at these new records, and trying to guess a bit at the
> > > original intent of the feature request, I think we may be going a bit
> > > overboard with the information we are logging.  I'm thinking all we
> > > really need to capture in the audit log is the system time both before
> > > and after the change (for the sake of simplicity I suggest using a
> > > data format similar to the audit record timestamp).
> > >
> > > While I created the GH issue for this, I believe the original request
> > > came from a Red Hat BZ that Steve created; Steve, what sort of
> > > certification requirements (if any?) are there for logging system time
> > > changes?
> >
> > That we record any attempts to change the system time. The problem is that
> > adjtimex passes a data structure that is opaque to user space. So, we can't
> > tell if someone is setting time, adjusting a tolerance, or simply retrieving
> > status.
> >
> > With stime, we can clearly see the time that was sent into the kernel and it
> > unconditionally sets time. With settimeofday, it uses a data structure that
> > we cannot see, but whatever the contents are we are definitely setting time.
> > Same goes for clock_settime. Only in 1 case do we actually see what the time
> > is. So, that is not really needed. So, I think what we need to know is did
> > the syscall do anything that adjusted the system's notion of time? And 
> > that's
> > all.
>
> So presumably my above suggestion of simply recording the system time
> both before and after the change would be sufficient, yes?

I wouldn't say this is the right approach here, for two reasons that
I'll try to explain below.

adjtimex(2) can be basically used for two major types of adjustment:
1. for (immediately) injecting offset into system time,
2. for changing NTP status variables.

(1.) is the more obvious and simple adjustment, which *directly*
alters the system time. For this adjustment the current proposed
solution simply logs the delta, by which the time is adjusted (it can
be retrieved easily from the supplied timex struct). In my opinion,
logging of this delta is more explicit than logging the timestamps
(which might not give the precise offset anyway, since time might flow
between the two timestamps) and is also more easily grepped in the
logs, as Steve pointed out in his reply. For example, you can quickly
filter out adjustments of less than +/-1 second by simply comparing
the offset in the records.

(2.) is a lot more tricky... These adjustments modify the variables of
the NTP algorithm, which is quite complex and it is not obvious how it
influences the system time. From my understanding, the algorithm is
used for adjustments that require smooth transition over time - such
as (or maybe this is the only use case) inserting a leap second. Note
that in this case, just logging timestamp before and after the syscall
is not sufficient, since the change doesn't happen immediately, but in
small increments that are gradually added *after* the syscall already
finished. I don't know if (or which of) these adjustments can be used
for a real attack, but at least the leap second insertion sounds like
something that could be used to shift the time without being easily
detected. This is why I am wary of throwing things out from the
logging until we understand what is truly important and what is not.

So, to sum up, my two arguments against logging before/after timestamps are:
1. For the case of direct offset injection we can much more easily log
the actual offset and this is also more informative.
2. For the case of NTP adjustments it is just not sufficient, we need
to log some or all of the variable adjustments and let the people
analyzing the logs figure out how that influenced the clock later (NTP
algorithm is just too complex).

I hope this explanation makes the situation a bit more clear. Time is
hard [1] and this particular time issue just refuses to be any
different :)

[1] http://sflanders.net/2015/02/09/time-hard-proper-ntp-configuration/

-- 
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


Re: [RFC PATCH ghak9 2/3] audit: Add a function to log the path of an fd

2018-07-16 Thread Ondrej Mosnacek
On Sat, Jul 14, 2018 at 6:26 PM Steve Grubb  wrote:
> On Thursday, July 12, 2018 7:36:32 AM EDT Ondrej Mosnacek wrote:
> > The function logs an FD_PATH record that is associated with the current
> > syscall. The record associates the given file descriptor with the
> > current path of the file under it (if it is possible to retrieve such
> > path). The reader of the log can then logically connect this information
> > to the syscall arguments from the SYSCALL record (based on the syscall
> > type).
> >
> > Record format:
> > type=FD_PATH msg=audit(...): fd= path=
>
> Event looks OK to me. However, do you check for AT_FDCWD? If so, should we
> skip generating this record?

Yes, AT_FDCWD is defined as -100 and I explicitly reject all negative
file descriptors (I'll add a comment clarifying that).

>
> -Steve
>
> > Signed-off-by: Ondrej Mosnacek 
> > ---
> >  include/linux/audit.h | 10 ++
> >  kernel/auditsc.c  | 36 
> >  2 files changed, 46 insertions(+)
> >
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index 9334fbef7bae..95d338bb603a 100644
> > --- a/include/linux/audit.h
> > +++ b/include/linux/audit.h
> > @@ -356,6 +356,7 @@ extern void __audit_log_capset(const struct cred *new,
> > const struct cred *old); extern void __audit_mmap_fd(int fd, int flags);
> >  extern void __audit_log_kern_module(char *name);
> >  extern void __audit_fanotify(unsigned int response);
> > +extern void __audit_fd_path(int fd);
> >
> >  static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
> >  {
> > @@ -458,6 +459,12 @@ static inline void audit_fanotify(unsigned int
> > response) __audit_fanotify(response);
> >  }
> >
> > +static inline void audit_fd_path(int fd)
> > +{
> > + if (fd >= 0 && !audit_dummy_context())
> > + __audit_fd_path(fd);
> > +}
> > +
> >  extern int audit_n_rules;
> >  extern int audit_signals;
> >  #else /* CONFIG_AUDITSYSCALL */
> > @@ -584,6 +591,9 @@ static inline void audit_log_kern_module(char *name)
> >  static inline void audit_fanotify(unsigned int response)
> >  { }
> >
> > +static inline void audit_fd_path(int fd)
> > +{ }
> > +
> >  static inline void audit_ptrace(struct task_struct *t)
> >  { }
> >  #define audit_n_rules 0
> > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > index d762e0b8160e..82dad69213a2 100644
> > --- a/kernel/auditsc.c
> > +++ b/kernel/auditsc.c
> > @@ -74,6 +74,8 @@
> >  #include 
> >  #include 
> >  #include 
> > +#include 
> > +#include 
> >  #include 
> >
> >  #include "audit.h"
> > @@ -2422,6 +2424,40 @@ void __audit_fanotify(unsigned int response)
> >   AUDIT_FANOTIFY, "resp=%u", response);
> >  }
> >
> > +void __audit_fd_path(int fd)
> > +{
> > + struct audit_buffer *ab;
> > + struct file *file;
> > + char *buf, *path;
> > +
> > + if (!audit_enabled)
> > + return;
> > +
> > + file = fget_raw(fd);
> > + if (!file)
> > + return;
> > +
> > + buf = kmalloc(PATH_MAX, GFP_KERNEL);
> > + if (!buf)
> > + return;
> > +
> > + path_get(>f_path);
> > + path = d_absolute_path(>f_path, buf, PATH_MAX);
> > + path_put(>f_path);
> > + fput(file);
> > + if (!path || IS_ERR(path))
> > + goto free_buf;
> > +
> > + ab = audit_log_start(audit_context(), GFP_KERNEL, AUDIT_FD_PATH);
> > + if (unlikely(!ab))
> > + goto free_buf;
> > + audit_log_format(ab, "fd=%i path=", fd);
> > + audit_log_untrustedstring(ab, path);
> > + audit_log_end(ab);
> > +free_buf:
> > + kfree(buf);
> > +}
> > +
> >  static void audit_log_task(struct audit_buffer *ab)
> >  {
> >   kuid_t auid, uid;
>
>
>
>


-- 
Ondrej Mosnacek 
Associate Software Engineer, Security Technologies
Red Hat, Inc.

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit


  1   2   >