diff options
author | Oleg Nesterov <oleg@redhat.com> | 2012-12-31 12:00:06 -0500 |
---|---|---|
committer | Oleg Nesterov <oleg@redhat.com> | 2013-02-08 11:47:12 -0500 |
commit | a6cb3f6d51253e9cf21a38b17c025018117809d7 (patch) | |
tree | f0ffafefd93cb97f550b0149b14e56a68c778576 /kernel/events | |
parent | 5a2df662aafdabffb2cf3adb780a5adf66dfb3bc (diff) |
uprobes: Do not play with utask in xol_get_insn_slot()
pre_ssout()->xol_get_insn_slot() path is confusing and buggy. This patch
cleanups the code, the next one fixes the bug.
Change xol_get_insn_slot() to only allocate the slot and do nothing more,
move the initialization of utask->xol_vaddr/vaddr into pre_ssout().
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Acked-by: Anton Arapov <anton@redhat.com>
Acked-by: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
Diffstat (limited to 'kernel/events')
-rw-r--r-- | kernel/events/uprobes.c | 37 |
1 files changed, 21 insertions, 16 deletions
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c index 16e54d63a9fd..8d9c5bcb110e 100644 --- a/kernel/events/uprobes.c +++ b/kernel/events/uprobes.c | |||
@@ -1176,30 +1176,26 @@ static unsigned long xol_take_insn_slot(struct xol_area *area) | |||
1176 | } | 1176 | } |
1177 | 1177 | ||
1178 | /* | 1178 | /* |
1179 | * xol_get_insn_slot - If was not allocated a slot, then | 1179 | * xol_get_insn_slot - allocate a slot for xol. |
1180 | * allocate a slot. | ||
1181 | * Returns the allocated slot address or 0. | 1180 | * Returns the allocated slot address or 0. |
1182 | */ | 1181 | */ |
1183 | static unsigned long xol_get_insn_slot(struct uprobe *uprobe, unsigned long slot_addr) | 1182 | static unsigned long xol_get_insn_slot(struct uprobe *uprobe) |
1184 | { | 1183 | { |
1185 | struct xol_area *area; | 1184 | struct xol_area *area; |
1186 | unsigned long offset; | 1185 | unsigned long offset; |
1186 | unsigned long xol_vaddr; | ||
1187 | void *vaddr; | 1187 | void *vaddr; |
1188 | 1188 | ||
1189 | area = get_xol_area(); | 1189 | area = get_xol_area(); |
1190 | if (!area) | 1190 | if (!area) |
1191 | return 0; | 1191 | return 0; |
1192 | 1192 | ||
1193 | current->utask->xol_vaddr = xol_take_insn_slot(area); | 1193 | xol_vaddr = xol_take_insn_slot(area); |
1194 | /* | 1194 | if (unlikely(!xol_vaddr)) |
1195 | * Initialize the slot if xol_vaddr points to valid | ||
1196 | * instruction slot. | ||
1197 | */ | ||
1198 | if (unlikely(!current->utask->xol_vaddr)) | ||
1199 | return 0; | 1195 | return 0; |
1200 | 1196 | ||
1201 | current->utask->vaddr = slot_addr; | 1197 | /* Initialize the slot */ |
1202 | offset = current->utask->xol_vaddr & ~PAGE_MASK; | 1198 | offset = xol_vaddr & ~PAGE_MASK; |
1203 | vaddr = kmap_atomic(area->page); | 1199 | vaddr = kmap_atomic(area->page); |
1204 | memcpy(vaddr + offset, uprobe->arch.insn, MAX_UINSN_BYTES); | 1200 | memcpy(vaddr + offset, uprobe->arch.insn, MAX_UINSN_BYTES); |
1205 | kunmap_atomic(vaddr); | 1201 | kunmap_atomic(vaddr); |
@@ -1209,7 +1205,7 @@ static unsigned long xol_get_insn_slot(struct uprobe *uprobe, unsigned long slot | |||
1209 | */ | 1205 | */ |
1210 | flush_dcache_page(area->page); | 1206 | flush_dcache_page(area->page); |
1211 | 1207 | ||
1212 | return current->utask->xol_vaddr; | 1208 | return xol_vaddr; |
1213 | } | 1209 | } |
1214 | 1210 | ||
1215 | /* | 1211 | /* |
@@ -1306,12 +1302,21 @@ static struct uprobe_task *get_utask(void) | |||
1306 | 1302 | ||
1307 | /* Prepare to single-step probed instruction out of line. */ | 1303 | /* Prepare to single-step probed instruction out of line. */ |
1308 | static int | 1304 | static int |
1309 | pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long vaddr) | 1305 | pre_ssout(struct uprobe *uprobe, struct pt_regs *regs, unsigned long bp_vaddr) |
1310 | { | 1306 | { |
1311 | if (xol_get_insn_slot(uprobe, vaddr) && !arch_uprobe_pre_xol(&uprobe->arch, regs)) | 1307 | struct uprobe_task *utask; |
1312 | return 0; | 1308 | unsigned long xol_vaddr; |
1309 | |||
1310 | utask = current->utask; | ||
1311 | |||
1312 | xol_vaddr = xol_get_insn_slot(uprobe); | ||
1313 | if (!xol_vaddr) | ||
1314 | return -ENOMEM; | ||
1315 | |||
1316 | utask->xol_vaddr = xol_vaddr; | ||
1317 | utask->vaddr = bp_vaddr; | ||
1313 | 1318 | ||
1314 | return -EFAULT; | 1319 | return arch_uprobe_pre_xol(&uprobe->arch, regs); |
1315 | } | 1320 | } |
1316 | 1321 | ||
1317 | /* | 1322 | /* |