[systemd-devel] [PATCH] Fix broken syscall(__NR_fanotify_mark... on 32bit mips.

Aurelien Jarno aurelien at aurel32.net
Wed Apr 20 03:16:05 PDT 2011


On Wed, Apr 20, 2011 at 03:22:08AM +0200, Lennart Poettering wrote:
> On Wed, 20.04.11 09:15, fykcee1 at gmail.com (fykcee1 at gmail.com) wrote:
> 
> > 
> > 2011/4/20 Lennart Poettering <lennart at poettering.net>
> > >
> > > On Thu, 14.04.11 17:34, fykcee1 at gmail.com (fykcee1 at gmail.com) wrote:
> > >
> > > > diff --git a/src/missing.h b/src/missing.h
> > > > index 35e209f..b367831 100644
> > > > --- a/src/missing.h
> > > > +++ b/src/missing.h
> > > > @@ -125,7 +125,12 @@ static inline int fanotify_init(unsigned int flags, unsigned int event_f_flags)
> > > >
> > > >  static inline int fanotify_mark(int fanotify_fd, unsigned int flags, uint64_t mask,
> > > >                                  int dfd, const char *pathname) {
> > > > -        return syscall(__NR_fanotify_mark, fanotify_fd, flags, mask, dfd, pathname);
> > > > +        if (sizeof(void *) == 4)
> > > > +                return syscall(__NR_fanotify_mark, fanotify_fd, flags,
> > > > +                               *((uint32_t *) &mask), *((uint32_t *) &mask + 1),
> > > > +                               dfd, pathname);
> > > > +        else /* 64bit */
> > > > +                return syscall(__NR_fanotify_mark, fanotify_fd, flags, mask, dfd, pathname);
> > > >  }
> > > >
> > > >  #ifndef BTRFS_IOCTL_MAGIC
> > >
> > > Hmm, wouldn't this break x86-32?
> > It works fine on my asus laptop with a 32bit CPU Pentium-M.
> > 
> > We pass two 32bit arguments instead of one 64bit argument. syscall()
> > doesn't know the prototype, I guess it will only fetch 9 native-width
> > arguments(1 syscall number + 8 parameters) from the stack. Aurelien,
> > am I right?
> 
> Hmm, I am not sure I understand this? How is it possible that both ways
> work on x86? There must be quite a difference between passing 6 or 7
> arguments to syscall.

syscall(64_bit_arg) actually pass the 64-bit argument in two different
registers (or on two different 32-bit stack entries). Then the GNU libc
copies the registers while converting from the userspace ABI to the
kernel ABI (usually passing more values into registers).

On a lot of 32-bit cpus which needs alignment, a 64-bit arguments have 
to be stack aligned, or register aligned. That's why due to the userspace
ABI, one register or one stack entry has to be empty. This later break
when this empty register arrives at the kernel level.

> Or are you suggesting that the current invocation is broken even on x86,
> just doesn't become visible since only the lower 32 bit of "mask" are
> used?
> 

No, on x86 it just work "by chance", as x86 is very flexible with
alignement.

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien at aurel32.net                 http://www.aurel32.net


More information about the systemd-devel mailing list