Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date: Tue, 10 Mar 2020 20:55:53 -0400
From: Rich Felker <dalias@...c.org>
To: musl@...ts.openwall.com
Subject: Re: mips32 little endian -ENOSYS is not -(-ENOSYS)

On Tue, Mar 10, 2020 at 10:10:15PM +0100, Andreas Dröscher wrote:
> Hi
> 
> I'm building a new toolchain for a very old hardware with a very old
> Linux Kernel (2.6.20). The CPU is a Alchemy (now AMD) AU1100
> (production was discontinued).
> 
> Obviously the Kernel lacks a lot of the modern system calls. I
> however expect the general system call interface to be consistent.
> Moreover, musl has fallbacks for many system-calls in place, kudos!
> However, the fallback is never triggered. I will present the issue
> on one example (epoll):
> 
> excerpt from src/linux/epoll.c:
> int epoll_create1(int flags)
> {
> int r = __syscall(SYS_epoll_create1, flags);
> #ifdef SYS_epoll_create
> if (r==-ENOSYS && !flags) r = __syscall(SYS_epoll_create, 1);
> #endif
> return __syscall_ret(r);
> }
> 
> If r is -89 (negative ENOSYS) the fallback is triggered else the
> result is returned as it is. However, in my case __syscall returnes
> 89 (positive ENOSYS).
> I've tracked the return into the kernel and there the negative value
> is returned. The Kernel additionally sets r7 to 1.
> 
> excerpt from arch/mips/syscall_arch.h:
> static inline long __syscall1(long n, long a)
> {
> register long r4 __asm__("$4") = a;
> register long r7 __asm__("$7");
> register long r2 __asm__("$2") = n;
> __asm__ __volatile__ (
> "syscall"
> : "+r"(r2), "=r"(r7)
> : "r"(r4)
> : SYSCALL_CLOBBERLIST, "$8", "$9", "$10");
> return r7 ? -r2 : r2;
> }
> 
> I assume the "bug" is triggered by __syscall1 If r7 is set it will
> change the sign of r2. I can patch that by replacing:
> return r7 ? -r2 : r2;
> with
> return (r7 && r2 > 0) ? -r2 : r2;
> 
> However I've no idea if I'm triggering any side effects or if I
> selected the wrong implementation for my architecture.

It sounds like what you're saying is that the ENOSYS codepath for
mips, at least on your old kernel, is not setting the error flag in r7
and returning ENOSYS in r2, but is instead returning -ENOSYS already
(and not clear whether it's setting r7 at all or just leaving a stale
value there).

Can anyone else confirm this, or point to kernel history that might
suggest it's a real bug? Your workaround looks like it should at least
be *safe* to do, and probably the right thing if this was/is a real
kernel bug in the official kernel rather than something some vendor
broke in their fork.

Rich

Powered by blists - more mailing lists

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.