Commit 386c5680 authored by Arnd Bergmann's avatar Arnd Bergmann Committed by Steffen Klassert

xfrm: use time64_t for in-kernel timestamps

The lifetime managment uses '__u64' timestamps on the user space
interface, but 'unsigned long' for reading the current time in the kernel
with get_seconds().

While this is probably safe beyond y2038, it will still overflow in 2106,
and the get_seconds() call is deprecated because fo that.

This changes the xfrm time handling to use time64_t consistently, along
with reading the time using the safer ktime_get_real_seconds(). It still
suffers from problems that can happen from a concurrent settimeofday()
call or (to a lesser degree) a leap second update, but since the time
stamps are part of the user API, there is nothing we can do to prevent
that.
Signed-off-by: default avatarArnd Bergmann <arnd@arndb.de>
Signed-off-by: default avatarSteffen Klassert <steffen.klassert@secunet.com>
parent 6d8e85ff
...@@ -189,8 +189,8 @@ static inline unsigned long make_jiffies(long secs) ...@@ -189,8 +189,8 @@ static inline unsigned long make_jiffies(long secs)
static void xfrm_policy_timer(struct timer_list *t) static void xfrm_policy_timer(struct timer_list *t)
{ {
struct xfrm_policy *xp = from_timer(xp, t, timer); struct xfrm_policy *xp = from_timer(xp, t, timer);
unsigned long now = get_seconds(); time64_t now = ktime_get_real_seconds();
long next = LONG_MAX; time64_t next = TIME64_MAX;
int warn = 0; int warn = 0;
int dir; int dir;
...@@ -202,7 +202,7 @@ static void xfrm_policy_timer(struct timer_list *t) ...@@ -202,7 +202,7 @@ static void xfrm_policy_timer(struct timer_list *t)
dir = xfrm_policy_id2dir(xp->index); dir = xfrm_policy_id2dir(xp->index);
if (xp->lft.hard_add_expires_seconds) { if (xp->lft.hard_add_expires_seconds) {
long tmo = xp->lft.hard_add_expires_seconds + time64_t tmo = xp->lft.hard_add_expires_seconds +
xp->curlft.add_time - now; xp->curlft.add_time - now;
if (tmo <= 0) if (tmo <= 0)
goto expired; goto expired;
...@@ -210,7 +210,7 @@ static void xfrm_policy_timer(struct timer_list *t) ...@@ -210,7 +210,7 @@ static void xfrm_policy_timer(struct timer_list *t)
next = tmo; next = tmo;
} }
if (xp->lft.hard_use_expires_seconds) { if (xp->lft.hard_use_expires_seconds) {
long tmo = xp->lft.hard_use_expires_seconds + time64_t tmo = xp->lft.hard_use_expires_seconds +
(xp->curlft.use_time ? : xp->curlft.add_time) - now; (xp->curlft.use_time ? : xp->curlft.add_time) - now;
if (tmo <= 0) if (tmo <= 0)
goto expired; goto expired;
...@@ -218,7 +218,7 @@ static void xfrm_policy_timer(struct timer_list *t) ...@@ -218,7 +218,7 @@ static void xfrm_policy_timer(struct timer_list *t)
next = tmo; next = tmo;
} }
if (xp->lft.soft_add_expires_seconds) { if (xp->lft.soft_add_expires_seconds) {
long tmo = xp->lft.soft_add_expires_seconds + time64_t tmo = xp->lft.soft_add_expires_seconds +
xp->curlft.add_time - now; xp->curlft.add_time - now;
if (tmo <= 0) { if (tmo <= 0) {
warn = 1; warn = 1;
...@@ -228,7 +228,7 @@ static void xfrm_policy_timer(struct timer_list *t) ...@@ -228,7 +228,7 @@ static void xfrm_policy_timer(struct timer_list *t)
next = tmo; next = tmo;
} }
if (xp->lft.soft_use_expires_seconds) { if (xp->lft.soft_use_expires_seconds) {
long tmo = xp->lft.soft_use_expires_seconds + time64_t tmo = xp->lft.soft_use_expires_seconds +
(xp->curlft.use_time ? : xp->curlft.add_time) - now; (xp->curlft.use_time ? : xp->curlft.add_time) - now;
if (tmo <= 0) { if (tmo <= 0) {
warn = 1; warn = 1;
...@@ -240,7 +240,7 @@ static void xfrm_policy_timer(struct timer_list *t) ...@@ -240,7 +240,7 @@ static void xfrm_policy_timer(struct timer_list *t)
if (warn) if (warn)
km_policy_expired(xp, dir, 0, 0); km_policy_expired(xp, dir, 0, 0);
if (next != LONG_MAX && if (next != TIME64_MAX &&
!mod_timer(&xp->timer, jiffies + make_jiffies(next))) !mod_timer(&xp->timer, jiffies + make_jiffies(next)))
xfrm_pol_hold(xp); xfrm_pol_hold(xp);
...@@ -791,7 +791,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) ...@@ -791,7 +791,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
} }
policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir, policy->index); policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir, policy->index);
hlist_add_head(&policy->byidx, net->xfrm.policy_byidx+idx_hash(net, policy->index)); hlist_add_head(&policy->byidx, net->xfrm.policy_byidx+idx_hash(net, policy->index));
policy->curlft.add_time = get_seconds(); policy->curlft.add_time = ktime_get_real_seconds();
policy->curlft.use_time = 0; policy->curlft.use_time = 0;
if (!mod_timer(&policy->timer, jiffies + HZ)) if (!mod_timer(&policy->timer, jiffies + HZ))
xfrm_pol_hold(policy); xfrm_pol_hold(policy);
...@@ -1282,7 +1282,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol) ...@@ -1282,7 +1282,7 @@ int xfrm_sk_policy_insert(struct sock *sk, int dir, struct xfrm_policy *pol)
old_pol = rcu_dereference_protected(sk->sk_policy[dir], old_pol = rcu_dereference_protected(sk->sk_policy[dir],
lockdep_is_held(&net->xfrm.xfrm_policy_lock)); lockdep_is_held(&net->xfrm.xfrm_policy_lock));
if (pol) { if (pol) {
pol->curlft.add_time = get_seconds(); pol->curlft.add_time = ktime_get_real_seconds();
pol->index = xfrm_gen_index(net, XFRM_POLICY_MAX+dir, 0); pol->index = xfrm_gen_index(net, XFRM_POLICY_MAX+dir, 0);
xfrm_sk_policy_link(pol, dir); xfrm_sk_policy_link(pol, dir);
} }
...@@ -2132,7 +2132,7 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, ...@@ -2132,7 +2132,7 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig,
} }
for (i = 0; i < num_pols; i++) for (i = 0; i < num_pols; i++)
pols[i]->curlft.use_time = get_seconds(); pols[i]->curlft.use_time = ktime_get_real_seconds();
if (num_xfrms < 0) { if (num_xfrms < 0) {
/* Prohibit the flow */ /* Prohibit the flow */
...@@ -2352,7 +2352,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, ...@@ -2352,7 +2352,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
return 1; return 1;
} }
pol->curlft.use_time = get_seconds(); pol->curlft.use_time = ktime_get_real_seconds();
pols[0] = pol; pols[0] = pol;
npols++; npols++;
...@@ -2366,7 +2366,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb, ...@@ -2366,7 +2366,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR); XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR);
return 0; return 0;
} }
pols[1]->curlft.use_time = get_seconds(); pols[1]->curlft.use_time = ktime_get_real_seconds();
npols++; npols++;
} }
} }
......
...@@ -475,8 +475,8 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me) ...@@ -475,8 +475,8 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
{ {
struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer); struct tasklet_hrtimer *thr = container_of(me, struct tasklet_hrtimer, timer);
struct xfrm_state *x = container_of(thr, struct xfrm_state, mtimer); struct xfrm_state *x = container_of(thr, struct xfrm_state, mtimer);
unsigned long now = get_seconds(); time64_t now = ktime_get_real_seconds();
long next = LONG_MAX; time64_t next = TIME64_MAX;
int warn = 0; int warn = 0;
int err = 0; int err = 0;
...@@ -537,7 +537,7 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me) ...@@ -537,7 +537,7 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
if (warn) if (warn)
km_state_expired(x, 0, 0); km_state_expired(x, 0, 0);
resched: resched:
if (next != LONG_MAX) { if (next != TIME64_MAX) {
tasklet_hrtimer_start(&x->mtimer, ktime_set(next, 0), HRTIMER_MODE_REL); tasklet_hrtimer_start(&x->mtimer, ktime_set(next, 0), HRTIMER_MODE_REL);
} }
...@@ -577,7 +577,7 @@ struct xfrm_state *xfrm_state_alloc(struct net *net) ...@@ -577,7 +577,7 @@ struct xfrm_state *xfrm_state_alloc(struct net *net)
tasklet_hrtimer_init(&x->mtimer, xfrm_timer_handler, tasklet_hrtimer_init(&x->mtimer, xfrm_timer_handler,
CLOCK_BOOTTIME, HRTIMER_MODE_ABS); CLOCK_BOOTTIME, HRTIMER_MODE_ABS);
timer_setup(&x->rtimer, xfrm_replay_timer_handler, 0); timer_setup(&x->rtimer, xfrm_replay_timer_handler, 0);
x->curlft.add_time = get_seconds(); x->curlft.add_time = ktime_get_real_seconds();
x->lft.soft_byte_limit = XFRM_INF; x->lft.soft_byte_limit = XFRM_INF;
x->lft.soft_packet_limit = XFRM_INF; x->lft.soft_packet_limit = XFRM_INF;
x->lft.hard_byte_limit = XFRM_INF; x->lft.hard_byte_limit = XFRM_INF;
...@@ -1588,7 +1588,7 @@ EXPORT_SYMBOL(xfrm_state_update); ...@@ -1588,7 +1588,7 @@ EXPORT_SYMBOL(xfrm_state_update);
int xfrm_state_check_expire(struct xfrm_state *x) int xfrm_state_check_expire(struct xfrm_state *x)
{ {
if (!x->curlft.use_time) if (!x->curlft.use_time)
x->curlft.use_time = get_seconds(); x->curlft.use_time = ktime_get_real_seconds();
if (x->curlft.bytes >= x->lft.hard_byte_limit || if (x->curlft.bytes >= x->lft.hard_byte_limit ||
x->curlft.packets >= x->lft.hard_packet_limit) { x->curlft.packets >= x->lft.hard_packet_limit) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment