diff options
author | Andrey A. Chernov <ache@FreeBSD.org> | 1996-06-21 18:49:36 +0000 |
---|---|---|
committer | Andrey A. Chernov <ache@FreeBSD.org> | 1996-06-21 18:49:36 +0000 |
commit | b08645daa4984a393839399a4c856a6074e1b9bd (patch) | |
tree | 2389cef92471120e94064e44d881fb59318d4874 | |
parent | 0e47b59f75e4d4056b1a34a5b7e71a92159177c1 (diff) | |
download | src-b08645daa4984a393839399a4c856a6074e1b9bd.tar.gz src-b08645daa4984a393839399a4c856a6074e1b9bd.zip |
Close security holes and restore suid bit
Restore writting cat's functionality
Notes
Notes:
svn path=/head/; revision=16573
-rw-r--r-- | gnu/usr.bin/man/man/Makefile | 2 | ||||
-rw-r--r-- | gnu/usr.bin/man/man/man.c | 169 |
2 files changed, 125 insertions, 46 deletions
diff --git a/gnu/usr.bin/man/man/Makefile b/gnu/usr.bin/man/man/Makefile index 1807455e219d..3c835255b453 100644 --- a/gnu/usr.bin/man/man/Makefile +++ b/gnu/usr.bin/man/man/Makefile @@ -1,5 +1,7 @@ PROG= man SRCS= man.c manpath.c glob.c +BINOWN= man +BINMODE=4555 .if exists(${.CURDIR}/../lib/obj) LDADD= -L${.CURDIR}/../lib/obj -lman diff --git a/gnu/usr.bin/man/man/man.c b/gnu/usr.bin/man/man/man.c index 1bce5e9a62b5..7403534ce02b 100644 --- a/gnu/usr.bin/man/man/man.c +++ b/gnu/usr.bin/man/man/man.c @@ -19,6 +19,7 @@ #include <sys/types.h> #include <stdio.h> #include <ctype.h> +#include <errno.h> #include <string.h> #include <sys/file.h> #include <signal.h> @@ -131,6 +132,7 @@ main (argc, argv) prognam = mkprogname (argv[0]); + unsetenv("IFS"); man_getopt (argc, argv); if (optind == argc) @@ -981,7 +983,7 @@ make_roff_command (file) fprintf (stderr, "using default preprocessor sequence\n"); if ((cp = get_expander(file)) == NULL) - cp = "cat"; + cp = "/bin/cat"; sprintf(buf, "%s %s | ", cp, file); #ifdef HAS_TROFF if (troff) @@ -1020,6 +1022,33 @@ make_roff_command (file) return buf; } +sig_t ohup, oint, oquit, oterm; +static char temp[FILENAME_MAX]; + +void cleantmp() +{ + unlink(temp); + exit(1); +} + +void +set_sigs() +{ + ohup = signal(SIGHUP, cleantmp); + oint = signal(SIGINT, cleantmp); + oquit = signal(SIGQUIT, cleantmp); + oterm = signal(SIGTERM, cleantmp); +} + +void +restore_sigs() +{ + signal(SIGHUP, ohup); + signal(SIGINT, oint); + signal(SIGQUIT, oquit); + signal(SIGTERM, oterm); +} + /* * Try to format the man page and create a new formatted file. Return * 1 for success and 0 for failure. @@ -1030,73 +1059,121 @@ make_cat_file (path, man_file, cat_file) register char *man_file; register char *cat_file; { - int status; - int mode; - FILE *fp; + int s, f; + FILE *fp, *pp; char *roff_command; char command[FILENAME_MAX]; - char temp[FILENAME_MAX]; - sprintf(temp, "%s.tmp", cat_file); - if ((fp = fopen (temp, "w")) != NULL) + roff_command = make_roff_command (man_file); + if (roff_command == NULL) + return 0; + + sprintf(temp, "%s.tmpXXXXXX", cat_file); + if ((f = mkstemp(temp)) >= 0 && (fp = fdopen(f, "w")) != NULL) { - fclose (fp); - unlink (temp); + set_sigs(); - roff_command = make_roff_command (man_file); - if (roff_command == NULL) + if (fchmod (f, CATMODE) < 0) { + perror("fchmod"); + unlink(temp); + restore_sigs(); + fclose(fp); return 0; - else + } else if (debug) + fprintf (stderr, "mode of %s is now %o\n", temp, CATMODE); + #ifdef DO_COMPRESS - sprintf (command, "(cd %s ; %s | %s > %s)", path, - roff_command, COMPRESSOR, temp); + sprintf (command, "(cd %s ; %s | %s)", path, + roff_command, COMPRESSOR); #else - sprintf (command, "(cd %s ; %s > %s)", path, - roff_command, temp); + sprintf (command, "(cd %s ; %s)", path, + roff_command); #endif - /* - * Don't let the user interrupt the system () call and screw up - * the formatted man page if we're not done yet. - */ fprintf (stderr, "Formatting page, please wait..."); fflush(stderr); - status = do_system_command (command); - - if (status <= 0) { - fprintf(stderr, "Failed.\n"); - unlink(temp); - return(0); - } + if (debug) + fprintf (stderr, "\ntrying command: %s\n", command); else { - if (rename(temp, cat_file) == -1) { - /* FS might be sticky */ - sprintf(command, "cp %s %s", temp, cat_file); - if (system(command)) - fprintf(stderr, - "\nHmm! Can't seem to rename %s to %s, check permissions on man dir!\n", - temp, cat_file); - unlink(temp); - return 0; + + if ((pp = popen(command, "r")) == NULL) { + s = errno; + fprintf(stderr, "Failed.\n"); + errno = s; + perror("popen"); + unlink(temp); + restore_sigs(); + fclose(fp); + return 0; } - } - fprintf(stderr, "Done.\n"); - if (status == 1) - { - mode = CATMODE; - chmod (cat_file, mode); - if (debug) - fprintf (stderr, "mode of %s is now %o\n", cat_file, mode); + while ((s = getc(pp)) != EOF) + putc(s, fp); + + if ((s = pclose(pp)) == -1) { + s = errno; + fprintf(stderr, "Failed.\n"); + errno = s; + perror("pclose"); + unlink(temp); + restore_sigs(); + fclose(fp); + return 0; } + if (s != 0) { + fprintf(stderr, "Failed.\n"); + gripe_system_command(s); + unlink(temp); + restore_sigs(); + fclose(fp); + return 0; + } + } + + if (rename(temp, cat_file) == -1) { + s = errno; + fprintf(stderr, + "\nHmm! Can't seem to rename %s to %s, check permissions on man dir!\n", + temp, cat_file); + errno = s; + perror("rename"); + unlink(temp); + restore_sigs(); + fclose(fp); + return 0; + } + restore_sigs(); + + if (fclose(fp)) { + s = errno; + unlink(cat_file); + fprintf(stderr, "Failed.\n"); + errno = s; + perror("fclose"); + return 0; + } + + fprintf(stderr, "Done.\n"); return 1; } else { - if (debug) - fprintf (stderr, "Couldn't open %s for writing.\n", cat_file); + if (f >= 0) { + s = errno; + unlink(temp); + errno = s; + } + if (debug) { + s = errno; + fprintf (stderr, "Couldn't open %s for writing.\n", temp); + errno = s; + } + if (f >= 0) { + perror("fdopen"); + close(f); + } return 0; } |