• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 19979552133

05 Dec 2025 05:29PM UTC coverage: 72.765% (-0.2%) from 72.917%
19979552133

push

github

yuwata
udev-rules: use the right variable

We carefully prepare a copy of a local buffer to save in device cache
and then save the buffer there instead... This leads to abort in free()
on exit (also, copied is leaked).

Reproducer:
 # udevadm test /sys/block/sr0

Follow-up-for: a9559ebcb

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=2406118

0 of 1 new or added line in 1 file covered. (0.0%)

1564 existing lines in 65 files now uncovered.

309707 of 425625 relevant lines covered (72.77%)

1149816.14 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.06
/src/basic/dlfcn-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include "dlfcn-util.h"
4
#include "errno-util.h"
5
#include "log.h"
6

7
void* safe_dlclose(void *dl) {
144,248✔
8
        if (!dl)
144,248✔
9
                return NULL;
10

11
        assert_se(dlclose(dl) == 0);
19,105✔
12
        return NULL;
13
}
14

15
static int dlsym_many_or_warnv(void *dl, int log_level, va_list ap) {
64,532✔
16
        void (**fn)(void);
64,532✔
17

18
        /* Tries to resolve a bunch of function symbols, and logs an error about if it cannot resolve one of
19
         * them. Note that this function possibly modifies the supplied function pointers if the whole
20
         * operation fails. */
21

22
        while ((fn = va_arg(ap, typeof(fn)))) {
1,546,650✔
23
                void (*tfn)(void);
1,482,118✔
24
                const char *symbol;
1,482,118✔
25

26
                symbol = va_arg(ap, typeof(symbol));
1,482,118✔
27

28
                tfn = (typeof(tfn)) dlsym(dl, symbol);
1,482,118✔
29
                if (!tfn)
1,482,118✔
30
                        return log_full_errno(log_level,
×
31
                                              SYNTHETIC_ERRNO(ELIBBAD),
32
                                              "Can't find symbol %s: %s", symbol, dlerror());
33
                *fn = tfn;
1,482,118✔
34
        }
35

36
        return 0;
37
}
38

39
int dlsym_many_or_warn_sentinel(void *dl, int log_level, ...) {
22,506✔
40
        va_list ap;
22,506✔
41
        int r;
22,506✔
42

43
        va_start(ap, log_level);
22,506✔
44
        r = dlsym_many_or_warnv(dl, log_level, ap);
22,506✔
45
        va_end(ap);
22,506✔
46

47
        return r;
22,506✔
48
}
49

50
int dlopen_many_sym_or_warn_sentinel(void **dlp, const char *filename, int log_level, ...) {
6,162,495✔
51
        int r;
6,162,495✔
52

53
        if (*dlp)
6,162,495✔
54
                return 0; /* Already loaded */
6,162,495✔
55

56
        _cleanup_(dlclosep) void *dl = NULL;
6,162,495✔
57
        const char *dle = NULL;
42,095✔
58
        r = dlopen_safe(filename, &dl, &dle);
42,095✔
59
        if (r < 0) {
42,095✔
60
                log_debug_errno(r, "Shared library '%s' is not available: %s", filename, dle ?: STRERROR(r));
69✔
61
                return -EOPNOTSUPP; /* Turn into recognizable error */
69✔
62
        }
63

64
        log_debug("Loaded shared library '%s' via dlopen().", filename);
42,026✔
65

66
        va_list ap;
42,026✔
67
        va_start(ap, log_level);
42,026✔
68
        r = dlsym_many_or_warnv(dl, log_level, ap);
42,026✔
69
        va_end(ap);
42,026✔
70

71
        if (r < 0)
42,026✔
72
                return r;
73

74
        /* Note that we never release the reference here, because there's no real reason to. After all this
75
         * was traditionally a regular shared library dependency which lives forever too. */
76
        *dlp = TAKE_PTR(dl);
42,026✔
77
        return 1;
42,026✔
78
}
79

80
static bool dlopen_blocked = false;
81

82
void block_dlopen(void) {
40,738✔
83
        dlopen_blocked = true;
40,738✔
84
}
40,738✔
85

86
int dlopen_safe(const char *filename, void **ret, const char **reterr_dlerror) {
72,124✔
87
        _cleanup_(dlclosep) void *dl = NULL;
72,124✔
88
        int r;
72,124✔
89

90
        assert(filename);
72,124✔
91

92
        /* A wrapper around dlopen(), that takes dlopen_blocked into account, and tries to normalize the
93
         * error reporting a bit. */
94

95
        int flags = RTLD_NOW|RTLD_NODELETE; /* Always set RTLD_NOW + RTLD_NODELETE, for security reasons */
72,124✔
96

97
        /* If dlopen() is blocked we'll still try it, but set RTLD_NOLOAD, so that it will still work if
98
         * already loaded (for example because the binary linked to things regularly), but fail if not. */
99
        if (dlopen_blocked)
72,124✔
100
                flags |= RTLD_NOLOAD;
79✔
101

102
        errno = 0;
72,124✔
103
        dl = dlopen(filename, flags);
72,124✔
104
        if (!dl) {
72,124✔
105
                if (dlopen_blocked) {
91✔
UNCOV
106
                        (void) dlerror(); /* consume error, so that no later call will return it */
×
107

UNCOV
108
                        if (reterr_dlerror)
×
UNCOV
109
                                *reterr_dlerror = NULL;
×
110

UNCOV
111
                        return log_debug_errno(SYNTHETIC_ERRNO(EPERM), "Refusing loading of '%s', as loading further dlopen() modules has been blocked.", filename);
×
112
                }
113

114
                r = errno_or_else(ENOPKG);
91✔
115

116
                if (reterr_dlerror)
91✔
117
                        *reterr_dlerror = dlerror();
80✔
118
                else
119
                        (void) dlerror(); /* consume error, so that no later call will return it */
11✔
120

121
                return r;
91✔
122
        }
123

124
        if (ret)
72,033✔
125
                *ret = TAKE_PTR(dl);
72,033✔
126

127
        return 0;
128
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc