From 0739fa74a0a5b987233a046e258fe16f2dfd7352 Mon Sep 17 00:00:00 2001 From: tg Date: Sat, 2 Jul 2011 17:57:41 +0000 Subject: [PATCH] address "env RANDOM=1=2=3 mksh" DoS by integrifying more --- check.t | 4 ++-- main.c | 37 +++++++++++++++++-------------------- sh.h | 5 +++-- var.c | 50 +++++++++++++++++++++++--------------------------- 4 files changed, 45 insertions(+), 51 deletions(-) diff --git a/check.t b/check.t index 24cf6b5..c7f943e 100644 --- a/check.t +++ b/check.t @@ -1,4 +1,4 @@ -# $MirOS: src/bin/mksh/check.t,v 1.469 2011/06/30 13:48:09 tg Exp $ +# $MirOS: src/bin/mksh/check.t,v 1.470 2011/07/02 17:57:37 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 R40 2011/06/30 + @(#)MIRBSD KSH R40 2011/07/02 description: Check version of shell. stdin: diff --git a/main.c b/main.c index e1ccd55..0ad9d9b 100644 --- a/main.c +++ b/main.c @@ -33,7 +33,7 @@ #include #endif -__RCSID("$MirOS: src/bin/mksh/main.c,v 1.193 2011/06/05 19:58:18 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/main.c,v 1.194 2011/07/02 17:57:39 tg Exp $"); extern char **environ; @@ -61,9 +61,7 @@ static const char initsubs[] = static const char *initcoms[] = { T_typeset, "-r", initvsn, NULL, T_typeset, "-x", "HOME", "PATH", "RANDOM", "SHELL", NULL, - T_typeset, "-i10", "COLUMNS", "KSHEGID", "KSHGID", "KSHUID", "LINES", - "OPTIND", "PGRP", "PPID", "RANDOM", "SECONDS", "TMOUT", "USER_ID", - NULL, + T_typeset, "-i10", "SECONDS", "TMOUT", NULL, T_alias, "integer=typeset -i", T_local_typeset, @@ -92,6 +90,10 @@ static const char *initcoms[] = { NULL }; +static const char *restr_com[] = { + T_typeset, "-r", "PATH", "ENV", "SHELL", NULL +}; + static int initio_done; /* top-level parsing and execution environment */ @@ -328,9 +330,9 @@ main(int argc, const char *argv[]) while (*wp != NULL) wp++; } - setint(global("COLUMNS"), 0); - setint(global("LINES"), 0); - setint(global("OPTIND"), 1); + setint_n(global("COLUMNS"), 0); + setint_n(global("LINES"), 0); + setint_n(global("OPTIND"), 1); kshuid = getuid(); kshgid = getgid(); @@ -343,21 +345,21 @@ main(int argc, const char *argv[]) (!ksheuid && !strchr(str_val(vp), '#'))) /* setstr can't fail here */ setstr(vp, safe_prompt, KSH_RETURN_ERROR); - setint((vp = global("PGRP")), (mksh_uari_t)kshpgrp); + setint_n((vp = global("PGRP")), (mksh_uari_t)kshpgrp); vp->flag |= INT_U; - setint((vp = global("PPID")), (mksh_uari_t)kshppid); + setint_n((vp = global("PPID")), (mksh_uari_t)kshppid); vp->flag |= INT_U; - setint((vp = global("USER_ID")), (mksh_uari_t)ksheuid); + setint_n((vp = global("USER_ID")), (mksh_uari_t)ksheuid); vp->flag |= INT_U; - setint((vp = global("KSHUID")), (mksh_uari_t)kshuid); + setint_n((vp = global("KSHUID")), (mksh_uari_t)kshuid); vp->flag |= INT_U; - setint((vp = global("KSHEGID")), (mksh_uari_t)kshegid); + setint_n((vp = global("KSHEGID")), (mksh_uari_t)kshegid); vp->flag |= INT_U; - setint((vp = global("KSHGID")), (mksh_uari_t)kshgid); + setint_n((vp = global("KSHGID")), (mksh_uari_t)kshgid); vp->flag |= INT_U; - setint((vp = global("RANDOM")), rndsetup()); + setint_n((vp = global("RANDOM")), rndsetup()); vp->flag |= INT_U; - setint((vp_pipest = global("PIPESTATUS")), 0); + setint_n((vp_pipest = global("PIPESTATUS")), 0); /* Set this before parsing arguments */ Flag(FPRIVILEGED) = kshuid != ksheuid || kshgid != kshegid; @@ -540,11 +542,6 @@ main(int argc, const char *argv[]) } if (restricted) { - static const char *restr_com[] = { - T_typeset, "-r", "PATH", - "ENV", "SHELL", - NULL - }; shcomexec(restr_com); /* After typeset command... */ Flag(FRESTRICTED) = 1; diff --git a/sh.h b/sh.h index dc0b3e5..479da7f 100644 --- a/sh.h +++ b/sh.h @@ -151,9 +151,9 @@ #endif #ifdef EXTERN -__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.480 2011/06/30 13:48:13 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.481 2011/07/02 17:57:40 tg Exp $"); #endif -#define MKSH_VERSION "R40 2011/06/30" +#define MKSH_VERSION "R40 2011/07/02" #ifndef MKSH_INCLUDES_ONLY @@ -1796,6 +1796,7 @@ char *str_val(struct tbl *); int setstr(struct tbl *, const char *, int); struct tbl *setint_v(struct tbl *, struct tbl *, bool); void setint(struct tbl *, mksh_ari_t); +void setint_n(struct tbl *, mksh_ari_t); struct tbl *typeset(const char *, Tflag, Tflag, int, int) MKSH_A_NONNULL((__nonnull__ (1))); void unset(struct tbl *, int); diff --git a/var.c b/var.c index f7eccf9..90d1702 100644 --- a/var.c +++ b/var.c @@ -26,7 +26,7 @@ #include #endif -__RCSID("$MirOS: src/bin/mksh/var.c,v 1.126 2011/06/21 21:50:26 tg Exp $"); +__RCSID("$MirOS: src/bin/mksh/var.c,v 1.127 2011/07/02 17:57:41 tg Exp $"); /*- * Variables @@ -50,7 +50,6 @@ static void getspec(struct tbl *); static void setspec(struct tbl *); static void unsetspec(struct tbl *); static int getint(struct tbl *, mksh_ari_t *, bool); -static mksh_ari_t intval(struct tbl *); static const char *array_index_calc(const char *, bool *, uint32_t *); /* @@ -401,20 +400,6 @@ str_val(struct tbl *vp) return (s); } -/* get variable integer value, with error checking */ -static mksh_ari_t -intval(struct tbl *vp) -{ - mksh_ari_t num; - int base; - - base = getint(vp, &num, false); - if (base == -1) - /* XXX check calls - is error here ok by POSIX? */ - errorf("%s: %s", str_val(vp), "bad number"); - return (num); -} - /* set variable to string value */ int setstr(struct tbl *vq, const char *s, int error_ok) @@ -571,19 +556,26 @@ setint_v(struct tbl *vq, struct tbl *vp, bool arith) if ((base = getint(vp, &num, arith)) == -1) return (NULL); + setint_n(vq, num); + if (vq->type == 0) + /* default base */ + vq->type = base; + return (vq); +} + +/* convert variable vq to integer variable, setting its value to num */ +void +setint_n(struct tbl *vq, mksh_ari_t num) +{ if (!(vq->flag & INTEGER) && (vq->flag & ALLOC)) { vq->flag &= ~ALLOC; vq->type = 0; afree(vq->val.s, vq->areap); } vq->val.i = num; - if (vq->type == 0) - /* default base */ - vq->type = base; vq->flag |= ISSET|INTEGER; if (vq->flag&SPECIAL) setspec(vq); - return (vq); } static char * @@ -1140,7 +1132,7 @@ getspec(struct tbl *vp) return; } vp->flag &= ~SPECIAL; - setint(vp, i); + setint_n(vp, i); vp->flag |= SPECIAL; } @@ -1187,11 +1179,6 @@ setspec(struct tbl *vp) sethistfile(str_val(vp)); return; #endif - case V_TMOUT: - /* AT&T ksh seems to do this (only listen if integer) */ - if (vp->flag & INTEGER) - ksh_tmout = vp->val.i >= 0 ? vp->val.i : 0; - return; /* common sub-cases */ case V_OPTIND: @@ -1201,8 +1188,14 @@ setspec(struct tbl *vp) case V_RANDOM: case V_SECONDS: case V_LINENO: + case V_TMOUT: vp->flag &= ~SPECIAL; - i = intval(vp); + if (getint(vp, &i, false) == -1) { + s = str_val(vp); + if (st != V_RANDOM) + errorf("%s: %s: %s", vp->name, "bad number", s); + i = hash(s); + } vp->flag |= SPECIAL; break; default: @@ -1246,6 +1239,9 @@ setspec(struct tbl *vp) /* The -1 is because line numbering starts at 1. */ user_lineno = (unsigned int)i - current_lineno - 1; break; + case V_TMOUT: + ksh_tmout = i >= 0 ? i : 0; + break; } }