libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2010-2013 Peter Miller 00004 * 00005 * This program is free software; you can redistribute it and/or modify it 00006 * under the terms of the GNU Lesser General Public License as published by 00007 * the Free Software Foundation; either version 3 of the License, or (at 00008 * your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, but 00011 * WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 00013 * General Public License for more details. 00014 * 00015 * You should have received a copy of the GNU Lesser General Public License 00016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00017 */ 00018 00019 #include <libexplain/ac/errno.h> 00020 #include <libexplain/ac/stdint.h> 00021 #include <libexplain/ac/signal.h> 00022 #include <libexplain/ac/sys/ptrace.h> 00023 #include <libexplain/ac/sys/user.h> 00024 00025 #include <libexplain/buffer/ebusy.h> 00026 #include <libexplain/buffer/efault.h> 00027 #include <libexplain/buffer/einval.h> 00028 #include <libexplain/buffer/eio.h> 00029 #include <libexplain/buffer/eperm.h> 00030 #include <libexplain/buffer/errno/generic.h> 00031 #include <libexplain/buffer/errno/ptrace.h> 00032 #include <libexplain/buffer/esrch.h> 00033 #include <libexplain/buffer/gettext.h> 00034 #include <libexplain/buffer/long.h> 00035 #include <libexplain/buffer/pid_t_star.h> 00036 #include <libexplain/buffer/pointer.h> 00037 #include <libexplain/buffer/ptrace_options.h> 00038 #include <libexplain/buffer/ptrace_request.h> 00039 #include <libexplain/buffer/ptrace_vm_entry.h> 00040 #include <libexplain/buffer/signal.h> 00041 #include <libexplain/explanation.h> 00042 #include <libexplain/is_efault.h> 00043 #include <libexplain/process_exists.h> 00044 00045 00046 static void 00047 explain_buffer_errno_ptrace_system_call(explain_string_buffer_t *sb, int errnum, 00048 int request, pid_t pid, void *addr, void *data) 00049 { 00050 (void)errnum; 00051 explain_string_buffer_puts(sb, "ptrace(request = "); 00052 explain_buffer_ptrace_request(sb, request); 00053 explain_string_buffer_puts(sb, ", pid = "); 00054 explain_buffer_pid_t(sb, pid); 00055 explain_string_buffer_puts(sb, ", addr = "); 00056 explain_buffer_pointer(sb, addr); 00057 explain_string_buffer_puts(sb, ", data = "); 00058 switch (request) 00059 { 00060 #ifdef PT_CONTINUE 00061 case PT_CONTINUE: 00062 #endif 00063 #ifdef PT_SYSCALL 00064 case PT_SYSCALL: 00065 #endif 00066 #ifdef PT_STEP 00067 case PT_STEP: 00068 #endif 00069 #ifdef PT_SYSEMU 00070 case PT_SYSEMU: 00071 #endif 00072 #ifdef PT_SYSEMU_SINGLESTEP 00073 case PT_SYSEMU_SINGLESTEP: 00074 #endif 00075 #ifdef PT_DETACH 00076 case PT_DETACH: 00077 #endif 00078 explain_buffer_signal(sb, (intptr_t)data); 00079 break; 00080 00081 #ifdef PT_SETOPTIONS 00082 case PT_SETOPTIONS: 00083 #endif 00084 #ifdef PT_OLDSETOPTIONS 00085 case PT_OLDSETOPTIONS: 00086 #endif 00087 explain_buffer_ptrace_options(sb, (intptr_t)data); 00088 break; 00089 00090 #ifdef PT_WRITE_I 00091 case PT_WRITE_I: 00092 #endif 00093 #ifdef PT_WRITE_D 00094 case PT_WRITE_D: 00095 #endif 00096 #ifdef PT_WRITE_U 00097 case PT_WRITE_U: 00098 #endif 00099 explain_buffer_long(sb, (intptr_t)data); 00100 break; 00101 00102 #ifdef PT_VM_ENTRY 00103 case PT_VM_ENTRY: 00104 explain_buffer_ptrace_vm_entry(sb, data); 00105 break; 00106 #endif 00107 00108 /* FIXME: FreeBSD's PT_IO uses struct ptrace_io_desc */ 00109 00110 default: 00111 explain_buffer_pointer(sb, data); 00112 break; 00113 } 00114 explain_string_buffer_putc(sb, ')'); 00115 } 00116 00117 00118 static int 00119 request_is_known(int request) 00120 { 00121 switch (request) 00122 { 00123 #ifdef PT_TRACE_ME 00124 case PT_TRACE_ME: 00125 #endif 00126 #ifdef PT_READ_I 00127 case PT_READ_I: 00128 #endif 00129 #ifdef PT_READ_D 00130 case PT_READ_D: 00131 #endif 00132 #ifdef PT_READ_U 00133 case PT_READ_U: 00134 #endif 00135 #ifdef PT_WRITE_I 00136 case PT_WRITE_I: 00137 #endif 00138 #ifdef PT_WRITE_D 00139 case PT_WRITE_D: 00140 #endif 00141 #ifdef PT_WRITE_U 00142 case PT_WRITE_U: 00143 #endif 00144 #ifdef PT_CONTINUE 00145 case PT_CONTINUE: 00146 #endif 00147 #ifdef PT_KILL 00148 case PT_KILL: 00149 #endif 00150 #ifdef PT_SINGLESTEP 00151 case PT_SINGLESTEP: 00152 #endif 00153 #ifdef PT_GETREGS 00154 case PT_GETREGS: 00155 #endif 00156 #ifdef PT_SETREGS 00157 case PT_SETREGS: 00158 #endif 00159 #ifdef PT_GETFPREGS 00160 case PT_GETFPREGS: 00161 #endif 00162 #ifdef PT_SETFPREGS 00163 case PT_SETFPREGS: 00164 #endif 00165 #ifdef PT_ATTACH 00166 case PT_ATTACH: 00167 #endif 00168 #ifdef PT_DETACH 00169 case PT_DETACH: 00170 #endif 00171 #ifdef PT_GETFPXREGS 00172 case PT_GETFPXREGS: 00173 #endif 00174 #ifdef PT_SETFPXREGS 00175 case PT_SETFPXREGS: 00176 #endif 00177 #ifdef PT_SYSCALL 00178 case PT_SYSCALL: 00179 #endif 00180 #ifdef PT_SETOPTIONS 00181 case PT_SETOPTIONS: 00182 #endif 00183 #ifdef PT_OLDSETOPTIONS 00184 case PT_OLDSETOPTIONS: 00185 #endif 00186 #ifdef PT_GETEVENTMSG 00187 case PT_GETEVENTMSG: 00188 #endif 00189 #ifdef PT_GETSIGINFO 00190 case PT_GETSIGINFO: 00191 #endif 00192 #ifdef PT_SETSIGINFO 00193 case PT_SETSIGINFO: 00194 #endif 00195 #ifdef PT_SYSEMU 00196 case PT_SYSEMU: 00197 #endif 00198 #ifdef PT_SYSEMU_SINGLESTEP 00199 case PT_SYSEMU_SINGLESTEP: 00200 #endif 00201 #ifdef PT_IO 00202 case PT_IO: 00203 #endif 00204 #ifdef PT_LWPINFO 00205 case PT_LWPINFO: 00206 #endif 00207 #ifdef PT_GETNUMLWPS 00208 case PT_GETNUMLWPS: 00209 #endif 00210 #ifdef PT_GETLWPLIST 00211 case PT_GETLWPLIST: 00212 #endif 00213 #ifdef PT_CLEARSTEP 00214 case PT_CLEARSTEP: 00215 #endif 00216 #ifdef PT_SETSTEP 00217 case PT_SETSTEP: 00218 #endif 00219 #ifdef PT_SUSPEND 00220 case PT_SUSPEND: 00221 #endif 00222 #ifdef PT_RESUME 00223 case PT_RESUME: 00224 #endif 00225 #ifdef PT_TO_SCE 00226 case PT_TO_SCE: 00227 #endif 00228 #ifdef PT_TO_SCX 00229 case PT_TO_SCX : 00230 #endif 00231 #ifdef PT_GETDBREGS 00232 case PT_GETDBREGS: 00233 #endif 00234 #ifdef PT_SETDBREGS 00235 case PT_SETDBREGS: 00236 #endif 00237 #ifdef PT_VM_TIMESTAMP 00238 case PT_VM_TIMESTAMP: 00239 #endif 00240 #ifdef PT_VM_ENTRY 00241 case PT_VM_ENTRY: 00242 #endif 00243 return 1; 00244 00245 default: 00246 break; 00247 } 00248 return 0; 00249 } 00250 00251 00252 static int 00253 calculate_addr_size(int request) 00254 { 00255 switch (request) 00256 { 00257 #ifdef PT_READ_U 00258 case PT_READ_U: 00259 #endif 00260 #ifdef PT_WRITE_I 00261 case PT_WRITE_I: 00262 #endif 00263 #ifdef PT_WRITE_D 00264 case PT_WRITE_D: 00265 #endif 00266 #ifdef PT_WRITE_U 00267 case PT_WRITE_U: 00268 #endif 00269 return sizeof(int); 00270 00271 default: 00272 break; 00273 } 00274 return 0; 00275 } 00276 00277 00278 static int 00279 calculate_data_size(int request) 00280 { 00281 /* 00282 * The following structs are all defined in <sys/user.h> (on Linux, 00283 * anyway), so if your system doesn't have them, we can't give 00284 * useful answers. 00285 */ 00286 switch (request) 00287 { 00288 #ifdef SYS_PTRACE_USER_REGS_STRUCT 00289 #ifdef PT_GETREGS 00290 case PT_GETREGS: 00291 return sizeof(struct user_regs_struct); 00292 #endif 00293 #ifdef PT_SETREGS 00294 case PT_SETREGS: 00295 return sizeof(struct user_regs_struct); 00296 #endif 00297 #endif /* SYS_PTRACE_USER_REGS_STRUCT */ 00298 00299 #ifdef SYS_PTRACE_USER_FPREGS_STRUCT 00300 #ifdef PT_GETFPREGS 00301 case PT_GETFPREGS: 00302 return sizeof(struct user_fpregs_struct); 00303 #endif 00304 #ifdef PT_SETFPREGS 00305 case PT_SETFPREGS: 00306 return sizeof(struct user_fpregs_struct); 00307 #endif 00308 #endif /* SYS_PTRACE_USER_FPREGS_STRUCT */ 00309 00310 #ifdef SYS_PTRACE_USER_FPXREGS_STRUCT 00311 #ifdef PT_GETFPXREGS 00312 case PT_GETFPXREGS: 00313 return sizeof(struct user_fpxregs_struct); 00314 #endif 00315 #ifdef PT_SETFPXREGS 00316 case PT_SETFPXREGS: 00317 return sizeof(struct user_fpxregs_struct); 00318 #endif 00319 #endif /* SYS_PTRACE_USER_FPREGS_STRUCT */ 00320 00321 #ifdef PT_GETEVENTMSG 00322 case PT_GETEVENTMSG: 00323 return sizeof(unsigned long); 00324 #endif 00325 #ifdef PT_GETSIGINFO 00326 case PT_GETSIGINFO: 00327 return sizeof(siginfo_t); 00328 #endif 00329 #ifdef PT_SETSIGINFO 00330 case PT_SETSIGINFO: 00331 return sizeof(siginfo_t); 00332 #endif 00333 00334 #ifdef PT_VM_ENTRY 00335 case PT_VM_ENTRY: 00336 /* FreeBSD, not Linux */ 00337 return sizeof(struct ptrace_vm_entry); 00338 #endif 00339 00340 default: 00341 break; 00342 } 00343 return 0; 00344 } 00345 00346 #if defined(PT_SETOPTIONS) || defined(PT_OLDSETOPTIONS) 00347 00348 static void 00349 setting_an_invalid_option(explain_string_buffer_t *sb) 00350 { 00351 explain_buffer_gettext 00352 ( 00353 sb, 00354 /* 00355 * xgettext: This error message is issued to explain an EINVAL 00356 * error reported by the ptrace(2) system call, in the case 00357 * where an attempt was made to set an invalid option. 00358 */ 00359 i18n("an attempt was made to set an invalid option") 00360 ); 00361 } 00362 00363 #endif 00364 00365 void 00366 explain_buffer_errno_ptrace_explanation(explain_string_buffer_t *sb, int errnum, 00367 const char *syscall_name, int request, pid_t pid, void *addr, void *data) 00368 { 00369 size_t addr_size = calculate_addr_size(request); 00370 size_t data_size = calculate_data_size(request); 00371 00372 /* 00373 * http://www.opengroup.org/onlinepubs/009695399/functions/ptrace.html 00374 */ 00375 switch (errnum) 00376 { 00377 case EBUSY: 00378 explain_buffer_gettext 00379 ( 00380 sb, 00381 /* 00382 * xgettext: This error message is issued to explain an EBUSY error 00383 * reported by the ptrace(2) system call, in the case where there 00384 * was an error with allocating or freeing a debug register. 00385 */ 00386 i18n("there was an error with allocating or freeing a debug " 00387 "register") 00388 ); 00389 break; 00390 00391 case EFAULT: 00392 if (addr_size && explain_is_efault_pointer(addr, addr_size)) 00393 { 00394 explain_buffer_efault(sb, "addr"); 00395 break; 00396 } 00397 if (data_size && explain_is_efault_pointer(data, data_size)) 00398 { 00399 explain_buffer_efault(sb, "data"); 00400 break; 00401 } 00402 explain_buffer_gettext 00403 ( 00404 sb, 00405 /* 00406 * xgettext: This error message is issued to explain an EFAULT error 00407 * reported by the ptrace(2) system call, in the cases where there 00408 * was an attempt to read from or write to an invalid area in the 00409 * parent's or child's memory, probably because the area wasn't 00410 * mapped or accessible. 00411 */ 00412 i18n("there was an attempt to read from or write to an invalid " 00413 "area in the parent's or child's memory, probably because the " 00414 "area wasn't mapped or accessible") 00415 ); 00416 /* 00417 * Unfortunately, under Linux, different variations of this 00418 * fault will return EIO or EFAULT more or less arbitrarily. 00419 */ 00420 break; 00421 00422 case EINVAL: 00423 if (!request_is_known(request)) 00424 { 00425 explain_buffer_einval_vague(sb, "request"); 00426 return; 00427 } 00428 #ifdef PT_SETOPTIONS 00429 if (request == PT_SETOPTIONS) 00430 { 00431 setting_an_invalid_option(sb); 00432 break; 00433 } 00434 #endif 00435 #ifdef PT_OLDSETOPTIONS 00436 if (request == PT_OLDSETOPTIONS) 00437 { 00438 setting_an_invalid_option(sb); 00439 break; 00440 } 00441 #endif 00442 goto generic; 00443 00444 case EIO: 00445 if (!request_is_known(request)) 00446 { 00447 explain_buffer_einval_vague(sb, "request"); 00448 return; 00449 } 00450 if (addr_size && explain_is_efault_pointer(addr, addr_size)) 00451 { 00452 explain_buffer_efault(sb, "addr"); 00453 break; 00454 } 00455 if (data_size && explain_is_efault_pointer(data, data_size)) 00456 { 00457 explain_buffer_efault(sb, "data"); 00458 break; 00459 } 00460 switch (request) 00461 { 00462 #ifdef PT_CONTINUE 00463 case PT_CONTINUE: 00464 #endif 00465 #ifdef PT_SYSCALL 00466 case PT_SYSCALL: 00467 #endif 00468 #ifdef PT_STEP 00469 case PT_STEP: 00470 #endif 00471 #ifdef PT_SYSEMU 00472 case PT_SYSEMU: 00473 #endif 00474 #ifdef PT_SYSEMU_SINGLESTEP 00475 case PT_SYSEMU_SINGLESTEP: 00476 #endif 00477 #ifdef PT_DETACH 00478 case PT_DETACH: 00479 #endif 00480 explain_buffer_gettext 00481 ( 00482 sb, 00483 /* 00484 * xgettext: This error message is issued to explain an EIO 00485 * error reported by the ptrace(2) system call, in the case 00486 * where an invalid signal was specified during a restart 00487 * request. 00488 */ 00489 i18n("an invalid signal was specified during a restart request") 00490 ); 00491 return; 00492 00493 default: 00494 break; 00495 } 00496 explain_buffer_gettext 00497 ( 00498 sb, 00499 /* 00500 * xgettext: This error message is issued to explain an EIO error 00501 * reported by the ptrace(2) system call, in the case where there 00502 * was a word-alignment violation. 00503 */ 00504 i18n("there was a word-alignment violation") 00505 ); 00506 break; 00507 00508 case EPERM: 00509 if (!explain_process_exists(pid)) 00510 { 00511 explain_buffer_eperm_kill(sb); 00512 break; 00513 } 00514 00515 /* 00516 * Unprivileged processes cannot trace processes that are 00517 * running set-user-ID or set-group-ID programs. 00518 * 00519 * The process may already be being traced. 00520 * FIXME: can prctl tell us this? 00521 * 00522 * The process may be init(8), i.e. pid == 1 00523 */ 00524 explain_buffer_gettext 00525 ( 00526 sb, 00527 /* 00528 * xgettext: This error message is issued to explain an EPERM error 00529 * reported by the ptrace(2) system call, in the case where the 00530 * specified process cannot be traced. 00531 */ 00532 i18n("the specified process cannot be traced") 00533 ); 00534 break; 00535 00536 case ESRCH: 00537 if (pid <= 0 || kill(pid, 0) < 0) 00538 { 00539 explain_buffer_eperm_kill(sb); 00540 break; 00541 } 00542 00543 /* FIXME: figure out which case applies */ 00544 /* FIXME: i18n */ 00545 explain_string_buffer_puts 00546 ( 00547 sb, 00548 "the specified process is not currently being traced by the " 00549 "caller, or is not stopped (for requests that require that)" 00550 ); 00551 break; 00552 00553 default: 00554 generic: 00555 explain_buffer_errno_generic(sb, errnum, syscall_name); 00556 break; 00557 } 00558 } 00559 00560 00561 void 00562 explain_buffer_errno_ptrace(explain_string_buffer_t *sb, int errnum, int 00563 request, pid_t pid, void *addr, void *data) 00564 { 00565 explain_explanation_t exp; 00566 00567 explain_explanation_init(&exp, errnum); 00568 explain_buffer_errno_ptrace_system_call(&exp.system_call_sb, errnum, 00569 request, pid, addr, data); 00570 explain_buffer_errno_ptrace_explanation(&exp.explanation_sb, errnum, 00571 "ptrace", request, pid, addr, data); 00572 explain_explanation_assemble(&exp, sb); 00573 } 00574 00575 00576 /* vim: set ts=8 sw=4 et : */