~ubuntu-branches/debian/wheezy/linux-2.6/wheezy

« back to all changes in this revision

Viewing changes to arch/m68k/kernel/ptrace_no.c

  • Committer: Bazaar Package Importer
  • Author(s): Ben Hutchings, Ben Hutchings, Aurelien Jarno
  • Date: 2011-06-07 12:14:05 UTC
  • mfrom: (43.1.9 sid)
  • Revision ID: james.westby@ubuntu.com-20110607121405-i3h1rd7nrnd2b73h
Tags: 2.6.39-2
[ Ben Hutchings ]
* [x86] Enable BACKLIGHT_APPLE, replacing BACKLIGHT_MBP_NVIDIA
  (Closes: #627492)
* cgroups: Disable memory resource controller by default. Allow it
  to be enabled using kernel parameter 'cgroup_enable=memory'.
* rt2800usb: Enable support for more USB devices including
  Linksys WUSB600N (Closes: #596626) (this change was accidentally
  omitted from 2.6.39-1)
* [x86] Remove Celeron from list of processors supporting PAE. Most
  'Celeron M' models do not.
* Update debconf template translations:
  - Swedish (Martin Bagge) (Closes: #628932)
  - French (David Prévot) (Closes: #628191)
* aufs: Update for 2.6.39 (Closes: #627837)
* Add stable 2.6.39.1, including:
  - ext4: dont set PageUptodate in ext4_end_bio()
  - pata_cmd64x: fix boot crash on parisc (Closes: #622997, #622745)
  - ext3: Fix fs corruption when make_indexed_dir() fails
  - netfilter: nf_ct_sip: validate Content-Length in TCP SIP messages
  - sctp: fix race between sctp_bind_addr_free() and
    sctp_bind_addr_conflict()
  - sctp: fix memory leak of the ASCONF queue when free asoc
  - md/bitmap: fix saving of events_cleared and other state
  - cdc_acm: Fix oops when Droids MuIn LCD is connected
  - cx88: Fix conversion from BKL to fine-grained locks (Closes: #619827)
  - keys: Set cred->user_ns in key_replace_session_keyring (CVE-2011-2184)
  - tmpfs: fix race between truncate and writepage
  - nfs41: Correct offset for LAYOUTCOMMIT
  - xen/mmu: fix a race window causing leave_mm BUG()
  - ext4: fix possible use-after-free in ext4_remove_li_request()
  For the complete list of changes, see:
   http://www.kernel.org/pub/linux/kernel/v2.6/ChangeLog-2.6.39.1
* Bump ABI to 2
* netfilter: Enable IP_SET, IP_SET_BITMAP_IP, IP_SET_BITMAP_IPMAC,
  IP_SET_BITMAP_PORT, IP_SET_HASH_IP, IP_SET_HASH_IPPORT,
  IP_SET_HASH_IPPORTIP, IP_SET_HASH_IPPORTNET, IP_SET_HASH_NET,
  IP_SET_HASH_NETPORT, IP_SET_LIST_SET, NETFILTER_XT_SET as modules
  (Closes: #629401)

[ Aurelien Jarno ]
* [mipsel/loongson-2f] Disable_SCSI_LPFC to workaround GCC ICE.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  linux/arch/m68knommu/kernel/ptrace.c
 
3
 *
 
4
 *  Copyright (C) 1994 by Hamish Macdonald
 
5
 *  Taken from linux/kernel/ptrace.c and modified for M680x0.
 
6
 *  linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by Linus Torvalds
 
7
 *
 
8
 * This file is subject to the terms and conditions of the GNU General
 
9
 * Public License.  See the file COPYING in the main directory of
 
10
 * this archive for more details.
 
11
 */
 
12
 
 
13
#include <linux/kernel.h>
 
14
#include <linux/sched.h>
 
15
#include <linux/mm.h>
 
16
#include <linux/smp.h>
 
17
#include <linux/errno.h>
 
18
#include <linux/ptrace.h>
 
19
#include <linux/user.h>
 
20
#include <linux/signal.h>
 
21
#include <linux/tracehook.h>
 
22
 
 
23
#include <asm/uaccess.h>
 
24
#include <asm/page.h>
 
25
#include <asm/pgtable.h>
 
26
#include <asm/system.h>
 
27
#include <asm/processor.h>
 
28
 
 
29
/*
 
30
 * does not yet catch signals sent when the child dies.
 
31
 * in exit.c or in signal.c.
 
32
 */
 
33
 
 
34
/* determines which bits in the SR the user has access to. */
 
35
/* 1 = access 0 = no access */
 
36
#define SR_MASK 0x001f
 
37
 
 
38
/* sets the trace bits. */
 
39
#define TRACE_BITS 0x8000
 
40
 
 
41
/* Find the stack offset for a register, relative to thread.esp0. */
 
42
#define PT_REG(reg)     ((long)&((struct pt_regs *)0)->reg)
 
43
#define SW_REG(reg)     ((long)&((struct switch_stack *)0)->reg \
 
44
                         - sizeof(struct switch_stack))
 
45
/* Mapping from PT_xxx to the stack offset at which the register is
 
46
   saved.  Notice that usp has no stack-slot and needs to be treated
 
47
   specially (see get_reg/put_reg below). */
 
48
static int regoff[] = {
 
49
        PT_REG(d1), PT_REG(d2), PT_REG(d3), PT_REG(d4),
 
50
        PT_REG(d5), SW_REG(d6), SW_REG(d7), PT_REG(a0),
 
51
        PT_REG(a1), PT_REG(a2), SW_REG(a3), SW_REG(a4),
 
52
        SW_REG(a5), SW_REG(a6), PT_REG(d0), -1,
 
53
        PT_REG(orig_d0), PT_REG(sr), PT_REG(pc),
 
54
};
 
55
 
 
56
/*
 
57
 * Get contents of register REGNO in task TASK.
 
58
 */
 
59
static inline long get_reg(struct task_struct *task, int regno)
 
60
{
 
61
        unsigned long *addr;
 
62
 
 
63
        if (regno == PT_USP)
 
64
                addr = &task->thread.usp;
 
65
        else if (regno < ARRAY_SIZE(regoff))
 
66
                addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
 
67
        else
 
68
                return 0;
 
69
        return *addr;
 
70
}
 
71
 
 
72
/*
 
73
 * Write contents of register REGNO in task TASK.
 
74
 */
 
75
static inline int put_reg(struct task_struct *task, int regno,
 
76
                          unsigned long data)
 
77
{
 
78
        unsigned long *addr;
 
79
 
 
80
        if (regno == PT_USP)
 
81
                addr = &task->thread.usp;
 
82
        else if (regno < ARRAY_SIZE(regoff))
 
83
                addr = (unsigned long *) (task->thread.esp0 + regoff[regno]);
 
84
        else
 
85
                return -1;
 
86
        *addr = data;
 
87
        return 0;
 
88
}
 
89
 
 
90
void user_enable_single_step(struct task_struct *task)
 
91
{
 
92
        unsigned long srflags;
 
93
        srflags = get_reg(task, PT_SR) | (TRACE_BITS << 16);
 
94
        put_reg(task, PT_SR, srflags);
 
95
}
 
96
 
 
97
void user_disable_single_step(struct task_struct *task)
 
98
{
 
99
        unsigned long srflags;
 
100
        srflags = get_reg(task, PT_SR) & ~(TRACE_BITS << 16);
 
101
        put_reg(task, PT_SR, srflags);
 
102
}
 
103
 
 
104
/*
 
105
 * Called by kernel/ptrace.c when detaching..
 
106
 *
 
107
 * Make sure the single step bit is not set.
 
108
 */
 
109
void ptrace_disable(struct task_struct *child)
 
110
{
 
111
        /* make sure the single step bit is not set. */
 
112
        user_disable_single_step(child);
 
113
}
 
114
 
 
115
long arch_ptrace(struct task_struct *child, long request,
 
116
                 unsigned long addr, unsigned long data)
 
117
{
 
118
        int ret;
 
119
        int regno = addr >> 2;
 
120
        unsigned long __user *datap = (unsigned long __user *) data;
 
121
 
 
122
        switch (request) {
 
123
                /* read the word at location addr in the USER area. */
 
124
                case PTRACE_PEEKUSR: {
 
125
                        unsigned long tmp;
 
126
                        
 
127
                        ret = -EIO;
 
128
                        if ((addr & 3) || addr > sizeof(struct user) - 3)
 
129
                                break;
 
130
                        
 
131
                        tmp = 0;  /* Default return condition */
 
132
                        ret = -EIO;
 
133
                        if (regno < 19) {
 
134
                                tmp = get_reg(child, regno);
 
135
                                if (regno == PT_SR)
 
136
                                        tmp >>= 16;
 
137
                        } else if (regno >= 21 && regno < 49) {
 
138
                                tmp = child->thread.fp[regno - 21];
 
139
                        } else if (regno == 49) {
 
140
                                tmp = child->mm->start_code;
 
141
                        } else if (regno == 50) {
 
142
                                tmp = child->mm->start_data;
 
143
                        } else if (regno == 51) {
 
144
                                tmp = child->mm->end_code;
 
145
                        } else
 
146
                                break;
 
147
                        ret = put_user(tmp, datap);
 
148
                        break;
 
149
                }
 
150
 
 
151
                case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
 
152
                        ret = -EIO;
 
153
                        if ((addr & 3) || addr > sizeof(struct user) - 3)
 
154
                                break;
 
155
 
 
156
                        if (regno == PT_SR) {
 
157
                                data &= SR_MASK;
 
158
                                data <<= 16;
 
159
                                data |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
 
160
                        }
 
161
                        if (regno < 19) {
 
162
                                if (put_reg(child, regno, data))
 
163
                                        break;
 
164
                                ret = 0;
 
165
                                break;
 
166
                        }
 
167
                        if (regno >= 21 && regno < 48)
 
168
                        {
 
169
                                child->thread.fp[regno - 21] = data;
 
170
                                ret = 0;
 
171
                        }
 
172
                        break;
 
173
 
 
174
                case PTRACE_GETREGS: { /* Get all gp regs from the child. */
 
175
                        int i;
 
176
                        unsigned long tmp;
 
177
                        for (i = 0; i < 19; i++) {
 
178
                            tmp = get_reg(child, i);
 
179
                            if (i == PT_SR)
 
180
                                tmp >>= 16;
 
181
                            if (put_user(tmp, datap)) {
 
182
                                ret = -EFAULT;
 
183
                                break;
 
184
                            }
 
185
                            datap++;
 
186
                        }
 
187
                        ret = 0;
 
188
                        break;
 
189
                }
 
190
 
 
191
                case PTRACE_SETREGS: { /* Set all gp regs in the child. */
 
192
                        int i;
 
193
                        unsigned long tmp;
 
194
                        for (i = 0; i < 19; i++) {
 
195
                            if (get_user(tmp, datap)) {
 
196
                                ret = -EFAULT;
 
197
                                break;
 
198
                            }
 
199
                            if (i == PT_SR) {
 
200
                                tmp &= SR_MASK;
 
201
                                tmp <<= 16;
 
202
                                tmp |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
 
203
                            }
 
204
                            put_reg(child, i, tmp);
 
205
                            datap++;
 
206
                        }
 
207
                        ret = 0;
 
208
                        break;
 
209
                }
 
210
 
 
211
#ifdef PTRACE_GETFPREGS
 
212
                case PTRACE_GETFPREGS: { /* Get the child FPU state. */
 
213
                        ret = 0;
 
214
                        if (copy_to_user(datap, &child->thread.fp,
 
215
                                         sizeof(struct user_m68kfp_struct)))
 
216
                                ret = -EFAULT;
 
217
                        break;
 
218
                }
 
219
#endif
 
220
 
 
221
#ifdef PTRACE_SETFPREGS
 
222
                case PTRACE_SETFPREGS: { /* Set the child FPU state. */
 
223
                        ret = 0;
 
224
                        if (copy_from_user(&child->thread.fp, datap,
 
225
                                           sizeof(struct user_m68kfp_struct)))
 
226
                                ret = -EFAULT;
 
227
                        break;
 
228
                }
 
229
#endif
 
230
 
 
231
        case PTRACE_GET_THREAD_AREA:
 
232
                ret = put_user(task_thread_info(child)->tp_value, datap);
 
233
                break;
 
234
 
 
235
                default:
 
236
                        ret = ptrace_request(child, request, addr, data);
 
237
                        break;
 
238
        }
 
239
        return ret;
 
240
}
 
241
 
 
242
asmlinkage int syscall_trace_enter(void)
 
243
{
 
244
        int ret = 0;
 
245
 
 
246
        if (test_thread_flag(TIF_SYSCALL_TRACE))
 
247
                ret = tracehook_report_syscall_entry(task_pt_regs(current));
 
248
        return ret;
 
249
}
 
250
 
 
251
asmlinkage void syscall_trace_leave(void)
 
252
{
 
253
        if (test_thread_flag(TIF_SYSCALL_TRACE))
 
254
                tracehook_report_syscall_exit(task_pt_regs(current), 0);
 
255
}