Skip to content

fix(opslogexport): stop root service writing to user home, export via… - #482

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:release/eaglefrom
GongHeng2017:202607021032-re-eagle-fix
Jul 3, 2026
Merged

fix(opslogexport): stop root service writing to user home, export via…#482
deepin-bot[bot] merged 1 commit into
linuxdeepin:release/eaglefrom
GongHeng2017:202607021032-re-eagle-fix

Conversation

@GongHeng2017

Copy link
Copy Markdown
Contributor

… /var/log

Root service no longer writes into the caller's home dir; it creates a random temp dir under /var/log, exports system logs there, and returns the path. The frontend collects user-permission logs itself and copies the root-exported logs out. cp -rP avoids following symlinks, target dir is validated under /var/log, perms tightened to 0755/0644.

root 服务不再写入用户家目录,改为在 /var/log 下创建随机临时目录导出系统
日志并返回路径;前端自行收集用户权限日志并拷贝 root 导出的内容。cp -rP
不跟随符号链接,校验目标目录位于 /var/log,权限收紧为 0755/0644。

Log: 重构运维日志导出,root 不再写入用户家目录
Influence: 消除 root 服务写入用户家目录的符号链接攻击面,改由 root 在 /var/log 随机目录导出、前端拷贝,提升安全性。

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @GongHeng2017, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
  • 检测到敏感词export变动
详情
    {
    "export": {
        "application/dbusproxy/dldbushandler.cpp": {
            "a": [
                "bool DLDBusHandler::exportOpsLog()",
                "    QDBusPendingReply<bool> reply = m_dbus->exportOpsLog();",
                "        qCDebug(logDBusHandler) << \"exportOpsLog succeeded:\" << reply.value();"
            ],
            "b": [
                "QString DLDBusHandler::exportOpsLog()",
                "    QDBusPendingReply<QString> reply = m_dbus->exportOpsLog();",
                "        qCDebug(logDBusHandler) << \"exportOpsLog succeeded, root temp dir:\" << reply.value();"
            ]
        },
        "application/dbusproxy/dldbushandler.h": {
            "a": [
                "    bool exportOpsLog();"
            ],
            "b": [
                "    QString exportOpsLog();"
            ]
        },
        "application/dbusproxy/dldbusinterface.h": {
            "a": [
                "    inline QDBusPendingReply<bool> exportOpsLog()"
            ],
            "b": [
                "    inline QDBusPendingReply<QString> exportOpsLog()"
            ]
        },
        "application/logallexportthread.cpp": {
            "a": [
                "        DLDBusHandler::instance(this)->exportOpsLog();",
                "        Utils::exportSomeOpsLogs(opsLogPath, userHomePath);"
            ],
            "b": [
                "        QString rootTempDir = DLDBusHandler::instance(this)->exportOpsLog();",
                "            qCWarning(logExportAll) << \"exportOpsLog returned empty or non-existent root temp dir, root-side ops logs may be missing\";",
                "        Utils::exportUserPermissionOpsLogs(opsLogPath, userHomePath);"
            ]
        },
        "application/utils.cpp": {
            "a": [
                "void Utils::exportSomeOpsLogs(const QString &outDir, const QString &userHomeDir)"
            ],
            "b": [
                "void Utils::exportUserPermissionAppLogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionSystemLogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionKernelLogs(const QString &outDir)",
                "void Utils::exportUserPermissionDDELogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionOpsLogs(const QString &outDir, const QString &userHomeDir)",
                "    Utils::exportUserPermissionAppLogs(outDir, userHomeDir);",
                "    Utils::exportUserPermissionSystemLogs(outDir, userHomeDir);",
                "    Utils::exportUserPermissionKernelLogs(outDir);",
                "    Utils::exportUserPermissionDDELogs(outDir, userHomeDir);"
            ]
        },
        "application/utils.h": {
            "a": [
                "    static void exportSomeOpsLogs(const QString &outDir, const QString &userHomeDir);"
            ],
            "b": [
                "    static void exportUserPermissionAppLogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionSystemLogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionKernelLogs(const QString &outDir);",
                "    static void exportUserPermissionDDELogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionOpsLogs(const QString &outDir, const QString &userHomeDir);"
            ]
        },
        "logViewerService/assets/data/com.deepin.logviewer.xml": {
            "b": [
                "    <method name=\"exportOpsLog\">"
            ]
        },
        "logViewerService/assets/data/deepin-log-viewer-daemon.service": {
            "b": [
                "# exportOpsLog \u9700\u8981\u5728 /var/log \u4e0b\u521b\u5efa\u4e34\u65f6\u5bfc\u51fa\u76ee\u5f55\uff0c\u987b\u663e\u5f0f\u653e\u5f00\u5199\u6743\u9650"
            ]
        },
        "logViewerService/logviewerservice.cpp": {
            "a": [
                "bool LogViewerService::exportOpsLog()"
            ],
            "b": [
                "QString LogViewerService::exportOpsLog()",
                "                    qCWarning(logService) << \"exportOpsLog: failed to remove stale temp dir:\" << oldPath;",
                "        qCWarning(logService) << \"exportOpsLog: failed to create temporary dir under /var/log:\" << tmpOpsDir.errorString();"
            ]
        },
        "logViewerService/logviewerservice.h": {
            "a": [
                "    Q_SCRIPTABLE bool exportOpsLog();"
            ],
            "b": [
                "    Q_SCRIPTABLE QString exportOpsLog();"
            ]
        },
        "logViewerService/opslogexport.cpp": {
            "a": [
                "            qWarning() << \"Failed to chown export path:\" << path << \"error:\" << strerror(errno);"
            ],
            "b": [
                "        qWarning() << \"OpsLogExport::run: target directory safety check failed, aborting export\";",
                " * target_dir \u7531 LogViewerService::exportOpsLog() \u901a\u8fc7 QTemporaryDir \u5728 /var/log \u4e0b",
                "    // - exportAptLogs/exportUosSteLogs/exportUosSteTwoLogs \u7b49\u540c\u6837\u662f\u6574\u76ee\u5f55 cp -rP\uff0c"
            ]
        }
    }
}

@github-actions
github-actions Bot requested a review from liujianqiang-niu July 2, 2026 13:26
@GongHeng2017
GongHeng2017 force-pushed the 202607021032-re-eagle-fix branch from a2bce5f to 82a79c4 Compare July 2, 2026 14:01
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown
  • 检测到敏感词export变动
详情
    {
    "export": {
        "application/dbusproxy/dldbushandler.cpp": {
            "a": [
                "bool DLDBusHandler::exportOpsLog()",
                "    QDBusPendingReply<bool> reply = m_dbus->exportOpsLog();",
                "        qCDebug(logDBusHandler) << \"exportOpsLog succeeded:\" << reply.value();"
            ],
            "b": [
                "QString DLDBusHandler::exportOpsLog()",
                "    QDBusPendingReply<QString> reply = m_dbus->exportOpsLog();",
                "        qCDebug(logDBusHandler) << \"exportOpsLog succeeded, root temp dir:\" << reply.value();"
            ]
        },
        "application/dbusproxy/dldbushandler.h": {
            "a": [
                "    bool exportOpsLog();"
            ],
            "b": [
                "    QString exportOpsLog();"
            ]
        },
        "application/dbusproxy/dldbusinterface.h": {
            "a": [
                "    inline QDBusPendingReply<bool> exportOpsLog()"
            ],
            "b": [
                "    inline QDBusPendingReply<QString> exportOpsLog()"
            ]
        },
        "application/logallexportthread.cpp": {
            "a": [
                "        DLDBusHandler::instance(this)->exportOpsLog();",
                "        Utils::exportSomeOpsLogs(opsLogPath, userHomePath);"
            ],
            "b": [
                "        QString rootTempDir = DLDBusHandler::instance(this)->exportOpsLog();",
                "            qCWarning(logExportAll) << \"exportOpsLog returned empty or non-existent root temp dir, root-side ops logs may be missing\";",
                "        Utils::exportUserPermissionOpsLogs(opsLogPath, userHomePath);"
            ]
        },
        "application/opslogpaths.h": {
            "b": [
                "// \u524d\u7aef\uff08application/utils.cpp \u7684 exportUserPermissionOpsLogs \u7cfb\u5217\uff09\u4e0e",
                "// root \u670d\u52a1\uff08logViewerService/opslogexport.cpp \u7684 createOpsLogDirStruct\uff09\u5fc5\u987b"
            ]
        },
        "application/utils.cpp": {
            "a": [
                "void Utils::exportSomeOpsLogs(const QString &outDir, const QString &userHomeDir)"
            ],
            "b": [
                "void Utils::exportUserPermissionAppLogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionSystemLogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionKernelLogs(const QString &outDir)",
                "void Utils::exportUserPermissionDDELogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionOpsLogs(const QString &outDir, const QString &userHomeDir)",
                "    Utils::exportUserPermissionAppLogs(outDir, userHomeDir);",
                "    Utils::exportUserPermissionSystemLogs(outDir, userHomeDir);",
                "    Utils::exportUserPermissionKernelLogs(outDir);",
                "    Utils::exportUserPermissionDDELogs(outDir, userHomeDir);"
            ]
        },
        "application/utils.h": {
            "a": [
                "    static void exportSomeOpsLogs(const QString &outDir, const QString &userHomeDir);"
            ],
            "b": [
                "    static void exportUserPermissionAppLogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionSystemLogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionKernelLogs(const QString &outDir);",
                "    static void exportUserPermissionDDELogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionOpsLogs(const QString &outDir, const QString &userHomeDir);"
            ]
        },
        "logViewerService/assets/data/com.deepin.logviewer.xml": {
            "b": [
                "    <method name=\"exportOpsLog\">"
            ]
        },
        "logViewerService/assets/data/deepin-log-viewer-daemon.service": {
            "b": [
                "# exportOpsLog \u9700\u8981\u5728 /var/log \u4e0b\u521b\u5efa\u4e34\u65f6\u5bfc\u51fa\u76ee\u5f55\uff0c\u987b\u663e\u5f0f\u653e\u5f00\u5199\u6743\u9650"
            ]
        },
        "logViewerService/logviewerservice.cpp": {
            "a": [
                "bool LogViewerService::exportOpsLog()",
                "        qCWarning(logService) << \"Failed to get caller home directory for export log\";"
            ],
            "b": [
                "QString LogViewerService::exportOpsLog()",
                "        qCWarning(logService) << \"Failed to get caller identity for export log\";",
                "                    qCWarning(logService) << \"exportOpsLog: failed to remove stale temp dir:\" << oldPath;",
                "        qCWarning(logService) << \"exportOpsLog: failed to create temporary dir under /var/log:\" << tmpOpsDir.errorString();"
            ]
        },
        "logViewerService/logviewerservice.h": {
            "a": [
                "    Q_SCRIPTABLE bool exportOpsLog();"
            ],
            "b": [
                "    Q_SCRIPTABLE QString exportOpsLog();"
            ]
        },
        "logViewerService/opslogexport.cpp": {
            "b": [
                "        qWarning() << \"OpsLogExport::run: target directory safety check failed, aborting export\";",
                " * target_dir \u7531 LogViewerService::exportOpsLog() \u901a\u8fc7 QTemporaryDir \u5728 /var/log \u4e0b",
                "    // exportOpsLog \u8fd4\u56de\u81f3\u524d\u7aef\u62f7\u8d1d\u5b8c\u6210\u7684\u65f6\u95f4\u7a97\u5185\u8bfb\u53d6 auth.log/syslog \u7b49\u654f\u611f\u65e5\u5fd7\u3002"
            ]
        }
    }
}

@GongHeng2017
GongHeng2017 force-pushed the 202607021032-re-eagle-fix branch from 82a79c4 to cbb34a5 Compare July 3, 2026 02:16
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
  • 检测到敏感词export变动
