Compare commits

..

1 Commits

Author SHA1 Message Date
Christopher Haster
8628d5e1f1 Fixed buffer overflow due to mistaking prog_size for cache_size
found by ajaybhargav
2019-04-12 08:41:42 -05:00
4 changed files with 19 additions and 33 deletions

View File

@@ -139,7 +139,7 @@ jobs:
install: install:
- sudo apt-get install libfuse-dev - sudo apt-get install libfuse-dev
- git clone --depth 1 https://github.com/geky/littlefs-fuse -b v2-alpha v2 - git clone --depth 1 https://github.com/geky/littlefs-fuse -b v2-alpha v2
- git clone --depth 1 https://github.com/geky/littlefs-fuse -b v1 v1 - git clone --depth 1 https://github.com/geky/littlefs-fuse v1
- fusermount -V - fusermount -V
- gcc --version - gcc --version
before_script: before_script:

41
lfs.c
View File

@@ -29,7 +29,7 @@ static inline void lfs_cache_drop(lfs_t *lfs, lfs_cache_t *rcache) {
static inline void lfs_cache_zero(lfs_t *lfs, lfs_cache_t *pcache) { static inline void lfs_cache_zero(lfs_t *lfs, lfs_cache_t *pcache) {
// zero to avoid information leak // zero to avoid information leak
memset(pcache->buffer, 0xff, lfs->cfg->prog_size); memset(pcache->buffer, 0xff, lfs->cfg->cache_size);
pcache->block = 0xffffffff; pcache->block = 0xffffffff;
} }
@@ -827,8 +827,7 @@ static lfs_stag_t lfs_dir_fetchmatch(lfs_t *lfs,
// next commit not yet programmed or we're not in valid range // next commit not yet programmed or we're not in valid range
if (!lfs_tag_isvalid(tag) || if (!lfs_tag_isvalid(tag) ||
off + lfs_tag_dsize(tag) > lfs->cfg->block_size) { off + lfs_tag_dsize(tag) > lfs->cfg->block_size) {
dir->erased = (lfs_tag_type1(ptag) == LFS_TYPE_CRC && dir->erased = (lfs_tag_type1(ptag) == LFS_TYPE_CRC);
dir->off % lfs->cfg->prog_size == 0);
break; break;
} }
@@ -855,7 +854,7 @@ static lfs_stag_t lfs_dir_fetchmatch(lfs_t *lfs,
} }
// reset the next bit if we need to // reset the next bit if we need to
ptag ^= (lfs_tag_chunk(tag) & 1U) << 31; ptag ^= (lfs_tag_chunk(tag) & 1) << 31;
// toss our crc into the filesystem seed for // toss our crc into the filesystem seed for
// pseudorandom numbers // pseudorandom numbers
@@ -1437,10 +1436,8 @@ static int lfs_dir_compact(lfs_t *lfs,
// space is complicated, we need room for tail, crc, gstate, // space is complicated, we need room for tail, crc, gstate,
// cleanup delete, and we cap at half a block to give room // cleanup delete, and we cap at half a block to give room
// for metadata updates. // for metadata updates.
if (end - begin < 0xff && if (size <= lfs_min(lfs->cfg->block_size - 36,
size <= lfs_min(lfs->cfg->block_size - 36, lfs_alignup(lfs->cfg->block_size/2, lfs->cfg->prog_size))) {
lfs_alignup(lfs->cfg->block_size/2,
lfs->cfg->prog_size))) {
break; break;
} }
@@ -1500,7 +1497,7 @@ static int lfs_dir_compact(lfs_t *lfs,
// begin loop to commit compaction to blocks until a compact sticks // begin loop to commit compaction to blocks until a compact sticks
while (true) { while (true) {
{ if (true) {
// There's nothing special about our global delta, so feed it into // There's nothing special about our global delta, so feed it into
// our local global delta // our local global delta
int err = lfs_dir_getgstate(lfs, dir, &lfs->gdelta); int err = lfs_dir_getgstate(lfs, dir, &lfs->gdelta);
@@ -1599,12 +1596,13 @@ static int lfs_dir_compact(lfs_t *lfs,
dir->count = end - begin; dir->count = end - begin;
dir->off = commit.off; dir->off = commit.off;
dir->etag = commit.ptag; dir->etag = commit.ptag;
dir->erased = (dir->off % lfs->cfg->prog_size == 0); dir->erased = true;
// note we able to have already handled move here // note we able to have already handled move here
if (lfs_gstate_hasmovehere(&lfs->gpending, dir->pair)) { if (lfs_gstate_hasmovehere(&lfs->gpending, dir->pair)) {
lfs_gstate_xormove(&lfs->gpending, lfs_gstate_xormove(&lfs->gpending,
&lfs->gpending, 0x3ff, NULL); &lfs->gpending, 0x3ff, NULL);
} }
} }
break; break;
@@ -1713,7 +1711,7 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,
} }
} }
if (dir->erased || dir->count >= 0xff) { if (dir->erased) {
// try to commit // try to commit
struct lfs_commit commit = { struct lfs_commit commit = {
.block = dir->pair[0], .block = dir->pair[0],
@@ -2124,7 +2122,7 @@ static int lfs_ctz_extend(lfs_t *lfs,
} }
LFS_ASSERT(nblock >= 2 && nblock <= lfs->cfg->block_count); LFS_ASSERT(nblock >= 2 && nblock <= lfs->cfg->block_count);
{ if (true) {
err = lfs_bd_erase(lfs, nblock); err = lfs_bd_erase(lfs, nblock);
if (err) { if (err) {
if (err == LFS_ERR_CORRUPT) { if (err == LFS_ERR_CORRUPT) {
@@ -2383,8 +2381,7 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
if (file->ctz.size > 0) { if (file->ctz.size > 0) {
lfs_stag_t res = lfs_dir_get(lfs, &file->m, lfs_stag_t res = lfs_dir_get(lfs, &file->m,
LFS_MKTAG(0x700, 0x3ff, 0), LFS_MKTAG(0x700, 0x3ff, 0),
LFS_MKTAG(LFS_TYPE_STRUCT, file->id, LFS_MKTAG(LFS_TYPE_STRUCT, file->id, file->cache.size),
lfs_min(file->cache.size, 0x3fe)),
file->cache.buffer); file->cache.buffer);
if (res < 0) { if (res < 0) {
err = res; err = res;
@@ -2579,7 +2576,6 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
while (true) { while (true) {
int err = lfs_file_flush(lfs, file); int err = lfs_file_flush(lfs, file);
if (err) { if (err) {
file->flags |= LFS_F_ERRED;
return err; return err;
} }
@@ -2615,7 +2611,6 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
if (err == LFS_ERR_NOSPC && (file->flags & LFS_F_INLINE)) { if (err == LFS_ERR_NOSPC && (file->flags & LFS_F_INLINE)) {
goto relocate; goto relocate;
} }
file->flags |= LFS_F_ERRED;
return err; return err;
} }
@@ -2629,7 +2624,6 @@ relocate:
file->off = file->pos; file->off = file->pos;
err = lfs_file_relocate(lfs, file); err = lfs_file_relocate(lfs, file);
if (err) { if (err) {
file->flags |= LFS_F_ERRED;
return err; return err;
} }
} }
@@ -2864,10 +2858,6 @@ int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
return LFS_ERR_BADF; return LFS_ERR_BADF;
} }
if (size > LFS_FILE_MAX) {
return LFS_ERR_INVAL;
}
lfs_off_t oldsize = lfs_file_size(lfs, file); lfs_off_t oldsize = lfs_file_size(lfs, file);
if (size < oldsize) { if (size < oldsize) {
// need to flush since directly changing metadata // need to flush since directly changing metadata
@@ -3233,9 +3223,8 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
lfs_cache_zero(lfs, &lfs->pcache); lfs_cache_zero(lfs, &lfs->pcache);
// setup lookahead, must be multiple of 64-bits // setup lookahead, must be multiple of 64-bits
LFS_ASSERT(lfs->cfg->lookahead_size % 8 == 0);
LFS_ASSERT(lfs->cfg->lookahead_size > 0); LFS_ASSERT(lfs->cfg->lookahead_size > 0);
LFS_ASSERT(lfs->cfg->lookahead_size % 8 == 0 &&
(uintptr_t)lfs->cfg->lookahead_buffer % 8 == 0);
if (lfs->cfg->lookahead_buffer) { if (lfs->cfg->lookahead_buffer) {
lfs->free.buffer = lfs->cfg->lookahead_buffer; lfs->free.buffer = lfs->cfg->lookahead_buffer;
} else { } else {
@@ -3303,7 +3292,7 @@ static int lfs_deinit(lfs_t *lfs) {
int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) { int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
int err = 0; int err = 0;
{ if (true) {
err = lfs_init(lfs, cfg); err = lfs_init(lfs, cfg);
if (err) { if (err) {
return err; return err;
@@ -4187,7 +4176,7 @@ static int lfs1_moved(lfs_t *lfs, const void *e) {
static int lfs1_mount(lfs_t *lfs, struct lfs1 *lfs1, static int lfs1_mount(lfs_t *lfs, struct lfs1 *lfs1,
const struct lfs_config *cfg) { const struct lfs_config *cfg) {
int err = 0; int err = 0;
{ if (true) {
err = lfs_init(lfs, cfg); err = lfs_init(lfs, cfg);
if (err) { if (err) {
return err; return err;
@@ -4258,7 +4247,7 @@ int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg) {
return err; return err;
} }
{ if (true) {
// iterate through each directory, copying over entries // iterate through each directory, copying over entries
// into new directory // into new directory
lfs1_dir_t dir1; lfs1_dir_t dir1;

8
lfs.h
View File

@@ -215,9 +215,8 @@ struct lfs_config {
// By default lfs_malloc is used to allocate this buffer. // By default lfs_malloc is used to allocate this buffer.
void *prog_buffer; void *prog_buffer;
// Optional statically allocated lookahead buffer. Must be lookahead_size // Optional statically allocated program buffer. Must be lookahead_size.
// and aligned to a 64-bit boundary. By default lfs_malloc is used to // By default lfs_malloc is used to allocate this buffer.
// allocate this buffer.
void *lookahead_buffer; void *lookahead_buffer;
// Optional upper limit on length of file names in bytes. No downside for // Optional upper limit on length of file names in bytes. No downside for
@@ -578,8 +577,7 @@ int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir);
// Read an entry in the directory // Read an entry in the directory
// //
// Fills out the info structure, based on the specified file or directory. // Fills out the info structure, based on the specified file or directory.
// Returns a positive value on success, 0 at the end of directory, // Returns a negative error code on failure.
// or a negative error code on failure.
int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info); int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info);
// Change the position of the directory // Change the position of the directory

View File

@@ -192,7 +192,6 @@ static inline uint32_t lfs_tobe32(uint32_t a) {
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size); uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size);
// Allocate memory, only used if buffers are not provided to littlefs // Allocate memory, only used if buffers are not provided to littlefs
// Note, memory must be 64-bit aligned
static inline void *lfs_malloc(size_t size) { static inline void *lfs_malloc(size_t size) {
#ifndef LFS_NO_MALLOC #ifndef LFS_NO_MALLOC
return malloc(size); return malloc(size);