aboutsummaryrefslogtreecommitdiffstats
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;