From owner-freebsd-arch@FreeBSD.ORG Mon Sep 3 23:17:36 2007 Return-Path: Delivered-To: arch@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 5ABEA16A419; Mon, 3 Sep 2007 23:17:36 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from fallbackmx02.syd.optusnet.com.au (fallbackmx02.syd.optusnet.com.au [211.29.133.72]) by mx1.freebsd.org (Postfix) with ESMTP id E9B5C13C459; Mon, 3 Sep 2007 23:17:35 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from mail35.syd.optusnet.com.au (mail35.syd.optusnet.com.au [211.29.133.51]) by fallbackmx02.syd.optusnet.com.au (8.12.11.20060308/8.12.11) with ESMTP id l831JCan001016; Mon, 3 Sep 2007 11:19:12 +1000 Received: from c220-239-235-248.carlnfd3.nsw.optusnet.com.au (c220-239-235-248.carlnfd3.nsw.optusnet.com.au [220.239.235.248]) by mail35.syd.optusnet.com.au (8.13.1/8.13.1) with ESMTP id l831Ib07017221 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 3 Sep 2007 11:18:44 +1000 Date: Mon, 3 Sep 2007 11:18:37 +1000 (EST) From: Bruce Evans X-X-Sender: bde@delplex.bde.org To: Roman Divacky In-Reply-To: <20070902173953.GA52566@freebsd.org> Message-ID: <20070903105130.L48985@delplex.bde.org> References: <20070902173953.GA52566@freebsd.org> MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed Cc: arch@freebsd.org, i386@freebsd.org Subject: Re: PSL_RF inclusion in PSL_USERCHANGE for i386 X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 03 Sep 2007 23:17:36 -0000 On Sun, 2 Sep 2007, Roman Divacky wrote: > in i386/i386/machdep.c the set_regs() function sets i386 registers (called > by ptrace for example). it checks what eflags are being changed and compares > that with a mask of allowed flags to be changed. the mask is defined in psl.h > like this: > > #define PSL_USERCHANGE (PSL_C | PSL_PF | PSL_AF | PSL_Z | PSL_N | PSL_T \ > | PSL_D | PSL_V | PSL_NT | PSL_AC | PSL_ID) > > PSL_RF (Flag to ensure single-step only happens once per instruction.). Can someone > tell me why this is omitted? I think its because of having in-kernel debugger. I think it is just because user mode cannot set this flag directly, except probably in vm86 mode (vm86 support code already has special cases for it). (Old) docs say that it can be set by popfl and iret, but popfl doesn't set it for me now and user mode cannot execute iret (?). > User-mode Linux requires this to be allowed. So I wonder why this is disabled in FreeBSD. > (Linux itself does not check the eflags in any way). > > thanks for answer, and/or pointer to answer FreeBSD allows setting or at least preserving it in sigreturn(). See my large comment in sigreturn(). The comment has been copied ad nauseum into 3 versions of sigreturn(), so removing this special case would be a large cleanup. According to the comment, for user mode it is the CPU that sets PSL_RF for faults (for all faults or only for debug faults, so that faults can be restarted without interference from debuggers. I think the CPU also automatically clears PSL_RF after executing 1 instruction, so it is hard to observe it as set and hard to see how setting it in set_regs() could have any effect. Well, set_regs() is just an easier way to set registers than sigreturn(). sigreturn() omits PSL_RF from its security check, so there there is no possibility of a _new_ security hole from omitting the check in set_regs() too. (But better put PSL_RF in PSL_USERCHANGE and remove all the special cases). After return to user mode with PSL_RF set, I think PSL_RF affects only the first instruction in user mode, so any changes in effects would be observable only there. Please check that something reasonable happens. The user mode code is something like: int $0x80 # syscall xxx # some instruction -- what happens for # hardware breakpoints, etc., on this # instruction. I vaguely remember problems (perhaps under another OS) with debugging the first instruction after a syscall returns. Perhaps they are still there and are caused by precisely the resume flag, if the resume flag is set automatically by int $N or if the kernel sets it. Allowing set_regs() to set the resume flag might cause the same problem for just the ptrace/procfs calls that use set_regs() if it doesn't affect all syscalls. It's hard to see how this problem could actually be a feature. To use it as a feature, userland would have to ensure that the xxx in the above is a certain instruction that benefits from this behaviour. Bruce