Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
linux
Commits
60c1b773
Commit
60c1b773
authored
Nov 21, 2002
by
Jeff Dike
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Added a bunch of C files under arch/um/kernel/skas and
arch/um/kernel/tt.
parent
651542f6
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
610 additions
and
0 deletions
+610
-0
arch/um/kernel/skas/include/proc_mm.h
arch/um/kernel/skas/include/proc_mm.h
+55
-0
arch/um/kernel/tt/syscall_user.c
arch/um/kernel/tt/syscall_user.c
+90
-0
arch/um/kernel/tt/tracer.c
arch/um/kernel/tt/tracer.c
+465
-0
No files found.
arch/um/kernel/skas/include/proc_mm.h
0 → 100644
View file @
60c1b773
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#ifndef __SKAS_PROC_MM_H
#define __SKAS_PROC_MM_H
#define MM_MMAP 54
#define MM_MUNMAP 55
#define MM_MPROTECT 56
#define MM_COPY_SEGMENTS 57
struct
mm_mmap
{
unsigned
long
addr
;
unsigned
long
len
;
unsigned
long
prot
;
unsigned
long
flags
;
unsigned
long
fd
;
unsigned
long
offset
;
};
struct
mm_munmap
{
unsigned
long
addr
;
unsigned
long
len
;
};
struct
mm_mprotect
{
unsigned
long
addr
;
unsigned
long
len
;
unsigned
int
prot
;
};
struct
proc_mm_op
{
int
op
;
union
{
struct
mm_mmap
mmap
;
struct
mm_munmap
munmap
;
struct
mm_mprotect
mprotect
;
int
copy_segments
;
}
u
;
};
#endif
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-file-style: "linux"
* End:
*/
arch/um/kernel/tt/syscall_user.c
0 → 100644
View file @
60c1b773
/*
* Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/ptrace.h>
#include <asm/unistd.h>
#include "sysdep/ptrace.h"
#include "sigcontext.h"
#include "ptrace_user.h"
#include "task.h"
#include "user_util.h"
#include "kern_util.h"
#include "syscall_user.h"
#include "tt.h"
/* XXX Bogus */
#define ERESTARTSYS 512
#define ERESTARTNOINTR 513
#define ERESTARTNOHAND 514
void
syscall_handler_tt
(
int
sig
,
struct
uml_pt_regs
*
regs
)
{
void
*
sc
;
long
result
;
int
index
,
syscall
;
syscall
=
regs
->
syscall
;
sc
=
regs
->
mode
.
tt
;
sc_to_regs
(
regs
,
sc
,
syscall
);
SC_START_SYSCALL
(
sc
);
index
=
record_syscall_start
(
syscall
);
syscall_trace
();
result
=
execute_syscall
(
regs
);
/* regs->sc may have changed while the system call ran (there may
* have been an interrupt or segfault), so it needs to be refreshed.
*/
regs
->
mode
.
tt
=
sc
;
SC_SET_SYSCALL_RETURN
(
sc
,
result
);
if
((
result
==
-
ERESTARTNOHAND
)
||
(
result
==
-
ERESTARTSYS
)
||
(
result
==
-
ERESTARTNOINTR
))
do_signal
(
result
);
syscall_trace
();
record_syscall_end
(
index
,
result
);
}
int
do_syscall
(
void
*
task
,
int
pid
)
{
unsigned
long
proc_regs
[
FRAME_SIZE
];
struct
uml_pt_regs
*
regs
;
int
syscall
;
if
(
ptrace_getregs
(
pid
,
proc_regs
)
<
0
)
tracer_panic
(
"Couldn't read registers"
);
syscall
=
PT_SYSCALL_NR
(
proc_regs
);
regs
=
TASK_REGS
(
task
);
UPT_SYSCALL_NR
(
regs
)
=
syscall
;
if
(
syscall
<
1
)
return
(
0
);
if
((
syscall
!=
__NR_sigreturn
)
&&
((
unsigned
long
*
)
PT_IP
(
proc_regs
)
>=
&
_stext
)
&&
((
unsigned
long
*
)
PT_IP
(
proc_regs
)
<=
&
_etext
))
tracer_panic
(
"I'm tracing myself and I can't get out"
);
if
(
ptrace
(
PTRACE_POKEUSER
,
pid
,
PT_SYSCALL_NR_OFFSET
,
__NR_getpid
)
<
0
)
tracer_panic
(
"do_syscall : Nullifying syscall failed, "
"errno = %d"
,
errno
);
return
(
1
);
}
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-file-style: "linux"
* End:
*/
arch/um/kernel/tt/tracer.c
0 → 100644
View file @
60c1b773
/*
* Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
* Licensed under the GPL
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sched.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/ptrace.h>
#include <sys/time.h>
#include <sys/wait.h>
#include "user.h"
#include "sysdep/ptrace.h"
#include "sigcontext.h"
#include "sysdep/sigcontext.h"
#include "os.h"
#include "signal_user.h"
#include "user_util.h"
#include "mem_user.h"
#include "process.h"
#include "kern_util.h"
#include "frame.h"
#include "chan_user.h"
#include "ptrace_user.h"
#include "mode.h"
#include "tt.h"
static
int
tracer_winch
[
2
];
int
is_tracer_winch
(
int
pid
,
int
fd
,
void
*
data
)
{
if
(
pid
!=
tracing_pid
)
return
(
0
);
register_winch_irq
(
tracer_winch
[
0
],
fd
,
-
1
,
data
);
return
(
0
);
}
static
void
tracer_winch_handler
(
int
sig
)
{
char
c
=
1
;
if
(
write
(
tracer_winch
[
1
],
&
c
,
sizeof
(
c
))
!=
sizeof
(
c
))
printk
(
"tracer_winch_handler - write failed, errno = %d
\n
"
,
errno
);
}
/* Called only by the tracing thread during initialization */
static
void
setup_tracer_winch
(
void
)
{
int
err
;
err
=
os_pipe
(
tracer_winch
,
1
,
1
);
if
(
err
){
printk
(
"setup_tracer_winch : os_pipe failed, errno = %d
\n
"
,
-
err
);
return
;
}
signal
(
SIGWINCH
,
tracer_winch_handler
);
}
void
attach_process
(
int
pid
)
{
if
((
ptrace
(
PTRACE_ATTACH
,
pid
,
0
,
0
)
<
0
)
||
(
ptrace
(
PTRACE_CONT
,
pid
,
0
,
0
)
<
0
))
tracer_panic
(
"OP_FORK failed to attach pid"
);
wait_for_stop
(
pid
,
SIGSTOP
,
PTRACE_CONT
,
NULL
);
if
(
ptrace
(
PTRACE_CONT
,
pid
,
0
,
0
)
<
0
)
tracer_panic
(
"OP_FORK failed to continue process"
);
}
void
tracer_panic
(
char
*
format
,
...)
{
va_list
ap
;
va_start
(
ap
,
format
);
vprintf
(
format
,
ap
);
printf
(
"
\n
"
);
while
(
1
)
pause
();
}
static
void
tracer_segv
(
int
sig
,
struct
sigcontext
sc
)
{
printf
(
"Tracing thread segfault at address 0x%lx, ip 0x%lx
\n
"
,
SC_FAULT_ADDR
(
&
sc
),
SC_IP
(
&
sc
));
while
(
1
)
pause
();
}
/* Changed early in boot, and then only read */
int
debug
=
0
;
int
debug_stop
=
1
;
int
debug_parent
=
0
;
int
honeypot
=
0
;
static
int
signal_tramp
(
void
*
arg
)
{
int
(
*
proc
)(
void
*
);
if
(
honeypot
&&
munmap
((
void
*
)
(
host_task_size
-
0x10000000
),
0x10000000
))
panic
(
"Unmapping stack failed"
);
if
(
ptrace
(
PTRACE_TRACEME
,
0
,
0
,
0
)
<
0
)
panic
(
"ptrace PTRACE_TRACEME failed"
);
os_stop_process
(
os_getpid
());
change_sig
(
SIGWINCH
,
0
);
signal
(
SIGUSR1
,
SIG_IGN
);
change_sig
(
SIGCHLD
,
0
);
signal
(
SIGSEGV
,
(
__sighandler_t
)
sig_handler
);
set_cmdline
(
"(idle thread)"
);
set_init_pid
(
os_getpid
());
proc
=
arg
;
return
((
*
proc
)(
NULL
));
}
static
void
last_ditch_exit
(
int
sig
)
{
kmalloc_ok
=
0
;
signal
(
SIGINT
,
SIG_DFL
);
signal
(
SIGTERM
,
SIG_DFL
);
signal
(
SIGHUP
,
SIG_DFL
);
uml_cleanup
();
exit
(
1
);
}
static
void
sleeping_process_signal
(
int
pid
,
int
sig
)
{
switch
(
sig
){
/* These two result from UML being ^Z-ed and bg-ed. PTRACE_CONT is
* right because the process must be in the kernel already.
*/
case
SIGCONT
:
case
SIGTSTP
:
if
(
ptrace
(
PTRACE_CONT
,
pid
,
0
,
sig
)
<
0
)
tracer_panic
(
"sleeping_process_signal : Failed to "
"continue pid %d, errno = %d
\n
"
,
pid
,
sig
);
break
;
/* This happens when the debugger (e.g. strace) is doing system call
* tracing on the kernel. During a context switch, the current task
* will be set to the incoming process and the outgoing process will
* hop into write and then read. Since it's not the current process
* any more, the trace of those will land here. So, we need to just
* PTRACE_SYSCALL it.
*/
case
SIGTRAP
:
if
(
ptrace
(
PTRACE_SYSCALL
,
pid
,
0
,
0
)
<
0
)
tracer_panic
(
"sleeping_process_signal : Failed to "
"PTRACE_SYSCALL pid %d, errno = %d
\n
"
,
pid
,
sig
);
break
;
case
SIGSTOP
:
break
;
default:
tracer_panic
(
"sleeping process %d got unexpected "
"signal : %d
\n
"
,
pid
,
sig
);
break
;
}
}
/* Accessed only by the tracing thread */
int
debugger_pid
=
-
1
;
int
debugger_parent
=
-
1
;
int
debugger_fd
=
-
1
;
int
gdb_pid
=
-
1
;
struct
{
int
pid
;
int
signal
;
unsigned
long
addr
;
struct
timeval
time
;
}
signal_record
[
1024
][
32
];
int
signal_index
[
32
];
int
nsignals
=
0
;
int
debug_trace
=
0
;
extern
int
io_nsignals
,
io_count
,
intr_count
;
extern
void
signal_usr1
(
int
sig
);
int
tracing_pid
=
-
1
;
int
tracer
(
int
(
*
init_proc
)(
void
*
),
void
*
sp
)
{
void
*
task
=
NULL
;
unsigned
long
eip
=
0
;
int
status
,
pid
=
0
,
sig
=
0
,
cont_type
,
tracing
=
0
,
op
=
0
;
int
last_index
,
proc_id
=
0
,
n
,
err
,
old_tracing
=
0
,
strace
=
0
;
capture_signal_stack
();
signal
(
SIGPIPE
,
SIG_IGN
);
setup_tracer_winch
();
tracing_pid
=
os_getpid
();
printf
(
"tracing thread pid = %d
\n
"
,
tracing_pid
);
pid
=
clone
(
signal_tramp
,
sp
,
CLONE_FILES
|
SIGCHLD
,
init_proc
);
n
=
waitpid
(
pid
,
&
status
,
WUNTRACED
);
if
(
n
<
0
){
printf
(
"waitpid on idle thread failed, errno = %d
\n
"
,
errno
);
exit
(
1
);
}
if
((
ptrace
(
PTRACE_CONT
,
pid
,
0
,
0
)
<
0
)){
printf
(
"Failed to continue idle thread, errno = %d
\n
"
,
errno
);
exit
(
1
);
}
signal
(
SIGSEGV
,
(
sighandler_t
)
tracer_segv
);
signal
(
SIGUSR1
,
signal_usr1
);
set_handler
(
SIGINT
,
last_ditch_exit
,
SA_ONESHOT
|
SA_NODEFER
,
-
1
);
set_handler
(
SIGTERM
,
last_ditch_exit
,
SA_ONESHOT
|
SA_NODEFER
,
-
1
);
set_handler
(
SIGHUP
,
last_ditch_exit
,
SA_ONESHOT
|
SA_NODEFER
,
-
1
);
if
(
debug_trace
){
printf
(
"Tracing thread pausing to be attached
\n
"
);
stop
();
}
if
(
debug
){
if
(
gdb_pid
!=
-
1
)
debugger_pid
=
attach_debugger
(
pid
,
gdb_pid
,
1
);
else
debugger_pid
=
init_ptrace_proxy
(
pid
,
1
,
debug_stop
);
if
(
debug_parent
){
debugger_parent
=
os_process_parent
(
debugger_pid
);
init_parent_proxy
(
debugger_parent
);
err
=
attach
(
debugger_parent
);
if
(
err
){
printf
(
"Failed to attach debugger parent %d, "
"errno = %d
\n
"
,
debugger_parent
,
err
);
debugger_parent
=
-
1
;
}
else
{
if
(
ptrace
(
PTRACE_SYSCALL
,
debugger_parent
,
0
,
0
)
<
0
){
printf
(
"Failed to continue debugger "
"parent, errno = %d
\n
"
,
errno
);
debugger_parent
=
-
1
;
}
}
}
}
set_cmdline
(
"(tracing thread)"
);
while
(
1
){
if
((
pid
=
waitpid
(
-
1
,
&
status
,
WUNTRACED
))
<=
0
){
if
(
errno
!=
ECHILD
){
printf
(
"wait failed - errno = %d
\n
"
,
errno
);
}
continue
;
}
if
(
pid
==
debugger_pid
){
int
cont
=
0
;
if
(
WIFEXITED
(
status
)
||
WIFSIGNALED
(
status
))
debugger_pid
=
-
1
;
/* XXX Figure out how to deal with gdb and SMP */
else
cont
=
debugger_signal
(
status
,
cpu_tasks
[
0
].
pid
);
if
(
cont
==
PTRACE_SYSCALL
)
strace
=
1
;
continue
;
}
else
if
(
pid
==
debugger_parent
){
debugger_parent_signal
(
status
,
pid
);
continue
;
}
nsignals
++
;
if
(
WIFEXITED
(
status
))
;
#ifdef notdef
{
printf
(
"Child %d exited with status %d
\n
"
,
pid
,
WEXITSTATUS
(
status
));
}
#endif
else
if
(
WIFSIGNALED
(
status
)){
sig
=
WTERMSIG
(
status
);
if
(
sig
!=
9
){
printf
(
"Child %d exited with signal %d
\n
"
,
pid
,
sig
);
}
}
else
if
(
WIFSTOPPED
(
status
)){
proc_id
=
pid_to_processor_id
(
pid
);
sig
=
WSTOPSIG
(
status
);
if
(
signal_index
[
proc_id
]
==
1024
){
signal_index
[
proc_id
]
=
0
;
last_index
=
1023
;
}
else
last_index
=
signal_index
[
proc_id
]
-
1
;
if
(((
sig
==
SIGPROF
)
||
(
sig
==
SIGVTALRM
)
||
(
sig
==
SIGALRM
))
&&
(
signal_record
[
proc_id
][
last_index
].
signal
==
sig
)
&&
(
signal_record
[
proc_id
][
last_index
].
pid
==
pid
))
signal_index
[
proc_id
]
=
last_index
;
signal_record
[
proc_id
][
signal_index
[
proc_id
]].
pid
=
pid
;
gettimeofday
(
&
signal_record
[
proc_id
][
signal_index
[
proc_id
]].
time
,
NULL
);
eip
=
ptrace
(
PTRACE_PEEKUSER
,
pid
,
PT_IP_OFFSET
,
0
);
signal_record
[
proc_id
][
signal_index
[
proc_id
]].
addr
=
eip
;
signal_record
[
proc_id
][
signal_index
[
proc_id
]
++
].
signal
=
sig
;
if
(
proc_id
==
-
1
){
sleeping_process_signal
(
pid
,
sig
);
continue
;
}
task
=
cpu_tasks
[
proc_id
].
task
;
tracing
=
is_tracing
(
task
);
old_tracing
=
tracing
;
switch
(
sig
){
case
SIGUSR1
:
sig
=
0
;
op
=
do_proc_op
(
task
,
proc_id
);
switch
(
op
){
case
OP_TRACE_ON
:
arch_leave_kernel
(
task
,
pid
);
tracing
=
1
;
break
;
case
OP_REBOOT
:
case
OP_HALT
:
unmap_physmem
();
kmalloc_ok
=
0
;
ptrace
(
PTRACE_KILL
,
pid
,
0
,
0
);
return
(
op
==
OP_REBOOT
);
case
OP_NONE
:
printf
(
"Detaching pid %d
\n
"
,
pid
);
detach
(
pid
,
SIGSTOP
);
continue
;
default:
break
;
}
/* OP_EXEC switches host processes on us,
* we want to continue the new one.
*/
pid
=
cpu_tasks
[
proc_id
].
pid
;
break
;
case
SIGTRAP
:
if
(
!
tracing
&&
(
debugger_pid
!=
-
1
)){
child_signal
(
pid
,
status
);
continue
;
}
tracing
=
0
;
if
(
do_syscall
(
task
,
pid
))
sig
=
SIGUSR2
;
else
clear_singlestep
(
task
);
break
;
case
SIGPROF
:
if
(
tracing
)
sig
=
0
;
break
;
case
SIGCHLD
:
case
SIGHUP
:
sig
=
0
;
break
;
case
SIGSEGV
:
case
SIGIO
:
case
SIGALRM
:
case
SIGVTALRM
:
case
SIGFPE
:
case
SIGBUS
:
case
SIGILL
:
case
SIGWINCH
:
default:
tracing
=
0
;
break
;
}
set_tracing
(
task
,
tracing
);
if
(
!
tracing
&&
old_tracing
)
arch_enter_kernel
(
task
,
pid
);
if
(
!
tracing
&&
(
debugger_pid
!=
-
1
)
&&
(
sig
!=
0
)
&&
(
sig
!=
SIGALRM
)
&&
(
sig
!=
SIGVTALRM
)
&&
(
sig
!=
SIGSEGV
)
&&
(
sig
!=
SIGTRAP
)
&&
(
sig
!=
SIGUSR2
)
&&
(
sig
!=
SIGIO
)){
child_signal
(
pid
,
status
);
continue
;
}
if
(
tracing
){
if
(
singlestepping
(
task
))
cont_type
=
PTRACE_SINGLESTEP
;
else
cont_type
=
PTRACE_SYSCALL
;
}
else
cont_type
=
PTRACE_CONT
;
if
((
cont_type
==
PTRACE_CONT
)
&&
(
debugger_pid
!=
-
1
)
&&
strace
)
cont_type
=
PTRACE_SYSCALL
;
if
(
ptrace
(
cont_type
,
pid
,
0
,
sig
)
!=
0
){
tracer_panic
(
"ptrace failed to continue "
"process - errno = %d
\n
"
,
errno
);
}
}
}
return
(
0
);
}
static
int
__init
uml_debug_setup
(
char
*
line
,
int
*
add
)
{
char
*
next
;
debug
=
1
;
*
add
=
0
;
if
(
*
line
!=
'='
)
return
(
0
);
line
++
;
while
(
line
!=
NULL
){
next
=
strchr
(
line
,
','
);
if
(
next
)
*
next
++
=
'\0'
;
if
(
!
strcmp
(
line
,
"go"
))
debug_stop
=
0
;
else
if
(
!
strcmp
(
line
,
"parent"
))
debug_parent
=
1
;
else
printk
(
"Unknown debug option : '%s'
\n
"
,
line
);
line
=
next
;
}
return
(
0
);
}
__uml_setup
(
"debug"
,
uml_debug_setup
,
"debug
\n
"
" Starts up the kernel under the control of gdb. See the
\n
"
" kernel debugging tutorial and the debugging session pages
\n
"
" at http://user-mode-linux.sourceforge.net/ for more information.
\n\n
"
);
static
int
__init
uml_debugtrace_setup
(
char
*
line
,
int
*
add
)
{
debug_trace
=
1
;
return
0
;
}
__uml_setup
(
"debugtrace"
,
uml_debugtrace_setup
,
"debugtrace
\n
"
" Causes the tracing thread to pause until it is attached by a
\n
"
" debugger and continued. This is mostly for debugging crashes
\n
"
" early during boot, and should be pretty much obsoleted by
\n
"
" the debug switch.
\n\n
"
);
static
int
__init
uml_honeypot_setup
(
char
*
line
,
int
*
add
)
{
jail_setup
(
""
,
add
);
honeypot
=
1
;
return
0
;
}
__uml_setup
(
"honeypot"
,
uml_honeypot_setup
,
"honeypot
\n
"
" This makes UML put process stacks in the same location as they are
\n
"
" on the host, allowing expoits such as stack smashes to work against
\n
"
" UML. This implies 'jail'.
\n\n
"
);
/*
* Overrides for Emacs so that we follow Linus's tabbing style.
* Emacs will notice this stuff at the end of the file and automatically
* adjust the settings for this buffer only. This must remain at the end
* of the file.
* ---------------------------------------------------------------------------
* Local variables:
* c-file-style: "linux"
* End:
*/
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment