--- src/util/disk_cache.c | 37 ++++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-)
diff --git a/src/util/disk_cache.c b/src/util/disk_cache.c index f5e1145..2a0edca 100644 --- a/src/util/disk_cache.c +++ b/src/util/disk_cache.c @@ -31,20 +31,21 @@ #include <sys/file.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/mman.h> #include <unistd.h> #include <fcntl.h> #include <pwd.h> #include <errno.h> #include <dirent.h> +#include "util/crc32.h" #include "util/u_atomic.h" #include "util/mesa-sha1.h" #include "util/ralloc.h" #include "main/errors.h" #include "disk_cache.h" /* Number of bits to mask off from a cache key to get an index. */ #define CACHE_INDEX_KEY_BITS 16 @@ -702,34 +703,48 @@ disk_cache_put(struct disk_cache *cache, /* OK, we're now on the hook to write out a file that we know is * not in the cache, and is also not being written out to the cache * by some other process. * * Before we do that, if the cache is too large, evict something * else first. */ if (*cache->size + size > cache->max_size) evict_random_item(cache); + /* Create CRC of the data and store at the start of the file. We will + * read this when restoring the cache and use it to check for corruption. + */ + uint32_t crc32 = util_hash_crc32(data, size); + size_t crc_size = sizeof(crc32); + for (len = 0; len < crc_size; len += ret) { + ret = write(fd, &crc32, crc_size - len); + if (ret == -1) { + unlink(filename_tmp); + goto done; + } + } + /* Now, finally, write out the contents to the temporary file, then * rename them atomically to the destination filename, and also * perform an atomic increment of the total cache size. */ for (len = 0; len < size; len += ret) { ret = write(fd, p + len, size - len); if (ret == -1) { unlink(filename_tmp); goto done; } } rename(filename_tmp, filename); + size += crc_size; p_atomic_add(cache->size, size); done: if (fd_final != -1) close(fd_final); /* This close finally releases the flock, (now that the final dile * has been renamed into place and the size has been added). */ if (fd != -1) close(fd); @@ -758,31 +773,47 @@ disk_cache_get(struct disk_cache *cache, cache_key key, size_t *size) if (fd == -1) goto fail; if (fstat(fd, &sb) == -1) goto fail; data = malloc(sb.st_size); if (data == NULL) goto fail; - for (len = 0; len < sb.st_size; len += ret) { - ret = read(fd, data + len, sb.st_size - len); + /* Load the CRC that was created when the file was written. */ + uint32_t crc32; + size_t crc_size = sizeof(crc32); + assert(sb.st_size > crc_size); + for (len = 0; len < crc_size; len += ret) { + ret = read(fd, &crc32 + len, crc_size - len); if (ret == -1) goto fail; } + /* Load the actual cache data. */ + size_t cache_data_size = sb.st_size - crc_size; + for (len = 0; len < cache_data_size; len += ret) { + ret = read(fd, data + len, cache_data_size - len); + if (ret == -1) + goto fail; + } + + /* Check the data for corruption */ + if (crc32 != util_hash_crc32(data, cache_data_size)) + goto fail; + free(filename); close(fd); if (size) - *size = sb.st_size; + *size = cache_data_size; return data; fail: if (data) free(data); if (filename) free(filename); if (fd != -1) close(fd); -- 2.9.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev