On Thu, 2021-03-04 at 10:35 +0100, Philippe Gerum wrote:
> [email protected] <[email protected]> writes:
> 
> > On Sat, 2021-02-20 at 16:18 +0100, Philippe Gerum via Xenomai wrote:
> > [snip]
> > > diff --git a/kernel/cobalt/posix/sem.c b/kernel/cobalt/posix/sem.c
> > > index 05a861dfe..467a9b7dd 100644
> > > --- a/kernel/cobalt/posix/sem.c
> > > +++ b/kernel/cobalt/posix/sem.c
> > > @@ -267,7 +267,7 @@ out:
> > >   return ret;
> > >  }
> > >  
> > > 
> > > 
> > > 
> > > -static inline int sem_fetch_timeout(struct timespec *ts,
> > > +static inline int sem_fetch_timeout(struct timespec64 *ts,
> > >                               const void __user *u_ts)
> > 
> > Handle the following with care, maybe my understanding of
> > CONFIG_XENO_ARCH_SYS3264 is wrong. See below...
> > 
> > My understanding is that this is a breaking change for 32 bit kernels.
> > The broken part is hidden here, but sem_fetch_timeout() now assumes
> > that the user provided timespec64, which is not be the case for 32 bit
> > applications running on a 32 bit kernel.
> > 
> 
> The user-provided memory is referred to by u_ts, not ts, which receives
> the timestamp fetch_timeout() is supposed to return. The change should
> only affect the return type, not the source one. sys32_fetch_timeout()
> should still do the right thing via sys32_get_timespec().

Adding the full code:

static inline int sem_fetch_timeout(struct timespec64 *ts,
                                    const void __user *u_ts)
{
        return u_ts == NULL ? -EFAULT :
                cobalt_copy_from_user(ts, u_ts, sizeof(*ts));
}

Copying sizeof(*ts) is to much if the application provided
"__old_time_t" (sizeof(time_t) =4) only. Isn't it? I would expect the
result (in ts) to be garbage. Due to different padding the "sec" field
(in ts) would now contain the nsec value from u_ts as well.

I will come up with a proposal to fix that. We need some discussion
anyway...

> 
> Did you observe a manifest breakage with 32_64 setups?
> 
> > 
> > >  {
> > >   return u_ts == NULL ? -EFAULT :
> > > @@ -276,10 +276,10 @@ static inline int sem_fetch_timeout(struct timespec 
> > > *ts,
> > >  
> > > 
> > > 
> > > 
> > >  int __cobalt_sem_timedwait(struct cobalt_sem_shadow __user *u_sem,
> > >                      const void __user *u_ts,
> > > -                    int (*fetch_timeout)(struct timespec *ts,
> > > +                    int (*fetch_timeout)(struct timespec64 *ts,
> > >                                           const void __user *u_ts))
> > >  {
> > > - struct timespec ts = { .tv_sec = 0, .tv_nsec = 0 };
> > > + struct timespec64 ts = { .tv_sec = 0, .tv_nsec = 0 };
> > >   int pull_ts = 1, ret, info;
> > >   struct cobalt_sem *sem;
> > >   xnhandle_t handle;
> > > @@ -434,7 +434,7 @@ COBALT_SYSCALL(sem_wait, primary,
> > >  
> > > 
> > > 
> > > 
> > >  COBALT_SYSCALL(sem_timedwait, primary,
> > >          (struct cobalt_sem_shadow __user *u_sem,
> > > -         struct timespec __user *u_ts))
> > > +         struct __user_old_timespec __user *u_ts))
> > 
> > This change is still correct, but this is where the journey begins. If
> > my understanding of CONFIG_XENO_ARCH_SYS3264 is correct, this syscall
> > is being used on 32 bit kernels as well. Is that understanding correct?
> 
> COBALT_SYSCALL(sem_timedwait, ...) is only used in native (e.g. mere
> 64bit, or 32bit) mode. The following one is used in 32bit over 64bit
> mode specifically:
> 
> COBALT_SYSCALL32emu(sem_timedwait, primary,
>                   (struct cobalt_sem_shadow __user *u_sem,
>                    struct old_timespec32 __user *u_ts))
> 
> 

Reply via email to