linux(4): Properly convert linux siginfo to native siginfo
add input validation. MFC after: 2 weeks
This commit is contained in:
parent
e29ea22f70
commit
9c1045ff00
@ -59,6 +59,7 @@ int linux_kernver(struct thread *td);
|
||||
|
||||
#define LINUX_KERNVER_2004000 LINUX_KERNVER(2,4,0)
|
||||
#define LINUX_KERNVER_2006000 LINUX_KERNVER(2,6,0)
|
||||
#define LINUX_KERNVER_2006039 LINUX_KERNVER(2,6,39)
|
||||
|
||||
#define linux_use26(t) (linux_kernver(t) >= LINUX_KERNVER_2006000)
|
||||
|
||||
|
@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <machine/../linux/linux.h>
|
||||
#include <machine/../linux/linux_proto.h>
|
||||
#endif
|
||||
#include <compat/linux/linux_mib.h>
|
||||
#include <compat/linux/linux_signal.h>
|
||||
#include <compat/linux/linux_timer.h>
|
||||
#include <compat/linux/linux_util.h>
|
||||
@ -651,17 +652,40 @@ siginfo_to_lsiginfo(const siginfo_t *si, l_siginfo_t *lsi, l_int sig)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
lsiginfo_to_ksiginfo(const l_siginfo_t *lsi, ksiginfo_t *ksi, int sig)
|
||||
int
|
||||
lsiginfo_to_siginfo(struct thread *td, const l_siginfo_t *lsi,
|
||||
siginfo_t *si, int sig)
|
||||
{
|
||||
|
||||
ksi->ksi_signo = sig;
|
||||
ksi->ksi_code = lsi->lsi_code; /* XXX. Convert. */
|
||||
ksi->ksi_pid = lsi->lsi_pid;
|
||||
ksi->ksi_uid = lsi->lsi_uid;
|
||||
ksi->ksi_status = lsi->lsi_status;
|
||||
ksi->ksi_addr = PTRIN(lsi->lsi_addr);
|
||||
ksi->ksi_info.si_value.sival_int = lsi->lsi_int;
|
||||
switch (lsi->lsi_code) {
|
||||
case LINUX_SI_TKILL:
|
||||
if (linux_kernver(td) >= LINUX_KERNVER_2006039) {
|
||||
linux_msg(td, "SI_TKILL forbidden since 2.6.39");
|
||||
return (EPERM);
|
||||
}
|
||||
si->si_code = SI_LWP;
|
||||
case LINUX_SI_QUEUE:
|
||||
si->si_code = SI_QUEUE;
|
||||
break;
|
||||
case LINUX_SI_TIMER:
|
||||
si->si_code = SI_TIMER;
|
||||
break;
|
||||
case LINUX_SI_MESGQ:
|
||||
si->si_code = SI_MESGQ;
|
||||
break;
|
||||
case LINUX_SI_ASYNCIO:
|
||||
si->si_code = SI_ASYNCIO;
|
||||
break;
|
||||
default:
|
||||
si->si_code = lsi->lsi_code;
|
||||
break;
|
||||
}
|
||||
|
||||
si->si_signo = sig;
|
||||
si->si_pid = td->td_proc->p_pid;
|
||||
si->si_uid = td->td_ucred->cr_ruid;
|
||||
si->si_value.sival_ptr = PTRIN(lsi->lsi_value.sival_ptr);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
@ -681,9 +705,14 @@ linux_rt_sigqueueinfo(struct thread *td, struct linux_rt_sigqueueinfo_args *args
|
||||
return (error);
|
||||
|
||||
if (linfo.lsi_code >= 0)
|
||||
/* SI_USER, SI_KERNEL */
|
||||
return (EPERM);
|
||||
|
||||
sig = linux_to_bsd_signal(args->sig);
|
||||
ksiginfo_init(&ksi);
|
||||
error = lsiginfo_to_siginfo(td, &linfo, &ksi.ksi_info, sig);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
error = ESRCH;
|
||||
if ((p = pfind_any(args->pid)) != NULL) {
|
||||
@ -692,9 +721,6 @@ linux_rt_sigqueueinfo(struct thread *td, struct linux_rt_sigqueueinfo_args *args
|
||||
PROC_UNLOCK(p);
|
||||
return (error);
|
||||
}
|
||||
|
||||
ksiginfo_init(&ksi);
|
||||
lsiginfo_to_ksiginfo(&linfo, &ksi, sig);
|
||||
error = tdsendsignal(p, NULL, sig, &ksi);
|
||||
PROC_UNLOCK(p);
|
||||
}
|
||||
@ -721,12 +747,15 @@ linux_rt_tgsigqueueinfo(struct thread *td, struct linux_rt_tgsigqueueinfo_args *
|
||||
if (linfo.lsi_code >= 0)
|
||||
return (EPERM);
|
||||
|
||||
sig = linux_to_bsd_signal(args->sig);
|
||||
ksiginfo_init(&ksi);
|
||||
error = lsiginfo_to_siginfo(td, &linfo, &ksi.ksi_info, sig);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
tds = linux_tdfind(td, args->tid, args->tgid);
|
||||
if (tds == NULL)
|
||||
return (ESRCH);
|
||||
|
||||
sig = linux_to_bsd_signal(args->sig);
|
||||
ksiginfo_init(&ksi);
|
||||
lsiginfo_to_ksiginfo(&linfo, &ksi, sig);
|
||||
return (linux_do_tkill(td, tds, &ksi));
|
||||
}
|
||||
|
@ -46,6 +46,7 @@
|
||||
int linux_do_sigaction(struct thread *, int, l_sigaction_t *, l_sigaction_t *);
|
||||
void ksiginfo_to_lsiginfo(const ksiginfo_t *ksi, l_siginfo_t *lsi, l_int sig);
|
||||
void siginfo_to_lsiginfo(const siginfo_t *si, l_siginfo_t *lsi, l_int sig);
|
||||
void lsiginfo_to_ksiginfo(const l_siginfo_t *lsi, ksiginfo_t *ksi, int sig);
|
||||
int lsiginfo_to_siginfo(struct thread *td, const l_siginfo_t *lsi,
|
||||
siginfo_t *si, int sig);
|
||||
|
||||
#endif /* _LINUX_SIGNAL_H_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user