Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7e8eda73 authored by Ondrej Mosnacek's avatar Ondrej Mosnacek Committed by Paul Moore
Browse files

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: default avatarOndrej Mosnacek <omosnace@redhat.com>
Reviewed-by: default avatarRichard Guy Briggs <rgb@redhat.com>
Reviewed-by: default avatarThomas Gleixner <tglx@linutronix.de>
Signed-off-by: default avatarPaul Moore <paul@paul-moore.com>
parent 2d87a067
Loading
Loading
Loading
Loading
+61 −0
Original line number Diff line number Diff line
@@ -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 inline void audit_ntp_init(struct audit_ntp_data *ad)
{ }

static inline void audit_ntp_set_old(struct audit_ntp_data *ad,
				     enum audit_ntp_type type, long long val)
{ }

static inline void audit_ntp_set_new(struct audit_ntp_data *ad,
				     enum audit_ntp_type type, long long val)
{ }

static inline void audit_ntp_log(const struct audit_ntp_data *ad)
{ }

static inline void audit_ptrace(struct task_struct *t)
{ }
#define audit_n_rules 0
+1 −0
Original line number Diff line number Diff line
@@ -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 */
+22 −0
Original line number Diff line number Diff line
@@ -2519,6 +2519,28 @@ void __audit_tk_injoffset(struct timespec64 offset)
		  (long long)offset.tv_sec, offset.tv_nsec);
}

static void audit_log_ntp_val(const struct audit_ntp_data *ad,
			      const char *op, enum audit_ntp_type type)
{
	const struct audit_ntp_val *val = &ad->vals[type];

	if (val->newval == val->oldval)
		return;

	audit_log(audit_context(), GFP_KERNEL, AUDIT_TIME_ADJNTPVAL,
		  "op=%s old=%lli new=%lli", op, val->oldval, val->newval);
}

void __audit_ntp_log(const struct audit_ntp_data *ad)
{
	audit_log_ntp_val(ad, "offset",	AUDIT_NTP_OFFSET);
	audit_log_ntp_val(ad, "freq",	AUDIT_NTP_FREQ);
	audit_log_ntp_val(ad, "status",	AUDIT_NTP_STATUS);
	audit_log_ntp_val(ad, "tai",	AUDIT_NTP_TAI);
	audit_log_ntp_val(ad, "tick",	AUDIT_NTP_TICK);
	audit_log_ntp_val(ad, "adjust",	AUDIT_NTP_ADJUST);
}

static void audit_log_task(struct audit_buffer *ab)
{
	kuid_t auid, uid;
+19 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include <linux/mm.h>
#include <linux/module.h>
#include <linux/rtc.h>
#include <linux/audit.h>

#include "ntp_internal.h"
#include "timekeeping_internal.h"
@@ -709,7 +710,7 @@ static inline void process_adjtimex_modes(const struct __kernel_timex *txc,
 * kernel time-keeping variables. used by xntpd.
 */
int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
		  s32 *time_tai)
		  s32 *time_tai, struct audit_ntp_data *ad)
{
	int result;

@@ -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);
		}

		txc->offset = shift_right(time_offset * NTP_INTERVAL_FREQ,
				  NTP_SCALE_SHIFT);
		if (!(time_status & STA_NANO))
+3 −1
Original line number Diff line number Diff line
@@ -8,6 +8,8 @@ extern void ntp_clear(void);
extern u64 ntp_tick_length(void);
extern ktime_t ntp_get_next_leap(void);
extern int second_overflow(time64_t secs);
extern int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts, s32 *time_tai);
extern int __do_adjtimex(struct __kernel_timex *txc,
			 const struct timespec64 *ts,
			 s32 *time_tai, struct audit_ntp_data *ad);
extern void __hardpps(const struct timespec64 *phase_ts, const struct timespec64 *raw_ts);
#endif /* _LINUX_NTP_INTERNAL_H */
Loading