Comment 0 for bug 874447

Revision history for this message
Christoph Trassl (chtrassl) wrote : Unsafe m_iconCacheDir handling may result in deletion of home directory

Version: sni-qt_0.2.5-0ubuntu1_amd64

The m_iconCacheDir variable is used unchecked throughout sni-qt. This may result in deletion of home directory.

This was found by an apparmor "DENIED" while running a sandboxed application (apparmor error data: operation="unlink" name="/home/user/.bash_history").

Lets assume we /tmp writes blocked and we have HOME/.* writes blocked.

1. statusnotifieritemfactory.cpp: FsUtils::generateTempDir is used to generate a temporary IconCache location.

[...]
StatusNotifierItemFactory::StatusNotifierItemFactory()
: m_isAvailable(false)
{
    QString tempSubDir = QString("sni-qt_%1_%2")
        .arg(QCoreApplication::applicationFilePath().section('/', -1))
        .arg(QCoreApplication::applicationPid());
    m_iconCacheDir = FsUtils::generateTempDir(tempSubDir);
    [...]

2. fsutils.cpp: Returns an empty QString if generation of file system objects failed.

QString generateTempDir(const QString& prefix)
{
    QDir dir = QDir::temp();
    if (!dir.mkpath(".")) {
        qCritical("Failed to generate temporary file for prefix %s: could not create %s",
            qPrintable(prefix), qPrintable(dir.path()));
        return QString();
    }

    QString tmpl = QString("%1/%2-XXXXXX")
        .arg(dir.path())
        .arg(prefix);
    QByteArray ba = QFile::encodeName(tmpl);
    const char* name = mkdtemp(ba.data());
    if (!name) {
        qCritical("Failed to generate temporary file for prefix %s: %s",
            qPrintable(prefix), strerror(errno));
        return QString();
    }
    return QFile::encodeName(name);
}

3. statusnotifieritemfactory.cpp: generateTempDir may have returned an empty QString (or another invalid location), which we are using as m_iconCacheDir

[...]
    m_iconCacheDir = FsUtils::generateTempDir(tempSubDir);
    SNI_VAR(m_iconCacheDir);

    m_iconCache = new IconCache(m_iconCacheDir, this);
[...]

4. iconcache.cpp: IconCache will be created with an empty QString (or another invalid location). If directory creation fails there is an error message printed, but the error stays unchecked.

IconCache::IconCache(const QString& baseDir, QObject* parent)
: QObject(parent)
, m_themePath(baseDir + "/icons")
{
    QDir dir(baseDir);
    bool ok = dir.mkdir("icons");
    if (!ok) {
        qCritical("Could not create '%s' dir for SNI icon cache", qPrintable(m_themePath));
        m_themePath = QString();
        return;
    }
}

5. statusnotifieritemfactory.cpp: So when closing an application using sni-qt m_iconCacheDir is wiped.

 StatusNotifierItemFactory::~StatusNotifierItemFactory()
{
    SNI_DEBUG;
    FsUtils::recursiveRm(m_iconCacheDir);
}