From patchwork Sat Dec 10 09:08:21 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: stsp X-Patchwork-Id: 31996 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:f944:0:0:0:0:0 with SMTP id q4csp1220873wrr; Sat, 10 Dec 2022 01:38:42 -0800 (PST) X-Google-Smtp-Source: AA0mqf7KPuxX3Sivg5K6fRtbFyLB5WtwuTqQm+xk+MOe8NLGCjBF/13/1/BU4UiR4BqZCiV9i1Te X-Received: by 2002:aa7:cd6f:0:b0:46c:3f90:f5d9 with SMTP id ca15-20020aa7cd6f000000b0046c3f90f5d9mr8516214edb.5.1670665122502; Sat, 10 Dec 2022 01:38:42 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1670665122; cv=none; d=google.com; s=arc-20160816; b=GhEoiIINcHOzZuTQQhgfWUGXnIsa+9q3+utHOF0jahghu8GtsxZeB73dDmdl40Yknq 3l0ExnCLpMwhyVQUoltCgf4FARuWTRPCCXrzwfbtu6Z999t9s82kzMliSt7jz3MZBqjO GX4n+AglHFg/m3U0pmyHo1MBmFt1SZm9YXtlowJ1mvkZaZ5ISbPOwcDfkiOk9xni6zES VlHDaAdwVft2QzS5Ba6PrC+agcSwfNejxt6AYmpB1BuORuaB5qS0ahdebWopj1lVGm/r axC8F5Bz+AccFqtqmSPepO4R4YfwYji+AV4cnSzdDvFlTgZ8LCsBzL9r1td8q4447LuD zTgg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:subject:from:cc:to:content-language:user-agent :mime-version:date:message-id:dkim-signature; bh=qfTbbs5wGTfTJ4tPkL8vGo/Ec4Ffv9XAZVjHA8GXlwI=; b=oCs4EeyQ7fTb0qRLloK35i75wGHWWu0n4o48n+OUk+Shw3F+9ZU+hWz75zjtZ8+SYF A3Sid4kqUiK7of2fXUHWI0JlZu7zU+1r/l3XNFXXF1iWvY7DQ3Rm5quvcVsf8pP6e72I F+XnkuoGfwoX5ypaEqosRhs8tv8NMJbB3bR/9bieRQlH2YYaMSW3vvkO62VCYIzsWhCE EjdGXep+hxwKFSY757xuZF8iTNbBWJOYJAv5rZ30gdp2Cii08SjbhPe9QFm3EaLt/PE+ nSKt9ygbA3ef0ZSyXDS84vxumn4dKotOmBGAvn0o0Q7xQFVFR59AvR3LRJd/TVJ417+S eLUA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@yandex.ru header.s=mail header.b=izWNDftH; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=yandex.ru Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id be23-20020a0564021a3700b0046cc68a5eb9si3186903edb.617.2022.12.10.01.38.18; Sat, 10 Dec 2022 01:38:42 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@yandex.ru header.s=mail header.b=izWNDftH; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=yandex.ru Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230007AbiLJJPc (ORCPT + 99 others); Sat, 10 Dec 2022 04:15:32 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:53728 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230009AbiLJJO4 (ORCPT ); Sat, 10 Dec 2022 04:14:56 -0500 X-Greylist: delayed 337 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Sat, 10 Dec 2022 01:14:05 PST Received: from forward106p.mail.yandex.net (forward106p.mail.yandex.net [IPv6:2a02:6b8:0:1472:2741:0:8b7:109]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 210162710; Sat, 10 Dec 2022 01:14:04 -0800 (PST) Received: from sas8-d2832c3b6ed7.qloud-c.yandex.net (sas8-d2832c3b6ed7.qloud-c.yandex.net [IPv6:2a02:6b8:c1b:2a09:0:640:d283:2c3b]) by forward106p.mail.yandex.net (Yandex) with ESMTP id 813A32FC21E3; Sat, 10 Dec 2022 12:08:23 +0300 (MSK) Received: by sas8-d2832c3b6ed7.qloud-c.yandex.net (smtp/Yandex) with ESMTPSA id L8X4Vd8YGa61-pBBFfpeV; Sat, 10 Dec 2022 12:08:23 +0300 X-Yandex-Fwd: 1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yandex.ru; s=mail; t=1670663303; bh=qfTbbs5wGTfTJ4tPkL8vGo/Ec4Ffv9XAZVjHA8GXlwI=; h=Subject:Cc:To:Message-ID:Date:From; b=izWNDftH4f8HIlVhxqcGt4kQv0R/ZDeF8uG7RA5jsQwq9DbfOVXZjJYWfl134YGAp O6BGpN90yQGlSPOJ4CglIq9bmx0KHr/aN2zXV5QYm9oXPQrNGefe3rszRXx4fImjHq m7KJJlTwAtTt4h2sa4LjJ3cN0ZwPU30FrMHNDXCg= Authentication-Results: sas8-d2832c3b6ed7.qloud-c.yandex.net; dkim=pass header.i=@yandex.ru Message-ID: <85ca9ae1-d319-ee77-4a71-bc9c7874f2cb@yandex.ru> Date: Sat, 10 Dec 2022 14:08:21 +0500 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.4.2 Content-Language: en-US To: linux-kernel@vger.kernel.org Cc: linux-x86_64@vger.kernel.org, luto@kernel.org From: stsp Subject: strange behavior with sigreturn() to 32bit X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1751819351693018677?= X-GMAIL-MSGID: =?utf-8?q?1751819351693018677?= Hi. I am playing with 32bit compatibility segments, and I am observing something very strange. To demonstrate the problem, I did the change to the kernel sigreturn test-case, and it is attached. The change just moves the magic value to EAX and calls an interrupt that produces a SIGSEGV. The SIGSEGV handler prints the needed regs. This patch intentionally adds 0x100000000 to the RIP register, because AFAIK the high part or 64bit regs are irrelevant in compatibility mode. Now with high part of RIP non-zero, we see this: $ ./sigreturn_64 err=0 trapno=d ax=0 ip=100000003 OK, obviously our asm code didn't execute - why is so? How does the high part of RIP affect compatibility mode? Then lets start the same example under gdb: Program received signal SIGSEGV, Segmentation fault. 0x0000000000403008 in int31 () (gdb) Continuing. err=18a trapno=d ax=a5f3 ip=403008 Wow! Much better now: error code is correct, ax is correct, but ip is invalid. Now lets remove that high-part trashing from source and recompile, then run again: $ ./sigreturn_64 err=0 trapno=d ax=a5f3 ip=6 This time error code is incorrect! All other values are good. Lets see under gdb: err=18a trapno=d ax=a5f3 ip=403008 Cool, under gdb the err code fixed itself but IP is wrong... Can anyone make any sense out of this? :) To me it seems completely chaotic and I suspect both sigreturn() and ptrace() are somehow "broken" here. diff --git a/tools/testing/selftests/x86/sigreturn.c b/tools/testing/selftests/x86/sigreturn.c index 5d7961a5f7f6..6c8f2431d77d 100644 --- a/tools/testing/selftests/x86/sigreturn.c +++ b/tools/testing/selftests/x86/sigreturn.c @@ -101,9 +101,14 @@ asm (".pushsection .text\n\t" "mov %ss,%ecx\n\t" "int3\n\t" ".size int3, . - int3\n\t" + ".type int31, @function\n\t" + "int31:\n\t" + "movl $0xa5f3, %eax\n\t" + "int $0x31\n\t" ".align 4096, 0xcc\n\t" ".popsection"); extern char int3[4096]; +extern char int31[]; /* * At startup, we prepapre: @@ -296,6 +301,7 @@ static volatile sig_atomic_t sig_corrupt_final_ss; # define REG_IP REG_RIP # define REG_SP REG_RSP # define REG_CX REG_RCX +# define REG_AX REG_RAX struct selectors { unsigned short cs, gs, fs, ss; @@ -316,6 +322,7 @@ static unsigned short *csptr(ucontext_t *ctx) # define REG_IP REG_EIP # define REG_SP REG_ESP # define REG_CX REG_ECX +# define REG_AX REG_EAX static greg_t *ssptr(ucontext_t *ctx) { @@ -444,9 +451,12 @@ static void sigusr1(int sig, siginfo_t *info, void *ctx_void) *ssptr(ctx) = sig_ss; ctx->uc_mcontext.gregs[REG_IP] = - sig_cs == code16_sel ? 0 : (unsigned long)&int3; + sig_cs == code16_sel ? ((unsigned long)&int31 - + (unsigned long)&int3) | 0x100000000 : + (unsigned long)&int3; ctx->uc_mcontext.gregs[REG_SP] = (unsigned long)0x8badf00d5aadc0deULL; ctx->uc_mcontext.gregs[REG_CX] = 0; + ctx->uc_mcontext.gregs[REG_AX] = 0; #ifdef __i386__ /* @@ -515,6 +525,20 @@ static void sigtrap(int sig, siginfo_t *info, void *ctx_void) sig_trapped = sig; } +static void sigsegv(int sig, siginfo_t *info, void *ctx_void) +{ + ucontext_t *ctx = (ucontext_t*)ctx_void; + + validate_signal_ss(sig, ctx); + + sig_err = ctx->uc_mcontext.gregs[REG_ERR]; + sig_trapno = ctx->uc_mcontext.gregs[REG_TRAPNO]; + printf("err=%x trapno=%x ax=%x ip=%llx\n", sig_err, sig_trapno, + (unsigned)ctx->uc_mcontext.gregs[REG_AX], + (unsigned long long)ctx->uc_mcontext.gregs[REG_IP]); + _exit(0); +} + #ifdef __x86_64__ /* Tests recovery if !UC_STRICT_RESTORE_SS */ static void sigusr2(int sig, siginfo_t *info, void *ctx_void) @@ -777,6 +801,7 @@ int main() sethandler(SIGUSR1, sigusr1, 0); sethandler(SIGTRAP, sigtrap, SA_ONSTACK); + sethandler(SIGSEGV, sigsegv, SA_ONSTACK); /* Easy cases: return to a 32-bit SS in each possible CS bitness. */ total_nerrs += test_valid_sigreturn(64, false, -1);