OSDN Git Service

xfrm: use time64_t for in-kernel timestamps
authorArnd Bergmann <arnd@arndb.de>
Wed, 11 Jul 2018 10:19:13 +0000 (12:19 +0200)
committerSteffen Klassert <steffen.klassert@secunet.com>
Wed, 11 Jul 2018 13:25:30 +0000 (15:25 +0200)
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: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c

index ef75891..5d2f734 100644 (file)
@@ -189,8 +189,8 @@ static inline unsigned long make_jiffies(long secs)
 static void xfrm_policy_timer(struct timer_list *t)
 {
        struct xfrm_policy *xp = from_timer(xp, t, timer);
-       unsigned long now = get_seconds();
-       long next = LONG_MAX;
+       time64_t now = ktime_get_real_seconds();
+       time64_t next = TIME64_MAX;
        int warn = 0;
        int dir;
 
@@ -202,7 +202,7 @@ static void xfrm_policy_timer(struct timer_list *t)
        dir = xfrm_policy_id2dir(xp->index);
 
        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;
                if (tmo <= 0)
                        goto expired;
@@ -210,7 +210,7 @@ static void xfrm_policy_timer(struct timer_list *t)
                        next = tmo;
        }
        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;
                if (tmo <= 0)
                        goto expired;
@@ -218,7 +218,7 @@ static void xfrm_policy_timer(struct timer_list *t)
                        next = tmo;
        }
        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;
                if (tmo <= 0) {
                        warn = 1;
@@ -228,7 +228,7 @@ static void xfrm_policy_timer(struct timer_list *t)
                        next = tmo;
        }
        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;
                if (tmo <= 0) {
                        warn = 1;
@@ -240,7 +240,7 @@ static void xfrm_policy_timer(struct timer_list *t)
 
        if (warn)
                km_policy_expired(xp, dir, 0, 0);
-       if (next != LONG_MAX &&
+       if (next != TIME64_MAX &&
            !mod_timer(&xp->timer, jiffies + make_jiffies(next)))
                xfrm_pol_hold(xp);
 
@@ -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);
        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;
        if (!mod_timer(&policy->timer, jiffies + HZ))
                xfrm_pol_hold(policy);
@@ -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],
                                lockdep_is_held(&net->xfrm.xfrm_policy_lock));
        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);
                xfrm_sk_policy_link(pol, dir);
        }
@@ -2132,7 +2132,7 @@ no_transform:
        }
 
        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) {
                /* Prohibit the flow */
@@ -2352,7 +2352,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
                return 1;
        }
 
-       pol->curlft.use_time = get_seconds();
+       pol->curlft.use_time = ktime_get_real_seconds();
 
        pols[0] = pol;
        npols++;
@@ -2366,7 +2366,7 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
                                XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR);
                                return 0;
                        }
-                       pols[1]->curlft.use_time = get_seconds();
+                       pols[1]->curlft.use_time = ktime_get_real_seconds();
                        npols++;
                }
        }
index c9ffcdf..27c84e6 100644 (file)
@@ -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 xfrm_state *x = container_of(thr, struct xfrm_state, mtimer);
-       unsigned long now = get_seconds();
-       long next = LONG_MAX;
+       time64_t now = ktime_get_real_seconds();
+       time64_t next = TIME64_MAX;
        int warn = 0;
        int err = 0;
 
@@ -537,7 +537,7 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
        if (warn)
                km_state_expired(x, 0, 0);
 resched:
-       if (next != LONG_MAX) {
+       if (next != TIME64_MAX) {
                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)
                tasklet_hrtimer_init(&x->mtimer, xfrm_timer_handler,
                                        CLOCK_BOOTTIME, HRTIMER_MODE_ABS);
                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_packet_limit = XFRM_INF;
                x->lft.hard_byte_limit = XFRM_INF;
@@ -1588,7 +1588,7 @@ EXPORT_SYMBOL(xfrm_state_update);
 int xfrm_state_check_expire(struct xfrm_state *x)
 {
        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 ||
            x->curlft.packets >= x->lft.hard_packet_limit) {