Details
Diff Detail
- Repository
- rS FreeBSD src repository - subversion
- Lint
Lint Not Applicable - Unit
Tests Not Applicable
Event Timeline
If nobody has used this in 23 years and it's not present in other platforms do we need this?
So this doesn't get lost this is the original change in SVN. It dates back before FreeBSD 2.0
https://svnweb.freebsd.org/base/head/sys/i386/i386/machdep.c?r1=4193&r2=4201
Well, preserving the trace flag is IMO reasonable behavior.
I believe the history of the PSL_T on exec is more involved because bzero() seems to disappeared after the commit you mentioned.
With LLDB I can single step across an exec so we must be setting the trap flag elsewhere for ptrace() to work.
I see bzero in every major release including 2.0, 3.0, 4.0, and 5.0
https://svnweb.freebsd.org/base/release/2.0/sys/i386/i386/machdep.c?revision=4762&view=markup#l865
https://svnweb.freebsd.org/base/release/3.0.0/sys/i386/i386/machdep.c?revision=42952&view=markup#l832
https://svnweb.freebsd.org/base/release/4.0.0/sys/i386/i386/machdep.c?revision=58337&view=markup#l1015
https://svnweb.freebsd.org/base/release/5.0.0/sys/i386/i386/machdep.c?revision=109388&view=markup#l1063
Probably you should fix or remove the dead code in the linux compat layer as well.
sys/amd64/linux/linux_sysvec.c Line 412
sys/amd64/linux32/linux32_sysvec.c Line 761
It seems like all this was originally to support exect() and isn't needed since it's never worked past FreeBSD 2.0.
I find that hard to believe, given that the cvs versions before 2.0 do not exist in svn, or ncvs, and should only exist in an offline repository called cvs.
Well the SVN revisions might be bogus because of the transition from CVS. But I'm assuming the dates and the snapshots of the releases are correct.
r4201 is where the bzero() was introduced to setregs() on Nov. 6, 1994
r4762 is the creation of RELEASE_2_0 on Nov. 22, 1994
https://svnweb.freebsd.org/base/release/2.0/sys/i386/i386/machdep.c?revision=4762&view=markup#l865
In any case the changes look good. Just do something about the Linux compat files I listed as well.
Yea, that is an "artifact" of cvs2svn, the actual svn version of the file shipped is 4221. You can see that if you use the Select for diff on version 4762 the diff to 4221 is null.
Either way if this bug has existed since then it clearly indicates this code is dead.
The reason I harped on the "Before 2.0" is that technically all 1.x code is to be unpublished by Agreement with AT&T/USL.
The time frame you are looking at here is 2.0, very near its actual release.
Yet, it's widely available. For example, you can find it at https://github.com/dspinellis/unix-history-repo/tree/FreeBSD-release/1.0-Import as well as all the pre-history of FreeBSD in the 386BSD + patchkit era. We're long past the time where it really matters for everybody that wasn't a direct party to that agreement, since there's no legal entity that could make an agreement on my behalf, since I wasn't even part of the project at the time, and the agreement was secret for years.
You can find a single points in time, namely the src's from the releases, that is not the cvs files. I am a party to the agreement, the agreement is still secret, though the UCB version is public. And as far as I know the "project" and Walnut Creeks hiers are still bound by that agreement.
After reviewing this stuff once more, I think that PSL_T inheritance should be done for a reason different than exect(3). Assume that the process was set for single-step with ptrace(PT_SETSTEP). Then, execve(2) must not clear the command.
We currently provide the exec stop event for execve(2) to debuggers, which is why debuggers typically work. But if you single-step a program and step into a syscall, then exec knocks off debugger despite reporting exec event.
Then this raises the question: should setuid/setgid binary execution inherit PSL_T ? We do not change credentials if the process is traced. Also, we reset signal handlers disposition on exec. So for setuid process, the result of inheritance is un-caught SIGTRAP.
I noticed PSL_T flag is masked out in the trap and system call entry path. It only gets set again by ptrace(PT_STEP, ...). This appears to be intentional because of the way ptrace() is being used.
The result is that the kernel doesn't preserve the trap flag if a user space application sets it. In the example below, the program receives only one signal. It is possible set the trap flag in the signal handler to keep receiving signals (tested it works).
This doesn't appear to be the behavior on other platforms but I didn't run it on my other architectures yet. I did test OS X which also doesn't clear the flag,, but then again it doesn't preserve PSL_T across execve().
This seems to have implications to this patch. Maybe there's a bigger discussion on the expected behavior around ptrace, PSL_T, and user space tracing itself.
https://svnweb.freebsd.org/base/head/sys/amd64/amd64/trap.c?revision=331650&view=markup#l925
sys/amd64/trap.c:
See Line 279 trap() & Line 942 amd64_syscall()
Example
static void sigtrap_handler(int sig, siginfo_t *info, void *ctx) { assert(sig == SIGTRAP); assert(info->si_code == TRAP_TRACE); ++caught; } int main(int argc, const char *argv[]) { struct sigaction act; assert(sigemptyset(&act.sa_mask) == 0); act.sa_sigaction = sigtrap_handler; act.sa_flags = SA_SIGINFO; assert(sigaction(SIGTRAP, &act, 0) == 0); printf("expected caught (1), received (%d)\n", caught); settrace(); /* sets PSL_T */ for (int i = 0; i < 5; i++) { printf("Hello\n"); } printf("expected caught (1), received (%d)\n", caught); }
Output:
expected caught (1), received (0) Hello Hello Hello Hello Hello expected caught (1), received (1)