The branch main has been updated by dchagin:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=9c1045ff00935a4bb0592d8c00ca1981d3e6eb8b

commit 9c1045ff00935a4bb0592d8c00ca1981d3e6eb8b
Author:     Dmitry Chagin <dcha...@freebsd.org>
AuthorDate: 2021-06-07 02:55:34 +0000
Commit:     Dmitry Chagin <dcha...@freebsd.org>
CommitDate: 2021-06-07 02:55:34 +0000

    linux(4): Properly convert linux siginfo to native siginfo
    add input validation.
    
    MFC after:      2 weeks
---
 sys/compat/linux/linux_mib.h    |  1 +
 sys/compat/linux/linux_signal.c | 59 ++++++++++++++++++++++++++++++-----------
 sys/compat/linux/linux_signal.h |  3 ++-
 3 files changed, 47 insertions(+), 16 deletions(-)

diff --git a/sys/compat/linux/linux_mib.h b/sys/compat/linux/linux_mib.h
index b3d5949c9630..c4d3d1e83f7e 100644
--- a/sys/compat/linux/linux_mib.h
+++ b/sys/compat/linux/linux_mib.h
@@ -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)
 
diff --git a/sys/compat/linux/linux_signal.c b/sys/compat/linux/linux_signal.c
index a479c9cc769c..02abfe961e6b 100644
--- a/sys/compat/linux/linux_signal.c
+++ b/sys/compat/linux/linux_signal.c
@@ -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));
 }
diff --git a/sys/compat/linux/linux_signal.h b/sys/compat/linux/linux_signal.h
index 5df74fb71029..bb34613fa2be 100644
--- a/sys/compat/linux/linux_signal.h
+++ b/sys/compat/linux/linux_signal.h
@@ -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_ */
_______________________________________________
dev-commits-src-main@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-main
To unsubscribe, send any mail to "dev-commits-src-main-unsubscr...@freebsd.org"

Reply via email to