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    [from the cache]
©2003-2011 Jasper Spaans