Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

udevd crash with lots of tags #2954

Closed
1 of 2 tasks
martinpitt opened this issue Apr 4, 2016 · 0 comments
Closed
1 of 2 tasks

udevd crash with lots of tags #2954

martinpitt opened this issue Apr 4, 2016 · 0 comments
Assignees
Labels
bug 🐛 Programming errors, that need preferential fixing udev

Comments

@martinpitt
Copy link
Contributor

Submission type

  • Bug report
  • Request for enhancement (RFE)

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:

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():

                char *tags = NULL;
                while ((tag = sd_device_get_tag_next(device)))
                        tags = strjoina(tags, ":", tag);

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.

@martinpitt martinpitt added bug 🐛 Programming errors, that need preferential fixing udev labels Apr 4, 2016
@martinpitt martinpitt self-assigned this Apr 4, 2016
martinpitt added a commit to martinpitt/systemd that referenced this issue Apr 4, 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 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.

Fixes systemd#2954
martinpitt added a commit to martinpitt/systemd that referenced this issue Apr 4, 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.

Fixes systemd#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.

Fixes systemd#2954
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Programming errors, that need preferential fixing udev
Development

No branches or pull requests

1 participant