Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src defend against malicious line in ut_line, which could cause ...
details: https://anonhg.NetBSD.org/src/rev/0462999be8d1
branches: trunk
changeset: 535379:0462999be8d1
user: itojun <itojun%NetBSD.org@localhost>
date: Fri Aug 16 20:21:48 2002 +0000
description:
defend against malicious line in ut_line, which could cause unwanted
writes to anything under /dev. revoke setuid/gid privs earlier.
From: xs%kittenz.org@localhost
diffstat:
lib/libutil/ttymsg.c | 28 ++++--
libexec/utmp_update/utmp_update.c | 33 +++++--
sbin/dump/optr.c | 9 +-
usr.bin/wall/wall.c | 30 +++++--
usr.bin/write/write.c | 159 +++++++++++++++++++++++++------------
5 files changed, 173 insertions(+), 86 deletions(-)
diffs (truncated from 586 to 300 lines):
diff -r cc05482b8104 -r 0462999be8d1 lib/libutil/ttymsg.c
--- a/lib/libutil/ttymsg.c Fri Aug 16 18:05:19 2002 +0000
+++ b/lib/libutil/ttymsg.c Fri Aug 16 20:21:48 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ttymsg.c,v 1.15 2000/07/05 11:46:42 ad Exp $ */
+/* $NetBSD: ttymsg.c,v 1.16 2002/08/16 20:21:48 itojun Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -38,7 +38,7 @@
#if 0
static char sccsid[] = "@(#)ttymsg.c 8.2 (Berkeley) 11/16/93";
#else
-__RCSID("$NetBSD: ttymsg.c,v 1.15 2000/07/05 11:46:42 ad Exp $");
+__RCSID("$NetBSD: ttymsg.c,v 1.16 2002/08/16 20:21:48 itojun Exp $");
#endif
#endif /* LIBC_SCCS and not lint */
@@ -67,8 +67,8 @@
char *
ttymsg(struct iovec *iov, int iovcnt, const char *line, int tmout)
{
- static char device[MAXNAMLEN] = _PATH_DEV;
static char errbuf[1024];
+ char device[MAXNAMLEN];
int cnt, fd, left, wret;
struct iovec localiov[6];
sigset_t nset;
@@ -81,12 +81,16 @@
if (iovcnt > sizeof(localiov) / sizeof(localiov[0]))
return ("too many iov's (change code in libutil/ttymsg.c)");
- (void)strncpy(device + sizeof(_PATH_DEV) - 1, line,
- sizeof(device) - sizeof(_PATH_DEV));
- if (strchr(device + sizeof(_PATH_DEV) - 1, '/')) {
- /* A slash is an attempt to break security... */
- (void) snprintf(errbuf, sizeof(errbuf), "'/' in \"%s\"",
- device);
+ if (strlcpy(device, _PATH_DEV, sizeof(device)) >= sizeof(device) ||
+ strlcat(device, line, sizeof(device)) >= sizeof(device)) {
+ (void) snprintf(errbuf, sizeof(errbuf), "%s: path too long",
+ line);
+ return (errbuf);
+ }
+ if (strcspn(line, "./") != strlen(line)) {
+ /* A slash or dot is an attempt to break security... */
+ (void) snprintf(errbuf, sizeof(errbuf), "'/' or '.' in \"%s\"",
+ line);
return (errbuf);
}
@@ -101,6 +105,12 @@
"%s: %s", device, strerror(errno));
return (errbuf);
}
+ if (!isatty(fd)) {
+ (void) snprintf(errbuf, sizeof(errbuf),
+ "%s: not a tty device", device);
+ (void) close(fd);
+ return (errbuf);
+ }
for (cnt = left = 0; cnt < iovcnt; ++cnt)
left += iov[cnt].iov_len;
diff -r cc05482b8104 -r 0462999be8d1 libexec/utmp_update/utmp_update.c
--- a/libexec/utmp_update/utmp_update.c Fri Aug 16 18:05:19 2002 +0000
+++ b/libexec/utmp_update/utmp_update.c Fri Aug 16 20:21:48 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: utmp_update.c,v 1.3 2002/08/09 10:01:53 soren Exp $ */
+/* $NetBSD: utmp_update.c,v 1.4 2002/08/16 20:21:48 itojun Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -41,6 +41,7 @@
#include <stdio.h>
#include <vis.h>
#include <err.h>
+#include <fcntl.h>
#include <pwd.h>
#include <utmpx.h>
#include <stdlib.h>
@@ -56,8 +57,14 @@
size_t len;
struct passwd *pwd;
struct stat st;
+ int fd;
+ uid_t euid;
- if (argc != 1) {
+ euid = geteuid();
+ if (seteuid(getuid()) == -1)
+ err(1, "seteuid");
+
+ if (argc != 2) {
(void)fprintf(stderr, "Usage: %s <vis-utmpx-entry>\n",
getprogname());
exit(1);
@@ -90,18 +97,20 @@
errx(1, "Current user `%s' does not match `%s' in utmpx entry",
pwd->pw_name, utx->ut_name);
- if (stat(utx->ut_line, &st) == -1)
+ fd = open(utx->ut_line, O_RDONLY, 0);
+ if (fd == -1)
+ err(1, "Cannot open `%s'", utx->ut_line);
+ if (fstat(fd, &st) == -1)
err(1, "Cannot stat `%s'", utx->ut_line);
-
- if (!S_ISCHR(st.st_mode))
- errx(1, "%s: Not a character device", utx->ut_line);
+ if (st.st_uid != getuid())
+ errx(1, "%s: Is not owned by you", utx->ut_line);
+ if (!isatty(fd))
+ errx(1, "%s: Not a tty device", utx->ut_line);
+ close(fd);
+ if (access(utx->ut_line, W_OK|R_OK) == -1)
+ err(1, "%s", utx->ut_line);
- /*
- * to check if the tty is writable here is problematic. First we
- * don't even know if it is a tty, secondly we are setuid so it
- * is not trivial to use access
- */
-
+ (void)seteuid(euid);
pututxline(utx);
return 0;
diff -r cc05482b8104 -r 0462999be8d1 sbin/dump/optr.c
--- a/sbin/dump/optr.c Fri Aug 16 18:05:19 2002 +0000
+++ b/sbin/dump/optr.c Fri Aug 16 20:21:48 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: optr.c,v 1.26 2002/08/02 02:07:09 christos Exp $ */
+/* $NetBSD: optr.c,v 1.27 2002/08/16 20:21:49 itojun Exp $ */
/*-
* Copyright (c) 1980, 1988, 1993
@@ -38,7 +38,7 @@
#if 0
static char sccsid[] = "@(#)optr.c 8.2 (Berkeley) 1/6/94";
#else
-__RCSID("$NetBSD: optr.c,v 1.26 2002/08/02 02:07:09 christos Exp $");
+__RCSID("$NetBSD: optr.c,v 1.27 2002/08/16 20:21:49 itojun Exp $");
#endif
#endif /* not lint */
@@ -272,11 +272,16 @@
int lmsg = 1;
FILE *f_tty;
+ if (strcspn(tty, "./") != strlen(tty))
+ return;
+
(void)strncpy(t, _PATH_DEV, sizeof(t) - 1);
(void)strncat(t, tty, sizeof(t) - sizeof(_PATH_DEV) - 1);
t[sizeof(t) - 1] = '\0';
if ((f_tty = fopen(t, "w")) != NULL) {
+ if (!isatty(fileno(f_tty)))
+ return;
setbuf(f_tty, buf);
(void) fprintf(f_tty,
"\n\
diff -r cc05482b8104 -r 0462999be8d1 usr.bin/wall/wall.c
--- a/usr.bin/wall/wall.c Fri Aug 16 18:05:19 2002 +0000
+++ b/usr.bin/wall/wall.c Fri Aug 16 20:21:48 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: wall.c,v 1.19 2002/08/02 01:52:13 christos Exp $ */
+/* $NetBSD: wall.c,v 1.20 2002/08/16 20:21:49 itojun Exp $ */
/*
* Copyright (c) 1988, 1990, 1993
@@ -43,7 +43,7 @@
#if 0
static char sccsid[] = "@(#)wall.c 8.2 (Berkeley) 11/16/93";
#endif
-__RCSID("$NetBSD: wall.c,v 1.19 2002/08/02 01:52:13 christos Exp $");
+__RCSID("$NetBSD: wall.c,v 1.20 2002/08/16 20:21:49 itojun Exp $");
#endif /* not lint */
/*
@@ -57,6 +57,7 @@
#include <sys/uio.h>
#include <err.h>
+#include <errno.h>
#include <paths.h>
#include <pwd.h>
#include <stdio.h>
@@ -71,7 +72,7 @@
int main(int, char **);
int nobanner;
-int mbufsize;
+size_t mbufsize;
char *mbuf;
/* ARGSUSED */
@@ -81,8 +82,14 @@
int ch;
struct iovec iov;
char *p;
- struct passwd *pep = getpwnam("nobody");
+ struct passwd *pep;
struct utmpentry *ep;
+ gid_t egid;
+
+ egid = getegid();
+ if (setegid(getgid()) == -1)
+ err(1, "setegid");
+ pep = getpwnam("nobody");
while ((ch = getopt(argc, argv, "n")) != -1)
switch (ch) {
@@ -107,6 +114,7 @@
iov.iov_base = mbuf;
iov.iov_len = mbufsize;
(void)getutentries(NULL, &ep);
+ (void)setegid(egid);
for (; ep; ep = ep->next)
if ((p = ttymsg(&iov, 1, ep->line, 60*5)) != NULL)
warnx("%s", p);
@@ -116,7 +124,7 @@
void
makemsg(const char *fname)
{
- register int ch, cnt;
+ int ch, cnt;
struct tm *lt;
struct passwd *pw;
struct stat sbuf;
@@ -127,9 +135,11 @@
char *p, *tty, tmpname[32], lbuf[100], hostname[MAXHOSTNAMELEN+1];
(void)snprintf(tmpname, sizeof tmpname, "%s/wall.XXXXXX", _PATH_TMP);
- if ((fd = mkstemp(tmpname)) == -1 || !(fp = fdopen(fd, "r+")))
+ if ((fd = mkstemp(tmpname)) == -1)
err(1, "can't open temporary file");
(void)unlink(tmpname);
+ if (!(fp = fdopen(fd, "r+")))
+ err(1, "can't open temporary file");
if (!nobanner) {
if (!(whom = getlogin()))
@@ -179,10 +189,12 @@
if (fstat(fd, &sbuf))
err(1, "can't stat temporary file");
+ if (sbuf.st_size > SIZE_T_MAX)
+ errx(1, "file too big");
mbufsize = sbuf.st_size;
- if (!(mbuf = malloc((u_int)mbufsize)))
+ if (!(mbuf = malloc(mbufsize)))
err(1, "malloc");
- if (fread(mbuf, sizeof(*mbuf), mbufsize, fp) != mbufsize)
+ if (fread(mbuf, 1, mbufsize, fp) != mbufsize)
err(1, "can't read temporary file");
- (void)close(fd);
+ (void)fclose(fp);
}
diff -r cc05482b8104 -r 0462999be8d1 usr.bin/write/write.c
--- a/usr.bin/write/write.c Fri Aug 16 18:05:19 2002 +0000
+++ b/usr.bin/write/write.c Fri Aug 16 20:21:48 2002 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: write.c,v 1.20 2002/08/02 01:59:44 christos Exp $ */
+/* $NetBSD: write.c,v 1.21 2002/08/16 20:21:49 itojun Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -46,7 +46,7 @@
#if 0
static char sccsid[] = "@(#)write.c 8.2 (Berkeley) 4/27/95";
#else
-__RCSID("$NetBSD: write.c,v 1.20 2002/08/02 01:59:44 christos Exp $");
+__RCSID("$NetBSD: write.c,v 1.21 2002/08/16 20:21:49 itojun Exp $");
#endif
#endif /* not lint */
@@ -64,25 +64,34 @@
#include <pwd.h>
#include <unistd.h>
#include <err.h>
+#include <errno.h>
#include "utmpentry.h"
void done(int);
-void do_write(const char *, const char *, const uid_t);
+void do_write(int, const char *, const uid_t);
void wr_fputs(char *);
-void search_utmp(char *, char *, char *, uid_t, int);
-int term_chk(const char *, int *, time_t *, int);
+int search_utmp(char *, char *, uid_t);
+int term_chk(uid_t, const char *, int *, time_t *, int);
int utmp_chk(const char *, const char *);
int main(int, char **);
+static gid_t saved_egid;
+
int
Home |
Main Index |
Thread Index |
Old Index