详情
    {
    "export": {
        "application/dbusproxy/dldbushandler.cpp": {
            "a": [
                "bool DLDBusHandler::exportOpsLog()",
                "    QDBusPendingReply<bool> reply = m_dbus->exportOpsLog();",
                "        qCDebug(logDBusHandler) << \"exportOpsLog succeeded:\" << reply.value();"
            ],
            "b": [
                "QString DLDBusHandler::exportOpsLog()",
                "    QDBusPendingReply<QString> reply = m_dbus->exportOpsLog();",
                "        qCDebug(logDBusHandler) << \"exportOpsLog succeeded, root temp dir:\" << reply.value();"
            ]
        },
        "application/dbusproxy/dldbushandler.h": {
            "a": [
                "    bool exportOpsLog();"
            ],
            "b": [
                "    QString exportOpsLog();"
            ]
        },
        "application/dbusproxy/dldbusinterface.h": {
            "a": [
                "    inline QDBusPendingReply<bool> exportOpsLog()"
            ],
            "b": [
                "    inline QDBusPendingReply<QString> exportOpsLog()"
            ]
        },
        "application/logallexportthread.cpp": {
            "a": [
                "        DLDBusHandler::instance(this)->exportOpsLog();",
                "        Utils::exportSomeOpsLogs(opsLogPath, userHomePath);"
            ],
            "b": [
                "        QString rootTempDir = DLDBusHandler::instance(this)->exportOpsLog();",
                "            qCWarning(logExportAll) << \"exportOpsLog returned empty or non-existent root temp dir, root-side ops logs may be missing\";",
                "        Utils::exportUserPermissionOpsLogs(opsLogPath, userHomePath);"
            ]
        },
        "application/opslogpaths.h": {
            "b": [
                "// \u524d\u7aef\uff08application/utils.cpp \u7684 exportUserPermissionOpsLogs \u7cfb\u5217\uff09\u4e0e",
                "// root \u670d\u52a1\uff08logViewerService/opslogexport.cpp \u7684 createOpsLogDirStruct\uff09\u5fc5\u987b"
            ]
        },
        "application/utils.cpp": {
            "a": [
                "void Utils::exportSomeOpsLogs(const QString &outDir, const QString &userHomeDir)"
            ],
            "b": [
                "void Utils::exportUserPermissionAppLogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionSystemLogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionKernelLogs(const QString &outDir)",
                "void Utils::exportUserPermissionDDELogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionOpsLogs(const QString &outDir, const QString &userHomeDir)",
                "    Utils::exportUserPermissionAppLogs(outDir, userHomeDir);",
                "    Utils::exportUserPermissionSystemLogs(outDir, userHomeDir);",
                "    Utils::exportUserPermissionKernelLogs(outDir);",
                "    Utils::exportUserPermissionDDELogs(outDir, userHomeDir);"
            ]
        },
        "application/utils.h": {
            "a": [
                "    static void exportSomeOpsLogs(const QString &outDir, const QString &userHomeDir);"
            ],
            "b": [
                "    static void exportUserPermissionAppLogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionSystemLogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionKernelLogs(const QString &outDir);",
                "    static void exportUserPermissionDDELogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionOpsLogs(const QString &outDir, const QString &userHomeDir);"
            ]
        },
        "logViewerService/assets/data/com.deepin.logviewer.xml": {
            "b": [
                "    <method name=\"exportOpsLog\">"
            ]
        },
        "logViewerService/assets/data/deepin-log-viewer-daemon.service": {
            "b": [
                "# exportOpsLog \u9700\u8981\u5728 /var/log \u4e0b\u521b\u5efa\u4e34\u65f6\u5bfc\u51fa\u76ee\u5f55\uff0c\u987b\u663e\u5f0f\u653e\u5f00\u5199\u6743\u9650"
            ]
        },
        "logViewerService/logviewerservice.cpp": {
            "a": [
                "bool LogViewerService::exportOpsLog()",
                "        qCWarning(logService) << \"Failed to get caller home directory for export log\";"
            ],
            "b": [
                "QString LogViewerService::exportOpsLog()",
                "        qCWarning(logService) << \"Failed to get caller identity for export log\";",
                "                    qCWarning(logService) << \"exportOpsLog: failed to remove stale temp dir:\" << oldPath;",
                "        qCWarning(logService) << \"exportOpsLog: failed to create temporary dir under /var/log:\" << tmpOpsDir.errorString();"
            ]
        },
        "logViewerService/logviewerservice.h": {
            "a": [
                "    Q_SCRIPTABLE bool exportOpsLog();"
            ],
            "b": [
                "    Q_SCRIPTABLE QString exportOpsLog();"
            ]
        },
        "logViewerService/opslogexport.cpp": {
            "a": [
                "            qWarning() << \"Failed to chown export path:\" << path << \"error:\" << strerror(errno);"
            ],
            "b": [
                "        qWarning() << \"OpsLogExport::run: target directory safety check failed, aborting export\";",
                " * target_dir \u7531 LogViewerService::exportOpsLog() \u901a\u8fc7 QTemporaryDir \u5728 /var/log \u4e0b",
                "    // - 0750/0640 \u800c\u975e 0755/0644\uff1a\u4ec5 caller \u540c\u7ec4\u53ef\u8bfb\uff0c\u907f\u514d\u4efb\u610f\u672c\u5730\u7528\u6237\u5728 exportOpsLog",
                "            qWarning() << \"Failed to chgrp export path:\" << path << \"error:\" << strerror(errno);"
            ]
        }
    }
}

@GongHeng2017
GongHeng2017 force-pushed the 202607021032-re-eagle-fix branch from cbb34a5 to 45900f0 Compare July 3, 2026 03:04
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
  • 检测到敏感词export变动
