Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/libexec/tftpd Prevent buffer overflows; reported by Maxime V...
details: https://anonhg.NetBSD.org/src/rev/bd858512915d
branches: trunk
changeset: 787703:bd858512915d
user: christos <christos%NetBSD.org@localhost>
date: Fri Jun 28 17:20:15 2013 +0000
description:
Prevent buffer overflows; reported by Maxime Villard
diffstat:
libexec/tftpd/tftpd.c | 60 +++++++++++++++++++++++++++-----------------------
1 files changed, 32 insertions(+), 28 deletions(-)
diffs (149 lines):
diff -r efa2dfab8450 -r bd858512915d libexec/tftpd/tftpd.c
--- a/libexec/tftpd/tftpd.c Fri Jun 28 17:13:34 2013 +0000
+++ b/libexec/tftpd/tftpd.c Fri Jun 28 17:20:15 2013 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tftpd.c,v 1.39 2011/08/29 20:41:07 joerg Exp $ */
+/* $NetBSD: tftpd.c,v 1.40 2013/06/28 17:20:15 christos Exp $ */
/*
* Copyright (c) 1983, 1993
@@ -36,7 +36,7 @@
#if 0
static char sccsid[] = "@(#)tftpd.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: tftpd.c,v 1.39 2011/08/29 20:41:07 joerg Exp $");
+__RCSID("$NetBSD: tftpd.c,v 1.40 2013/06/28 17:20:15 christos Exp $");
#endif
#endif /* not lint */
@@ -419,8 +419,8 @@
}
static int
-blk_handler(struct tftphdr *tp, char *opt, char *val, char *ack,
- int *ackl, int *ec)
+blk_handler(struct tftphdr *tp, const char *val, char *ack, size_t asize,
+ size_t *ackl, int *ec)
{
unsigned long bsize;
char *endp;
@@ -450,17 +450,18 @@
}
tftp_blksize = bsize;
- strcpy(ack + *ackl, "blksize");
- *ackl += 8;
- l = sprintf(ack + *ackl, "%lu", bsize);
- *ackl += l + 1;
+ if (asize > *ackl && (l = snprintf(ack + *ackl, asize - *ackl,
+ "blksize%c%lu%c", 0, bsize, 0)) > 0)
+ *ackl += l;
+ else
+ return -1;
return 0;
}
static int
-timeout_handler(struct tftphdr *tp, char *opt, char *val, char *ack,
- int *ackl, int *ec)
+timeout_handler(struct tftphdr *tp, const char *val, char *ack, size_t asize,
+ size_t *ackl, int *ec)
{
unsigned long tout;
char *endp;
@@ -486,11 +487,11 @@
}
rexmtval = tout;
- strcpy(ack + *ackl, "timeout");
- *ackl += 8;
- l = sprintf(ack + *ackl, "%lu", tout);
- *ackl += l + 1;
-
+ if (asize > *ackl && (l = snprintf(ack + *ackl, asize - *ackl,
+ "timeout%c%lu%c", 0, tout, 0)))
+ *ackl += l;
+ else
+ return -1;
/*
* Arbitrarily pick a maximum timeout on a request to 3
* retransmissions if the interval timeout is more than
@@ -507,8 +508,8 @@
}
static int
-tsize_handler(struct tftphdr *tp, char *opt, char *val, char *ack,
- int *ackl, int *ec)
+tsize_handler(struct tftphdr *tp, const char *val, char *ack, size_t asize,
+ size_t *ackl, int *ec)
{
unsigned long fsize;
char *endp;
@@ -550,8 +551,8 @@
static const struct tftp_options {
const char *o_name;
- int (*o_handler)(struct tftphdr *, char *, char *, char *,
- int *, int *);
+ int (*o_handler)(struct tftphdr *, const char *, char *, size_t,
+ size_t *, int *);
} options[] = {
{ "blksize", blk_handler },
{ "timeout", timeout_handler },
@@ -564,8 +565,8 @@
* recognize in oackbuf.
*/
static int
-get_options(struct tftphdr *tp, char *cp, int size, char *ackb,
- int *alen, int *err)
+get_options(struct tftphdr *tp, char *cp, int size, char *ackb, size_t asize,
+ size_t *alen, int *err)
{
const struct tftp_options *op;
char *option, *value, *endp;
@@ -597,7 +598,7 @@
break;
}
if (op->o_name) {
- r = op->o_handler(tp, option, value, ackb, alen, &ec);
+ r = op->o_handler(tp, value, ackb, asize, alen, &ec);
if (r < 0) {
rv = -1;
break;
@@ -621,7 +622,8 @@
struct formats *pf;
char *cp;
char *filename, *mode;
- int first, ecode, alen, etftp = 0, r;
+ int first, ecode, etftp = 0, r;
+ size_t alen;
ecode = 0; /* XXX gcc */
first = 1;
@@ -666,7 +668,8 @@
size -= (++cp - (char *) tp);
if (size > 0 && *cp) {
alen = 2; /* Skip over opcode */
- r = get_options(tp, cp, size, oackbuf, &alen, &ecode);
+ r = get_options(tp, cp, size, oackbuf, sizeof(oackbuf),
+ &alen, &ecode);
if (r > 0) {
etftp = 1;
} else if (r < 0) {
@@ -708,10 +711,11 @@
if (tftp_opt_tsize) {
int l;
- strcpy(oackbuf + alen, "tsize");
- alen += 6;
- l = sprintf(oackbuf + alen, "%u", tftp_tsize);
- alen += l + 1;
+ if (sizeof(oackbuf) > alen &&
+ (l = snprintf(oackbuf + alen,
+ sizeof(oackbuf) - alen, "tsize%c%u%c", 0,
+ tftp_tsize, 0)))
+ alen += l;
}
oack_h = (struct tftphdr *) oackbuf;
oack_h->th_opcode = htons(OACK);
Home |
Main Index |
Thread Index |
Old Index