# openEuler 24.03 MATE 桌面登录要输两次密码?lightdm-gtk-greeter 空指针崩溃修复实录

 

> 环境:openEuler 24.03 LTS SP4 x86_64,内核 6.6.0-159.4.10.164.oe2403sp4,MATE 1.28,

> lightdm 1.30.0-14,lightdm-gtk(lightdm-gtk-greeter)2.0.8-2,cairo 1.18.0-2

>

> 现象:每次开机在登录界面输入密码后,**总要重新输一次密码、登录两次才能进桌面**。

 

## 一、问题现象

 

- 开机进入登录界面 → 输入密码 → 屏幕一闪,登录界面重新出现 → 再次输入密码 → 成功进桌面。

- 每次开机必现,且第二次登录必然成功。

- `/var/log/lightdm/seat0-greeter.log` 反复出现:

 

```

(lightdm-gtk-greeter:1359): Gtk-WARNING: Drawing a gadget with negative dimensions. (node menubar owner GreeterMenuBar)

```

 

## 二、初步排查:确实是 greeter 崩溃,LightDM 自动重启登录界面

 

1. **coredump 证据**:`/var/lib/systemd/coredump/` 里每次开机都有一个新的 `core.lightdm-gtk-gre.*`,说明登录界面进程每次必崩一次。

 

2. **内核日志**(崩溃现场):

 

```

kernel: lightdm-gtk-gre[1359]: segfault at 10 ip ... in libcairo.so.2.11802.2 ...

```

 

3. **lightdm 日志**(`/var/log/lightdm/lightdm.log.old`)证实了"崩溃 → 重启"的完整链路:

 

```

[+188.72s] Continue authentication

[+190.46s] Authentication complete with return value 0: 成功 ← 密码已通过!

[+201.43s] Session pid=1334: Exited with return value 1 ← greeter 进程退出(崩溃)

[+201.43s] ... (随后 LightDM 重新拉起 greeter,用户被迫再次登录)

```

 

> 关键点:**第一次输入的密码其实已经验证通过了**,崩溃发生在认证成功之后、会话启动之前。

 

## 三、误入歧途:以为是 cairo 的 bug(排除过程)

 

崩溃地址在 `libcairo.so.2` 里,于是怀疑是 cairo 1.18.0 的缺陷(当时 openEuler 恰好有 CVE-2025-50422 的补丁,属于同一家族)。

 

- 把 cairo 升级到 openEuler 25.03 仓库的 **1.18.2**(`dnf install https://.../cairo-1.18.2-1.oe2503.x86_64.rpm`,注意要连同 `cairo-gobject` 一起升,否则版本锁冲突)→ **重启后依然崩溃**。

- 对比 cairo 1.18.0 与 1.18.2 源码,崩溃相关文件(`cairo-rectangle.c`/`cairo-spline.c`/`cairo-boxes.c`)**完全没变**,升级无效是必然的。

 

**结论:崩溃点虽然在 cairo 里,但根因不在 cairo,而是调用方传了空指针。**

 

## 四、决定性证据:gdb 解开 coredump 拿到调用栈

 

```bash

sudo dnf install -y gdb

sudo unlz4 -f /var/lib/systemd/coredump/core.lightdm-gtk-gre.*.lz4 /tmp/greeter-core

sudo gdb -batch -ex "bt" -ex "info registers" /usr/sbin/lightdm-gtk-greeter /tmp/greeter-core

```

 

调用栈:

 

```

#0 cairo_surface_get_type () in /usr/lib64/libcairo.so.2

#1 greeter_background_save_xroot () ← greeter 自己的背景保存函数

#2 内部回调

#7 liblightdm-gobject-1.so ← LightDM 信号触发(认证完成)

#13 main ()

```

 

寄存器:`rdi = 0x0` —— **`cairo_surface_get_type(NULL)` 传入了空指针**,读取 `surface->type`(偏移 0x10)→ 段错误(与内核日志 `segfault at 10` 完全吻合)。

 

## 五、根因定位(源码级)

 

`lightdm-gtk-greeter-2.0.8/src/greeterbackground.c` 中:

 

```c

void greeter_background_save_xroot(GreeterBackground* background)

{

    ...

    surface = create_root_surface(priv->screen); // ← 返回 NULL!

    cr = cairo_create(surface);

    ...

    set_surface_as_root(priv->screen, surface); // ← 这里对 NULL 调 cairo_surface_get_type

}

```

 

`create_root_surface()` 返回 NULL 的唯一路径是 **`XOpenDisplay()` 失败**:

 

```c

static cairo_surface_t* create_root_surface(GdkScreen* screen)

{

    ...

    display = XOpenDisplay (gdk_display_get_name (...));

    if (!display)

    {

        g_warning("[Background] Failed to create root pixmap");

        return NULL; // ← 崩溃前的警告

    }

    ...

}

```

 