详情
    {
    "export": {
        "application/dbusproxy/dldbushandler.cpp": {
            "a": [
                "bool DLDBusHandler::exportOpsLog()",
                "    QDBusPendingReply<bool> reply = m_dbus->exportOpsLog();",
                "        qCDebug(logDBusHandler) << \"exportOpsLog succeeded:\" << reply.value();"
            ],
            "b": [
                "QString DLDBusHandler::exportOpsLog()",
                "    QDBusPendingReply<QString> reply = m_dbus->exportOpsLog();",
                "        qCDebug(logDBusHandler) << \"exportOpsLog succeeded, root temp dir:\" << reply.value();"
            ]
        },
        "application/dbusproxy/dldbushandler.h": {
            "a": [
                "    bool exportOpsLog();"
            ],
            "b": [
                "    QString exportOpsLog();"
            ]
        },
        "application/dbusproxy/dldbusinterface.h": {
            "a": [
                "    inline QDBusPendingReply<bool> exportOpsLog()"
            ],
            "b": [
                "    inline QDBusPendingReply<QString> exportOpsLog()"
            ]
        },
        "application/logallexportthread.cpp": {
            "a": [
                "        DLDBusHandler::instance(this)->exportOpsLog();",
                "        Utils::exportSomeOpsLogs(opsLogPath, userHomePath);"
            ],
            "b": [
                "        QString rootTempDir = DLDBusHandler::instance(this)->exportOpsLog();",
                "            qCWarning(logExportAll) << \"exportOpsLog returned empty or non-existent root temp dir, root-side ops logs may be missing\";",
                "        Utils::exportUserPermissionOpsLogs(opsLogPath, userHomePath);"
            ]
        },
        "application/opslogpaths.h": {
            "b": [
                "// \u524d\u7aef\uff08application/utils.cpp \u7684 exportUserPermissionOpsLogs \u7cfb\u5217\uff09\u4e0e",
                "// root \u670d\u52a1\uff08logViewerService/opslogexport.cpp \u7684 createOpsLogDirStruct\uff09\u5fc5\u987b"
            ]
        },
        "application/utils.cpp": {
            "a": [
                "void Utils::exportSomeOpsLogs(const QString &outDir, const QString &userHomeDir)"
            ],
            "b": [
                "void Utils::exportUserPermissionAppLogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionSystemLogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionKernelLogs(const QString &outDir)",
                "void Utils::exportUserPermissionDDELogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionOpsLogs(const QString &outDir, const QString &userHomeDir)",
                "    Utils::exportUserPermissionAppLogs(outDir, userHomeDir);",
                "    Utils::exportUserPermissionSystemLogs(outDir, userHomeDir);",
                "    Utils::exportUserPermissionKernelLogs(outDir);",
                "    Utils::exportUserPermissionDDELogs(outDir, userHomeDir);"
            ]
        },
        "application/utils.h": {
            "a": [
                "    static void exportSomeOpsLogs(const QString &outDir, const QString &userHomeDir);"
            ],
            "b": [
                "    static void exportUserPermissionAppLogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionSystemLogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionKernelLogs(const QString &outDir);",
                "    static void exportUserPermissionDDELogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionOpsLogs(const QString &outDir, const QString &userHomeDir);"
            ]
        },
        "logViewerService/assets/data/com.deepin.logviewer.xml": {
            "b": [
                "    <method name=\"exportOpsLog\">"
            ]
        },
        "logViewerService/assets/data/deepin-log-viewer-daemon.service": {
            "b": [
                "# exportOpsLog \u9700\u8981\u5728 /var/log \u4e0b\u521b\u5efa\u4e34\u65f6\u5bfc\u51fa\u76ee\u5f55\uff0c\u987b\u663e\u5f0f\u653e\u5f00\u5199\u6743\u9650"
            ]
        },
        "logViewerService/logviewerservice.cpp": {
            "a": [
                "bool LogViewerService::exportOpsLog()",
                "        qCWarning(logService) << \"Failed to get caller home directory for export log\";"
            ],
            "b": [
                "QString LogViewerService::exportOpsLog()",
                "        qCWarning(logService) << \"Failed to get caller identity for export log\";",
                "        qCWarning(logService) << \"exportOpsLog: failed to create temporary dir under /var/log:\" << tmpOpsDir.errorString();",
                "    // \u6388\u6743\u6821\u9a8c\uff1a\u4e0e exportOpsLog \u4e00\u81f4\uff0c\u4f7f\u7528 s_Action_View\u3002",
                "    // \u65e0\u53c2\u8bbe\u8ba1\uff1a\u6e05\u7406\u7684\u662f\u670d\u52a1\u7aef\u5728 exportOpsLog \u4e2d\u7f13\u5b58\u7684\u672c\u8fdb\u7a0b\u4e34\u65f6\u76ee\u5f55\u8def\u5f84\uff0c"
            ]
        },
        "logViewerService/logviewerservice.h": {
            "a": [
                "    Q_SCRIPTABLE bool exportOpsLog();"
            ],
            "b": [
                "    Q_SCRIPTABLE QString exportOpsLog();",
                "    // \u6e05\u7406 exportOpsLog \u5728 /var/log \u4e0b\u521b\u5efa\u7684\u4e34\u65f6\u5bfc\u51fa\u76ee\u5f55\u3002\u65e0\u53c2\uff1a\u6e05\u7406\u7684\u662f\u670d\u52a1\u7aef\u7f13\u5b58",
                "    QString m_opsTempDir;  // exportOpsLog \u521b\u5efa\u7684 /var/log \u4e34\u65f6\u76ee\u5f55\u8def\u5f84\uff0c\u4f9b removeOpsLogTempDir \u6e05\u7406"
            ]
        },
        "logViewerService/opslogexport.cpp": {
            "a": [
                "            qWarning() << \"Failed to chown export path:\" << path << \"error:\" << strerror(errno);"
            ],
            "b": [
                "        qWarning() << \"OpsLogExport::run: target directory safety check failed, aborting export\";",
                " * target_dir \u7531 LogViewerService::exportOpsLog() \u901a\u8fc7 QTemporaryDir \u5728 /var/log \u4e0b",
                "    // - 0750/0640 \u800c\u975e 0755/0644\uff1a\u4ec5 caller \u540c\u7ec4\u53ef\u8bfb\uff0c\u907f\u514d\u4efb\u610f\u672c\u5730\u7528\u6237\u5728 exportOpsLog",
                "            qWarning() << \"Failed to chgrp export path:\" << path << \"error:\" << strerror(errno);"
            ]
        }
    }
}

@GongHeng2017
GongHeng2017 force-pushed the 202607021032-re-eagle-fix branch from 45900f0 to ad08fc3 Compare July 3, 2026 03:34
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
  • 检测到敏感词export变动
