Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[fsstorageplugin] Implement symlink policy. JB#44457
If buteo-mtp bumps upon symlinks, they are followed indiscriminately - which
allows escaping from storage directory boundaries and/or blacklist
configuration.

While the current behavior can be considered as a feature, sometimes it might
be desirable to limit whether and what kind of symlinks are followed.

Implement symbolic link policy, controlled by environment variable
BUTEO_MTP_SYMLINK_POLICY, which can have one of the following values:

- AllowAll - symbolic links are always followed
- DenyAll - all symbolic links are ignored
- AllowWithinStorage - symbolic links that stay within the storage
  are followed

By default "AllowAll" is selected, i.e. buteo-mtp behaves like before.

Signed-off-by: Simo Piiroinen <simo.piiroinen@jollamobile.com>
  • Loading branch information
spiiroin committed Feb 28, 2019
1 parent f05ed72 commit ee0a28c
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 1 deletion.
71 changes: 70 additions & 1 deletion mts/platform/storage/fsstorageplugin/fsstorageplugin.cpp
Expand Up @@ -379,7 +379,7 @@ static void file_set_mtime(const QString &path, time_t t)
FSStoragePlugin::FSStoragePlugin( quint32 storageId, MTPStorageType storageType, QString storagePath,
QString volumeLabel, QString storageDescription ) :
StoragePlugin(storageId),
m_storagePath(QDir(storagePath).absolutePath()),
m_storagePath(QDir(storagePath).canonicalPath()),
m_root(0),
m_writeObjectHandle(0),
m_largestPuoid(0),
Expand Down Expand Up @@ -1144,6 +1144,45 @@ StorageItem* FSStoragePlugin::findStorageItemByPath( const QString &path )
return storageItem;
}

FSStoragePlugin::SymLinkPolicy FSStoragePlugin::s_symLinkPolicy = SymLinkPolicy::Undefined;

FSStoragePlugin::SymLinkPolicy FSStoragePlugin::symLinkPolicy()
{
if (s_symLinkPolicy == SymLinkPolicy::Undefined) {
FSStoragePlugin::SymLinkPolicy usePolicy = SymLinkPolicy::Default;
QByteArray envData = qgetenv("BUTEO_MTP_SYMLINK_POLICY");
QString envValue = QString::fromUtf8(envData.data()).toLower();
if (envValue == "allowall" || envValue == "allow")
usePolicy = SymLinkPolicy::AllowAll;
else if (envValue == "allowwithinstorage" || envValue == "storage")
usePolicy = SymLinkPolicy::AllowWithinStorage;
else if (envValue == "denyall" || envValue == "deny")
usePolicy = SymLinkPolicy::DenyAll;
else if (!envValue.isEmpty())
MTP_LOG_WARNING("unknown SymLinkPolicy:" << envValue);
setSymLinkPolicy(usePolicy);
}
return s_symLinkPolicy;
}

void FSStoragePlugin::setSymLinkPolicy(FSStoragePlugin::SymLinkPolicy policy)
{
static const char * const lut[] = {
"Undefined",
"AllowAll",
"AllowWithinStorage",
"DenyAll",
};

if (s_symLinkPolicy != policy) {
MTP_LOG_INFO("SymLinkPolicy changed:"
<< lut[s_symLinkPolicy]
<< "->"
<< lut[policy]);
s_symLinkPolicy = policy;
}
}

/************************************************************
* MTPrespCode FSStoragePlugin::addToStorage
***********************************************************/
Expand All @@ -1156,6 +1195,36 @@ MTPResponseCode FSStoragePlugin::addToStorage( const QString &path,
return MTP_RESP_AccessDenied;
}

// Handle symbolic link policy
QFileInfo pathInfo(path);
if (pathInfo.isSymLink()) {
QString targetPath(pathInfo.canonicalFilePath());
if (targetPath.isEmpty()) {
MTP_LOG_WARNING("excluded broken symlink:" << path);
return MTP_RESP_AccessDenied;
}
switch (symLinkPolicy()) {
case SymLinkPolicy::AllowAll:
break;
case SymLinkPolicy::AllowWithinStorage:
{
// NB: m_storagePath is in canonical form
int prefixLen = m_storagePath.length();
if (targetPath.length() <= prefixLen ||
targetPath[prefixLen] != '/' ||
!targetPath.startsWith(m_storagePath)) {
MTP_LOG_INFO("excluded out-of-storage symlink:" << path);
return MTP_RESP_AccessDenied;
}
}
break;
default:
case SymLinkPolicy::DenyAll:
MTP_LOG_INFO("excluded symlink:" << path);
return MTP_RESP_AccessDenied;
}
}

// If we already have StorageItem for given path...
if( m_pathNamesMap.contains( path ) )
{
Expand Down
12 changes: 12 additions & 0 deletions mts/platform/storage/fsstorageplugin/fsstorageplugin.h
Expand Up @@ -57,6 +57,16 @@ class FSStoragePlugin : public StoragePlugin
{
Q_OBJECT
public:
enum SymLinkPolicy {
Undefined,
AllowAll,
AllowWithinStorage,
DenyAll,
Default = AllowAll,
};
static SymLinkPolicy symLinkPolicy();
static void setSymLinkPolicy(SymLinkPolicy policy);

/// Constructor.
FSStoragePlugin( quint32 storageId = 0, MTPStorageType storageType = MTP_STORAGE_TYPE_FixedRAM,
QString storagePath = "", QString volumeLabel = "", QString storageDescription = "" );
Expand Down Expand Up @@ -433,6 +443,8 @@ private slots:
ObjHandle m_testHandleProvider;
friend class FSStoragePlugin_test;
#endif

static SymLinkPolicy s_symLinkPolicy;
};
}

Expand Down

0 comments on commit ee0a28c

Please sign in to comment.