Add qt_safe_ftok wrapper for ftok

The ftok function unfortunately can return duplicate keys even for different
files if the same project id is used. This is discussed e.g. in Stevens'
"Advanced Programming in the UNIX Environment".

We want the key to be predictable so we cannot just pass a random number as
the project id. To reduce the propability of key collisions we hash the file
name with the project number as seed for a predictable value. This is the same
approach taken e.g. by Apache, but the real fix is to move away from System V
IPC completely once this is feasible on our supported platforms.

Task-number: QTBUG-48375
Change-Id: If1a57f215f7ddd147aa38919907cfb83db07aea0
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Louai Al-Khanji
2015-09-30 05:35:16 +00:00
parent 813f468a14
commit ac0184d608
3 changed files with 16 additions and 2 deletions
+14
View File
@@ -47,6 +47,7 @@
#include "qplatformdefs.h"
#include "qatomic.h"
#include "qhash.h"
#ifndef Q_OS_UNIX
# error "qcore_unix_p.h included on a non-Unix system"
@@ -322,6 +323,19 @@ union qt_semun {
unsigned short *array; /* array for GETALL, SETALL */
};
#ifndef QT_POSIX_IPC
#ifndef QT_NO_SHAREDMEMORY
#ifndef Q_OS_ANDROID
static inline key_t qt_safe_ftok(const QByteArray &filename, int proj_id)
{
// Unfortunately ftok can return colliding keys even for different files.
// Try to add some more entropy via qHash.
return ::ftok(filename.constData(), qHash(filename, proj_id));
}
#endif // !Q_OS_ANDROID
#endif // !QT_NO_SHAREDMEMORY
#endif // !QT_POSIX_IPC
QT_END_NAMESPACE
#endif
+1 -1
View File
@@ -82,7 +82,7 @@ key_t QSharedMemoryPrivate::handle()
return 0;
}
unix_key = ftok(QFile::encodeName(nativeKey).constData(), 'Q');
unix_key = qt_safe_ftok(QFile::encodeName(nativeKey), 'Q');
if (-1 == unix_key) {
errorString = QSharedMemory::tr("%1: ftok failed").arg(QLatin1String("QSharedMemory::handle:"));
error = QSharedMemory::KeyError;
@@ -85,7 +85,7 @@ key_t QSystemSemaphorePrivate::handle(QSystemSemaphore::AccessMode mode)
createdFile = (1 == built);
// Get the unix key for the created file
unix_key = ftok(QFile::encodeName(fileName).constData(), 'Q');
unix_key = qt_safe_ftok(QFile::encodeName(fileName), 'Q');
if (-1 == unix_key) {
errorString = QCoreApplication::tr("%1: ftok failed", "QSystemSemaphore").arg(QLatin1String("QSystemSemaphore::handle:"));
error = QSystemSemaphore::KeyError;