summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsobomax <sobomax@FreeBSD.org>2005-02-13 16:42:08 +0000
committersobomax <sobomax@FreeBSD.org>2005-02-13 16:42:08 +0000
commit1d558007d0e84104e9e49a8c08e4a4f6faad3a81 (patch)
tree55af5c404f315b928f52273e849b0e73080b7f0d
parent5775bba72ee8cddb1a59602a8d654da0e8f4e1b3 (diff)
downloadFreeBSD-src-1d558007d0e84104e9e49a8c08e4a4f6faad3a81.zip
FreeBSD-src-1d558007d0e84104e9e49a8c08e4a4f6faad3a81.tar.gz
Split out kill(2) syscall service routine into user-level and kernel part, the
former is callable from user space and the latter from the kernel one. Make kernel version take additional argument which tells if the respective call should check for additional restrictions for sending signals to suid/sugid applications or not. Make all emulation layers using non-checked version, since signal numbers in emulation layers can have different meaning that in native mode and such protection can cause misbehaviour. As a result remove LIBTHR from the signals allowed to be delivered to a suid/sugid application. Requested (sorta) by: rwatson MFC after: 2 weeks
-rw-r--r--sys/alpha/osf1/osf1_signal.c2
-rw-r--r--sys/compat/linux/linux_signal.c2
-rw-r--r--sys/compat/svr4/svr4_signal.c2
-rw-r--r--sys/i386/ibcs2/ibcs2_signal.c2
-rw-r--r--sys/kern/kern_prot.c9
-rw-r--r--sys/kern/kern_sig.c33
-rw-r--r--sys/sys/proc.h6
-rw-r--r--sys/sys/syscallsubr.h2
8 files changed, 36 insertions, 22 deletions
diff --git a/sys/alpha/osf1/osf1_signal.c b/sys/alpha/osf1/osf1_signal.c
index 355cb1c..7a96223 100644
--- a/sys/alpha/osf1/osf1_signal.c
+++ b/sys/alpha/osf1/osf1_signal.c
@@ -445,7 +445,7 @@ osf1_kill(td, uap)
ka.pid = uap->pid;
ka.signum = uap->signum;
- return kill(td, &ka);
+ return kern_kill(td, &ka, 0);
}
diff --git a/sys/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c
index fc25e3f..fa4ae7b 100644
--- a/sys/compat/linux/linux_signal.c
+++ b/sys/compat/linux/linux_signal.c
@@ -435,5 +435,5 @@ linux_kill(struct thread *td, struct linux_kill_args *args)
tmp.signum = args->signum;
tmp.pid = args->pid;
- return (kill(td, &tmp));
+ return (kern_kill(td, &tmp, 0));
}
diff --git a/sys/compat/svr4/svr4_signal.c b/sys/compat/svr4/svr4_signal.c
index 1a3f7f1..2ccebd5 100644
--- a/sys/compat/svr4/svr4_signal.c
+++ b/sys/compat/svr4/svr4_signal.c
@@ -521,7 +521,7 @@ svr4_sys_kill(td, uap)
return (EINVAL);
ka.pid = uap->pid;
ka.signum = SVR4_SVR42BSD_SIG(uap->signum);
- return kill(td, &ka);
+ return kern_kill(td, &ka, 0);
}
diff --git a/sys/i386/ibcs2/ibcs2_signal.c b/sys/i386/ibcs2/ibcs2_signal.c
index b2f3393..0cb3b9a 100644
--- a/sys/i386/ibcs2/ibcs2_signal.c
+++ b/sys/i386/ibcs2/ibcs2_signal.c
@@ -437,5 +437,5 @@ ibcs2_kill(td, uap)
return (EINVAL);
ka.pid = uap->pid;
ka.signum = ibcs2_to_bsd_sig[_SIG_IDX(uap->signo)];
- return kill(td, &ka);
+ return kern_kill(td, &ka, 0);
}
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index 21f277f..d989ab3 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -1427,7 +1427,7 @@ SYSCTL_INT(_security_bsd, OID_AUTO, conservative_signals, CTLFLAG_RW,
* References: cred and proc must be valid for the lifetime of the call.
*/
int
-cr_cansignal(struct ucred *cred, struct proc *proc, int signum)
+cr_cansignal(struct ucred *cred, struct proc *proc, int signum, int pedantic)
{
int error;
@@ -1453,7 +1453,7 @@ cr_cansignal(struct ucred *cred, struct proc *proc, int signum)
* bit on the target process. If the bit is set, then additional
* restrictions are placed on the set of available signals.
*/
- if (conservative_signals && (proc->p_flag & P_SUGID)) {
+ if (conservative_signals && (proc->p_flag & P_SUGID) && pedantic) {
switch (signum) {
case 0:
case SIGKILL:
@@ -1467,7 +1467,6 @@ cr_cansignal(struct ucred *cred, struct proc *proc, int signum)
case SIGHUP:
case SIGUSR1:
case SIGUSR2:
- case SIGTHR:
/*
* Generally, permit job and terminal control
* signals.
@@ -1508,7 +1507,7 @@ cr_cansignal(struct ucred *cred, struct proc *proc, int signum)
* References: td and p must be valid for the lifetime of the call
*/
int
-p_cansignal(struct thread *td, struct proc *p, int signum)
+p_cansignal(struct thread *td, struct proc *p, int signum, int pedantic)
{
KASSERT(td == curthread, ("%s: td not curthread", __func__));
@@ -1525,7 +1524,7 @@ p_cansignal(struct thread *td, struct proc *p, int signum)
if (signum == SIGCONT && td->td_proc->p_session == p->p_session)
return (0);
- return (cr_cansignal(td->td_ucred, p, signum));
+ return (cr_cansignal(td->td_ucred, p, signum, pedantic));
}
/*-
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 2889adb..0974801 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -82,7 +82,8 @@ __FBSDID("$FreeBSD$");
static int coredump(struct thread *);
static char *expand_name(const char *, uid_t, pid_t);
-static int killpg1(struct thread *td, int sig, int pgid, int all);
+static int killpg1(struct thread *td, int sig, int pgid, int all,
+ int pedantic);
static int issignal(struct thread *p);
static int sigprop(int sig);
static void stop(struct proc *);
@@ -1299,9 +1300,9 @@ kern_sigaltstack(struct thread *td, stack_t *ss, stack_t *oss)
* cp is calling process.
*/
static int
-killpg1(td, sig, pgid, all)
+killpg1(td, sig, pgid, all, pedantic)
register struct thread *td;
- int sig, pgid, all;
+ int sig, pgid, all, pedantic;
{
register struct proc *p;
struct pgrp *pgrp;
@@ -1319,7 +1320,7 @@ killpg1(td, sig, pgid, all)
PROC_UNLOCK(p);
continue;
}
- if (p_cansignal(td, p, sig) == 0) {
+ if (p_cansignal(td, p, sig, pedantic) == 0) {
nfound++;
if (sig)
psignal(p, sig);
@@ -1344,12 +1345,12 @@ killpg1(td, sig, pgid, all)
}
sx_sunlock(&proctree_lock);
LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
- PROC_LOCK(p);
+ PROC_LOCK(p);
if (p->p_pid <= 1 || p->p_flag & P_SYSTEM) {
PROC_UNLOCK(p);
continue;
}
- if (p_cansignal(td, p, sig) == 0) {
+ if (p_cansignal(td, p, sig, pedantic) == 0) {
nfound++;
if (sig)
psignal(p, sig);
@@ -1376,6 +1377,16 @@ kill(td, uap)
register struct thread *td;
register struct kill_args *uap;
{
+
+ return kern_kill(td, uap, 1);
+}
+
+int
+kern_kill(td, uap, pedantic)
+ struct thread *td;
+ struct kill_args *uap;
+ int pedantic;
+{
register struct proc *p;
int error;
@@ -1388,7 +1399,7 @@ kill(td, uap)
if ((p = zpfind(uap->pid)) == NULL)
return (ESRCH);
}
- error = p_cansignal(td, p, uap->signum);
+ error = p_cansignal(td, p, uap->signum, pedantic);
if (error == 0 && uap->signum)
psignal(p, uap->signum);
PROC_UNLOCK(p);
@@ -1396,11 +1407,11 @@ kill(td, uap)
}
switch (uap->pid) {
case -1: /* broadcast signal */
- return (killpg1(td, uap->signum, 0, 1));
+ return (killpg1(td, uap->signum, 0, 1, pedantic));
case 0: /* signal own process group */
- return (killpg1(td, uap->signum, 0, 0));
+ return (killpg1(td, uap->signum, 0, 0, pedantic));
default: /* negative explicit process group */
- return (killpg1(td, uap->signum, -uap->pid, 0));
+ return (killpg1(td, uap->signum, -uap->pid, 0, pedantic));
}
/* NOTREACHED */
}
@@ -1424,7 +1435,7 @@ okillpg(td, uap)
if ((u_int)uap->signum > _SIG_MAXSIG)
return (EINVAL);
- return (killpg1(td, uap->signum, uap->pgid, 0));
+ return (killpg1(td, uap->signum, uap->pgid, 0, 1));
}
#endif /* COMPAT_43 */
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 52b47efe..cda4ccf 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -831,7 +831,8 @@ struct proc *zpfind(pid_t); /* Find zombie process by id. */
void adjustrunqueue(struct thread *, int newpri);
void ast(struct trapframe *framep);
struct thread *choosethread(void);
-int cr_cansignal(struct ucred *cred, struct proc *proc, int signum);
+int cr_cansignal(struct ucred *cred, struct proc *proc, int signum,
+ int pedantic);
int enterpgrp(struct proc *p, pid_t pgid, struct pgrp *pgrp,
struct session *sess);
int enterthispgrp(struct proc *p, struct pgrp *pgrp);
@@ -848,7 +849,8 @@ void mi_switch(int flags, struct thread *newtd);
int p_candebug(struct thread *td, struct proc *p);
int p_cansee(struct thread *td, struct proc *p);
int p_cansched(struct thread *td, struct proc *p);
-int p_cansignal(struct thread *td, struct proc *p, int signum);
+int p_cansignal(struct thread *td, struct proc *p, int signum,
+ int pedantic);
struct pargs *pargs_alloc(int len);
void pargs_drop(struct pargs *pa);
void pargs_free(struct pargs *pa);
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
index a996ba7..04f007c 100644
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -42,6 +42,7 @@ struct msqid_ds;
struct rlimit;
struct rusage;
struct sockaddr;
+struct kill_args;
struct stat;
int kern___getcwd(struct thread *td, u_char *buf, enum uio_seg bufseg,
@@ -69,6 +70,7 @@ int kern_getitimer(struct thread *, u_int, struct itimerval *);
int kern_getrusage(struct thread *td, int who, struct rusage *rup);
int kern_getsockopt(struct thread *td, int s, int level, int name,
void *optval, enum uio_seg valseg, socklen_t *valsize);
+int kern_kill(struct thread *, struct kill_args *, int);
int kern_lchown(struct thread *td, char *path, enum uio_seg pathseg,
int uid, int gid);
int kern_link(struct thread *td, char *path, char *link,
OpenPOWER on IntegriCloud