Skip to content

Commit f41f0ee

Browse files
committed
Fix leak of dpkg cache when dpkginfo_init is called multiple times
In the dpkginfo probe, the dpkg cache was allocated in dpkginfo_init. However, dpkginfo_init can be called multiple times, leading the cgCache pointer to be overridden and leaking the dpkg cache. There are usually two dpkginfo probes running at the same time: CPE and OVAL. The opencache function is conditioned by the _init_done flag, however, this flag was never set, so opencache was always called. This change sets _init_done to 1 after opencache has been called, and allocate the dpkg cache only when _init_done is 0. Concurrent access to the cgCache static variable is now protected by a statically initialized mutex in dpkginfo_probe.c. We chose to keep cgCache as a static variable, because allocating cgCache for every thread has big performance impact. Also, calling new/delete revealed memory leaks in libapt. Consequently, cgCache is initialized once and never freed. The call to the cgCache->ReadOnlyOpen method is now done in the dpkginfo_get_by_name function, so the dpkg cache is always up to date. The cgCache->Close method is still called in dpkginfo_ini. This change also removes the unused dpkg_mmap static variable in dpkginfo-helper.cxx.
1 parent ed91feb commit f41f0ee

File tree

2 files changed

+13
-15
lines changed

2 files changed

+13
-15
lines changed

src/OVAL/probes/unix/linux/dpkginfo-helper.cxx

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ using namespace std;
2424
static int _init_done = 0;
2525
static pkgCacheFile *cgCache = NULL;
2626

27-
static MMap *dpkg_mmap = NULL;
28-
2927
static int opencache (void) {
3028
if (pkgInitConfig (*_config) == false) return 0;
3129

@@ -37,8 +35,6 @@ static int opencache (void) {
3735

3836
if (pkgInitSystem (*_config, _system) == false) return 0;
3937

40-
if (!cgCache->ReadOnlyOpen(NULL)) return 0;
41-
4238
if (_error->PendingError () == true) {
4339
_error->DumpErrors ();
4440
return 0;
@@ -53,6 +49,8 @@ struct dpkginfo_reply_t * dpkginfo_get_by_name(const char *name, int *err)
5349
pkgRecords Recs (cache);
5450
struct dpkginfo_reply_t *reply = NULL;
5551

52+
if (!cgCache->ReadOnlyOpen(NULL)) return 0;
53+
5654
// Locate the package
5755
pkgCache::PkgIterator Pkg = cache.FindPkg(name);
5856
if (Pkg.end() == true) {
@@ -127,11 +125,15 @@ void dpkginfo_free_reply(struct dpkginfo_reply_t *reply)
127125

128126
int dpkginfo_init()
129127
{
130-
cgCache = new pkgCacheFile;
131-
if (_init_done == 0)
128+
if (_init_done == 0) {
129+
cgCache = new pkgCacheFile;
132130
if (opencache() != 1) {
131+
delete cgCache;
132+
cgCache = NULL;
133133
return -1;
134134
}
135+
_init_done = 1;
136+
}
135137

136138
return 0;
137139
}
@@ -142,12 +144,6 @@ int dpkginfo_fini()
142144
cgCache->Close();
143145
}
144146

145-
delete cgCache;
146-
cgCache = NULL;
147-
148-
delete dpkg_mmap;
149-
dpkg_mmap = NULL;
150-
151147
return 0;
152148
}
153149

src/OVAL/probes/unix/linux/dpkginfo_probe.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ struct dpkginfo_global {
6969
};
7070

7171
static struct dpkginfo_global g_dpkg = {
72+
.mutex = PTHREAD_MUTEX_INITIALIZER,
7273
.init_done = -1,
7374
};
7475

@@ -78,9 +79,9 @@ int dpkginfo_probe_offline_mode_supported(void) {
7879

7980
void *dpkginfo_probe_init(void)
8081
{
81-
pthread_mutex_init (&(g_dpkg.mutex), NULL);
82-
82+
pthread_mutex_lock (&(g_dpkg.mutex));
8383
g_dpkg.init_done = dpkginfo_init();
84+
pthread_mutex_unlock (&(g_dpkg.mutex));
8485
if (g_dpkg.init_done < 0) {
8586
dE("dpkginfo_init has failed.");
8687
}
@@ -92,8 +93,9 @@ void dpkginfo_probe_fini (void *ptr)
9293
{
9394
struct dpkginfo_global *d = (struct dpkginfo_global *)ptr;
9495

96+
pthread_mutex_lock (&(d->mutex));
9597
dpkginfo_fini();
96-
pthread_mutex_destroy (&(d->mutex));
98+
pthread_mutex_unlock (&(d->mutex));
9799

98100
return;
99101
}

0 commit comments

Comments
 (0)