详情
    {
    "export": {
        "application/dbusproxy/dldbushandler.cpp": {
            "a": [
                "bool DLDBusHandler::exportOpsLog()",
                "    QDBusPendingReply<bool> reply = m_dbus->exportOpsLog();",
                "        qCDebug(logDBusHandler) << \"exportOpsLog succeeded:\" << reply.value();"
            ],
            "b": [
                "QString DLDBusHandler::exportOpsLog()",
                "    QDBusPendingReply<QString> reply = m_dbus->exportOpsLog();",
                "        qCDebug(logDBusHandler) << \"exportOpsLog succeeded, root temp dir:\" << reply.value();"
            ]
        },
        "application/dbusproxy/dldbushandler.h": {
            "a": [
                "    bool exportOpsLog();"
            ],
            "b": [
                "    QString exportOpsLog();"
            ]
        },
        "application/dbusproxy/dldbusinterface.h": {
            "a": [
                "    inline QDBusPendingReply<bool> exportOpsLog()"
            ],
            "b": [
                "    inline QDBusPendingReply<QString> exportOpsLog()"
            ]
        },
        "application/logallexportthread.cpp": {
            "a": [
                "        DLDBusHandler::instance(this)->exportOpsLog();",
                "        Utils::exportSomeOpsLogs(opsLogPath, userHomePath);"
            ],
            "b": [
                "        QString rootTempDir = DLDBusHandler::instance(this)->exportOpsLog();",
                "            qCWarning(logExportAll) << \"exportOpsLog returned empty or non-existent root temp dir, root-side ops logs may be missing\";",
                "        Utils::exportUserPermissionOpsLogs(opsLogPath, userHomePath);"
            ]
        },
        "application/opslogpaths.h": {
            "b": [
                "// \u524d\u7aef\uff08application/utils.cpp \u7684 exportUserPermissionOpsLogs \u7cfb\u5217\uff09\u4e0e",
                "// root \u670d\u52a1\uff08logViewerService/opslogexport.cpp \u7684 createOpsLogDirStruct\uff09\u5fc5\u987b"
            ]
        },
        "application/utils.cpp": {
            "a": [
                "void Utils::exportSomeOpsLogs(const QString &outDir, const QString &userHomeDir)"
            ],
            "b": [
                "// \u5b89\u5168\u62f7\u8d1d\u8f85\u52a9\uff1a\u5bf9\u9f50 root \u4fa7 opslogexport.cpp \u7684\u7b26\u53f7\u94fe\u63a5\u9632\u62a4\u7b56\u7565\u3002",
                "void Utils::exportUserPermissionAppLogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionSystemLogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionKernelLogs(const QString &outDir)",
                "void Utils::exportUserPermissionDDELogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionOpsLogs(const QString &outDir, const QString &userHomeDir)",
                "    Utils::exportUserPermissionAppLogs(outDir, userHomeDir);",
                "    Utils::exportUserPermissionSystemLogs(outDir, userHomeDir);",
                "    Utils::exportUserPermissionKernelLogs(outDir);",
                "    Utils::exportUserPermissionDDELogs(outDir, userHomeDir);"
            ]
        },
        "application/utils.h": {
            "a": [
                "    static void exportSomeOpsLogs(const QString &outDir, const QString &userHomeDir);"
            ],
            "b": [
                "    static void exportUserPermissionAppLogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionSystemLogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionKernelLogs(const QString &outDir);",
                "    static void exportUserPermissionDDELogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionOpsLogs(const QString &outDir, const QString &userHomeDir);"
            ]
        },
        "logViewerService/assets/data/com.deepin.logviewer.xml": {
            "b": [
                "    <method name=\"exportOpsLog\">"
            ]
        },
        "logViewerService/assets/data/deepin-log-viewer-daemon.service": {
            "b": [
                "# exportOpsLog \u9700\u8981\u5728 /var/log \u4e0b\u521b\u5efa\u4e34\u65f6\u5bfc\u51fa\u76ee\u5f55\uff0c\u987b\u663e\u5f0f\u653e\u5f00\u5199\u6743\u9650"
            ]
        },
        "logViewerService/logviewerservice.cpp": {
            "a": [
                "bool LogViewerService::exportOpsLog()",
                "        qCWarning(logService) << \"Failed to get caller home directory for export log\";"
            ],
            "b": [
                "QString LogViewerService::exportOpsLog()",
                "        qCWarning(logService) << \"Failed to get caller identity for export log\";",
                "        qCWarning(logService) << \"exportOpsLog: failed to create temporary dir under /var/log:\" << tmpOpsDir.errorString();",
                "    // \u6388\u6743\u6821\u9a8c\uff1a\u4e0e exportOpsLog \u4e00\u81f4\uff0c\u4f7f\u7528 s_Action_View\u3002",
                "    // \u65e0\u53c2\u8bbe\u8ba1\uff1a\u6e05\u7406\u7684\u662f\u670d\u52a1\u7aef\u5728 exportOpsLog \u4e2d\u7f13\u5b58\u7684\u672c\u8fdb\u7a0b\u4e34\u65f6\u76ee\u5f55\u8def\u5f84\uff0c"
            ]
        },
        "logViewerService/logviewerservice.h": {
            "a": [
                "    Q_SCRIPTABLE bool exportOpsLog();"
            ],
            "b": [
                "    Q_SCRIPTABLE QString exportOpsLog();",
                "    // \u6e05\u7406 exportOpsLog \u5728 /var/log \u4e0b\u521b\u5efa\u7684\u4e34\u65f6\u5bfc\u51fa\u76ee\u5f55\u3002\u65e0\u53c2\uff1a\u6e05\u7406\u7684\u662f\u670d\u52a1\u7aef\u7f13\u5b58",
                "    QString m_opsTempDir;  // exportOpsLog \u521b\u5efa\u7684 /var/log \u4e34\u65f6\u76ee\u5f55\u8def\u5f84\uff0c\u4f9b removeOpsLogTempDir \u6e05\u7406"
            ]
        },
        "logViewerService/opslogexport.cpp": {
            "a": [
                "            qWarning() << \"Failed to chown export path:\" << path << \"error:\" << strerror(errno);"
            ],
            "b": [
                "        qWarning() << \"OpsLogExport::run: target directory safety check failed, aborting export\";",
                " * target_dir \u7531 LogViewerService::exportOpsLog() \u901a\u8fc7 QTemporaryDir \u5728 /var/log \u4e0b",
                "    // - 0750/0640 \u800c\u975e 0755/0644\uff1a\u4ec5 caller \u540c\u7ec4\u53ef\u8bfb\uff0c\u907f\u514d\u4efb\u610f\u672c\u5730\u7528\u6237\u5728 exportOpsLog",
                "            qWarning() << \"Failed to chgrp export path:\" << path << \"error:\" << strerror(errno);"
            ]
        }
    }
}

@GongHeng2017
GongHeng2017 force-pushed the 202607021032-re-eagle-fix branch from ad08fc3 to 4142b4d Compare July 3, 2026 03:56
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
  • 检测到敏感词export变动
