summaryrefslogtreecommitdiff
path: root/security/sudosh3/files/patch-src::replay.c
blob: 286a1d20d1c54072df7e542a79cd59031e1c41d1 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
Address the buffer-overflow problem outlined here:
	http://packetstormsecurity.com/files/85687/sa38292.txt
(buffer is of size BUFSIZ, but the check is for 8Mb, which may not be the
same) by not using a buffer at all. Instead we simply mmap the script-file.

The patch also adds closing of the script file at the end and fixes some
compiler warnings (the the -Wall -W levels).

On 32-bit architectures this limits the replayable script-size to 4Gb.

	-mi
--- src/replay.c	2009-11-24 09:54:58.000000000 -0500
+++ src/replay.c	2013-02-12 15:51:31.000000000 -0500
@@ -19,4 +19,6 @@
 #include "super.h"
 #include "struct.h"
+#include <sys/mman.h>
+#include <stdint.h>
 
 #define LL() fprintf(stderr, "[%s, line %i]: ", __FILE__, __LINE__)
@@ -71,5 +73,5 @@
 void show_sessions(void);
 
-int main(int argc, char **argv, char **environ)
+int main(int argc, char *argv[])
 {
 	int c;
@@ -406,14 +408,15 @@
 void replay(const char *time, const char *script, int div, int maxwait)
 {
-	char read_buffer[BUFSIZ];
+	char *read_buffer;
 	char timebuf[BUFSIZ];
 	float ftime = 0;
 	int b = 0;
 	int bInput = 0;
-	int r = 0;
 	int sec, usec;
 	char buffer[BUFSIZ];
 	struct s_file s_time;
 	struct s_file s_script;
+	struct stat sb;
+	off_t offset;
 	struct timeval tv;
 
@@ -432,9 +435,13 @@
 	}
 
-	if ((s_script.fd = open(script, O_RDONLY)) == -1) {
+	if ((s_script.fd = open(script, O_RDONLY)) == -1 ||
+	    fstat(s_script.fd, &sb) ||
+	    (read_buffer = mmap(NULL, sb.st_size, PROT_READ, MAP_NOCORE|MAP_SHARED, s_script.fd, 0))
+	    == MAP_FAILED) {
 		LL();
 		fprintf(stderr, "%s: %s: %s (%i)\n", progname, script, strerror(errno), errno);
 		exit(EXIT_FAILURE);
 	}
+	offset = 0;
 
 	for (s_time.line = 1; fgets(buffer, BUFSIZ - 1, s_time.f); s_time.line++) {
@@ -478,29 +485,22 @@
 		tv.tv_usec = (time_t) usec;
 
-		if (b > 1024 * 1024 * 8) {	/* 8MB */
+		if (b > sb.st_size - offset) {	/* 8MB */
 			LL();
-			fprintf(stderr, "[error]: line %i: wanted to read %i bytes, but the limit is 8MB.\n", s_time.line, b);
-			exit(EXIT_FAILURE);
-		}
-
-		memset(read_buffer, '\0', BUFSIZ);
-		r = read(s_script.fd, read_buffer, (size_t) b);
-
-		if (r != b) {
-			LL();
-			fprintf(stderr, "[failure]: read %i bytes out of %i.\n", r, b);
+			fprintf(stderr, "[error]: line %i: wanted to read %i bytes, but only %jd are "
+			    "left in %s.\n", s_time.line, b, (intmax_t)sb.st_size - offset, script);
 			exit(EXIT_FAILURE);
 		}
 
 		select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &tv);
-		fputs(read_buffer, stdout);
+		fwrite(read_buffer + offset, 1, b, stdout); /* Should we check for error here? XXX */
+		offset += b;
 		fflush(stdout);
-		memset(read_buffer, '\0', BUFSIZ);
 	}
+	munmap(read_buffer, sb.st_size);
+	close(s_script.fd);
 	fprintf(stderr, "[info]: EOF\n");
 	fflush(stderr);
 }
 
-
 session *session_malloc(void)
 {
@@ -586,5 +586,5 @@
 session *sort_list(session * list)
 {
-	session *p, *q, *e, *tail, *oldhead;
+	session *p, *q, *e, *tail;
 	int insize, nmerges, psize, qsize, i;
 
@@ -597,5 +597,4 @@
 
 		p = list;
-		oldhead = list;
 		list = (session *) 0;
 		tail = (session *) 0;