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 34 additions and 34 deletions

View File

@@ -136,11 +136,10 @@ jobs:
env:
- STAGE=test
- NAME=littlefs-migration
if: branch !~ -prefix$
install:
- 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 v1 v1
- git clone --depth 1 https://github.com/geky/littlefs-fuse v1
- fusermount -V
- gcc --version
before_script:

56
lfs.c
View File

@@ -80,6 +80,21 @@ static int lfs_bd_read(lfs_t *lfs,
diff = lfs_min(diff, rcache->off-off);
}
if (size >= hint && off % lfs->cfg->read_size == 0 &&
size >= lfs->cfg->read_size) {
// bypass cache?
diff = lfs_aligndown(diff, lfs->cfg->read_size);
int err = lfs->cfg->read(lfs->cfg, block, off, data, diff);
if (err) {
return err;
}
data += diff;
off += diff;
size -= diff;
continue;
}
// load to cache, first condition can no longer fail
LFS_ASSERT(block < lfs->cfg->block_count);
rcache->block = block;
@@ -812,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
if (!lfs_tag_isvalid(tag) ||
off + lfs_tag_dsize(tag) > lfs->cfg->block_size) {
dir->erased = (lfs_tag_type1(ptag) == LFS_TYPE_CRC &&
dir->off % lfs->cfg->prog_size == 0);
dir->erased = (lfs_tag_type1(ptag) == LFS_TYPE_CRC);
break;
}
@@ -840,7 +854,7 @@ static lfs_stag_t lfs_dir_fetchmatch(lfs_t *lfs,
}
// 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
// pseudorandom numbers
@@ -1422,10 +1436,8 @@ static int lfs_dir_compact(lfs_t *lfs,
// space is complicated, we need room for tail, crc, gstate,
// cleanup delete, and we cap at half a block to give room
// for metadata updates.
if (end - begin < 0xff &&
size <= lfs_min(lfs->cfg->block_size - 36,
lfs_alignup(lfs->cfg->block_size/2,
lfs->cfg->prog_size))) {
if (size <= lfs_min(lfs->cfg->block_size - 36,
lfs_alignup(lfs->cfg->block_size/2, lfs->cfg->prog_size))) {
break;
}
@@ -1485,7 +1497,7 @@ static int lfs_dir_compact(lfs_t *lfs,
// begin loop to commit compaction to blocks until a compact sticks
while (true) {
{
if (true) {
// There's nothing special about our global delta, so feed it into
// our local global delta
int err = lfs_dir_getgstate(lfs, dir, &lfs->gdelta);
@@ -1584,12 +1596,13 @@ static int lfs_dir_compact(lfs_t *lfs,
dir->count = end - begin;
dir->off = commit.off;
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
if (lfs_gstate_hasmovehere(&lfs->gpending, dir->pair)) {
lfs_gstate_xormove(&lfs->gpending,
&lfs->gpending, 0x3ff, NULL);
}
}
break;
@@ -1698,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
struct lfs_commit commit = {
.block = dir->pair[0],
@@ -2109,7 +2122,7 @@ static int lfs_ctz_extend(lfs_t *lfs,
}
LFS_ASSERT(nblock >= 2 && nblock <= lfs->cfg->block_count);
{
if (true) {
err = lfs_bd_erase(lfs, nblock);
if (err) {
if (err == LFS_ERR_CORRUPT) {
@@ -2368,8 +2381,7 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
if (file->ctz.size > 0) {
lfs_stag_t res = lfs_dir_get(lfs, &file->m,
LFS_MKTAG(0x700, 0x3ff, 0),
LFS_MKTAG(LFS_TYPE_STRUCT, file->id,
lfs_min(file->cache.size, 0x3fe)),
LFS_MKTAG(LFS_TYPE_STRUCT, file->id, file->cache.size),
file->cache.buffer);
if (res < 0) {
err = res;
@@ -2564,7 +2576,6 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
while (true) {
int err = lfs_file_flush(lfs, file);
if (err) {
file->flags |= LFS_F_ERRED;
return err;
}
@@ -2600,7 +2611,6 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
if (err == LFS_ERR_NOSPC && (file->flags & LFS_F_INLINE)) {
goto relocate;
}
file->flags |= LFS_F_ERRED;
return err;
}
@@ -2614,7 +2624,6 @@ relocate:
file->off = file->pos;
err = lfs_file_relocate(lfs, file);
if (err) {
file->flags |= LFS_F_ERRED;
return err;
}
}
@@ -2734,7 +2743,7 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
if ((file->flags & LFS_F_INLINE) &&
lfs_max(file->pos+nsize, file->ctz.size) >
lfs_min(0x3fe, lfs_min(
lfs_min(LFS_ATTR_MAX, lfs_min(
lfs->cfg->cache_size, lfs->cfg->block_size/8))) {
// inline file doesn't fit anymore
file->off = file->pos;
@@ -2849,10 +2858,6 @@ int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) {
return LFS_ERR_BADF;
}
if (size > LFS_FILE_MAX) {
return LFS_ERR_INVAL;
}
lfs_off_t oldsize = lfs_file_size(lfs, file);
if (size < oldsize) {
// need to flush since directly changing metadata
@@ -3218,9 +3223,8 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) {
lfs_cache_zero(lfs, &lfs->pcache);
// 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 % 8 == 0 &&
(uintptr_t)lfs->cfg->lookahead_buffer % 8 == 0);
if (lfs->cfg->lookahead_buffer) {
lfs->free.buffer = lfs->cfg->lookahead_buffer;
} else {
@@ -3288,7 +3292,7 @@ static int lfs_deinit(lfs_t *lfs) {
int lfs_format(lfs_t *lfs, const struct lfs_config *cfg) {
int err = 0;
{
if (true) {
err = lfs_init(lfs, cfg);
if (err) {
return err;
@@ -4172,7 +4176,7 @@ static int lfs1_moved(lfs_t *lfs, const void *e) {
static int lfs1_mount(lfs_t *lfs, struct lfs1 *lfs1,
const struct lfs_config *cfg) {
int err = 0;
{
if (true) {
err = lfs_init(lfs, cfg);
if (err) {
return err;
@@ -4243,7 +4247,7 @@ int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg) {
return err;
}
{
if (true) {
// iterate through each directory, copying over entries
// into new directory
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.
void *prog_buffer;
// Optional statically allocated lookahead buffer. Must be lookahead_size
// and aligned to a 64-bit boundary. By default lfs_malloc is used to
// allocate this buffer.
// Optional statically allocated program buffer. Must be lookahead_size.
// By default lfs_malloc is used to allocate this buffer.
void *lookahead_buffer;
// 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
//
// Fills out the info structure, based on the specified file or directory.
// Returns a positive value on success, 0 at the end of directory,
// or a negative error code on failure.
// Returns a negative error code on failure.
int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info);
// 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);
// 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) {
#ifndef LFS_NO_MALLOC
return malloc(size);