Bug 2158724
| Summary: | systemd can send non-UTF8 messages over DBus, causing DBus to disconnect it | ||
|---|---|---|---|
| Product: | Red Hat Enterprise Linux 8 | Reporter: | Renaud Métrich <rmetrich> |
| Component: | systemd | Assignee: | Michal Sekletar <msekleta> |
| Status: | ON_QA --- | QA Contact: | Frantisek Sumsal <fsumsal> |
| Severity: | high | Docs Contact: | |
| Priority: | high | ||
| Version: | 8.7 | CC: | bwelterl, dking, jamacku, kurathod, msekleta, qguo, systemd-maint-list |
| Target Milestone: | rc | Keywords: | Triaged |
| Target Release: | --- | ||
| Hardware: | All | ||
| OS: | Linux | ||
| Whiteboard: | |||
| Fixed In Version: | systemd-239-77.el8 | Doc Type: | If docs needed, set a value |
| Doc Text: | Story Points: | --- | |
| Clone Of: | Environment: | ||
| Last Closed: | Type: | Bug | |
| Regression: | --- | Mount Type: | --- |
| Documentation: | --- | CRM: | |
| Verified Versions: | Category: | --- | |
| oVirt Team: | --- | RHEL 7.3 requirements from Atomic Host: | |
| Cloudforms Team: | --- | Target Upstream Version: | |
| Embargoed: | |||
|
Description
Renaud Métrich
2023-01-06 10:20:41 UTC
UPDATED DESCRIPTION: The DBus message sent upon mounting a CIFS share can be broken, depending on the output of `/proc/self/mountinfo` and `/run/mount/utab` systemd relies on to build the message: in case the CIFS share is presented by a NetApp appliance and contains non-ascii characters (e.g. "ü") and charset "iso8859-1" is used, systemd sends a non-UTF8 message through the bus, causing DBus to disconnect it. Example of CIFS share listed in /proc/self/mountinfo (redacted): -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< -------- //netapp.server/path/to/share/containing/umlaut_xxx�xxx /mount/point cifs rw,relatime,vers=3.0,xxx,iocharset=iso8859-1,xxx 0 0 -------- 8< ---------------- 8< ---------------- 8< ---------------- 8< -------- I think we need to ensure that systemd always sends properly formatted messages to avoid any DBus breakage. See also related BZs: - #2162660 (DBus) - #2162655 (Kernel/CIFS) REPRODUCER BELOW:
We can reproduce through having a CIFS share, which we then hack (using systemtap) to push a non-UTF8 character, see below.
CIFS setup (local):
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
# yum -y install samba
# cat >> /etc/samba/smb.conf << EOF
[cifs]
path = /cifs
browseable = Yes
read only = No
guest ok = Yes
EOF
# mkdir -p /cifs/ssXss
# echo "//localhost/cifs/ssXss /mnt cifs guest,noauto 0 0" >> /etc/fstab
# systemctl enable smb --now
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
SYSTEMTAP SCRIPT (let it run):
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
# yum -y install systemtap
# stap-prep
# stap -v -g -e 'probe module("cifs").statement("cifs_show_devname@fs/cifs/cifsfs.c:480") { $devname[19] = 129; printf("new devname: %s\n", kernel_string_quoted($devname)); }'
...
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
The script replaces "ssXss" by "ssüss" once mount is done.
Corresponding source in kernel-4.18.0-425.10.1.el8_7.x86_64 (we are interested in hacking "devname" variable to report something not UTF8 in /proc/mounts):
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
475 static int cifs_show_devname(struct seq_file *m, struct dentry *root)
476 {
477 struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
478 char *devname = kstrdup(cifs_sb->ctx->source, GFP_KERNEL);
479
480 if (devname == NULL)
481 seq_puts(m, "none");
482 else {
483 convert_delimiter(devname, '/');
484 /* escape all spaces in share names */
485 seq_escape(m, devname, " \t");
486 kfree(devname);
487 }
488 return 0;
489 }
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
####################
REPRODUCING STEPS:
####################
1. Check there is some "subscribed" client in systemd (i.e. systemd-logind)
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
# gdb -ex "set pagination off" -ex "set confirm off" -ex "f 3" -ex "p m->subscribed" -ex "q" /usr/lib/systemd/systemd 1
[...]
#3 0x0000563e699efb62 in manager_loop (m=m@entry=0x563e6a06ae50) at ../src/core/manager.c:2898
2898 r = sd_event_run(m->event, wait_usec);
$1 = (sd_bus_track *) 0x563e6a238130
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
2. Start systemtap and let it run
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
# stap -v -g -e 'probe module("cifs").statement("cifs_show_devname@fs/cifs/cifsfs.c:480") { $devname[19] = 129; printf("new devname: %s\n", kernel_string_quoted($devname)); }'
...
Pass 5: starting run.
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
3. Mount the local CIFS share
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
# mount /mnt
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
Systemtap will report:
new devname: "//localhost/cifs/ss\201ss"
showing it's hacking the output as planned.
4. Login on the system as a new user (to trigger some dbus traffic AND new mounts due to the new user)
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
$ ssh admin@localhost true
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
5. Check systemd got disconnected from the bus (it has no "subscribed" clients anymore)
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
# gdb -ex "set pagination off" -ex "set confirm off" -ex "f 3" -ex "p m->subscribed" -ex "q" /usr/lib/systemd/systemd 1
...
#3 0x0000563e699efb62 in manager_loop (m=m@entry=0x563e6a06ae50) at ../src/core/manager.c:2898
2898 r = sd_event_run(m->event, wait_usec);
$1 = (sd_bus_track *) 0x0
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
At step 5 we see the leaks starts happening, sessions in /run/systemd/sessions are not destroyed anymore since systemd-logind doesn't receive notifications anymore:
# ssh admin@localhost true
# ssh admin@localhost true
# ssh admin@localhost true
# ll /run/systemd/sessions/
total 24
-rw-r--r-- 1 root root 322 Jan 20 15:49 1
-rw-r--r-- 1 root root 322 Jan 20 15:49 2
-rw-r--r-- 1 root root 306 Jan 20 15:54 5
-rw-r--r-- 1 root root 252 Jan 20 15:56 6
-rw-r--r-- 1 root root 252 Jan 20 15:56 7
-rw-r--r-- 1 root root 252 Jan 20 15:56 8
fix merged to github main branch -> https://github.com/redhat-plumbers/systemd-rhel8/pull/389 |