Re: [Y2038] [PATCH v2 24/24] y2038: sparc: remove use of struct timex
Hi Arnd, On Sat, Dec 14, 2019 at 7:59 AM Arnd Bergmann wrote: > > 'struct timex' is one of the last users of 'struct timeval' and is > only referenced in one place in the kernel any more, to convert the > user space timex into the kernel-internal version on sparc64, with a > different tv_usec member type. > > As a preparation for hiding the time_t definition and everything > using that in the kernel, change the implementation once more > to only convert the timeval member, and then enclose the > struct definition in an #ifdef. > > Signed-off-by: Arnd Bergmann > --- > arch/sparc/kernel/sys_sparc_64.c | 29 +++-- > include/uapi/linux/timex.h | 2 ++ > 2 files changed, 17 insertions(+), 14 deletions(-) > > diff --git a/arch/sparc/kernel/sys_sparc_64.c > b/arch/sparc/kernel/sys_sparc_64.c > index 9f41a6f5a032..1c85b0af4dfd 100644 > --- a/arch/sparc/kernel/sys_sparc_64.c > +++ b/arch/sparc/kernel/sys_sparc_64.c > @@ -548,34 +548,35 @@ SYSCALL_DEFINE2(getdomainname, char __user *, name, > int, len) > return err; > } > > -SYSCALL_DEFINE1(sparc_adjtimex, struct timex __user *, txc_p) > +SYSCALL_DEFINE1(sparc_adjtimex, struct __kernel_timex __user *, txc_p) > { > - struct timex txc; /* Local copy of parameter */ > - struct __kernel_timex *kt = (void *) > + struct __kernel_timex txc; > + __kernel_old_timeval *tv = (void *)>time; > int ret; > > /* Copy the user data space into the kernel copy > * structure. But bear in mind that the structures > * may change > */ > - if (copy_from_user(, txc_p, sizeof(struct timex))) > + if (copy_from_user(, txc_p, sizeof(txc))) > return -EFAULT; > > /* > * override for sparc64 specific timeval type: tv_usec > * is 32 bit wide instead of 64-bit in __kernel_timex > */ > - kt->time.tv_usec = txc.time.tv_usec; > + kt->time.tv_usec = tv->tv_usec; Am I mis-reading the patch, or is "kt" not defined? Thanks, -- Julian Calaby Email: julian.cal...@gmail.com Profile: http://www.google.com/profiles/julian.calaby/ ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [PATCH v2 01/24] Input: input_event: fix struct padding on sparc64
On Fri, Dec 13, 2019 at 09:49:10PM +0100, Arnd Bergmann wrote: > Going through all uses of timeval, I noticed that we screwed up > input_event in the previous attempts to fix it: > > The time fields now match between kernel and user space, but > all following fields are in the wrong place. > > Add the required padding that is implied by the glibc timeval > definition to fix the layout, and use a struct initializer > to avoid leaking kernel stack data. > > Cc: sparcli...@vger.kernel.org > Cc: "David S. Miller" > Fixes: 141e5dcaa735 ("Input: input_event - fix the CONFIG_SPARC64 mixup") > Fixes: 2e746942ebac ("Input: input_event - provide override for sparc64") > Signed-off-by: Arnd Bergmann Applied, thank you. > --- > drivers/input/evdev.c | 14 +++--- > drivers/input/misc/uinput.c | 14 +- > include/uapi/linux/input.h | 1 + > 3 files changed, 17 insertions(+), 12 deletions(-) > > diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c > index d7dd6fcf2db0..f918fca9ada3 100644 > --- a/drivers/input/evdev.c > +++ b/drivers/input/evdev.c > @@ -224,13 +224,13 @@ static void __pass_event(struct evdev_client *client, >*/ > client->tail = (client->head - 2) & (client->bufsize - 1); > > - client->buffer[client->tail].input_event_sec = > - event->input_event_sec; > - client->buffer[client->tail].input_event_usec = > - event->input_event_usec; > - client->buffer[client->tail].type = EV_SYN; > - client->buffer[client->tail].code = SYN_DROPPED; > - client->buffer[client->tail].value = 0; > + client->buffer[client->tail] = (struct input_event) { > + .input_event_sec = event->input_event_sec, > + .input_event_usec = event->input_event_usec, > + .type = EV_SYN, > + .code = SYN_DROPPED, > + .value = 0, > + }; > > client->packet_head = client->tail; > } > diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c > index fd253781be71..2dabbe47d43e 100644 > --- a/drivers/input/misc/uinput.c > +++ b/drivers/input/misc/uinput.c > @@ -74,12 +74,16 @@ static int uinput_dev_event(struct input_dev *dev, > struct uinput_device*udev = input_get_drvdata(dev); > struct timespec64 ts; > > - udev->buff[udev->head].type = type; > - udev->buff[udev->head].code = code; > - udev->buff[udev->head].value = value; > ktime_get_ts64(); > - udev->buff[udev->head].input_event_sec = ts.tv_sec; > - udev->buff[udev->head].input_event_usec = ts.tv_nsec / NSEC_PER_USEC; > + > + udev->buff[udev->head] = (struct input_event) { > + .input_event_sec = ts.tv_sec, > + .input_event_usec = ts.tv_nsec / NSEC_PER_USEC, > + .type = type, > + .code = code, > + .value = value, > + }; > + > udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE; > > wake_up_interruptible(>waitq); > diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h > index f056b2a00d5c..9a61c28ed3ae 100644 > --- a/include/uapi/linux/input.h > +++ b/include/uapi/linux/input.h > @@ -34,6 +34,7 @@ struct input_event { > __kernel_ulong_t __sec; > #if defined(__sparc__) && defined(__arch64__) > unsigned int __usec; > + unsigned int __pad; > #else > __kernel_ulong_t __usec; > #endif > -- > 2.20.0 > -- Dmitry ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [PATCH v2 10/12] nfsd: use boottime for lease expiry alculation
On Fri, Dec 13, 2019 at 10:13 PM Bruce Fields wrote: > On Fri, Dec 13, 2019 at 01:23:08PM -0500, Chuck Lever wrote: > > > On Dec 13, 2019, at 11:40 AM, Arnd Bergmann wrote: > > > On Fri, Dec 13, 2019 at 5:26 PM Chuck Lever > > > wrote: > > >>> + > > >>> + /* nfsd4_lease is set to at most one hour */ > > >>> + if (WARN_ON_ONCE(nn->nfsd4_lease > 3600)) > > >>> + return 360 * HZ; > > >> > > >> Why is the WARN_ON_ONCE added here? Is it really necessary? > > > > > > This is to ensure the kernel doesn't change to a larger limit that > > > requires a 64-bit division on a 32-bit architecture. > > > > > > With the old code, dividing by 10 was always fast as > > > nn->nfsd4_lease was the size of an integer register. Now it > > > is 64 bit wide, and I check that truncating it to 32 bit again > > > is safe. > > > > OK. That comment should state this reason rather than just repeating > > what the code does. ;-) > > Note that __nfsd4_write_time() already limits nfsd4_lease to 3600. > > We could just use a smaller type for nfsd4_lease if that'd help. I think it's generally clearer to have only one type to store the lease time, and time64_t is the most sensible one, even if the range is a bit excessive. I've seen too many time related bugs from mixing integer types incorrectly. Arnd ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [PATCH v2 19/24] xfs: rename compat_time_t to old_time32_t
On Fri, Dec 13, 2019 at 09:53:47PM +0100, Arnd Bergmann wrote: > The compat_time_t type has been removed everywhere else, > as most users rely on old_time32_t for both native and > compat mode handling of 32-bit time_t. > > Remove the last one in xfs. > > Signed-off-by: Arnd Bergmann Looks fine to me, assuming that compat_time_t -> old_time32_t. Reviewed-by: Darrick J. Wong --D > --- > fs/xfs/xfs_ioctl32.c | 2 +- > fs/xfs/xfs_ioctl32.h | 2 +- > 2 files changed, 2 insertions(+), 2 deletions(-) > > diff --git a/fs/xfs/xfs_ioctl32.c b/fs/xfs/xfs_ioctl32.c > index c4c4f09113d3..a49bd80b2c3b 100644 > --- a/fs/xfs/xfs_ioctl32.c > +++ b/fs/xfs/xfs_ioctl32.c > @@ -107,7 +107,7 @@ xfs_ioctl32_bstime_copyin( > xfs_bstime_t*bstime, > compat_xfs_bstime_t __user *bstime32) > { > - compat_time_t sec32; /* tv_sec differs on 64 vs. 32 */ > + old_time32_tsec32; /* tv_sec differs on 64 vs. 32 */ > > if (get_user(sec32, >tv_sec) || > get_user(bstime->tv_nsec, >tv_nsec)) > diff --git a/fs/xfs/xfs_ioctl32.h b/fs/xfs/xfs_ioctl32.h > index 8c7743cd490e..053de7d894cd 100644 > --- a/fs/xfs/xfs_ioctl32.h > +++ b/fs/xfs/xfs_ioctl32.h > @@ -32,7 +32,7 @@ > #endif > > typedef struct compat_xfs_bstime { > - compat_time_t tv_sec; /* seconds */ > + old_time32_ttv_sec; /* seconds */ > __s32 tv_nsec;/* and nanoseconds */ > } compat_xfs_bstime_t; > > -- > 2.20.0 > ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [PATCH v2 21/24] xfs: quota: move to time64_t interfaces
On Fri, Dec 13, 2019 at 09:53:49PM +0100, Arnd Bergmann wrote: > As a preparation for removing the 32-bit time_t type and > all associated interfaces, change xfs to use time64_t and > ktime_get_real_seconds() for the quota housekeeping. > > Signed-off-by: Arnd Bergmann Looks mostly reasonable to me... The bigtime series refactors the triplicated timer handling and whatnot, but I don't think it would be difficult to rebase that series assuming this lands first (which it probably will, I expect a new incompat ondisk feature to take a /long/ time to get through review.) > --- > fs/xfs/xfs_dquot.c | 6 +++--- > fs/xfs/xfs_qm.h | 6 +++--- > fs/xfs/xfs_quotaops.c| 6 +++--- > fs/xfs/xfs_trans_dquot.c | 8 +--- > 4 files changed, 14 insertions(+), 12 deletions(-) > > diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c > index 2bff21ca9d78..9cfd3209f52b 100644 > --- a/fs/xfs/xfs_dquot.c > +++ b/fs/xfs/xfs_dquot.c > @@ -137,7 +137,7 @@ xfs_qm_adjust_dqtimers( > (d->d_blk_hardlimit && >(be64_to_cpu(d->d_bcount) > > be64_to_cpu(d->d_blk_hardlimit { > - d->d_btimer = cpu_to_be32(get_seconds() + > + d->d_btimer = cpu_to_be32(ktime_get_real_seconds() + > mp->m_quotainfo->qi_btimelimit); > } else { > d->d_bwarns = 0; > @@ -160,7 +160,7 @@ xfs_qm_adjust_dqtimers( > (d->d_ino_hardlimit && >(be64_to_cpu(d->d_icount) > > be64_to_cpu(d->d_ino_hardlimit { > - d->d_itimer = cpu_to_be32(get_seconds() + > + d->d_itimer = cpu_to_be32(ktime_get_real_seconds() + > mp->m_quotainfo->qi_itimelimit); > } else { > d->d_iwarns = 0; > @@ -183,7 +183,7 @@ xfs_qm_adjust_dqtimers( > (d->d_rtb_hardlimit && >(be64_to_cpu(d->d_rtbcount) > > be64_to_cpu(d->d_rtb_hardlimit { > - d->d_rtbtimer = cpu_to_be32(get_seconds() + > + d->d_rtbtimer = cpu_to_be32(ktime_get_real_seconds() + > mp->m_quotainfo->qi_rtbtimelimit); Hmm, so one thing that I clean up on the way to bigtime is the total lack of clamping here. If (for example) it's September 2105 and rtbtimelimit is set to 1 year, this will cause an integer overflow. The quota timer will be set to 1970 and expire immediately, rather than what I'd consider the best effort of February 2106. (I'll grant you the current code also behaves like this...) Reviewed-by: Darrick J. Wong --D > } else { > d->d_rtbwarns = 0; > diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h > index 7823af39008b..4e57edca8bce 100644 > --- a/fs/xfs/xfs_qm.h > +++ b/fs/xfs/xfs_qm.h > @@ -64,9 +64,9 @@ struct xfs_quotainfo { > struct xfs_inode*qi_pquotaip; /* project quota inode */ > struct list_lru qi_lru; > int qi_dquots; > - time_t qi_btimelimit; /* limit for blks timer */ > - time_t qi_itimelimit; /* limit for inodes timer */ > - time_t qi_rtbtimelimit;/* limit for rt blks timer */ > + time64_t qi_btimelimit; /* limit for blks timer */ > + time64_t qi_itimelimit; /* limit for inodes timer */ > + time64_t qi_rtbtimelimit;/* limit for rt blks timer */ > xfs_qwarncnt_t qi_bwarnlimit; /* limit for blks warnings */ > xfs_qwarncnt_t qi_iwarnlimit; /* limit for inodes warnings */ > xfs_qwarncnt_t qi_rtbwarnlimit;/* limit for rt blks warnings */ > diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c > index c7de17deeae6..38669e827206 100644 > --- a/fs/xfs/xfs_quotaops.c > +++ b/fs/xfs/xfs_quotaops.c > @@ -37,9 +37,9 @@ xfs_qm_fill_state( > tstate->flags |= QCI_SYSFILE; > tstate->blocks = ip->i_d.di_nblocks; > tstate->nextents = ip->i_d.di_nextents; > - tstate->spc_timelimit = q->qi_btimelimit; > - tstate->ino_timelimit = q->qi_itimelimit; > - tstate->rt_spc_timelimit = q->qi_rtbtimelimit; > + tstate->spc_timelimit = (u32)q->qi_btimelimit; > + tstate->ino_timelimit = (u32)q->qi_itimelimit; > + tstate->rt_spc_timelimit = (u32)q->qi_rtbtimelimit; > tstate->spc_warnlimit = q->qi_bwarnlimit; > tstate->ino_warnlimit = q->qi_iwarnlimit; > tstate->rt_spc_warnlimit = q->qi_rtbwarnlimit; > diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c > index a6fe2d8dc40f..d1b9869bc5fa 100644 > --- a/fs/xfs/xfs_trans_dquot.c > +++ b/fs/xfs/xfs_trans_dquot.c > @@ -580,7 +580,7 @@ xfs_trans_dqresv( > { > xfs_qcnt_t hardlimit; > xfs_qcnt_t softlimit; > - time_t timer; > + time64_ttimer; >
Re: [Y2038] [PATCH v2 10/12] nfsd: use boottime for lease expiry alculation
On Fri, Dec 13, 2019 at 01:23:08PM -0500, Chuck Lever wrote: > > > > On Dec 13, 2019, at 11:40 AM, Arnd Bergmann wrote: > > > > On Fri, Dec 13, 2019 at 5:26 PM Chuck Lever wrote: > >>> On Dec 13, 2019, at 9:10 AM, Arnd Bergmann wrote: > > > >>> diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c > >>> index 24534db87e86..508d7c6c00b5 100644 > >>> --- a/fs/nfsd/nfs4callback.c > >>> +++ b/fs/nfsd/nfs4callback.c > >>> @@ -823,7 +823,12 @@ static const struct rpc_program cb_program = { > >>> static int max_cb_time(struct net *net) > >>> { > >>> struct nfsd_net *nn = net_generic(net, nfsd_net_id); > >>> - return max(nn->nfsd4_lease/10, (time_t)1) * HZ; > >>> + > >>> + /* nfsd4_lease is set to at most one hour */ > >>> + if (WARN_ON_ONCE(nn->nfsd4_lease > 3600)) > >>> + return 360 * HZ; > >> > >> Why is the WARN_ON_ONCE added here? Is it really necessary? > > > > This is to ensure the kernel doesn't change to a larger limit that > > requires a 64-bit division on a 32-bit architecture. > > > > With the old code, dividing by 10 was always fast as > > nn->nfsd4_lease was the size of an integer register. Now it > > is 64 bit wide, and I check that truncating it to 32 bit again > > is safe. > > OK. That comment should state this reason rather than just repeating > what the code does. ;-) Note that __nfsd4_write_time() already limits nfsd4_lease to 3600. We could just use a smaller type for nfsd4_lease if that'd help. --b. ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [PATCH v2 10/12] nfsd: use boottime for lease expiry alculation
On Fri, Dec 13, 2019 at 7:23 PM Chuck Lever wrote: > > On Dec 13, 2019, at 11:40 AM, Arnd Bergmann wrote: > > > > On Fri, Dec 13, 2019 at 5:26 PM Chuck Lever wrote: > >>> On Dec 13, 2019, at 9:10 AM, Arnd Bergmann wrote: > > > >>> diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c > >>> index 24534db87e86..508d7c6c00b5 100644 > > > > With the old code, dividing by 10 was always fast as > > nn->nfsd4_lease was the size of an integer register. Now it > > is 64 bit wide, and I check that truncating it to 32 bit again > > is safe. > > OK. That comment should state this reason rather than just repeating > what the code does. ;-) I changed the comment now to: + /* +* nfsd4_lease is set to at most one hour in __nfsd4_write_time, +* so we can use 32-bit math on it. Warn if that assumption +* ever stops being true. +*/ Modified branch pushed to git://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground.git y2038-nfsd-v2 Arnd ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [PATCH v2 20/24] xfs: disallow broken ioctls without compat-32-bit-time
On Fri, Dec 13, 2019 at 09:53:48PM +0100, Arnd Bergmann wrote: > When building a kernel that disables support for 32-bit time_t > system calls, it also makes sense to disable the old xfs_bstat > ioctls completely, as they truncate the timestamps to 32-bit > values. Note that current xfs doesn't support > 32-bit timestamps at all, so for now the old bulkstat/swapext ioctls will never overflow. Granted, I melded everyone's suggestions into a more fully formed 'bigtime' feature patchset that I'll dump out soon as part of my usual end of year carpetbombing of the mailing list, so we likely still need most of this patch anyway... > Any application using these needs to be updated to use the v5 > interfaces. > > Signed-off-by: Arnd Bergmann > --- > fs/xfs/xfs_ioctl.c | 26 ++ > 1 file changed, 26 insertions(+) > > diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c > index 7b35d62ede9f..a4a4eed8879c 100644 > --- a/fs/xfs/xfs_ioctl.c > +++ b/fs/xfs/xfs_ioctl.c > @@ -36,6 +36,7 @@ > #include "xfs_reflink.h" > #include "xfs_ioctl.h" > > +#include > #include > #include > > @@ -617,6 +618,23 @@ xfs_fsinumbers_fmt( > return xfs_ibulk_advance(breq, sizeof(struct xfs_inogrp)); > } > > +/* disallow y2038-unsafe ioctls with CONFIG_COMPAT_32BIT_TIME=n */ > +static bool xfs_have_compat_bstat_time32(unsigned int cmd) The v5 bulkstat ioctls follow an entirely separate path through xfs_ioctl.c, so I think you don't need the @cmd parameter. > +{ > + if (IS_ENABLED(CONFIG_COMPAT_32BIT_TIME)) > + return true; > + > + if (IS_ENABLED(CONFIG_64BIT) && !in_compat_syscall()) > + return true; > + > + if (cmd == XFS_IOC_FSBULKSTAT_SINGLE || > + cmd == XFS_IOC_FSBULKSTAT || > + cmd == XFS_IOC_SWAPEXT) > + return false; > + > + return true; > +} > + > STATIC int > xfs_ioc_fsbulkstat( > xfs_mount_t *mp, > @@ -637,6 +655,9 @@ xfs_ioc_fsbulkstat( > if (!capable(CAP_SYS_ADMIN)) > return -EPERM; > > + if (!xfs_have_compat_bstat_time32(cmd)) > + return -EINVAL; > + > if (XFS_FORCED_SHUTDOWN(mp)) > return -EIO; > > @@ -1815,6 +1836,11 @@ xfs_ioc_swapext( > struct fd f, tmp; > int error = 0; > > + if (xfs_have_compat_bstat_time32(XFS_IOC_SWAPEXT)) { if (!xfs_have...()) ? --D > + error = -EINVAL; > + goto out; > + } > + > /* Pull information for the target fd */ > f = fdget((int)sxp->sx_fdtarget); > if (!f.file) { > -- > 2.20.0 > ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 24/24] y2038: sparc: remove use of struct timex
'struct timex' is one of the last users of 'struct timeval' and is only referenced in one place in the kernel any more, to convert the user space timex into the kernel-internal version on sparc64, with a different tv_usec member type. As a preparation for hiding the time_t definition and everything using that in the kernel, change the implementation once more to only convert the timeval member, and then enclose the struct definition in an #ifdef. Signed-off-by: Arnd Bergmann --- arch/sparc/kernel/sys_sparc_64.c | 29 +++-- include/uapi/linux/timex.h | 2 ++ 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/arch/sparc/kernel/sys_sparc_64.c b/arch/sparc/kernel/sys_sparc_64.c index 9f41a6f5a032..1c85b0af4dfd 100644 --- a/arch/sparc/kernel/sys_sparc_64.c +++ b/arch/sparc/kernel/sys_sparc_64.c @@ -548,34 +548,35 @@ SYSCALL_DEFINE2(getdomainname, char __user *, name, int, len) return err; } -SYSCALL_DEFINE1(sparc_adjtimex, struct timex __user *, txc_p) +SYSCALL_DEFINE1(sparc_adjtimex, struct __kernel_timex __user *, txc_p) { - struct timex txc; /* Local copy of parameter */ - struct __kernel_timex *kt = (void *) + struct __kernel_timex txc; + __kernel_old_timeval *tv = (void *)>time; int ret; /* Copy the user data space into the kernel copy * structure. But bear in mind that the structures * may change */ - if (copy_from_user(, txc_p, sizeof(struct timex))) + if (copy_from_user(, txc_p, sizeof(txc))) return -EFAULT; /* * override for sparc64 specific timeval type: tv_usec * is 32 bit wide instead of 64-bit in __kernel_timex */ - kt->time.tv_usec = txc.time.tv_usec; + kt->time.tv_usec = tv->tv_usec; ret = do_adjtimex(kt); - txc.time.tv_usec = kt->time.tv_usec; + tv->tv_usec = kt->time.tv_usec; - return copy_to_user(txc_p, , sizeof(struct timex)) ? -EFAULT : ret; + return copy_to_user(txc_p, , sizeof(txc)) ? -EFAULT : ret; } -SYSCALL_DEFINE2(sparc_clock_adjtime, const clockid_t, which_clock,struct timex __user *, txc_p) +SYSCALL_DEFINE2(sparc_clock_adjtime, const clockid_t, which_clock, + struct __kernel_timex __user *, txc_p) { - struct timex txc; /* Local copy of parameter */ - struct __kernel_timex *kt = (void *) + struct __kernel_timex txc; + __kernel_old_timeval *tv = (void *)>time; int ret; if (!IS_ENABLED(CONFIG_POSIX_TIMERS)) { @@ -590,18 +591,18 @@ SYSCALL_DEFINE2(sparc_clock_adjtime, const clockid_t, which_clock,struct timex _ * structure. But bear in mind that the structures * may change */ - if (copy_from_user(, txc_p, sizeof(struct timex))) + if (copy_from_user(, txc_p, sizeof(txc))) return -EFAULT; /* * override for sparc64 specific timeval type: tv_usec * is 32 bit wide instead of 64-bit in __kernel_timex */ - kt->time.tv_usec = txc.time.tv_usec; + kt->time.tv_usec = tv->tv_usec; ret = do_clock_adjtime(which_clock, kt); - txc.time.tv_usec = kt->time.tv_usec; + tv->tv_usec = kt->time.tv_usec; - return copy_to_user(txc_p, , sizeof(struct timex)) ? -EFAULT : ret; + return copy_to_user(txc_p, , sizeof(txc)) ? -EFAULT : ret; } SYSCALL_DEFINE5(utrap_install, utrap_entry_t, type, diff --git a/include/uapi/linux/timex.h b/include/uapi/linux/timex.h index 9f517f9010bb..bd627c368d09 100644 --- a/include/uapi/linux/timex.h +++ b/include/uapi/linux/timex.h @@ -57,6 +57,7 @@ #define NTP_API4 /* NTP API version */ +#ifndef __KERNEL__ /* * syscall interface - used (mainly by NTP daemon) * to discipline kernel clock oscillator @@ -91,6 +92,7 @@ struct timex { int :32; int :32; int :32; int :32; int :32; int :32; int :32; }; +#endif struct __kernel_timex_timeval { __kernel_time64_t tv_sec; -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 23/24] y2038: rename itimerval to __kernel_old_itimerval
Take the renaming of timeval and timespec one level further, also renaming itimerval to __kernel_old_itimerval, to avoid namespace conflicts with the user-space structure that may use 64-bit time_t members. Signed-off-by: Arnd Bergmann --- include/linux/syscalls.h| 9 - include/uapi/linux/time_types.h | 5 + kernel/time/itimer.c| 18 +- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index d0391cc2dae9..27245fec2a8a 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -16,8 +16,7 @@ struct inode; struct iocb; struct io_event; struct iovec; -struct itimerspec; -struct itimerval; +struct __kernel_old_itimerval; struct kexec_segment; struct linux_dirent; struct linux_dirent64; @@ -591,10 +590,10 @@ asmlinkage long sys_nanosleep_time32(struct old_timespec32 __user *rqtp, struct old_timespec32 __user *rmtp); /* kernel/itimer.c */ -asmlinkage long sys_getitimer(int which, struct itimerval __user *value); +asmlinkage long sys_getitimer(int which, struct __kernel_old_itimerval __user *value); asmlinkage long sys_setitimer(int which, - struct itimerval __user *value, - struct itimerval __user *ovalue); + struct __kernel_old_itimerval __user *value, + struct __kernel_old_itimerval __user *ovalue); /* kernel/kexec.c */ asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, diff --git a/include/uapi/linux/time_types.h b/include/uapi/linux/time_types.h index 074e391d73a1..bcc0002115d3 100644 --- a/include/uapi/linux/time_types.h +++ b/include/uapi/linux/time_types.h @@ -33,6 +33,11 @@ struct __kernel_old_timespec { longtv_nsec;/* nanoseconds */ }; +struct __kernel_old_itimerval { + struct __kernel_old_timeval it_interval;/* timer interval */ + struct __kernel_old_timeval it_value; /* current value */ +}; + struct __kernel_sock_timeval { __s64 tv_sec; __s64 tv_usec; diff --git a/kernel/time/itimer.c b/kernel/time/itimer.c index 9e59c9ea92aa..ca4e6d57d68b 100644 --- a/kernel/time/itimer.c +++ b/kernel/time/itimer.c @@ -97,20 +97,20 @@ static int do_getitimer(int which, struct itimerspec64 *value) return 0; } -static int put_itimerval(struct itimerval __user *o, +static int put_itimerval(struct __kernel_old_itimerval __user *o, const struct itimerspec64 *i) { - struct itimerval v; + struct __kernel_old_itimerval v; v.it_interval.tv_sec = i->it_interval.tv_sec; v.it_interval.tv_usec = i->it_interval.tv_nsec / NSEC_PER_USEC; v.it_value.tv_sec = i->it_value.tv_sec; v.it_value.tv_usec = i->it_value.tv_nsec / NSEC_PER_USEC; - return copy_to_user(o, , sizeof(struct itimerval)) ? -EFAULT : 0; + return copy_to_user(o, , sizeof(struct __kernel_old_itimerval)) ? -EFAULT : 0; } -SYSCALL_DEFINE2(getitimer, int, which, struct itimerval __user *, value) +SYSCALL_DEFINE2(getitimer, int, which, struct __kernel_old_itimerval __user *, value) { struct itimerspec64 get_buffer; int error = do_getitimer(which, _buffer); @@ -314,11 +314,11 @@ SYSCALL_DEFINE1(alarm, unsigned int, seconds) #endif -static int get_itimerval(struct itimerspec64 *o, const struct itimerval __user *i) +static int get_itimerval(struct itimerspec64 *o, const struct __kernel_old_itimerval __user *i) { - struct itimerval v; + struct __kernel_old_itimerval v; - if (copy_from_user(, i, sizeof(struct itimerval))) + if (copy_from_user(, i, sizeof(struct __kernel_old_itimerval))) return -EFAULT; /* Validate the timevals in value. */ @@ -333,8 +333,8 @@ static int get_itimerval(struct itimerspec64 *o, const struct itimerval __user * return 0; } -SYSCALL_DEFINE3(setitimer, int, which, struct itimerval __user *, value, - struct itimerval __user *, ovalue) +SYSCALL_DEFINE3(setitimer, int, which, struct __kernel_old_itimerval __user *, value, + struct __kernel_old_itimerval __user *, ovalue) { struct itimerspec64 set_buffer, get_buffer; int error; -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 22/24] y2038: remove obsolete jiffies conversion functions
Now that the last user of timespec_to_jiffies() is gone, these can just be removed, everything else is using ktime_t or timespec64 already. Signed-off-by: Arnd Bergmann --- include/linux/jiffies.h | 20 -- kernel/time/time.c | 58 - 2 files changed, 5 insertions(+), 73 deletions(-) diff --git a/include/linux/jiffies.h b/include/linux/jiffies.h index 1b6d31da7cbc..e3279ef24d28 100644 --- a/include/linux/jiffies.h +++ b/include/linux/jiffies.h @@ -422,26 +422,6 @@ static __always_inline unsigned long usecs_to_jiffies(const unsigned int u) extern unsigned long timespec64_to_jiffies(const struct timespec64 *value); extern void jiffies_to_timespec64(const unsigned long jiffies, struct timespec64 *value); -static inline unsigned long timespec_to_jiffies(const struct timespec *value) -{ - struct timespec64 ts = timespec_to_timespec64(*value); - - return timespec64_to_jiffies(); -} - -static inline void jiffies_to_timespec(const unsigned long jiffies, - struct timespec *value) -{ - struct timespec64 ts; - - jiffies_to_timespec64(jiffies, ); - *value = timespec64_to_timespec(ts); -} - -extern unsigned long timeval_to_jiffies(const struct timeval *value); -extern void jiffies_to_timeval(const unsigned long jiffies, - struct timeval *value); - extern clock_t jiffies_to_clock_t(unsigned long x); static inline clock_t jiffies_delta_to_clock_t(long delta) { diff --git a/kernel/time/time.c b/kernel/time/time.c index 704ccd9451b0..cdd7386115ff 100644 --- a/kernel/time/time.c +++ b/kernel/time/time.c @@ -626,10 +626,12 @@ EXPORT_SYMBOL(__usecs_to_jiffies); * The >> (NSEC_JIFFIE_SC - SEC_JIFFIE_SC) converts the scaled nsec * value to a scaled second value. */ -static unsigned long -__timespec64_to_jiffies(u64 sec, long nsec) + +unsigned long +timespec64_to_jiffies(const struct timespec64 *value) { - nsec = nsec + TICK_NSEC - 1; + u64 sec = value->tv_sec; + long nsec = value->tv_nsec + TICK_NSEC - 1; if (sec >= MAX_SEC_IN_JIFFIES){ sec = MAX_SEC_IN_JIFFIES; @@ -640,18 +642,6 @@ __timespec64_to_jiffies(u64 sec, long nsec) (NSEC_JIFFIE_SC - SEC_JIFFIE_SC))) >> SEC_JIFFIE_SC; } - -static unsigned long -__timespec_to_jiffies(unsigned long sec, long nsec) -{ - return __timespec64_to_jiffies((u64)sec, nsec); -} - -unsigned long -timespec64_to_jiffies(const struct timespec64 *value) -{ - return __timespec64_to_jiffies(value->tv_sec, value->tv_nsec); -} EXPORT_SYMBOL(timespec64_to_jiffies); void @@ -668,44 +658,6 @@ jiffies_to_timespec64(const unsigned long jiffies, struct timespec64 *value) } EXPORT_SYMBOL(jiffies_to_timespec64); -/* - * We could use a similar algorithm to timespec_to_jiffies (with a - * different multiplier for usec instead of nsec). But this has a - * problem with rounding: we can't exactly add TICK_NSEC - 1 to the - * usec value, since it's not necessarily integral. - * - * We could instead round in the intermediate scaled representation - * (i.e. in units of 1/2^(large scale) jiffies) but that's also - * perilous: the scaling introduces a small positive error, which - * combined with a division-rounding-upward (i.e. adding 2^(scale) - 1 - * units to the intermediate before shifting) leads to accidental - * overflow and overestimates. - * - * At the cost of one additional multiplication by a constant, just - * use the timespec implementation. - */ -unsigned long -timeval_to_jiffies(const struct timeval *value) -{ - return __timespec_to_jiffies(value->tv_sec, -value->tv_usec * NSEC_PER_USEC); -} -EXPORT_SYMBOL(timeval_to_jiffies); - -void jiffies_to_timeval(const unsigned long jiffies, struct timeval *value) -{ - /* -* Convert jiffies to nanoseconds and separate with -* one divide. -*/ - u32 rem; - - value->tv_sec = div_u64_rem((u64)jiffies * TICK_NSEC, - NSEC_PER_SEC, ); - value->tv_usec = rem / NSEC_PER_USEC; -} -EXPORT_SYMBOL(jiffies_to_timeval); - /* * Convert jiffies/jiffies_64 to clock_t and back. */ -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 21/24] xfs: quota: move to time64_t interfaces
As a preparation for removing the 32-bit time_t type and all associated interfaces, change xfs to use time64_t and ktime_get_real_seconds() for the quota housekeeping. Signed-off-by: Arnd Bergmann --- fs/xfs/xfs_dquot.c | 6 +++--- fs/xfs/xfs_qm.h | 6 +++--- fs/xfs/xfs_quotaops.c| 6 +++--- fs/xfs/xfs_trans_dquot.c | 8 +--- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c index 2bff21ca9d78..9cfd3209f52b 100644 --- a/fs/xfs/xfs_dquot.c +++ b/fs/xfs/xfs_dquot.c @@ -137,7 +137,7 @@ xfs_qm_adjust_dqtimers( (d->d_blk_hardlimit && (be64_to_cpu(d->d_bcount) > be64_to_cpu(d->d_blk_hardlimit { - d->d_btimer = cpu_to_be32(get_seconds() + + d->d_btimer = cpu_to_be32(ktime_get_real_seconds() + mp->m_quotainfo->qi_btimelimit); } else { d->d_bwarns = 0; @@ -160,7 +160,7 @@ xfs_qm_adjust_dqtimers( (d->d_ino_hardlimit && (be64_to_cpu(d->d_icount) > be64_to_cpu(d->d_ino_hardlimit { - d->d_itimer = cpu_to_be32(get_seconds() + + d->d_itimer = cpu_to_be32(ktime_get_real_seconds() + mp->m_quotainfo->qi_itimelimit); } else { d->d_iwarns = 0; @@ -183,7 +183,7 @@ xfs_qm_adjust_dqtimers( (d->d_rtb_hardlimit && (be64_to_cpu(d->d_rtbcount) > be64_to_cpu(d->d_rtb_hardlimit { - d->d_rtbtimer = cpu_to_be32(get_seconds() + + d->d_rtbtimer = cpu_to_be32(ktime_get_real_seconds() + mp->m_quotainfo->qi_rtbtimelimit); } else { d->d_rtbwarns = 0; diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h index 7823af39008b..4e57edca8bce 100644 --- a/fs/xfs/xfs_qm.h +++ b/fs/xfs/xfs_qm.h @@ -64,9 +64,9 @@ struct xfs_quotainfo { struct xfs_inode*qi_pquotaip; /* project quota inode */ struct list_lru qi_lru; int qi_dquots; - time_t qi_btimelimit; /* limit for blks timer */ - time_t qi_itimelimit; /* limit for inodes timer */ - time_t qi_rtbtimelimit;/* limit for rt blks timer */ + time64_t qi_btimelimit; /* limit for blks timer */ + time64_t qi_itimelimit; /* limit for inodes timer */ + time64_t qi_rtbtimelimit;/* limit for rt blks timer */ xfs_qwarncnt_t qi_bwarnlimit; /* limit for blks warnings */ xfs_qwarncnt_t qi_iwarnlimit; /* limit for inodes warnings */ xfs_qwarncnt_t qi_rtbwarnlimit;/* limit for rt blks warnings */ diff --git a/fs/xfs/xfs_quotaops.c b/fs/xfs/xfs_quotaops.c index c7de17deeae6..38669e827206 100644 --- a/fs/xfs/xfs_quotaops.c +++ b/fs/xfs/xfs_quotaops.c @@ -37,9 +37,9 @@ xfs_qm_fill_state( tstate->flags |= QCI_SYSFILE; tstate->blocks = ip->i_d.di_nblocks; tstate->nextents = ip->i_d.di_nextents; - tstate->spc_timelimit = q->qi_btimelimit; - tstate->ino_timelimit = q->qi_itimelimit; - tstate->rt_spc_timelimit = q->qi_rtbtimelimit; + tstate->spc_timelimit = (u32)q->qi_btimelimit; + tstate->ino_timelimit = (u32)q->qi_itimelimit; + tstate->rt_spc_timelimit = (u32)q->qi_rtbtimelimit; tstate->spc_warnlimit = q->qi_bwarnlimit; tstate->ino_warnlimit = q->qi_iwarnlimit; tstate->rt_spc_warnlimit = q->qi_rtbwarnlimit; diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c index a6fe2d8dc40f..d1b9869bc5fa 100644 --- a/fs/xfs/xfs_trans_dquot.c +++ b/fs/xfs/xfs_trans_dquot.c @@ -580,7 +580,7 @@ xfs_trans_dqresv( { xfs_qcnt_t hardlimit; xfs_qcnt_t softlimit; - time_t timer; + time64_ttimer; xfs_qwarncnt_t warns; xfs_qwarncnt_t warnlimit; xfs_qcnt_t total_count; @@ -635,7 +635,8 @@ xfs_trans_dqresv( goto error_return; } if (softlimit && total_count > softlimit) { - if ((timer != 0 && get_seconds() > timer) || + if ((timer != 0 && +ktime_get_real_seconds() > timer) || (warns != 0 && warns >= warnlimit)) { xfs_quota_warn(mp, dqp, QUOTA_NL_BSOFTLONGWARN); @@ -662,7 +663,8 @@ xfs_trans_dqresv( goto error_return; } if (softlimit
[Y2038] [PATCH v2 20/24] xfs: disallow broken ioctls without compat-32-bit-time
When building a kernel that disables support for 32-bit time_t system calls, it also makes sense to disable the old xfs_bstat ioctls completely, as they truncate the timestamps to 32-bit values. Any application using these needs to be updated to use the v5 interfaces. Signed-off-by: Arnd Bergmann --- fs/xfs/xfs_ioctl.c | 26 ++ 1 file changed, 26 insertions(+) diff --git a/fs/xfs/xfs_ioctl.c b/fs/xfs/xfs_ioctl.c index 7b35d62ede9f..a4a4eed8879c 100644 --- a/fs/xfs/xfs_ioctl.c +++ b/fs/xfs/xfs_ioctl.c @@ -36,6 +36,7 @@ #include "xfs_reflink.h" #include "xfs_ioctl.h" +#include #include #include @@ -617,6 +618,23 @@ xfs_fsinumbers_fmt( return xfs_ibulk_advance(breq, sizeof(struct xfs_inogrp)); } +/* disallow y2038-unsafe ioctls with CONFIG_COMPAT_32BIT_TIME=n */ +static bool xfs_have_compat_bstat_time32(unsigned int cmd) +{ + if (IS_ENABLED(CONFIG_COMPAT_32BIT_TIME)) + return true; + + if (IS_ENABLED(CONFIG_64BIT) && !in_compat_syscall()) + return true; + + if (cmd == XFS_IOC_FSBULKSTAT_SINGLE || + cmd == XFS_IOC_FSBULKSTAT || + cmd == XFS_IOC_SWAPEXT) + return false; + + return true; +} + STATIC int xfs_ioc_fsbulkstat( xfs_mount_t *mp, @@ -637,6 +655,9 @@ xfs_ioc_fsbulkstat( if (!capable(CAP_SYS_ADMIN)) return -EPERM; + if (!xfs_have_compat_bstat_time32(cmd)) + return -EINVAL; + if (XFS_FORCED_SHUTDOWN(mp)) return -EIO; @@ -1815,6 +1836,11 @@ xfs_ioc_swapext( struct fd f, tmp; int error = 0; + if (xfs_have_compat_bstat_time32(XFS_IOC_SWAPEXT)) { + error = -EINVAL; + goto out; + } + /* Pull information for the target fd */ f = fdget((int)sxp->sx_fdtarget); if (!f.file) { -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 18/24] nfs: fscache: use timespec64 in inode auxdata
nfs currently behaves differently on 32-bit and 64-bit kernels regarding the on-disk format of nfs_fscache_inode_auxdata. That format should really be the same on any kernel, and we should avoid the 'timespec' type in order to remove that from the kernel later on. Using plain 'timespec64' would not be good here, since that includes implied padding and would possibly leak kernel stack data to the on-disk format on 32-bit architectures. struct __kernel_timespec would work as a replacement, but open-coding the two struct members in nfs_fscache_inode_auxdata makes it more obvious what's going on here, and keeps the current format for 64-bit architectures. Cc: David Howells Signed-off-by: Arnd Bergmann --- fs/nfs/fscache-index.c | 6 -- fs/nfs/fscache.c | 18 -- fs/nfs/fscache.h | 8 +--- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/fs/nfs/fscache-index.c b/fs/nfs/fscache-index.c index 15f271401dcc..573b1da9342c 100644 --- a/fs/nfs/fscache-index.c +++ b/fs/nfs/fscache-index.c @@ -84,8 +84,10 @@ enum fscache_checkaux nfs_fscache_inode_check_aux(void *cookie_netfs_data, return FSCACHE_CHECKAUX_OBSOLETE; memset(, 0, sizeof(auxdata)); - auxdata.mtime = timespec64_to_timespec(nfsi->vfs_inode.i_mtime); - auxdata.ctime = timespec64_to_timespec(nfsi->vfs_inode.i_ctime); + auxdata.mtime_sec = nfsi->vfs_inode.i_mtime.tv_sec; + auxdata.mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec; + auxdata.ctime_sec = nfsi->vfs_inode.i_ctime.tv_sec; + auxdata.ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec; if (NFS_SERVER(>vfs_inode)->nfs_client->rpc_ops->version == 4) auxdata.change_attr = inode_peek_iversion_raw(>vfs_inode); diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c index 3800ab6f08fa..7def925d3af5 100644 --- a/fs/nfs/fscache.c +++ b/fs/nfs/fscache.c @@ -238,8 +238,10 @@ void nfs_fscache_init_inode(struct inode *inode) return; memset(, 0, sizeof(auxdata)); - auxdata.mtime = timespec64_to_timespec(nfsi->vfs_inode.i_mtime); - auxdata.ctime = timespec64_to_timespec(nfsi->vfs_inode.i_ctime); + auxdata.mtime_sec = nfsi->vfs_inode.i_mtime.tv_sec; + auxdata.mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec; + auxdata.ctime_sec = nfsi->vfs_inode.i_ctime.tv_sec; + auxdata.ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec; if (NFS_SERVER(>vfs_inode)->nfs_client->rpc_ops->version == 4) auxdata.change_attr = inode_peek_iversion_raw(>vfs_inode); @@ -263,8 +265,10 @@ void nfs_fscache_clear_inode(struct inode *inode) dfprintk(FSCACHE, "NFS: clear cookie (0x%p/0x%p)\n", nfsi, cookie); memset(, 0, sizeof(auxdata)); - auxdata.mtime = timespec64_to_timespec(nfsi->vfs_inode.i_mtime); - auxdata.ctime = timespec64_to_timespec(nfsi->vfs_inode.i_ctime); + auxdata.mtime_sec = nfsi->vfs_inode.i_mtime.tv_sec; + auxdata.mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec; + auxdata.ctime_sec = nfsi->vfs_inode.i_ctime.tv_sec; + auxdata.ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec; fscache_relinquish_cookie(cookie, , false); nfsi->fscache = NULL; } @@ -305,8 +309,10 @@ void nfs_fscache_open_file(struct inode *inode, struct file *filp) return; memset(, 0, sizeof(auxdata)); - auxdata.mtime = timespec64_to_timespec(nfsi->vfs_inode.i_mtime); - auxdata.ctime = timespec64_to_timespec(nfsi->vfs_inode.i_ctime); + auxdata.mtime_sec = nfsi->vfs_inode.i_mtime.tv_sec; + auxdata.mtime_nsec = nfsi->vfs_inode.i_mtime.tv_nsec; + auxdata.ctime_sec = nfsi->vfs_inode.i_ctime.tv_sec; + auxdata.ctime_nsec = nfsi->vfs_inode.i_ctime.tv_nsec; if (inode_is_open_for_write(inode)) { dfprintk(FSCACHE, "NFS: nfsi 0x%p disabling cache\n", nfsi); diff --git a/fs/nfs/fscache.h b/fs/nfs/fscache.h index ad041cfbf9ec..6754c8607230 100644 --- a/fs/nfs/fscache.h +++ b/fs/nfs/fscache.h @@ -62,9 +62,11 @@ struct nfs_fscache_key { * cache object. */ struct nfs_fscache_inode_auxdata { - struct timespec mtime; - struct timespec ctime; - u64 change_attr; + s64 mtime_sec; + s64 mtime_nsec; + s64 ctime_sec; + s64 ctime_nsec; + u64 change_attr; }; /* -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 16/24] nfs: use time64_t internally
The timestamps for the cache are all in boottime seconds, so they don't overflow 32-bit values, but the use of time_t is deprecated because it generally does overflow when used with wall-clock time. There are multiple possible ways of avoiding it: - leave time_t, which is safe here, but forces others to look into this code to determine that it is over and over. - use a more generic type, like 'int' or 'long', which is known to be sufficient here but loses the documentation of referring to timestamps - use ktime_t everywhere, and convert into seconds in the few places where we want realtime-seconds. The conversion is sometimes expensive, but not more so than the conversion we do today. - use time64_t to clarify that this code is safe. Nothing would change for 64-bit architectures, but it is slightly less efficient on 32-bit architectures. Without a clear winner of the three approaches above, this picks the last one, favouring readability over a small performance loss on 32-bit architectures. Signed-off-by: Arnd Bergmann --- include/linux/sunrpc/cache.h | 42 +-- net/sunrpc/auth_gss/svcauth_gss.c | 2 +- net/sunrpc/cache.c| 16 ++-- net/sunrpc/svcauth_unix.c | 10 4 files changed, 37 insertions(+), 33 deletions(-) diff --git a/include/linux/sunrpc/cache.h b/include/linux/sunrpc/cache.h index f8603724fbee..0f64de7caa39 100644 --- a/include/linux/sunrpc/cache.h +++ b/include/linux/sunrpc/cache.h @@ -45,8 +45,8 @@ */ struct cache_head { struct hlist_node cache_list; - time_t expiry_time;/* After time time, don't use the data */ - time_t last_refresh; /* If CACHE_PENDING, this is when upcall was + time64_texpiry_time;/* After time time, don't use the data */ + time64_tlast_refresh; /* If CACHE_PENDING, this is when upcall was * sent, else this is when update was * received, though it is alway set to * be *after* ->flush_time. @@ -95,22 +95,22 @@ struct cache_detail { /* fields below this comment are for internal use * and should not be touched by cache owners */ - time_t flush_time; /* flush all cache items with + time64_tflush_time; /* flush all cache items with * last_refresh at or earlier * than this. last_refresh * is never set at or earlier * than this. */ struct list_headothers; - time_t nextcheck; + time64_tnextcheck; int entries; /* fields for communication over channel */ struct list_headqueue; atomic_twriters;/* how many time is /channel open */ - time_t last_close; /* if no writers, when did last close */ - time_t last_warn; /* when we last warned about no writers */ + time64_tlast_close; /* if no writers, when did last close */ + time64_tlast_warn; /* when we last warned about no writers */ union { struct proc_dir_entry *procfs; @@ -147,18 +147,22 @@ struct cache_deferred_req { * timestamps kept in the cache are expressed in seconds * since boot. This is the best for measuring differences in * real time. + * This reimplemnts ktime_get_boottime_seconds() in a slightly + * faster but less accurate way. When we end up converting + * back to wallclock (CLOCK_REALTIME), that error often + * cancels out during the reverse operation. */ -static inline time_t seconds_since_boot(void) +static inline time64_t seconds_since_boot(void) { - struct timespec boot; - getboottime(); - return get_seconds() - boot.tv_sec; + struct timespec64 boot; + getboottime64(); + return ktime_get_real_seconds() - boot.tv_sec; } -static inline time_t convert_to_wallclock(time_t sinceboot) +static inline time64_t convert_to_wallclock(time64_t sinceboot) { - struct timespec boot; - getboottime(); + struct timespec64 boot; + getboottime64(); return boot.tv_sec + sinceboot; } @@ -273,7 +277,7 @@ static inline int get_uint(char **bpp, unsigned int *anint) return 0; } -static inline int get_time(char **bpp, time_t *time) +static inline int get_time(char **bpp, time64_t *time) { char buf[50]; long long ll; @@
[Y2038] [PATCH v2 17/24] nfs: fix timstamp debug prints
Starting in v5.5, the timestamps are correctly passed down as 64-bit seconds with NFSv4 on 32-bit machines, but some debug statements still truncate them to 'long'. Fixes: e86d5a02874c ("NFS: Convert struct nfs_fattr to use struct timespec64") Signed-off-by: Arnd Bergmann --- fs/nfs/nfs4xdr.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 936c57779ff4..728d88b6a698 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -4097,7 +4097,7 @@ static int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, str status = NFS_ATTR_FATTR_ATIME; bitmap[1] &= ~FATTR4_WORD1_TIME_ACCESS; } - dprintk("%s: atime=%ld\n", __func__, (long)time->tv_sec); + dprintk("%s: atime=%lld\n", __func__, time->tv_sec); return status; } @@ -4115,7 +4115,7 @@ static int decode_attr_time_metadata(struct xdr_stream *xdr, uint32_t *bitmap, s status = NFS_ATTR_FATTR_CTIME; bitmap[1] &= ~FATTR4_WORD1_TIME_METADATA; } - dprintk("%s: ctime=%ld\n", __func__, (long)time->tv_sec); + dprintk("%s: ctime=%lld\n", __func__, time->tv_sec); return status; } @@ -4132,8 +4132,8 @@ static int decode_attr_time_delta(struct xdr_stream *xdr, uint32_t *bitmap, status = decode_attr_time(xdr, time); bitmap[1] &= ~FATTR4_WORD1_TIME_DELTA; } - dprintk("%s: time_delta=%ld %ld\n", __func__, (long)time->tv_sec, - (long)time->tv_nsec); + dprintk("%s: time_delta=%lld %ld\n", __func__, time->tv_sec, + time->tv_nsec); return status; } @@ -4197,7 +4197,7 @@ static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, str status = NFS_ATTR_FATTR_MTIME; bitmap[1] &= ~FATTR4_WORD1_TIME_MODIFY; } - dprintk("%s: mtime=%ld\n", __func__, (long)time->tv_sec); + dprintk("%s: mtime=%lld\n", __func__, time->tv_sec); return status; } -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 15/24] sunrpc: convert to time64_t for expiry
Using signed 32-bit types for UTC time leads to the y2038 overflow, which is what happens in the sunrpc code at the moment. This changes the sunrpc code over to use time64_t where possible. The one exception is the gss_import_v{1,2}_context() function for kerberos5, which uses 32-bit timestamps in the protocol. Here, we can at least treat the numbers as 'unsigned', which extends the range from 2038 to 2106. Signed-off-by: Arnd Bergmann --- include/linux/sunrpc/gss_api.h| 4 ++-- include/linux/sunrpc/gss_krb5.h | 2 +- net/sunrpc/auth_gss/gss_krb5_mech.c | 12 +--- net/sunrpc/auth_gss/gss_krb5_seal.c | 8 net/sunrpc/auth_gss/gss_krb5_unseal.c | 6 +++--- net/sunrpc/auth_gss/gss_krb5_wrap.c | 16 net/sunrpc/auth_gss/gss_mech_switch.c | 2 +- net/sunrpc/auth_gss/svcauth_gss.c | 4 ++-- 8 files changed, 30 insertions(+), 24 deletions(-) diff --git a/include/linux/sunrpc/gss_api.h b/include/linux/sunrpc/gss_api.h index bd691e08be3b..1cc6cefb1220 100644 --- a/include/linux/sunrpc/gss_api.h +++ b/include/linux/sunrpc/gss_api.h @@ -48,7 +48,7 @@ int gss_import_sec_context( size_t bufsize, struct gss_api_mech *mech, struct gss_ctx **ctx_id, - time_t *endtime, + time64_t*endtime, gfp_t gfp_mask); u32 gss_get_mic( struct gss_ctx *ctx_id, @@ -108,7 +108,7 @@ struct gss_api_ops { const void *input_token, size_t bufsize, struct gss_ctx *ctx_id, - time_t *endtime, + time64_t*endtime, gfp_t gfp_mask); u32 (*gss_get_mic)( struct gss_ctx *ctx_id, diff --git a/include/linux/sunrpc/gss_krb5.h b/include/linux/sunrpc/gss_krb5.h index 02c0412e368c..c1d77dd8ed41 100644 --- a/include/linux/sunrpc/gss_krb5.h +++ b/include/linux/sunrpc/gss_krb5.h @@ -106,9 +106,9 @@ struct krb5_ctx { struct crypto_sync_skcipher *initiator_enc_aux; u8 Ksess[GSS_KRB5_MAX_KEYLEN]; /* session key */ u8 cksum[GSS_KRB5_MAX_KEYLEN]; - s32 endtime; atomic_tseq_send; atomic64_t seq_send64; + time64_tendtime; struct xdr_netobj mech_used; u8 initiator_sign[GSS_KRB5_MAX_KEYLEN]; u8 acceptor_sign[GSS_KRB5_MAX_KEYLEN]; diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 6e5d6d240215..75b3c2e9e8f8 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c @@ -253,6 +253,7 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx) { u32 seq_send; int tmp; + u32 time32; p = simple_get_bytes(p, end, >initiate, sizeof(ctx->initiate)); if (IS_ERR(p)) @@ -290,9 +291,11 @@ gss_import_v1_context(const void *p, const void *end, struct krb5_ctx *ctx) p = ERR_PTR(-ENOSYS); goto out_err; } - p = simple_get_bytes(p, end, >endtime, sizeof(ctx->endtime)); + p = simple_get_bytes(p, end, , sizeof(time32)); if (IS_ERR(p)) goto out_err; + /* unsigned 32-bit time overflows in year 2106 */ + ctx->endtime = (time64_t)time32; p = simple_get_bytes(p, end, _send, sizeof(seq_send)); if (IS_ERR(p)) goto out_err; @@ -587,15 +590,18 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, { u64 seq_send64; int keylen; + u32 time32; p = simple_get_bytes(p, end, >flags, sizeof(ctx->flags)); if (IS_ERR(p)) goto out_err; ctx->initiate = ctx->flags & KRB5_CTX_FLAG_INITIATOR; - p = simple_get_bytes(p, end, >endtime, sizeof(ctx->endtime)); + p = simple_get_bytes(p, end, , sizeof(time32)); if (IS_ERR(p)) goto out_err; + /* unsigned 32-bit time overflows in year 2106 */ + ctx->endtime = (time64_t)time32; p = simple_get_bytes(p, end, _send64, sizeof(seq_send64)); if (IS_ERR(p)) goto out_err; @@ -659,7 +665,7 @@ gss_import_v2_context(const void *p, const void *end, struct krb5_ctx *ctx, static int gss_import_sec_context_kerberos(const void *p, size_t len, struct gss_ctx *ctx_id, - time_t *endtime, + time64_t *endtime, gfp_t gfp_mask) { const void *end = (const void *)((const char *)p + len);
[Y2038] [PATCH v2 14/24] drm/etnaviv: avoid deprecated timespec
struct timespec is being removed from the kernel because it often leads to code that is not y2038-safe. In the etnaviv driver, monotonic timestamps are used, which do not suffer from overflow, but the usage of timespec here gets in the way of removing the interface completely. Pass down the user-supplied 64-bit value here rather than converting it to an intermediate timespec to avoid the conversion. The conversion is transparent for all regular CLOCK_MONOTONIC values, but is a small change in behavior for excessively large values: the existing code would treat e.g. tv_sec=0x1 the same as tv_sec=0 and not block, while the new code it would block for up to 2^31 seconds. The new behavior is more logical here, but if it causes problems, the truncation can be put back. Signed-off-by: Arnd Bergmann --- drivers/gpu/drm/etnaviv/etnaviv_drv.c | 11 +++ drivers/gpu/drm/etnaviv/etnaviv_drv.h | 11 ++- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 4 ++-- drivers/gpu/drm/etnaviv/etnaviv_gem.h | 2 +- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 5 +++-- drivers/gpu/drm/etnaviv/etnaviv_gpu.h | 5 +++-- 6 files changed, 18 insertions(+), 20 deletions(-) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index 95d72dc00280..3eb0f9223bea 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -282,11 +282,6 @@ static int etnaviv_ioctl_gem_new(struct drm_device *dev, void *data, args->flags, >handle); } -#define TS(t) ((struct timespec){ \ - .tv_sec = (t).tv_sec, \ - .tv_nsec = (t).tv_nsec \ -}) - static int etnaviv_ioctl_gem_cpu_prep(struct drm_device *dev, void *data, struct drm_file *file) { @@ -304,7 +299,7 @@ static int etnaviv_ioctl_gem_cpu_prep(struct drm_device *dev, void *data, if (!obj) return -ENOENT; - ret = etnaviv_gem_cpu_prep(obj, args->op, (args->timeout)); + ret = etnaviv_gem_cpu_prep(obj, args->op, >timeout); drm_gem_object_put_unlocked(obj); @@ -357,7 +352,7 @@ static int etnaviv_ioctl_wait_fence(struct drm_device *dev, void *data, { struct drm_etnaviv_wait_fence *args = data; struct etnaviv_drm_private *priv = dev->dev_private; - struct timespec *timeout = (args->timeout); + struct drm_etnaviv_timespec *timeout = >timeout; struct etnaviv_gpu *gpu; if (args->flags & ~(ETNA_WAIT_NONBLOCK)) @@ -409,7 +404,7 @@ static int etnaviv_ioctl_gem_wait(struct drm_device *dev, void *data, { struct etnaviv_drm_private *priv = dev->dev_private; struct drm_etnaviv_gem_wait *args = data; - struct timespec *timeout = (args->timeout); + struct drm_etnaviv_timespec *timeout = >timeout; struct drm_gem_object *obj; struct etnaviv_gpu *gpu; int ret; diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.h b/drivers/gpu/drm/etnaviv/etnaviv_drv.h index 32cfa5a48d42..efc656efeb0f 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.h +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.h @@ -61,7 +61,7 @@ int etnaviv_gem_prime_pin(struct drm_gem_object *obj); void etnaviv_gem_prime_unpin(struct drm_gem_object *obj); void *etnaviv_gem_vmap(struct drm_gem_object *obj); int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, u32 op, - struct timespec *timeout); + struct drm_etnaviv_timespec *timeout); int etnaviv_gem_cpu_fini(struct drm_gem_object *obj); void etnaviv_gem_free_object(struct drm_gem_object *obj); int etnaviv_gem_new_handle(struct drm_device *dev, struct drm_file *file, @@ -107,11 +107,12 @@ static inline size_t size_vstruct(size_t nelem, size_t elem_size, size_t base) * between the specified timeout and the current CLOCK_MONOTONIC time. */ static inline unsigned long etnaviv_timeout_to_jiffies( - const struct timespec *timeout) + const struct drm_etnaviv_timespec *timeout) { - struct timespec64 ts, to; - - to = timespec_to_timespec64(*timeout); + struct timespec64 ts, to = { + .tv_sec = timeout->tv_sec, + .tv_nsec = timeout->tv_nsec, + }; ktime_get_ts64(); diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem.c b/drivers/gpu/drm/etnaviv/etnaviv_gem.c index cb1faaac380a..6adea180d629 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_gem.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_gem.c @@ -373,7 +373,7 @@ static inline enum dma_data_direction etnaviv_op_to_dma_dir(u32 op) } int etnaviv_gem_cpu_prep(struct drm_gem_object *obj, u32 op, - struct timespec *timeout) + struct drm_etnaviv_timespec *timeout) { struct etnaviv_gem_object *etnaviv_obj = to_etnaviv_bo(obj); struct drm_device *dev = obj->dev; @@ -431,7 +431,7 @@ int etnaviv_gem_cpu_fini(struct drm_gem_object *obj) } int etnaviv_gem_wait_bo(struct etnaviv_gpu *gpu, struct drm_gem_object *obj, - struct timespec
[Y2038] [PATCH v2 13/24] drm/etnaviv: reject timeouts with tv_nsec >= NSEC_PER_SEC
Most kernel interfaces that take a timespec require normalized representation with tv_nsec between 0 and NSEC_PER_SEC. Passing values larger than 0x1ull further behaves differently on 32-bit and 64-bit kernels, and can cause the latter to spend a long time counting seconds in timespec64_sub()/set_normalized_timespec64(). Reject those large values at the user interface to enforce sane and portable behavior. Signed-off-by: Arnd Bergmann --- drivers/gpu/drm/etnaviv/etnaviv_drv.c | 9 + 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c index 1f9c01be40d7..95d72dc00280 100644 --- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c +++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c @@ -297,6 +297,9 @@ static int etnaviv_ioctl_gem_cpu_prep(struct drm_device *dev, void *data, if (args->op & ~(ETNA_PREP_READ | ETNA_PREP_WRITE | ETNA_PREP_NOSYNC)) return -EINVAL; + if (args->timeout.tv_nsec > NSEC_PER_SEC) + return -EINVAL; + obj = drm_gem_object_lookup(file, args->handle); if (!obj) return -ENOENT; @@ -360,6 +363,9 @@ static int etnaviv_ioctl_wait_fence(struct drm_device *dev, void *data, if (args->flags & ~(ETNA_WAIT_NONBLOCK)) return -EINVAL; + if (args->timeout.tv_nsec > NSEC_PER_SEC) + return -EINVAL; + if (args->pipe >= ETNA_MAX_PIPES) return -EINVAL; @@ -411,6 +417,9 @@ static int etnaviv_ioctl_gem_wait(struct drm_device *dev, void *data, if (args->flags & ~(ETNA_WAIT_NONBLOCK)) return -EINVAL; + if (args->timeout.tv_nsec > NSEC_PER_SEC) + return -EINVAL; + if (args->pipe >= ETNA_MAX_PIPES) return -EINVAL; -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 12/24] drm/msm: avoid using 'timespec'
The timespec structure and associated interfaces are deprecated and will be removed in the future because of the y2038 overflow. The use of ktime_to_timespec() in timeout_to_jiffies() does not suffer from that overflow, but is easy to avoid by just converting the ktime_t into jiffies directly. Reviewed-by: Jordan Crouse Signed-off-by: Arnd Bergmann --- drivers/gpu/drm/msm/msm_drv.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h index 71547e756e29..740bf7c70d8f 100644 --- a/drivers/gpu/drm/msm/msm_drv.h +++ b/drivers/gpu/drm/msm/msm_drv.h @@ -454,8 +454,7 @@ static inline unsigned long timeout_to_jiffies(const ktime_t *timeout) remaining_jiffies = 0; } else { ktime_t rem = ktime_sub(*timeout, now); - struct timespec ts = ktime_to_timespec(rem); - remaining_jiffies = timespec_to_jiffies(); + remaining_jiffies = ktime_divns(rem, NSEC_PER_SEC / HZ); } return remaining_jiffies; -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 11/24] hfs/hfsplus: use 64-bit inode timestamps
The interpretation of on-disk timestamps in HFS and HFS+ differs between 32-bit and 64-bit kernels at the moment. Use 64-bit timestamps consistently so apply the current 64-bit behavior everyhere. According to the official documentation for HFS+ [1], inode timestamps are supposed to cover the time range from 1904 to 2040 as originally used in classic MacOS. The traditional Linux usage is to convert the timestamps into an unsigned 32-bit number based on the Unix epoch and from there to a time_t. On 32-bit systems, that wraps the time from 2038 to 1902, so the last two years of the valid time range become garbled. On 64-bit systems, all times before 1970 get turned into timestamps between 2038 and 2106, which is more convenient but also different from the documented behavior. Looking at the Darwin sources [2], it seems that MacOS is inconsistent in yet another way: all timestamps are wrapped around to a 32-bit unsigned number when written to the disk, but when read back, all numeric values lower than 2082844800U are assumed to be invalid, so we cannot represent the times before 1970 or the times after 2040. While all implementations seem to agree on the interpretation of values between 1970 and 2038, they often differ on the exact range they support when reading back values outside of the common range: MacOS (traditional):1904-2040 Apple Documentation:1904-2040 MacOS X source comments:1970-2040 MacOS X source code:1970-2038 32-bit Linux: 1902-2038 64-bit Linux: 1970-2106 hfsfuse:1970-2040 hfsutils (32 bit, old libc) 1902-2038 hfsutils (32 bit, new libc) 1970-2106 hfsutils (64 bit) 1904-2040 hfsplus-utils 1904-2040 hfsexplorer 1904-2040 7-zip 1904-2040 Out of the above, the range from 1970 to 2106 seems to be the most useful, as it allows using HFS and HFS+ beyond year 2038, and this matches the behavior that most users would see today on Linux, as few people run 32-bit kernels any more. Link: [1] https://developer.apple.com/library/archive/technotes/tn/tn1150.html Link: [2] https://opensource.apple.com/source/hfs/hfs-407.30.1/core/MacOSStubs.c.auto.html Link: https://lore.kernel.org/lkml/20180711224625.airwna6gzyatoowe@eaf/ Suggested-by: "Ernesto A. Fernández" Reviewed-by: Vyacheslav Dubeyko Reviewed-by: Ernesto A. Fernández Signed-off-by: Arnd Bergmann --- v3: revert back to 1970-2106 time range fix bugs found in review merge both patches into one drop cc:stable tag v2: treat pre-1970 dates as invalid following MacOS X behavior, reword and expand changelog text --- fs/hfs/hfs_fs.h | 28 ++-- fs/hfs/inode.c | 4 ++-- fs/hfsplus/hfsplus_fs.h | 28 +++- fs/hfsplus/inode.c | 12 ++-- 4 files changed, 53 insertions(+), 19 deletions(-) diff --git a/fs/hfs/hfs_fs.h b/fs/hfs/hfs_fs.h index 6d0783e2e276..f71c384064c8 100644 --- a/fs/hfs/hfs_fs.h +++ b/fs/hfs/hfs_fs.h @@ -242,19 +242,35 @@ extern void hfs_mark_mdb_dirty(struct super_block *sb); /* * There are two time systems. Both are based on seconds since * a particular time/date. - * Unix: unsigned lil-endian since 00:00 GMT, Jan. 1, 1970 + * Unix: signed little-endian since 00:00 GMT, Jan. 1, 1970 * mac:unsigned big-endian since 00:00 GMT, Jan. 1, 1904 * + * HFS implementations are highly inconsistent, this one matches the + * traditional behavior of 64-bit Linux, giving the most useful + * time range between 1970 and 2106, by treating any on-disk timestamp + * under HFS_UTC_OFFSET (Jan 1 1970) as a time between 2040 and 2106. */ -#define __hfs_u_to_mtime(sec) cpu_to_be32(sec + 2082844800U - sys_tz.tz_minuteswest * 60) -#define __hfs_m_to_utime(sec) (be32_to_cpu(sec) - 2082844800U + sys_tz.tz_minuteswest * 60) +#define HFS_UTC_OFFSET 2082844800U +static inline time64_t __hfs_m_to_utime(__be32 mt) +{ + time64_t ut = (u32)(be32_to_cpu(mt) - HFS_UTC_OFFSET); + + return ut + sys_tz.tz_minuteswest * 60; +} + +static inline __be32 __hfs_u_to_mtime(time64_t ut) +{ + ut -= sys_tz.tz_minuteswest * 60; + + return cpu_to_be32(lower_32_bits(ut) + HFS_UTC_OFFSET); +} #define HFS_I(inode) (container_of(inode, struct hfs_inode_info, vfs_inode)) #define HFS_SB(sb) ((struct hfs_sb_info *)(sb)->s_fs_info) -#define hfs_m_to_utime(time) (struct timespec){ .tv_sec = __hfs_m_to_utime(time) } -#define hfs_u_to_mtime(time) __hfs_u_to_mtime((time).tv_sec) -#define hfs_mtime()__hfs_u_to_mtime(get_seconds()) +#define hfs_m_to_utime(time) (struct timespec64){ .tv_sec = __hfs_m_to_utime(time) } +#define hfs_u_to_mtime(time) __hfs_u_to_mtime((time).tv_sec) +#define hfs_mtime()__hfs_u_to_mtime(ktime_get_real_seconds()) static inline const char *hfs_mdb_name(struct super_block *sb) { diff
[Y2038] [PATCH v2 10/24] hostfs: pass 64-bit timestamps to/from user space
The use of 'struct timespec' is deprecated in the kernel, so we want to avoid the conversions from/to the proper timespec64 structure. On the user space side, we have a 'struct timespec' that is defined by the C library and that will be incompatible with the kernel's view on 32-bit architectures once they move to a 64-bit time_t, breaking the shared binary layout of hostfs_iattr and hostfs_stat. This changes the two structures to use a new hostfs_timespec structure with fixed 64-bit seconds/nanoseconds for passing the timestamps between hostfs_kern.c and hostfs_user.c. With a new enough user space side, this will allow timestamps beyond year 2038. Signed-off-by: Arnd Bergmann --- fs/hostfs/hostfs.h | 22 +- fs/hostfs/hostfs_kern.c | 15 +-- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/fs/hostfs/hostfs.h b/fs/hostfs/hostfs.h index f4295aa19350..69cb796f6270 100644 --- a/fs/hostfs/hostfs.h +++ b/fs/hostfs/hostfs.h @@ -37,16 +37,20 @@ * is on, and remove the appropriate bits from attr->ia_mode (attr is a * "struct iattr *"). -BlaisorBlade */ +struct hostfs_timespec { + long long tv_sec; + long long tv_nsec; +}; struct hostfs_iattr { - unsigned intia_valid; - unsigned short ia_mode; - uid_t ia_uid; - gid_t ia_gid; - loff_t ia_size; - struct timespec ia_atime; - struct timespec ia_mtime; - struct timespec ia_ctime; + unsigned intia_valid; + unsigned short ia_mode; + uid_t ia_uid; + gid_t ia_gid; + loff_t ia_size; + struct hostfs_timespec ia_atime; + struct hostfs_timespec ia_mtime; + struct hostfs_timespec ia_ctime; }; struct hostfs_stat { @@ -56,7 +60,7 @@ struct hostfs_stat { unsigned int uid; unsigned int gid; unsigned long long size; - struct timespec atime, mtime, ctime; + struct hostfs_timespec atime, mtime, ctime; unsigned int blksize; unsigned long long blocks; unsigned int maj; diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 5a7eb0c79839..e6b8c49076bb 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -549,9 +549,9 @@ static int read_name(struct inode *ino, char *name) set_nlink(ino, st.nlink); i_uid_write(ino, st.uid); i_gid_write(ino, st.gid); - ino->i_atime = timespec_to_timespec64(st.atime); - ino->i_mtime = timespec_to_timespec64(st.mtime); - ino->i_ctime = timespec_to_timespec64(st.ctime); + ino->i_atime = (struct timespec64){ st.atime.tv_sec, st.atime.tv_nsec }; + ino->i_mtime = (struct timespec64){ st.mtime.tv_sec, st.mtime.tv_nsec }; + ino->i_ctime = (struct timespec64){ st.ctime.tv_sec, st.ctime.tv_nsec }; ino->i_size = st.size; ino->i_blocks = st.blocks; return 0; @@ -820,15 +820,18 @@ static int hostfs_setattr(struct dentry *dentry, struct iattr *attr) } if (attr->ia_valid & ATTR_ATIME) { attrs.ia_valid |= HOSTFS_ATTR_ATIME; - attrs.ia_atime = timespec64_to_timespec(attr->ia_atime); + attrs.ia_atime = (struct hostfs_timespec) + { attr->ia_atime.tv_sec, attr->ia_atime.tv_nsec }; } if (attr->ia_valid & ATTR_MTIME) { attrs.ia_valid |= HOSTFS_ATTR_MTIME; - attrs.ia_mtime = timespec64_to_timespec(attr->ia_mtime); + attrs.ia_mtime = (struct hostfs_timespec) + { attr->ia_mtime.tv_sec, attr->ia_mtime.tv_nsec }; } if (attr->ia_valid & ATTR_CTIME) { attrs.ia_valid |= HOSTFS_ATTR_CTIME; - attrs.ia_ctime = timespec64_to_timespec(attr->ia_ctime); + attrs.ia_ctime = (struct hostfs_timespec) + { attr->ia_ctime.tv_sec, attr->ia_ctime.tv_nsec }; } if (attr->ia_valid & ATTR_ATIME_SET) { attrs.ia_valid |= HOSTFS_ATTR_ATIME_SET; -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 09/24] quota: avoid time_t in v1_disk_dqblk definition
The time_t type is part of the user interface and not always the same, with the move to 64-bit timestamps and the difference between architectures. Make the quota format definition independent of this type and use a basic type of the same length. Make it unsigned in the process to keep the v1 format working until year 2106 instead of 2038 on 32-bit architectures. Hopefully, everybody has already moved to a newer format long ago (v2 was introduced with linux-2.4), but it's hard to be sure. Signed-off-by: Arnd Bergmann --- fs/quota/quotaio_v1.h | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/quota/quotaio_v1.h b/fs/quota/quotaio_v1.h index bd11e2c08119..31dca9a89176 100644 --- a/fs/quota/quotaio_v1.h +++ b/fs/quota/quotaio_v1.h @@ -25,8 +25,10 @@ struct v1_disk_dqblk { __u32 dqb_ihardlimit; /* absolute limit on allocated inodes */ __u32 dqb_isoftlimit; /* preferred inode limit */ __u32 dqb_curinodes;/* current # allocated inodes */ - time_t dqb_btime; /* time limit for excessive disk use */ - time_t dqb_itime; /* time limit for excessive inode use */ + + /* below fields differ in length on 32-bit vs 64-bit architectures */ + unsigned long dqb_btime; /* time limit for excessive disk use */ + unsigned long dqb_itime; /* time limit for excessive inode use */ }; #define v1_dqoff(UID) ((loff_t)((UID) * sizeof (struct v1_disk_dqblk))) -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 08/24] packet: clarify timestamp overflow
The memory mapped packet socket data structure in version 1 through 3 all contain 32-bit second values for the packet time stamps, which makes them suffer from the overflow of time_t in y2038 or y2106 (depending on whether user space interprets the value as signed or unsigned). The implementation uses the deprecated getnstimeofday() function. In order to get rid of that, this changes the code to use ktime_get_real_ts64() as a replacement, documenting the nature of the overflow. As long as the user applications treat the timestamps as unsigned, or only use the difference between timestamps, they are fine, and changing the timestamps to 64-bit wouldn't require a more invasive user space API change. Note: a lot of other APIs suffer from incompatible structures when time_t gets redefined to 64-bit in 32-bit user space, but this one does not. Acked-by: Willem de Bruijn Link: https://lore.kernel.org/lkml/CAF=yd-jomr-gwsr-ebnknspfl46ueg564flfqtcmnem-pre...@mail.gmail.com/T/#u Signed-off-by: Arnd Bergmann --- net/packet/af_packet.c | 27 +-- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 53c1d41fb1c9..60300f3fcddc 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -408,17 +408,17 @@ static int __packet_get_status(const struct packet_sock *po, void *frame) } } -static __u32 tpacket_get_timestamp(struct sk_buff *skb, struct timespec *ts, +static __u32 tpacket_get_timestamp(struct sk_buff *skb, struct timespec64 *ts, unsigned int flags) { struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb); if (shhwtstamps && (flags & SOF_TIMESTAMPING_RAW_HARDWARE) && - ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts)) + ktime_to_timespec64_cond(shhwtstamps->hwtstamp, ts)) return TP_STATUS_TS_RAW_HARDWARE; - if (ktime_to_timespec_cond(skb->tstamp, ts)) + if (ktime_to_timespec64_cond(skb->tstamp, ts)) return TP_STATUS_TS_SOFTWARE; return 0; @@ -428,13 +428,20 @@ static __u32 __packet_set_timestamp(struct packet_sock *po, void *frame, struct sk_buff *skb) { union tpacket_uhdr h; - struct timespec ts; + struct timespec64 ts; __u32 ts_status; if (!(ts_status = tpacket_get_timestamp(skb, , po->tp_tstamp))) return 0; h.raw = frame; + /* +* versions 1 through 3 overflow the timestamps in y2106, since they +* all store the seconds in a 32-bit unsigned integer. +* If we create a version 4, that should have a 64-bit timestamp, +* either 64-bit seconds + 32-bit nanoseconds, or just 64-bit +* nanoseconds. +*/ switch (po->tp_version) { case TPACKET_V1: h.h1->tp_sec = ts.tv_sec; @@ -774,8 +781,8 @@ static void prb_close_block(struct tpacket_kbdq_core *pkc1, * It shouldn't really happen as we don't close empty * blocks. See prb_retire_rx_blk_timer_expired(). */ - struct timespec ts; - getnstimeofday(); + struct timespec64 ts; + ktime_get_real_ts64(); h1->ts_last_pkt.ts_sec = ts.tv_sec; h1->ts_last_pkt.ts_nsec = ts.tv_nsec; } @@ -805,7 +812,7 @@ static void prb_thaw_queue(struct tpacket_kbdq_core *pkc) static void prb_open_block(struct tpacket_kbdq_core *pkc1, struct tpacket_block_desc *pbd1) { - struct timespec ts; + struct timespec64 ts; struct tpacket_hdr_v1 *h1 = >hdr.bh1; smp_rmb(); @@ -818,7 +825,7 @@ static void prb_open_block(struct tpacket_kbdq_core *pkc1, BLOCK_NUM_PKTS(pbd1) = 0; BLOCK_LEN(pbd1) = BLK_PLUS_PRIV(pkc1->blk_sizeof_priv); - getnstimeofday(); + ktime_get_real_ts64(); h1->ts_first_pkt.ts_sec = ts.tv_sec; h1->ts_first_pkt.ts_nsec = ts.tv_nsec; @@ -2168,7 +2175,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, unsigned long status = TP_STATUS_USER; unsigned short macoff, netoff, hdrlen; struct sk_buff *copy_skb = NULL; - struct timespec ts; + struct timespec64 ts; __u32 ts_status; bool is_drop_n_account = false; bool do_vnet = false; @@ -2300,7 +2307,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, skb_copy_bits(skb, 0, h.raw + macoff, snaplen); if (!(ts_status = tpacket_get_timestamp(skb, , po->tp_tstamp))) - getnstimeofday(); + ktime_get_real_ts64(); status |= ts_status; -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 07/24] tsacct: add 64-bit btime field
As there is only a 32-bit ac_btime field in taskstat and we should handle dates after the overflow, add a new field with the same information but 64-bit width that can hold a full time64_t. Signed-off-by: Arnd Bergmann --- include/uapi/linux/taskstats.h | 5 - kernel/tsacct.c| 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/taskstats.h b/include/uapi/linux/taskstats.h index 7d3ea366e93b..ccbd08709321 100644 --- a/include/uapi/linux/taskstats.h +++ b/include/uapi/linux/taskstats.h @@ -34,7 +34,7 @@ */ -#define TASKSTATS_VERSION 9 +#define TASKSTATS_VERSION 10 #define TS_COMM_LEN32 /* should be >= TASK_COMM_LEN * in linux/sched.h */ @@ -169,6 +169,9 @@ struct taskstats { /* Delay waiting for thrashing page */ __u64 thrashing_count; __u64 thrashing_delay_total; + + /* v10: 64-bit btime to avoid overflow */ + __u64 ac_btime64; /* 64-bit begin time */ }; diff --git a/kernel/tsacct.c b/kernel/tsacct.c index ab12616ee6fb..257ffb993ea2 100644 --- a/kernel/tsacct.c +++ b/kernel/tsacct.c @@ -36,6 +36,7 @@ void bacct_add_tsk(struct user_namespace *user_ns, /* Convert to seconds for btime (note y2106 limit) */ btime = ktime_get_real_seconds() - div_u64(delta, USEC_PER_SEC); stats->ac_btime = clamp_t(time64_t, btime, 0, U32_MAX); + stats->ac_btime64 = btime; if (thread_group_leader(tsk)) { stats->ac_exitcode = tsk->exit_code; -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 05/24] um: ubd: use 64-bit time_t where possible
The ubd code suffers from a possible y2038 overflow on 32-bit architectures, both for the cow header and the os_file_modtime() function. Replace time_t with time64_t to extend the ubd_kern side as much as possible. Whether this makes a difference for the user side depends on the host libc implementation that may use either 32-bit or 64-bit time_t. For the cow file format, the header contains an unsigned 32-bit timestamp, which is good until y2106, passing this through a 'long long' gives us a consistent interpretation between 32-bit and 64-bit um kernels. Signed-off-by: Arnd Bergmann --- arch/um/drivers/cow.h | 2 +- arch/um/drivers/cow_user.c | 7 --- arch/um/drivers/ubd_kern.c | 10 +- arch/um/include/shared/os.h | 2 +- arch/um/os-Linux/file.c | 2 +- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/arch/um/drivers/cow.h b/arch/um/drivers/cow.h index 760c507dd5b6..103adac691ed 100644 --- a/arch/um/drivers/cow.h +++ b/arch/um/drivers/cow.h @@ -11,7 +11,7 @@ extern int init_cow_file(int fd, char *cow_file, char *backing_file, extern int file_reader(__u64 offset, char *buf, int len, void *arg); extern int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, __u32 *version_out, - char **backing_file_out, time_t *mtime_out, + char **backing_file_out, long long *mtime_out, unsigned long long *size_out, int *sectorsize_out, __u32 *align_out, int *bitmap_offset_out); diff --git a/arch/um/drivers/cow_user.c b/arch/um/drivers/cow_user.c index 74b0c2686c95..29b46581ddd1 100644 --- a/arch/um/drivers/cow_user.c +++ b/arch/um/drivers/cow_user.c @@ -17,6 +17,7 @@ #define PATH_LEN_V1 256 +/* unsigned time_t works until year 2106 */ typedef __u32 time32_t; struct cow_header_v1 { @@ -197,7 +198,7 @@ int write_cow_header(char *cow_file, int fd, char *backing_file, int sectorsize, int alignment, unsigned long long *size) { struct cow_header_v3 *header; - unsigned long modtime; + long long modtime; int err; err = cow_seek_file(fd, 0); @@ -276,7 +277,7 @@ int file_reader(__u64 offset, char *buf, int len, void *arg) int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, __u32 *version_out, char **backing_file_out, - time_t *mtime_out, unsigned long long *size_out, + long long *mtime_out, unsigned long long *size_out, int *sectorsize_out, __u32 *align_out, int *bitmap_offset_out) { @@ -363,7 +364,7 @@ int read_cow_header(int (*reader)(__u64, char *, int, void *), void *arg, /* * this was used until Dec2005 - 64bits are needed to represent -* 2038+. I.e. we can safely do this truncating cast. +* 2106+. I.e. we can safely do this truncating cast. * * Additionally, we must use be32toh() instead of be64toh(), since * the program used to use the former (tested - I got mtime diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c index 6627d7c30f37..dcabb463e011 100644 --- a/arch/um/drivers/ubd_kern.c +++ b/arch/um/drivers/ubd_kern.c @@ -561,7 +561,7 @@ static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out) __u32 version; __u32 align; char *backing_file; - time_t mtime; + time64_t mtime; unsigned long long size; int sector_size; int bitmap_offset; @@ -600,9 +600,9 @@ static int read_cow_bitmap(int fd, void *buf, int offset, int len) return 0; } -static int backing_file_mismatch(char *file, __u64 size, time_t mtime) +static int backing_file_mismatch(char *file, __u64 size, time64_t mtime) { - unsigned long modtime; + time64_t modtime; unsigned long long actual; int err; @@ -628,7 +628,7 @@ static int backing_file_mismatch(char *file, __u64 size, time_t mtime) return -EINVAL; } if (modtime != mtime) { - printk(KERN_ERR "mtime mismatch (%ld vs %ld) of COW header vs " + printk(KERN_ERR "mtime mismatch (%lld vs %lld) of COW header vs " "backing file\n", mtime, modtime); return -EINVAL; } @@ -671,7 +671,7 @@ static int open_ubd_file(char *file, struct openflags *openflags, int shared, unsigned long *bitmap_len_out, int *data_offset_out, int *create_cow_out) { - time_t mtime; + time64_t mtime; unsigned long long size; __u32 version, align; char *backing_file; diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h index 506bcd1bca68..0f30204b6afa 100644 --- a/arch/um/include/shared/os.h +++
[Y2038] [PATCH v2 06/24] acct: stop using get_seconds()
In 'struct acct', 'struct acct_v3', and 'struct taskstats' we have a 32-bit 'ac_btime' field containing an absolute time value, which will overflow in year 2106. There are two possible ways to deal with it: a) let it overflow and have user space code deal with reconstructing the data based on the current time, or b) truncate the times based on the range of the u32 type. Neither of them solves the actual problem. Pick the second one to best document what the issue is, and have someone fix it in a future version. Signed-off-by: Arnd Bergmann --- include/uapi/linux/acct.h | 2 ++ include/uapi/linux/taskstats.h | 1 + kernel/acct.c | 4 +++- kernel/tsacct.c| 8 +--- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/include/uapi/linux/acct.h b/include/uapi/linux/acct.h index 0e72172cd23a..985b89068591 100644 --- a/include/uapi/linux/acct.h +++ b/include/uapi/linux/acct.h @@ -49,6 +49,7 @@ struct acct __u16 ac_uid16; /* LSB of Real User ID */ __u16 ac_gid16; /* LSB of Real Group ID */ __u16 ac_tty; /* Control Terminal */ + /* __u32 range means times from 1970 to 2106 */ __u32 ac_btime; /* Process Creation Time */ comp_t ac_utime; /* User Time */ comp_t ac_stime; /* System Time */ @@ -81,6 +82,7 @@ struct acct_v3 __u32 ac_gid; /* Real Group ID */ __u32 ac_pid; /* Process ID */ __u32 ac_ppid;/* Parent Process ID */ + /* __u32 range means times from 1970 to 2106 */ __u32 ac_btime; /* Process Creation Time */ #ifdef __KERNEL__ __u32 ac_etime; /* Elapsed Time */ diff --git a/include/uapi/linux/taskstats.h b/include/uapi/linux/taskstats.h index 5e8ca16a9079..7d3ea366e93b 100644 --- a/include/uapi/linux/taskstats.h +++ b/include/uapi/linux/taskstats.h @@ -112,6 +112,7 @@ struct taskstats { __u32 ac_gid; /* Group ID */ __u32 ac_pid; /* Process ID */ __u32 ac_ppid;/* Parent process ID */ + /* __u32 range means times from 1970 to 2106 */ __u32 ac_btime; /* Begin time [sec since 1970] */ __u64 ac_etime __attribute__((aligned(8))); /* Elapsed time [usec] */ diff --git a/kernel/acct.c b/kernel/acct.c index 81f9831a7859..11ff4a596d6b 100644 --- a/kernel/acct.c +++ b/kernel/acct.c @@ -416,6 +416,7 @@ static void fill_ac(acct_t *ac) { struct pacct_struct *pacct = >signal->pacct; u64 elapsed, run_time; + time64_t btime; struct tty_struct *tty; /* @@ -448,7 +449,8 @@ static void fill_ac(acct_t *ac) } #endif do_div(elapsed, AHZ); - ac->ac_btime = get_seconds() - elapsed; + btime = ktime_get_real_seconds() - elapsed; + ac->ac_btime = clamp_t(time64_t, btime, 0, U32_MAX); #if ACCT_VERSION==2 ac->ac_ahz = AHZ; #endif diff --git a/kernel/tsacct.c b/kernel/tsacct.c index 7be3e7530841..ab12616ee6fb 100644 --- a/kernel/tsacct.c +++ b/kernel/tsacct.c @@ -24,6 +24,7 @@ void bacct_add_tsk(struct user_namespace *user_ns, const struct cred *tcred; u64 utime, stime, utimescaled, stimescaled; u64 delta; + time64_t btime; BUILD_BUG_ON(TS_COMM_LEN < TASK_COMM_LEN); @@ -32,9 +33,10 @@ void bacct_add_tsk(struct user_namespace *user_ns, /* Convert to micro seconds */ do_div(delta, NSEC_PER_USEC); stats->ac_etime = delta; - /* Convert to seconds for btime */ - do_div(delta, USEC_PER_SEC); - stats->ac_btime = get_seconds() - delta; + /* Convert to seconds for btime (note y2106 limit) */ + btime = ktime_get_real_seconds() - div_u64(delta, USEC_PER_SEC); + stats->ac_btime = clamp_t(time64_t, btime, 0, U32_MAX); + if (thread_group_leader(tsk)) { stats->ac_exitcode = tsk->exit_code; if (tsk->flags & PF_FORKNOEXEC) -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 04/24] xtensa: ISS: avoid struct timeval
'struct timeval' will get removed from the kernel, change the one user in arch/xtensa to avoid referencing it, by using a fixed-length array instead. Acked-by: Max Filippov Signed-off-by: Arnd Bergmann --- arch/xtensa/platforms/iss/include/platform/simcall.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/xtensa/platforms/iss/include/platform/simcall.h b/arch/xtensa/platforms/iss/include/platform/simcall.h index 2ba45858e50a..4e2a48380dbf 100644 --- a/arch/xtensa/platforms/iss/include/platform/simcall.h +++ b/arch/xtensa/platforms/iss/include/platform/simcall.h @@ -113,9 +113,9 @@ static inline int simc_write(int fd, const void *buf, size_t count) static inline int simc_poll(int fd) { - struct timeval tv = { .tv_sec = 0, .tv_usec = 0 }; + long timeval[2] = { 0, 0 }; - return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)); + return __simc(SYS_select_one, fd, XTISS_SELECT_ONE_READ, (int)); } static inline int simc_lseek(int fd, uint32_t off, int whence) -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 00/24] drivers, fs: y2038 updates
These are updates to devidce drivers and file systems that for some reason or another were not included in the kernel in the previous y2038 series. I've gone through all users of time_t again to make sure the kernel is in a long-term maintainable state. Posting these as a series for better organization, but each change here is applicable standalone. Please merge, review, ack/nack etc as you see fit. I will add these to my y2038 branch [1] for linux-next, but can keep rebasing for feedback and to remove any patches that get picked up by a maintainer. Changes since v1 [2]: - Add Acks I received - Rebase to v5.5-rc1, droping patches that got merged already - Add NFS, XFS and the final three patches from another series - Rewrite etnaviv patches Arnd [1] https://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground.git/log/?h=y2038 [2] https://lore.kernel.org/lkml/20191108213257.3097633-1-a...@arndb.de/ Arnd Bergmann (24): Input: input_event: fix struct padding on sparc64 fat: use prandom_u32() for i_generation dlm: use SO_SNDTIMEO_NEW instead of SO_SNDTIMEO_OLD xtensa: ISS: avoid struct timeval um: ubd: use 64-bit time_t where possible acct: stop using get_seconds() tsacct: add 64-bit btime field packet: clarify timestamp overflow quota: avoid time_t in v1_disk_dqblk definition hostfs: pass 64-bit timestamps to/from user space hfs/hfsplus: use 64-bit inode timestamps drm/msm: avoid using 'timespec' drm/etnaviv: reject timeouts with tv_nsec >= NSEC_PER_SEC drm/etnaviv: avoid deprecated timespec sunrpc: convert to time64_t for expiry nfs: use time64_t internally nfs: fix timstamp debug prints nfs: fscache: use timespec64 in inode auxdata xfs: rename compat_time_t to old_time32_t xfs: disallow broken ioctls without compat-32-bit-time xfs: quota: move to time64_t interfaces y2038: remove obsolete jiffies conversion functions y2038: rename itimerval to __kernel_old_itimerval y2038: sparc: remove use of struct timex arch/sparc/kernel/sys_sparc_64.c | 29 +- arch/um/drivers/cow.h | 2 +- arch/um/drivers/cow_user.c| 7 ++- arch/um/drivers/ubd_kern.c| 10 ++-- arch/um/include/shared/os.h | 2 +- arch/um/os-Linux/file.c | 2 +- .../platforms/iss/include/platform/simcall.h | 4 +- drivers/gpu/drm/etnaviv/etnaviv_drv.c | 20 --- drivers/gpu/drm/etnaviv/etnaviv_drv.h | 11 ++-- drivers/gpu/drm/etnaviv/etnaviv_gem.c | 4 +- drivers/gpu/drm/etnaviv/etnaviv_gem.h | 2 +- drivers/gpu/drm/etnaviv/etnaviv_gpu.c | 5 +- drivers/gpu/drm/etnaviv/etnaviv_gpu.h | 5 +- drivers/gpu/drm/msm/msm_drv.h | 3 +- drivers/input/evdev.c | 14 ++--- drivers/input/misc/uinput.c | 14 +++-- fs/dlm/lowcomms.c | 6 +- fs/fat/inode.c| 3 +- fs/hfs/hfs_fs.h | 28 +++-- fs/hfs/inode.c| 4 +- fs/hfsplus/hfsplus_fs.h | 28 +++-- fs/hfsplus/inode.c| 12 ++-- fs/hostfs/hostfs.h| 22 --- fs/hostfs/hostfs_kern.c | 15 +++-- fs/nfs/fscache-index.c| 6 +- fs/nfs/fscache.c | 18 -- fs/nfs/fscache.h | 8 ++- fs/nfs/nfs4xdr.c | 10 ++-- fs/quota/quotaio_v1.h | 6 +- fs/xfs/xfs_dquot.c| 6 +- fs/xfs/xfs_ioctl.c| 26 + fs/xfs/xfs_ioctl32.c | 2 +- fs/xfs/xfs_ioctl32.h | 2 +- fs/xfs/xfs_qm.h | 6 +- fs/xfs/xfs_quotaops.c | 6 +- fs/xfs/xfs_trans_dquot.c | 8 ++- include/linux/jiffies.h | 20 --- include/linux/sunrpc/cache.h | 42 -- include/linux/sunrpc/gss_api.h| 4 +- include/linux/sunrpc/gss_krb5.h | 2 +- include/linux/syscalls.h | 9 ++- include/uapi/linux/acct.h | 2 + include/uapi/linux/input.h| 1 + include/uapi/linux/taskstats.h| 6 +- include/uapi/linux/time_types.h | 5 ++ include/uapi/linux/timex.h| 2 + kernel/acct.c | 4 +- kernel/time/itimer.c | 18 +++--- kernel/time/time.c| 58 ++- kernel/tsacct.c | 9 ++- net/packet/af_packet.c| 27 + net/sunrpc/auth_gss/gss_krb5_mech.c | 12 +++-
[Y2038] [PATCH v2 03/24] dlm: use SO_SNDTIMEO_NEW instead of SO_SNDTIMEO_OLD
Eliminate one more use of 'struct timeval' from the kernel so we can eventually remove the definition as well. The kernel supports the new format with a 64-bit time_t version of timeval here, so use that instead of the old timeval. Acked-by: Deepa Dinamani Signed-off-by: Arnd Bergmann --- fs/dlm/lowcomms.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c index 3951d39b9b75..cdfaf4f0e11a 100644 --- a/fs/dlm/lowcomms.c +++ b/fs/dlm/lowcomms.c @@ -1035,7 +1035,7 @@ static void sctp_connect_to_sock(struct connection *con) int result; int addr_len; struct socket *sock; - struct timeval tv = { .tv_sec = 5, .tv_usec = 0 }; + struct __kernel_sock_timeval tv = { .tv_sec = 5, .tv_usec = 0 }; if (con->nodeid == 0) { log_print("attempt to connect sock 0 foiled"); @@ -1087,12 +1087,12 @@ static void sctp_connect_to_sock(struct connection *con) * since O_NONBLOCK argument in connect() function does not work here, * then, we should restore the default value of this attribute. */ - kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO_OLD, (char *), + kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO_NEW, (char *), sizeof(tv)); result = sock->ops->connect(sock, (struct sockaddr *), addr_len, 0); memset(, 0, sizeof(tv)); - kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO_OLD, (char *), + kernel_setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO_NEW, (char *), sizeof(tv)); if (result == -EINPROGRESS) -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 01/24] Input: input_event: fix struct padding on sparc64
Going through all uses of timeval, I noticed that we screwed up input_event in the previous attempts to fix it: The time fields now match between kernel and user space, but all following fields are in the wrong place. Add the required padding that is implied by the glibc timeval definition to fix the layout, and use a struct initializer to avoid leaking kernel stack data. Cc: sparcli...@vger.kernel.org Cc: "David S. Miller" Fixes: 141e5dcaa735 ("Input: input_event - fix the CONFIG_SPARC64 mixup") Fixes: 2e746942ebac ("Input: input_event - provide override for sparc64") Signed-off-by: Arnd Bergmann --- drivers/input/evdev.c | 14 +++--- drivers/input/misc/uinput.c | 14 +- include/uapi/linux/input.h | 1 + 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index d7dd6fcf2db0..f918fca9ada3 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -224,13 +224,13 @@ static void __pass_event(struct evdev_client *client, */ client->tail = (client->head - 2) & (client->bufsize - 1); - client->buffer[client->tail].input_event_sec = - event->input_event_sec; - client->buffer[client->tail].input_event_usec = - event->input_event_usec; - client->buffer[client->tail].type = EV_SYN; - client->buffer[client->tail].code = SYN_DROPPED; - client->buffer[client->tail].value = 0; + client->buffer[client->tail] = (struct input_event) { + .input_event_sec = event->input_event_sec, + .input_event_usec = event->input_event_usec, + .type = EV_SYN, + .code = SYN_DROPPED, + .value = 0, + }; client->packet_head = client->tail; } diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index fd253781be71..2dabbe47d43e 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -74,12 +74,16 @@ static int uinput_dev_event(struct input_dev *dev, struct uinput_device*udev = input_get_drvdata(dev); struct timespec64 ts; - udev->buff[udev->head].type = type; - udev->buff[udev->head].code = code; - udev->buff[udev->head].value = value; ktime_get_ts64(); - udev->buff[udev->head].input_event_sec = ts.tv_sec; - udev->buff[udev->head].input_event_usec = ts.tv_nsec / NSEC_PER_USEC; + + udev->buff[udev->head] = (struct input_event) { + .input_event_sec = ts.tv_sec, + .input_event_usec = ts.tv_nsec / NSEC_PER_USEC, + .type = type, + .code = code, + .value = value, + }; + udev->head = (udev->head + 1) % UINPUT_BUFFER_SIZE; wake_up_interruptible(>waitq); diff --git a/include/uapi/linux/input.h b/include/uapi/linux/input.h index f056b2a00d5c..9a61c28ed3ae 100644 --- a/include/uapi/linux/input.h +++ b/include/uapi/linux/input.h @@ -34,6 +34,7 @@ struct input_event { __kernel_ulong_t __sec; #if defined(__sparc__) && defined(__arch64__) unsigned int __usec; + unsigned int __pad; #else __kernel_ulong_t __usec; #endif -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 02/24] fat: use prandom_u32() for i_generation
Similar to commit 46c9a946d766 ("shmem: use monotonic time for i_generation") we should not use the deprecated get_seconds() interface for i_generation. prandom_u32() is the replacement used in other file systems. Signed-off-by: Arnd Bergmann --- fs/fat/inode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 5f04c5c810fb..594b05ae16c9 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include "fat.h" @@ -521,7 +522,7 @@ int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) inode->i_uid = sbi->options.fs_uid; inode->i_gid = sbi->options.fs_gid; inode_inc_iversion(inode); - inode->i_generation = get_seconds(); + inode->i_generation = prandom_u32(); if ((de->attr & ATTR_DIR) && !IS_FREE(de->name)) { inode->i_generation &= ~1; -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [PATCH v2 10/12] nfsd: use boottime for lease expiry alculation
> On Dec 13, 2019, at 11:40 AM, Arnd Bergmann wrote: > > On Fri, Dec 13, 2019 at 5:26 PM Chuck Lever wrote: >>> On Dec 13, 2019, at 9:10 AM, Arnd Bergmann wrote: > >>> diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c >>> index 24534db87e86..508d7c6c00b5 100644 >>> --- a/fs/nfsd/nfs4callback.c >>> +++ b/fs/nfsd/nfs4callback.c >>> @@ -823,7 +823,12 @@ static const struct rpc_program cb_program = { >>> static int max_cb_time(struct net *net) >>> { >>> struct nfsd_net *nn = net_generic(net, nfsd_net_id); >>> - return max(nn->nfsd4_lease/10, (time_t)1) * HZ; >>> + >>> + /* nfsd4_lease is set to at most one hour */ >>> + if (WARN_ON_ONCE(nn->nfsd4_lease > 3600)) >>> + return 360 * HZ; >> >> Why is the WARN_ON_ONCE added here? Is it really necessary? > > This is to ensure the kernel doesn't change to a larger limit that > requires a 64-bit division on a 32-bit architecture. > > With the old code, dividing by 10 was always fast as > nn->nfsd4_lease was the size of an integer register. Now it > is 64 bit wide, and I check that truncating it to 32 bit again > is safe. OK. That comment should state this reason rather than just repeating what the code does. ;-) >> (Otherwise these all LGTM). > > Thanks for taking a look. > > Arnd -- Chuck Lever ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [PATCH v2 10/12] nfsd: use boottime for lease expiry alculation
On Fri, Dec 13, 2019 at 5:26 PM Chuck Lever wrote: > > On Dec 13, 2019, at 9:10 AM, Arnd Bergmann wrote: > > diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c > > index 24534db87e86..508d7c6c00b5 100644 > > --- a/fs/nfsd/nfs4callback.c > > +++ b/fs/nfsd/nfs4callback.c > > @@ -823,7 +823,12 @@ static const struct rpc_program cb_program = { > > static int max_cb_time(struct net *net) > > { > > struct nfsd_net *nn = net_generic(net, nfsd_net_id); > > - return max(nn->nfsd4_lease/10, (time_t)1) * HZ; > > + > > + /* nfsd4_lease is set to at most one hour */ > > + if (WARN_ON_ONCE(nn->nfsd4_lease > 3600)) > > + return 360 * HZ; > > Why is the WARN_ON_ONCE added here? Is it really necessary? This is to ensure the kernel doesn't change to a larger limit that requires a 64-bit division on a 32-bit architecture. With the old code, dividing by 10 was always fast as nn->nfsd4_lease was the size of an integer register. Now it is 64 bit wide, and I check that truncating it to 32 bit again is safe. > (Otherwise these all LGTM). Thanks for taking a look. Arnd ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [PATCH v5 6/8] media: v4l2-core: fix v4l2_buffer handling for time64 ABI
On Fri, Dec 13, 2019 at 4:33 PM Hans Verkuil wrote: > On 12/13/19 4:08 PM, Arnd Bergmann wrote: > > On Thu, Dec 12, 2019 at 4:43 PM Hans Verkuil wrote: > > > > I've heard good things about the prebuilt toolchains from http://musl.cc/. > > These seems to come with a libstdc++, but I have not tried that myself. > > I'll see if I can give those a spin, but if I can't get it to work quickly, > then I don't plan on spending much time on it. Ok, sounds good. The way the series is structured, I tried to have the time64 ioctls use the existing code, while adding new time32 ioctls to ensure that we catch the bugs in the new time32 version through testing, and have fewer bugs to start with in the time64 version. Arnd ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
Re: [Y2038] [PATCH v5 6/8] media: v4l2-core: fix v4l2_buffer handling for time64 ABI
On 12/13/19 4:08 PM, Arnd Bergmann wrote: > On Thu, Dec 12, 2019 at 4:43 PM Hans Verkuil wrote: >> >> On 11/26/19 5:18 PM, Arnd Bergmann wrote: >>> >>> switch (cmd) { >>> +#ifdef COMPAT_32BIT_TIME >> >> COMPAT_32BIT_TIME -> CONFIG_COMPAT_32BIT_TIME > > Fixed. > >>> + *vb = (struct v4l2_buffer) { >>> + .index = vb32.index, >>> + .type = vb32.type, >>> + .bytesused = vb32.bytesused, >>> + .flags = vb32.flags, >>> + .field = vb32.field, >>> + .timestamp.tv_sec = vb32.timestamp.tv_sec, >>> + .timestamp.tv_usec = vb32.timestamp.tv_usec, >>> + .timecode = vb32.timecode, >> >> You forgot to copy sequence. >> >>> + .memory = vb32.memory, >>> + .m.userptr = vb32.m.usercopy, >> >> usercopy -> userptr > > Fixed. > >>> + .length = vb32.length, >>> + .request_fd = vb32.request_fd, >>> + }; >>> + >>> + if (cmd == VIDIOC_QUERYBUF_TIME32) >>> + memset(>length, 0, sizeof(*vb) - >>> +offsetof(struct v4l2_buffer, length)); >> >> It's from the field AFTER vb->length that this needs to be zeroed. It's best >> to >> use the CLEAR_AFTER_FIELD macro here. > > I'm a bit lost about this one: the fields that are not explicitly > uninitialized here are already set to zero by the assignment > above. Should this simply be a > > if (cmd == VIDIOC_QUERYBUF_TIME32) >vb->request_fd = 0; Yes, you are correct. That's much simpler. > > then? I don't remember where that memset() originally came > from or why request_fd has to be cleared here. > >>> @@ -3100,6 +3141,30 @@ static int video_put_user(void __user *arg, void >>> *parg, unsigned int cmd) >>> return -EFAULT; >>> break; >>> } >>> + case VIDIOC_QUERYBUF_TIME32: >>> + case VIDIOC_QBUF_TIME32: >>> + case VIDIOC_DQBUF_TIME32: >>> + case VIDIOC_PREPARE_BUF_TIME32: { >>> + struct v4l2_buffer *vb = parg; >>> + struct v4l2_buffer_time32 vb32 = { >>> + .index = vb->index, >>> + .type = vb->type, >>> + .bytesused = vb->bytesused, >>> + .flags = vb->flags, >>> + .field = vb->field, >>> + .timestamp.tv_sec = vb->timestamp.tv_sec, >>> + .timestamp.tv_usec = vb->timestamp.tv_usec, >>> + .timecode = vb->timecode, >> >> You forgot to copy sequence. > > Fixed. > >> With these changes this patch series passed both the 64 and 32 bit compliance >> tests (in fact, all the issues mentioned above were found with these >> compliance >> tests). > > Yay compliance tests! > >> I am unable to test with musl since v4l2-ctl and v4l2-compliance are C++ >> programs, >> and there doesn't appear to be an easy way to compile a C++ program with >> musl. >> >> If you happen to have a test environment where you can compile C++ with musl, >> then let me know and I can give instructions on how to run the compliance >> tests. >> >> If you can't test that, then I can merge this regardless, and hope for the >> best >> once the Y2038 fixes end up in glibc. But ideally I'd like to have this >> tested. > > I've heard good things about the prebuilt toolchains from http://musl.cc/. > These seems to come with a libstdc++, but I have not tried that myself. I'll see if I can give those a spin, but if I can't get it to work quickly, then I don't plan on spending much time on it. Regards, Hans > > I've folded the change below into this patch in my y2038-v4l2-v6 branch > but have not been able to update the copy on git.kernel.org yet because of > server-side issues today. > > Arnd > > 8<- > diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c > b/drivers/media/v4l2-core/v4l2-ioctl.c > index c416870a3166..667225712343 100644 > --- a/drivers/media/v4l2-core/v4l2-ioctl.c > +++ b/drivers/media/v4l2-core/v4l2-ioctl.c > @@ -3055,7 +3055,7 @@ static int video_get_user(void __user *arg, void > *parg, unsigned int cmd, > } > > switch (cmd) { > -#ifdef COMPAT_32BIT_TIME > +#ifdef CONFIG_COMPAT_32BIT_TIME > case VIDIOC_QUERYBUF_TIME32: > case VIDIOC_QBUF_TIME32: > case VIDIOC_DQBUF_TIME32: > @@ -3075,15 +3075,15 @@ static int video_get_user(void __user *arg, > void *parg, unsigned int cmd, > .timestamp.tv_sec = vb32.timestamp.tv_sec, > .timestamp.tv_usec = vb32.timestamp.tv_usec, > .timecode = vb32.timecode, > +
Re: [Y2038] [PATCH v5 6/8] media: v4l2-core: fix v4l2_buffer handling for time64 ABI
On Thu, Dec 12, 2019 at 4:43 PM Hans Verkuil wrote: > > On 11/26/19 5:18 PM, Arnd Bergmann wrote: > > > > switch (cmd) { > > +#ifdef COMPAT_32BIT_TIME > > COMPAT_32BIT_TIME -> CONFIG_COMPAT_32BIT_TIME Fixed. > > + *vb = (struct v4l2_buffer) { > > + .index = vb32.index, > > + .type = vb32.type, > > + .bytesused = vb32.bytesused, > > + .flags = vb32.flags, > > + .field = vb32.field, > > + .timestamp.tv_sec = vb32.timestamp.tv_sec, > > + .timestamp.tv_usec = vb32.timestamp.tv_usec, > > + .timecode = vb32.timecode, > > You forgot to copy sequence. > > > + .memory = vb32.memory, > > + .m.userptr = vb32.m.usercopy, > > usercopy -> userptr Fixed. > > + .length = vb32.length, > > + .request_fd = vb32.request_fd, > > + }; > > + > > + if (cmd == VIDIOC_QUERYBUF_TIME32) > > + memset(>length, 0, sizeof(*vb) - > > +offsetof(struct v4l2_buffer, length)); > > It's from the field AFTER vb->length that this needs to be zeroed. It's best > to > use the CLEAR_AFTER_FIELD macro here. I'm a bit lost about this one: the fields that are not explicitly uninitialized here are already set to zero by the assignment above. Should this simply be a if (cmd == VIDIOC_QUERYBUF_TIME32) vb->request_fd = 0; then? I don't remember where that memset() originally came from or why request_fd has to be cleared here. > > @@ -3100,6 +3141,30 @@ static int video_put_user(void __user *arg, void > > *parg, unsigned int cmd) > > return -EFAULT; > > break; > > } > > + case VIDIOC_QUERYBUF_TIME32: > > + case VIDIOC_QBUF_TIME32: > > + case VIDIOC_DQBUF_TIME32: > > + case VIDIOC_PREPARE_BUF_TIME32: { > > + struct v4l2_buffer *vb = parg; > > + struct v4l2_buffer_time32 vb32 = { > > + .index = vb->index, > > + .type = vb->type, > > + .bytesused = vb->bytesused, > > + .flags = vb->flags, > > + .field = vb->field, > > + .timestamp.tv_sec = vb->timestamp.tv_sec, > > + .timestamp.tv_usec = vb->timestamp.tv_usec, > > + .timecode = vb->timecode, > > You forgot to copy sequence. Fixed. > With these changes this patch series passed both the 64 and 32 bit compliance > tests (in fact, all the issues mentioned above were found with these > compliance > tests). Yay compliance tests! > I am unable to test with musl since v4l2-ctl and v4l2-compliance are C++ > programs, > and there doesn't appear to be an easy way to compile a C++ program with musl. > > If you happen to have a test environment where you can compile C++ with musl, > then let me know and I can give instructions on how to run the compliance > tests. > > If you can't test that, then I can merge this regardless, and hope for the > best > once the Y2038 fixes end up in glibc. But ideally I'd like to have this > tested. I've heard good things about the prebuilt toolchains from http://musl.cc/. These seems to come with a libstdc++, but I have not tried that myself. I've folded the change below into this patch in my y2038-v4l2-v6 branch but have not been able to update the copy on git.kernel.org yet because of server-side issues today. Arnd 8<- diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c index c416870a3166..667225712343 100644 --- a/drivers/media/v4l2-core/v4l2-ioctl.c +++ b/drivers/media/v4l2-core/v4l2-ioctl.c @@ -3055,7 +3055,7 @@ static int video_get_user(void __user *arg, void *parg, unsigned int cmd, } switch (cmd) { -#ifdef COMPAT_32BIT_TIME +#ifdef CONFIG_COMPAT_32BIT_TIME case VIDIOC_QUERYBUF_TIME32: case VIDIOC_QBUF_TIME32: case VIDIOC_DQBUF_TIME32: @@ -3075,15 +3075,15 @@ static int video_get_user(void __user *arg, void *parg, unsigned int cmd, .timestamp.tv_sec = vb32.timestamp.tv_sec, .timestamp.tv_usec = vb32.timestamp.tv_usec, .timecode = vb32.timecode, + .sequence = vb32.sequence, .memory = vb32.memory, - .m.userptr = vb32.m.usercopy, + .m.userptr = vb32.m.userptr, .length = vb32.length, .request_fd = vb32.request_fd, }; if (cmd ==
[Y2038] [PATCH v2 00/12] nfsd: avoid 32-bit time_t
Hi Bruce, Chuck, NFSd is one of the last areas of the kernel that is not y2038 safe yet, this series addresses the remaining issues here. I did not get any comments for the first version I posted [1], and I hope this just means that everything was fine and you plan to merge this soon ;-) I uploaded a git branch to [2] for testing. Please review and merge for linux-5.6 so we can remove the 32-bit time handling from that release. Arnd Changes from v1: - separate nfs and nfsd, as most of the nfs changes are merged now - rebase to v5.5 [1] https://lore.kernel.org/lkml/2019201639.2240623-1-a...@arndb.de/ [2] https://git.kernel.org/pub/scm/linux/kernel/git/arnd/playground.git/log/?h=y2038-nfsd Arnd Bergmann (12): nfsd: use ktime_get_seconds() for timestamps nfsd: print 64-bit timestamps in client_info_show nfsd: handle nfs3 timestamps as unsigned nfsd: use timespec64 in encode_time_delta nfsd: make 'boot_time' 64-bit wide nfsd: pass a 64-bit guardtime to nfsd_setattr() nfsd: use time64_t in nfsd_proc_setattr() check nfsd: fix delay timer on 32-bit architectures nfsd: fix jiffies/time_t mixup in LRU list nfsd: use boottime for lease expiry alculation nfsd: use ktime_get_real_seconds() in nfs4_verifier nfsd: remove nfs4_reset_lease() declarations fs/nfsd/netns.h| 6 ++-- fs/nfsd/nfs3xdr.c | 20 + fs/nfsd/nfs4callback.c | 7 - fs/nfsd/nfs4layouts.c | 2 +- fs/nfsd/nfs4proc.c | 2 +- fs/nfsd/nfs4recover.c | 8 ++--- fs/nfsd/nfs4state.c| 68 -- fs/nfsd/nfs4xdr.c | 4 +-- fs/nfsd/nfsctl.c | 6 ++-- fs/nfsd/nfsd.h | 2 -- fs/nfsd/nfsfh.h| 4 +-- fs/nfsd/nfsproc.c | 6 ++-- fs/nfsd/state.h| 10 +++ fs/nfsd/vfs.c | 4 +-- fs/nfsd/vfs.h | 2 +- fs/nfsd/xdr3.h | 2 +- 16 files changed, 74 insertions(+), 79 deletions(-) -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 10/12] nfsd: use boottime for lease expiry alculation
A couple of time_t variables are only used to track the state of the lease time and its expiration. The code correctly uses the 'time_after()' macro to make this work on 32-bit architectures even beyond year 2038, but the get_seconds() function and the time_t type itself are deprecated as they behave inconsistently between 32-bit and 64-bit architectures and often lead to code that is not y2038 safe. As a minor issue, using get_seconds() leads to problems with concurrent settimeofday() or clock_settime() calls, in the worst case timeout never triggering after the time has been set backwards. Change nfsd to use time64_t and ktime_get_boottime_seconds() here. This is clearly excessive, as boottime by itself means we never go beyond 32 bits, but it does mean we handle this correctly and consistently without having to worry about corner cases and should be no more expensive than the previous implementation on 64-bit architectures. The max_cb_time() function gets changed in order to avoid an expensive 64-bit division operation, but as the lease time is at most one hour, there is no change in behavior. Signed-off-by: Arnd Bergmann --- fs/nfsd/netns.h| 4 ++-- fs/nfsd/nfs4callback.c | 7 ++- fs/nfsd/nfs4state.c| 41 +++-- fs/nfsd/nfsctl.c | 6 +++--- fs/nfsd/state.h| 8 5 files changed, 34 insertions(+), 32 deletions(-) diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h index 29bbe28eda53..2baf32311e00 100644 --- a/fs/nfsd/netns.h +++ b/fs/nfsd/netns.h @@ -92,8 +92,8 @@ struct nfsd_net { bool in_grace; const struct nfsd4_client_tracking_ops *client_tracking_ops; - time_t nfsd4_lease; - time_t nfsd4_grace; + time64_t nfsd4_lease; + time64_t nfsd4_grace; bool somebody_reclaimed; bool track_reclaim_completes; diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c index 24534db87e86..508d7c6c00b5 100644 --- a/fs/nfsd/nfs4callback.c +++ b/fs/nfsd/nfs4callback.c @@ -823,7 +823,12 @@ static const struct rpc_program cb_program = { static int max_cb_time(struct net *net) { struct nfsd_net *nn = net_generic(net, nfsd_net_id); - return max(nn->nfsd4_lease/10, (time_t)1) * HZ; + + /* nfsd4_lease is set to at most one hour */ + if (WARN_ON_ONCE(nn->nfsd4_lease > 3600)) + return 360 * HZ; + + return max(((u32)nn->nfsd4_lease)/10, 1u) * HZ; } static struct workqueue_struct *callback_wq; diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 9a063c4b4460..6afdef63f6d7 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -170,7 +170,7 @@ renew_client_locked(struct nfs4_client *clp) clp->cl_clientid.cl_boot, clp->cl_clientid.cl_id); list_move_tail(>cl_lru, >client_lru); - clp->cl_time = get_seconds(); + clp->cl_time = ktime_get_boottime_seconds(); } static void put_client_renew_locked(struct nfs4_client *clp) @@ -2612,7 +2612,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name, gen_clid(clp, nn); kref_init(>cl_nfsdfs.cl_ref); nfsd4_init_cb(>cl_cb_null, clp, NULL, NFSPROC4_CLNT_CB_NULL); - clp->cl_time = get_seconds(); + clp->cl_time = ktime_get_boottime_seconds(); clear_bit(0, >cl_cb_slot_busy); copy_verf(clp, verf); memcpy(>cl_addr, sa, sizeof(struct sockaddr_storage)); @@ -4282,7 +4282,7 @@ move_to_close_lru(struct nfs4_ol_stateid *s, struct net *net) last = oo->oo_last_closed_stid; oo->oo_last_closed_stid = s; list_move_tail(>oo_close_lru, >close_lru); - oo->oo_time = get_seconds(); + oo->oo_time = ktime_get_boottime_seconds(); spin_unlock(>client_lock); if (last) nfs4_put_stid(>st_stid); @@ -4377,7 +4377,7 @@ static void nfsd4_cb_recall_prepare(struct nfsd4_callback *cb) */ spin_lock(_lock); if (dp->dl_time == 0) { - dp->dl_time = get_seconds(); + dp->dl_time = ktime_get_boottime_seconds(); list_add_tail(>dl_recall_lru, >del_recall_lru); } spin_unlock(_lock); @@ -5183,9 +5183,8 @@ nfsd4_end_grace(struct nfsd_net *nn) */ static bool clients_still_reclaiming(struct nfsd_net *nn) { - unsigned long now = (unsigned long) ktime_get_real_seconds(); - unsigned long double_grace_period_end = (unsigned long)nn->boot_time + - 2 * (unsigned long)nn->nfsd4_lease; + time64_t double_grace_period_end = nn->boot_time + + 2 * nn->nfsd4_lease; if (nn->track_reclaim_completes && atomic_read(>nr_reclaim_complete) == @@ -5198,12 +5197,12 @@ static bool clients_still_reclaiming(struct nfsd_net *nn) * If we've given them *two* lease times to reclaim, and they're * still not done, give
[Y2038] [PATCH v2 05/12] nfsd: make 'boot_time' 64-bit wide
The local boot time variable gets truncated to time_t at the moment, which can lead to slightly odd behavior on 32-bit architectures. Use ktime_get_real_seconds() instead of get_seconds() to always get a 64-bit result, and keep it that way wherever possible. It still gets truncated in a few places: - When assigning to cl_clientid.cl_boot, this is already documented and is only used as a unique identifier. - In clients_still_reclaiming(), the truncation is to 'unsigned long' in order to use the 'time_before() helper. Signed-off-by: Arnd Bergmann --- fs/nfsd/netns.h | 2 +- fs/nfsd/nfs4recover.c | 8 fs/nfsd/nfs4state.c | 14 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h index 9a4ef815fb8c..29bbe28eda53 100644 --- a/fs/nfsd/netns.h +++ b/fs/nfsd/netns.h @@ -40,7 +40,7 @@ struct nfsd_net { struct lock_manager nfsd4_manager; bool grace_ended; - time_t boot_time; + time64_t boot_time; /* internal mount of the "nfsd" pseudofilesystem: */ struct vfsmount *nfsd_mnt; diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 2481e7662128..a8fb18609146 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -1445,7 +1445,7 @@ nfsd4_cld_grace_done_v0(struct nfsd_net *nn) } cup->cu_u.cu_msg.cm_cmd = Cld_GraceDone; - cup->cu_u.cu_msg.cm_u.cm_gracetime = (int64_t)nn->boot_time; + cup->cu_u.cu_msg.cm_u.cm_gracetime = nn->boot_time; ret = cld_pipe_upcall(cn->cn_pipe, >cu_u.cu_msg); if (!ret) ret = cup->cu_u.cu_msg.cm_status; @@ -1782,7 +1782,7 @@ nfsd4_cltrack_client_has_session(struct nfs4_client *clp) } static char * -nfsd4_cltrack_grace_start(time_t grace_start) +nfsd4_cltrack_grace_start(time64_t grace_start) { int copied; size_t len; @@ -1795,7 +1795,7 @@ nfsd4_cltrack_grace_start(time_t grace_start) if (!result) return result; - copied = snprintf(result, len, GRACE_START_ENV_PREFIX "%ld", + copied = snprintf(result, len, GRACE_START_ENV_PREFIX "%lld", grace_start); if (copied >= len) { /* just return nothing if output was truncated */ @@ -2004,7 +2004,7 @@ nfsd4_umh_cltrack_grace_done(struct nfsd_net *nn) char *legacy; char timestr[22]; /* FIXME: better way to determine max size? */ - sprintf(timestr, "%ld", nn->boot_time); + sprintf(timestr, "%lld", nn->boot_time); legacy = nfsd4_cltrack_legacy_topdir(); nfsd4_umh_cltrack_upcall("gracedone", timestr, legacy, NULL); kfree(legacy); diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 27a629cc5a46..1ac431aa29c4 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -753,7 +753,7 @@ int nfs4_init_cp_state(struct nfsd_net *nn, struct nfsd4_copy *copy) if (new_id < 0) return 0; copy->cp_stateid.si_opaque.so_id = new_id; - copy->cp_stateid.si_opaque.so_clid.cl_boot = nn->boot_time; + copy->cp_stateid.si_opaque.so_clid.cl_boot = (u32)nn->boot_time; copy->cp_stateid.si_opaque.so_clid.cl_id = nn->s2s_cp_cl_id; return 1; } @@ -1862,7 +1862,7 @@ STALE_CLIENTID(clientid_t *clid, struct nfsd_net *nn) */ if (clid->cl_boot == (u32)nn->boot_time) return 0; - dprintk("NFSD stale clientid (%08x/%08x) boot_time %08lx\n", + dprintk("NFSD stale clientid (%08x/%08x) boot_time %08llx\n", clid->cl_boot, clid->cl_id, nn->boot_time); return 1; } @@ -,7 +,7 @@ static void gen_confirm(struct nfs4_client *clp, struct nfsd_net *nn) static void gen_clid(struct nfs4_client *clp, struct nfsd_net *nn) { - clp->cl_clientid.cl_boot = nn->boot_time; + clp->cl_clientid.cl_boot = (u32)nn->boot_time; clp->cl_clientid.cl_id = nn->clientid_counter++; gen_confirm(clp, nn); } @@ -5183,9 +5183,9 @@ nfsd4_end_grace(struct nfsd_net *nn) */ static bool clients_still_reclaiming(struct nfsd_net *nn) { - unsigned long now = get_seconds(); - unsigned long double_grace_period_end = nn->boot_time + - 2 * nn->nfsd4_lease; + unsigned long now = (unsigned long) ktime_get_real_seconds(); + unsigned long double_grace_period_end = (unsigned long)nn->boot_time + + 2 * (unsigned long)nn->nfsd4_lease; if (nn->track_reclaim_completes && atomic_read(>nr_reclaim_complete) == @@ -7640,7 +7640,7 @@ static int nfs4_state_create_net(struct net *net) INIT_LIST_HEAD(>sessionid_hashtbl[i]); nn->conf_name_tree = RB_ROOT; nn->unconf_name_tree = RB_ROOT; - nn->boot_time = get_seconds(); + nn->boot_time = ktime_get_real_seconds(); nn->grace_ended = false;
[Y2038] [PATCH v2 07/12] nfsd: use time64_t in nfsd_proc_setattr() check
Change to time64_t and ktime_get_real_seconds() to make the logic work correctly on 32-bit architectures beyond 2038. Signed-off-by: Arnd Bergmann --- fs/nfsd/nfsproc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index aa013b736073..b25c90be29fb 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -94,7 +94,7 @@ nfsd_proc_setattr(struct svc_rqst *rqstp) * Solaris, at least, doesn't seem to care what the time * request is. We require it be within 30 minutes of now. */ - time_t delta = iap->ia_atime.tv_sec - get_seconds(); + time64_t delta = iap->ia_atime.tv_sec - ktime_get_real_seconds(); nfserr = fh_verify(rqstp, fhp, 0, NFSD_MAY_NOP); if (nfserr) -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 12/12] nfsd: remove nfs4_reset_lease() declarations
The function was removed a long time ago, but the declaration and a dummy implementation are still there, referencing the deprecated time_t type. Remove both. Fixes: f958a1320ff7 ("nfsd4: remove unnecessary lease-setting function") Signed-off-by: Arnd Bergmann --- fs/nfsd/nfsd.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/nfsd/nfsd.h b/fs/nfsd/nfsd.h index 57b93d95fa5c..31f1522f 100644 --- a/fs/nfsd/nfsd.h +++ b/fs/nfsd/nfsd.h @@ -142,7 +142,6 @@ int nfs4_state_start(void); int nfs4_state_start_net(struct net *net); void nfs4_state_shutdown(void); void nfs4_state_shutdown_net(struct net *net); -void nfs4_reset_lease(time_t leasetime); int nfs4_reset_recoverydir(char *recdir); char * nfs4_recoverydir(void); bool nfsd4_spo_must_allow(struct svc_rqst *rqstp); @@ -153,7 +152,6 @@ static inline int nfs4_state_start(void) { return 0; } static inline int nfs4_state_start_net(struct net *net) { return 0; } static inline void nfs4_state_shutdown(void) { } static inline void nfs4_state_shutdown_net(struct net *net) { } -static inline void nfs4_reset_lease(time_t leasetime) { } static inline int nfs4_reset_recoverydir(char *recdir) { return 0; } static inline char * nfs4_recoverydir(void) {return NULL; } static inline bool nfsd4_spo_must_allow(struct svc_rqst *rqstp) -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 08/12] nfsd: fix delay timer on 32-bit architectures
The nfsd4_cb_layout_done() function takes a 'time_t' value, multiplied by NSEC_PER_SEC*2 to get a nanosecond value. This works fine on 64-bit architectures, but on 32-bit, any value over 1 second results in a signed integer overflow with unexpected results. Cast one input to a 64-bit type in order to produce the same result that we have on 64-bit architectures, regarless of the type of nfsd4_lease. Fixes: 6b9b21073d3b ("nfsd: give up on CB_LAYOUTRECALLs after two lease periods") Signed-off-by: Arnd Bergmann --- fs/nfsd/nfs4layouts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c index 2681c70283ce..e12409eca7cc 100644 --- a/fs/nfsd/nfs4layouts.c +++ b/fs/nfsd/nfs4layouts.c @@ -675,7 +675,7 @@ nfsd4_cb_layout_done(struct nfsd4_callback *cb, struct rpc_task *task) /* Client gets 2 lease periods to return it */ cutoff = ktime_add_ns(task->tk_start, -nn->nfsd4_lease * NSEC_PER_SEC * 2); +(u64)nn->nfsd4_lease * NSEC_PER_SEC * 2); if (ktime_before(now, cutoff)) { rpc_delay(task, HZ/100); /* 10 mili-seconds */ -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 01/12] nfsd: use ktime_get_seconds() for timestamps
The delegation logic in nfsd uses the somewhat inefficient seconds_since_boot() function to record time intervals. Signed-off-by: Arnd Bergmann --- fs/nfsd/nfs4state.c | 10 +- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 369e574c5092..bfdb3366239c 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -806,7 +806,7 @@ static void nfs4_free_deleg(struct nfs4_stid *stid) static DEFINE_SPINLOCK(blocked_delegations_lock); static struct bloom_pair { int entries, old_entries; - time_t swap_time; + time64_t swap_time; int new; /* index into 'set' */ DECLARE_BITMAP(set[2], 256); } blocked_delegations; @@ -818,15 +818,15 @@ static int delegation_blocked(struct knfsd_fh *fh) if (bd->entries == 0) return 0; - if (seconds_since_boot() - bd->swap_time > 30) { + if (ktime_get_seconds() - bd->swap_time > 30) { spin_lock(_delegations_lock); - if (seconds_since_boot() - bd->swap_time > 30) { + if (ktime_get_seconds() - bd->swap_time > 30) { bd->entries -= bd->old_entries; bd->old_entries = bd->entries; memset(bd->set[bd->new], 0, sizeof(bd->set[0])); bd->new = 1-bd->new; - bd->swap_time = seconds_since_boot(); + bd->swap_time = ktime_get_seconds(); } spin_unlock(_delegations_lock); } @@ -856,7 +856,7 @@ static void block_delegations(struct knfsd_fh *fh) __set_bit((hash>>8)&255, bd->set[bd->new]); __set_bit((hash>>16)&255, bd->set[bd->new]); if (bd->entries == 0) - bd->swap_time = seconds_since_boot(); + bd->swap_time = ktime_get_seconds(); bd->entries += 1; spin_unlock(_delegations_lock); } -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 09/12] nfsd: fix jiffies/time_t mixup in LRU list
The nfsd4_blocked_lock->nbl_time timestamp is recorded in jiffies, but then compared to a CLOCK_REALTIME timestamp later on, which makes no sense. For consistency with the other timestamps, change this to use a time_t. This is a change in behavior, which may cause regressions, but the current code is not sensible. On a system with CONFIG_HZ=1000, the 'time_after((unsigned long)nbl->nbl_time, (unsigned long)cutoff))' check is false for roughly the first 18 days of uptime and then true for the next 49 days. Fixes: 7919d0a27f1e ("nfsd: add a LRU list for blocked locks") Signed-off-by: Arnd Bergmann --- fs/nfsd/nfs4state.c | 2 +- fs/nfsd/state.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 5cb0f774218a..9a063c4b4460 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -6549,7 +6549,7 @@ nfsd4_lock(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, } if (fl_flags & FL_SLEEP) { - nbl->nbl_time = jiffies; + nbl->nbl_time = get_seconds(); spin_lock(>blocked_locks_lock); list_add_tail(>nbl_list, _sop->lo_blocked); list_add_tail(>nbl_lru, >blocked_locks_lru); diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index 2b4165cd1d3e..03fc7b4380f9 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -606,7 +606,7 @@ static inline bool nfsd4_stateid_generation_after(stateid_t *a, stateid_t *b) struct nfsd4_blocked_lock { struct list_headnbl_list; struct list_headnbl_lru; - unsigned long nbl_time; + time_t nbl_time; struct file_locknbl_lock; struct knfsd_fh nbl_fh; struct nfsd4_callback nbl_cb; -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 06/12] nfsd: pass a 64-bit guardtime to nfsd_setattr()
Guardtime handling in nfs3 differs between 32-bit and 64-bit architectures, and uses the deprecated time_t type. Change it to using time64_t, which behaves the same way on 64-bit and 32-bit architectures, treating the number as an unsigned 32-bit entity with a range of year 1970 to 2106 consistently, and avoiding the y2038 overflow. Signed-off-by: Arnd Bergmann --- fs/nfsd/nfs4proc.c | 2 +- fs/nfsd/nfs4state.c | 2 +- fs/nfsd/nfsproc.c | 4 ++-- fs/nfsd/vfs.c | 4 ++-- fs/nfsd/vfs.h | 2 +- fs/nfsd/xdr3.h | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 4798667af647..bcf6803cf3a6 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c @@ -975,7 +975,7 @@ nfsd4_setattr(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, if (status) goto out; status = nfsd_setattr(rqstp, >current_fh, >sa_iattr, - 0, (time_t)0); + 0, (time64_t)0); out: fh_drop_write(>current_fh); return status; diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 1ac431aa29c4..5cb0f774218a 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -4671,7 +4671,7 @@ nfsd4_truncate(struct svc_rqst *rqstp, struct svc_fh *fh, return 0; if (!(open->op_share_access & NFS4_SHARE_ACCESS_WRITE)) return nfserr_inval; - return nfsd_setattr(rqstp, fh, , 0, (time_t)0); + return nfsd_setattr(rqstp, fh, , 0, (time64_t)0); } static __be32 nfs4_get_vfs_file(struct svc_rqst *rqstp, struct nfs4_file *fp, diff --git a/fs/nfsd/nfsproc.c b/fs/nfsd/nfsproc.c index c83ddac22f38..aa013b736073 100644 --- a/fs/nfsd/nfsproc.c +++ b/fs/nfsd/nfsproc.c @@ -113,7 +113,7 @@ nfsd_proc_setattr(struct svc_rqst *rqstp) } } - nfserr = nfsd_setattr(rqstp, fhp, iap, 0, (time_t)0); + nfserr = nfsd_setattr(rqstp, fhp, iap, 0, (time64_t)0); done: return nfsd_return_attrs(nfserr, resp); } @@ -380,7 +380,7 @@ nfsd_proc_create(struct svc_rqst *rqstp) */ attr->ia_valid &= ATTR_SIZE; if (attr->ia_valid) - nfserr = nfsd_setattr(rqstp, newfhp, attr, 0, (time_t)0); + nfserr = nfsd_setattr(rqstp, newfhp, attr, 0, (time64_t)0); } out_unlock: diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index c0dc491537a6..fd5ba6997447 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -358,7 +358,7 @@ nfsd_get_write_access(struct svc_rqst *rqstp, struct svc_fh *fhp, */ __be32 nfsd_setattr(struct svc_rqst *rqstp, struct svc_fh *fhp, struct iattr *iap, -int check_guard, time_t guardtime) +int check_guard, time64_t guardtime) { struct dentry *dentry; struct inode*inode; @@ -1123,7 +1123,7 @@ nfsd_create_setattr(struct svc_rqst *rqstp, struct svc_fh *resfhp, if (!uid_eq(current_fsuid(), GLOBAL_ROOT_UID)) iap->ia_valid &= ~(ATTR_UID|ATTR_GID); if (iap->ia_valid) - return nfsd_setattr(rqstp, resfhp, iap, 0, (time_t)0); + return nfsd_setattr(rqstp, resfhp, iap, 0, (time64_t)0); /* Callers expect file metadata to be committed here */ return nfserrno(commit_metadata(resfhp)); } diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h index cc110a10bfe8..bbb485177b25 100644 --- a/fs/nfsd/vfs.h +++ b/fs/nfsd/vfs.h @@ -48,7 +48,7 @@ __be32 nfsd_lookup_dentry(struct svc_rqst *, struct svc_fh *, const char *, unsigned int, struct svc_export **, struct dentry **); __be32 nfsd_setattr(struct svc_rqst *, struct svc_fh *, - struct iattr *, int, time_t); + struct iattr *, int, time64_t); int nfsd_mountpoint(struct dentry *, struct svc_export *); #ifdef CONFIG_NFSD_V4 __be32 nfsd4_set_nfs4_label(struct svc_rqst *, struct svc_fh *, diff --git a/fs/nfsd/xdr3.h b/fs/nfsd/xdr3.h index 99ff9f403ff1..0fa12988fb6a 100644 --- a/fs/nfsd/xdr3.h +++ b/fs/nfsd/xdr3.h @@ -14,7 +14,7 @@ struct nfsd3_sattrargs { struct svc_fh fh; struct iattrattrs; int check_guard; - time_t guardtime; + time64_tguardtime; }; struct nfsd3_diropargs { -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 02/12] nfsd: print 64-bit timestamps in client_info_show
The nii_time field gets truncated to 'time_t' on 32-bit architectures before printing. Remove the use of 'struct timespec' to product the correct output beyond 2038. Signed-off-by: Arnd Bergmann --- fs/nfsd/nfs4state.c | 5 ++--- fs/nfsd/state.h | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index bfdb3366239c..27a629cc5a46 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -2292,7 +2292,7 @@ static int client_info_show(struct seq_file *m, void *v) clp->cl_nii_domain.len); seq_printf(m, "\nImplementation name: "); seq_quote_mem(m, clp->cl_nii_name.data, clp->cl_nii_name.len); - seq_printf(m, "\nImplementation time: [%ld, %ld]\n", + seq_printf(m, "\nImplementation time: [%lld, %ld]\n", clp->cl_nii_time.tv_sec, clp->cl_nii_time.tv_nsec); } drop_client(clp); @@ -2946,8 +2946,7 @@ static __be32 copy_impl_id(struct nfs4_client *clp, xdr_netobj_dup(>cl_nii_name, >nii_name, GFP_KERNEL); if (!clp->cl_nii_name.data) return nfserr_jukebox; - clp->cl_nii_time.tv_sec = exid->nii_time.tv_sec; - clp->cl_nii_time.tv_nsec = exid->nii_time.tv_nsec; + clp->cl_nii_time = exid->nii_time; return 0; } diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index d61b83b9654c..2b4165cd1d3e 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -320,7 +320,7 @@ struct nfs4_client { /* NFSv4.1 client implementation id: */ struct xdr_netobj cl_nii_domain; struct xdr_netobj cl_nii_name; - struct timespec cl_nii_time; + struct timespec64 cl_nii_time; /* for v4.0 and v4.1 callbacks: */ struct nfs4_cb_conn cl_cb_conn; -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 04/12] nfsd: use timespec64 in encode_time_delta
The values in encode_time_delta are always small and don't overflow the range of 'struct timespec', so changing it has no effect. Change it to timespec64 as a prerequisite for removing the timespec definition later. Signed-off-by: Arnd Bergmann --- fs/nfsd/nfs4xdr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index d2dc4c0e22e8..d95e9668eeff 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -2024,11 +2024,11 @@ static __be32 *encode_change(__be32 *p, struct kstat *stat, struct inode *inode, */ static __be32 *encode_time_delta(__be32 *p, struct inode *inode) { - struct timespec ts; + struct timespec64 ts; u32 ns; ns = max_t(u32, NSEC_PER_SEC/HZ, inode->i_sb->s_time_gran); - ts = ns_to_timespec(ns); + ts = ns_to_timespec64(ns); p = xdr_encode_hyper(p, ts.tv_sec); *p++ = cpu_to_be32(ts.tv_nsec); -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038
[Y2038] [PATCH v2 11/12] nfsd: use ktime_get_real_seconds() in nfs4_verifier
gen_confirm() generates a unique identifier based on the current time. This overflows in year 2038, but that is harmless since it generally does not lead to duplicates, as long as the time has been initialized by a real-time clock or NTP. Using ktime_get_boottime_seconds() or ktime_get_seconds() would avoid the overflow, but it would be more likely to result in non-unique numbers. Signed-off-by: Arnd Bergmann --- fs/nfsd/nfs4state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 6afdef63f6d7..efe3161f6cf7 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -2215,7 +2215,7 @@ static void gen_confirm(struct nfs4_client *clp, struct nfsd_net *nn) * This is opaque to client, so no need to byte-swap. Use * __force to keep sparse happy */ - verf[0] = (__force __be32)get_seconds(); + verf[0] = (__force __be32)(u32)ktime_get_real_seconds(); verf[1] = (__force __be32)nn->clverifier_counter++; memcpy(clp->cl_confirm.data, verf, sizeof(clp->cl_confirm.data)); } -- 2.20.0 ___ Y2038 mailing list Y2038@lists.linaro.org https://lists.linaro.org/mailman/listinfo/y2038