Changes all the uses of time_t for the structs key and key_preparsed_payload to time64_t. This also involves the functions that use them in security/keys. This is to handle the y2038 problem where time_t will overflow in 2038.
Also since time_t was a long int and time64_t is long long, uses of LONG_MAX and TIME_T_MAX were replaced by S64_MAX.
Signed-off-by: Arnd Bergmann arnd@arndb.de Signed-off-by: Aya Mahfouz mahfouz.saif.elyazal@gmail.com --- Changelog: v1: The changes were originally made by Arnd Bergmann in relation to time_t. I've broken down a patch sent to me into two independent patches.
include/linux/key-type.h | 2 +- include/linux/key.h | 6 +++--- security/keys/gc.c | 23 ++++++++++++----------- security/keys/internal.h | 8 ++++---- security/keys/key.c | 24 +++++++++--------------- security/keys/keyring.c | 18 +++++++++--------- security/keys/permission.c | 3 +-- security/keys/proc.c | 8 ++++---- security/keys/process_keys.c | 2 +- 9 files changed, 44 insertions(+), 50 deletions(-)
diff --git a/include/linux/key-type.h b/include/linux/key-type.h index 7463355..2c844ae 100644 --- a/include/linux/key-type.h +++ b/include/linux/key-type.h @@ -44,7 +44,7 @@ struct key_preparsed_payload { const void *data; /* Raw data */ size_t datalen; /* Raw datalen */ size_t quotalen; /* Quota length for proposed payload */ - time_t expiry; /* Expiry time of key */ + time64_t expiry; /* Expiry time of key */ bool trusted; /* True if key is trusted */ };
diff --git a/include/linux/key.h b/include/linux/key.h index 66f7052..6f69a25 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -145,10 +145,10 @@ struct key { struct key_user *user; /* owner of this key */ void *security; /* security data for this key */ union { - time_t expiry; /* time at which key expires (or 0) */ - time_t revoked_at; /* time at which key was revoked */ + time64_t expiry; /* time at which key expires (or 0) */ + time64_t revoked_at; /* time at which key was revoked */ }; - time_t last_used_at; /* last time used for LRU keyring discard */ + time64_t last_used_at; /* last time used for LRU keyring discard */ kuid_t uid; kgid_t gid; key_perm_t perm; /* access permissions */ diff --git a/security/keys/gc.c b/security/keys/gc.c index addf060..a467a61 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c @@ -32,7 +32,7 @@ DECLARE_WORK(key_gc_work, key_garbage_collector); static void key_gc_timer_func(unsigned long); static DEFINE_TIMER(key_gc_timer, key_gc_timer_func, 0, 0);
-static time_t key_gc_next_run = LONG_MAX; +static time64_t key_gc_next_run = S64_MAX; static struct key_type *key_gc_dead_keytype;
static unsigned long key_gc_flags; @@ -53,12 +53,12 @@ struct key_type key_type_dead = { * Schedule a garbage collection run. * - time precision isn't particularly important */ -void key_schedule_gc(time_t gc_at) +void key_schedule_gc(time64_t gc_at) { unsigned long expires; - time_t now = current_kernel_time().tv_sec; + time64_t now = ktime_get_real_seconds();
- kenter("%ld", gc_at - now); + kenter("%ld", (long)(gc_at - now));
if (gc_at <= now || test_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags)) { kdebug("IMMEDIATE"); @@ -87,7 +87,7 @@ void key_schedule_gc_links(void) static void key_gc_timer_func(unsigned long data) { kenter(""); - key_gc_next_run = LONG_MAX; + key_gc_next_run = S64_MAX; key_schedule_gc_links(); }
@@ -186,11 +186,11 @@ static void key_garbage_collector(struct work_struct *work)
struct rb_node *cursor; struct key *key; - time_t new_timer, limit; + time64_t new_timer, limit;
kenter("[%lx,%x]", key_gc_flags, gc_state);
- limit = current_kernel_time().tv_sec; + limit = ktime_get_real_seconds(); if (limit > key_gc_delay) limit -= key_gc_delay; else @@ -206,7 +206,7 @@ static void key_garbage_collector(struct work_struct *work) gc_state |= KEY_GC_REAPING_DEAD_1; kdebug("new pass %x", gc_state);
- new_timer = LONG_MAX; + new_timer = S64_MAX;
/* As only this function is permitted to remove things from the key * serial tree, if cursor is non-NULL then it will always point to a @@ -234,8 +234,9 @@ continue_scanning:
if (gc_state & KEY_GC_SET_TIMER) { if (key->expiry > limit && key->expiry < new_timer) { - kdebug("will expire %x in %ld", - key_serial(key), key->expiry - limit); + kdebug("will expire %x in %lld", + key_serial(key), + (s64)(key->expiry - limit)); new_timer = key->expiry; } } @@ -275,7 +276,7 @@ maybe_resched: */ kdebug("pass complete");
- if (gc_state & KEY_GC_SET_TIMER && new_timer != (time_t)LONG_MAX) { + if (gc_state & KEY_GC_SET_TIMER && new_timer != (time64_t)S64_MAX) { new_timer += key_gc_delay; key_schedule_gc(new_timer); } diff --git a/security/keys/internal.h b/security/keys/internal.h index 5105c2c..5f4f007 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h @@ -125,7 +125,7 @@ struct keyring_search_context { int skipped_ret; bool possessed; key_ref_t result; - struct timespec now; + time64_t now; };
extern bool key_default_cmp(const struct key *key, @@ -164,8 +164,8 @@ extern void key_change_session_keyring(struct callback_head *twork);
extern struct work_struct key_gc_work; extern unsigned key_gc_delay; -extern void keyring_gc(struct key *keyring, time_t limit); -extern void key_schedule_gc(time_t gc_at); +extern void keyring_gc(struct key *keyring, time64_t limit); +extern void key_schedule_gc(time64_t gc_at); extern void key_schedule_gc_links(void); extern void key_gc_keytype(struct key_type *ktype);
@@ -204,7 +204,7 @@ extern struct key *key_get_instantiation_authkey(key_serial_t target_id); /* * Determine whether a key is dead. */ -static inline bool key_is_dead(const struct key *key, time_t limit) +static inline bool key_is_dead(const struct key *key, time64_t limit) { return key->flags & ((1 << KEY_FLAG_DEAD) | diff --git a/security/keys/key.c b/security/keys/key.c index ab7997d..d134a26 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -436,7 +436,7 @@ static int __key_instantiate_and_link(struct key *key, if (authkey) key_revoke(authkey);
- if (prep->expiry != TIME_T_MAX) { + if (prep->expiry != S64_MAX) { key->expiry = prep->expiry; key_schedule_gc(prep->expiry + key_gc_delay); } @@ -482,7 +482,7 @@ int key_instantiate_and_link(struct key *key, prep.data = data; prep.datalen = datalen; prep.quotalen = key->type->def_datalen; - prep.expiry = TIME_T_MAX; + prep.expiry = S64_MAX; if (key->type->preparse) { ret = key->type->preparse(&prep); if (ret < 0) @@ -536,7 +536,6 @@ int key_reject_and_link(struct key *key, struct key *authkey) { struct assoc_array_edit *edit; - struct timespec now; int ret, awaken, link_ret = 0;
key_check(key); @@ -558,8 +557,7 @@ int key_reject_and_link(struct key *key, smp_wmb(); set_bit(KEY_FLAG_NEGATIVE, &key->flags); set_bit(KEY_FLAG_INSTANTIATED, &key->flags); - now = current_kernel_time(); - key->expiry = now.tv_sec + timeout; + key->expiry = ktime_get_real_seconds() + timeout; key_schedule_gc(key->expiry + key_gc_delay);
if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) @@ -678,15 +676,13 @@ found_kernel_type:
void key_set_timeout(struct key *key, unsigned timeout) { - struct timespec now; - time_t expiry = 0; + time64_t expiry = 0;
/* make the changes with the locks held to prevent races */ down_write(&key->sem);
if (timeout > 0) { - now = current_kernel_time(); - expiry = now.tv_sec + timeout; + expiry = ktime_get_real_seconds() + timeout; }
key->expiry = expiry; @@ -814,7 +810,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, prep.datalen = plen; prep.quotalen = index_key.type->def_datalen; prep.trusted = flags & KEY_ALLOC_TRUSTED; - prep.expiry = TIME_T_MAX; + prep.expiry = S64_MAX; if (index_key.type->preparse) { ret = index_key.type->preparse(&prep); if (ret < 0) { @@ -945,7 +941,7 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) prep.data = payload; prep.datalen = plen; prep.quotalen = key->type->def_datalen; - prep.expiry = TIME_T_MAX; + prep.expiry = S64_MAX; if (key->type->preparse) { ret = key->type->preparse(&prep); if (ret < 0) @@ -979,8 +975,7 @@ EXPORT_SYMBOL(key_update); */ void key_revoke(struct key *key) { - struct timespec now; - time_t time; + time64_t time;
key_check(key);
@@ -995,8 +990,7 @@ void key_revoke(struct key *key) key->type->revoke(key);
/* set the death time to no more than the expiry time */ - now = current_kernel_time(); - time = now.tv_sec; + time = ktime_get_real_seconds(); if (key->revoked_at == 0 || key->revoked_at > time) { key->revoked_at = time; key_schedule_gc(key->revoked_at + key_gc_delay); diff --git a/security/keys/keyring.c b/security/keys/keyring.c index f931ccf..a272386 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c @@ -545,7 +545,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data) goto skipped; }
- if (key->expiry && ctx->now.tv_sec >= key->expiry) { + if (key->expiry && ctx->now >= key->expiry) { if (!(ctx->flags & KEYRING_SEARCH_SKIP_EXPIRED)) ctx->result = ERR_PTR(-EKEYEXPIRED); kleave(" = %d [expire]", ctx->skipped_ret); @@ -806,10 +806,10 @@ found: key = key_ref_to_ptr(ctx->result); key_check(key); if (!(ctx->flags & KEYRING_SEARCH_NO_UPDATE_TIME)) { - key->last_used_at = ctx->now.tv_sec; - keyring->last_used_at = ctx->now.tv_sec; + key->last_used_at = ctx->now; + keyring->last_used_at = ctx->now; while (sp > 0) - stack[--sp].keyring->last_used_at = ctx->now.tv_sec; + stack[--sp].keyring->last_used_at = ctx->now; } kleave(" = true"); return true; @@ -870,7 +870,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, }
rcu_read_lock(); - ctx->now = current_kernel_time(); + ctx->now = ktime_get_real_seconds(); if (search_nested_keyrings(keyring, ctx)) __key_get(key_ref_to_ptr(ctx->result)); rcu_read_unlock(); @@ -1011,7 +1011,7 @@ struct key *find_keyring_by_name(const char *name, bool skip_perm_check) * (ie. it has a zero usage count) */ if (!atomic_inc_not_zero(&keyring->usage)) continue; - keyring->last_used_at = current_kernel_time().tv_sec; + keyring->last_used_at = ktime_get_real_seconds(); goto out; } } @@ -1342,7 +1342,7 @@ static void keyring_revoke(struct key *keyring) static bool keyring_gc_select_iterator(void *object, void *iterator_data) { struct key *key = keyring_ptr_to_key(object); - time_t *limit = iterator_data; + time64_t *limit = iterator_data;
if (key_is_dead(key, *limit)) return false; @@ -1353,7 +1353,7 @@ static bool keyring_gc_select_iterator(void *object, void *iterator_data) static int keyring_gc_check_iterator(const void *object, void *iterator_data) { const struct key *key = keyring_ptr_to_key(object); - time_t *limit = iterator_data; + time64_t *limit = iterator_data;
key_check(key); return key_is_dead(key, *limit); @@ -1365,7 +1365,7 @@ static int keyring_gc_check_iterator(const void *object, void *iterator_data) * Not called with any locks held. The keyring's key struct will not be * deallocated under us as only our caller may deallocate it. */ -void keyring_gc(struct key *keyring, time_t limit) +void keyring_gc(struct key *keyring, time64_t limit) { int result;
diff --git a/security/keys/permission.c b/security/keys/permission.c index 732cc0b..507b1d41 100644 --- a/security/keys/permission.c +++ b/security/keys/permission.c @@ -100,8 +100,7 @@ int key_validate(const struct key *key)
/* check it hasn't expired */ if (key->expiry) { - struct timespec now = current_kernel_time(); - if (now.tv_sec >= key->expiry) + if (ktime_get_real_seconds() >= key->expiry) return -EKEYEXPIRED; }
diff --git a/security/keys/proc.c b/security/keys/proc.c index f0611a6..f3c20aa 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c @@ -178,7 +178,7 @@ static int proc_keys_show(struct seq_file *m, void *v) { struct rb_node *_p = v; struct key *key = rb_entry(_p, struct key, serial_node); - struct timespec now; + time64_t now; unsigned long timo; key_ref_t key_ref, skey_ref; char xbuf[12]; @@ -216,17 +216,17 @@ static int proc_keys_show(struct seq_file *m, void *v) if (rc < 0) return 0;
- now = current_kernel_time(); + now = ktime_get_real_seconds();
rcu_read_lock();
/* come up with a suitable timeout value */ if (key->expiry == 0) { memcpy(xbuf, "perm", 5); - } else if (now.tv_sec >= key->expiry) { + } else if (now >= key->expiry) { memcpy(xbuf, "expd", 5); } else { - timo = key->expiry - now.tv_sec; + timo = key->expiry - now;
if (timo < 60) sprintf(xbuf, "%lus", timo); diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index a3f85d2..7acede7 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c @@ -721,7 +721,7 @@ try_again: if (ret < 0) goto invalid_key;
- key->last_used_at = current_kernel_time().tv_sec; + key->last_used_at = ktime_get_real_seconds();
error: put_cred(ctx.cred);
On Tuesday 17 November 2015 23:20:28 Aya Mahfouz wrote:
Changes all the uses of time_t for the structs key and key_preparsed_payload to time64_t. This also involves the functions that use them in security/keys. This is to handle the y2038 problem where time_t will overflow in 2038.
Also since time_t was a long int and time64_t is long long, uses of LONG_MAX and TIME_T_MAX were replaced by S64_MAX.
Signed-off-by: Arnd Bergmann arnd@arndb.de Signed-off-by: Aya Mahfouz mahfouz.saif.elyazal@gmail.com
Looks pretty good. Two very minor comments:
Changelog: v1: The changes were originally made by Arnd Bergmann in relation to time_t. I've broken down a patch sent to me into two independent patches.
I suppose you have tried and failed to split it up into smaller chunks?
-static time_t key_gc_next_run = LONG_MAX; +static time64_t key_gc_next_run = S64_MAX; static struct key_type *key_gc_dead_keytype; static unsigned long key_gc_flags; @@ -53,12 +53,12 @@ struct key_type key_type_dead = {
- Schedule a garbage collection run.
- time precision isn't particularly important
*/ -void key_schedule_gc(time_t gc_at) +void key_schedule_gc(time64_t gc_at) { unsigned long expires;
- time_t now = current_kernel_time().tv_sec;
- time64_t now = ktime_get_real_seconds();
- kenter("%ld", gc_at - now);
- kenter("%ld", (long)(gc_at - now));
if (gc_at <= now || test_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags)) { kdebug("IMMEDIATE");
I noticed now that this is wrong when gc_at is S64_MAX, because that would overflow a 'long'. The code currently doesn't appear to do that, but it's safer to just print it as a "%lld" instead as you do elsehwere.
Arnd
On Wed, Nov 18, 2015 at 03:10:30PM +0100, Arnd Bergmann wrote:
On Tuesday 17 November 2015 23:20:28 Aya Mahfouz wrote:
Changes all the uses of time_t for the structs key and key_preparsed_payload to time64_t. This also involves the functions that use them in security/keys. This is to handle the y2038 problem where time_t will overflow in 2038.
Also since time_t was a long int and time64_t is long long, uses of LONG_MAX and TIME_T_MAX were replaced by S64_MAX.
Signed-off-by: Arnd Bergmann arnd@arndb.de Signed-off-by: Aya Mahfouz mahfouz.saif.elyazal@gmail.com
Looks pretty good. Two very minor comments:
Thanks Arnd!
Changelog: v1: The changes were originally made by Arnd Bergmann in relation to time_t. I've broken down a patch sent to me into two independent patches.
I suppose you have tried and failed to split it up into smaller chunks?
I'm playing it safe since there are uses of key->expiry that are dependent on key_preparsed_payload->expiry. If you would like for me to break it down further, I can try.
-static time_t key_gc_next_run = LONG_MAX; +static time64_t key_gc_next_run = S64_MAX; static struct key_type *key_gc_dead_keytype; static unsigned long key_gc_flags; @@ -53,12 +53,12 @@ struct key_type key_type_dead = {
- Schedule a garbage collection run.
- time precision isn't particularly important
*/ -void key_schedule_gc(time_t gc_at) +void key_schedule_gc(time64_t gc_at) { unsigned long expires;
- time_t now = current_kernel_time().tv_sec;
- time64_t now = ktime_get_real_seconds();
- kenter("%ld", gc_at - now);
- kenter("%ld", (long)(gc_at - now));
if (gc_at <= now || test_bit(KEY_GC_REAP_KEYTYPE, &key_gc_flags)) { kdebug("IMMEDIATE");
I noticed now that this is wrong when gc_at is S64_MAX, because that would overflow a 'long'. The code currently doesn't appear to do that, but it's safer to just print it as a "%lld" instead as you do elsehwere.
No problems, I missed it too. I will fix it and resend the patch.
Arnd
On Wednesday 18 November 2015 17:33:38 Aya Mahfouz wrote:
Changelog: v1: The changes were originally made by Arnd Bergmann in relation to time_t. I've broken down a patch sent to me into two independent patches.
I suppose you have tried and failed to split it up into smaller chunks?
I'm playing it safe since there are uses of key->expiry that are dependent on key_preparsed_payload->expiry. If you would like for me to break it down further, I can try.
I think that would be helpful. The current version is a little too big to review properly in one chunk.
Arnd
On Wed, Nov 18, 2015 at 04:35:58PM +0100, Arnd Bergmann wrote:
On Wednesday 18 November 2015 17:33:38 Aya Mahfouz wrote:
Changelog: v1: The changes were originally made by Arnd Bergmann in relation to time_t. I've broken down a patch sent to me into two independent patches.
I suppose you have tried and failed to split it up into smaller chunks?
I'm playing it safe since there are uses of key->expiry that are dependent on key_preparsed_payload->expiry. If you would like for me to break it down further, I can try.
I think that would be helpful. The current version is a little too big to review properly in one chunk.
I've tried several time to break it up into 2 or 3 patches without ignoring dependencies but I fail every time to come with a set of independent patches. Can I keep it as is? I'm open to any division suggestions.
Thanks,
Arnd
On Friday 27 November 2015 16:42:54 Aya Mahfouz wrote:
On Wed, Nov 18, 2015 at 04:35:58PM +0100, Arnd Bergmann wrote:
On Wednesday 18 November 2015 17:33:38 Aya Mahfouz wrote:
Changelog: v1: The changes were originally made by Arnd Bergmann in relation to time_t. I've broken down a patch sent to me into two independent patches.
I suppose you have tried and failed to split it up into smaller chunks?
I'm playing it safe since there are uses of key->expiry that are dependent on key_preparsed_payload->expiry. If you would like for me to break it down further, I can try.
I think that would be helpful. The current version is a little too big to review properly in one chunk.
I've tried several time to break it up into 2 or 3 patches without ignoring dependencies but I fail every time to come with a set of independent patches. Can I keep it as is? I'm open to any division suggestions.
My first idea would be to split the key_preparsed_payload changes from the struct key changes. Have you tried that? What problems did you run into?
Arnd
On Fri, Nov 27, 2015 at 04:22:24PM +0100, Arnd Bergmann wrote:
On Friday 27 November 2015 16:42:54 Aya Mahfouz wrote:
On Wed, Nov 18, 2015 at 04:35:58PM +0100, Arnd Bergmann wrote:
On Wednesday 18 November 2015 17:33:38 Aya Mahfouz wrote:
Changelog: v1: The changes were originally made by Arnd Bergmann in relation to time_t. I've broken down a patch sent to me into two independent patches.
I suppose you have tried and failed to split it up into smaller chunks?
I'm playing it safe since there are uses of key->expiry that are dependent on key_preparsed_payload->expiry. If you would like for me to break it down further, I can try.
I think that would be helpful. The current version is a little too big to review properly in one chunk.
I've tried several time to break it up into 2 or 3 patches without ignoring dependencies but I fail every time to come with a set of independent patches. Can I keep it as is? I'm open to any division suggestions.
My first idea would be to split the key_preparsed_payload changes from the struct key changes. Have you tried that? What problems did you run into?
Yes, the problem is that the assignments to key->expiry come from key_preparsed_payload-> expiry. I tried the following division:
patch 1 include/linux/key.h security/keys/keyring.c security/keys/permission.c security/keys/process_keys.c security/keys/gc.c security/keys/internal.h
patch 2 include/linux/key-type.h security/keys/key.c
But key.c manipulates structures of type key and key_preparsed_payload.
Arnd
On Friday 27 November 2015 18:55:43 Aya Mahfouz wrote:
My first idea would be to split the key_preparsed_payload changes from the struct key changes. Have you tried that? What problems did you run into?
Yes, the problem is that the assignments to key->expiry come from key_preparsed_payload-> expiry. I tried the following division:
patch 1 include/linux/key.h security/keys/keyring.c security/keys/permission.c security/keys/process_keys.c security/keys/gc.c security/keys/internal.h
patch 2 include/linux/key-type.h security/keys/key.c
But key.c manipulates structures of type key and key_preparsed_payload.
Ok, so splitting the patch by files won't work, but that's rarely possible. It takes a little practice to split up multi-file patches, but it's not hard once you've done it a few times. Here are two methods that I tend to use:
a) 'git reset HEAD^' to undo a commit but leave the changes in place, then do 'git add -p' to selectively add changes I want in one patch, using the 'edit' subcommand when I need to split up changes within a single line.
b) 'git revert HEAD', followed by 'git show HEAD^ | patch -p1' to keep the original patch in place, then undo changes individually until you have a simpler patch to apply. Then do 'git diff HEAD^^ | patch -Rp1' to get back the changes from the original patch in a second commit. Repeat as necessary, then use 'git rebase -i' to reorder the patches as needed and clean out the extra commits.
If there are not too many instances where the two patches clash, I would probably add explicit conversions between time_t and time64_t using a cast to annotate where the first patch is incomplete.
Arnd
On Fri, Nov 27, 2015 at 09:35:22PM +0100, Arnd Bergmann wrote:
On Friday 27 November 2015 18:55:43 Aya Mahfouz wrote:
My first idea would be to split the key_preparsed_payload changes from the struct key changes. Have you tried that? What problems did you run into?
Yes, the problem is that the assignments to key->expiry come from key_preparsed_payload-> expiry. I tried the following division:
patch 1 include/linux/key.h security/keys/keyring.c security/keys/permission.c security/keys/process_keys.c security/keys/gc.c security/keys/internal.h
patch 2 include/linux/key-type.h security/keys/key.c
But key.c manipulates structures of type key and key_preparsed_payload.
Ok, so splitting the patch by files won't work, but that's rarely possible. It takes a little practice to split up multi-file patches, but it's not hard once you've done it a few times. Here are two methods that I tend to use:
a) 'git reset HEAD^' to undo a commit but leave the changes in place, then do 'git add -p' to selectively add changes I want in one patch, using the 'edit' subcommand when I need to split up changes within a single line.
b) 'git revert HEAD', followed by 'git show HEAD^ | patch -p1' to keep the original patch in place, then undo changes individually until you have a simpler patch to apply. Then do 'git diff HEAD^^ | patch -Rp1' to get back the changes from the original patch in a second commit. Repeat as necessary, then use 'git rebase -i' to reorder the patches as needed and clean out the extra commits.
If there are not too many instances where the two patches clash, I would probably add explicit conversions between time_t and time64_t using a cast to annotate where the first patch is incomplete.
Aha! I see. Will get to work! Thanks Arnd! =D
Arnd