lkml.org 
[lkml]   [2000]   [Sep]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[PATCH/RFC] Fix SI_SIGIO in 2.2.17

    Hello,

    The attached is a fix against 2.2.17 for the
    spurious SIGIO signal returned from send_sigio() depending
    on the "current" process permissions. No changes for the
    applications, no changes in the si_code values.

    The change allows the EPERM check to be skipped for
    si_code==SI_SIGIO sent from the kernel. The calls to
    send_sig_info from arch/<arch>/kernel/signal.c can be
    changed to the new function send_sig_info_nocheck(), for
    performance reasons, i.e. the requeue of the signal can't
    return EINVAL or EPERM - "current" always passes the EPERM
    check in send_sig_info (current->uid==t->uid when
    t==current).

    I can boot with this patch but the maintainers have
    to check it and whether the arch/*/kernel/signal.c can
    switch to the new _nocheck() function to save some CPU
    cycles.


    On Thu, 21 Sep 2000, Jamie Lokier wrote:

    > Julian Anastasov wrote:
    > > I'm talking about test8. __SI_CODE is in 2.4, not in 2.2.
    > > The handling is very different. We can't wait for si_code==SI_SIGIO
    > > in 2.4 anymore. SI_SIGIO is used only in 2.2:fs/fcntl.c. 2.4 stores
    > > POLL_xxx in si_code instead of SI_SIGIO.
    >
    > Why does it do that? si_band already stores the POLL_xxx code.

    si_band=POLLxxx not POLL_xxx :) Not sure, may be
    (1) the 2.4 binaries will be surprised in 2.2 or (2) The
    Single UNIX Specification, Version 2

    > -- Jamie


    Regards

    --
    Julian Anastasov <ja@ssi.bg>
    --- linux-2.2.17/include/linux/sched.h.orig Thu Sep 21 08:05:01 2000
    +++ linux/include/linux/sched.h Fri Sep 22 14:39:40 2000
    @@ -504,6 +504,8 @@
    extern void flush_signal_handlers(struct task_struct *);
    extern int dequeue_signal(sigset_t *block, siginfo_t *);
    extern int send_sig_info(int, struct siginfo *info, struct task_struct *);
    +extern int send_sig_info_nocheck(int, struct siginfo *info,
    + struct task_struct *);
    extern int force_sig_info(int, struct siginfo *info, struct task_struct *);
    extern int kill_pg_info(int, struct siginfo *info, pid_t);
    extern int kill_sl_info(int, struct siginfo *info, pid_t);
    --- linux-2.2.17/fs/fcntl.c.orig Thu Sep 21 08:02:32 2000
    +++ linux/fs/fcntl.c Fri Sep 22 14:40:04 2000
    @@ -256,7 +256,7 @@
    si.si_pid = pid;
    si.si_uid = uid;
    si.si_fd = fa->fa_fd;
    - if (!send_sig_info(fown->signum, &si, p))
    + if (!send_sig_info_nocheck(fown->signum, &si, p))
    break;
    /* fall-through: fall back on the old plain SIGIO signal */
    case 0:
    --- linux-2.2.17/kernel/signal.c.orig Thu Sep 21 08:04:07 2000
    +++ linux/kernel/signal.c Fri Sep 22 14:38:45 2000
    @@ -250,7 +250,7 @@
    }

    int
    -send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
    +send_sig_info_nocheck(int sig, struct siginfo *info, struct task_struct *t)
    {
    unsigned long flags;
    int ret;
    @@ -259,18 +259,6 @@
    printk("SIG queue (%s:%d): %d ", t->comm, t->pid, sig);
    #endif

    - ret = -EINVAL;
    - if (sig < 0 || sig > _NSIG)
    - goto out_nolock;
    - /* The somewhat baroque permissions check... */
    - ret = -EPERM;
    - if ((!info || ((unsigned long)info != 1 && SI_FROMUSER(info)))
    - && ((sig != SIGCONT) || (current->session != t->session))
    - && (current->euid ^ t->suid) && (current->euid ^ t->uid)
    - && (current->uid ^ t->suid) && (current->uid ^ t->uid)
    - && !capable(CAP_KILL))
    - goto out_nolock;
    -
    /* The null signal is a permissions and process existance probe.
    No signal is actually delivered. Same goes for zombies.
    We have to grab the spinlock now so that we do not race
    @@ -405,6 +393,30 @@
    return ret;
    }

    +int
    +send_sig_info(int sig, struct siginfo *info, struct task_struct *t)
    +{
    + int ret;
    +
    + ret = -EINVAL;
    + if (sig < 0 || sig > _NSIG)
    + goto out;
    + /* The somewhat baroque permissions check... */
    + ret = -EPERM;
    + if ((!info || ((unsigned long)info != 1 && SI_FROMUSER(info)))
    + && ((sig != SIGCONT) || (current->session != t->session))
    + && (current->euid ^ t->suid) && (current->euid ^ t->uid)
    + && (current->uid ^ t->suid) && (current->uid ^ t->uid)
    + && !capable(CAP_KILL))
    + goto out;
    +
    + return send_sig_info_nocheck(sig, info, t);
    +
    +out:
    +
    + return ret;
    +}
    +
    /*
    * Force a signal that the process can't ignore: if necessary
    * we unblock the signal and change any SIG_IGN to SIG_DFL.
    @@ -634,6 +646,7 @@
    EXPORT_SYMBOL(recalc_sigpending);
    EXPORT_SYMBOL(send_sig);
    EXPORT_SYMBOL(send_sig_info);
    +EXPORT_SYMBOL(send_sig_info_nocheck);


    /*
    \
     
     \ /
      Last update: 2005-03-22 12:38    [W:0.027 / U:30.300 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site