diff -ru lsm-2.4/arch/mips/kernel/sysirix.c lsm-2.4-settime/arch/mips/kernel/sysirix.c --- lsm-2.4/arch/mips/kernel/sysirix.c 2003-12-11 14:43:11.000000000 -0600 +++ lsm-2.4-settime/arch/mips/kernel/sysirix.c 2003-12-12 10:17:28.000000000 -0600 @@ -618,8 +618,14 @@ asmlinkage int irix_stime(int value) { - if (!capable(CAP_SYS_TIME)) - return -EPERM; + int err; + struct timespec ts; + + ts.tv_sec = value; + ts.tv_nsec = 0; + err = security_settime(&ts, NULL); + if (err) + return err; write_lock_irq(&xtime_lock); xtime.tv_sec = value; diff -ru lsm-2.4/include/linux/init.h lsm-2.4-settime/include/linux/init.h --- lsm-2.4/include/linux/init.h 2003-12-11 14:43:34.000000000 -0600 +++ lsm-2.4-settime/include/linux/init.h 2003-12-11 16:52:09.000000000 -0600 @@ -124,6 +124,8 @@ #define __initcall(fn) #define __security_initcall(fn) +#define security_initcall(fn) module_init(fn) + /* For assembly routines */ #define __INIT #define __FINIT diff -ru lsm-2.4/include/linux/security.h lsm-2.4-settime/include/linux/security.h --- lsm-2.4/include/linux/security.h 2003-12-11 14:43:34.000000000 -0600 +++ lsm-2.4-settime/include/linux/security.h 2003-12-12 10:04:32.000000000 -0600 @@ -39,6 +39,7 @@ * as the default capabilities functions */ extern int cap_capable (struct task_struct *tsk, int cap); +extern int cap_settime (struct timespec *ts, struct timezone *tz); struct sk_buff; extern int cap_netlink_send (struct sk_buff *skb); extern int cap_netlink_recv (struct sk_buff *skb); @@ -1177,8 +1178,8 @@ * Return 0 if permission is granted. * @settime: * Check permission to change the system time. - * struct timeval and timezone are defined in include/linux/time.h - * @tv contains new time + * struct timespec and timezone are defined in include/linux/time.h + * @ts contains new time * @tz contains new timezone * Return 0 if permission is granted. * @@ -1265,7 +1266,7 @@ int (*quotactl) (int cmds, int type, int id, struct super_block * sb); int (*quota_on) (struct file * f); int (*syslog) (int type); - int (*settime) (struct timeval *tv, struct timezone *tz); + int (*settime) (struct timespec *ts, struct timezone *tz); int (*netlink_send) (struct sk_buff * skb); int (*netlink_recv) (struct sk_buff * skb); @@ -1618,9 +1619,9 @@ return security_ops->syslog(type); } -static inline int security_settime(struct timeval *tv, struct timezone *tz) +static inline int security_settime(struct timespec *ts, struct timezone *tz) { - return security_ops->settime(tv, tz); + return security_ops->settime(ts, tz); } static inline int security_netlink_send(struct sk_buff * skb) @@ -2369,9 +2370,9 @@ return cap_syslog(type); } -static inline int security_settime(struct timeval *tv, struct timezone *tz) +static inline int security_settime(struct timespec *ts, struct timezone *tz) { - return 0; + return cap_settime(ts, tz); } static inline int security_netlink_send(struct sk_buff * skb) diff -ru lsm-2.4/kernel/time.c lsm-2.4-settime/kernel/time.c --- lsm-2.4/kernel/time.c 2003-12-11 14:43:35.000000000 -0600 +++ lsm-2.4-settime/kernel/time.c 2003-12-12 10:42:11.000000000 -0600 @@ -75,11 +75,18 @@ asmlinkage long sys_stime(int * tptr) { int value; + struct timespec ts; + int err; - if (!capable(CAP_SYS_TIME)) - return -EPERM; if (get_user(value, tptr)) return -EFAULT; + + ts.tv_sec = value; + ts.tv_nsec = 0; + err = security_settime(&ts, NULL); + if (err) + return err; + write_lock_irq(&xtime_lock); vxtime_lock(); xtime.tv_sec = value; @@ -150,14 +157,14 @@ { static int firsttime = 1; int error = 0; + struct timespec ts; - if (!capable(CAP_SYS_TIME)) - return -EPERM; - - /* Call the Linux Security Module to perform its checks */ - error = security_settime(tv, tz); - if (error) - return error; + /* Call the Linux Security Module to perform its checks */ + ts.tv_sec = tv.tv_sec; + ts.tv_nsec = tv.tv_usec * NSEC_PER_USEC; + error = security_settime(&ts, tz); + if (error) + return error; if (tz) { /* SMP safe, global irq locking makes it work. */ diff -ru lsm-2.4/security/capability.c lsm-2.4-settime/security/capability.c --- lsm-2.4/security/capability.c 2003-12-11 14:43:36.000000000 -0600 +++ lsm-2.4-settime/security/capability.c 2003-12-12 10:13:19.000000000 -0600 @@ -36,6 +36,14 @@ return -EPERM; } +int cap_settime (struct timespec *ts, struct timezone *tz) +{ + if (!capable (CAP_SYS_TIME)) + return -EPERM; + else + return 0; +} + int cap_netlink_send (struct sk_buff *skb) { NETLINK_CB (skb).eff_cap = current->cap_effective; @@ -316,6 +324,7 @@ } EXPORT_SYMBOL(cap_capable); +EXPORT_SYMBOL(cap_settime); EXPORT_SYMBOL(cap_ptrace); EXPORT_SYMBOL(cap_capget); EXPORT_SYMBOL(cap_capset_check); @@ -339,6 +348,7 @@ .capset_check = cap_capset_check, .capset_set = cap_capset_set, .capable = cap_capable, + .settime = cap_settime, .netlink_send = cap_netlink_send, .netlink_recv = cap_netlink_recv, diff -ru lsm-2.4/security/dummy.c lsm-2.4-settime/security/dummy.c --- lsm-2.4/security/dummy.c 2003-12-11 14:43:36.000000000 -0600 +++ lsm-2.4-settime/security/dummy.c 2003-12-12 10:18:12.000000000 -0600 @@ -164,8 +164,10 @@ return 0; } -static int dummy_settime (struct timeval *tv, struct timezone *tz) +static int dummy_settime (struct timespec *ts, struct timezone *tz) { + if (!capable (CAP_SYS_TIME)) + return -EPERM; return 0; }