aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey A. Chernov <ache@FreeBSD.org>1996-06-21 18:49:36 +0000
committerAndrey A. Chernov <ache@FreeBSD.org>1996-06-21 18:49:36 +0000
commitb08645daa4984a393839399a4c856a6074e1b9bd (patch)
tree2389cef92471120e94064e44d881fb59318d4874
parent0e47b59f75e4d4056b1a34a5b7e71a92159177c1 (diff)
downloadsrc-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/Makefile2
-rw-r--r--gnu/usr.bin/man/man/man.c169
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;
}