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
687bc18d
Commit
687bc18d
authored
Feb 07, 2003
by
Daniel Jacobowitz
Browse files
Options
Browse Files
Download
Plain Diff
Hand merge
parents
8eae2998
88d9b869
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
80 additions
and
7 deletions
+80
-7
include/linux/ptrace.h
include/linux/ptrace.h
+6
-0
include/linux/sched.h
include/linux/sched.h
+3
-0
kernel/exit.c
kernel/exit.c
+25
-3
kernel/fork.c
kernel/fork.c
+4
-2
kernel/ptrace.c
kernel/ptrace.c
+35
-1
kernel/signal.c
kernel/signal.c
+7
-1
No files found.
include/linux/ptrace.h
View file @
687bc18d
...
...
@@ -26,6 +26,8 @@
/* 0x4200-0x4300 are reserved for architecture-independent additions. */
#define PTRACE_SETOPTIONS 0x4200
#define PTRACE_GETEVENTMSG 0x4201
#define PTRACE_GETSIGINFO 0x4202
#define PTRACE_SETSIGINFO 0x4203
/* options set using PTRACE_SETOPTIONS */
#define PTRACE_O_TRACESYSGOOD 0x00000001
...
...
@@ -33,12 +35,16 @@
#define PTRACE_O_TRACEVFORK 0x00000004
#define PTRACE_O_TRACECLONE 0x00000008
#define PTRACE_O_TRACEEXEC 0x00000010
#define PTRACE_O_TRACEVFORKDONE 0x00000020
#define PTRACE_O_TRACEEXIT 0x00000040
/* Wait extended result codes for the above trace options. */
#define PTRACE_EVENT_FORK 1
#define PTRACE_EVENT_VFORK 2
#define PTRACE_EVENT_CLONE 3
#define PTRACE_EVENT_EXEC 4
#define PTRACE_EVENT_VFORK_DONE 5
#define PTRACE_EVENT_EXIT 6
#include <asm/ptrace.h>
#include <linux/sched.h>
...
...
include/linux/sched.h
View file @
687bc18d
...
...
@@ -417,6 +417,7 @@ struct task_struct {
struct
backing_dev_info
*
backing_dev_info
;
unsigned
long
ptrace_message
;
siginfo_t
*
last_siginfo
;
/* For ptrace use. */
};
extern
void
__put_task_struct
(
struct
task_struct
*
tsk
);
...
...
@@ -457,6 +458,8 @@ do { if (atomic_dec_and_test(&(tsk)->usage)) __put_task_struct(tsk); } while(0)
#define PT_TRACE_VFORK 0x00000020
#define PT_TRACE_CLONE 0x00000040
#define PT_TRACE_EXEC 0x00000080
#define PT_TRACE_VFORK_DONE 0x00000100
#define PT_TRACE_EXIT 0x00000200
#if CONFIG_SMP
extern
void
set_cpus_allowed
(
task_t
*
p
,
unsigned
long
new_mask
);
...
...
kernel/exit.c
View file @
687bc18d
...
...
@@ -199,6 +199,17 @@ static inline int has_stopped_jobs(int pgrp)
for_each_task_pid
(
pgrp
,
PIDTYPE_PGID
,
p
,
l
,
pid
)
{
if
(
p
->
state
!=
TASK_STOPPED
)
continue
;
/* If p is stopped by a debugger on a signal that won't
stop it, then don't count p as stopped. This isn't
perfect but it's a good approximation. */
if
(
unlikely
(
p
->
ptrace
)
&&
p
->
exit_code
!=
SIGSTOP
&&
p
->
exit_code
!=
SIGTSTP
&&
p
->
exit_code
!=
SIGTTOU
&&
p
->
exit_code
!=
SIGTTIN
)
continue
;
retval
=
1
;
break
;
}
...
...
@@ -594,7 +605,7 @@ static void exit_notify(struct task_struct *tsk)
* is about to become orphaned.
*/
t
=
tsk
->
parent
;
t
=
tsk
->
real_
parent
;
if
((
t
->
pgrp
!=
tsk
->
pgrp
)
&&
(
t
->
session
==
tsk
->
session
)
&&
...
...
@@ -627,8 +638,16 @@ static void exit_notify(struct task_struct *tsk)
tsk
->
exit_signal
=
SIGCHLD
;
if
(
tsk
->
exit_signal
!=
-
1
)
do_notify_parent
(
tsk
,
tsk
->
exit_signal
);
/* If something other than our normal parent is ptracing us, then
* send it a SIGCHLD instead of honoring exit_signal. exit_signal
* only has special meaning to our real parent.
*/
if
(
tsk
->
exit_signal
!=
-
1
)
{
if
(
tsk
->
parent
==
tsk
->
real_parent
)
do_notify_parent
(
tsk
,
tsk
->
exit_signal
);
else
do_notify_parent
(
tsk
,
SIGCHLD
);
}
tsk
->
state
=
TASK_ZOMBIE
;
/*
...
...
@@ -661,6 +680,9 @@ NORET_TYPE void do_exit(long code)
profile_exit_task
(
tsk
);
if
(
unlikely
(
current
->
ptrace
&
PT_TRACE_EXIT
))
ptrace_notify
((
PTRACE_EVENT_EXIT
<<
8
)
|
SIGTRAP
);
acct_process
(
code
);
__exit_mm
(
tsk
);
...
...
kernel/fork.c
View file @
687bc18d
...
...
@@ -1085,9 +1085,11 @@ struct task_struct *do_fork(unsigned long clone_flags,
ptrace_notify
((
trace
<<
8
)
|
SIGTRAP
);
}
if
(
clone_flags
&
CLONE_VFORK
)
if
(
clone_flags
&
CLONE_VFORK
)
{
wait_for_completion
(
&
vfork
);
else
if
(
unlikely
(
current
->
ptrace
&
PT_TRACE_VFORK_DONE
))
ptrace_notify
((
PTRACE_EVENT_VFORK_DONE
<<
8
)
|
SIGTRAP
);
}
else
/*
* Let the child process run first, to avoid most of the
* COW overhead when the child exec()s afterwards.
...
...
kernel/ptrace.c
View file @
687bc18d
...
...
@@ -277,15 +277,43 @@ static int ptrace_setoptions(struct task_struct *child, long data)
else
child
->
ptrace
&=
~
PT_TRACE_EXEC
;
if
(
data
&
PTRACE_O_TRACEVFORKDONE
)
child
->
ptrace
|=
PT_TRACE_VFORK_DONE
;
else
child
->
ptrace
&=
~
PT_TRACE_VFORK_DONE
;
if
(
data
&
PTRACE_O_TRACEEXIT
)
child
->
ptrace
|=
PT_TRACE_EXIT
;
else
child
->
ptrace
&=
~
PT_TRACE_EXIT
;
if
((
data
&
(
PTRACE_O_TRACESYSGOOD
|
PTRACE_O_TRACEFORK
|
PTRACE_O_TRACEVFORK
|
PTRACE_O_TRACECLONE
|
PTRACE_O_TRACEEXEC
))
|
PTRACE_O_TRACEEXEC
|
PTRACE_O_TRACEEXIT
|
PTRACE_O_TRACEVFORKDONE
))
!=
data
)
return
-
EINVAL
;
return
0
;
}
static
int
ptrace_getsiginfo
(
struct
task_struct
*
child
,
long
data
)
{
if
(
child
->
last_siginfo
==
NULL
)
return
-
EINVAL
;
return
copy_siginfo_to_user
((
siginfo_t
*
)
data
,
child
->
last_siginfo
);
}
static
int
ptrace_setsiginfo
(
struct
task_struct
*
child
,
long
data
)
{
if
(
child
->
last_siginfo
==
NULL
)
return
-
EINVAL
;
if
(
copy_from_user
(
child
->
last_siginfo
,
(
siginfo_t
*
)
data
,
sizeof
(
siginfo_t
))
!=
0
)
return
-
EFAULT
;
return
0
;
}
int
ptrace_request
(
struct
task_struct
*
child
,
long
request
,
long
addr
,
long
data
)
{
...
...
@@ -301,6 +329,12 @@ int ptrace_request(struct task_struct *child, long request,
case
PTRACE_GETEVENTMSG
:
ret
=
put_user
(
child
->
ptrace_message
,
(
unsigned
long
*
)
data
);
break
;
case
PTRACE_GETSIGINFO
:
ret
=
ptrace_getsiginfo
(
child
,
data
);
break
;
case
PTRACE_SETSIGINFO
:
ret
=
ptrace_setsiginfo
(
child
,
data
);
break
;
default:
break
;
}
...
...
kernel/signal.c
View file @
687bc18d
...
...
@@ -1427,17 +1427,23 @@ int get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs)
/* Let the debugger run. */
current
->
exit_code
=
signr
;
current
->
last_siginfo
=
info
;
set_current_state
(
TASK_STOPPED
);
notify_parent
(
current
,
SIGCHLD
);
schedule
();
current
->
last_siginfo
=
NULL
;
/* We're back. Did the debugger cancel the sig? */
signr
=
current
->
exit_code
;
if
(
signr
==
0
)
continue
;
current
->
exit_code
=
0
;
/* Update the siginfo structure. Is this good? */
/* Update the siginfo structure if the signal has
changed. If the debugger wanted something
specific in the siginfo structure then it should
have updated *info via PTRACE_SETSIGINFO. */
if
(
signr
!=
info
->
si_signo
)
{
info
->
si_signo
=
signr
;
info
->
si_errno
=
0
;
...
...
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