diff options
| author | Ondrej Mosnacek <omosnace@redhat.com> | 2019-04-10 05:14:19 -0400 |
|---|---|---|
| committer | Paul Moore <paul@paul-moore.com> | 2019-04-15 18:10:17 -0400 |
| commit | 2d87a0674bd60d855e4008e2d84f5b23d7cb9b7d (patch) | |
| tree | f1652a306b9313539536d13ab52aa94249d1b0c9 | |
| parent | 699c1868a743f530081f429058616a2dd5d8a4b2 (diff) | |
timekeeping: Audit clock adjustments
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 <omosnace@redhat.com>
Reviewed-by: Richard Guy Briggs <rgb@redhat.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
[PM: fixed a line width problem in __audit_tk_injoffset()]
Signed-off-by: Paul Moore <paul@paul-moore.com>
| -rw-r--r-- | include/linux/audit.h | 14 | ||||
| -rw-r--r-- | include/uapi/linux/audit.h | 1 | ||||
| -rw-r--r-- | kernel/auditsc.c | 7 | ||||
| -rw-r--r-- | kernel/time/timekeeping.c | 6 |
4 files changed, 28 insertions, 0 deletions
diff --git a/include/linux/audit.h b/include/linux/audit.h index 1e69d9fe16da..2c62c0468888 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); | |||
| 365 | extern void __audit_mmap_fd(int fd, int flags); | 365 | extern void __audit_mmap_fd(int fd, int flags); |
| 366 | extern void __audit_log_kern_module(char *name); | 366 | extern void __audit_log_kern_module(char *name); |
| 367 | extern void __audit_fanotify(unsigned int response); | 367 | extern void __audit_fanotify(unsigned int response); |
| 368 | extern void __audit_tk_injoffset(struct timespec64 offset); | ||
| 368 | 369 | ||
| 369 | static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) | 370 | static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) |
| 370 | { | 371 | { |
| @@ -467,6 +468,16 @@ static inline void audit_fanotify(unsigned int response) | |||
| 467 | __audit_fanotify(response); | 468 | __audit_fanotify(response); |
| 468 | } | 469 | } |
| 469 | 470 | ||
| 471 | static inline void audit_tk_injoffset(struct timespec64 offset) | ||
| 472 | { | ||
| 473 | /* ignore no-op events */ | ||
| 474 | if (offset.tv_sec == 0 && offset.tv_nsec == 0) | ||
| 475 | return; | ||
| 476 | |||
| 477 | if (!audit_dummy_context()) | ||
| 478 | __audit_tk_injoffset(offset); | ||
| 479 | } | ||
| 480 | |||
| 470 | extern int audit_n_rules; | 481 | extern int audit_n_rules; |
| 471 | extern int audit_signals; | 482 | extern int audit_signals; |
| 472 | #else /* CONFIG_AUDITSYSCALL */ | 483 | #else /* CONFIG_AUDITSYSCALL */ |
| @@ -580,6 +591,9 @@ static inline void audit_log_kern_module(char *name) | |||
| 580 | static inline void audit_fanotify(unsigned int response) | 591 | static inline void audit_fanotify(unsigned int response) |
| 581 | { } | 592 | { } |
| 582 | 593 | ||
| 594 | static inline void audit_tk_injoffset(struct timespec64 offset) | ||
| 595 | { } | ||
| 596 | |||
| 583 | static inline void audit_ptrace(struct task_struct *t) | 597 | static inline void audit_ptrace(struct task_struct *t) |
| 584 | { } | 598 | { } |
| 585 | #define audit_n_rules 0 | 599 | #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 @@ | |||
| 114 | #define AUDIT_REPLACE 1329 /* Replace auditd if this packet unanswerd */ | 114 | #define AUDIT_REPLACE 1329 /* Replace auditd if this packet unanswerd */ |
| 115 | #define AUDIT_KERN_MODULE 1330 /* Kernel Module events */ | 115 | #define AUDIT_KERN_MODULE 1330 /* Kernel Module events */ |
| 116 | #define AUDIT_FANOTIFY 1331 /* Fanotify access decision */ | 116 | #define AUDIT_FANOTIFY 1331 /* Fanotify access decision */ |
| 117 | #define AUDIT_TIME_INJOFFSET 1332 /* Timekeeping offset injected */ | ||
| 117 | 118 | ||
| 118 | #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ | 119 | #define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ |
| 119 | #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ | 120 | #define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ |
diff --git a/kernel/auditsc.c b/kernel/auditsc.c index 51a2ceb3a1ca..3843495d0083 100644 --- a/kernel/auditsc.c +++ b/kernel/auditsc.c | |||
| @@ -2512,6 +2512,13 @@ void __audit_fanotify(unsigned int response) | |||
| 2512 | AUDIT_FANOTIFY, "resp=%u", response); | 2512 | AUDIT_FANOTIFY, "resp=%u", response); |
| 2513 | } | 2513 | } |
| 2514 | 2514 | ||
| 2515 | void __audit_tk_injoffset(struct timespec64 offset) | ||
| 2516 | { | ||
| 2517 | audit_log(audit_context(), GFP_KERNEL, AUDIT_TIME_INJOFFSET, | ||
| 2518 | "sec=%lli nsec=%li", | ||
| 2519 | (long long)offset.tv_sec, offset.tv_nsec); | ||
| 2520 | } | ||
| 2521 | |||
| 2515 | static void audit_log_task(struct audit_buffer *ab) | 2522 | static void audit_log_task(struct audit_buffer *ab) |
| 2516 | { | 2523 | { |
| 2517 | kuid_t auid, uid; | 2524 | 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 @@ | |||
| 21 | #include <linux/stop_machine.h> | 21 | #include <linux/stop_machine.h> |
| 22 | #include <linux/pvclock_gtod.h> | 22 | #include <linux/pvclock_gtod.h> |
| 23 | #include <linux/compiler.h> | 23 | #include <linux/compiler.h> |
| 24 | #include <linux/audit.h> | ||
| 24 | 25 | ||
| 25 | #include "tick-internal.h" | 26 | #include "tick-internal.h" |
| 26 | #include "ntp_internal.h" | 27 | #include "ntp_internal.h" |
| @@ -1250,6 +1251,9 @@ out: | |||
| 1250 | /* signal hrtimers about time change */ | 1251 | /* signal hrtimers about time change */ |
| 1251 | clock_was_set(); | 1252 | clock_was_set(); |
| 1252 | 1253 | ||
| 1254 | if (!ret) | ||
| 1255 | audit_tk_injoffset(ts_delta); | ||
| 1256 | |||
| 1253 | return ret; | 1257 | return ret; |
| 1254 | } | 1258 | } |
| 1255 | EXPORT_SYMBOL(do_settimeofday64); | 1259 | EXPORT_SYMBOL(do_settimeofday64); |
| @@ -2322,6 +2326,8 @@ int do_adjtimex(struct __kernel_timex *txc) | |||
| 2322 | ret = timekeeping_inject_offset(&delta); | 2326 | ret = timekeeping_inject_offset(&delta); |
| 2323 | if (ret) | 2327 | if (ret) |
| 2324 | return ret; | 2328 | return ret; |
| 2329 | |||
| 2330 | audit_tk_injoffset(delta); | ||
| 2325 | } | 2331 | } |
| 2326 | 2332 | ||
| 2327 | ktime_get_real_ts64(&ts); | 2333 | ktime_get_real_ts64(&ts); |
