Tuesday, January 27, 2015

linux: how to determine if a binary is prelinked

On my systems I use aide to find changes to the system. On one of them, aide was complaining:

WARNING: AIDE detected prelinked binary objects on your system but the prelink tool (/usr/sbin/prelink) is missing!
WARNING: prelinked files will be processed without a prelink undo operation! Please install prelink to fix this.

This is because at one point, I did in fact use prelink. However, I had many issues with aide and prelink and finally just got fed up and removed it. Before doing that you're supposed to undo the prelink, but apparently I missed a file. But aide didn't tell me which one! I couldn't find any information on the net about how to determine whether a binary is prelinked, so here's the answer:

readelf -S | grep prelink

If the binary is prelinked, you'll get something like:

[30] .gnu.prelink_undo PROGBITS 0000000000000000 000e4790

But what if you don't know which file is prelinked? And /etc/prelink.cache is non-existent (because someone removed it) or empty? In that case, you have to examine every ELF binary on the system. I elected to break this into two steps. First, find all the ELF binaries:

find / -type f ! -path "/sys/*" ! -path "/dev/*" ! -path "/proc/*" \
! -path "/opt/splunk/var/*" ! -path "/mnt/*" ! -path "/media/*" ! -path "/srv/*" \
! -path "/net/*" ! -path "/selinux/*" | xargs file | grep ELF | cut -f1 -d':' \
> /tmp/elffiles

Now that you have a list of all the ELF binaries, test each of them to find out if they are prelinked. I did not use xargs in this case because although readelf works on multiple files, when combined with grep it would be hard to tell which of the arguments in the long argument list is the culprit:
for file in $(cat /tmp/elffiles) ; do
   readelf -S $file | grep -q prelink
   if [ $? -eq 0 ]; then echo $file is prelinked ; fi
done

I realize the above doesn't handle paths with spaces or other weird characters. I guess I'm lucky my system didn't have any of those.