详情
    {
    "export": {
        "application/dbusproxy/dldbushandler.cpp": {
            "a": [
                "bool DLDBusHandler::exportOpsLog()",
                "    QDBusPendingReply<bool> reply = m_dbus->exportOpsLog();",
                "        qCDebug(logDBusHandler) << \"exportOpsLog succeeded:\" << reply.value();"
            ],
            "b": [
                "QString DLDBusHandler::exportOpsLog()",
                "    QDBusPendingReply<QString> reply = m_dbus->exportOpsLog();",
                "        qCDebug(logDBusHandler) << \"exportOpsLog succeeded, root temp dir:\" << reply.value();"
            ]
        },
        "application/dbusproxy/dldbushandler.h": {
            "a": [
                "    bool exportOpsLog();"
            ],
            "b": [
                "    QString exportOpsLog();"
            ]
        },
        "application/dbusproxy/dldbusinterface.h": {
            "a": [
                "    inline QDBusPendingReply<bool> exportOpsLog()"
            ],
            "b": [
                "    inline QDBusPendingReply<QString> exportOpsLog()"
            ]
        },
        "application/logallexportthread.cpp": {
            "a": [
                "        DLDBusHandler::instance(this)->exportOpsLog();",
                "        Utils::exportSomeOpsLogs(opsLogPath, userHomePath);"
            ],
            "b": [
                "        QString rootTempDir = DLDBusHandler::instance(this)->exportOpsLog();",
                "            qCWarning(logExportAll) << \"exportOpsLog returned empty or non-existent root temp dir, root-side ops logs may be missing\";",
                "        Utils::exportUserPermissionOpsLogs(opsLogPath, userHomePath);"
            ]
        },
        "application/opslogpaths.h": {
            "b": [
                "// \u524d\u7aef\uff08application/utils.cpp \u7684 exportUserPermissionOpsLogs \u7cfb\u5217\uff09\u4e0e",
                "// root \u670d\u52a1\uff08logViewerService/opslogexport.cpp \u7684 createOpsLogDirStruct\uff09\u5fc5\u987b"
            ]
        },
        "application/utils.cpp": {
            "a": [
                "void Utils::exportSomeOpsLogs(const QString &outDir, const QString &userHomeDir)"
            ],
            "b": [
                "// \u5b89\u5168\u62f7\u8d1d\u8f85\u52a9\uff1a\u5bf9\u9f50 root \u4fa7 opslogexport.cpp \u7684\u7b26\u53f7\u94fe\u63a5\u9632\u62a4\u7b56\u7565\u3002",
                "void Utils::exportUserPermissionAppLogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionSystemLogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionKernelLogs(const QString &outDir)",
                "void Utils::exportUserPermissionDDELogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionOpsLogs(const QString &outDir, const QString &userHomeDir)",
                "    Utils::exportUserPermissionAppLogs(outDir, userHomeDir);",
                "    Utils::exportUserPermissionSystemLogs(outDir, userHomeDir);",
                "    Utils::exportUserPermissionKernelLogs(outDir);",
                "    Utils::exportUserPermissionDDELogs(outDir, userHomeDir);"
            ]
        },
        "application/utils.h": {
            "a": [
                "    static void exportSomeOpsLogs(const QString &outDir, const QString &userHomeDir);"
            ],
            "b": [
                "    static void exportUserPermissionAppLogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionSystemLogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionKernelLogs(const QString &outDir);",
                "    static void exportUserPermissionDDELogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionOpsLogs(const QString &outDir, const QString &userHomeDir);"
            ]
        },
        "logViewerService/assets/data/com.deepin.logviewer.xml": {
            "b": [
                "    <method name=\"exportOpsLog\">"
            ]
        },
        "logViewerService/assets/data/deepin-log-viewer-daemon.service": {
            "b": [
                "# exportOpsLog \u9700\u8981\u5728 /var/log \u4e0b\u521b\u5efa\u4e34\u65f6\u5bfc\u51fa\u76ee\u5f55\uff0c\u987b\u663e\u5f0f\u653e\u5f00\u5199\u6743\u9650"
            ]
        },
        "logViewerService/logviewerservice.cpp": {
            "a": [
                "bool LogViewerService::exportOpsLog()",
                "        qCWarning(logService) << \"Failed to get caller home directory for export log\";"
            ],
            "b": [
                "QString LogViewerService::exportOpsLog()",
                "        qCWarning(logService) << \"Failed to get caller identity for export log\";",
                "        qCWarning(logService) << \"exportOpsLog: failed to create temporary dir under /var/log:\" << tmpOpsDir.errorString();",
                "    // \u6388\u6743\u6821\u9a8c\uff1a\u4e0e exportOpsLog \u4e00\u81f4\uff0c\u4f7f\u7528 s_Action_View\u3002",
                "    // \u65e0\u53c2\u8bbe\u8ba1\uff1a\u6e05\u7406\u7684\u662f\u670d\u52a1\u7aef\u5728 exportOpsLog \u4e2d\u7f13\u5b58\u7684\u672c\u8fdb\u7a0b\u4e34\u65f6\u76ee\u5f55\u8def\u5f84\uff0c"
            ]
        },
        "logViewerService/logviewerservice.h": {
            "a": [
                "    Q_SCRIPTABLE bool exportOpsLog();"
            ],
            "b": [
                "    Q_SCRIPTABLE QString exportOpsLog();",
                "    // \u6e05\u7406 exportOpsLog \u5728 /var/log \u4e0b\u521b\u5efa\u7684\u4e34\u65f6\u5bfc\u51fa\u76ee\u5f55\u3002\u65e0\u53c2\uff1a\u6e05\u7406\u7684\u662f\u670d\u52a1\u7aef\u7f13\u5b58",
                "    QString m_opsTempDir;  // exportOpsLog \u521b\u5efa\u7684 /var/log \u4e34\u65f6\u76ee\u5f55\u8def\u5f84\uff0c\u4f9b removeOpsLogTempDir \u6e05\u7406"
            ]
        },
        "logViewerService/opslogexport.cpp": {
            "a": [
                "            qWarning() << \"Failed to chown export path:\" << path << \"error:\" << strerror(errno);"
            ],
            "b": [
                "        qWarning() << \"OpsLogExport::run: target directory safety check failed, aborting export\";",
                " * target_dir \u7531 LogViewerService::exportOpsLog() \u901a\u8fc7 QTemporaryDir \u5728 /var/log \u4e0b",
                "    // - 0750/0640 \u800c\u975e 0755/0644\uff1a\u4ec5 caller \u540c\u7ec4\u53ef\u8bfb\uff0c\u907f\u514d\u4efb\u610f\u672c\u5730\u7528\u6237\u5728 exportOpsLog",
                "            qWarning() << \"Failed to chgrp export path:\" << path << \"error:\" << strerror(errno);"
            ]
        }
    }
}

