From 1379851360349d6617ad32944a25ee5e2bb74fc2 Mon Sep 17 00:00:00 2001 From: netblue30 Date: Sat, 8 Aug 2015 19:12:30 -0400 Subject: Baseline firejail 0.9.28 --- src/ftee/main.c | 228 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 228 insertions(+) create mode 100644 src/ftee/main.c (limited to 'src/ftee/main.c') 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 @@ +#include "ftee.h" +#include +#include +#include +#include +#define MAXBUF 512 + +static unsigned char buf[MAXBUF]; + +static FILE *out_fp = NULL; +static int out_cnt = 0; +static int out_max = 500 * 1024; + +static void log_close(void) { + if (out_fp) { + fclose(out_fp); + out_fp = NULL; + } +} + +static void log_rotate(const char *fname) { + struct stat s; + int index = strlen(fname); + char *name1 = malloc(index + 2 + 1); + char *name2 = malloc(index + 2 + 1); + if (!name1 || !name2) + errExit("malloc"); + strcpy(name1, fname); + strcpy(name2, fname); + fflush(0); + + // delete filename.5 + sprintf(name1 + index, ".5"); + if (stat(name1, &s) == 0) { + int rv = unlink(name1); + if (rv == -1) + perror("unlink"); + } + + // move files 1 to 4 down one position + sprintf(name2 + index, ".4"); + if (stat(name2, &s) == 0) { + int rv = rename(name2, name1); + if (rv == -1) + perror("rename"); + } + + sprintf(name1 + index, ".3"); + if (stat(name1, &s) == 0) { + int rv = rename(name1, name2); + if (rv == -1) + perror("rename"); + } + + sprintf(name2 + index, ".2"); + if (stat(name2, &s) == 0) { + /* coverity[toctou] */ + int rv = rename(name2, name1); + if (rv == -1) + perror("rename"); + } + + sprintf(name1 + index, ".1"); + if (stat(name1, &s) == 0) { + int rv = rename(name1, name2); + if (rv == -1) + perror("rename"); + } + + // move the first file + if (out_fp) + fclose(out_fp); + + out_fp = NULL; + if (stat(fname, &s) == 0) { + int rv = rename(fname, name1); + if (rv == -1) + perror("rename"); + } + + free(name1); + free(name2); +} + +static void log_write(const unsigned char *str, int len, const char *fname) { + assert(fname); + + if (out_fp == NULL) { + out_fp = fopen(fname, "w"); + if (!out_fp) { + fprintf(stderr, "Error: cannot open log file %s\n", fname); + exit(1); + } + out_cnt = 0; + } + + // rotate files + out_cnt += len; + if (out_cnt >= out_max) { + log_rotate(fname); + + // reopen the first file + if (out_fp) + fclose(out_fp); + out_fp = fopen(fname, "w"); + if (!out_fp) { + fprintf(stderr, "Error: cannot open log file %s\n", fname); + exit(1); + } + out_cnt = len; + } + + fwrite(str, len, 1, out_fp); + fflush(0); +} + + +// return 1 if the file is a directory +static int is_dir(const char *fname) { + assert(fname); + if (*fname == '\0') + return 0; + + // if fname doesn't end in '/', add one + int rv; + struct stat s; + if (fname[strlen(fname) - 1] == '/') + rv = stat(fname, &s); + else { + char *tmp; + if (asprintf(&tmp, "%s/", fname) == -1) { + fprintf(stderr, "Error: cannot allocate memory, %s:%d\n", __FILE__, __LINE__); + exit(1); + } + rv = stat(tmp, &s); + free(tmp); + } + + if (rv == -1) + return 0; + + if (S_ISDIR(s.st_mode)) + return 1; + + return 0; +} + +// return 1 if the file is a link +static int is_link(const char *fname) { + assert(fname); + if (*fname == '\0') + return 0; + + struct stat s; + if (lstat(fname, &s) == 0) { + if (S_ISLNK(s.st_mode)) + return 1; + } + + return 0; +} + + + + + +static void usage(void) { + printf("Usage: ftee filename\n"); +} + +int main(int argc, char **argv) { + if (argc < 2) { + fprintf(stderr, "Error: please provide a filename to store the program output\n"); + usage(); + exit(1); + } + char *fname = argv[1]; + + + // do not accept directories, links, and files with ".." + if (strstr(fname, "..") || is_link(fname) || is_dir(fname)) { + fprintf(stderr, "Error: invalid output file. Links, directories and files with \"..\" are not allowed.\n"); + exit(1); + } + + struct stat s; + if (stat(fname, &s) == 0) { + // check permissions + if (s.st_uid != getuid() || s.st_gid != getgid()) { + fprintf(stderr, "Error: the output file needs to be owned by the current user.\n"); + exit(1); + } + + // check hard links + if (s.st_nlink != 1) { + fprintf(stderr, "Error: no hard links allowed.\n"); + exit(1); + } + } + + // check if we can append to this file + /* coverity[toctou] */ + FILE *fp = fopen(fname, "a"); + if (!fp) { + fprintf(stderr, "Error: cannot open output file %s\n", fname); + exit(1); + } + fclose(fp); + + + // preserve the last log file + log_rotate(fname); + + setvbuf (stdout, NULL, _IONBF, 0); + while(1) { + int n = read(0, buf, sizeof(buf)); + if (n < 0 && errno == EINTR) + continue; + if (n <= 0) + break; + + fwrite(buf, n, 1, stdout); + log_write(buf, n, fname); + } + + log_close(); + return 0; +} -- cgit v1.2.3-54-g00ecf