アプリケーションが glibc の times(2) 関数でセグメンテーションフォールトを発生させる

Solution In Progress - Updated -

Environment

  • Red Hat Enterprise Linux 6.3
  • kernel-2.6.32-279.14.1.el6
  • glibc-2.12-1.80.el6_3.6

Issue

  • アプリケーションが glibc の times(2) 関数でセグメンテーションフォールトを発生させます。
Core was generated by `<an application>'.
Program terminated with signal 11, Segmentation fault.
#0  __times (buf=0x0) at ../sysdeps/unix/sysv/linux/times.c:43
43            touch (buf->tms_utime);
Missing separate debuginfos, use: debuginfo-install clusterpro-3.1.7-1.i686
(gdb) bt
#0  __times (buf=0x0) at ../sysdeps/unix/sysv/linux/times.c:43
#1  0x00e73da9 in xmllib_times (buf=0x0) at src/xml.c:785
#2  0x080518b5 in rm_wait_monitor (pmon=0x8f4a2b8, nintv=10) at src/rm.c:1477
#3  0x08051e25 in rm_monitor (pmon=0x8f4a2b8) at src/rm.c:1596
#4  0x00bd9a49 in start_thread (arg=0xb5fa6b70) at pthread_create.c:301
#5  0x00b1663e in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:133
(gdb)

Resolution

glibc-2.12-1.166.el6 以降にアップデートします。
RHBA-2015:1286-3

Root Cause

  • glibc __times() 関数が、アプリケーションが NULL ポインターを引数として渡し、カーネルが EFAULT を返す状況を適切に処理しません。

Diagnostic Steps

$ gdb /usr/sbin/clprm core.3916
...
Core was generated by `clprm'.
Program terminated with signal 11, Segmentation fault.
#0  __times (buf=0x0) at ../sysdeps/unix/sysv/linux/times.c:43
43            touch (buf->tms_utime);
(gdb) bt
#0  __times (buf=0x0) at ../sysdeps/unix/sysv/linux/times.c:43
#1  0x00e73da9 in xmllib_times (buf=0x0) at src/xml.c:785
#2  0x080518b5 in rm_wait_monitor (pmon=0x8f4a2b8, nintv=10) at src/rm.c:1477
#3  0x08051e25 in rm_monitor (pmon=0x8f4a2b8) at src/rm.c:1596
#4  0x00bd9a49 in start_thread (arg=0xb5fa6b70) at pthread_create.c:301
#5  0x00b1663e in clone () at ../sysdeps/unix/sysv/linux/i386/clone.S:133
(gdb) p $eip
$1 = (void (*)()) 0xad4df2 <__times+50>
(gdb) disassemble 
Dump of assembler code for function __times:
...
=> 0x00ad4df2 <+50>:    mov    (%edx),%ecx
...
(gdb) p $edx
$2 = 0
(gdb) list __times
21      #include <sysdep.h>
22
23
24      clock_t
25      __times (struct tms *buf)
26      {
27        INTERNAL_SYSCALL_DECL (err);
28        clock_t ret = INTERNAL_SYSCALL (times, err, 1, buf);
29        if (INTERNAL_SYSCALL_ERROR_P (ret, err)
30            && __builtin_expect (INTERNAL_SYSCALL_ERRNO (ret, err) == EFAULT, 0))
31          {
(gdb) p ret
$3 = -14
(gdb)

ここでは、渡した引数が 0x0 (NULL) で、times システムコールが返した値が EFAULT (14) であることが確認できます。

/usr/include/asm-generic/errno-base.h:
#define EFAULT          14      /* Bad address */

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.