fstat(2) after open(2) for set -C case when initial stat(2) was !S_ISREG
to fix race condition as suggested by jilles
This commit is contained in:
parent
c56d848a10
commit
4059e105a2
6
check.t
6
check.t
@ -1,4 +1,4 @@
|
|||||||
# $MirOS: src/bin/mksh/check.t,v 1.716 2015/12/12 23:31:15 tg Exp $
|
# $MirOS: src/bin/mksh/check.t,v 1.717 2015/12/31 21:03:44 tg Exp $
|
||||||
# -*- mode: sh -*-
|
# -*- mode: sh -*-
|
||||||
#-
|
#-
|
||||||
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
# Copyright © 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
|
||||||
@ -30,7 +30,7 @@
|
|||||||
# (2013/12/02 20:39:44) http://openbsd.cs.toronto.edu/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
|
# (2013/12/02 20:39:44) http://openbsd.cs.toronto.edu/cgi-bin/cvsweb/src/regress/bin/ksh/?sortby=date
|
||||||
|
|
||||||
expected-stdout:
|
expected-stdout:
|
||||||
@(#)MIRBSD KSH R52 2015/12/12
|
@(#)MIRBSD KSH R52 2015/12/31
|
||||||
description:
|
description:
|
||||||
Check version of shell.
|
Check version of shell.
|
||||||
stdin:
|
stdin:
|
||||||
@ -39,7 +39,7 @@ name: KSH_VERSION
|
|||||||
category: shell:legacy-no
|
category: shell:legacy-no
|
||||||
---
|
---
|
||||||
expected-stdout:
|
expected-stdout:
|
||||||
@(#)LEGACY KSH R52 2015/12/12
|
@(#)LEGACY KSH R52 2015/12/31
|
||||||
description:
|
description:
|
||||||
Check version of legacy shell.
|
Check version of legacy shell.
|
||||||
stdin:
|
stdin:
|
||||||
|
38
exec.c
38
exec.c
@ -23,7 +23,7 @@
|
|||||||
|
|
||||||
#include "sh.h"
|
#include "sh.h"
|
||||||
|
|
||||||
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.169 2015/12/31 12:58:43 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.170 2015/12/31 21:03:47 tg Exp $");
|
||||||
|
|
||||||
#ifndef MKSH_DEFAULT_EXECSHELL
|
#ifndef MKSH_DEFAULT_EXECSHELL
|
||||||
#define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh"
|
#define MKSH_DEFAULT_EXECSHELL MKSH_UNIXROOT "/bin/sh"
|
||||||
@ -1363,7 +1363,7 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
|||||||
int u = -1;
|
int u = -1;
|
||||||
char *cp = iop->ioname;
|
char *cp = iop->ioname;
|
||||||
int iotype = iop->ioflag & IOTYPE;
|
int iotype = iop->ioflag & IOTYPE;
|
||||||
bool do_open = true, do_close = false;
|
bool do_open = true, do_close = false, do_fstat = false;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
struct ioword iotmp;
|
struct ioword iotmp;
|
||||||
struct stat statb;
|
struct stat statb;
|
||||||
@ -1392,14 +1392,27 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case IOWRITE:
|
case IOWRITE:
|
||||||
flags = O_WRONLY | O_CREAT | O_TRUNC;
|
if (Flag(FNOCLOBBER) && !(iop->ioflag & IOCLOB)) {
|
||||||
|
/* >file under set -C */
|
||||||
|
if (stat(cp, &statb)) {
|
||||||
|
/* nonexistent file */
|
||||||
|
flags = O_WRONLY | O_CREAT | O_EXCL;
|
||||||
|
} else if (S_ISREG(statb.st_mode)) {
|
||||||
|
/* regular file, refuse clobbering */
|
||||||
|
goto clobber_refused;
|
||||||
|
} else {
|
||||||
/*
|
/*
|
||||||
* The stat() is here to allow redirections to
|
* allow redirections to things
|
||||||
* things like /dev/null without error.
|
* like /dev/null without error
|
||||||
*/
|
*/
|
||||||
if (Flag(FNOCLOBBER) && !(iop->ioflag & IOCLOB) &&
|
flags = O_WRONLY;
|
||||||
(stat(cp, &statb) < 0 || S_ISREG(statb.st_mode)))
|
/* but check again after opening */
|
||||||
flags |= O_EXCL;
|
do_fstat = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* >|file or set +C */
|
||||||
|
flags = O_WRONLY | O_CREAT | O_TRUNC;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IORDWR:
|
case IORDWR:
|
||||||
@ -1444,6 +1457,15 @@ iosetup(struct ioword *iop, struct tbl *tp)
|
|||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
u = binopen3(cp, flags, 0666);
|
u = binopen3(cp, flags, 0666);
|
||||||
|
if (do_fstat && u >= 0) {
|
||||||
|
/* prevent race conditions */
|
||||||
|
if (fstat(u, &statb) || S_ISREG(statb.st_mode)) {
|
||||||
|
close(u);
|
||||||
|
clobber_refused:
|
||||||
|
u = -1;
|
||||||
|
errno = EEXIST;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (u < 0) {
|
if (u < 0) {
|
||||||
/* herein() may already have printed message */
|
/* herein() may already have printed message */
|
||||||
|
4
sh.h
4
sh.h
@ -175,9 +175,9 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef EXTERN
|
#ifdef EXTERN
|
||||||
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.751 2015/12/12 22:25:15 tg Exp $");
|
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.752 2015/12/31 21:03:47 tg Exp $");
|
||||||
#endif
|
#endif
|
||||||
#define MKSH_VERSION "R52 2015/12/12"
|
#define MKSH_VERSION "R52 2015/12/31"
|
||||||
|
|
||||||
/* arithmetic types: C implementation */
|
/* arithmetic types: C implementation */
|
||||||
#if !HAVE_CAN_INTTYPES
|
#if !HAVE_CAN_INTTYPES
|
||||||
|
Loading…
x
Reference in New Issue
Block a user