… /var/log

Root service no longer writes into the caller's home dir; it creates a
random temp dir under /var/log, exports system logs there, and returns
the path. The frontend collects user-permission logs itself and copies
the root-exported logs out. cp -rP avoids following symlinks, target
dir is validated under /var/log, perms tightened to 0755/0644.

root 服务不再写入用户家目录,改为在 /var/log 下创建随机临时目录导出系统
日志并返回路径;前端自行收集用户权限日志并拷贝 root 导出的内容。cp -rP
不跟随符号链接,校验目标目录位于 /var/log,权限收紧为 0755/0644。

Log: 重构运维日志导出,root 不再写入用户家目录
Influence: 消除 root 服务写入用户家目录的符号链接攻击面,改由 root 在 /var/log 随机目录导出、前端拷贝,提升安全性。
@GongHeng2017
GongHeng2017 force-pushed the 202607021032-re-eagle-fix branch from 4142b4d to 60e1fe7 Compare July 3, 2026 05:17
@github-actions

github-actions Bot commented Jul 3, 2026

Copy link
Copy Markdown
  • 检测到敏感词export变动
详情
    {
    "export": {
        "application/dbusproxy/dldbushandler.cpp": {
            "a": [
                "bool DLDBusHandler::exportOpsLog()",
                "    QDBusPendingReply<bool> reply = m_dbus->exportOpsLog();",
                "        qCDebug(logDBusHandler) << \"exportOpsLog succeeded:\" << reply.value();"
            ],
            "b": [
                "QString DLDBusHandler::exportOpsLog()",
                "    QDBusPendingReply<QString> reply = m_dbus->exportOpsLog();",
                "        qCDebug(logDBusHandler) << \"exportOpsLog succeeded, root temp dir:\" << reply.value();"
            ]
        },
        "application/dbusproxy/dldbushandler.h": {
            "a": [
                "    bool exportOpsLog();"
            ],
            "b": [
                "    QString exportOpsLog();"
            ]
        },
        "application/dbusproxy/dldbusinterface.h": {
            "a": [
                "    inline QDBusPendingReply<bool> exportOpsLog()"
            ],
            "b": [
                "    inline QDBusPendingReply<QString> exportOpsLog()"
            ]
        },
        "application/logallexportthread.cpp": {
            "a": [
                "        DLDBusHandler::instance(this)->exportOpsLog();",
                "        Utils::exportSomeOpsLogs(opsLogPath, userHomePath);"
            ],
            "b": [
                "        QString rootTempDir = DLDBusHandler::instance(this)->exportOpsLog();",
                "            qCWarning(logExportAll) << \"exportOpsLog returned empty or non-existent root temp dir, root-side ops logs may be missing\";",
                "        Utils::exportUserPermissionOpsLogs(opsLogPath, userHomePath);"
            ]
        },
        "application/opslogpaths.h": {
            "b": [
                "// \u524d\u7aef\uff08application/utils.cpp \u7684 exportUserPermissionOpsLogs \u7cfb\u5217\uff09\u4e0e",
                "// root \u670d\u52a1\uff08logViewerService/opslogexport.cpp \u7684 createOpsLogDirStruct\uff09\u5fc5\u987b"
            ]
        },
        "application/utils.cpp": {
            "a": [
                "void Utils::exportSomeOpsLogs(const QString &outDir, const QString &userHomeDir)"
            ],
            "b": [
                "// \u5b89\u5168\u62f7\u8d1d\u8f85\u52a9\uff1a\u5bf9\u9f50 root \u4fa7 opslogexport.cpp \u7684\u7b26\u53f7\u94fe\u63a5\u9632\u62a4\u7b56\u7565\u3002",
                "void Utils::exportUserPermissionAppLogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionSystemLogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionKernelLogs(const QString &outDir)",
                "void Utils::exportUserPermissionDDELogs(const QString &outDir, const QString &userHomeDir)",
                "void Utils::exportUserPermissionOpsLogs(const QString &outDir, const QString &userHomeDir)",
                "    Utils::exportUserPermissionAppLogs(outDir, userHomeDir);",
                "    Utils::exportUserPermissionSystemLogs(outDir, userHomeDir);",
                "    Utils::exportUserPermissionKernelLogs(outDir);",
                "    Utils::exportUserPermissionDDELogs(outDir, userHomeDir);"
            ]
        },
        "application/utils.h": {
            "a": [
                "    static void exportSomeOpsLogs(const QString &outDir, const QString &userHomeDir);"
            ],
            "b": [
                "    static void exportUserPermissionAppLogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionSystemLogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionKernelLogs(const QString &outDir);",
                "    static void exportUserPermissionDDELogs(const QString &outDir, const QString &userHomeDir);",
                "    static void exportUserPermissionOpsLogs(const QString &outDir, const QString &userHomeDir);"
            ]
        },
        "logViewerService/assets/data/com.deepin.logviewer.xml": {
            "b": [
                "    <method name=\"exportOpsLog\">"
            ]
        },
        "logViewerService/assets/data/deepin-log-viewer-daemon.service": {
            "b": [
                "# exportOpsLog \u9700\u8981\u5728 /var/log \u4e0b\u521b\u5efa\u4e34\u65f6\u5bfc\u51fa\u76ee\u5f55\uff0c\u987b\u663e\u5f0f\u653e\u5f00\u5199\u6743\u9650"
            ]
        },
        "logViewerService/logviewerservice.cpp": {
            "a": [
                "bool LogViewerService::exportOpsLog()",
                "        qCWarning(logService) << \"Failed to get caller home directory for export log\";"
            ],
            "b": [
                "QString LogViewerService::exportOpsLog()",
                "        qCWarning(logService) << \"Failed to get caller identity for export log\";",
                "        qCWarning(logService) << \"exportOpsLog: failed to create temporary dir under /var/log:\" << tmpOpsDir.errorString();",
                "    // \u6388\u6743\u6821\u9a8c\uff1a\u4e0e exportOpsLog \u4e00\u81f4\uff0c\u4f7f\u7528 s_Action_View\u3002",
                "    // \u65e0\u53c2\u8bbe\u8ba1\uff1a\u6e05\u7406\u7684\u662f\u670d\u52a1\u7aef\u5728 exportOpsLog \u4e2d\u6309\u5f53\u524d\u8c03\u7528\u8005\u7f13\u5b58\u7684\u672c\u8fdb\u7a0b\u4e34\u65f6\u76ee\u5f55\u8def\u5f84\uff0c"
            ]
        },
        "logViewerService/logviewerservice.h": {
            "a": [
                "    Q_SCRIPTABLE bool exportOpsLog();"
            ],
            "b": [
                "    Q_SCRIPTABLE QString exportOpsLog();",
                "    // \u6e05\u7406 exportOpsLog \u5728 /var/log \u4e0b\u521b\u5efa\u7684\u4e34\u65f6\u5bfc\u51fa\u76ee\u5f55\u3002\u65e0\u53c2\uff1a\u6e05\u7406\u7684\u662f\u670d\u52a1\u7aef\u7f13\u5b58",
                "    // exportOpsLog \u521b\u5efa\u7684 /var/log \u4e34\u65f6\u76ee\u5f55\u8def\u5f84\uff0c\u6309 D-Bus \u8c03\u7528\u65b9 unique bus name \u9694\u79bb\u5b58\u50a8\uff0c",
                "    // \u6309 fd-relative \u5b89\u5168\u65b9\u5f0f\u5220\u9664 exportOpsLog \u4ea7\u751f\u7684 /var/log \u4e34\u65f6\u76ee\u5f55\uff08path \u4e3a\u7f13\u5b58\u8def\u5f84\uff09\u3002"
            ]
        },
        "logViewerService/opslogexport.cpp": {
            "a": [
                "            qWarning() << \"Failed to chown export path:\" << path << \"error:\" << strerror(errno);"
            ],
            "b": [
                "        qWarning() << \"OpsLogExport::run: target directory safety check failed, aborting export\";",
                " * target_dir \u7531 LogViewerService::exportOpsLog() \u901a\u8fc7 QTemporaryDir \u5728 /var/log \u4e0b",
                "    // - 0750/0640 \u800c\u975e 0755/0644\uff1a\u4ec5 caller \u540c\u7ec4\u53ef\u8bfb\uff0c\u907f\u514d\u4efb\u610f\u672c\u5730\u7528\u6237\u5728 exportOpsLog",
                "            qWarning() << \"Failed to chgrp export path:\" << path << \"error:\" << strerror(errno);"
            ]
        }
    }
}

