tail: fix the checks if the file was rotated

The freopen(3) was replaced with fileargs_open(3) and fclose(3).
In the following function, we skip if the stream is standard in, so it is
safe to do so.
This also requires us to change the logic first to open the file and then
check its status. The stat(2) is disallowed in capability mode.

This commit unbrakes the -F option.
The bug was introduced in the r348708.

Reported by:	pho
Tested by:	pho
This commit is contained in:
Mariusz Zaborski 2019-06-09 22:55:21 +00:00
parent 39d51a9400
commit c851fce6d7
6 changed files with 31 additions and 11 deletions

View File

@ -78,3 +78,4 @@ int maparound(struct mapinfo *, off_t);
void printfn(const char *, int); void printfn(const char *, int);
extern int Fflag, fflag, qflag, rflag, rval, no_files; extern int Fflag, fflag, qflag, rflag, rval, no_files;
extern fileargs_t *fa;

View File

@ -57,6 +57,9 @@ static const char sccsid[] = "@(#)forward.c 8.1 (Berkeley) 6/6/93";
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <libcasper.h>
#include <casper/cap_fileargs.h>
#include "extern.h" #include "extern.h"
static void rlines(FILE *, const char *fn, off_t, struct stat *); static void rlines(FILE *, const char *fn, off_t, struct stat *);
@ -310,6 +313,7 @@ follow(file_info_t *files, enum STYLE style, off_t off)
int active, ev_change, i, n = -1; int active, ev_change, i, n = -1;
struct stat sb2; struct stat sb2;
file_info_t *file; file_info_t *file;
FILE *ftmp;
struct timespec ts; struct timespec ts;
/* Position each of the files */ /* Position each of the files */
@ -346,7 +350,9 @@ follow(file_info_t *files, enum STYLE style, off_t off)
if (Fflag) { if (Fflag) {
for (i = 0, file = files; i < no_files; i++, file++) { for (i = 0, file = files; i < no_files; i++, file++) {
if (!file->fp) { if (!file->fp) {
file->fp = fopen(file->file_name, "r"); file->fp =
fileargs_fopen(fa, file->file_name,
"r");
if (file->fp != NULL && if (file->fp != NULL &&
fstat(fileno(file->fp), &file->st) fstat(fileno(file->fp), &file->st)
== -1) { == -1) {
@ -359,7 +365,9 @@ follow(file_info_t *files, enum STYLE style, off_t off)
} }
if (fileno(file->fp) == STDIN_FILENO) if (fileno(file->fp) == STDIN_FILENO)
continue; continue;
if (stat(file->file_name, &sb2) == -1) { ftmp = fileargs_fopen(fa, file->file_name, "r");
if (ftmp == NULL ||
fstat(fileno(file->fp), &sb2) == -1) {
if (errno != ENOENT) if (errno != ENOENT)
ierr(file->file_name); ierr(file->file_name);
show(file); show(file);
@ -367,6 +375,9 @@ follow(file_info_t *files, enum STYLE style, off_t off)
fclose(file->fp); fclose(file->fp);
file->fp = NULL; file->fp = NULL;
} }
if (ftmp != NULL) {
fclose(ftmp);
}
ev_change++; ev_change++;
continue; continue;
} }
@ -375,14 +386,13 @@ follow(file_info_t *files, enum STYLE style, off_t off)
sb2.st_dev != file->st.st_dev || sb2.st_dev != file->st.st_dev ||
sb2.st_nlink == 0) { sb2.st_nlink == 0) {
show(file); show(file);
file->fp = freopen(file->file_name, "r", fclose(file->fp);
file->fp); file->fp = ftmp;
if (file->fp != NULL) memcpy(&file->st, &sb2,
memcpy(&file->st, &sb2, sizeof(struct stat));
sizeof(struct stat));
else if (errno != ENOENT)
ierr(file->file_name);
ev_change++; ev_change++;
} else {
fclose(ftmp);
} }
} }
} }

View File

@ -51,6 +51,9 @@ static const char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 6/6/93";
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <libcasper.h>
#include <casper/cap_fileargs.h>
#include "extern.h" #include "extern.h"
void void

View File

@ -51,6 +51,9 @@ static const char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/6/93";
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <libcasper.h>
#include <casper/cap_fileargs.h>
#include "extern.h" #include "extern.h"
/* /*

View File

@ -55,6 +55,9 @@ __FBSDID("$FreeBSD$");
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
#include <libcasper.h>
#include <casper/cap_fileargs.h>
#include "extern.h" #include "extern.h"
static void r_buf(FILE *, const char *); static void r_buf(FILE *, const char *);

View File

@ -65,6 +65,7 @@ static const char sccsid[] = "@(#)tail.c 8.1 (Berkeley) 6/6/93";
#include "extern.h" #include "extern.h"
int Fflag, fflag, qflag, rflag, rval, no_files; int Fflag, fflag, qflag, rflag, rval, no_files;
fileargs_t *fa;
static file_info_t *files; static file_info_t *files;
@ -90,10 +91,9 @@ main(int argc, char *argv[])
int i, ch, first; int i, ch, first;
file_info_t *file; file_info_t *file;
char *p; char *p;
fileargs_t *fa;
cap_rights_t rights; cap_rights_t rights;
cap_rights_init(&rights, CAP_FSTAT, CAP_FCNTL, CAP_MMAP_RW); cap_rights_init(&rights, CAP_FSTAT, CAP_FSTATFS, CAP_FCNTL, CAP_MMAP_RW);
if (caph_rights_limit(STDIN_FILENO, &rights) < 0 || if (caph_rights_limit(STDIN_FILENO, &rights) < 0 ||
caph_limit_stderr() < 0 || caph_limit_stdout() < 0) caph_limit_stderr() < 0 || caph_limit_stdout() < 0)
err(1, "can't limit stdio rights"); err(1, "can't limit stdio rights");