Subject: Re: kern/33671: getpriority(2) under COMPAT_LINUX return wrong values
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: David Laight <david@l8s.co.uk>
List: netbsd-bugs
Date: 06/10/2006 09:00:05
The following reply was made to PR kern/33671; it has been noted by GNATS.

From: David Laight <david@l8s.co.uk>
To: gnats-bugs@netbsd.org
Cc: 
Subject: Re: kern/33671: getpriority(2) under COMPAT_LINUX return wrong values
Date: Sat, 10 Jun 2006 10:05:37 +0100

 > On Thu, Jun 08, 2006 at 06:25:00PM +0000, Nicolas Joly wrote:
 > > >Number:         33671
 > > >Category:       kern
 > > >Synopsis:       getpriority(2) under COMPAT_LINUX return wrong values
 > [...]
 > > >Description:
 > > While running some linux binaries on my -current NetBSD/amd64, i
 > > noticed that getpriority(2) return wrong values. According to the
 > > linux man page (notes section), this syscall returns values in 40..1
 > > interval instead of the expected -20 to 20 range.
 > 
 > I just got some time to take a closer look ... And made the attached
 > patch. I successfully tested it on -current amd64 and i386 boxes, but
 > i suspect all other platforms with COMPAT_LINUX need to be fixed too.
 > 
 > -- 
 > Nicolas Joly
 > 
 > Biological Software and Databanks.
 > Institut Pasteur, Paris.
 
 > Index: sys/compat/linux/arch/amd64/syscalls.master
 > ===================================================================
 > RCS file: /cvsroot/src/sys/compat/linux/arch/amd64/syscalls.master,v
 > retrieving revision 1.10
 > diff -u -r1.10 syscalls.master
 > --- sys/compat/linux/arch/amd64/syscalls.master	9 Feb 2006 19:18:56 -0000	1.10
 > +++ sys/compat/linux/arch/amd64/syscalls.master	9 Jun 2006 14:31:39 -0000
 > @@ -304,7 +304,7 @@
 >  138	STD		{ int linux_sys_fstatfs64(int fd, \
 >  			    size_t sz, struct linux_statfs64 *sp); }
 >  139	UNIMPL		sysfs
 > -140	NOARGS		{ int sys_getpriority(int which, int who); }
 > +140	STD		{ int linux_sys_getpriority(int which, int who); }
 >  141	NOARGS		{ int sys_setpriority(int which, int who, int prio); }
 >  142	STD		{ int linux_sys_sched_setparam(pid_t pid, \
 >  			    const struct linux_sched_param *sp); }
 > Index: sys/compat/linux/arch/i386/syscalls.master
 > ===================================================================
 > RCS file: /cvsroot/src/sys/compat/linux/arch/i386/syscalls.master,v
 > retrieving revision 1.77
 > diff -u -r1.77 syscalls.master
 > --- sys/compat/linux/arch/i386/syscalls.master	11 Dec 2005 12:20:14 -0000	1.77
 > +++ sys/compat/linux/arch/i386/syscalls.master	9 Jun 2006 14:31:39 -0000
 > @@ -184,7 +184,7 @@
 >  93	NOARGS		{ int compat_43_sys_ftruncate(int fd, long length); }
 >  94	NOARGS		{ int sys_fchmod(int fd, int mode); }
 >  95	STD		{ int linux_sys_fchown16(int fd, int uid, int gid); }
 > -96	NOARGS		{ int sys_getpriority(int which, int who); }
 > +96	STD		{ int linux_sys_getpriority(int which, int who); }
 >  97	NOARGS		{ int sys_setpriority(int which, int who, int prio); }
 >  98	NOARGS		{ int sys_profil(caddr_t samples, u_int size, \
 >  			    u_int offset, u_int scale); }
 > Index: sys/compat/linux/common/linux_misc.c
 > ===================================================================
 > RCS file: /cvsroot/src/sys/compat/linux/common/linux_misc.c,v
 > retrieving revision 1.155
 > diff -u -r1.155 linux_misc.c
 > --- sys/compat/linux/common/linux_misc.c	7 Jun 2006 22:33:33 -0000	1.155
 > +++ sys/compat/linux/common/linux_misc.c	9 Jun 2006 14:31:40 -0000
 > @@ -1745,4 +1745,28 @@
 >  	return (ENOSYS);
 >  }
 >  
 > +int
 > +linux_sys_getpriority(l, v, retval)
 > +        struct lwp *l;
 > +        void *v;
 > +        register_t *retval;
 > +{
 > +        struct linux_sys_getpriority_args /* {
 > +                syscallarg(int) which;
 > +                syscallarg(int) who;
 > +        } */ *uap = v;
 > +        struct sys_getpriority_args bsa;
 > +        int error;
 > +
 > +        SCARG(&bsa, which) = SCARG(uap, which);
 > +        SCARG(&bsa, who) = SCARG(uap, who);
 > +
 > +        if ((error = sys_getpriority(l, &bsa, retval)))
 > +                return error;
 > +
 > +        *retval = 20 - *retval;
 > +
 > +        return 0;
 > +}
 > +
 >  #endif /* !COMPAT_LINUX32 */
 
 Since the argument layout is the same, and that is usually assumed for
 syscall emulation, isn't it enough to do:
 
 int
 linux_sys_getpriority(struct lwp *l, void *v, register_t retval)
 {
         int error = sys_getpriority(l, v, retval);
         *retval = 20 - *retval;
         return error;
 }
 
 	David
 
 -- 
 David Laight: david@l8s.co.uk