@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

★ 总体评分:100分

■ 【总体评价】

代码实现了极其优秀的符号链接攻击面消除与TOCTOU安全加固重构,无任何安全缺陷
逻辑严密、注释详尽、架构拆分合理,完全符合安全编码规范,无需扣分

■ 【详细分析】

  • 1.语法逻辑(完全正确)✓

代码重构彻底且逻辑自洽,safeRemoveDirRecursive 函数通过先收集目录条目再遍历删除的方式,完美规避了在迭代过程中修改目录结构导致的未定义行为。基于文件描述符的 openat/fstatat/unlinkat 调用链签名准确,AT_SYMLINK_NOFOLLOW 与 O_NOFOLLOW 标志位使用正确。getCallerHomeAndGid 改为输出参数形式,错误处理路径均返回 false 并附带日志,无空指针解引用或内存泄漏风险。

  • 2.代码质量(优秀)✓

架构设计极具前瞻性,将前后端共享的目录结构提取为 opslogpaths.h 公共头文件,彻底消除了硬编码路径不一致的维护隐患。前端日志收集逻辑拆分为 exportUserPermissionAppLogs 等多个职责单一的函数,可读性大幅提升。注释质量极高,不仅说明了“做什么”,更深入阐释了“为什么”(如解释不把 owner 改成 caller 的原因、解释 /var/log 自身可能是符号链接的场景),是教科书级别的安全注释。

  • 3.代码性能(高效)✓

safeRemoveDirRecursive 预分配 QVector 存储条目名,避免了反复进入内核态,对于临时目录内有限数量的日志文件而言性能开销极低且安全收益巨大。processCmdWithArgs 引入 300 秒超时上限,从系统整体可用性角度看是极大的性能与稳定性提升,有效防止了导出线程被特殊设备文件永久阻塞。

  • 4.代码安全(存在0个安全漏洞)✓

漏洞对比统计:新增漏洞 0 个,减少漏洞 1 个,持平 0 个
本次重构彻底消除了原有的“root 服务直接写用户家目录导致的符号链接跟随与拒绝服务”严重漏洞。新增代码在各个维度均实现了严密防护:1. 消除写攻击面,root 不再操作用户可控路径;2. 全链路符号链接拦截,root 侧 isSymLink 过滤与 cp -rP 结合,前端 safeCpSkipSymlinks 双重保险;3. TOCTOU 安全删除,全程 fd-relative 操作不重新解析路径;4. 最小权限隔离,0750/0640 配合 callerGid 确保用户仅读不可写;5. 无参清理接口杜绝路径注入。经逐行审计,未发现任何新的安全漏洞。

■ 【改进建议代码示例】

// utils.cpp 中的 safeCpSkipSymlinks 优化:增加空列表检查,避免极端情况下执行无效的 cp 命令
static void safeCpSkipSymlinks(const QStringList &sources, const QString &dest, bool recursive)
{
    QStringList validSources;
    for (const QString &src : sources) {
        if (QFileInfo(src).isSymLink()) {
            qCWarning(logUtils) << "skip symlink source to avoid DoS:" << src;
            continue;
        }
        validSources << src;
    }

    // 防御性检查:若所有源路径均为符号链接被过滤,直接返回,避免执行 "cp -P dest" 导致命令报错
    if (validSources.isEmpty()) {
        qCWarning(logUtils) << "no valid sources to copy after symlink filtering, skipping cp";
        return;
    }

    QStringList args;
    args << "-P";  // 不跟随源参数自身及递归树内的符号链接
    if (recursive)
        args << "-r";
    args << validSources << dest;
    Utils::executeCmd("cp", args);
}

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: GongHeng2017, max-lvs

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@GongHeng2017

Copy link
Copy Markdown
Contributor Author

/forcemerge

@deepin-bot

deepin-bot Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

This pr force merged! (status: unstable)

@deepin-bot
deepin-bot Bot merged commit 23fb3f5 into linuxdeepin:release/eagle Jul 3, 2026
21 of 23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants