From mboxrd@z Thu Jan 1 00:00:00 1970 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on inbox.vuxu.org X-Spam-Level: X-Spam-Status: No, score=-3.3 required=5.0 tests=MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL autolearn=ham autolearn_force=no version=3.4.4 Received: (qmail 30074 invoked from network); 8 Jul 2021 01:39:59 -0000 Received: from mother.openwall.net (195.42.179.200) by inbox.vuxu.org with ESMTPUTF8; 8 Jul 2021 01:39:59 -0000 Received: (qmail 22364 invoked by uid 550); 8 Jul 2021 01:39:56 -0000 Mailing-List: contact musl-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Reply-To: musl@lists.openwall.com Received: (qmail 22343 invoked from network); 8 Jul 2021 01:39:55 -0000 Date: Wed, 7 Jul 2021 21:39:43 -0400 From: Rich Felker To: musl@lists.openwall.com Message-ID: <20210708013943.GS13220@brightrain.aerifal.cx> References: <20210708001519.649-1-ericonr@disroot.org> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <20210708001519.649-1-ericonr@disroot.org> User-Agent: Mutt/1.5.21 (2010-09-15) Subject: Re: [musl] [PATCH] fix fexecve fallback code when fd is negative On Wed, Jul 07, 2021 at 09:15:19PM -0300, Érico Nogueira wrote: > even though passing negative fd values to fexecve shouldn't happen on > the part of any application, if it does happen and the current kernel > doesn't implement SYS_execveat, musl will call execve on > "/proc/self/fd/(unsigned)fd", which might be an existing, unrelated, > file. > > this was introduced in commit c8c0844f7fbcb955848ca84432e5ffcf71f1cef1, > when fexecve started using __procfdname, which takes an unsigned integer > instead of signed one. > > this also fixes the POSIX-compliance of the function, since POSIX > specifies: > > The fexecve() function shall fail if: > > EBADF The fd argument is not a valid file descriptor open for > executing. > > this corner case was found while investigating usage of __procfdname. > all other cases are correct: > > - fchmod,fchdir,fchown -> will fail the direct syscall first > - fchmodat -> is in the *at family so fd can be -1, only uses procfdname with another fd > - fstatat -> checks for fd>=0 in the branch that uses procfdname > - ttyname_r -> fd goes through isatty() > --- > src/process/fexecve.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/src/process/fexecve.c b/src/process/fexecve.c > index 554c1981..ab81b2d3 100644 > --- a/src/process/fexecve.c > +++ b/src/process/fexecve.c > @@ -8,6 +8,8 @@ int fexecve(int fd, char *const argv[], char *const envp[]) > { > int r = __syscall(SYS_execveat, fd, "", argv, envp, AT_EMPTY_PATH); > if (r != -ENOSYS) return __syscall_ret(r); > + else if (fd < 0) return __syscall_ret(-EBADF); > + > char buf[15 + 3*sizeof(int)]; > __procfdname(buf, fd); > execve(buf, argv, envp); > -- > 2.32.0 To document what we discussed on IRC, if x has type int and x<0, (unsigned)x > INT_MAX, so it cannot masquerade as a value in the range 0..INT_MAX (which a fd must be). This means the code is already working, and the line following the above context: if (errno == ENOENT) errno = EBADF; handles conversion to the expected error code. Rich