Due to the security_settime() with timespec type is not year 2038 safe on 32bit systems. Introduce the security_settime64() function with timespec64 type.
Change the settime() callback of security_list_options structure argument with timespec64 type as a helper function wrapped by security_settime64().
The cap_settime() as a helper function is only called by security_settime64() and security_settime() functions, and it need change the argument with timespec64 type.
Signed-off-by: Baolin Wang baolin.wang@linaro.org --- include/linux/lsm_hooks.h | 5 +++-- include/linux/security.h | 20 +++++++++++++++++--- security/commoncap.c | 2 +- security/security.c | 2 +- 4 files changed, 22 insertions(+), 7 deletions(-)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 9429f05..d791f35 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1191,7 +1191,8 @@ * Return 0 if permission is granted. * @settime: * Check permission to change the system time. - * struct timespec and timezone are defined in include/linux/time.h + * struct timespec64 is defined in include/linux/time64.h and timezone + * is defined in include/linux/time.h * @ts contains new time * @tz contains new timezone * Return 0 if permission is granted. @@ -1324,7 +1325,7 @@ union security_list_options { int (*quotactl)(int cmds, int type, int id, struct super_block *sb); int (*quota_on)(struct dentry *dentry); int (*syslog)(int type); - int (*settime)(const struct timespec *ts, const struct timezone *tz); + int (*settime)(const struct timespec64 *ts, const struct timezone *tz); int (*vm_enough_memory)(struct mm_struct *mm, long pages);
int (*bprm_set_creds)(struct linux_binprm *bprm); diff --git a/include/linux/security.h b/include/linux/security.h index 79d85dd..520f903 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -69,7 +69,7 @@ struct timezone; /* These functions are in security/commoncap.c */ extern int cap_capable(const struct cred *cred, struct user_namespace *ns, int cap, int audit); -extern int cap_settime(const struct timespec *ts, const struct timezone *tz); +extern int cap_settime(const struct timespec64 *ts, const struct timezone *tz); extern int cap_ptrace_access_check(struct task_struct *child, unsigned int mode); extern int cap_ptrace_traceme(struct task_struct *parent); extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted); @@ -206,7 +206,13 @@ int security_capable_noaudit(const struct cred *cred, struct user_namespace *ns, int security_quotactl(int cmds, int type, int id, struct super_block *sb); int security_quota_on(struct dentry *dentry); int security_syslog(int type); -int security_settime(const struct timespec *ts, const struct timezone *tz); +int security_settime64(const struct timespec64 *ts, const struct timezone *tz); +static int security_settime(const struct timespec *ts, const struct timezone *tz) +{ + struct timespec64 ts64 = timespec_to_timespec64(*ts); + + return security_settime64(&ts64, tz); +} int security_vm_enough_memory_mm(struct mm_struct *mm, long pages); int security_bprm_set_creds(struct linux_binprm *bprm); int security_bprm_check(struct linux_binprm *bprm); @@ -457,10 +463,18 @@ static inline int security_syslog(int type) return 0; }
+static inline int security_settime64(const struct timespec64 *ts, + const struct timezone *tz) +{ + return cap_settime(ts, tz); +} + static inline int security_settime(const struct timespec *ts, const struct timezone *tz) { - return cap_settime(ts, tz); + struct timsepc64 ts64 = timespec_to_timespec64(*ts); + + return cap_settime(&ts64, tz); }
static inline int security_vm_enough_memory_mm(struct mm_struct *mm, long pages) diff --git a/security/commoncap.c b/security/commoncap.c index d103f5a4..17b1f79 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -111,7 +111,7 @@ int cap_capable(const struct cred *cred, struct user_namespace *targ_ns, * Determine whether the current process may set the system clock and timezone * information, returning 0 if permission granted, -ve if denied. */ -int cap_settime(const struct timespec *ts, const struct timezone *tz) +int cap_settime(const struct timespec64 *ts, const struct timezone *tz) { if (!capable(CAP_SYS_TIME)) return -EPERM; diff --git a/security/security.c b/security/security.c index 595fffa..8d0dbd6 100644 --- a/security/security.c +++ b/security/security.c @@ -213,7 +213,7 @@ int security_syslog(int type) return call_int_hook(syslog, 0, type); }
-int security_settime(const struct timespec *ts, const struct timezone *tz) +int security_settime64(const struct timespec64 *ts, const struct timezone *tz) { return call_int_hook(settime, 0, ts, tz); }