aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOndrej Mosnacek <omosnace@redhat.com>2019-04-10 05:14:20 -0400
committerPaul Moore <paul@paul-moore.com>2019-04-15 18:14:01 -0400
commit7e8eda734d30de81d06a949c9bf9853c445ede4e (patch)
treed16d77f902e5e7bc24ce1afcb0589544d5e5e602
parent2d87a0674bd60d855e4008e2d84f5b23d7cb9b7d (diff)
ntp: Audit NTP parameters adjustment
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 <omosnace@redhat.com> Reviewed-by: Richard Guy Briggs <rgb@redhat.com> Reviewed-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Paul Moore <paul@paul-moore.com>
-rw-r--r--include/linux/audit.h61
-rw-r--r--include/uapi/linux/audit.h1
-rw-r--r--kernel/auditsc.c22
-rw-r--r--kernel/time/ntp.c22
-rw-r--r--kernel/time/ntp_internal.h4
-rw-r--r--kernel/time/timekeeping.c7
6 files changed, 112 insertions, 5 deletions
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 2c62c0468888..43a23e28ba23 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -86,6 +86,29 @@ struct audit_field {
86 u32 op; 86 u32 op;
87}; 87};
88 88
89enum audit_ntp_type {
90 AUDIT_NTP_OFFSET,
91 AUDIT_NTP_FREQ,
92 AUDIT_NTP_STATUS,
93 AUDIT_NTP_TAI,
94 AUDIT_NTP_TICK,
95 AUDIT_NTP_ADJUST,
96
97 AUDIT_NTP_NVALS /* count */
98};
99
100#ifdef CONFIG_AUDITSYSCALL
101struct audit_ntp_val {
102 long long oldval, newval;
103};
104
105struct audit_ntp_data {
106 struct audit_ntp_val vals[AUDIT_NTP_NVALS];
107};
108#else
109struct audit_ntp_data {};
110#endif
111
89extern int is_audit_feature_set(int which); 112extern int is_audit_feature_set(int which);
90 113
91extern int __init audit_register_class(int class, unsigned *list); 114extern int __init audit_register_class(int class, unsigned *list);
@@ -366,6 +389,7 @@ extern void __audit_mmap_fd(int fd, int flags);
366extern void __audit_log_kern_module(char *name); 389extern void __audit_log_kern_module(char *name);
367extern void __audit_fanotify(unsigned int response); 390extern void __audit_fanotify(unsigned int response);
368extern void __audit_tk_injoffset(struct timespec64 offset); 391extern void __audit_tk_injoffset(struct timespec64 offset);
392extern void __audit_ntp_log(const struct audit_ntp_data *ad);
369 393
370static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) 394static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp)
371{ 395{
@@ -478,6 +502,29 @@ static inline void audit_tk_injoffset(struct timespec64 offset)
478 __audit_tk_injoffset(offset); 502 __audit_tk_injoffset(offset);
479} 503}
480 504
505static inline void audit_ntp_init(struct audit_ntp_data *ad)
506{
507 memset(ad, 0, sizeof(*ad));
508}
509
510static inline void audit_ntp_set_old(struct audit_ntp_data *ad,
511 enum audit_ntp_type type, long long val)
512{
513 ad->vals[type].oldval = val;
514}
515
516static inline void audit_ntp_set_new(struct audit_ntp_data *ad,
517 enum audit_ntp_type type, long long val)
518{
519 ad->vals[type].newval = val;
520}
521
522static inline void audit_ntp_log(const struct audit_ntp_data *ad)
523{
524 if (!audit_dummy_context())
525 __audit_ntp_log(ad);
526}
527
481extern int audit_n_rules; 528extern int audit_n_rules;
482extern int audit_signals; 529extern int audit_signals;
483#else /* CONFIG_AUDITSYSCALL */ 530#else /* CONFIG_AUDITSYSCALL */
@@ -594,6 +641,20 @@ static inline void audit_fanotify(unsigned int response)
594static inline void audit_tk_injoffset(struct timespec64 offset) 641static inline void audit_tk_injoffset(struct timespec64 offset)
595{ } 642{ }
596 643
644static inline void audit_ntp_init(struct audit_ntp_data *ad)
645{ }
646
647static inline void audit_ntp_set_old(struct audit_ntp_data *ad,
648 enum audit_ntp_type type, long long val)
649{ }
650
651static inline void audit_ntp_set_new(struct audit_ntp_data *ad,
652 enum audit_ntp_type type, long long val)
653{ }
654
655static inline void audit_ntp_log(const struct audit_ntp_data *ad)
656{ }
657
597static inline void audit_ptrace(struct task_struct *t) 658static inline void audit_ptrace(struct task_struct *t)
598{ } 659{ }
599#define audit_n_rules 0 660#define audit_n_rules 0
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index ab58d67baf4d..a1280af20336 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -115,6 +115,7 @@
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#define AUDIT_TIME_INJOFFSET 1332 /* Timekeeping offset injected */
118#define AUDIT_TIME_ADJNTPVAL 1333 /* NTP value adjustment */
118 119
119#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */ 120#define AUDIT_AVC 1400 /* SE Linux avc denial or grant */
120#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */ 121#define AUDIT_SELINUX_ERR 1401 /* Internal SE Linux Errors */
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 3843495d0083..5371b59bde36 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2519,6 +2519,28 @@ void __audit_tk_injoffset(struct timespec64 offset)
2519 (long long)offset.tv_sec, offset.tv_nsec); 2519 (long long)offset.tv_sec, offset.tv_nsec);
2520} 2520}
2521 2521
2522static void audit_log_ntp_val(const struct audit_ntp_data *ad,
2523 const char *op, enum audit_ntp_type type)
2524{
2525 const struct audit_ntp_val *val = &ad->vals[type];
2526
2527 if (val->newval == val->oldval)
2528 return;
2529
2530 audit_log(audit_context(), GFP_KERNEL, AUDIT_TIME_ADJNTPVAL,
2531 "op=%s old=%lli new=%lli", op, val->oldval, val->newval);
2532}
2533
2534void __audit_ntp_log(const struct audit_ntp_data *ad)
2535{
2536 audit_log_ntp_val(ad, "offset", AUDIT_NTP_OFFSET);
2537 audit_log_ntp_val(ad, "freq", AUDIT_NTP_FREQ);
2538 audit_log_ntp_val(ad, "status", AUDIT_NTP_STATUS);
2539 audit_log_ntp_val(ad, "tai", AUDIT_NTP_TAI);
2540 audit_log_ntp_val(ad, "tick", AUDIT_NTP_TICK);
2541 audit_log_ntp_val(ad, "adjust", AUDIT_NTP_ADJUST);
2542}
2543
2522static void audit_log_task(struct audit_buffer *ab) 2544static void audit_log_task(struct audit_buffer *ab)
2523{ 2545{
2524 kuid_t auid, uid; 2546 kuid_t auid, uid;
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index 92a90014a925..ac5555e25733 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -17,6 +17,7 @@
17#include <linux/mm.h> 17#include <linux/mm.h>
18#include <linux/module.h> 18#include <linux/module.h>
19#include <linux/rtc.h> 19#include <linux/rtc.h>
20#include <linux/audit.h>
20 21
21#include "ntp_internal.h" 22#include "ntp_internal.h"
22#include "timekeeping_internal.h" 23#include "timekeeping_internal.h"
@@ -709,7 +710,7 @@ static inline void process_adjtimex_modes(const struct __kernel_timex *txc,
709 * kernel time-keeping variables. used by xntpd. 710 * kernel time-keeping variables. used by xntpd.
710 */ 711 */
711int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts, 712int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
712 s32 *time_tai) 713 s32 *time_tai, struct audit_ntp_data *ad)
713{ 714{
714 int result; 715 int result;
715 716
@@ -720,14 +721,29 @@ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
720 /* adjtime() is independent from ntp_adjtime() */ 721 /* adjtime() is independent from ntp_adjtime() */
721 time_adjust = txc->offset; 722 time_adjust = txc->offset;
722 ntp_update_frequency(); 723 ntp_update_frequency();
724
725 audit_ntp_set_old(ad, AUDIT_NTP_ADJUST, save_adjust);
726 audit_ntp_set_new(ad, AUDIT_NTP_ADJUST, time_adjust);
723 } 727 }
724 txc->offset = save_adjust; 728 txc->offset = save_adjust;
725 } else { 729 } else {
726
727 /* If there are input parameters, then process them: */ 730 /* If there are input parameters, then process them: */
728 if (txc->modes) 731 if (txc->modes) {
732 audit_ntp_set_old(ad, AUDIT_NTP_OFFSET, time_offset);
733 audit_ntp_set_old(ad, AUDIT_NTP_FREQ, time_freq);
734 audit_ntp_set_old(ad, AUDIT_NTP_STATUS, time_status);
735 audit_ntp_set_old(ad, AUDIT_NTP_TAI, *time_tai);
736 audit_ntp_set_old(ad, AUDIT_NTP_TICK, tick_usec);
737
729 process_adjtimex_modes(txc, time_tai); 738 process_adjtimex_modes(txc, time_tai);
730 739
740 audit_ntp_set_new(ad, AUDIT_NTP_OFFSET, time_offset);
741 audit_ntp_set_new(ad, AUDIT_NTP_FREQ, time_freq);
742 audit_ntp_set_new(ad, AUDIT_NTP_STATUS, time_status);
743 audit_ntp_set_new(ad, AUDIT_NTP_TAI, *time_tai);
744 audit_ntp_set_new(ad, AUDIT_NTP_TICK, tick_usec);
745 }
746
731 txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ, 747 txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ,
732 NTP_SCALE_SHIFT); 748 NTP_SCALE_SHIFT);
733 if (!(time_status & STA_NANO)) 749 if (!(time_status & STA_NANO))
diff --git a/kernel/time/ntp_internal.h b/kernel/time/ntp_internal.h
index 40e6122e634e..908ecaa65fc3 100644
--- a/kernel/time/ntp_internal.h
+++ b/kernel/time/ntp_internal.h
@@ -8,6 +8,8 @@ extern void ntp_clear(void);
8extern u64 ntp_tick_length(void); 8extern u64 ntp_tick_length(void);
9extern ktime_t ntp_get_next_leap(void); 9extern ktime_t ntp_get_next_leap(void);
10extern int second_overflow(time64_t secs); 10extern int second_overflow(time64_t secs);
11extern int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts, s32 *time_tai); 11extern int __do_adjtimex(struct __kernel_timex *txc,
12 const struct timespec64 *ts,
13 s32 *time_tai, struct audit_ntp_data *ad);
12extern void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts); 14extern void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts);
13#endif /* _LINUX_NTP_INTERNAL_H */ 15#endif /* _LINUX_NTP_INTERNAL_H */
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 3d24be4cd607..f366f2fdf1b0 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -2307,6 +2307,7 @@ static int timekeeping_validate_timex(const struct __kernel_timex *txc)
2307int do_adjtimex(struct __kernel_timex *txc) 2307int do_adjtimex(struct __kernel_timex *txc)
2308{ 2308{
2309 struct timekeeper *tk = &tk_core.timekeeper; 2309 struct timekeeper *tk = &tk_core.timekeeper;
2310 struct audit_ntp_data ad;
2310 unsigned long flags; 2311 unsigned long flags;
2311 struct timespec64 ts; 2312 struct timespec64 ts;
2312 s32 orig_tai, tai; 2313 s32 orig_tai, tai;
@@ -2330,13 +2331,15 @@ int do_adjtimex(struct __kernel_timex *txc)
2330 audit_tk_injoffset(delta); 2331 audit_tk_injoffset(delta);
2331 } 2332 }
2332 2333
2334 audit_ntp_init(&ad);
2335
2333 ktime_get_real_ts64(&ts); 2336 ktime_get_real_ts64(&ts);
2334 2337
2335 raw_spin_lock_irqsave(&timekeeper_lock, flags); 2338 raw_spin_lock_irqsave(&timekeeper_lock, flags);
2336 write_seqcount_begin(&tk_core.seq); 2339 write_seqcount_begin(&tk_core.seq);
2337 2340
2338 orig_tai = tai = tk->tai_offset; 2341 orig_tai = tai = tk->tai_offset;
2339 ret = __do_adjtimex(txc, &ts, &tai); 2342 ret = __do_adjtimex(txc, &ts, &tai, &ad);
2340 2343
2341 if (tai != orig_tai) { 2344 if (tai != orig_tai) {
2342 __timekeeping_set_tai_offset(tk, tai); 2345 __timekeeping_set_tai_offset(tk, tai);
@@ -2347,6 +2350,8 @@ int do_adjtimex(struct __kernel_timex *txc)
2347 write_seqcount_end(&tk_core.seq); 2350 write_seqcount_end(&tk_core.seq);
2348 raw_spin_unlock_irqrestore(&timekeeper_lock, flags); 2351 raw_spin_unlock_irqrestore(&timekeeper_lock, flags);
2349 2352
2353 audit_ntp_log(&ad);
2354
2350 /* Update the multiplier immediately if frequency was set directly */ 2355 /* Update the multiplier immediately if frequency was set directly */
2351 if (txc->modes & (ADJ_FREQUENCY | ADJ_TICK)) 2356 if (txc->modes & (ADJ_FREQUENCY | ADJ_TICK))
2352 timekeeping_advance(TK_ADV_FREQ); 2357 timekeeping_advance(TK_ADV_FREQ);