[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Bug#779467: dpkg: start-stop-daemon sometimes exits with "_cpu_tick_frequency: no such symbol" on kFreeBSD



Thank you for the speedy reply!

Unfortunately, with your patch, start-stop-daemon crashes.
With valgrind (kfreebsd patches in stalled bug
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=702729) the site of
the crash is spelled out:

Invalid read of size 4
   at 0x40221B: do_findprocs (start-stop-daemon.c:1796)
   by 0x402264: do_stop (start-stop-daemon.c:1932)
   by 0x4037B3: main (start-stop-daemon.c:2117)
 Address 0x1b91e28 is 1,160 bytes inside a block of size 1,080,710 free'd
   at 0x100D1BC: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-freebsd.so)
   by 0x12176BE: kvm_getprocs (in /lib/libkvm.so.6)
   by 0x401EA4: ssd_kvm_get_procs (start-stop-daemon.c:1273)
   by 0x402085: pid_check (start-stop-daemon.c:1610)
   by 0x402224: do_findprocs (start-stop-daemon.c:1796)
   by 0x402264: do_stop (start-stop-daemon.c:1932)
   by 0x4037B3: main (start-stop-daemon.c:2117)

.. it appears that each call to ssd_kvm_get_procs(kd) frees the result of a
previous call to ssd_kvm_get_procs(kd).  Before your patch, the kd in
each call was distinct; but now it is the same.  The manpage for
kvm_getprocs has this to say:
     The memory allocated to the argv pointers and string storage is owned by
     the kvm library.  Subsequent kvm_getprocs() and kvm_close(3) calls will
     clobber this storage.
which seems to be exactly what is going on.  Boo.

If you feel that a patch that doesn't change program flow is
lower-impact, then this alternative does run for me.  It makes each
each function with a kvm_t local declare it as static.  It's the same
idea as your patch, but pushed up a level so that one function's call to
ssd_kvm_get_procs doesn't free the memory used in another function.

Jeff
diff -Nru dpkg-1.17.23/debian/changelog dpkg-1.17.23+local3/debian/changelog
--- dpkg-1.17.23/debian/changelog	2014-12-27 16:44:47.000000000 -0600
+++ dpkg-1.17.23+local3/debian/changelog	2015-03-01 19:43:18.000000000 -0600
@@ -1,3 +1,10 @@
+dpkg (1.17.23+local3) UNRELEASED; urgency=medium
+
+  * Non-maintainer upload.
+  * Avoid resource exhaustion by having one kvm_t per function using it.
+
+ -- Jeff Epler <jepler@unpythonic.net>  Sun, 01 Mar 2015 19:42:38 -0600
+
 dpkg (1.17.23) unstable; urgency=low
 
   [ Guillem Jover ]
diff -Nru dpkg-1.17.23/utils/start-stop-daemon.c dpkg-1.17.23+local3/utils/start-stop-daemon.c
--- dpkg-1.17.23/utils/start-stop-daemon.c	2014-12-13 16:07:23.000000000 -0600
+++ dpkg-1.17.23+local3/utils/start-stop-daemon.c	2015-03-01 19:42:19.000000000 -0600
@@ -1367,7 +1367,7 @@
 static bool
 pid_is_exec(pid_t pid, const struct stat *esb)
 {
-	kvm_t *kd;
+	static kvm_t *kd;
 	int argv_len = 0;
 	struct kinfo_proc *kp;
 	struct stat sb;
@@ -1375,7 +1375,7 @@
 	char **pid_argv_p;
 	char *start_argv_0_p, *end_argv_0_p;
 
-	kd = ssd_kvm_open();
+	if (!kd) kd = ssd_kvm_open();
 	kp = ssd_kvm_get_procs(kd, KERN_PROC_PID, pid, NULL);
 	if (kp == NULL)
 		return false;
@@ -1457,11 +1457,11 @@
 static bool
 pid_is_child(pid_t pid, pid_t ppid)
 {
-	kvm_t *kd;
+	static kvm_t *kd;
 	struct kinfo_proc *kp;
 	pid_t proc_ppid;
 
-	kd = ssd_kvm_open();
+	if (!kd) kd = ssd_kvm_open();
 	kp = ssd_kvm_get_procs(kd, KERN_PROC_PID, pid, NULL);
 	if (kp == NULL)
 		return false;
@@ -1515,11 +1515,11 @@
 static bool
 pid_is_user(pid_t pid, uid_t uid)
 {
-	kvm_t *kd;
+	static kvm_t *kd;
 	uid_t proc_uid;
 	struct kinfo_proc *kp;
 
-	kd = ssd_kvm_open();
+	if (!kd) kd = ssd_kvm_open();
 	kp = ssd_kvm_get_procs(kd, KERN_PROC_PID, pid, NULL);
 	if (kp == NULL)
 		return false;
@@ -1599,11 +1599,11 @@
 static bool
 pid_is_cmd(pid_t pid, const char *name)
 {
-	kvm_t *kd;
+	static kvm_t *kd;
 	struct kinfo_proc *kp;
 	char *process_name;
 
-	kd = ssd_kvm_open();
+	if (!kd) kd = ssd_kvm_open();
 	kp = ssd_kvm_get_procs(kd, KERN_PROC_PID, pid, NULL);
 	if (kp == NULL)
 		return false;
@@ -1768,12 +1768,12 @@
 static enum status_code
 do_procinit(void)
 {
-	kvm_t *kd;
+	static kvm_t *kd;
 	int nentries, i;
 	struct kinfo_proc *kp;
 	enum status_code prog_status = STATUS_DEAD;
 
-	kd = ssd_kvm_open();
+	if (!kd) kd = ssd_kvm_open();
 	kp = ssd_kvm_get_procs(kd, KERN_PROC_ALL, 0, &nentries);
 
 	for (i = 0; i < nentries; i++) {

Reply to: