Bug#891477: udev: MemoryDenyWriteExecute breaks gzip on i386

Pascal Hambourg pascal at plouf.fr.eu.org
Sun Feb 25 22:22:06 GMT 2018


Package: udev
Version: 232-25+deb9u1

This a follow-up to bug #855798 "udev: MemoryDenyWriteExecute=yes should 
not be applied to udev plugins" which was closed because the affected 
program was not part of Debian. Now it seems that gzip is also affected 
by MemoryDenyWriteExecute=yes when run by udev on i386.

Context:
VT console events trigger a rule in 
/lib/udev/rules.d/90-console-setup.rules which runs 
/etc/console-setup/cached_setup_font.sh. This script runs setfont to set 
the configured console font. setfont calls gzip to uncompress the 
.psf.gz (cached_Lat15-Fixed16.psf.gz in my case) font file but gzip 
fails. So the console font is not set at boot time.

The following command triggers the error on i386:

systemd-run -t -p MemoryDenyWriteExecute=yes gzip -h

Error message:

error while loading shared libraries: cannot restore segment prot after 
reloc: Operation not permitted

strace:
======================================
execve("/bin/gzip", ["gzip", "-h"], [/* 4 vars */]) = 0
brk(NULL)                               = 0x9ac000
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or 
directory)
mmap2(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 
0) = 0xb7703000
access("/etc/ld.so.preload", R_OK)      = -1 ENOENT (No such file or 
directory)
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=14043, ...}) = 0
mmap2(NULL, 14043, PROT_READ, MAP_PRIVATE, 3, 0) = 0xb76ff000
close(3)                                = 0
access("/etc/ld.so.nohwcap", F_OK)      = -1 ENOENT (No such file or 
directory)
open("/lib/i386-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
read(3, 
"\177ELF\1\1\1\3\0\0\0\0\0\0\0\0\3\0\3\0\1\0\0\0\360\203\1\0004\0\0\0\334L\33\0\0\0\0\0004\0 
\0\n\0(\0E\0D\0\6\0\0\0004\0\0\0004\0\0\0004\0\0\0@\1\0\0@\1\0\0\5\0\0\0"..., 
512) = 512
fstat64(3, {st_mode=S_IFREG|0755, st_size=1791908, ...}) = 0
mmap2(NULL, 1800732, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 
0) = 0xb7547000
mprotect(0xb76f8000, 4096, PROT_NONE)   = 0
mmap2(0xb76f9000, 12288, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1b1000) = 0xb76f9000
mmap2(0xb76fc000, 10780, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0xb76fc000
close(3)                                = 0
set_thread_area({entry_number:-1, base_addr:0xb7705840, limit:1048575, 
seg_32bit:1, contents:0, read_exec_only:0, limit_in_pages:1, 
seg_not_present:0, useable:1}) = 0 (entry_number:6)
mprotect(0xb76f9000, 8192, PROT_READ)   = 0
mprotect(0x405000, 98304, PROT_READ|PROT_WRITE) = 0
mprotect(0x405000, 98304, PROT_READ|PROT_EXEC) = -1 EPERM (Operation not 
permitted)
writev(2, [{iov_base="gzip", iov_len=4}, {iov_base=": ", iov_len=2}, 
{iov_base="error while loading shared libraries", iov_len=36}, 
{iov_base=": ", iov_len=2}, {iov_base="", iov_len=0}, {iov_base="", 
iov_len=0}, {iov_base="cannot restore segment prot after reloc", 
iov_len=39}, {iov_base=": ", iov_len=2}, {iov_base="Operation not 
permitted", iov_len=23}, {iov_base="\n", iov_len=1}], 10) = 109
exit_group(127)                         = ?
+++ exited with 127 +++
======================================

One can see that mprotect is called with PROT_EXEC, which is prohibited 
by MemoryDenyWriteExecute and returns an error. The error message text 
is from /lib/ld-linux.so.2.

setfont/gzip works on i386 when run outside udev or when run from udev 
without MemoryDenyWriteExecute=yes in 
/lib/systemd/system/systemd-udevd.service.
It works on amd64 in any case.

Actually I am not sure whether this bug should be filed against udev or 
gzip. There might be other affected programs still unnoticed in Debian.



More information about the Pkg-systemd-maintainers mailing list