而 `set_surface_as_root()` 第一行就直接对参数取类型,**没有判空**:

 

```c

static void set_surface_as_root(GdkScreen* screen, cairo_surface_t* surface)

{

    g_return_if_fail(cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB); // NULL → 段错误

    ...

}

```

 

崩溃前 greeter 日志的最后两行(实锤):

 

```

No protocol specified

** (lightdm-gtk-greeter:1359): WARNING: [Background] Failed to create root pixmap

```

 

**`No protocol specified` = XOpenDisplay 新连接被 X 服务器以 X 授权失败拒绝**(登录成功瞬间 LightDM 轮换/清理了授权文件,greeter 用旧 cookie 打不开新连接)。greeter 没处理 NULL → 段错误 → LightDM 重启登录界面 → 用户再输一次密码。

 

> 这是 **lightdm-gtk-greeter 上游至今未修的 bug**(2.0.9 同样存在),与 cairo 无关。

 

## 六、修复方案:打补丁重新编译

 

对 `greeterbackground.c` 加空指针检查(两处,防御性):

 

```diff

--- a/src/greeterbackground.c

+++ b/src/greeterbackground.c

@@ -1087,6 +1087,11 @@ greeter_background_save_xroot(GreeterBackground* background)

 

     priv = background->priv;

     surface = create_root_surface(priv->screen);

+ if (surface == NULL)

+ {

+ g_warning("[Background] Failed to create root surface, skipping");

+ return;

+ }

     cr = cairo_create(surface);

 

     gdk_cairo_set_source_rgba(cr, &ROOT_COLOR);

```

 

```diff

--- a/src/greeterbackground.c

+++ b/src/greeterbackground.c

@@ -1740,6 +1740,7 @@ set_surface_as_root(GdkScreen* screen, cairo_surface_t* surface)

     Pixmap pixmap_id;

     Window xroot;

 

+ g_return_if_fail(surface != NULL);

     g_return_if_fail(cairo_surface_get_type (surface) == CAIRO_SURFACE_TYPE_XLIB);

```

 

编译安装步骤(openEuler 24.03 SP4 实测可用):

 

```bash

# 1. 安装构建依赖

sudo dnf install -y gtk3-devel lightdm-gobject-devel automake autoconf libtool \

    intltool gettext-devel gobject-introspection-devel xfce4-dev-tools

 

# 2. 下载源码(2.0.8,官方 tag)

curl -L -o lgg208.tar.gz https://codeload.github.com/Xubuntu/lightdm-gtk-greeter/tar.gz/refs/tags/lightdm-gtk-greeter-2.0.8

tar xzf lgg208.tar.gz && cd lightdm-gtk-greeter-lightdm-gtk-greeter-2.0.8

 

# 3. 应用上面的补丁(编辑 src/greeterbackground.c)

 

# 4. 构建(注意:2.0.8 是 GTK3 版,需要 gtk3-devel 而非 gtk2-devel)

autoreconf -fi

./configure --prefix=/usr

make -j$(nproc)

# 若提示 xdt-csource 生成头文件失败,手工生成:

# cd src && xdt-csource --static --strip-comments --strip-content --name=lightdm_gtk_greeter_ui lightdm-gtk-greeter.glade > lightdm-gtk-greeter-ui.h && cd ..

 

# 5. 备份并安装

sudo cp /usr/sbin/lightdm-gtk-greeter /usr/sbin/lightdm-gtk-greeter.orig

sudo cp src/lightdm-gtk-greeter /usr/sbin/lightdm-gtk-greeter

 

# 6. 重启验证

sudo reboot

```

 

## 七、验证结果

 

- 重启后**输入一次密码直接进桌面**。

- `/var/lib/systemd/coredump/` 不再产生新的崩溃记录。

- 登录界面外观、功能与原来完全一致(该补丁只在"创建根窗口背景失败"时跳过该步骤,不影响任何正常功能)。

 

## 八、给维护者的建议

 

1. 该修复(`create_root_surface()` 返回值判空)应提交到上游 https://github.com/Xubuntu/lightdm-gtk-greeter,2.0.9 仍有此问题。

2. 另外建议关注 `GreeterMenuBar` 的 "negative dimensions" 布局警告(Debian Bug #1085346),虽不致命但会刷爆 `seat0-greeter.log`。

3. 顺带一提:排查中还发现 X 授权文件在会话启动瞬间会被 LightDM 轮换,导致 greeter 的新 X 连接失败——若上游愿意,也可以研究让 `save_xroot` 复用现有连接而不是另开一个。

 

---

 

*附:本次排查用到的关键命令(gdb 调用栈、lightdm 日志、coredump 分析)已在文中给出;若你的发行版 lightdm-gtk-greeter 版本不同,补丁位置(`greeter_background_save_xroot`)不变,可对照源码适配。*

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