Просмотр исходного кода

s-s-d: Cope with bogus OpenVZ kernels that prepend the " (deleted)" marker

There are OpenVZ Linux kernels that instead of appending, prepend the
deleted marker, making the exec check fail to match. Add a workaround
so that those systems do not get affected.

This will still be affecting any other userland tool that checks the
/proc/PID/exe symlink, and might end up helping this behaviour to get
entrenched, but better this than the getting strange system failures.

Closes: #731530
Guillem Jover лет назад: 12
Родитель
Сommit
b766dca911
2 измененных файлов с 15 добавлено и 4 удалено
  1. 3 0
      debian/changelog
  2. 12 4
      utils/start-stop-daemon.c

+ 3 - 0
debian/changelog

@@ -14,6 +14,9 @@ dpkg (1.17.10) UNRELEASED; urgency=low
   * Fix non-security sensitive TOCTOU race in update-alternative alternative
     database loading.
   * Fix non-security sensitive TOCTOU race in update-alternative rename code.
+  * Add a workaround to start-stop-daemon for bogus OpenVZ Linux kernels that
+    prepend, instead of appending, the " (deleted)" marker in /proc/PID/exe.
+    Closes: #731530
 
   [ Updated manpages translations ]
   * German (Helge Kreutzmann).

+ 12 - 4
utils/start-stop-daemon.c

@@ -1166,6 +1166,7 @@ pid_is_exec(pid_t pid, const struct stat *esb)
 {
 	char lname[32];
 	char lcontents[_POSIX_PATH_MAX + 1];
+	char *filename;
 	const char deleted[] = " (deleted)";
 	int nread;
 	struct stat sb;
@@ -1175,11 +1176,18 @@ pid_is_exec(pid_t pid, const struct stat *esb)
 	if (nread == -1)
 		return false;
 
-	lcontents[nread] = '\0';
-	if (strcmp(lcontents + nread - strlen(deleted), deleted) == 0)
-		lcontents[nread - strlen(deleted)] = '\0';
+	filename = lcontents;
+	filename[nread] = '\0';
 
-	if (stat(lcontents, &sb) != 0)
+	/* OpenVZ kernels contain a bogus patch that instead of appending,
+	 * prepends the deleted marker. Workaround those. Otherwise handle
+	 * the normal appended marker. */
+	if (strncmp(filename, deleted, strlen(deleted)) == 0)
+		filename += strlen(deleted);
+	else if (strcmp(filename + nread - strlen(deleted), deleted) == 0)
+		filename[nread - strlen(deleted)] = '\0';
+
+	if (stat(filename, &sb) != 0)
 		return false;
 
 	return (sb.st_dev == esb->st_dev && sb.st_ino == esb->st_ino);