Skip to content

Commit

Permalink
Merge branch 'jb44457_symlink_policy' into 'master'
Browse files Browse the repository at this point in the history
Make it possible to limit to which extent buteo-mtp exposes symlinks

See merge request mer-core/buteo-mtp!24
  • Loading branch information
spiiroin committed Mar 1, 2019
2 parents 4f89a4e + 0a57804 commit 3c24906
Show file tree
Hide file tree
Showing 7 changed files with 122 additions and 28 deletions.
4 changes: 3 additions & 1 deletion init/systemd/buteo-mtp.service
Expand Up @@ -2,7 +2,9 @@
Description=MTP service

[Service]
ExecStart=/usr/lib/mtp/start-mtp.sh
EnvironmentFile=-/etc/sysconfig/buteo-mtp
EnvironmentFile=-/var/lib/environment/buteo-mtp/*.conf
ExecStart=/usr/lib/mtp/mtp_service $SERVICE_PARAMETERS
Restart=always
RestartSec=1
Nice=-10
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
1 change: 1 addition & 0 deletions rpm/buteo-mtp-qt5.spec
Expand Up @@ -17,6 +17,7 @@ BuildRequires: pkgconfig(buteosyncfw5)
BuildRequires: pkgconfig(Qt5SystemInfo)
BuildRequires: pkgconfig(blkid)
BuildRequires: pkgconfig(mount)
BuildRequires: pkgconfig(mlite5)
# for the thumbnailer unit test
BuildRequires: pkgconfig(Qt5Gui)
BuildRequires: ssu-devel >= 0.37.9
Expand Down
39 changes: 34 additions & 5 deletions service/service.cpp
Expand Up @@ -25,12 +25,14 @@
#include <signal.h>
#include <iostream>
#include <QCoreApplication>
#include <QCommandLineParser>
#include <QDir>
#include <QObject>
#include <QEventLoop>
#include <QStringList>
#include <QTimer>
#include <Logger.h>
#include <MGConfItem>
#include "mts.h"

using namespace meegomtp1dot0;
Expand All @@ -46,26 +48,53 @@ void signalHandler(int signum, siginfo_t *info, void *context)
_exit(0);
}

static void setupSymLinkPolicy()
{
MGConfItem confItem("/desktop/sailfish/buteo-mtp/symlink_policy");
QString symLinkPolicy(confItem.value().toString());

/* Note that we override value that might be existing in env,
* i.e. environment is used only as a vehicle for conveying the
* dconf setting data from main binary over to plugin that gets
* loaded at later stage.
*/
qputenv("BUTEO_MTP_SYMLINK_POLICY", symLinkPolicy.toUtf8());
}

int main(int argc, char** argv)
{
QCoreApplication app(argc, argv);
QCommandLineParser parser;
parser.setApplicationDescription("standalone buteo-mtp daemon");
parser.addHelpOption();
QCommandLineOption logToHomeOption(QStringList() << "d" << "log-to-home",
"Log to \"$HOME/mtp.log\".");
parser.addOption(logToHomeOption);
parser.process(app);
bool logToHome(parser.isSet(logToHomeOption));

/* Get symlink policy from dconf */
setupSymLinkPolicy();

struct sigaction action;

action.sa_sigaction = signalHandler;
action.sa_flags = SA_SIGINFO | SA_RESTART;
sigemptyset(&action.sa_mask);

if (sigaction(SIGINT, &action, NULL) < 0) return(-1);
if (sigaction(SIGALRM, &action, NULL) < 0) return(-1);
if (sigaction(SIGUSR1, &action, NULL) < 0) return(-1);
if (sigaction(SIGINT, &action, NULL) < 0)
return EXIT_FAILURE;
if (sigaction(SIGALRM, &action, NULL) < 0)
return EXIT_FAILURE;
if (sigaction(SIGUSR1, &action, NULL) < 0)
return EXIT_FAILURE;

QObject::connect(&app,SIGNAL(aboutToQuit()),Mts::getInstance(),SLOT(destroyInstance()));

bool ok = Mts::getInstance()->activate();
if( ok )
{
if (app.arguments().count() > 1 && app.arguments().at(1) == "-d")
if (logToHome)
{
Buteo::Logger::createInstance(QDir::homePath() + "/mtp.log", false, 0);
if (!Mts::getInstance()->debugLogsEnabled())
Expand All @@ -81,5 +110,5 @@ int main(int argc, char** argv)
{
Mts::destroyInstance();
}
return 0;
return EXIT_SUCCESS;
}
3 changes: 2 additions & 1 deletion service/service.pro
Expand Up @@ -12,12 +12,13 @@ QT -= gui
CONFIG += link_pkgconfig
equals(QT_MAJOR_VERSION, 4): PKGCONFIG += buteosyncfw
equals(QT_MAJOR_VERSION, 5): PKGCONFIG += buteosyncfw5
PKGCONFIG += mlite5

SOURCES += service.cpp

#install
target.path += /usr/lib/mtp/
target.files = start-mtp.sh mtp_service
target.files = mtp_service
desktop.path = /etc/xdg/autostart
desktop.files = buteo-mtp.desktop
INSTALLS += target desktop
Expand Down
20 changes: 0 additions & 20 deletions service/start-mtp.sh

This file was deleted.

0 comments on commit 3c24906

Please sign in to comment.