These series of patches try to convert parport device(ppdev) to
y2038 safe, and support y2038 safe and unsafe application at the
same time. The first two version is here[1][2][3].
An y2038 safe application/kernel use 64bit time_t(aka time64_t)
to avoid 32-bit time types broken in the year 2038. Given that
some time relative struct(e.g. timeval in ppdev.c) is mainly the
offset of the real time, the old 32bit time_t in such application
is safe. We need to handle the 32bit time_t and 64bit time_t
application at the same time. My approach here is handle them as
different ioctl command for different size of timeval.
Build successful on arm64, arm and x86_64 with C=1.
Changes since v3:
1. Remove the useless compat ioctl in fs/compat_ioctl.c for
parport device.
Changes since v2:
1. Fix the wrong parameter in copy_to_user.
Changes since v1:
1. Fix the warning when build against x86_64.
[1] https://lkml.org/lkml/2015/12/9/32
[2] https://lkml.org/lkml/2015/12/17/111
[3] http://www.spinics.net/lists/y2038/msg01059.html
Bamvor Jian Zhang (3):
ppdev: convert to y2038 safe
ppdev: add support for compat ioctl
fs/compat: remove useless compat ioctl for parport device
drivers/char/ppdev.c | 87 ++++++++++++++++++++++++++++++++++++++++------------
fs/compat_ioctl.c | 22 -------------
2 files changed, 67 insertions(+), 42 deletions(-)
--
2.1.4
These series of patches try to convert parport device(ppdev) to
y2038 safe, and support y2038 safe and unsafe application at the
same time. The first version is here[1].
An y2038 safe application/kernel use 64bit time_t(aka time64_t)
to avoid 32-bit time types broken in the year 2038. Given that
some time relative struct(e.g. timeval in ppdev.c) is mainly the
offset of the real time, the old 32bit time_t in such application
is safe. We need to handle the 32bit time_t and 64bit time_t
application at the same time. My approach here is handle them as
different ioctl command for different size of timeval.
Build successful on arm64, arm and x86_64.
Changes since v1:
1. Fix the warning when build against x86_64.
[1] https://lkml.org/lkml/2015/12/9/32
Bamvor Jian Zhang (2):
ppdev: convert to y2038 safe
ppdev: add support for compat ioctl
drivers/char/ppdev.c | 87 ++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 67 insertions(+), 20 deletions(-)
--
2.1.4
On Thu, Jan 07, 2016 at 09:50:30AM +0100, Michael Adam wrote:
> Hi,
>
> the patch contains a conflict resolution artifact..
>
Thanks, I've fixed it in my tree now.
I will wait to hear other comments before I send an update.
-Deepa
These series of patches try to convert parport device(ppdev) to
y2038 safe, and support y2038 safe and unsafe application at the
same time. The first two version is here[1][2].
An y2038 safe application/kernel use 64bit time_t(aka time64_t)
to avoid 32-bit time types broken in the year 2038. Given that
some time relative struct(e.g. timeval in ppdev.c) is mainly the
offset of the real time, the old 32bit time_t in such application
is safe. We need to handle the 32bit time_t and 64bit time_t
application at the same time. My approach here is handle them as
different ioctl command for different size of timeval.
Build successful on arm64, arm and x86_64.
Changes since v2:
1. Fix the wrong parameter in copy_to_user.
Changes since v1:
1. Fix the warning when build against x86_64.
[1] https://lkml.org/lkml/2015/12/9/32
[2] https://lkml.org/lkml/2015/12/17/111
Bamvor Jian Zhang (2):
ppdev: convert to y2038 safe
ppdev: add support for compat ioctl
drivers/char/ppdev.c | 87 ++++++++++++++++++++++++++++++++++++++++------------
1 file changed, 67 insertions(+), 20 deletions(-)
--
2.1.4
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