From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 74752 invoked by alias); 3 Mar 2020 18:43:25 -0000 Mailing-List: contact gdb-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-owner@sourceware.org Received: (qmail 74744 invoked by uid 89); 3 Mar 2020 18:43:25 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-5.5 required=5.0 tests=AWL,BAYES_50,GIT_PATCH_2,KAM_SHORT,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.1 spammy=sk:stackc, sk:stack-c, blog, H*f:hVBKidLXDc7A4o X-HELO: mail-qk1-f175.google.com Received: from mail-qk1-f175.google.com (HELO mail-qk1-f175.google.com) (209.85.222.175) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 03 Mar 2020 18:43:23 +0000 Received: by mail-qk1-f175.google.com with SMTP id h22so4454495qke.5 for ; Tue, 03 Mar 2020 10:43:23 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to; bh=FoXGuU+pMXYBYeSG08nadWItc8dtVG9P96VP0bZ5+RU=; b=DFG6nIFdS93GLJPCXqy8cxbcKBGr+yXnBVMmEG66nUbZTqXGspJVpgqLY4v9E1cwdY 7CNeXNGGfd41Yra/3wEP4d6ZMXj+lecsMD/3KrDZS6YHfUIhC7B+HynskdsUlOH8Jey4 NxEbrmovumWx/lU9nCB6To8LybxT2QZDuRd7crAOFFvAf9OKXQ3v0iVLRqohU/7HACPx lubzEURU7EmffFQR8bDq+nduG4+ygOx/hqknmCBmlRs3g7RMqvBT0LJxpheNUenGWsRU 2A7eiohxu3b8XKY9ZBCUilCZTc94+SvYP6QmiwqQ6FVWcolKGezgwlqOvKvGXQ6wyDIg RKUA== MIME-Version: 1.0 References: In-Reply-To: From: Maxim Blinov Date: Tue, 03 Mar 2020 18:43:00 -0000 Message-ID: Subject: Fwd: use of %fs segment register in x86_64 with -fstack-check To: gdb@sourceware.org Content-Type: text/plain; charset="UTF-8" X-SW-Source: 2020-03/txt/msg00004.txt (Sorry, forgot to CC gdb ml) ---------- Forwarded message --------- From: Maxim Blinov Date: Tue, 3 Mar 2020 at 18:37 Subject: Re: use of %fs segment register in x86_64 with -fstack-check To: Ruslan Kabatsayev Hi Ruslan, thankyou for your explanations. Unfortunately, I still can't see the whole picture. On Tue, 3 Mar 2020 at 16:51, Ruslan Kabatsayev wrote: > Not quite. As noted at [1] this OR is to ensure that stack hasn't > overflowed. This is the part added by -fstack-check (you can see it go > away when you remove this option). See [2] for documentation. I don't understand how the OR insns check that the stack hasn't overflowed. >From [1], the author writes "it just inserts a NULL byte". What is *it* in this context? I don't see anyone writing anything to the stack in the assembly. Does linux do it on our behalf, and then the OR insns check that those bytes are indeed NULL? Furthermore, I can't see who uses the result of the OR operation. I'm under the impression that there is some page fault magic happening under the hood, but what is that magic? No insns after the ORs perform any conditional jumps based on the ORs results that I can see (although I am not very knowledgeable about x86_64 asm.) So I am still confused. I did read [2] before posting, but unfortunately I didn't find it very helpful. I tried to step through each insn in my head to demonstrate where i dont get it: 0x555555554560
sub $0x2f78,%rsp Ok, whatever %rsp was, its now %rsp - 12152. Thats a lot more than 8000, but fine. Lets call %rsp before we subtracted it "%original". 0x555555554567 orq $0x0,0xf58(%rsp) Ok, we OR with memory location %rsp + 3928. Taking into account the previous offset, we're accessing %original + (3928 - 12152) which is %original - 8224. So this is about 200 bytes after the stack array ends. The instruction doesn't change the value at 0xf58(%rsp). My understanding is that this instruction will fetch the quadword at 0xf58(%rsp), OR it with $0x0, and then store the result of that computation back to the same address. How does this check that no stack overflow has occurred? 0x555555554570 orq $0x0,(%rsp) We do it again, this time at %original - 12152 (the bottom of the stack). Is this because we might span over two pages? 0x555555554575 add $0x1020,%rsp Now we set %rsp to be %original - 8024. So now we are actually pointing to the stack byte just after the large array. 0x55555555457c mov %rsp,%rdi Now we save %rsp to %rdi, despite %rdi not being used anywhere... not sure about this one. 0x55555555457f mov %fs:0x28,%rax Load the magic sentinel pattern, OK. 0x555555554588 mov %rax,0x1f48(%rsp) 0x1f48 corresponds to %original - 16. So we are writing a sentinel value to almost the start of the stack for this func. 0x555555554590 xor %eax,%eax 0x555555554592 callq 0x5555555546d0 Clear %eax for foo's return value and call foo. 0x555555554597 mov 0x1f48(%rsp),%rdx 0x55555555459f xor %fs:0x28,%rdx 0x5555555545a8 jne 0x5555555545b4 Now we double-check that the sentinel value at %original - 16 is exactly the same as it was before we called foo, and if it isn't, we go to __stack_chk_fail. So, this protects us against the case where foo trashed the start of our stack? 0x5555555545aa xor %eax,%eax 0x5555555545ac add $0x1f58,%rsp 0x5555555545b3 retq Clear our own return value, cleanup the stack, and exit. I just don't understand how the ORs are ensuring the stack hasn't overflowed. > Right. But note that this is enabled not by -fstack-check, but rather > by some of the -fstack-protector* options that are on by default on > modern Linux distributions. You can confirm this by explicitly passing > -fno-stack-protector and seeing this sentinel checking gone. Ok, I see. > The FS segment base points to the TLS. See [3] and links therein. ... > It's the offset of stack_guard member of tcbhead_t. See the > corresponding glibc source [4]. Got it, thankyou. > [1]: https://stackoverflow.com/a/44670648/673852 > [2]: https://gcc.gnu.org/onlinedocs/gccint/Stack-Checking.html > [3]: https://chao-tic.github.io/blog/2018/12/25/tls > [4]: https://code.woboq.org/userspace/glibc/sysdeps/x86_64/nptl/tls.h.html#42 > > Regards, > Ruslan