summaryrefslogtreecommitdiffstats
path: root/libexec
diff options
context:
space:
mode:
authoryar <yar@FreeBSD.org>2002-01-28 19:28:14 +0000
committeryar <yar@FreeBSD.org>2002-01-28 19:28:14 +0000
commitdc82fedb5a0b52746bb2b4a6d1fef7b198f963af (patch)
treecc70648d56369afdd2a65f52ef411514cf29abda /libexec
parent494635a1dd3758290dafdc988884148b0a5894ea (diff)
downloadFreeBSD-src-dc82fedb5a0b52746bb2b4a6d1fef7b198f963af.zip
FreeBSD-src-dc82fedb5a0b52746bb2b4a6d1fef7b198f963af.tar.gz
Remove the setjmp/longjmp stuff completely. Use signal
handlers to set flags only (with exception for sigquit(), which still seems to call some non-reentrant functions on its way to _exit(2).) That must eliminate the possibility of catching SIGSEGV from following non-reentrant paths from signal handlers. PR: bin/32740 bin/33846 Submitted by: Maxim Konovalov <maxim@macomnet.ru> Obtained from: OpenBSD
Diffstat (limited to 'libexec')
-rw-r--r--libexec/ftpd/ftpcmd.y21
-rw-r--r--libexec/ftpd/ftpd.c117
2 files changed, 94 insertions, 44 deletions
diff --git a/libexec/ftpd/ftpcmd.y b/libexec/ftpd/ftpcmd.y
index 687e3a0..5928c02 100644
--- a/libexec/ftpd/ftpcmd.y
+++ b/libexec/ftpd/ftpcmd.y
@@ -60,7 +60,6 @@ static const char rcsid[] =
#include <glob.h>
#include <netdb.h>
#include <pwd.h>
-#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -101,6 +100,7 @@ off_t restart_point;
static int cmd_type;
static int cmd_form;
static int cmd_bytesz;
+static int state;
char cbuf[512];
char *fromname = (char *) 0;
@@ -750,9 +750,11 @@ cmd
reply(221, "Goodbye.");
dologout(0);
}
- | error CRLF
+ | error
{
- yyerrok;
+ yyclearin; /* discard lookahead data */
+ yyerrok; /* clear error condition */
+ state = 0; /* reset lexer state */
}
;
rcmd
@@ -1047,8 +1049,6 @@ check_login_ro
%%
-extern jmp_buf errcatch;
-
#define CMD 0 /* beginning of command */
#define ARGS 1 /* expect miscellaneous arguments */
#define STR1 2 /* expect SP followed by STRING */
@@ -1253,7 +1253,7 @@ toolong(signo)
static int
yylex()
{
- static int cpos, state;
+ static int cpos;
char *cp, *cp2;
struct tab *p;
int n;
@@ -1290,8 +1290,7 @@ yylex()
if (p != 0) {
if (p->implemented == 0) {
nack(p->name);
- longjmp(errcatch,0);
- /* NOTREACHED */
+ return (LEXERR);
}
state = p->state;
yylval.s = p->name;
@@ -1316,8 +1315,7 @@ yylex()
if (p->implemented == 0) {
state = CMD;
nack(p->name);
- longjmp(errcatch,0);
- /* NOTREACHED */
+ return (LEXERR);
}
state = p->state;
yylval.s = p->name;
@@ -1467,9 +1465,8 @@ yylex()
default:
fatalerror("Unknown state in scanner.");
}
- yyerror((char *) 0);
state = CMD;
- longjmp(errcatch,0);
+ return (LEXERR);
}
}
diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c
index 90cd030..ae905c0 100644
--- a/libexec/ftpd/ftpd.c
+++ b/libexec/ftpd/ftpd.c
@@ -79,7 +79,6 @@ static const char rcsid[] =
#include <pwd.h>
#include <grp.h>
#include <opie.h>
-#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -125,7 +124,6 @@ union sockunion pasv_addr;
int daemon_mode;
int data;
-jmp_buf errcatch, urgcatch;
int logged_in;
struct passwd *pw;
int ftpdebug;
@@ -150,6 +148,7 @@ int noepsv=0; /* EPSV command is disabled. */
int noretr=0; /* RETR command is disabled. */
int noguestretr=0; /* RETR command is disabled for anon users. */
+static volatile sig_atomic_t recvurg;
sig_atomic_t transflag;
off_t file_size;
off_t byte_count;
@@ -243,7 +242,8 @@ static void inithosts __P((void));
static void selecthost __P((union sockunion *));
#endif
static void ack __P((char *));
-static void myoob __P((int));
+static void sigurg __P((int));
+static void myoob __P((void));
static int checkuser __P((char *, char *, int));
static FILE *dataconn __P((char *, off_t, char *));
static void dolog __P((struct sockaddr *));
@@ -252,8 +252,9 @@ static void end_login __P((void));
static FILE *getdatasock __P((char *));
static char *gunique __P((char *));
static void lostconn __P((int));
+static void sigquit __P((int));
static int receive_data __P((FILE *, FILE *));
-static void send_data __P((FILE *, FILE *, off_t, off_t, int));
+static int send_data __P((FILE *, FILE *, off_t, off_t, int));
static struct passwd *
sgetpwnam __P((char *));
static char *sgetsave __P((char *));
@@ -286,8 +287,11 @@ main(argc, argv, envp)
char *bindname = NULL;
int family = AF_UNSPEC;
int enable_v4 = 0;
+ struct sigaction sa;
tzset(); /* in case no timezone database in ~ftp */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = SA_RESTART;
#ifdef OLD_SETPROCTITLE
/*
@@ -419,7 +423,8 @@ main(argc, argv, envp)
syslog(LOG_ERR, "failed to become a daemon");
exit(1);
}
- (void) signal(SIGCHLD, reapchild);
+ sa.sa_handler = reapchild;
+ (void)sigaction(SIGCHLD, &sa, NULL);
/* init bind_sa */
memset(&hints, 0, sizeof(hints));
@@ -522,10 +527,23 @@ main(argc, argv, envp)
}
}
- (void) signal(SIGCHLD, SIG_IGN);
- (void) signal(SIGPIPE, lostconn);
- if (signal(SIGURG, myoob) == SIG_ERR)
- syslog(LOG_ERR, "signal: %m");
+ sa.sa_handler = SIG_DFL;
+ (void)sigaction(SIGCHLD, &sa, NULL);
+
+ sa.sa_handler = sigurg;
+ sa.sa_flags = 0; /* don't restart syscalls for SIGURG */
+ (void)sigaction(SIGURG, &sa, NULL);
+
+ sigfillset(&sa.sa_mask); /* block all signals in handler */
+ sa.sa_flags = SA_RESTART;
+ sa.sa_handler = sigquit;
+ (void)sigaction(SIGHUP, &sa, NULL);
+ (void)sigaction(SIGINT, &sa, NULL);
+ (void)sigaction(SIGQUIT, &sa, NULL);
+ (void)sigaction(SIGTERM, &sa, NULL);
+
+ sa.sa_handler = lostconn;
+ (void)sigaction(SIGPIPE, &sa, NULL);
addrlen = sizeof(ctrl_addr);
if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) {
@@ -610,7 +628,6 @@ main(argc, argv, envp)
hostname[MAXHOSTNAMELEN - 1] = '\0';
#endif
reply(220, "%s FTP server (%s) ready.", hostname, version);
- (void) setjmp(errcatch);
for (;;)
(void) yyparse();
/* NOTREACHED */
@@ -626,6 +643,15 @@ lostconn(signo)
dologout(1);
}
+static void
+sigquit(signo)
+ int signo;
+{
+
+ syslog(LOG_ERR, "got signal %d", signo);
+ dologout(1);
+}
+
#ifdef VIRTUAL_HOSTING
/*
* read in virtual host tables (if they exist)
@@ -1770,7 +1796,7 @@ pdata_err:
*
* NB: Form isn't handled.
*/
-static void
+static int
send_data(instr, outstr, blksize, filesize, isreg)
FILE *instr, *outstr;
off_t blksize;
@@ -1783,14 +1809,12 @@ send_data(instr, outstr, blksize, filesize, isreg)
off_t cnt;
transflag++;
- if (setjmp(urgcatch)) {
- transflag = 0;
- return;
- }
switch (type) {
case TYPE_A:
while ((c = getc(instr)) != EOF) {
+ if (recvurg)
+ goto got_oob;
byte_count++;
if (c == '\n') {
if (ferror(outstr))
@@ -1799,6 +1823,8 @@ send_data(instr, outstr, blksize, filesize, isreg)
}
(void) putc(c, outstr);
}
+ if (recvurg)
+ goto got_oob;
fflush(outstr);
transflag = 0;
if (ferror(instr))
@@ -1806,7 +1832,7 @@ send_data(instr, outstr, blksize, filesize, isreg)
if (ferror(outstr))
goto data_err;
reply(226, "Transfer complete.");
- return;
+ return (0);
case TYPE_I:
case TYPE_L:
@@ -1828,6 +1854,8 @@ send_data(instr, outstr, blksize, filesize, isreg)
while (err != -1 && cnt < filesize) {
err = sendfile(filefd, netfd, offset, len,
(struct sf_hdtr *) NULL, &cnt, 0);
+ if (recvurg)
+ goto got_oob;
byte_count += cnt;
offset += cnt;
len -= cnt;
@@ -1841,14 +1869,14 @@ send_data(instr, outstr, blksize, filesize, isreg)
}
reply(226, "Transfer complete.");
- return;
+ return (0);
}
oldway:
if ((buf = malloc((u_int)blksize)) == NULL) {
transflag = 0;
perror_reply(451, "Local resource failure: malloc");
- return;
+ return (-1);
}
while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 &&
@@ -1862,21 +1890,28 @@ oldway:
goto data_err;
}
reply(226, "Transfer complete.");
- return;
+ return (0);
default:
transflag = 0;
reply(550, "Unimplemented TYPE %d in send_data", type);
- return;
+ return (-1);
}
data_err:
transflag = 0;
perror_reply(426, "Data connection");
- return;
+ return (-1);
file_err:
transflag = 0;
perror_reply(551, "Error on input file");
+ return (-1);
+
+got_oob:
+ myoob();
+ recvurg = 0;
+ transflag = 0;
+ return (-1);
}
/*
@@ -1894,11 +1929,6 @@ receive_data(instr, outstr)
char buf[BUFSIZ];
transflag++;
- if (setjmp(urgcatch)) {
- transflag = 0;
- return (-1);
- }
-
bare_lfs = 0;
switch (type) {
@@ -1906,10 +1936,14 @@ receive_data(instr, outstr)
case TYPE_I:
case TYPE_L:
while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) {
+ if (recvurg)
+ goto got_oob;
if (write(fileno(outstr), buf, cnt) != cnt)
goto file_err;
byte_count += cnt;
}
+ if (recvurg)
+ goto got_oob;
if (cnt < 0)
goto data_err;
transflag = 0;
@@ -1922,6 +1956,8 @@ receive_data(instr, outstr)
case TYPE_A:
while ((c = getc(instr)) != EOF) {
+ if (recvurg)
+ goto got_oob;
byte_count++;
if (c == '\n')
bare_lfs++;
@@ -1937,6 +1973,8 @@ receive_data(instr, outstr)
(void) putc(c, outstr);
contin2: ;
}
+ if (recvurg)
+ goto got_oob;
fflush(outstr);
if (ferror(instr))
goto data_err;
@@ -1965,6 +2003,12 @@ file_err:
transflag = 0;
perror_reply(452, "Error writing file");
return (-1);
+
+got_oob:
+ myoob();
+ recvurg = 0;
+ transflag = 0;
+ return (-1);
}
void
@@ -2384,9 +2428,16 @@ dologout(status)
}
static void
-myoob(signo)
+sigurg(signo)
int signo;
{
+
+ recvurg = 1;
+}
+
+static void
+myoob()
+{
char *cp;
/* only process if transfer occurring */
@@ -2402,7 +2453,6 @@ myoob(signo)
tmpline[0] = '\0';
reply(426, "Transfer aborted. Data connection closed.");
reply(226, "Abort successful");
- longjmp(urgcatch, 1);
}
if (strcmp(cp, "STAT\r\n") == 0) {
tmpline[0] = '\0';
@@ -2718,10 +2768,6 @@ send_file_list(whichf)
simple = 1;
}
- if (setjmp(urgcatch)) {
- transflag = 0;
- goto out;
- }
while ((dirname = *dirlist++)) {
if (stat(dirname, &st) < 0) {
/*
@@ -2763,6 +2809,13 @@ send_file_list(whichf)
while ((dir = readdir(dirp)) != NULL) {
char nbuf[MAXPATHLEN];
+ if (recvurg) {
+ myoob();
+ recvurg = 0;
+ transflag = 0;
+ goto out;
+ }
+
if (dir->d_name[0] == '.' && dir->d_namlen == 1)
continue;
if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
OpenPOWER on IntegriCloud