[PATCH] ash: avoid some redirection oddities

David Laight David.Laight at ACULAB.COM
Tue Apr 26 15:56:40 UTC 2022


From: Ron Yorston
> Sent: 26 April 2022 16:10
> 
> A user reports:
> 
>    I know this code is wrong but it shouldn't cause the shell to exit:
>    echo text >&9999
>    This instead cause the creation of a file:
>    echo text >&9999999999
> 
>    I think it would be better if they report Bad file descriptor
> 
> The first case happens because save_fd_on_redirect() causes an exit
> when dup_CLOEXEC() returns any error other than EBADF.  Despite its
> name dup_CLOEXEC() actually uses fcntl(2) which returns EINVAL when
> the file descriptor is greater than the maximum allowed.
> 
> The second case is due to any numeric string longer than nine digits
> being treated as a file name rather than a number.  Bash doesn't
> do this.
...
> @@ -9635,7 +9634,7 @@ expredir(union node *n)
>  				if (fn.list == NULL)
>  					ash_msg_and_raise_error("redir error");
>  #if BASH_REDIR_OUTPUT
> -				if (!isdigit_str9(fn.list->text)) {
> +				if (!isdigit_str(fn.list->text)) {
>  					/* >&file, not >&fd */
>  					if (redir->nfile.fd != 1) /* 123>&file - BAD */
>  						ash_msg_and_raise_error("redir error");
> @@ -11945,19 +11944,21 @@ static void
>  fixredir(union node *n, const char *text, int err)
>  {
>  	int fd;
> +	struct rlimit limit;
> 
>  	TRACE(("Fix redir %s %d\n", text, err));
>  	if (!err)
>  		n->ndup.vname = NULL;
> 
> +	getrlimit(RLIMIT_NOFILE, &limit);

Doing an extra system call seems suboptimal.
Why not just allow EINVAL as equivalent to EBADF later on?

>  	fd = bb_strtou(text, NULL, 10);

Can't you do this conversion earlier and check the 'unconverted'
character for being '\0'?
Would save scanning the string twice.

> -	if (!errno && fd >= 0)
> +	if (!errno && fd >= 0 && fd < limit.rlim_cur - 1)
>  		n->ndup.dupfd = fd;
>  	else if (LONE_DASH(text))
>  		n->ndup.dupfd = -1;
>  	else {
>  		if (err)
> -			raise_error_syntax("bad fd number");
> +			raise_error_syntax(strerror(EBADF));
>  		n->ndup.vname = makename();
...

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)



More information about the busybox mailing list