All of lore.kernel.org
 help / color / mirror / Atom feed
* Errors in sigaction struct definition
@ 2005-03-10 18:36 Jordi Brinquez
  0 siblings, 0 replies; only message in thread
From: Jordi Brinquez @ 2005-03-10 18:36 UTC (permalink / raw)
  To: Linux Kernel list; +Cc: Xavi Martorell, Jordi Brínquez

I found a problem while using sigaction structure because of problems
on definition of that structure.

I found it on version 2.6.10 but it was confirmed on version 2.6.8 and
2.6.11 (so probably on other 2.6.x versions)

Extract from /include/asm-i386/signal.h (lines 142-172)

#ifdef __KERNEL__
struct old_sigaction {
    __sighandler_t sa_handler;
    old_sigset_t sa_mask;
    unsigned long sa_flags;
    __sigrestore_t sa_restorer;
};

struct sigaction {
    __sighandler_t sa_handler;
    unsigned long sa_flags;
    __sigrestore_t sa_restorer;
    sigset_t sa_mask;       /* mask last for extensibility */
};

struct k_sigaction {
    struct sigaction sa;
};
#else
/* Here we must cater to libcs that poke about in kernel headers.  */

struct sigaction {
    union {
      __sighandler_t _sa_handler;
      void (*_sa_sigaction)(int, struct siginfo *, void *);
    } _u;
    sigset_t sa_mask;
    unsigned long sa_flags;
    void (*sa_restorer)(void);
};

As you can see the order of the fields in sigaction struct defined
under __KERNEL__ is:
    sa_handler;
    sa_flags;
    sa_restorer;
    sa_mask;
and the order of the fields of the section for the user code is:
    union {...} _u;
    sa_mask;
    sa_flags;
    sa_restorer;

The order is not the same.

Now if we look at the routine that manages the sigaction
(rt_sigaction) we have the following code:

Extract from /kernel/signal.c (lines 2545-2573)

#ifdef __ARCH_WANT_SYS_RT_SIGACTION
asmlinkage long
sys_rt_sigaction(int sig,
         const struct sigaction __user *act,
         struct sigaction __user *oact,
         size_t sigsetsize)
{
    struct k_sigaction new_sa, old_sa;
    int ret = -EINVAL;

    /* XXX: Don't preclude handling different sized sigset_t's.  */
    if (sigsetsize != sizeof(sigset_t))
        goto out;

    if (act) {
        if (copy_from_user(&new_sa.sa, act, sizeof(new_sa.sa)))
            return -EFAULT;
    }

    ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);

    if (!ret && oact) {
        if (copy_to_user(oact, &old_sa.sa, sizeof(old_sa.sa)))
            return -EFAULT;
    }
out:
    return ret;
}
#endif /* __ARCH_WANT_SYS_RT_SIGACTION */

As you can see the algorithm that copies the values from user struct
to kernel struct is copy_from_user (and copy to_user) so because the
diferent definition of the structures the data goes corrupted.

To solve that problem there are two solutions:

- Reorder the fields on user structure (easy solution)
- Change the copy_to_user and copy_from_user for code using __put_user
and __get_user

I think that implementing both can prevent future problems.

Greets,

Jordi

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2005-03-10 18:45 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-03-10 18:36 Errors in sigaction struct definition Jordi Brinquez

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.