aboutsummaryrefslogtreecommitdiffstats
path: root/src/ftee
diff options
context:
space:
mode:
authorLibravatar netblue30 <netblue30@yahoo.com>2015-08-08 19:12:30 -0400
committerLibravatar netblue30 <netblue30@yahoo.com>2015-08-08 19:12:30 -0400
commit1379851360349d6617ad32944a25ee5e2bb74fc2 (patch)
treef69b48e90708bfa3c2723d5a27ed3e024c827b43 /src/ftee
parentdelete files (diff)
downloadfirejail-1379851360349d6617ad32944a25ee5e2bb74fc2.tar.gz
firejail-1379851360349d6617ad32944a25ee5e2bb74fc2.tar.zst
firejail-1379851360349d6617ad32944a25ee5e2bb74fc2.zip
Baseline firejail 0.9.28
Diffstat (limited to 'src/ftee')
-rw-r--r--src/ftee/Makefile.in24
-rw-r--r--src/ftee/ftee.h24
-rw-r--r--src/ftee/main.c228
3 files changed, 276 insertions, 0 deletions
diff --git a/src/ftee/Makefile.in b/src/ftee/Makefile.in
new file mode 100644
index 000000000..6911f0a3c
--- /dev/null
+++ b/src/ftee/Makefile.in
@@ -0,0 +1,24 @@
1all: ftee
2
3PREFIX=@prefix@
4VERSION=@PACKAGE_VERSION@
5NAME=@PACKAGE_NAME@
6
7H_FILE_LIST = $(wildcard *.[h])
8C_FILE_LIST = $(wildcard *.c)
9OBJS = $(C_FILE_LIST:.c=.o)
10BINOBJS = $(foreach file, $(OBJS), $file)
11CFLAGS += -ggdb -O2 -DVERSION='"$(VERSION)"' -DPREFIX='"$(PREFIX)"' -fstack-protector-all -D_FORTIFY_SOURCE=2 -fPIE -pie -Wformat -Wformat-security
12LDFLAGS += -pie -Wl,-z,relro -Wl,-z,now -lpthread
13
14%.o : %.c $(H_FILE_LIST)
15 $(CC) $(CFLAGS) $(INCLUDE) -c $< -o $@
16
17ftee: $(OBJS)
18 $(CC) $(LDFLAGS) -o $@ $(OBJS)
19
20clean:; rm -f *.o ftee
21
22distclean: clean
23 rm -fr Makefile
24
diff --git a/src/ftee/ftee.h b/src/ftee/ftee.h
new file mode 100644
index 000000000..a28cc5bb5
--- /dev/null
+++ b/src/ftee/ftee.h
@@ -0,0 +1,24 @@
1/*
2 * Copyright (C) 2014, 2015 netblue30 (netblue30@yahoo.com)
3 *
4 * This file is part of firejail project
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19*/
20#ifndef FTEE_H
21#define FTEE_H
22#include "../include/common.h"
23
24#endif \ No newline at end of file
diff --git a/src/ftee/main.c b/src/ftee/main.c
new file mode 100644
index 000000000..4dca3cf48
--- /dev/null
+++ b/src/ftee/main.c
@@ -0,0 +1,228 @@
1#include "ftee.h"
2#include <errno.h>
3#include <sys/types.h>
4#include <sys/stat.h>
5#include <unistd.h>
6#define MAXBUF 512
7
8static unsigned char buf[MAXBUF];
9
10static FILE *out_fp = NULL;
11static int out_cnt = 0;
12static int out_max = 500 * 1024;
13
14static void log_close(void) {
15 if (out_fp) {
16 fclose(out_fp);
17 out_fp = NULL;
18 }
19}
20
21static void log_rotate(const char *fname) {
22 struct stat s;
23 int index = strlen(fname);
24 char *name1 = malloc(index + 2 + 1);
25 char *name2 = malloc(index + 2 + 1);
26 if (!name1 || !name2)
27 errExit("malloc");
28 strcpy(name1, fname);
29 strcpy(name2, fname);
30 fflush(0);
31
32 // delete filename.5
33 sprintf(name1 + index, ".5");
34 if (stat(name1, &s) == 0) {
35 int rv = unlink(name1);
36 if (rv == -1)
37 perror("unlink");
38 }
39
40 // move files 1 to 4 down one position
41 sprintf(name2 + index, ".4");
42 if (stat(name2, &s) == 0) {
43 int rv = rename(name2, name1);
44 if (rv == -1)
45 perror("rename");
46 }
47
48 sprintf(name1 + index, ".3");
49 if (stat(name1, &s) == 0) {
50 int rv = rename(name1, name2);
51 if (rv == -1)
52 perror("rename");
53 }
54
55 sprintf(name2 + index, ".2");
56 if (stat(name2, &s) == 0) {
57 /* coverity[toctou] */
58 int rv = rename(name2, name1);
59 if (rv == -1)
60 perror("rename");
61 }
62
63 sprintf(name1 + index, ".1");
64 if (stat(name1, &s) == 0) {
65 int rv = rename(name1, name2);
66 if (rv == -1)
67 perror("rename");
68 }
69
70 // move the first file
71 if (out_fp)
72 fclose(out_fp);
73
74 out_fp = NULL;
75 if (stat(fname, &s) == 0) {
76 int rv = rename(fname, name1);
77 if (rv == -1)
78 perror("rename");
79 }
80
81 free(name1);
82 free(name2);
83}
84
85static void log_write(const unsigned char *str, int len, const char *fname) {
86 assert(fname);
87
88 if (out_fp == NULL) {
89 out_fp = fopen(fname, "w");
90 if (!out_fp) {
91 fprintf(stderr, "Error: cannot open log file %s\n", fname);
92 exit(1);
93 }
94 out_cnt = 0;
95 }
96
97 // rotate files
98 out_cnt += len;
99 if (out_cnt >= out_max) {
100 log_rotate(fname);
101
102 // reopen the first file
103 if (out_fp)
104 fclose(out_fp);
105 out_fp = fopen(fname, "w");
106 if (!out_fp) {
107 fprintf(stderr, "Error: cannot open log file %s\n", fname);
108 exit(1);
109 }
110 out_cnt = len;
111 }
112
113 fwrite(str, len, 1, out_fp);
114 fflush(0);
115}
116
117
118// return 1 if the file is a directory
119static int is_dir(const char *fname) {
120 assert(fname);
121 if (*fname == '\0')
122 return 0;
123
124 // if fname doesn't end in '/', add one
125 int rv;
126 struct stat s;
127 if (fname[strlen(fname) - 1] == '/')
128 rv = stat(fname, &s);
129 else {
130 char *tmp;
131 if (asprintf(&tmp, "%s/", fname) == -1) {
132 fprintf(stderr, "Error: cannot allocate memory, %s:%d\n", __FILE__, __LINE__);
133 exit(1);
134 }
135 rv = stat(tmp, &s);
136 free(tmp);
137 }
138
139 if (rv == -1)
140 return 0;
141
142 if (S_ISDIR(s.st_mode))
143 return 1;
144
145 return 0;
146}
147
148// return 1 if the file is a link
149static int is_link(const char *fname) {
150 assert(fname);
151 if (*fname == '\0')
152 return 0;
153
154 struct stat s;
155 if (lstat(fname, &s) == 0) {
156 if (S_ISLNK(s.st_mode))
157 return 1;
158 }
159
160 return 0;
161}
162
163
164
165
166
167static void usage(void) {
168 printf("Usage: ftee filename\n");
169}
170
171int main(int argc, char **argv) {
172 if (argc < 2) {
173 fprintf(stderr, "Error: please provide a filename to store the program output\n");
174 usage();
175 exit(1);
176 }
177 char *fname = argv[1];
178
179
180 // do not accept directories, links, and files with ".."
181 if (strstr(fname, "..") || is_link(fname) || is_dir(fname)) {
182 fprintf(stderr, "Error: invalid output file. Links, directories and files with \"..\" are not allowed.\n");
183 exit(1);
184 }
185
186 struct stat s;
187 if (stat(fname, &s) == 0) {
188 // check permissions
189 if (s.st_uid != getuid() || s.st_gid != getgid()) {
190 fprintf(stderr, "Error: the output file needs to be owned by the current user.\n");
191 exit(1);
192 }
193
194 // check hard links
195 if (s.st_nlink != 1) {
196 fprintf(stderr, "Error: no hard links allowed.\n");
197 exit(1);
198 }
199 }
200
201 // check if we can append to this file
202 /* coverity[toctou] */
203 FILE *fp = fopen(fname, "a");
204 if (!fp) {
205 fprintf(stderr, "Error: cannot open output file %s\n", fname);
206 exit(1);
207 }
208 fclose(fp);
209
210
211 // preserve the last log file
212 log_rotate(fname);
213
214 setvbuf (stdout, NULL, _IONBF, 0);
215 while(1) {
216 int n = read(0, buf, sizeof(buf));
217 if (n < 0 && errno == EINTR)
218 continue;
219 if (n <= 0)
220 break;
221
222 fwrite(buf, n, 1, stdout);
223 log_write(buf, n, fname);
224 }
225
226 log_close();
227 return 0;
228}