Looks like `read -e -u N' creates (and leaks) a new stream for fd N. If a second `read' tries to fdopen the same fd once more, Android's FDSAN (on and enforcing defualt) causes the process to abort:
$ bash -c 'read -eu3; read -eu3' 3<&0 fdsan: failed to exchange ownership of file descriptor: fd 3 is owned by FILE* 0x7131a45d18, was expected to be unowned Aborted bash -c 'read -eu3; read -eu3' 3<&0 I guess when Readline is being used for `read' input, a proper thing to do is dup() the fd supplied by -u (thereby defeating the point of the option..) and fclose() the resulting stream when done. I think the current behavior is due to a report[1] about -u being silently ignored with -e, though maybe forbidding the combination explicitly would be fine too. [1]: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=927768 --- builtins/read.def | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/builtins/read.def b/builtins/read.def index 35b71967..fbba6c62 100644 --- a/builtins/read.def +++ b/builtins/read.def @@ -201,6 +201,17 @@ read_builtin_timeout (int fd) #endif } +void reset_rl_instream (FILE *save_instream) +{ + fclose (rl_instream); + rl_instream = save_instream; +} + +void uw_reset_rl_instream (void *fp) +{ + reset_rl_instream (fp); +} + /* Read the value of the shell variables whose names follow. The reading is done from the current input stream, whatever that may be. Successive words of the input line are assigned @@ -613,12 +624,26 @@ read_builtin (WORD_LIST *list) save_instream = 0; if (edit && fd != 0) { + int fd2; + FILE *fp2; + + if ((fd2 = dup (fd)) < 0 || (fp2 = fdopen (fd2, "r")) == 0) + { + builtin_error ("%d: %s", fd, strerror (errno)); + if (fd2 >= 0) + close (fd2); + run_unwind_frame ("read_builtin"); + return (EXECUTION_FAILURE); + } + if (bash_readline_initialized == 0) initialize_readline (); - unwind_protect_var (rl_instream); save_instream = rl_instream; - rl_instream = fdopen (fd, "r"); + rl_instream = fp2; + add_unwind_protect (uw_reset_rl_instream, save_instream); + + fd = fd2; } #endif @@ -896,7 +921,7 @@ add_char: #if defined (READLINE) if (save_instream) - rl_instream = save_instream; /* can't portably free it */ + reset_rl_instream (save_instream); #endif discard_unwind_frame ("read_builtin"); -- 2.45.1