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 <[EMAIL PROTECTED]>
--- 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);
 
 
 /*

Reply via email to