Skip to content

Commit 8da9da9

Browse files
committed
refactor: migrate update log monitoring to DBus interface
1. Replace file system watcher with DBus-based log monitoring 2. Implement pipe-based log data transfer for better security 3. Add historical and realtime log fetching capabilities 4. Introduce systemd service for secure log file copying 5. Fix potential security issues with file permissions 1. 从文件系统监控改为基于DBus的日志监控 2. 实现基于管道的日志数据传输以提高安全性 3. 添加历史日志和实时日志获取功能 4. 引入systemd服务实现安全的日志文件复制 5. 修复文件权限相关的潜在安全问题 refactor: 迁移更新日志监控到DBus接口 1. 将文件系统监控替换为基于DBus的日志监控 2. 实现基于管道的日志数据传输以提高安全性 3. 添加历史日志和实时日志获取功能 4. 引入systemd服务实现安全的日志文件复制 5. 修复文件权限相关的潜在安全问题
1 parent b30d609 commit 8da9da9

12 files changed

Lines changed: 354 additions & 127 deletions

File tree

.reuse/dep5

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,12 @@ Copyright: None
2929
License: CC0-1.0
3030

3131
# bash scripts
32-
Files: *.sh src/dde-update/misc/98deepin-upgrade-check
32+
Files: *.sh src/dde-update/misc/98deepin-upgrade-check src/dde-upadte/misc/copy-update-log.sh
3333
Copyright: None
3434
License: CC0-1.0
3535

