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); /*