From 9637d8a253493be471d9a71640e91349f7a8a050 Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Wed, 29 Jul 2015 11:57:54 -0700 Subject: [PATCH] Extend local PLT reference check On x86, linker in binutils 2.26 and newer consolidates R_*_JUMP_SLOT with R_*_GLOB_DAT relocation against the same symbol. This patch extends local PLT reference check to support alternate relocations. [BZ #18078] * scripts/check-localplt.awk: Support alternate relocations. * scripts/localplt.awk: Also check relocations in DT_RELA/DT_REL sections. * sysdeps/unix/sysv/linux/i386/localplt.data: Mark free and malloc entries with + REL R_386_GLOB_DAT. * sysdeps/x86_64/localplt.data: New file. --- ChangeLog | 10 +++++ NEWS | 22 +++++----- scripts/check-localplt.awk | 40 +++++++++++++++--- scripts/localplt.awk | 47 ++++++++++++++++++++++ sysdeps/unix/sysv/linux/i386/localplt.data | 8 ++-- sysdeps/x86_64/localplt.data | 19 +++++++++ 6 files changed, 127 insertions(+), 19 deletions(-) create mode 100644 sysdeps/x86_64/localplt.data diff --git a/ChangeLog b/ChangeLog index 9a5e489d86..6f393fd01e 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2015-07-29 H.J. Lu + + [BZ #18078] + * scripts/check-localplt.awk: Support alternate relocations. + * scripts/localplt.awk: Also check relocations in DT_RELA/DT_REL + sections. + * sysdeps/unix/sysv/linux/i386/localplt.data: Mark free and + malloc entries with + REL R_386_GLOB_DAT. + * sysdeps/x86_64/localplt.data: New file. + 2015-07-29 Andrew Senkevich [BZ #18731] diff --git a/NEWS b/NEWS index 5698310e77..5be4917b71 100644 --- a/NEWS +++ b/NEWS @@ -18,17 +18,17 @@ Version 2.22 17841, 17912, 17916, 17930, 17932, 17944, 17949, 17964, 17965, 17967, 17969, 17977, 17978, 17987, 17991, 17996, 17998, 17999, 18007, 18019, 18020, 18029, 18030, 18032, 18034, 18036, 18038, 18039, 18042, 18043, - 18046, 18047, 18049, 18068, 18080, 18093, 18100, 18104, 18110, 18111, - 18116, 18125, 18128, 18134, 18138, 18185, 18196, 18197, 18206, 18210, - 18211, 18217, 18219, 18220, 18221, 18234, 18244, 18245, 18247, 18287, - 18319, 18324, 18333, 18346, 18371, 18383, 18397, 18400, 18409, 18410, - 18412, 18418, 18422, 18434, 18444, 18457, 18468, 18469, 18470, 18479, - 18483, 18495, 18496, 18497, 18498, 18502, 18507, 18508, 18512, 18513, - 18519, 18520, 18522, 18527, 18528, 18529, 18530, 18532, 18533, 18534, - 18536, 18539, 18540, 18542, 18544, 18545, 18546, 18547, 18549, 18553, - 18557, 18558, 18569, 18583, 18585, 18586, 18592, 18593, 18594, 18602, - 18612, 18613, 18619, 18633, 18641, 18643, 18648, 18657, 18676, 18694, - 18696. + 18046, 18047, 18049, 18068, 18078, 18080, 18093, 18100, 18104, 18110, + 18111, 18116, 18125, 18128, 18134, 18138, 18185, 18196, 18197, 18206, + 18210, 18211, 18217, 18219, 18220, 18221, 18234, 18244, 18245, 18247, + 18287, 18319, 18324, 18333, 18346, 18371, 18383, 18397, 18400, 18409, + 18410, 18412, 18418, 18422, 18434, 18444, 18457, 18468, 18469, 18470, + 18479, 18483, 18495, 18496, 18497, 18498, 18502, 18507, 18508, 18512, + 18513, 18519, 18520, 18522, 18527, 18528, 18529, 18530, 18532, 18533, + 18534, 18536, 18539, 18540, 18542, 18544, 18545, 18546, 18547, 18549, + 18553, 18557, 18558, 18569, 18583, 18585, 18586, 18592, 18593, 18594, + 18602, 18612, 18613, 18619, 18633, 18641, 18643, 18648, 18657, 18676, + 18694, 18696. * Cache information can be queried via sysconf() function on s390 e.g. with _SC_LEVEL1_ICACHE_SIZE as argument. diff --git a/scripts/check-localplt.awk b/scripts/check-localplt.awk index bb1b912131..3965292888 100644 --- a/scripts/check-localplt.awk +++ b/scripts/check-localplt.awk @@ -3,9 +3,14 @@ # Each line is either a comment starting with # or it looks like: # libfoo.so: function # or +# libfoo.so: function + {RELA|REL} RELOC +# or # libfoo.so: function ? -# The latter means that a PLT entry for function is optional in libfoo.so. -# The former means one is required. +# The first entry means that one is required. +# The second entry means that one is required and relocation may also be +# {RELA|REL} RELOC. +# The third entry means that a PLT entry for function is optional in +# libfoo.so. # The second file argument is - and this (stdin) receives the output # of the check-localplt program. @@ -14,7 +19,10 @@ BEGIN { result = 0 } FILENAME != "-" && /^#/ { next } FILENAME != "-" { - if (NF != 2 && !(NF == 3 && $3 == "?")) { + if (NF == 5 && $3 == "+" && ($4 == "RELA" || $4 == "REL")) { + accept_type[$1 " " $2] = $4; + accept_reloc[$1 " " $2] = $5; + } else if (NF != 2 && !(NF == 3 && $3 == "?")) { printf "%s:%d: bad data line: %s\n", FILENAME, FNR, $0 > "/dev/stderr"; result = 2; } else { @@ -23,7 +31,7 @@ FILENAME != "-" { next; } -NF != 2 { +NF != 2 && !(NF == 4 && ($3 == "RELA" || $3 == "REL")) { print "Unexpected output from check-localplt:", $0 > "/dev/stderr"; result = 2; next @@ -31,7 +39,23 @@ NF != 2 { { key = $1 " " $2 - if (key in accept) { + if ($3 == "RELA" || $3 == "REL") { + # Entries like: + # libc.so: free + RELA R_X86_64_GLOB_DAT + # may be ignored. + if (key in accept_type && accept_type[key] == $3 && accept_reloc[key] == $4) { + # Match + # libc.so: free + RELA R_X86_64_GLOB_DAT + delete accept_type[key] + } + } else if (NF == 2 && key in accept_reloc) { + # Match + # libc.so: free + # against + # libc.so: free + RELA R_X86_64_GLOB_DAT + if (key in accept_type) + delete accept_type[key] + } else if (key in accept) { delete accept[key] } else { print "Extra PLT reference:", $0; @@ -49,5 +73,11 @@ END { } } + for (key in accept_type) { + # It's mandatory. + print "Missing required PLT or " accept_reloc[key] " reference:", key; + result = 1; + } + exit(result); } diff --git a/scripts/localplt.awk b/scripts/localplt.awk index 84c94d1024..f75b3b427b 100644 --- a/scripts/localplt.awk +++ b/scripts/localplt.awk @@ -13,6 +13,8 @@ FILENAME != lastfile { } lastfile = FILENAME; jmprel_offset = 0; + rela_offset = 0; + rel_offset = 0; delete section_offset_by_address; } @@ -43,6 +45,30 @@ in_relocs && relocs_offset == jmprel_offset && NF >= 5 { } } +in_relocs && relocs_offset == rela_offset && NF >= 5 { + # Relocations against GNU_IFUNC symbols are not shown as an hexadecimal + # value, but rather as the resolver symbol followed by (). + if ($4 ~ /\(\)/) { + print whatfile, gensub(/@.*/, "", "g", $5), "RELA", $3 + } else { + symval = strtonum("0x" $4); + if (symval != 0) + print whatfile, gensub(/@.*/, "", "g", $5), "RELA", $3 + } +} + +in_relocs && relocs_offset == rel_offset && NF >= 5 { + # Relocations against GNU_IFUNC symbols are not shown as an hexadecimal + # value, but rather as the resolver symbol followed by (). + if ($4 ~ /\(\)/) { + print whatfile, gensub(/@.*/, "", "g", $5), "REL", $3 + } else { + symval = strtonum("0x" $4); + if (symval != 0) + print whatfile, gensub(/@.*/, "", "g", $5), "REL", $3 + } +} + in_relocs { next } $1 == "Relocation" && $2 == "section" && $5 == "offset" { @@ -62,4 +88,25 @@ $2 == "(JMPREL)" { next } +$2 == "(RELA)" { + rela_addr = strtonum($3); + if (rela_addr in section_offset_by_address) { + rela_offset = section_offset_by_address[rela_addr]; + } else { + print FILENAME ": *** DT_RELA does not match any section's address"; + result = 2; + } + next +} + +$2 == "(REL)" { + rel_addr = strtonum($3); + if (rel_addr in section_offset_by_address) { + rel_offset = section_offset_by_address[rel_addr]; + } else { + print FILENAME ": *** DT_REL does not match any section's address"; + result = 2; + } + next +} END { exit(result) } diff --git a/sysdeps/unix/sysv/linux/i386/localplt.data b/sysdeps/unix/sysv/linux/i386/localplt.data index b25abf8006..2e03821dfd 100644 --- a/sysdeps/unix/sysv/linux/i386/localplt.data +++ b/sysdeps/unix/sysv/linux/i386/localplt.data @@ -1,7 +1,9 @@ +# Linker in binutils 2.26 and newer consolidates R_X86_64_JUMP_SLOT +# relocation with R_386_GLOB_DAT relocation against the same symbol. libc.so: _Unwind_Find_FDE libc.so: calloc -libc.so: free -libc.so: malloc +libc.so: free + REL R_386_GLOB_DAT +libc.so: malloc + REL R_386_GLOB_DAT libc.so: memalign libc.so: realloc libm.so: matherr @@ -12,4 +14,4 @@ ld.so: __libc_memalign ld.so: malloc ld.so: calloc ld.so: realloc -ld.so: free +ld.so: free + REL R_386_GLOB_DAT diff --git a/sysdeps/x86_64/localplt.data b/sysdeps/x86_64/localplt.data new file mode 100644 index 0000000000..d140476dfe --- /dev/null +++ b/sysdeps/x86_64/localplt.data @@ -0,0 +1,19 @@ +# See scripts/check-localplt.awk for how this file is processed. +# PLT use is required for the malloc family and for matherr because +# users can define their own functions and have library internals call them. +# Linker in binutils 2.26 and newer consolidates R_X86_64_JUMP_SLOT +# relocation with R_X86_64_GLOB_DAT relocation against the same symbol. +libc.so: calloc +libc.so: free + RELA R_X86_64_GLOB_DAT +libc.so: malloc + RELA R_X86_64_GLOB_DAT +libc.so: memalign +libc.so: realloc +libm.so: matherr +# The dynamic loader uses __libc_memalign internally to allocate aligned +# TLS storage. The other malloc family of functions are expected to allow +# user symbol interposition. +ld.so: __libc_memalign +ld.so: malloc +ld.so: calloc +ld.so: realloc +ld.so: free + RELA R_X86_64_GLOB_DAT