lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20171221152520.25867-2-vladislav.valtchev@gmail.com>
Date:   Thu, 21 Dec 2017 17:25:18 +0200
From:   "Vladislav Valtchev (VMware)" <vladislav.valtchev@...il.com>
To:     rostedt@...dmis.org
Cc:     y.karadz@...il.com, linux-trace-devel@...r.kernel.org,
        linux-kernel@...r.kernel.org,
        "Vladislav Valtchev (VMware)" <vladislav.valtchev@...il.com>
Subject: [PATCH v2 1/3] trace-cmd: Make read_proc() to return int status via OUT arg

This patch changes both the implementation and the interface of read_proc()
in trace-stack.c. First, it makes the function to read a string from the proc
file and then parse it as an integer using strtol(). Then, it makes the function
to return the integer read from the proc file using the int *status OUT
parameter, in order to make possible its return value to be used by the caller
to check if the operation succeeded.

This new implementation relaxes the external contraints the function relies on,
making it possible to be used by trace stat. The point is that 'stat' should not
fail in case there is something wrong with the stack tracer. Only the call to
die() in case the file is empty has been left in this patch: it will be removed
as well in a separate commit.

Signed-off-by: Vladislav Valtchev (VMware) <vladislav.valtchev@...il.com>
---
 trace-stack.c | 79 +++++++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 63 insertions(+), 16 deletions(-)

diff --git a/trace-stack.c b/trace-stack.c
index aa79ae3..c1058ca 100644
--- a/trace-stack.c
+++ b/trace-stack.c
@@ -20,6 +20,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <limits.h>
 #include <getopt.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -49,37 +50,79 @@ static void test_available(void)
 		die("stack tracer not configured on running kernel");
 }
 
-static char read_proc(void)
+/*
+ * Returns:
+ *   -1 - Something went wrong
+ *    0 - File does not exist (stack tracer not enabled)
+ *    1 - Success
+ */
+static int read_proc(int *status)
 {
-	char buf[1];
+	struct stat stat_buf;
+	char buf[64];
+	long num;
 	int fd;
 	int n;
 
+	if (stat(PROC_FILE, &stat_buf) < 0) {
+		/* stack tracer not configured on running kernel */
+		*status = 0; /* not configured means disabled */
+		return 0;
+	}
+
 	fd = open(PROC_FILE, O_RDONLY);
-	if (fd < 0)
-		die("reading %s", PROC_FILE);
-	n = read(fd, buf, 1);
-	close(fd);
-	if (n != 1)
+
+	if (fd < 0) {
+		/* we cannot open the file: likely a permission problem. */
+		return -1;
+	}
+
+	n = read(fd, buf, sizeof(buf));
+
+	/* We assume that the file is never empty we got no errors. */
+	if (n <= 0)
 		die("error reading %s", PROC_FILE);
 
-	return buf[0];
+	/* Does this file have more than 63 characters?? */
+	if (n >= sizeof(buf))
+		return -1;
+
+	/* n is guaranteed to be in the range [1, sizeof(buf)-1]. */
+	buf[n] = 0;
+	close(fd);
+
+	errno = 0;
+
+	/* Read an integer from buf ignoring any non-digit trailing characters. */
+	num = strtol(buf, NULL, 10);
+
+	/* strtol() returned 0: we have to check for errors */
+	if (!num && (errno == EINVAL || errno == ERANGE))
+		return -1;
+
+	if (num > INT_MAX || num < INT_MIN)
+		return -1; /* the number is good but does not fit in 'int' */
+
+	*status = num;
+	return 1; /* full success */
 }
 
-static void start_stop_trace(char val)
+/* NOTE: this implementation only accepts new_status in the range [0..9]. */
+static void change_stack_tracer_status(int new_status)
 {
 	char buf[1];
+	int status;
 	int fd;
 	int n;
 
-	buf[0] = read_proc();
-	if (buf[0] == val)
-		return;
+	if (read_proc(&status) > 0 && status == new_status)
+		return; /* nothing to do */
 
 	fd = open(PROC_FILE, O_WRONLY);
+
 	if (fd < 0)
 		die("writing %s", PROC_FILE);
-	buf[0] = val;
+	buf[0] = new_status + '0';
 	n = write(fd, buf, 1);
 	if (n < 0)
 		die("writing into %s", PROC_FILE);
@@ -88,12 +131,12 @@ static void start_stop_trace(char val)
 
 static void start_trace(void)
 {
-	start_stop_trace('1');
+	change_stack_tracer_status(1);
 }
 
 static void stop_trace(void)
 {
-	start_stop_trace('0');
+	change_stack_tracer_status(0);
 }
 
 static void reset_trace(void)
@@ -123,8 +166,12 @@ static void read_trace(void)
 	char *buf = NULL;
 	size_t n;
 	int r;
+	int status;
 
-	if (read_proc() == '1')
+	if (read_proc(&status) <= 0)
+		die("Invalid stack tracer state");
+
+	if (status > 0)
 		printf("(stack tracer running)\n");
 	else
 		printf("(stack tracer not running)\n");
-- 
2.14.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