Skip to content

Commit 1632949

Browse files
JohnoKingMcDutchie
authored andcommitted
Fix handling of close-on-exec bit (#860)
This commit's main purpose is to robustify ksh93's handling of the close-on-exec bit. Much of this code is based on groundwork laid out in ksh93v-, though many other changes were made beyond that since the 93v- syscall intercepts were not backported. - Avoid needlessly calling fcntl twice if F_DUPFD_CLOEXEC is available. - Added support for F_DUPFD_CLOEXEC to sh_fcntl. - Incidentally fixed file descriptor leakage in histexceptf(). - Added support for close-on-exec to sh_pipe and sh_rpipe, which is implemented via SOCK_CLOEXEC, pipe2(2) and (as a fallback) plain fcntl F_SETFD. - For process substitutions, rather than use another fcntl to undo close-on-exec (like in 93v-), instead add a second argument to sh_pipe and sh_rpipe that can be used to specify whether close-on-exec is wanted. - Added support for O_CLOEXEC to sh_open(). - Made it such that sh_iomovefd preserves the presence or absence of the close-on-exec bit. - The ksh93v- change to make sh_iomovefd return fds >9 broke one of the regression tests, so that was changed to dup to 3 or higher. src/lib/libast/features/lib: - When ksh is compiled on illumos with clang, the libast _lib_select test will fail and subsequently many io.sh test failures then occur. This is caused by the FD_ZERO macro calling memset implicitly, which is invalid in C99. To fix this, a string.h include directive has been added to the feature test.
1 parent f931608 commit 1632949

File tree

16 files changed

+192
-134
lines changed

16 files changed

+192
-134
lines changed

src/cmd/ksh93/bltins/hist.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ int b_hist(int argc,char *argv[], Shbltin_t *context)
206206
errormsg(SH_DICT,ERROR_exit(1),e_create,"");
207207
UNREACHABLE();
208208
}
209-
if((fdo=open(fname,O_CREAT|O_RDWR,S_IRUSR|S_IWUSR)) < 0)
209+
if((fdo=open(fname,O_CREAT|O_RDWR|O_cloexec,S_IRUSR|S_IWUSR)) < 0)
210210
{
211211
errormsg(SH_DICT,ERROR_system(1),e_create,fname);
212212
UNREACHABLE();

src/cmd/ksh93/edit/history.c

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,7 @@ static History_t *hist_ptr;
123123
cp = "unknown";
124124
}
125125
logname = sh_strdup(cp);
126-
if((acctfd=sh_open(acctfile,
127-
O_BINARY|O_WRONLY|O_APPEND|O_CREAT,S_IRUSR|S_IWUSR))>=0 &&
128-
(unsigned)acctfd < 10)
126+
if((acctfd=sh_open(acctfile,O_BINARY|O_WRONLY|O_APPEND|O_CREAT|O_cloexec,S_IRUSR|S_IWUSR))>=0 && acctfd < 10)
129127
{
130128
int n;
131129
if((n = sh_fcntl(acctfd, F_dupfd_cloexec, 10)) >= 0)
@@ -145,8 +143,8 @@ static History_t *hist_ptr;
145143
sfsprintf(newfile,sizeof(newfile),"%.8s%d\0",e_devfdNN,acctfd);
146144
nv_putval(np,newfile,NV_RDONLY);
147145
}
148-
else
149-
fcntl(acctfd,F_SETFD,FD_CLOEXEC);
146+
else if(!(sh.fdstatus[acctfd]&IOCLEX))
147+
sh_fcntl(acctfd,F_SETFD,FD_CLOEXEC);
150148
return 1;
151149
}
152150
#endif /* SHOPT_ACCTFILE */
@@ -156,7 +154,7 @@ static int sh_checkaudit(const char *name, char *logbuf, size_t len)
156154
{
157155
char *cp, *last;
158156
int id1, id2, r=0, n, fd;
159-
if((fd=open(name, O_RDONLY,O_cloexec)) < 0)
157+
if((fd=open(name, O_RDONLY|O_cloexec)) < 0)
160158
return 0;
161159
if((n = read(fd, logbuf,len-1)) < 0)
162160
goto done;
@@ -205,7 +203,7 @@ int sh_histinit(void)
205203
History_t *hp;
206204
char *histname;
207205
char *fname=0;
208-
int histmask, maxlines, hist_start=0;
206+
int histmask, maxlines, hist_start=0, n;
209207
char *cp;
210208
off_t hsize = 0;
211209

@@ -224,13 +222,10 @@ int sh_histinit(void)
224222
cp = path_relative(histname);
225223
if(!histinit)
226224
histmode = S_IRUSR|S_IWUSR;
227-
if((fd=open(cp,O_BINARY|O_APPEND|O_RDWR|O_CREAT|O_cloexec,histmode))>=0)
228-
{
225+
if((fd=sh_open(cp,O_BINARY|O_APPEND|O_RDWR|O_CREAT|O_cloexec,histmode))>=0)
229226
hsize=lseek(fd,0,SEEK_END);
230-
}
231-
if((unsigned)fd < 10)
227+
if(fd > 0 && fd < 10)
232228
{
233-
int n;
234229
if((n=sh_fcntl(fd,F_dupfd_cloexec,10))>=0)
235230
{
236231
sh_close(fd);
@@ -253,13 +248,13 @@ int sh_histinit(void)
253248
{
254249
if(!(fname = pathtmp(NULL,0,0,NULL)))
255250
return 0;
256-
fd = open(fname,O_BINARY|O_APPEND|O_CREAT|O_RDWR,S_IRUSR|S_IWUSR|O_cloexec);
251+
fd = sh_open(fname,O_BINARY|O_APPEND|O_CREAT|O_RDWR|O_cloexec,S_IRUSR|S_IWUSR);
257252
}
258253
}
259254
if(fd<0)
260255
return 0;
261-
/* set the file to close-on-exec */
262-
fcntl(fd,F_SETFD,FD_CLOEXEC);
256+
if(!(sh.fdstatus[fd]&IOCLEX))
257+
sh_fcntl(fd,F_SETFD,FD_CLOEXEC); /* set the file to close-on-exec */
263258
if(cp=nv_getval(HISTSIZE))
264259
{
265260
intmax_t m = strtoll(cp, NULL, 10);
@@ -344,7 +339,6 @@ int sh_histinit(void)
344339
{
345340
if((fd=sh_open(buff,O_BINARY|O_WRONLY|O_APPEND|O_CREAT|O_cloexec,S_IRUSR|S_IWUSR))>=0 && fd < 10)
346341
{
347-
int n;
348342
if((n = sh_fcntl(fd,F_dupfd_cloexec, 10)) >= 0)
349343
{
350344
sh_close(fd);
@@ -354,7 +348,8 @@ int sh_histinit(void)
354348
if(fd>=0)
355349
{
356350
const char *tty;
357-
fcntl(fd,F_SETFD,FD_CLOEXEC);
351+
if(!(sh.fdstatus[fd]&IOCLEX))
352+
sh_fcntl(fd,F_SETFD,FD_CLOEXEC);
358353
tty = ttyname(2);
359354
hp->tty = sh_strdup(tty?tty:"notty");
360355
hp->auditfp = sfnew(NULL,NULL,-1,fd,SFIO_WRITE);
@@ -1125,12 +1120,21 @@ static int hist_exceptf(Sfio_t* fp, int type, void *data, Sfdisc_t *handle)
11251120
return 0;
11261121
/* write failure could be NFS problem, try to reopen */
11271122
sh_close(oldfd=sffileno(fp));
1128-
if((newfd=open(hp->histname,O_BINARY|O_APPEND|O_CREAT|O_RDWR|O_cloexec,S_IRUSR|S_IWUSR)) >= 0)
1123+
if((newfd=sh_open(hp->histname,O_BINARY|O_APPEND|O_CREAT|O_RDWR|O_cloexec,S_IRUSR|S_IWUSR)) >= 0)
11291124
{
1130-
if(sh_fcntl(newfd, F_dupfd_cloexec, oldfd) != oldfd)
1131-
return -1;
1132-
fcntl(oldfd,F_SETFD,FD_CLOEXEC);
1133-
close(newfd);
1125+
if(newfd != oldfd)
1126+
{
1127+
int dupfd = sh_fcntl(newfd, F_dupfd_cloexec, oldfd);
1128+
sh_close(newfd);
1129+
if(dupfd != oldfd)
1130+
{
1131+
if(dupfd > -1)
1132+
sh_close(dupfd);
1133+
return -1;
1134+
}
1135+
}
1136+
if(!(sh.fdstatus[oldfd]&IOCLEX))
1137+
sh_fcntl(oldfd,F_SETFD,FD_CLOEXEC);
11341138
if(lseek(oldfd,0,SEEK_END) < hp->histcnt)
11351139
{
11361140
int index = hp->histind;

src/cmd/ksh93/features/externs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ tst execve_dir_enoexec note{ does execve(3) set errno to ENOEXEC when trying to
219219
{
220220
char dirname[64];
221221
int e;
222-
sprintf(dirname,".dir.%u",(unsigned)getpid());
222+
sprintf(dirname,".dir.%u",(unsigned int)getpid());
223223
mkdir(dirname,0777);
224224
execve(dirname,argv,environ);
225225
e = errno;

src/cmd/ksh93/include/io.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,7 @@ extern void sh_ioinit(void);
7979
extern int sh_iomovefd(int);
8080
extern int sh_iorenumber(int,int);
8181
extern void sh_pclose(int[]);
82-
extern int sh_rpipe(int[]);
82+
extern int sh_rpipe(int[],int);
8383
extern void sh_iorestore(int,int);
8484
extern Sfio_t *sh_iostream(int);
8585
extern int sh_redirect(struct ionod*,int);

src/cmd/ksh93/include/shell.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,7 @@ extern Sfio_t *sh_pathopen(const char*);
468468
extern ssize_t sh_read(int, void*, size_t);
469469
extern ssize_t sh_write(int, const void*, size_t);
470470
extern off_t sh_seek(int, off_t, int);
471-
extern int sh_pipe(int[]);
471+
extern int sh_pipe(int[],int);
472472
extern mode_t sh_umask(mode_t);
473473
extern Shwait_f sh_waitnotify(Shwait_f);
474474
extern Shscope_t *sh_getscope(int,int);
@@ -493,7 +493,6 @@ extern Shell_t sh;
493493
# define close(a) sh_close(a)
494494
# define exit(a) sh_exit(a)
495495
# define fcntl(a,b,c) sh_fcntl(a,b,c)
496-
# define pipe(a) sh_pipe(a)
497496
# define read(a,b,c) sh_read(a,b,c)
498497
# define write(a,b,c) sh_write(a,b,c)
499498
# define umask(a) sh_umask(a)

src/cmd/ksh93/sh/args.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,7 @@ char **sh_argbuild(int *nargs, const struct comnod *comptr,int flag)
714714
}
715715

716716
#if _pipe_socketpair && !_socketpair_devfd
717-
# define sh_pipe(a) sh_rpipe(a)
717+
# define sh_pipe(a,b) sh_rpipe(a,b)
718718
#endif
719719

720720
struct argnod *sh_argprocsub(struct argnod *argp)
@@ -734,7 +734,7 @@ struct argnod *sh_argprocsub(struct argnod *argp)
734734
#if SHOPT_DEVFD
735735
sfwrite(sh.stk,e_devfdNN,8);
736736
pv[2] = 0;
737-
sh_pipe(pv);
737+
sh_pipe(pv,0);
738738
#else
739739
pv[0] = -1;
740740
while(sh.fifo = pathtemp(0,0,0,"ksh.fifo",0), sh.fifo && mkfifo(sh.fifo,0)<0)

0 commit comments

Comments
 (0)