krb5 commit: Make rcache file2 code slightly more robust

Greg Hudson ghudson at mit.edu
Mon Jun 10 10:54:55 EDT 2019


https://github.com/krb5/krb5/commit/ce8d619429255e0c1483d7fce3dffdc93baaac20
commit ce8d619429255e0c1483d7fce3dffdc93baaac20
Author: Greg Hudson <ghudson at mit.edu>
Date:   Sat Jun 1 15:08:24 2019 -0400

    Make rcache file2 code slightly more robust
    
    In rc_file2.c:store(), when making note of available records,
    explicitly check for an empty record (r1stamp or t2stamp is 0), to
    more closely match the check for terminating the search.  This
    silences a Coverity false positive, as Coverity does not assume that
    now > skew as it would be in practice.
    
    To preserve code readability, shorten some variable names, add an
    expired() inline helper function, and add comments.

 src/lib/krb5/rcache/rc_file2.c |   30 +++++++++++++++++++++---------
 1 files changed, 21 insertions(+), 9 deletions(-)

diff --git a/src/lib/krb5/rcache/rc_file2.c b/src/lib/krb5/rcache/rc_file2.c
index 6519cc3..10f9a92 100644
--- a/src/lib/krb5/rcache/rc_file2.c
+++ b/src/lib/krb5/rcache/rc_file2.c
@@ -123,6 +123,14 @@ write_record(int fd, off_t offset, const uint8_t tag[TAG_LEN],
     return 0;
 }
 
+/* Return true if timestamp is expired, for the current timestamp (now) and
+ * allowable clock skew. */
+static inline krb5_boolean
+expired(uint32_t timestamp, uint32_t now, uint32_t skew)
+{
+    return ts_after(now, ts_incr(timestamp, skew));
+}
+
 /* Check and store a record into an open and locked file.  fd is assumed to be
  * at offset 0. */
 static krb5_error_code
@@ -134,8 +142,8 @@ store(krb5_context context, int fd, const uint8_t tag[TAG_LEN], uint32_t now,
     off_t table_offset = -1, nrecords = 0, avail_offset = -1, record_offset;
     ssize_t st;
     int ind, nread;
-    uint8_t seed[K5_HASH_SEED_LEN], rec1_tag[TAG_LEN], rec2_tag[TAG_LEN];
-    uint32_t rec1_stamp, rec2_stamp;
+    uint8_t seed[K5_HASH_SEED_LEN], r1tag[TAG_LEN], r2tag[TAG_LEN];
+    uint32_t r1stamp, r2stamp;
 
     /* Read or generate the hash seed. */
     st = read(fd, seed, sizeof(seed));
@@ -161,23 +169,27 @@ store(krb5_context context, int fd, const uint8_t tag[TAG_LEN], uint32_t now,
         ind = k5_siphash24(tag, TAG_LEN, seed) % nrecords;
         record_offset = table_offset + ind * RECORD_LEN;
 
-        ret = read_records(fd, record_offset, rec1_tag, &rec1_stamp, rec2_tag,
-                           &rec2_stamp, &nread);
+        ret = read_records(fd, record_offset, r1tag, &r1stamp, r2tag, &r2stamp,
+                           &nread);
         if (ret)
             return ret;
 
-        if ((nread >= 1 && memcmp(rec1_tag, tag, TAG_LEN) == 0) ||
-            (nread == 2 && memcmp(rec2_tag, tag, TAG_LEN) == 0))
+        if ((nread >= 1 && memcmp(r1tag, tag, TAG_LEN) == 0) ||
+            (nread == 2 && memcmp(r2tag, tag, TAG_LEN) == 0))
             return KRB5KRB_AP_ERR_REPEAT;
 
+        /* Make note of the first record available for writing (empty, beyond
+         * the end of the file, or expired). */
         if (avail_offset == -1) {
-            if (nread == 0 || ts_after(now, ts_incr(rec1_stamp, skew)))
+            if (nread == 0 || !r1stamp || expired(r1stamp, now, skew))
                 avail_offset = record_offset;
-            else if (nread == 1 || ts_after(now, ts_incr(rec2_stamp, skew)))
+            else if (nread == 1 || !r2stamp || expired(r2stamp, now, skew))
                 avail_offset = record_offset + RECORD_LEN;
         }
 
-        if (nread < 2 || rec1_stamp == 0 || rec2_stamp == 0)
+        /* Stop searching if we encountered an empty record or one beyond the
+         * end of the file, as tag would have been written there previously. */
+        if (nread < 2 || !r1stamp || !r2stamp)
             return write_record(fd, avail_offset, tag, now);
 
         /* Use a different hash seed for the next table we search. */


More information about the cvs-krb5 mailing list