You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A colleague of mine did some performance measurements for using udev device tags, as they'd like to use them for a language to describe access control. During that we noticed that udevd crashes if you try to add a large number of tags:
for i in `seq 10000`; do printf 'KERNEL=="kmsg", TAG+="test%i"\n' $i; done > /run/udev/rules.d/70-manytags.rules
udevadm trigger --sysname-match=kmsg --verbose
Then udevd crashes with
worker [13738] terminated by signal 11 (Segmentation fault)
#0 0x00005555555f0fed in device_properties_prepare (device=0x555555683600) at src/libsystemd/sd-device/sd-device.c:1486
_appendees_ = {
0x7fffff801d80 ":test7679:test4364:test1143:test5855:test7318:test5305:test7786:test4511:test5674:test4140:test845:test2656:test1697:test3090:test4065:test2086:test8131:test4315:test5852:test1207:test81:test1387:test"..., 0x55555562642c ":",
0x555555674ab0 "test3837"}
_len_ = 12166
_i_ = 0
_d_ = 0x7fffff7fede0 <error: Cannot access memory at address 0x7fffff7fede0>
_p_ = 0x7fffff7fede0 <error: Cannot access memory at address 0x7fffff7fede0>
tags = 0x7fffff801d80 ":test7679:test4364:test1143:test5855:test7318:test5305:test7786:test4511:test5674:test4140:test845:test2656:test1697:test3090:test4065:test2086:test8131:test4315:test5852:test1207:test81:test1387:test"...
tag = 0x555555674ab0 "test3837"
r = 0
__PRETTY_FUNCTION__ = "device_properties_prepare"
This crashes in src/libsystemd/sd-device/sd-device.c, device_properties_prepare():
strjoina() (which essentially is alloca() with some automatic size determination) is very efficient with a few tags, but it has an undefined upper bound and undefined behaviour on stack overflow, i. e. there is no way to find out when it failed. In most cases of where systemd uses strjoina() the number of items is known exactly and small, but I don't think it's a good idea to use strjoina() in an unbounded loop like this as there's no safe way to determine overflows.
The text was updated successfully, but these errors were encountered:
strjoina() is unsafe to be used in an unbounded loop as alloca() has no error
reporting. Thus devices with a large number of tags trigger a segfault in
device_properties_prepare() due to overflowing the stack.
Rewrite the building of the "tags" string using greedy_realloc() and strpcpy()
to work with arbitrary many tags. This also avoids re-copying the entire string
in each loop iteration.
Before this commit we always appended one ":". Change this to start with an
iniital ":" and for each tag append instead of prepend a ":". This unifies what
happens for the first and all subsequent tags so that we can use a for loop.
Fixessystemd#2954
strjoina() is unsafe to be used in an unbounded loop as alloca() has no error
reporting. Thus devices with a large number of tags or devlinks trigger a
segfault in device_properties_prepare() due to overflowing the stack.
Rewrite the building of the "tags" and "devlinks" strings using
GREEDY_REALLOC() and strpcpy() to work with arbitrarily long strings. This also
avoids re-copying the entire string in each loop iteration.
Before this commit we always appended one final ":" to "tags". Change this to
start with an iniital ":" and for each tag append instead of prepend a ":".
This unifies what happens for the first and all subsequent tags so that we can
use a for loop.
Fixessystemd#2954
martinpitt
added a commit
to martinpitt/systemd
that referenced
this issue
Apr 5, 2016
strjoina() is unsafe to be used in an unbounded loop as alloca() has no error
reporting. Thus devices with a large number of tags or devlinks trigger a
segfault in device_properties_prepare() due to overflowing the stack.
Rewrite the building of the "tags" and "devlinks" strings using
GREEDY_REALLOC() and strpcpy() to work with arbitrarily long strings. This also
avoids re-copying the entire string in each loop iteration.
Before this commit we always appended one final ":" to "tags". Change this to
start with an iniital ":" and for each tag append instead of prepend a ":".
This unifies what happens for the first and all subsequent tags so that we can
use a for loop.
Fixessystemd#2954
Submission type
systemd version the issue has been seen with
229 and current master
Used distribution
Ubuntu, upstream master build (Downstream report: https://launchpad.net/bugs/1564976)
Steps to reproduce the problem
A colleague of mine did some performance measurements for using udev device tags, as they'd like to use them for a language to describe access control. During that we noticed that udevd crashes if you try to add a large number of tags:
Then udevd crashes with
This crashes in src/libsystemd/sd-device/sd-device.c, device_properties_prepare():
strjoina() (which essentially is alloca() with some automatic size determination) is very efficient with a few tags, but it has an undefined upper bound and undefined behaviour on stack overflow, i. e. there is no way to find out when it failed. In most cases of where systemd uses
strjoina()
the number of items is known exactly and small, but I don't think it's a good idea to usestrjoina()
in an unbounded loop like this as there's no safe way to determine overflows.The text was updated successfully, but these errors were encountered: