nfs4: Verify inode number before opening a file

This commit is contained in:
Pawel Dziepak
2012-06-29 02:15:22 +02:00
parent ef629eaf23
commit f7bf941a8c
6 changed files with 113 additions and 20 deletions
@@ -91,7 +91,8 @@ Filesystem::Mount(Filesystem** pfs, RPC::Server* serv, const char* fsPath,
req.GetFH(); req.GetFH();
req.Access(); req.Access();
Attribute attr[] = { FATTR4_FSID, FATTR4_FS_LOCATIONS }; Attribute attr[] = { FATTR4_SUPPORTED_ATTRS, FATTR4_FH_EXPIRE_TYPE,
FATTR4_FSID, FATTR4_FS_LOCATIONS };
req.GetAttr(attr, sizeof(attr) / sizeof(Attribute)); req.GetAttr(attr, sizeof(attr) / sizeof(Attribute));
status_t result = request.Send(); status_t result = request.Send();
@@ -119,22 +120,28 @@ Filesystem::Mount(Filesystem** pfs, RPC::Server* serv, const char* fsPath,
AttrValue* values; AttrValue* values;
uint32 count; uint32 count;
result = reply.GetAttr(&values, &count); result = reply.GetAttr(&values, &count);
if (result != B_OK || count < 1) if (result != B_OK || count < 2)
return result; return result;
Filesystem* fs = new(std::nothrow) Filesystem;
if (fs == NULL)
return B_NO_MEMORY;
// FATTR4_SUPPORTED_ATTRS is mandatory
memcpy(fs->fSupAttrs, &values[0].fData.fValue64, sizeof(fs->fSupAttrs));
// FATTR4_FH_EXPIRE_TYPE is mandatory
fs->fExpireType = values[1].fData.fValue32;
// FATTR4_FSID is mandatory // FATTR4_FSID is mandatory
FilesystemId* fsid = FilesystemId* fsid =
reinterpret_cast<FilesystemId*>(values[0].fData.fPointer); reinterpret_cast<FilesystemId*>(values[2].fData.fPointer);
Filesystem* fs = new(std::nothrow) Filesystem; if (count == 4 && values[3].fAttribute == FATTR4_FS_LOCATIONS) {
if (count == 2 && values[1].fAttribute == FATTR4_FS_LOCATIONS) {
FSLocations* locs = FSLocations* locs =
reinterpret_cast<FSLocations*>(values[1].fData.fLocations); reinterpret_cast<FSLocations*>(values[3].fData.fLocations);
fs->fPath = strdup(locs->fRootPath); fs->fPath = strdup(locs->fRootPath);
delete locs;
} else } else
fs->fPath = NULL; fs->fPath = NULL;
@@ -162,6 +169,7 @@ Filesystem::Mount(Filesystem** pfs, RPC::Server* serv, const char* fsPath,
*pfs = fs; *pfs = fs;
delete[] values;
return B_OK; return B_OK;
} }
@@ -264,6 +272,8 @@ Filesystem::ReadInfo(struct fs_info* info)
info->flags = B_FS_IS_READONLY; info->flags = B_FS_IS_READONLY;
strncpy(info->volume_name, fName, B_FILE_NAME_LENGTH); strncpy(info->volume_name, fName, B_FILE_NAME_LENGTH);
delete[] values;
return B_OK; return B_OK;
} }
@@ -310,6 +320,7 @@ Filesystem::Migrate(const Filehandle& fh, const RPC::Server* serv)
reinterpret_cast<module_info**>(&dns)); reinterpret_cast<module_info**>(&dns));
if (result != B_OK) { if (result != B_OK) {
mutex_unlock(&fMigrationLock); mutex_unlock(&fMigrationLock);
delete[] values;
return result; return result;
} }
@@ -337,7 +348,7 @@ Filesystem::Migrate(const Filehandle& fh, const RPC::Server* serv)
} }
put_module(DNS_RESOLVER_MODULE_NAME); put_module(DNS_RESOLVER_MODULE_NAME);
delete locs; delete[] values;
if (server == fServer) { if (server == fServer) {
mutex_unlock(&fMigrationLock); mutex_unlock(&fMigrationLock);
@@ -33,6 +33,9 @@ public:
status_t Migrate(const Filehandle& fh, status_t Migrate(const Filehandle& fh,
const RPC::Server* serv); const RPC::Server* serv);
inline bool IsAttrSupported(Attribute attr) const;
inline uint32 ExpireType() const;
inline RPC::Server* Server(); inline RPC::Server* Server();
inline NFS4Server* NFSServer(); inline NFS4Server* NFSServer();
@@ -46,6 +49,9 @@ public:
private: private:
Filesystem(); Filesystem();
uint32 fExpireType;
uint32 fSupAttrs[2];
FilesystemId fFsId; FilesystemId fFsId;
const char* fPath; const char* fPath;
mutex fMigrationLock; mutex fMigrationLock;
@@ -63,6 +69,20 @@ private:
}; };
inline bool
Filesystem::IsAttrSupported(Attribute attr) const
{
return sIsAttrSet(attr, fSupAttrs, 2);
}
inline uint32
Filesystem::ExpireType() const
{
return fExpireType;
}
inline RPC::Server* inline RPC::Server*
Filesystem::Server() Filesystem::Server()
{ {
+38 -1
View File
@@ -819,8 +819,28 @@ Inode::Open(int mode, OpenFileCookie* cookie)
cookie->fOwnerId = atomic_add64(&cookie->fLastOwnerId, 1); cookie->fOwnerId = atomic_add64(&cookie->fLastOwnerId, 1);
req.PutFH(fParentFH); // Since we are opening the file using a pair (parentFH, name) we
// need to check for race conditions.
if (fFilesystem->IsAttrSupported(FATTR4_FILEID)) {
req.PutFH(fParentFH);
req.LookUp(fName);
AttrValue attr;
attr.fAttribute = FATTR4_FILEID;
attr.fFreePointer = false;
attr.fData.fValue64 = fFileId;
req.Verify(&attr, 1);
} else if (fFilesystem->ExpireType() == FH4_PERSISTENT) {
req.PutFH(fParentFH);
req.LookUp(fName);
AttrValue attr;
attr.fAttribute = FATTR4_FILEHANDLE;
attr.fFreePointer = true;
attr.fData.fPointer = malloc(sizeof(fHandle));
memcpy(attr.fData.fPointer, &fHandle, sizeof(fHandle));
req.Verify(&attr, 1);
}
req.PutFH(fParentFH);
if ((mode & O_TRUNC) == O_TRUNC) { if ((mode & O_TRUNC) == O_TRUNC) {
AttrValue attr; AttrValue attr;
attr.fAttribute = FATTR4_SIZE; attr.fAttribute = FATTR4_SIZE;
@@ -844,6 +864,21 @@ Inode::Open(int mode, OpenFileCookie* cookie)
if (_HandleErrors(reply.NFS4Error(), serv)) if (_HandleErrors(reply.NFS4Error(), serv))
continue; continue;
// Verify if the file we want to open is the file this Inode
// represents.
if (fFilesystem->IsAttrSupported(FATTR4_FILEID) ||
fFilesystem->ExpireType() == FH4_PERSISTENT) {
reply.PutFH();
result = reply.LookUp();
if (result != B_OK)
return result;
result = reply.Verify();
if (result != B_OK && reply.NFS4Error() == NFS4ERR_NOT_SAME)
return B_ENTRY_NOT_FOUND;
else if (result != B_OK)
return result;
}
reply.PutFH(); reply.PutFH();
result = reply.Open(cookie->fStateId, &cookie->fStateSeq, &confirm); result = reply.Open(cookie->fStateId, &cookie->fStateSeq, &confirm);
if (result != B_OK) if (result != B_OK)
@@ -1191,6 +1226,8 @@ Inode::_ReadDirUp(struct dirent* de, uint32 pos, uint32 size)
} else } else
fileId = values[0].fData.fValue64; fileId = values[0].fData.fValue64;
delete[] values;
return _FillDirEntry(de, _FileIdToInoT(fileId), "..", pos, size); return _FillDirEntry(de, _FileIdToInoT(fileId), "..", pos, size);
} while (true); } while (true);
} }
@@ -124,6 +124,17 @@ enum Attribute {
FATTR4_MAXIMUM_ATTR_ID FATTR4_MAXIMUM_ATTR_ID
}; };
static inline bool sIsAttrSet(Attribute attr, const uint32* bitmap,
uint32 count)
{
if ((uint32)attr / 32 >= count)
return false;
return (bitmap[attr / 32] & 1 << attr % 32) != 0;
}
enum FileType { enum FileType {
NF4REG = 1, /* Regular File */ NF4REG = 1, /* Regular File */
NF4DIR = 2, /* Directory */ NF4DIR = 2, /* Directory */
@@ -154,15 +154,6 @@ static inline uint32 sCountBits(uint32 v)
} }
static inline bool sIsAttrSet(Attribute attr, uint32* bitmap, uint32 count)
{
if ((uint32)attr / 32 >= count)
return false;
return (bitmap[attr / 32] & 1 << attr % 32) != 0;
}
status_t status_t
ReplyInterpreter::GetAttr(AttrValue** attrs, uint32* count) ReplyInterpreter::GetAttr(AttrValue** attrs, uint32* count)
{ {
@@ -513,6 +504,18 @@ ReplyInterpreter::_DecodeAttrs(XDR::ReadStream& str, AttrValue** attrs,
uint32 current = 0; uint32 current = 0;
if (sIsAttrSet(FATTR4_SUPPORTED_ATTRS, bitmap, bcount)) {
values[current].fAttribute = FATTR4_SUPPORTED_ATTRS;
uint32 count = stream.GetInt();
uint32 i;
// two uint32 are enough for NFS4, not for NFS4.1
for (i = 0; i < min_c(count, 2); i++)
((uint32*)&values[current].fData.fValue64)[i] = stream.GetUInt();
for (; i < count; i++)
stream.GetUInt();
current++;
}
if (sIsAttrSet(FATTR4_TYPE, bitmap, bcount)) { if (sIsAttrSet(FATTR4_TYPE, bitmap, bcount)) {
values[current].fAttribute = FATTR4_TYPE; values[current].fAttribute = FATTR4_TYPE;
values[current].fData.fValue32 = stream.GetInt(); values[current].fData.fValue32 = stream.GetInt();
@@ -716,6 +716,17 @@ RequestBuilder::_EncodeAttrs(XDR::WriteStream& stream, AttrValue* attr,
i++; i++;
} }
if (i < count && attr[i].fAttribute == FATTR4_FILEHANDLE) {
Filehandle* fh = reinterpret_cast<Filehandle*>(attr[i].fData.fPointer);
str.AddOpaque(fh->fFH, fh->fSize);
i++;
}
if (i < count && attr[i].fAttribute == FATTR4_FILEID) {
str.AddUHyper(attr[i].fData.fValue64);
i++;
}
if (i < count && attr[i].fAttribute == FATTR4_MODE) { if (i < count && attr[i].fAttribute == FATTR4_MODE) {
str.AddUInt(attr[i].fData.fValue32); str.AddUInt(attr[i].fData.fValue32);
i++; i++;