nfs4: readdir() should not read more than requested
Additionally, file attribute decoding checks more strictly whether received data are sane.
This commit is contained in:
@@ -65,7 +65,6 @@ Inode::Inode(Filesystem* fs, const Filehandle &fh, bool root)
|
|||||||
status_t
|
status_t
|
||||||
Inode::LookUp(const char* name, ino_t* id)
|
Inode::LookUp(const char* name, ino_t* id)
|
||||||
{
|
{
|
||||||
dprintf("nfs4: lookup: %s\n", name);
|
|
||||||
if (fType != NF4DIR)
|
if (fType != NF4DIR)
|
||||||
return B_NOT_A_DIRECTORY;
|
return B_NOT_A_DIRECTORY;
|
||||||
|
|
||||||
@@ -338,7 +337,7 @@ Inode::ReadDir(void* _buffer, uint32 size, uint32* _count, uint64* cookie)
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (count < *_count && !eof) {
|
while (count < *_count && !eof) {
|
||||||
this_count = *_count;
|
this_count = *_count - count;
|
||||||
DirEntry* dirents;
|
DirEntry* dirents;
|
||||||
|
|
||||||
status_t result = _ReadDirOnce(&dirents, &this_count, cookie, &eof);
|
status_t result = _ReadDirOnce(&dirents, &this_count, cookie, &eof);
|
||||||
@@ -346,7 +345,7 @@ Inode::ReadDir(void* _buffer, uint32 size, uint32* _count, uint64* cookie)
|
|||||||
return result;
|
return result;
|
||||||
|
|
||||||
uint32 i;
|
uint32 i;
|
||||||
for (i = 0; i < this_count; i++) {
|
for (i = 0; i < min_c(this_count, *_count - count); i++) {
|
||||||
struct dirent* de = reinterpret_cast<dirent*>(buffer + pos);
|
struct dirent* de = reinterpret_cast<dirent*>(buffer + pos);
|
||||||
|
|
||||||
ino_t id;
|
ino_t id;
|
||||||
@@ -371,7 +370,7 @@ Inode::ReadDir(void* _buffer, uint32 size, uint32* _count, uint64* cookie)
|
|||||||
return B_BUFFER_OVERFLOW;
|
return B_BUFFER_OVERFLOW;
|
||||||
|
|
||||||
*_count = count;
|
*_count = count;
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -99,7 +99,8 @@ enum Attribute {
|
|||||||
FATTR4_TIME_METADATA = 52,
|
FATTR4_TIME_METADATA = 52,
|
||||||
FATTR4_TIME_MODIFY = 53,
|
FATTR4_TIME_MODIFY = 53,
|
||||||
FATTR4_TIME_MODIFY_SET = 54,
|
FATTR4_TIME_MODIFY_SET = 54,
|
||||||
FATTR4_MOUNTED_ON_FILEID = 55
|
FATTR4_MOUNTED_ON_FILEID = 55,
|
||||||
|
FATTR4_MAXIMUM_ATTR_ID
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FileType {
|
enum FileType {
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ ReplyInterpreter::ReadDir(uint64* cookie, DirEntry** dirents, uint32* _count,
|
|||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ReplyInterpreter::_DecodeAttrs(XDR::ReadStream& str, AttrValue** attrs,
|
ReplyInterpreter::_DecodeAttrs(XDR::ReadStream& str, AttrValue** attrs,
|
||||||
uint32* count)
|
uint32* count)
|
||||||
@@ -170,6 +171,13 @@ ReplyInterpreter::_DecodeAttrs(XDR::ReadStream& str, AttrValue** attrs,
|
|||||||
attr_count += sCountBits(bitmap[i]);
|
attr_count += sCountBits(bitmap[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (attr_count == 0) {
|
||||||
|
*attrs = NULL;
|
||||||
|
*count = 0;
|
||||||
|
return B_OK;
|
||||||
|
} else if (attr_count > FATTR4_MAXIMUM_ATTR_ID)
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
uint32 size;
|
uint32 size;
|
||||||
const void* ptr = str.GetOpaque(&size);
|
const void* ptr = str.GetOpaque(&size);
|
||||||
XDR::ReadStream stream(const_cast<void*>(ptr), size);
|
XDR::ReadStream stream(const_cast<void*>(ptr), size);
|
||||||
|
|||||||
Reference in New Issue
Block a user