3636
# configuration files for CI scripts/tools
37-
Files: .github/* .obs/* .tx/transifex.yaml .tx/deepin.conf
37+
Files: .github/* .obs/* .tx/transifex.yaml .tx/deepin.conf src/dde-update/misc/deepin-update-log-copy@.service src/dde-update/misc/52-deepin-update-ui.rules
3838
Copyright: None
3939
License: CC0-1.0
4040

debian/control

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,6 @@ Homepage: http://www.deepin.org/
1818

1919
Package: deepin-update-ui
2020
Architecture: any
21-
Depends: ${shlibs:Depends}, ${misc:Depends}
21+
Depends: ${shlibs:Depends}, ${misc:Depends}, lastore-daemon (>>6.2.25),
2222
Description: The UI collection for updating functions, including control
2323
center update plugins, full screen update interfaces, rollback pages, etc.

src/common/common/logwatcherhelper.cpp

Lines changed: 112 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,21 @@
44
#include "logwatcherhelper.h"
55

66
#include <QDebug>
7-
#include <QDir>
7+
#include <QDBusPendingCallWatcher>
8+
#include <QDBusPendingCall>
89

9-
#define UPDATE_LOG_FILE "/tmp/lastore_update_detail.log"
10+
#include <unistd.h>
11+
#include <fcntl.h>
1012

11-
LogWatcherHelper::LogWatcherHelper(QObject *parent)
13+
#include "../dbus/updatedbusproxy.h"
14+
15+
LogWatcherHelper::LogWatcherHelper(UpdateDBusProxy *dbusProxy, QObject *parent)
1216
: QObject(parent)
13-
, m_fileWatcher(nullptr)
14-
, m_lastFileSize(0)
1517
, m_data(QString())
18+
, m_dbusProxy(dbusProxy)
19+
, m_readFd(-1)
20+
, m_writeFd(-1)
21+
, m_socketNotifier(nullptr)
1622
{
1723

1824
}
@@ -24,126 +30,136 @@ LogWatcherHelper::~LogWatcherHelper()
2430

2531
void LogWatcherHelper::startWatchFile()
2632
{
27-
qInfo() << "Start watch update log file";
28-
if (m_fileWatcher) {
29-
qWarning() << "Log file watcher already exists";
33+
qDebug() << "Start watch update log via DBus interface";
34+
35+
if (!m_dbusProxy) {
36+
qWarning() << "DBus proxy is null, cannot start watching";
3037
return;
3138
}
32-
33-
m_fileWatcher = new QFileSystemWatcher(this);
34-
connect(m_fileWatcher, &QFileSystemWatcher::fileChanged, this, &LogWatcherHelper::onFileChanged);
35-
connect(m_fileWatcher, &QFileSystemWatcher::directoryChanged, this, &LogWatcherHelper::onDirectoryChanged);
36-
37-
// 总是监控 /tmp 目录以检测文件创建/删除
38-
const QString logDir = "/tmp";
39-
if (QDir(logDir).exists()) {
40-
m_fileWatcher->addPath(logDir);
41-
} else {
42-
qWarning() << "tmp directory does not exist:" << logDir;
39+
40+
if (m_readFd != -1) {
41+
qWarning() << "Log watcher already started";
42+
return;
4343
}
4444

45-
// 如果日志文件已存在,也监控它
46-
if (QFile::exists(UPDATE_LOG_FILE)) {
47-
m_fileWatcher->addPath(UPDATE_LOG_FILE);
48-
49-
// 立即读取现有文件内容
50-
m_lastFileSize = 0;
51-
m_data = QString();
52-
readFileIncrement();
53-
}
45+
// 设置管道并调用 DBus 接口
46+
setupLogPipe();
5447
}
5548

5649
void LogWatcherHelper::stopWatchFile()
5750
{
58-
qInfo() << "Stop watch update log file";
59-
if (m_fileWatcher) {
60-
m_fileWatcher->removePaths(m_fileWatcher->files());
61-
delete m_fileWatcher;
62-
m_fileWatcher = nullptr;
51+
qDebug() << "Stop watch update log";
52+
53+
// 停止文件描述符监听
54+
if (m_socketNotifier) {
55+
m_socketNotifier->setEnabled(false);
56+
delete m_socketNotifier;
57+
m_socketNotifier = nullptr;
58+
}
59+
60+
// 关闭文件描述符
61+
if (m_readFd != -1) {
62+
close(m_readFd);
63+
m_readFd = -1;
64+
}
65+
66+
if (m_writeFd != -1) {
67+
close(m_writeFd);
68+
m_writeFd = -1;
6369
}
6470

65-
// 重置文件大小记录
66-
m_lastFileSize = 0;
71+
// 重置数据
6772
m_data = QString();
6873
}
6974

70-
void LogWatcherHelper::onFileChanged(const QString &path)
75+
void LogWatcherHelper::setupLogPipe()
7176
{
72-
if (path != UPDATE_LOG_FILE) {
77+
// 创建管道
78+
int pipefd[2];
79+
if (pipe(pipefd) == -1) {
80+
qWarning() << "Failed to create pipe for log reading";
7381
return;
7482
}
7583

76-
readFileIncrement();
77-
78-
// 重新添加文件到监控列表(QFileSystemWatcher 在文件变化后可能会自动移除监控)
79-
if (m_fileWatcher && !m_fileWatcher->files().contains(path)) {
80-
m_fileWatcher->addPath(path);
81-
}
84+
m_readFd = pipefd[0];
85+
m_writeFd = pipefd[1];
86+
87+
// 设置读端为非阻塞
88+
int flags = fcntl(m_readFd, F_GETFL, 0);
89+
fcntl(m_readFd, F_SETFL, flags | O_NONBLOCK);
90+
91+
// 设置 QSocketNotifier 来监听读端文件描述符
92+
m_socketNotifier = new QSocketNotifier(m_readFd, QSocketNotifier::Read, this);
93+
connect(m_socketNotifier, &QSocketNotifier::activated, this, &LogWatcherHelper::onDataAvailable);
94+
95+
// 第一步:先获取历史日志 (realtime=false)
96+
qDebug() << "First getting historical logs...";
97+
QDBusPendingCall historyCall = m_dbusProxy->GetUpdateDetails(m_writeFd, false);
98+
QDBusPendingCallWatcher* historyWatcher = new QDBusPendingCallWatcher(historyCall, this);
99+
100+
connect(historyWatcher, &QDBusPendingCallWatcher::finished, this, [this, historyWatcher](void) {
101+
// 可能获取历史日志失败(比如没有历史日志),但是不影响实时日志的获取
102+
if (historyWatcher->isError()) {
103+
qWarning() << "GetUpdateDetails for history failed:" << historyWatcher->error().message();
104+
historyWatcher->deleteLater();
105+
}
106+
107+
qDebug() << "Historical logs completed, starting realtime monitoring...";
108+
109+
// 历史日志获取完成,直接启动实时日志监听
110+
startRealtimeLogAfterHistory();
111+
112+
historyWatcher->deleteLater();
113+
});
82114
}
83115

84-
void LogWatcherHelper::onDirectoryChanged(const QString &path)
116+
void LogWatcherHelper::startRealtimeLogAfterHistory()
85117
{
86-
if (path != "/tmp") {
87-
return;
88-
}
89-
90-
const bool fileExists = QFile::exists(UPDATE_LOG_FILE);
91-
const bool fileWatched = m_fileWatcher && m_fileWatcher->files().contains(UPDATE_LOG_FILE);
92-
93-
if (fileExists && !fileWatched) {
94-
m_fileWatcher->addPath(UPDATE_LOG_FILE);
95-
m_lastFileSize = 0;
96-
m_data = QString();
97-
readFileIncrement();
98-
} else if (!fileExists && fileWatched) {
99-
qInfo() << "Update log file was deleted:" << UPDATE_LOG_FILE;
100-
m_lastFileSize = 0;
101-
emit fileReset();
102-
m_data = QString();
118+
// 启用文件描述符监听
119+
if (m_socketNotifier) {
120+
m_socketNotifier->setEnabled(true);
103121
}
122+
123+
// 开始获取实时增量日志 (realtime=true)
124+
QDBusPendingCall realtimeCall = m_dbusProxy->GetUpdateDetails(m_writeFd, true);
125+
QDBusPendingCallWatcher* realtimeWatcher = new QDBusPendingCallWatcher(realtimeCall, this);
126+
127+
connect(realtimeWatcher, &QDBusPendingCallWatcher::finished, this, [this, realtimeWatcher](void) {
128+
129+
if (realtimeWatcher->isError()) {
130+
qWarning() << "GetUpdateDetails for realtime failed:" << realtimeWatcher->error().message();
131+
stopWatchFile();
132+
} else {
133+
qDebug() << "Realtime log monitoring started successfully";
134+
}
135+
136+
realtimeWatcher->deleteLater();
137+
});
104138
}
105139

106-
void LogWatcherHelper:: readFileIncrement()
140+
void LogWatcherHelper::onDataAvailable()
107141
{
108-
QFile logFile(UPDATE_LOG_FILE);
109-
110-
if (!logFile.exists()) {
111-
qWarning() << "Log file does not exist:" << UPDATE_LOG_FILE;
112-
return;
113-
}
114-
115-
const qint64 currentFileSize = logFile.size();
116-
117-
// 如果文件变小了,说明文件被重新创建或截断,重新开始读取
118-
if (currentFileSize < m_lastFileSize) {
119-
m_lastFileSize = 0;
120-
m_data = QString();
121-
emit fileReset();
122-
}
142+
readAvailableData();
143+
}
123144

124-
// 如果文件大小没变,没有新内容
125-
if (currentFileSize == m_lastFileSize) {
145+
void LogWatcherHelper::readAvailableData()
146+
{
147+
if (m_readFd == -1) {
126148
return;
127149
}
128150

129-
if (!logFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
130-
qWarning() << "Failed to open log file for reading:" << logFile.errorString();
131-
return;
151+
QByteArray buffer;
152+
char readBuffer[4096];
153+
ssize_t bytesRead;
154+
155+
while ((bytesRead = read(m_readFd, readBuffer, sizeof(readBuffer))) > 0) {
156+
buffer.append(readBuffer, bytesRead);
132157
}
158+
159+
if (!buffer.isEmpty()) {
160+
QString newContent = QString::fromUtf8(buffer);
133161

134-
// 定位到上次读取的位置
135-
if (!logFile.seek(m_lastFileSize)) {
136-
qWarning() << "Failed to seek to position:" << m_lastFileSize;
137-
logFile.close();
138-
return;
162+
m_data.append(newContent);
163+
emit incrementalDataChanged(newContent);
139164
}
140-
141-
const QByteArray newData = logFile.readAll();
142-
logFile.close();
143-
144-
m_lastFileSize = currentFileSize;
145-
146-
const QString incrementalContent = QString::fromUtf8(newData);
147-
m_data.append(incrementalContent);
148-
emit incrementalDataChanged(incrementalContent);
149165
}

src/common/common/logwatcherhelper.h

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,32 +5,38 @@
55
#define LOGWATCHERHELPER_H
66

77
#include <QObject>
8-
#include <QFileSystemWatcher>
8+
#include <QSocketNotifier>
9+
10+
class UpdateDBusProxy;
911

1012
class LogWatcherHelper : public QObject
1113
{
1214
Q_OBJECT
1315

1416
public:
15-
explicit LogWatcherHelper(QObject *parent = nullptr);
17+
explicit LogWatcherHelper(UpdateDBusProxy *dbusProxy, QObject *parent = nullptr);
1618
~LogWatcherHelper();
1719

1820
void startWatchFile();
1921
void stopWatchFile();
20-
void readFileIncrement();
2122

2223
private slots:
23-
void onFileChanged(const QString &path);
24-
void onDirectoryChanged(const QString &path);
24+
void onDataAvailable();
2525

2626
signals:
2727
void incrementalDataChanged(const QString &incrementaldata);
2828
void fileReset();
2929

3030
private:
31-
QFileSystemWatcher *m_fileWatcher;
32-
qint64 m_lastFileSize;
31+
void setupLogPipe();
32+
void readAvailableData();
33+
void startRealtimeLogAfterHistory();
34+
3335
QString m_data;
36+
UpdateDBusProxy *m_dbusProxy;
37+
int m_readFd;
38+
int m_writeFd;
39+
QSocketNotifier *m_socketNotifier;
3440
};
3541

3642
#endif // LOGWATCHERHELPER_H

src/common/dbus/updatedbusproxy.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <QDBusMetaType>
99
#include <QDBusPendingReply>
1010
#include <QDBusReply>
11+
#include <QDBusUnixFileDescriptor>
1112

1213
#include "common/commondefine.h"
1314

@@ -375,11 +376,12 @@ QDBusPendingCall UpdateDBusProxy::CheckUpgrade(int checkMode, int checkOrder)
375376
return m_managerInter->asyncCallWithArgumentList(QStringLiteral("CheckUpgrade"), argumentList);
376377
}
377378

378-
QDBusPendingReply<void> UpdateDBusProxy::ExportUpdateDetails(const QString &filename)
379+
QDBusPendingReply<void> UpdateDBusProxy::GetUpdateDetails(int fd, bool realtime)
379380
{
380381
QList<QVariant> argumentList;
381-
argumentList << QVariant::fromValue(filename);
382-
return m_managerInter->asyncCallWithArgumentList(QStringLiteral("ExportUpdateDetails"), argumentList);
382+
argumentList << QVariant::fromValue(QDBusUnixFileDescriptor(fd));
383+
argumentList << QVariant::fromValue(realtime);
384+
return m_managerInter->asyncCallWithArgumentList(QStringLiteral("GetUpdateDetails"), argumentList);
383385
}
384386

385387
bool UpdateDBusProxy::onBattery()

src/common/dbus/updatedbusproxy.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ class UpdateDBusProxy : public QObject
107107
QDBusPendingReply<QDBusObjectPath> PrepareDistUpgradePartly(int updateMode);
108108
QDBusPendingReply<QDBusObjectPath> fixError(const QString &errorType);
109109
QDBusPendingCall CheckUpgrade(int checkMode, int checkOrder);
110-
QDBusPendingReply<void> ExportUpdateDetails(const QString &filename);
110+
QDBusPendingReply<void> GetUpdateDetails(int fd, bool realtime);
111111

112112

113113
// Power

0 commit comments

Comments
 (0)