From patchwork Sun Jul 19 15:50:32 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oscar Carter X-Patchwork-Id: 11672497 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A1DE713B4 for ; Sun, 19 Jul 2020 15:52:06 +0000 (UTC) Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.kernel.org (Postfix) with SMTP id 09561207EA for ; Sun, 19 Jul 2020 15:52:05 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=gmx.net header.i=@gmx.net header.b="SuTsQ1Ru" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 09561207EA Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gmx.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=kernel-hardening-return-19394-patchwork-kernel-hardening=patchwork.kernel.org@lists.openwall.com Received: (qmail 9801 invoked by uid 550); 19 Jul 2020 15:52:04 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 9776 invoked from network); 19 Jul 2020 15:52:03 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1595173881; bh=UxIl6mQen7XHyeByrGPPzVo5oIulQzy1cfNBw4mJwKk=; h=X-UI-Sender-Class:From:To:Cc:Subject:Date:In-Reply-To:References; b=SuTsQ1RuKd1Yyt7mauDt3BNF40vASogagV5nvvha5YSYs1cLI1Cf0lsUXEg5yW1GI Xp36OFwLS7PIaAV7aGhcOAP7yPCCzVAmt9WBdJ7wzNeZ4OiXgPspLWJpQuEfcPWkcx tEGDeKbS56bIAIBtXzlRiHz0xOLcv9DX0ipXICYw= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c From: Oscar Carter To: Steven Rostedt , Ingo Molnar , Kees Cook Cc: Oscar Carter , linux-kernel@vger.kernel.org, kernel-hardening@lists.openwall.com, Jann Horn Subject: [PATCH v2 1/2] kernel/trace: Prepare to remove function callback casts Date: Sun, 19 Jul 2020 17:50:32 +0200 Message-Id: <20200719155033.24201-2-oscar.carter@gmx.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200719155033.24201-1-oscar.carter@gmx.com> References: <20200719155033.24201-1-oscar.carter@gmx.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:2z12NmO4u8UaSayx3JZjEGOcyrHYJ4xFELYM88klsQhmJlBUw5R ZNiIhd83afniCVMUF1UDUfbNAVXAxTD+6MtwUWxSSMssNq3DZtnzZpfuOLzGZPWH5LOHvyj 92nr89bVIbT9WYJk3uvwdohIL10+ECLUNMQ98SG3NdC87Gp1UGtAs7O3geVLHSPkJhi8Yb3 4DAG/29QWv/o6Z2sngFNA== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:uMgpbrCNjLY=:QEGMcSDeJXgrI0HoHw1xAh LCEzKfBq8KCcJvdSmqkwUJENEdUY1slU+Il1VaseHlMpmP/rBKAyPVQt7kUCl21f42Zec7eRr ylFn9uMnJ/KL+/Ldgtlqe9cXofKoqVKMWiWSrAXUlX2SUT5he0U5+c0h78TWGZOJ06uSrOFjO GjIB/VSM0rk5KpFbljpiinl7v8f+fuQ9N6z1D9XMkrqjP2hjK6npdF91oy6K5xBo8COM9olBd ah8/SpIDNNKoxyHf+kpTAmYcoYGu77eJLvX71WPFqvcV+qNplnepzmYpnYPmeR1lag0qiOK8n 9Kw9LX1WGB3bXkak6VdLKbXoQgUTMlol1Nw99R8rDLm7ZzM5pgzXGFU72984ILTmKYb58NJfx mON0Y9t+L61bsglxxbYBSMRF96PtdTXqqdSE6f9LENIbY7UkqmwEDSP9PeYz3Aeu2Ldhr1xN1 jxIsxyNeqpNksV5v9KrsPmWtWDlhNdHD1lkFU9lzwmJvDRMx/ENaEp53Ak+tnTv4zBYmQY4js X3pkhNYjdaQQW3hMhOssrRy3Vm9GV/JblJx9elyrumAR/qZkAGskOHU5PvemkFYTon8C/5ahz QcyE1AQU0JmU+HQ+wSZoQxWf6L0M4mDVpAI4n5aeCZwHcze3oJb3lroQ9WIJ8OmNtxpiwFGWM 9t/Xf0DPdILb7ceMaZqSKkn2PzXyjozAAoafLGkDNM8Hlky9gu3zFXrIiYyVZY09zU0wbqJCK FlnG1gaMhEtThyCB4pfku/f/GotOFwL/ggbOq4UceAVqHI8fGdc9BE1q8owG2gVPowaE0SwNu BzAsjA/04wc5RU2ERuIBeBfC1Km3CcOqvebyDrFAumFs3JqNaVXC9VFB6L08/H5lKVqKBO2lF 86R/aHFMBmqg4H9nAzpRg6krVuFE5vaSj7FzlRbKhefQZ3NSMOJVpv9NcylANRC1D/u6dRhzA b5b4vMvAXFeHuZoNlaz+5gWmG+noxr8L+XAZS44yQaf1kvrzHx2bJYkmKSu4OJhXlTybMV3/i 9vIPPsaJg3ZpClrk7urOvbn6DZ7m1iHmSOydFZwn62R+wTEWYkCpsJpU2IVffOc0BCtYSIeEv 7/RRAbOwRt3ETEaRTlUoAxbUdDeNSmKQnvJCU4jfDPPuRIvybQ6J5lsDLNM3oeKCjX8m3Y62o 50hVn9noWAl+GrZIEfcn3grUXWMU/x1950r7pmiF/BmXzjBfibb57+Ubo7f9caFA1IawrI0OK AUyMIH+ecdfhkQRNdIKOCy++7Op3OBGrDDpLxbA== In an effort to enable -Wcast-function-type in the top-level Makefile to support Control Flow Integrity builds, there are the need to remove all the function callback casts. ftrace_ops_list_func() can no longer be defined as ftrace_ops_no_ops(). The reason for ftrace_ops_no_ops() is to use that when an architecture calls ftrace_ops_list_func() with only two parameters (called from assembly). And to make sure there's no C side-effects, those archs call ftrace_ops_no_ops() which only has two parameters, as the function ftrace_ops_list_func() has four parameters. This patch prepares all the infrastructure to remove the casts. Define a new function pointer to use when the archs don't support ftrace ops. Also define a union to combine this new function pointer (two parameters) with the ftrace_func_t function pointer (four parameters). This way, using this union it's possible to use two different function prototypes with the same variable. Also create two static inline helpers to set and compare against the fields of the new union type. These helpers are duplicated for the archs that support ftrace ops and for the archs that don't support ftrace ops as both cases use different function prototypes. Signed-off-by: Oscar Carter --- kernel/trace/ftrace.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) -- 2.20.1 diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 1903b80db6eb..fd8fbb422860 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -119,13 +119,45 @@ struct ftrace_ops __rcu *ftrace_ops_list __read_mostly = &ftrace_list_end; ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub; struct ftrace_ops global_ops; +typedef void (*ftrace_func_no_ops_t)(unsigned long ip, + unsigned long parent_ip); + +union ftrace_func { + ftrace_func_t ops; + ftrace_func_no_ops_t no_ops; +}; + #if ARCH_SUPPORTS_FTRACE_OPS static void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, struct ftrace_ops *op, struct pt_regs *regs); + +static inline void ftrace_set_ufunc(union ftrace_func *ufunc, + ftrace_func_t func) +{ + ufunc->ops = func; +} + +static inline bool ftrace_same_address_ufunc(union ftrace_func *ufunc, + ftrace_func_t func) +{ + return (ufunc->ops == func); +} #else /* See comment below, where ftrace_ops_list_func is defined */ static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip); #define ftrace_ops_list_func ((ftrace_func_t)ftrace_ops_no_ops) + +static inline void ftrace_set_ufunc(union ftrace_func *ufunc, + ftrace_func_no_ops_t func) +{ + ufunc->no_ops = func; +} + +static inline bool ftrace_same_address_ufunc(union ftrace_func *ufunc, + ftrace_func_no_ops_t func) +{ + return (ufunc->no_ops == func); +} #endif static inline void ftrace_ops_init(struct ftrace_ops *ops) From patchwork Sun Jul 19 15:50:33 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Oscar Carter X-Patchwork-Id: 11672499 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4A755913 for ; Sun, 19 Jul 2020 15:52:15 +0000 (UTC) Received: from mother.openwall.net (mother.openwall.net [195.42.179.200]) by mail.kernel.org (Postfix) with SMTP id 7B7FA207EA for ; Sun, 19 Jul 2020 15:52:14 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=pass (1024-bit key) header.d=gmx.net header.i=@gmx.net header.b="dl9Qv6LY" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7B7FA207EA Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=gmx.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=kernel-hardening-return-19395-patchwork-kernel-hardening=patchwork.kernel.org@lists.openwall.com Received: (qmail 11371 invoked by uid 550); 19 Jul 2020 15:52:10 -0000 Mailing-List: contact kernel-hardening-help@lists.openwall.com; run by ezmlm Precedence: bulk List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-ID: Delivered-To: mailing list kernel-hardening@lists.openwall.com Received: (qmail 11295 invoked from network); 19 Jul 2020 15:52:10 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1595173888; bh=N+UeP24eqVRjJpemOD2oTkwdHQmg8hfH9M861ui7lqc=; h=X-UI-Sender-Class:From:To:Cc:Subject:Date:In-Reply-To:References; b=dl9Qv6LYCoziMGrFyKXiJ98zjZduLijQGDv8AUlVyG2XYMNKbyCIzB3ZU9MIN8TWC wX0hb0X9KeR3RnLe4C2UMu7Z37kTBb0I5h5ABte1hdHrlKT98KrbAHE4JhmdsI+zju uRYM4Oa01/jk3J1cNjAxf1bVCkAvBUd+Nk51pbRo= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c From: Oscar Carter To: Steven Rostedt , Ingo Molnar , Kees Cook Cc: Oscar Carter , linux-kernel@vger.kernel.org, kernel-hardening@lists.openwall.com, Jann Horn Subject: [PATCH v2 2/2] kernel/trace: Remove function callback casts Date: Sun, 19 Jul 2020 17:50:33 +0200 Message-Id: <20200719155033.24201-3-oscar.carter@gmx.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200719155033.24201-1-oscar.carter@gmx.com> References: <20200719155033.24201-1-oscar.carter@gmx.com> MIME-Version: 1.0 X-Provags-ID: V03:K1:yMLosVOVnTKjix38LbWzPsQaGdmB29CtaF2TTr1A9omeTBF3BUz ydqpg8sqfwZOnZwTkLl5iCEmMpusAAzkxpTlDAUTdo5iDEw5sH4XLsaGqm0lZ9pU/sMfEUG +2yMMw9pxfZYU5VoiKlxUf8sN5+WWgypIKJTPBr7Poz8TwnnwaNh/oX7m2TxnUdhj990rLQ CeyAxe4nR4uGMJqZbuI6A== X-Spam-Flag: NO X-UI-Out-Filterresults: notjunk:1;V03:K0:LdEQnRocgaA=:nSFO6IKDyDnCxNWHZorvAR BKP7FQFRcf4ATCdiommHAote0u+awdGJh6DzY4ep15XlBSULgWzdoZNyM/hcfAgaFszEw0c44 BMHLdOEHyZau9Zr6k8jgBsWrIQlQdjUoWj1f0iG8jKesizrNKsij3PvexG52Ejcd+UW31qkBk ZGdGL1ZjlhYtypfkWOeNIKUJ9l1i3rvze4wp0xbevyj+YUtlsvwSUtow8YIruOs5E5i3rbu/3 GYIrSvuaRPQ3D8ckL5UG9yQcm/ZElaaRiBNWo2JZTdxpa5dIWA068yG/9Plo9S8I7KA8Jvov0 G71gwJFxx+24M8Qk17M32esMG4kCQXDMj3ow8ycng7SxenRYgXW8O+kOloj4EQk1cHZvt8zfP 1Ok0sRMnHonR2k+GIJkAc8kyfGk2Ro+JKSIsyJeHPZYAL/20GdrRhcCncq8jvfXhPGGcjOipZ bONO+En/2r7ioS1FaRz9D+jKjHeECKt4LZsydYvoHWxCXzmrzHe61+DhvFz+Q7C9c0ESakdys li/eVxQ/DHwYdnX0X/81fPUoCjxxfkOfvIgkQKQfUVU0KyGWTBOCtAWxEAX15AIuEu/XZb0du vCOfQ3YaaEQfG73DyFmrxVccS9jbGXEdiNGDz7yxzUgJ2c3LICkGwQ2gB6i0tCglAWn+a2udB ABTl9aAGV6TEMuz6hFb0KajWvtRAeYWlfDT08UOyBiaxKsP9U5O0i2eN75Me4OMdHUri7Q5rw C8Uv3yW+hF7kwVayXDHMyIJaUjD5cx6G4pMw4zOWjvIeM2J20BI6+AhBNOmCDEmaujED5ZXEw uIM7emRkwo64K3vbflZbbtujLBVawdDxTTyTMBWftKuosZ283DwNrXao8R78qIWXxgBt6ff47 6C4lGHJZE54lDIGQOqgPidP7qVcczejAcXc0fAH+JpJG+GFIQFbQvrRSi4AnZi2hXvcPGifPI IQb0rpy1OcW4uWVmCc0Lmeq7UDzFnAm8vHfANtAftHJyjmUu2VmkhZftWxKxEIn5umuk9YOC/ oCpBl2l0l9o2i/g8ejI9NtklLxuLkg1ElIcmqBjXRNS0LjdFmNqc/UJqeFVIhg1S88Sz1XmFw SUUWkEHmN0DpRu9/tus74AhNcaT7AXC64hss2XG8VEATk76t7CsOaaeEChxlR5Ve946MFh0tr oFznsBP73HcIwX664soZySaVU54FE9hfxz7z9BcKB1rGSpTVN5COcUreQjoV9bzdrQpfIgHZ6 p6CpBJuXPEzPZ1z168MKlFnfqg/sr+n3UM4Zr6Q== In an effort to enable -Wcast-function-type in the top-level Makefile to support Control Flow Integrity builds, there are the need to remove all the function callback casts. ftrace_ops_list_func() can no longer be defined as ftrace_ops_no_ops(). The reason for ftrace_ops_no_ops() is to use that when an architecture calls ftrace_ops_list_func() with only two parameters (called from assembly). And to make sure there's no C side-effects, those archs call ftrace_ops_no_ops() which only has two parameters, as the function ftrace_ops_list_func() has four parameters. This patch removes the no longer needed function ftrace_ops_no_ops() and all the function callback casts using the previous defined ftrace_func union and the two function helpers called ftrace_set_ufunc() and ftrace_same_address_ufunc(). Signed-off-by: Oscar Carter --- kernel/trace/ftrace.c | 48 ++++++++++++++++++++++++++----------------- 1 file changed, 29 insertions(+), 19 deletions(-) -- 2.20.1 diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index fd8fbb422860..124ccf914657 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -143,9 +143,7 @@ static inline bool ftrace_same_address_ufunc(union ftrace_func *ufunc, return (ufunc->ops == func); } #else -/* See comment below, where ftrace_ops_list_func is defined */ -static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip); -#define ftrace_ops_list_func ((ftrace_func_t)ftrace_ops_no_ops) +static void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip); static inline void ftrace_set_ufunc(union ftrace_func *ufunc, ftrace_func_no_ops_t func) @@ -198,22 +196,29 @@ static void ftrace_sync_ipi(void *data) smp_rmb(); } -static ftrace_func_t ftrace_ops_get_list_func(struct ftrace_ops *ops) +static union ftrace_func ftrace_ops_get_list_func(struct ftrace_ops *ops) { + union ftrace_func list_func; + /* * If this is a dynamic, RCU, or per CPU ops, or we force list func, * then it needs to call the list anyway. */ if (ops->flags & (FTRACE_OPS_FL_DYNAMIC | FTRACE_OPS_FL_RCU) || FTRACE_FORCE_LIST_FUNC) - return ftrace_ops_list_func; + ftrace_set_ufunc(&list_func, ftrace_ops_list_func); + else + list_func.ops = ftrace_ops_get_func(ops); - return ftrace_ops_get_func(ops); + return list_func; } static void update_ftrace_function(void) { - ftrace_func_t func; + union ftrace_func func; +#ifndef CONFIG_DYNAMIC_FTRACE + union ftrace_func tmp; +#endif /* * Prepare the ftrace_ops that the arch callback will use. @@ -225,7 +230,7 @@ static void update_ftrace_function(void) /* If there's no ftrace_ops registered, just call the stub function */ if (set_function_trace_op == &ftrace_list_end) { - func = ftrace_stub; + func.ops = ftrace_stub; /* * If we are at the end of the list and this ops is @@ -239,21 +244,21 @@ static void update_ftrace_function(void) } else { /* Just use the default ftrace_ops */ set_function_trace_op = &ftrace_list_end; - func = ftrace_ops_list_func; + ftrace_set_ufunc(&func, ftrace_ops_list_func); } update_function_graph_func(); /* If there's no change, then do nothing more here */ - if (ftrace_trace_function == func) + if (ftrace_trace_function == func.ops) return; /* * If we are using the list function, it doesn't care * about the function_trace_ops. */ - if (func == ftrace_ops_list_func) { - ftrace_trace_function = func; + if (ftrace_same_address_ufunc(&func, ftrace_ops_list_func)) { + ftrace_trace_function = func.ops; /* * Don't even bother setting function_trace_ops, * it would be racy to do so anyway. @@ -272,7 +277,9 @@ static void update_ftrace_function(void) * function we want, albeit indirectly, but it handles the * ftrace_ops and doesn't depend on function_trace_op. */ - ftrace_trace_function = ftrace_ops_list_func; + ftrace_set_ufunc(&tmp, ftrace_ops_list_func); + ftrace_trace_function = tmp.ops; + /* * Make sure all CPUs see this. Yes this is slow, but static * tracing is slow and nasty to have enabled. @@ -287,7 +294,7 @@ static void update_ftrace_function(void) /* OK, we are all set to update the ftrace_trace_function now! */ #endif /* !CONFIG_DYNAMIC_FTRACE */ - ftrace_trace_function = func; + ftrace_trace_function = func.ops; } static void add_ftrace_ops(struct ftrace_ops __rcu **list, @@ -2680,6 +2687,7 @@ void ftrace_modify_all_code(int command) int update = command & FTRACE_UPDATE_TRACE_FUNC; int mod_flags = 0; int err = 0; + union ftrace_func func; if (command & FTRACE_MAY_SLEEP) mod_flags = FTRACE_MODIFY_MAY_SLEEP_FL; @@ -2695,7 +2703,8 @@ void ftrace_modify_all_code(int command) * traced. */ if (update) { - err = ftrace_update_ftrace_func(ftrace_ops_list_func); + ftrace_set_ufunc(&func, ftrace_ops_list_func); + err = ftrace_update_ftrace_func(func.ops); if (FTRACE_WARN_ON(err)) return; } @@ -2705,7 +2714,9 @@ void ftrace_modify_all_code(int command) else if (command & FTRACE_DISABLE_CALLS) ftrace_replace_code(mod_flags); - if (update && ftrace_trace_function != ftrace_ops_list_func) { + ftrace_set_ufunc(&func, ftrace_ops_list_func); + + if (update && ftrace_trace_function != func.ops) { function_trace_op = set_function_trace_op; smp_wmb(); /* If irqs are disabled, we are in stop machine */ @@ -6890,14 +6901,13 @@ static void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip, { __ftrace_ops_list_func(ip, parent_ip, NULL, regs); } -NOKPROBE_SYMBOL(ftrace_ops_list_func); #else -static void ftrace_ops_no_ops(unsigned long ip, unsigned long parent_ip) +static void ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip) { __ftrace_ops_list_func(ip, parent_ip, NULL, NULL); } -NOKPROBE_SYMBOL(ftrace_ops_no_ops); #endif +NOKPROBE_SYMBOL(ftrace_ops_list_func); /* * If there's only one function registered but it does not support