The y2038 issue of printer exist in the time_t of timeval in ioctl
LPSETTIME. This patch try to convert it to y2038 safe by the
following steps:
1. Remove timeval from lp_set_timeout in order to support 32bit and
64bit time_t in the same function without the new definition
of timeval64 or something else.
2. Handle both 32bit and 64bit time in the same LPSETTIMEOUT switch
case in order to support y2038 safe and non-safe cases.
3. Merge compat of LPSETTIMEOUT into non-comapt one.
I thought split these steps into three different patches. But I feel
these changes are simple and direct.
Signed-off-by: Bamvor Jian Zhang <bamvor.zhangjian(a)linaro.org>
---
drivers/char/lp.c | 94 ++++++++++++++++++++++++++++++-------------------------
1 file changed, 52 insertions(+), 42 deletions(-)
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index c4094c4..a207e0c 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -136,6 +136,14 @@
#include <asm/irq.h>
#include <asm/uaccess.h>
+/*
+ * FIXME: It should be removed after COMPAT_USE_64BIT_TIME is accessible for
+ * 32bit architecture.
+ */
+#ifndef COMPAT_USE_64BIT_TIME
+#define COMPAT_USE_64BIT_TIME (0)
+#endif /* COMPAT_USE_64BIT_TIME */
+
/* if you have more than 8 printers, remember to increase LP_NO */
#define LP_NO 8
@@ -572,6 +580,22 @@ static int lp_release(struct inode * inode, struct file * file)
return 0;
}
+static int lp_set_timeout(unsigned int minor, s64 tv_sec, s64 tv_usec)
+{
+ long to_jiffies;
+
+ if ((tv_sec < 0) || (tv_usec < 0))
+ return -EINVAL;
+
+ to_jiffies = usecs_to_jiffies(tv_usec);
+ to_jiffies += tv_sec * (long)HZ;
+ if (to_jiffies <= 0)
+ return -EINVAL;
+
+ lp_table[minor].timeout = to_jiffies;
+ return 0;
+}
+
static int lp_do_ioctl(unsigned int minor, unsigned int cmd,
unsigned long arg, void __user *argp)
{
@@ -586,6 +610,9 @@ static int lp_do_ioctl(unsigned int minor, unsigned int cmd,
if ((LP_F(minor) & LP_EXIST) == 0)
return -ENODEV;
switch ( cmd ) {
+ s32 time32[2];
+ s64 time64[2];
+
case LPTIME:
if (arg > UINT_MAX / HZ)
return -EINVAL;
@@ -647,58 +674,49 @@ static int lp_do_ioctl(unsigned int minor, unsigned int cmd,
sizeof(struct lp_stats));
break;
#endif
- case LPGETFLAGS:
- status = LP_F(minor);
+ case LPGETFLAGS:
+ status = LP_F(minor);
if (copy_to_user(argp, &status, sizeof(int)))
return -EFAULT;
break;
+ case LPSETTIMEOUT:
+ /*
+ * For 64bit application or 32bit application with 64bit
+ * time_t
+ */
+ if ((IS_ENABLED(CONFIG_64BIT) && !is_compat_task())
+ || COMPAT_USE_64BIT_TIME) {
+ if (copy_from_user(time64, argp,
+ sizeof(time64)))
+ return -EFAULT;
+
+ return lp_set_timeout(minor, time64[0],
+ time64[1]);
+ } else {
+ if (copy_from_user(time32, argp,
+ sizeof(time32)))
+ return -EFAULT;
+
+ return lp_set_timeout(minor, time32[0],
+ time32[1]);
+ }
+ break;
default:
retval = -EINVAL;
}
return retval;
}
-static int lp_set_timeout(unsigned int minor, struct timeval *par_timeout)
-{
- long to_jiffies;
-
- /* Convert to jiffies, place in lp_table */
- if ((par_timeout->tv_sec < 0) ||
- (par_timeout->tv_usec < 0)) {
- return -EINVAL;
- }
- to_jiffies = DIV_ROUND_UP(par_timeout->tv_usec, 1000000/HZ);
- to_jiffies += par_timeout->tv_sec * (long) HZ;
- if (to_jiffies <= 0) {
- return -EINVAL;
- }
- lp_table[minor].timeout = to_jiffies;
- return 0;
-}
-
static long lp_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
unsigned int minor;
- struct timeval par_timeout;
int ret;
minor = iminor(file_inode(file));
mutex_lock(&lp_mutex);
- switch (cmd) {
- case LPSETTIMEOUT:
- if (copy_from_user(&par_timeout, (void __user *)arg,
- sizeof (struct timeval))) {
- ret = -EFAULT;
- break;
- }
- ret = lp_set_timeout(minor, &par_timeout);
- break;
- default:
- ret = lp_do_ioctl(minor, cmd, arg, (void __user *)arg);
- break;
- }
+ ret = lp_do_ioctl(minor, cmd, arg, (void __user *)arg);
mutex_unlock(&lp_mutex);
return ret;
@@ -709,19 +727,11 @@ static long lp_compat_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
unsigned int minor;
- struct timeval par_timeout;
int ret;
minor = iminor(file_inode(file));
mutex_lock(&lp_mutex);
switch (cmd) {
- case LPSETTIMEOUT:
- if (compat_get_timeval(&par_timeout, compat_ptr(arg))) {
- ret = -EFAULT;
- break;
- }
- ret = lp_set_timeout(minor, &par_timeout);
- break;
#ifdef LP_STATS
case LPGETSTATS:
/* FIXME: add an implementation if you set LP_STATS */
--
2.1.4
From: Shraddha Barke <shraddha.6596(a)gmail.com>
32-bit systems using 'struct timeval' will break in the year 2038,
in order to avoid that replace the code with more appropriate types.
This patch replaces the use of struct timeval and do_gettimeofday()
with ktime_get_real_seconds() which returns a 64 bit seconds value.
Real time is used since if monotonic time is used we would get
duplicate timestamps after reboot as monotonic time starts from
zero on every reboot.
Signed-off-by: Shraddha Barke <shraddha.6596(a)gmail.com>
---
Changes in v2-
Used real time and updated commit message.
drivers/block/sx8.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index 59c91d4..1ec9fd2 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -23,7 +23,7 @@
#include <linux/workqueue.h>
#include <linux/bitops.h>
#include <linux/delay.h>
-#include <linux/time.h>
+#include <linux/ktime.h>
#include <linux/hdreg.h>
#include <linux/dma-mapping.h>
#include <linux/completion.h>
@@ -671,17 +671,17 @@ static int carm_send_special (struct carm_host *host, carm_sspc_t func)
static unsigned int carm_fill_sync_time(struct carm_host *host,
unsigned int idx, void *mem)
{
- struct timeval tv;
struct carm_msg_sync_time *st = mem;
- do_gettimeofday(&tv);
+ time64_t kt = ktime_get_real_seconds();
memset(st, 0, sizeof(*st));
st->type = CARM_MSG_MISC;
st->subtype = MISC_SET_TIME;
st->handle = cpu_to_le32(TAG_ENCODE(idx));
- st->timestamp = cpu_to_le32(tv.tv_sec);
+ st->timestamp = cpu_to_le32(kt);
+ /* This driver will break in 2106 */
return sizeof(struct carm_msg_sync_time);
}
--
2.1.4
A new fax document for you.
To view it please open the attachment.
Scanned at: Wed, 23 Dec 2015 10:26:50 +0300
Scanned by: Ernest Hoover
Filesize: 116 Kb
Pages: 12
Quality: 400 DPI
File name: fax_00325060.doc
Processed in: 50 seconds
Thanks for choosing Interfax!
You have a new fax!
Please, download fax document attached to this email.
Pages sent: 4
Scanned: Tue, 22 Dec 2015 12:17:43 +0300
Processed in: 44 seconds
Resolution: 600 DPI
Fax name: scanned_00284615.doc
Author: Felix Singer
Filesize: 300 Kb
Thank you for using Interfax!
32-bit systems using 'struct timeval' will break in the year 2038,
in order to avoid that replace the code with more appropriate types.
This patch replaces timeval with 64 bit ktime_t which is y2038 safe.
Since st->timestamp is only interested in seconds, directly using
time64_t here. Function ktime_get_seconds is used since it uses
monotonic instead of real time and thus will not cause overflow.
Signed-off-by: Shraddha Barke <shraddha.6596(a)gmail.com>
---
drivers/block/sx8.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c
index 59c91d4..baadb77 100644
--- a/drivers/block/sx8.c
+++ b/drivers/block/sx8.c
@@ -23,7 +23,7 @@
#include <linux/workqueue.h>
#include <linux/bitops.h>
#include <linux/delay.h>
-#include <linux/time.h>
+#include <linux/ktime.h>
#include <linux/hdreg.h>
#include <linux/dma-mapping.h>
#include <linux/completion.h>
@@ -671,16 +671,15 @@ static int carm_send_special (struct carm_host *host, carm_sspc_t func)
static unsigned int carm_fill_sync_time(struct carm_host *host,
unsigned int idx, void *mem)
{
- struct timeval tv;
struct carm_msg_sync_time *st = mem;
- do_gettimeofday(&tv);
+ time64_t tv = ktime_get_seconds();
memset(st, 0, sizeof(*st));
st->type = CARM_MSG_MISC;
st->subtype = MISC_SET_TIME;
st->handle = cpu_to_le32(TAG_ENCODE(idx));
- st->timestamp = cpu_to_le32(tv.tv_sec);
+ st->timestamp = cpu_to_le32(tv);
return sizeof(struct carm_msg_sync_time);
}
--
2.1.4
From: Shraddha Barke <shraddha.6596(a)gmail.com>
32-bit systems using 'struct timeval' will break in the year 2038,
in order to avoid that the code should be replaced with appropriate
types. This patch replaces timeval with 64-bit ktime_t which is y2038
safe. Here, time64_t is used directly since mlc->lcv_t is interested
only in seconds.
Signed-off-by: Shraddha Barke <shraddha.6596(a)gmail.com>
---
drivers/input/serio/hil_mlc.c | 8 +++-----
include/linux/hil_mlc.h | 2 +-
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/input/serio/hil_mlc.c b/drivers/input/serio/hil_mlc.c
index 65605e4..fb297aa 100644
--- a/drivers/input/serio/hil_mlc.c
+++ b/drivers/input/serio/hil_mlc.c
@@ -274,14 +274,12 @@ static int hilse_match(hil_mlc *mlc, int unused)
/* An LCV used to prevent runaway loops, forces 5 second sleep when reset. */
static int hilse_init_lcv(hil_mlc *mlc, int unused)
{
- struct timeval tv;
+ time64_t now = ktime_get_seconds();
- do_gettimeofday(&tv);
-
- if (mlc->lcv && (tv.tv_sec - mlc->lcv_tv.tv_sec) < 5)
+ if (mlc->lcv && (now - mlc->lcv_t) < 5)
return -1;
- mlc->lcv_tv = tv;
+ mlc->lcv_t = now;
mlc->lcv = 0;
return 0;
diff --git a/include/linux/hil_mlc.h b/include/linux/hil_mlc.h
index 394a840..29bb5e3 100644
--- a/include/linux/hil_mlc.h
+++ b/include/linux/hil_mlc.h
@@ -149,7 +149,7 @@ struct hil_mlc {
int ddi; /* Last operational device id */
int lcv; /* LCV to throttle loops */
- struct timeval lcv_tv; /* Time loop was started */
+ time64_t lcv_t; /* Time loop was started */
int di_map[7]; /* Maps below items to live devs */
struct hil_mlc_devinfo di[HIL_MLC_DEVMEM];
--
2.1.4
The first two patches contain the basic framework for the 64 bit time migration
for filesystems.
The next two patches shows how the framework has been adapted to vfs layer and
cifs filesystem.
There might be some minor changes or additions required as I start adapting to
other filesystems.
The change to timestamp conversion functions(to and from unix format to others)
and range checks will be part of a separate series.
Changes since v1:
* move SYSTEM_TIME macros to fs.h
* add 64 bit version of CURRENT_TIME macros.
Deepa Dinamani (4):
vfs: Add 64 bit time support
kernel: time: Add macros and functions to support 64 bit time
vfs: Add support for vfs code to use 64 bit time.
fs: cifs: Add support for cifs to use 64 bit time
fs/attr.c | 14 ++++-----
fs/bad_inode.c | 9 ++++--
fs/binfmt_misc.c | 7 +++--
fs/cifs/cache.c | 16 ++++++----
fs/cifs/cifsencrypt.c | 2 +-
fs/cifs/cifsglob.h | 6 ++--
fs/cifs/cifsproto.h | 7 +++--
fs/cifs/cifssmb.c | 9 ++++--
fs/cifs/file.c | 9 ++++--
fs/cifs/inode.c | 68 +++++++++++++++++++++++++---------------
fs/cifs/netmisc.c | 10 +++---
fs/inode.c | 44 ++++++++++++++++----------
fs/libfs.c | 58 +++++++++++++++++++++++++---------
fs/locks.c | 5 ++-
fs/nsfs.c | 6 +++-
fs/pipe.c | 6 +++-
fs/posix_acl.c | 2 +-
fs/stat.c | 6 ++--
fs/utimes.c | 4 +--
include/linux/fs.h | 85 +++++++++++++++++++++++++++++++++++++++++++-------
include/linux/stat.h | 6 ++--
include/linux/time64.h | 39 +++++++++++++++++++++++
kernel/time/time.c | 65 +++++++++++++++++++++++++++++++++++++-
23 files changed, 366 insertions(+), 117 deletions(-)
--
1.9.1