rdpdr/drive: fixes for hung peers & info requests

drive_file_init: only allow directories and regular files
This is fixes issue #2071

Even if the server is only interested in getting a file's or directory's
attributes FreeRDP still tries to open the object with read permissions.
If the FreeRDP client has no read permissions for this object the call will
fail which forces the server to perform some expensive workarounds (e.g.
getting to the stat buffers via a directory enumeration request).

On Linux we can try to open the file or directory with the O_PATH flag in
order to obtain a file descriptor who's only purpose is to perform operations
that act purely at the file descriptor level.
This commit is contained in:
Norbert Federa
2014-09-02 15:42:44 +02:00
parent d37af95e70
commit e393499ff8

View File

@@ -49,7 +49,9 @@
#endif
#ifdef HAVE_FCNTL_H
#define __USE_GNU /* for O_PATH */
#include <fcntl.h>
#undef __USE_GNU
#endif
#ifdef _WIN32
@@ -192,6 +194,11 @@ static BOOL drive_file_init(DRIVE_FILE* file, UINT32 DesiredAccess, UINT32 Creat
if (STAT(file->fullpath, &st) == 0)
{
file->is_dir = (S_ISDIR(st.st_mode) ? TRUE : FALSE);
if (!file->is_dir && !S_ISREG(st.st_mode))
{
file->err = EPERM;
return TRUE;
}
#ifndef WIN32
if (st.st_size > (unsigned long) 0x07FFFFFFF)
largeFile = TRUE;
@@ -306,6 +313,25 @@ DRIVE_FILE* drive_file_new(const char* base_path, const char* path, UINT32 id,
return NULL;
}
#if defined(__linux__) && defined(O_PATH)
if (file->fd < 0 && file->err == EACCES)
{
/**
* We have no access permissions for the file or directory but if the
* peer is only interested in reading the object's attributes we can try
* to obtain a file descriptor who's only purpose is to perform
* operations that act purely at the file descriptor level.
* See open(2)
**/
{
if ((file->fd = OPEN(file->fullpath, O_PATH)) >= 0)
{
file->err = 0;
}
}
}
#endif
return file;
}