• Address concerns of Chris Palmer from the Android security team
– possible integer overflows in memory allocation, mostly ‣ multiplication: all are checked now ‣ addition: reviewed them, most were “proven” or guessed to be “almost” impossible to run over (e.g. when we have a string whose length is taken it is assumed that the length will be more than only a few bytes below SIZE_MAX, since code and stack have to fit); some are checked now (e.g. when one of the summands is an off_t); most of the unchecked ones are annotated now ⇒ cost (MirBSD/i386 static): +76 .text ⇒ cost (Debian sid/i386): +779 .text -4 .data – on Linux targets, setuid() setresuid() setresgid() can fail with EAGAIN; check for that and, if so, warn once and retry infinitely (other targets to be added later once we know that they are “insane”) ⇒ cost (Debian sid/i386): +192 .text (includes .rodata) • setmode.c: Do overflow checking for realloc() too; switch back from calloc() to a checked malloc() for simplification while there • define -DIN_MKSH and let setmode.c look a tad nicer while here
This commit is contained in:
parent
08862021ee
commit
667d792d6a
6
Build.sh
6
Build.sh
@ -1,5 +1,5 @@
|
||||
#!/bin/sh
|
||||
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.460 2010/09/14 21:15:09 tg Exp $'
|
||||
srcversion='$MirOS: src/bin/mksh/Build.sh,v 1.461 2010/09/14 21:26:04 tg Exp $'
|
||||
#-
|
||||
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
# Thorsten Glaser <tg@mirbsd.org>
|
||||
@ -441,7 +441,7 @@ IRIX*)
|
||||
: ${HAVE_SETLOCALE_CTYPE=0}
|
||||
;;
|
||||
Linux)
|
||||
CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE"
|
||||
CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE -DSETUID_CAN_FAIL_WITH_EAGAIN"
|
||||
: ${HAVE_REVOKE=0}
|
||||
;;
|
||||
MidnightBSD)
|
||||
@ -1427,11 +1427,11 @@ addsrcs '!' HAVE_SETMODE setmode.c
|
||||
addsrcs '!' HAVE_STRLCPY strlcpy.c
|
||||
addsrcs USE_PRINTF_BUILTIN printf.c
|
||||
test 1 = "$USE_PRINTF_BUILTIN" && CPPFLAGS="$CPPFLAGS -DMKSH_PRINTF_BUILTIN"
|
||||
test 0 = "$HAVE_SETMODE" && CPPFLAGS="$CPPFLAGS -DHAVE_CONFIG_H -DCONFIG_H_FILENAME=\\\"sh.h\\\""
|
||||
test 1 = "$HAVE_CAN_VERB" && CFLAGS="$CFLAGS -verbose"
|
||||
|
||||
$e $bi$me: Finished configuration testing, now producing output.$ao
|
||||
|
||||
CPPFLAGS="$CPPFLAGS -DIN_MKSH"
|
||||
files=
|
||||
objs=
|
||||
sp=
|
||||
|
4
Makefile
4
Makefile
@ -1,4 +1,4 @@
|
||||
# $MirOS: src/bin/mksh/Makefile,v 1.81 2010/08/24 15:19:53 tg Exp $
|
||||
# $MirOS: src/bin/mksh/Makefile,v 1.82 2010/09/14 21:26:05 tg Exp $
|
||||
#-
|
||||
# Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
|
||||
# Thorsten Glaser <tg@mirbsd.org>
|
||||
@ -43,7 +43,7 @@ CPPFLAGS+= -DMKSH_ASSUME_UTF8 \
|
||||
-DHAVE_SETMODE=1 -DHAVE_SETRESUGID=1 -DHAVE_SETGROUPS=1 \
|
||||
-DHAVE_STRCASESTR=1 -DHAVE_STRLCPY=1 -DHAVE_FLOCK_DECL=1 \
|
||||
-DHAVE_REVOKE_DECL=1 -DHAVE_SYS_SIGLIST_DECL=1 \
|
||||
-DHAVE_PERSISTENT_HISTORY=1
|
||||
-DHAVE_PERSISTENT_HISTORY=1 -DIN_MKSH
|
||||
COPTS+= -std=gnu99 -Wall
|
||||
.endif
|
||||
|
||||
|
4
check.t
4
check.t
@ -1,4 +1,4 @@
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.391 2010/09/05 19:51:29 tg Exp $
|
||||
# $MirOS: src/bin/mksh/check.t,v 1.392 2010/09/14 21:26:07 tg Exp $
|
||||
# $OpenBSD: bksl-nl.t,v 1.2 2001/01/28 23:04:56 niklas Exp $
|
||||
# $OpenBSD: history.t,v 1.5 2001/01/28 23:04:56 niklas Exp $
|
||||
# $OpenBSD: read.t,v 1.3 2003/03/10 03:48:16 david Exp $
|
||||
@ -25,7 +25,7 @@
|
||||
# http://www.research.att.com/~gsf/public/ifs.sh
|
||||
|
||||
expected-stdout:
|
||||
@(#)MIRBSD KSH R39 2010/09/05
|
||||
@(#)MIRBSD KSH R39 2010/09/14
|
||||
description:
|
||||
Check version of shell.
|
||||
stdin:
|
||||
|
24
edit.c
24
edit.c
@ -25,7 +25,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.200 2010/09/05 19:51:31 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.201 2010/09/14 21:26:09 tg Exp $");
|
||||
|
||||
/*
|
||||
* in later versions we might use libtermcap for this, but since external
|
||||
@ -424,7 +424,7 @@ x_command_glob(int flags, const char *str, int slen, char ***wordsp)
|
||||
int i, path_order = 0;
|
||||
|
||||
info = (struct path_order_info *)
|
||||
alloc(nwords * sizeof(struct path_order_info), ATEMP);
|
||||
alloc2(nwords, sizeof(struct path_order_info), ATEMP);
|
||||
for (i = 0; i < nwords; i++) {
|
||||
info[i].word = words[i];
|
||||
info[i].base = x_basename(words[i], NULL);
|
||||
@ -678,13 +678,15 @@ glob_table(const char *pat, XPtrV *wp, struct table *tp)
|
||||
static void
|
||||
glob_path(int flags, const char *pat, XPtrV *wp, const char *lpath)
|
||||
{
|
||||
const char *sp, *p;
|
||||
const char *sp = lpath, *p;
|
||||
char *xp, **words;
|
||||
int staterr, pathlen, patlen, oldsize, newsize, i, j;
|
||||
size_t pathlen, patlen, oldsize, newsize, i, j;
|
||||
int staterr;
|
||||
XString xs;
|
||||
|
||||
patlen = strlen(pat) + 1;
|
||||
sp = lpath;
|
||||
patlen = strlen(pat);
|
||||
checkoktoadd(patlen, 129 + X_EXTRA);
|
||||
++patlen;
|
||||
Xinit(xs, xp, patlen + 128, ATEMP);
|
||||
while (sp) {
|
||||
xp = Xstring(xs, xp);
|
||||
@ -2466,7 +2468,7 @@ x_init_emacs(void)
|
||||
ainit(AEDIT);
|
||||
x_nextcmd = -1;
|
||||
|
||||
x_tab = alloc(X_NTABS * sizeof(*x_tab), AEDIT);
|
||||
x_tab = alloc2(X_NTABS, sizeof(*x_tab), AEDIT);
|
||||
for (j = 0; j < X_TABSZ; j++)
|
||||
x_tab[0][j] = XFUNC_insert;
|
||||
for (i = 1; i < X_NTABS; i++)
|
||||
@ -2477,7 +2479,7 @@ x_init_emacs(void)
|
||||
= x_defbindings[i].xdb_func;
|
||||
|
||||
#ifndef MKSH_SMALL
|
||||
x_atab = alloc(X_NTABS * sizeof(*x_atab), AEDIT);
|
||||
x_atab = alloc2(X_NTABS, sizeof(*x_atab), AEDIT);
|
||||
for (i = 1; i < X_NTABS; i++)
|
||||
for (j = 0; j < X_TABSZ; j++)
|
||||
x_atab[i][j] = NULL;
|
||||
@ -3912,7 +3914,7 @@ vi_cmd(int argcnt, const char *cmd)
|
||||
{
|
||||
static char alias[] = "_\0";
|
||||
struct tbl *ap;
|
||||
int olen, nlen;
|
||||
size_t olen, nlen;
|
||||
char *p, *nbuf;
|
||||
|
||||
/* lookup letter in alias list... */
|
||||
@ -3929,6 +3931,10 @@ vi_cmd(int argcnt, const char *cmd)
|
||||
nlen = strlen(ap->val.s) + 1;
|
||||
olen = !macro.p ? 2 :
|
||||
macro.len - (macro.p - macro.buf);
|
||||
/*
|
||||
* at this point, it's fairly reasonable that
|
||||
* nlen + olen + 2 doesn't overflow
|
||||
*/
|
||||
nbuf = alloc(nlen + 1 + olen, APERM);
|
||||
memcpy(nbuf, ap->val.s, nlen);
|
||||
nbuf[nlen++] = cmd[1];
|
||||
|
6
eval.c
6
eval.c
@ -22,7 +22,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.92 2010/08/28 20:22:16 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.93 2010/09/14 21:26:10 tg Exp $");
|
||||
|
||||
/*
|
||||
* string expansion
|
||||
@ -1562,6 +1562,10 @@ alt_expand(XPtrV *wp, char *start, char *exp_start, char *end, int fdo)
|
||||
char *news;
|
||||
int l1, l2, l3;
|
||||
|
||||
/*
|
||||
* addition safe since these operate on
|
||||
* one string (separate substrings)
|
||||
*/
|
||||
l1 = brace_start - start;
|
||||
l2 = (p - 1) - field_start;
|
||||
l3 = end - brace_end;
|
||||
|
4
exec.c
4
exec.c
@ -22,7 +22,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.81 2010/09/05 19:51:32 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.82 2010/09/14 21:26:11 tg Exp $");
|
||||
|
||||
#ifndef MKSH_DEFAULT_EXECSHELL
|
||||
#define MKSH_DEFAULT_EXECSHELL "/bin/sh"
|
||||
@ -101,7 +101,7 @@ execute(struct op *volatile t,
|
||||
flags &= ~XTIME;
|
||||
|
||||
if (t->ioact != NULL || t->type == TPIPE || t->type == TCOPROC) {
|
||||
e->savefd = alloc(NUFILE * sizeof(short), ATEMP);
|
||||
e->savefd = alloc2(NUFILE, sizeof(short), ATEMP);
|
||||
/* initialise to not redirected */
|
||||
memset(e->savefd, 0, NUFILE * sizeof(short));
|
||||
}
|
||||
|
22
funcs.c
22
funcs.c
@ -25,7 +25,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.161 2010/09/05 19:51:33 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.162 2010/09/14 21:26:12 tg Exp $");
|
||||
|
||||
#if HAVE_KILLPG
|
||||
/*
|
||||
@ -208,6 +208,7 @@ do_realpath(const char *upath)
|
||||
afree(tp, ATEMP);
|
||||
}
|
||||
|
||||
/* ipath and upath are in memory at the same time -> unchecked */
|
||||
Xinit(xs, xp, strlen(ip = ipath) + 1, ATEMP);
|
||||
|
||||
while (*ip) {
|
||||
@ -277,8 +278,15 @@ do_realpath(const char *upath)
|
||||
}
|
||||
|
||||
/* get symlink(7) target */
|
||||
if (pathcnd)
|
||||
if (pathcnd) {
|
||||
#ifdef NO_PATH_MAX
|
||||
if (notoktoadd(pathlen, 1)) {
|
||||
errno = ENAMETOOLONG;
|
||||
goto notfound;
|
||||
}
|
||||
#endif
|
||||
ldest = aresize(ldest, pathlen + 1, ATEMP);
|
||||
}
|
||||
llen = readlink(Xstring(xs, xp), ldest, pathlen);
|
||||
if (llen < 0)
|
||||
/* oops... */
|
||||
@ -397,7 +405,7 @@ c_cd(const char **wp)
|
||||
}
|
||||
} else if (!wp[2]) {
|
||||
/* Two arguments - substitute arg1 in PWD for arg2 */
|
||||
int ilen, olen, nlen, elen;
|
||||
size_t ilen, olen, nlen, elen;
|
||||
char *cp;
|
||||
|
||||
if (!current_wd[0]) {
|
||||
@ -413,6 +421,12 @@ c_cd(const char **wp)
|
||||
bi_errorf("bad substitution");
|
||||
return (1);
|
||||
}
|
||||
/*-
|
||||
* ilen = part of current_wd before wp[0]
|
||||
* elen = part of current_wd after wp[0]
|
||||
* because current_wd and wp[1] need to be in memory at the
|
||||
* same time beforehand the addition can stay unchecked
|
||||
*/
|
||||
ilen = cp - current_wd;
|
||||
olen = strlen(wp[0]);
|
||||
nlen = strlen(wp[1]);
|
||||
@ -2381,7 +2395,7 @@ c_set(const char **wp)
|
||||
while (*++wp != NULL)
|
||||
strdupx(*wp, *wp, &l->area);
|
||||
l->argc = wp - owp - 1;
|
||||
l->argv = alloc((l->argc + 2) * sizeof(char *), &l->area);
|
||||
l->argv = alloc2(l->argc + 2, sizeof(char *), &l->area);
|
||||
for (wp = l->argv; (*wp++ = *owp++) != NULL; )
|
||||
;
|
||||
}
|
||||
|
21
histrap.c
21
histrap.c
@ -26,7 +26,7 @@
|
||||
#include <sys/file.h>
|
||||
#endif
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.101 2010/08/28 20:22:18 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.102 2010/09/14 21:26:13 tg Exp $");
|
||||
|
||||
/*-
|
||||
* MirOS: This is the default mapping type, and need not be specified.
|
||||
@ -92,6 +92,8 @@ c_fc(const char **wp)
|
||||
sflag = true;
|
||||
else {
|
||||
size_t len = strlen(p);
|
||||
|
||||
/* almost certainly not overflowing */
|
||||
editor = alloc(len + 4, ATEMP);
|
||||
memcpy(editor, p, len);
|
||||
memcpy(editor + len, " $_", 4);
|
||||
@ -269,7 +271,17 @@ c_fc(const char **wp)
|
||||
return (1);
|
||||
}
|
||||
|
||||
n = stat(tf->name, &statb) < 0 ? 128 : statb.st_size + 1;
|
||||
if (stat(tf->name, &statb) < 0)
|
||||
n = 128;
|
||||
else {
|
||||
if (notoktoadd(statb.st_size, 1 + X_EXTRA)) {
|
||||
bi_errorf(T_intovfl,
|
||||
(unsigned long)statb.st_size, '+',
|
||||
1UL + X_EXTRA);
|
||||
goto errout;
|
||||
}
|
||||
n = statb.st_size + 1;
|
||||
}
|
||||
Xinit(xs, xp, n, hist_source->areap);
|
||||
while ((n = shf_read(xp, Xnleft(xs, xp), shf)) > 0) {
|
||||
xp += n;
|
||||
@ -279,6 +291,7 @@ c_fc(const char **wp)
|
||||
if (n < 0) {
|
||||
bi_errorf("can't %s temporary file %s: %s",
|
||||
"read", tf->name, strerror(shf_errno(shf)));
|
||||
errout:
|
||||
shf_close(shf);
|
||||
return (1);
|
||||
}
|
||||
@ -532,7 +545,7 @@ sethistsize(int n)
|
||||
cursize = n;
|
||||
}
|
||||
|
||||
history = aresize(history, n * sizeof(char *), APERM);
|
||||
history = aresize2(history, n, sizeof(char *), APERM);
|
||||
|
||||
histsize = n;
|
||||
histptr = history + cursize;
|
||||
@ -583,7 +596,7 @@ init_histvec(void)
|
||||
{
|
||||
if (history == (char **)NULL) {
|
||||
histsize = HISTORYSIZE;
|
||||
history = alloc(histsize * sizeof(char *), APERM);
|
||||
history = alloc2(histsize, sizeof(char *), APERM);
|
||||
histptr = history - 1;
|
||||
}
|
||||
}
|
||||
|
13
lalloc.c
13
lalloc.c
@ -20,7 +20,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.12 2010/08/28 20:22:19 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/lalloc.c,v 1.13 2010/09/14 21:26:14 tg Exp $");
|
||||
|
||||
/* build with CPPFLAGS+= -DUSE_REALLOC_MALLOC=0 on ancient systems */
|
||||
#if defined(USE_REALLOC_MALLOC) && (USE_REALLOC_MALLOC == 0)
|
||||
@ -67,6 +67,15 @@ findptr(ALLOC_ITEM **lpp, char *ptr, Area *ap)
|
||||
return (ap);
|
||||
}
|
||||
|
||||
void *
|
||||
aresize2(void *ptr, size_t fac1, size_t fac2, Area *ap)
|
||||
{
|
||||
if (fac1 && fac2 && (SIZE_MAX / fac1 < fac2))
|
||||
internal_errorf(T_intovfl, (unsigned long)fac1, '*',
|
||||
(unsigned long)fac2);
|
||||
return (aresize(ptr, fac1 * fac2, ap));
|
||||
}
|
||||
|
||||
void *
|
||||
aresize(void *ptr, size_t numb, Area *ap)
|
||||
{
|
||||
@ -80,7 +89,7 @@ aresize(void *ptr, size_t numb, Area *ap)
|
||||
pp->next = lp->next;
|
||||
}
|
||||
|
||||
if ((numb >= SIZE_MAX - ALLOC_SIZE) ||
|
||||
if (notoktoadd(numb, ALLOC_SIZE) ||
|
||||
(lp = remalloc(lp, numb + ALLOC_SIZE)) == NULL
|
||||
#ifndef MKSH_SMALL
|
||||
|| ALLOC_ISUNALIGNED(lp)
|
||||
|
12
lex.c
12
lex.c
@ -22,7 +22,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.120 2010/08/28 20:22:20 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.121 2010/09/14 21:26:14 tg Exp $");
|
||||
|
||||
/*
|
||||
* states while lexing word
|
||||
@ -1446,7 +1446,7 @@ getsc_line(Source *s)
|
||||
int linelen;
|
||||
|
||||
linelen = Xlength(s->xs, xp);
|
||||
XcheckN(s->xs, xp, fc_e_n + /* NUL */ 1);
|
||||
XcheckN(s->xs, xp, Tn_fc_e_ + /* NUL */ 1);
|
||||
/* reload after potential realloc */
|
||||
cp = Xstring(s->xs, xp);
|
||||
/* change initial '!' into space */
|
||||
@ -1454,10 +1454,10 @@ getsc_line(Source *s)
|
||||
/* NUL terminate the current string */
|
||||
*xp = '\0';
|
||||
/* move the actual string forward */
|
||||
memmove(cp + fc_e_n, cp, linelen + /* NUL */ 1);
|
||||
xp += fc_e_n;
|
||||
memmove(cp + Tn_fc_e_, cp, linelen + /* NUL */ 1);
|
||||
xp += Tn_fc_e_;
|
||||
/* prepend it with "fc -e -" */
|
||||
memcpy(cp, fc_e_, fc_e_n);
|
||||
memcpy(cp, T_fc_e_, Tn_fc_e_);
|
||||
}
|
||||
#endif
|
||||
s->start = s->str = cp;
|
||||
@ -1749,7 +1749,7 @@ getsc_bn(void)
|
||||
static Lex_state *
|
||||
push_state_(State_info *si, Lex_state *old_end)
|
||||
{
|
||||
Lex_state *news = alloc(STATE_BSIZE * sizeof(Lex_state), ATEMP);
|
||||
Lex_state *news = alloc2(STATE_BSIZE, sizeof(Lex_state), ATEMP);
|
||||
|
||||
news[0].ls_info.base = old_end;
|
||||
si->base = &news[0];
|
||||
|
21
main.c
21
main.c
@ -33,7 +33,7 @@
|
||||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.171 2010/09/14 21:00:13 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.172 2010/09/14 21:26:14 tg Exp $");
|
||||
|
||||
extern char **environ;
|
||||
|
||||
@ -84,7 +84,7 @@ static const char *initcoms[] = {
|
||||
"history=fc -l",
|
||||
"nameref=typeset -n",
|
||||
"nohup=nohup ",
|
||||
r_fc_e_,
|
||||
T_r_fc_e_,
|
||||
"source=PATH=$PATH:. command .",
|
||||
"login=exec login",
|
||||
NULL,
|
||||
@ -119,7 +119,7 @@ mksh_init(int argc, const char *argv[])
|
||||
struct tbl *vp;
|
||||
struct stat s_stdin;
|
||||
#if !defined(_PATH_DEFPATH) && defined(_CS_PATH)
|
||||
size_t k;
|
||||
ssize_t k;
|
||||
char *cp;
|
||||
#endif
|
||||
|
||||
@ -181,7 +181,7 @@ mksh_init(int argc, const char *argv[])
|
||||
def_path = _PATH_DEFPATH;
|
||||
#else
|
||||
#ifdef _CS_PATH
|
||||
if ((k = confstr(_CS_PATH, NULL, 0)) != (size_t)-1 && k > 0 &&
|
||||
if ((k = confstr(_CS_PATH, NULL, 0)) > 0 &&
|
||||
confstr(_CS_PATH, cp = alloc(k + 1, APERM), k + 1) == k + 1)
|
||||
def_path = cp;
|
||||
else
|
||||
@ -1266,6 +1266,7 @@ maketemp(Area *ap, Temp_type type, struct temp **tlist)
|
||||
pathname = tempnam(dir, "mksh.");
|
||||
len = ((pathname == NULL) ? 0 : strlen(pathname)) + 1;
|
||||
#endif
|
||||
/* reasonably sure that this will not overflow */
|
||||
tp = alloc(sizeof(struct temp) + len, ap);
|
||||
tp->name = (char *)&tp[1];
|
||||
#if !HAVE_MKSTEMP
|
||||
@ -1313,7 +1314,7 @@ texpand(struct table *tp, size_t nsize)
|
||||
struct tbl *tblp, **pp;
|
||||
struct tbl **ntblp, **otblp = tp->tbls;
|
||||
|
||||
ntblp = alloc(nsize * sizeof(struct tbl *), tp->areap);
|
||||
ntblp = alloc2(nsize, sizeof(struct tbl *), tp->areap);
|
||||
for (i = 0; i < nsize; i++)
|
||||
ntblp[i] = NULL;
|
||||
tp->size = nsize;
|
||||
@ -1392,7 +1393,7 @@ struct tbl *
|
||||
ktenter(struct table *tp, const char *n, uint32_t h)
|
||||
{
|
||||
struct tbl **pp, *p;
|
||||
int len;
|
||||
size_t len;
|
||||
|
||||
if (tp->size == 0)
|
||||
texpand(tp, INIT_TBLS);
|
||||
@ -1407,8 +1408,9 @@ ktenter(struct table *tp, const char *n, uint32_t h)
|
||||
}
|
||||
|
||||
/* create new tbl entry */
|
||||
len = strlen(n) + 1;
|
||||
p = alloc(offsetof(struct tbl, name[0]) + len, tp->areap);
|
||||
len = strlen(n);
|
||||
checkoktoadd(len, offsetof(struct tbl, name[0]) + 1);
|
||||
p = alloc(offsetof(struct tbl, name[0]) + ++len, tp->areap);
|
||||
p->flag = 0;
|
||||
p->type = 0;
|
||||
p->areap = tp->areap;
|
||||
@ -1456,7 +1458,8 @@ ktsort(struct table *tp)
|
||||
size_t i;
|
||||
struct tbl **p, **sp, **dp;
|
||||
|
||||
p = alloc((tp->size + 1) * sizeof(struct tbl *), ATEMP);
|
||||
/* tp->size + 1 will not overflow */
|
||||
p = alloc2(tp->size + 1, sizeof(struct tbl *), ATEMP);
|
||||
sp = tp->tbls; /* source */
|
||||
dp = p; /* dest */
|
||||
i = (size_t)tp->size;
|
||||
|
38
misc.c
38
misc.c
@ -29,7 +29,7 @@
|
||||
#include <grp.h>
|
||||
#endif
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.146 2010/09/14 21:15:10 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.147 2010/09/14 21:26:15 tg Exp $");
|
||||
|
||||
unsigned char chtypes[UCHAR_MAX + 1]; /* type bits for unsigned char */
|
||||
|
||||
@ -45,6 +45,25 @@ static const unsigned char *cclass(const unsigned char *, int);
|
||||
static void chvt(const char *);
|
||||
#endif
|
||||
|
||||
#ifdef SETUID_CAN_FAIL_WITH_EAGAIN
|
||||
/* we don't need to check for other codes, EPERM won't happen */
|
||||
#define DO_SETUID(func, argvec) do { \
|
||||
bool messaged = false; \
|
||||
\
|
||||
while (/* CONSTCOND */ 1) \
|
||||
if (!(func argvec) || errno != EAGAIN) \
|
||||
break; \
|
||||
else if (!messaged) { \
|
||||
warningf(true, "%s failed with EAGAIN," \
|
||||
" probably due to a too low process" \
|
||||
" limit; retrying infinitely", #func); \
|
||||
messaged = true; \
|
||||
} \
|
||||
} while (/* CONSTCOND */ 0)
|
||||
#else
|
||||
#define DO_SETUID(func, argvec) func argvec
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Fast character classes
|
||||
*/
|
||||
@ -82,12 +101,15 @@ initctypes(void)
|
||||
|
||||
/* called from XcheckN() to grow buffer */
|
||||
char *
|
||||
Xcheck_grow_(XString *xsp, const char *xp, unsigned int more)
|
||||
Xcheck_grow_(XString *xsp, const char *xp, size_t more)
|
||||
{
|
||||
const char *old_beg = xsp->beg;
|
||||
|
||||
xsp->len += more > xsp->len ? more : xsp->len;
|
||||
xsp->beg = aresize(xsp->beg, xsp->len + 8, xsp->areap);
|
||||
if (more < xsp->len)
|
||||
more = xsp->len;
|
||||
/* (xsp->len + X_EXTRA) never overflows */
|
||||
checkoktoadd(more, xsp->len + X_EXTRA);
|
||||
xsp->beg = aresize(xsp->beg, (xsp->len += more) + X_EXTRA, xsp->areap);
|
||||
xsp->end = xsp->beg + xsp->len;
|
||||
return (xsp->beg + (xp - old_beg));
|
||||
}
|
||||
@ -222,14 +244,16 @@ change_flag(enum sh_flag f, int what, unsigned int newval)
|
||||
#if HAVE_SETRESUGID
|
||||
gid_t kshegid = getgid();
|
||||
|
||||
setresgid(kshegid, kshegid, kshegid);
|
||||
DO_SETUID(setresgid, (kshegid, kshegid, kshegid));
|
||||
#if HAVE_SETGROUPS
|
||||
/* setgroups doesn't EAGAIN on Linux */
|
||||
setgroups(1, &kshegid);
|
||||
#endif
|
||||
setresuid(ksheuid, ksheuid, ksheuid);
|
||||
DO_SETUID(setresuid, (ksheuid, ksheuid, ksheuid));
|
||||
#else
|
||||
/* seteuid, setegid, setgid don't EAGAIN on Linux */
|
||||
seteuid(ksheuid = kshuid = getuid());
|
||||
setuid(ksheuid);
|
||||
DO_SETUID(setuid, (ksheuid));
|
||||
setegid(kshegid = kshgid = getgid());
|
||||
setgid(kshegid);
|
||||
#endif
|
||||
|
44
setmode.c
44
setmode.c
@ -33,14 +33,10 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(HAVE_CONFIG_H) && (HAVE_CONFIG_H != 0)
|
||||
/* usually when packaged with third-party software */
|
||||
#ifdef CONFIG_H_FILENAME
|
||||
#include CONFIG_H_FILENAME
|
||||
#ifdef IN_MKSH
|
||||
#include "sh.h"
|
||||
#undef SETMODE_DEBUG
|
||||
#else
|
||||
#include "config.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@ -55,20 +51,36 @@
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
__SCCSID("@(#)setmode.c 8.2 (Berkeley) 3/25/94");
|
||||
__RCSID("$MirOS: src/bin/mksh/setmode.c,v 1.14 2009/06/10 18:12:48 tg Rel $");
|
||||
__RCSID("$miros: src/lib/libc/gen/setmode.c,v 1.12 2009/06/10 18:12:42 tg Exp $");
|
||||
#endif
|
||||
|
||||
__SCCSID("@(#)setmode.c 8.2 (Berkeley) 3/25/94");
|
||||
__RCSID("$MirOS: src/bin/mksh/setmode.c,v 1.15 2010/09/14 21:26:16 tg Exp $");
|
||||
__RCSID("$miros: src/lib/libc/gen/setmode.c,v 1.14 2010/09/14 21:26:04 tg Exp $");
|
||||
|
||||
#ifdef IN_MKSH
|
||||
|
||||
/* for mksh */
|
||||
#ifdef ksh_isdigit
|
||||
#undef isdigit
|
||||
#define isdigit ksh_isdigit
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifndef S_ISTXT
|
||||
#define S_ISTXT 0001000
|
||||
#endif
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
#ifdef SIZE_T_MAX
|
||||
#define SIZE_MAX SIZE_T_MAX
|
||||
#else
|
||||
#define SIZE_MAX ((size_t)-1)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define SET_LEN 6 /* initial # of bitcmd struct to malloc */
|
||||
#define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */
|
||||
|
||||
@ -165,12 +177,15 @@ getmode(const void *bbox, mode_t omode)
|
||||
}
|
||||
}
|
||||
|
||||
#define notoktomul(a, b) ((a) && (b) && (SIZE_MAX / (a) < (b)))
|
||||
|
||||
#define ADDCMD(a, b, c, d) \
|
||||
if (set >= endset) { \
|
||||
BITCMD *newset; \
|
||||
setlen += SET_LEN_INCR; \
|
||||
newset = realloc(saveset, sizeof(BITCMD) * setlen); \
|
||||
if (newset == NULL) { \
|
||||
if (notoktomul(setlen, sizeof(BITCMD)) || \
|
||||
(newset = realloc(saveset, setlen * \
|
||||
sizeof(BITCMD))) == NULL) { \
|
||||
free(saveset); \
|
||||
return (NULL); \
|
||||
} \
|
||||
@ -210,7 +225,8 @@ setmode(const char *p)
|
||||
|
||||
setlen = SET_LEN + 2;
|
||||
|
||||
if ((set = calloc(sizeof(BITCMD), setlen)) == NULL)
|
||||
if (notoktomul(setlen, sizeof(BITCMD)) ||
|
||||
(set = malloc(setlen * sizeof(BITCMD))) == NULL)
|
||||
return (NULL);
|
||||
saveset = set;
|
||||
endset = set + (setlen - 2);
|
||||
|
36
sh.h
36
sh.h
@ -154,9 +154,9 @@
|
||||
#endif
|
||||
|
||||
#ifdef EXTERN
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.413 2010/09/14 21:15:11 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.414 2010/09/14 21:26:16 tg Exp $");
|
||||
#endif
|
||||
#define MKSH_VERSION "R39 2010/09/05"
|
||||
#define MKSH_VERSION "R39 2010/09/14"
|
||||
|
||||
#ifndef MKSH_INCLUDES_ONLY
|
||||
|
||||
@ -630,10 +630,11 @@ extern const struct shoption options[];
|
||||
/* null value for variable; comparision pointer for unset */
|
||||
EXTERN char null[] I__("");
|
||||
/* helpers for string pooling */
|
||||
#define T_synerr "syntax error"
|
||||
EXTERN const char r_fc_e_[] I__("r=fc -e -");
|
||||
#define fc_e_ (r_fc_e_ + 2) /* "fc -e -" */
|
||||
#define fc_e_n 7 /* strlen(fc_e_) */
|
||||
EXTERN const char T_intovfl[] I__("integer overflow %lu %c %lu prevented");
|
||||
EXTERN const char T_synerr[] I__("syntax error");
|
||||
EXTERN const char T_r_fc_e_[] I__("r=fc -e -");
|
||||
#define T_fc_e_ (T_r_fc_e_ + 2) /* "fc -e -" */
|
||||
#define Tn_fc_e_ 7 /* strlen(T_fc_e_) */
|
||||
EXTERN const char T_local_typeset[] I__("local=typeset");
|
||||
#define T__typeset (T_local_typeset + 5) /* "=typeset" */
|
||||
#define T_typeset (T_local_typeset + 6) /* "typeset" */
|
||||
@ -1223,7 +1224,7 @@ typedef char *XStringP;
|
||||
#define XcheckN(xs, xp, n) do { \
|
||||
int more = ((xp) + (n)) - (xs).end; \
|
||||
if (more > 0) \
|
||||
(xp) = Xcheck_grow_(&(xs), (xp), more); \
|
||||
(xp) = Xcheck_grow_(&(xs), (xp), (size_t)more); \
|
||||
} while (/* CONSTCOND */ 0)
|
||||
|
||||
/* check for overflow, expand string */
|
||||
@ -1244,7 +1245,7 @@ typedef char *XStringP;
|
||||
#define Xsavepos(xs, xp) ((xp) - (xs).beg)
|
||||
#define Xrestpos(xs, xp, n) ((xs).beg + (n))
|
||||
|
||||
char *Xcheck_grow_(XString *, const char *, unsigned int);
|
||||
char *Xcheck_grow_(XString *, const char *, size_t);
|
||||
|
||||
/*
|
||||
* expandable vector of generic pointers
|
||||
@ -1257,7 +1258,7 @@ typedef struct XPtrV {
|
||||
|
||||
#define XPinit(x, n) do { \
|
||||
void **vp__; \
|
||||
vp__ = alloc((n) * sizeof(void *), ATEMP); \
|
||||
vp__ = alloc2((n), sizeof(void *), ATEMP); \
|
||||
(x).cur = (x).beg = vp__; \
|
||||
(x).end = vp__ + (n); \
|
||||
} while (/* CONSTCOND */ 0)
|
||||
@ -1265,8 +1266,8 @@ typedef struct XPtrV {
|
||||
#define XPput(x, p) do { \
|
||||
if ((x).cur >= (x).end) { \
|
||||
size_t n = XPsize(x); \
|
||||
(x).beg = aresize((x).beg, \
|
||||
n * 2 * sizeof(void *), ATEMP); \
|
||||
(x).beg = aresize2((x).beg, \
|
||||
n, 2 * sizeof(void *), ATEMP); \
|
||||
(x).cur = (x).beg + n; \
|
||||
(x).end = (x).cur + n; \
|
||||
} \
|
||||
@ -1275,7 +1276,7 @@ typedef struct XPtrV {
|
||||
|
||||
#define XPptrv(x) ((x).beg)
|
||||
#define XPsize(x) ((x).cur - (x).beg)
|
||||
#define XPclose(x) aresize((x).beg, XPsize(x) * sizeof(void *), ATEMP)
|
||||
#define XPclose(x) aresize2((x).beg, XPsize(x), sizeof(void *), ATEMP)
|
||||
#define XPfree(x) afree((x).beg, ATEMP)
|
||||
|
||||
#define IDENT 64
|
||||
@ -1392,12 +1393,21 @@ EXTERN int histsize; /* history size */
|
||||
/* user and system time of last j_waitjed job */
|
||||
EXTERN struct timeval j_usrtime, j_systime;
|
||||
|
||||
#define notoktoadd(val, cnst) ((val) > (SIZE_MAX - (cnst)))
|
||||
#define checkoktoadd(val, cnst) do { \
|
||||
if (notoktoadd((val), (cnst))) \
|
||||
internal_errorf(T_intovfl, (unsigned long)(val), \
|
||||
'+', (unsigned long)(cnst)); \
|
||||
} while (/* CONSTCOND */ 0)
|
||||
|
||||
/* lalloc.c */
|
||||
void ainit(Area *);
|
||||
void afreeall(Area *);
|
||||
/* these cannot fail and can take NULL (not for ap) */
|
||||
#define alloc(n, ap) aresize(NULL, (n), (ap))
|
||||
#define alloc(n, ap) aresize(NULL, (n), (ap))
|
||||
#define alloc2(m, n, ap) aresize2(NULL, (m), (n), (ap))
|
||||
void *aresize(void *, size_t, Area *);
|
||||
void *aresize2(void *, size_t, size_t, Area *);
|
||||
void afree(void *, Area *); /* can take NULL */
|
||||
/* edit.c */
|
||||
#ifndef MKSH_SMALL
|
||||
|
13
shf.c
13
shf.c
@ -24,7 +24,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.39 2010/08/28 20:22:23 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/shf.c,v 1.40 2010/09/14 21:26:17 tg Exp $");
|
||||
|
||||
/* flags to shf_emptybuf() */
|
||||
#define EB_READSW 0x01 /* about to switch to reading */
|
||||
@ -47,7 +47,8 @@ struct shf *
|
||||
shf_open(const char *name, int oflags, int mode, int sflags)
|
||||
{
|
||||
struct shf *shf;
|
||||
int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
|
||||
int bsize = /* at most 512 */
|
||||
sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
|
||||
int fd;
|
||||
|
||||
/* Done before open so if alloca fails, fd won't be lost. */
|
||||
@ -85,7 +86,8 @@ shf_open(const char *name, int oflags, int mode, int sflags)
|
||||
struct shf *
|
||||
shf_fdopen(int fd, int sflags, struct shf *shf)
|
||||
{
|
||||
int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
|
||||
int bsize = /* at most 512 */
|
||||
sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
|
||||
|
||||
/* use fcntl() to figure out correct read/write flags */
|
||||
if (sflags & SHF_GETFL) {
|
||||
@ -142,7 +144,8 @@ shf_fdopen(int fd, int sflags, struct shf *shf)
|
||||
struct shf *
|
||||
shf_reopen(int fd, int sflags, struct shf *shf)
|
||||
{
|
||||
int bsize = sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
|
||||
int bsize = /* at most 512 */
|
||||
sflags & SHF_UNBUF ? (sflags & SHF_RD ? 1 : 0) : SHF_BSIZE;
|
||||
|
||||
/* use fcntl() to figure out correct read/write flags */
|
||||
if (sflags & SHF_GETFL) {
|
||||
@ -344,7 +347,7 @@ shf_emptybuf(struct shf *shf, int flags)
|
||||
!(shf->flags & SHF_ALLOCB))
|
||||
return (EOF);
|
||||
/* allocate more space for buffer */
|
||||
nbuf = aresize(shf->buf, 2 * shf->wbsize, shf->areap);
|
||||
nbuf = aresize2(shf->buf, 2, shf->wbsize, shf->areap);
|
||||
shf->rp = nbuf + (shf->rp - shf->buf);
|
||||
shf->wp = nbuf + (shf->wp - shf->buf);
|
||||
shf->rbsize += shf->wbsize;
|
||||
|
10
syn.c
10
syn.c
@ -22,7 +22,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.51 2010/08/28 20:22:23 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.52 2010/09/14 21:26:18 tg Exp $");
|
||||
|
||||
struct nesting_state {
|
||||
int start_token; /* token than began nesting (eg, FOR) */
|
||||
@ -231,7 +231,8 @@ get_command(int cf)
|
||||
XPtrV args, vars;
|
||||
struct nesting_state old_nesting;
|
||||
|
||||
iops = alloc((NUFILE + 1) * sizeof(struct ioword *), ATEMP);
|
||||
/* NUFILE is small enough to leave this addition unchecked */
|
||||
iops = alloc2((NUFILE + 1), sizeof(struct ioword *), ATEMP);
|
||||
XPinit(args, 16);
|
||||
XPinit(vars, 16);
|
||||
|
||||
@ -476,7 +477,7 @@ get_command(int cf)
|
||||
t->ioact = NULL;
|
||||
} else {
|
||||
iops[iopn++] = NULL;
|
||||
iops = aresize(iops, iopn * sizeof(struct ioword *), ATEMP);
|
||||
iops = aresize2(iops, iopn, sizeof(struct ioword *), ATEMP);
|
||||
t->ioact = iops;
|
||||
}
|
||||
|
||||
@ -656,12 +657,13 @@ function_body(char *name,
|
||||
if ((t->left = get_command(CONTIN)) == NULL) {
|
||||
char *tv;
|
||||
/*
|
||||
* Probably something like foo() followed by eof or ;.
|
||||
* Probably something like foo() followed by EOF or ';'.
|
||||
* This is accepted by sh and ksh88.
|
||||
* To make "typeset -f foo" work reliably (so its output can
|
||||
* be used as input), we pretend there is a colon here.
|
||||
*/
|
||||
t->left = newtp(TCOM);
|
||||
/* (2 * sizeof(char *)) is small enough */
|
||||
t->left->args = alloc(2 * sizeof(char *), ATEMP);
|
||||
t->left->args[0] = tv = alloc(3, ATEMP);
|
||||
tv[0] = CHAR;
|
||||
|
8
tree.c
8
tree.c
@ -22,7 +22,7 @@
|
||||
|
||||
#include "sh.h"
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.31 2010/08/28 20:22:24 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/tree.c,v 1.32 2010/09/14 21:26:19 tg Exp $");
|
||||
|
||||
#define INDENT 4
|
||||
|
||||
@ -454,7 +454,7 @@ tcopy(struct op *t, Area *ap)
|
||||
else {
|
||||
for (tw = (const char **)t->vars; *tw++ != NULL; )
|
||||
;
|
||||
rw = r->vars = alloc((tw - (const char **)t->vars + 1) *
|
||||
rw = r->vars = alloc2(tw - (const char **)t->vars + 1,
|
||||
sizeof(*tw), ap);
|
||||
for (tw = (const char **)t->vars; *tw != NULL; )
|
||||
*rw++ = wdcopy(*tw++, ap);
|
||||
@ -466,7 +466,7 @@ tcopy(struct op *t, Area *ap)
|
||||
else {
|
||||
for (tw = t->args; *tw++ != NULL; )
|
||||
;
|
||||
r->args = (const char **)(rw = alloc((tw - t->args + 1) *
|
||||
r->args = (const char **)(rw = alloc2(tw - t->args + 1,
|
||||
sizeof(*tw), ap));
|
||||
for (tw = t->args; *tw != NULL; )
|
||||
*rw++ = wdcopy(*tw++, ap);
|
||||
@ -636,7 +636,7 @@ iocopy(struct ioword **iow, Area *ap)
|
||||
|
||||
for (ior = iow; *ior++ != NULL; )
|
||||
;
|
||||
ior = alloc((ior - iow + 1) * sizeof(struct ioword *), ap);
|
||||
ior = alloc2(ior - iow + 1, sizeof(struct ioword *), ap);
|
||||
|
||||
for (i = 0; iow[i] != NULL; i++) {
|
||||
struct ioword *p, *q;
|
||||
|
14
var.c
14
var.c
@ -26,7 +26,7 @@
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.112 2010/08/28 20:22:24 tg Exp $");
|
||||
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.113 2010/09/14 21:26:19 tg Exp $");
|
||||
|
||||
/*
|
||||
* Variables
|
||||
@ -649,10 +649,13 @@ exportprep(struct tbl *vp, const char *val)
|
||||
{
|
||||
char *xp;
|
||||
char *op = (vp->flag&ALLOC) ? vp->val.s : NULL;
|
||||
int namelen = strlen(vp->name);
|
||||
int vallen = strlen(val) + 1;
|
||||
size_t namelen, vallen;
|
||||
|
||||
namelen = strlen(vp->name);
|
||||
vallen = strlen(val) + 1;
|
||||
|
||||
vp->flag |= ALLOC;
|
||||
/* since name+val are both in memory this can go unchecked */
|
||||
xp = alloc(namelen + 1 + vallen, vp->areap);
|
||||
memcpy(vp->val.s = xp, vp->name, namelen);
|
||||
xp += namelen;
|
||||
@ -1317,9 +1320,10 @@ arraysearch(struct tbl *vp, uint32_t val)
|
||||
news = curr;
|
||||
} else
|
||||
news = NULL;
|
||||
len = strlen(vp->name) + 1;
|
||||
if (!news) {
|
||||
news = alloc(offsetof(struct tbl, name[0]) + len, vp->areap);
|
||||
len = strlen(vp->name);
|
||||
checkoktoadd(len, 1 + offsetof(struct tbl, name[0]));
|
||||
news = alloc(offsetof(struct tbl, name[0]) + ++len, vp->areap);
|
||||
memcpy(news->name, vp->name, len);
|
||||
}
|
||||
news->flag = (vp->flag & ~(ALLOC|DEFINED|ISSET|SPECIAL)) | AINDEX;
|
||||
|
Loading…
x
Reference in New Issue
Block a user