This Time Self-Hosted
dark mode light mode Search

One more reason not to trust CMake

So everybody says that CMake is great because it’s faster. Of course CMake achieves speed with an approach different from the one autotools have, that is, they don’t discover features, they apply knowledge. Hey it’s a valid method as any other, if you actually know what you are doing, and if you can keep up with variants and all the rest. Another thing that it does is to avoid the re-linking during the install phase.

Let me try to explain why re-linking exists: when you build a project using libtool, there might be binaries (executables and/or libraries) that depend on shared libraries that are being built in the same source tree. When you run the executables from the source tree, you want them to be used. When you install, as you might be installing just a subtree of the original software, libtool tries to guess if you just installed the library or not (often making mistakes) and if not, it re-links the target, that is, recreates it from scratch to link to the system library. In the case of packages built by ebuild, by the use of DESTDIR, we almost always have the relinking stage in there. Given that GNU ld is slow (and IMHO should be improved, rather than replaced by gold, but that’s material for another post), it’s a very wasteful process indeed, and libtool should be fixed not to perform that stage every time.

One of the things that the relinking stage is supposed to take care is to replace the rpath entries. An rpath entry specify to the runtime linker (ld.so) where to find the dependent libraries outside of the usual library paths (that is /etc/ld.so.conf and LD_LIBRARY_PATH). It’s used for non-standard install directories (for instance for internal libraries that should never be linked against) or during the in-tree execution of software, so that the just-built libraries are preferred over the ones in the system already.

So to make the install phase faster in CMake, they decided, with 2.6 series, to avoid the relinking, by messing with the rpath entries directly. It would be all fine and nice if they did it correctly of course.

I reported earlier a bug about cmake creating insecure runpaths in executables starting from version 2.6. Don’t panic, if you’re using Portage, it’s all fine, because the scanelf run that reports the problem also fixes it already. In that bug you can find a link to a discussion from April . The problem was known before 2.6.0 final was released, yet it was not addressed.

So it seems like someone (Alex) used chrpath first. That’s a good choice, there’s a tool out there that does what you need, use it. At the worse you use it wrong and you fix it fine.

But no, that’s not good enough for Kitware, of course, and Brad King decided to replace that with a built-in ELF parser (and editor). Guess what? Mr. King does not know ELF that well, and expected an empty rpath to behave like no rpath at all.

Try these simple commands:

% echo "echo Mr. King does not know ELF" > test-cmake-rpath
% chmod +x test-cmake-rpath
% PATH= test-cmake-rpathCode language: PHP (php)

An empty PATH adds the current working directory to it. Which means that the generated ELF files from CMake 2.6 would load any library that is in the current working directory that is named after one of the names in the NEEDED lines of itself and its dependencies. There are a few attack vectors exploiting those; not all of them are exactly easy to apply, most of them don’t cause root vulnerabilities but it’s still not good.

Now of course a mistake, or missing knowledge about a particular meaning of a value in an ELF file is nothing major. Myself I didn’t know about PATH= before a few months ago, but I did know an empty rpath was not good at least.

What is the problem then? The problem is that messing with an ELF attribute like rpath, without knowing ELF files, without knowing the behaviour of ld.so and even more importantly without asking to any of the QA team of any of the distributions out there (Gentoo is certainly not the only one who dislikes insecure rpath), is just not something that earns my trust. At all.

And even worse, if the original implementation used chrpath, why not leaving it at that? Given you don’t know enough about ELF files it sounds like a very good idea. It’s not like chrpath is a tremendously exotic tool to have around for distributions.

For your information, this is how chrpath behave, and how it’s difficult to actually misuse:

flame@enterprise mytmpfs % scanelf -r hellow*
 TYPE   RPATH FILE 
ET_EXEC /tmp hellow 
ET_EXEC   -   hellow-2 
ET_EXEC  hellow-3 
flame@enterprise mytmpfs % scan
flame@enterprise mytmpfs % gcc -Wl,-rpath,/tmp hellow.c -o hellow 
flame@enterprise mytmpfs % scanelf -r hellow 
 TYPE   RPATH FILE 
ET_EXEC /tmp hellow 
flame@enterprise mytmpfs % cp hellow hellow-2
flame@enterprise mytmpfs % chrpath -d hellow-2   
flame@enterprise mytmpfs % scanelf -r hellow-2
 TYPE   RPATH FILE 
ET_EXEC   -   hellow-2 
flame@enterprise mytmpfs % cp hellow hellow-3
flame@enterprise mytmpfs % chrpath -r '' hellow-3
hellow-3: RPATH=/tmp
hellow-3: new RPATH: 
flame@enterprise mytmpfs % scanelf -r hellow-3
 TYPE   RPATH FILE 
ET_EXEC  hellow-3Code language: CSS (css)

And this is the easy fix:

flame@enterprise mytmpfs % scanelf -Xr hellow-3
 TYPE   RPATH FILE 
ET_EXEC   -   hellow-3 Code language: CSS (css)

Okay now at the end of the day, what can we do about this problem? Well in Gentoo we should disable this behaviour from CMake, let’s make it a bit slower, but safer; even if scanelf is covering our butts, it’s still a patching up something that someone else is continuously screwing up; and it opens the vulnerability when the users build without Portage.

And indeed, if you are building something with CMake 2.6, outside of Portage, you might also want to fix the rpaths of the installed executables and libraries, by issuing scanelf -RXr $path_to_the_installed_tree. Possibly after each time you rebuild your stuff.

To finish, a nice note that shows just how much caring people handling CMake in KDE are …. KDE trunk will require CMake 2.6 on August 4th . Nevermind there is an open security issue related to the code it builds.

Oh the irony, and they say I don’t give enough arguments why I don’t like CMake!

Comments 11
  1. debian doesn’t have this problem:cmake on debian is build with:echo CMAKE_SKIP_RPATH:BOOL=YES >> Build/CMakeCache.txt

  2. @gebi that makes running QA tests difficultNote that outside of Portage, adding -DCMAKE_NO_BUILTIN_CHRPATH:BOOL=ONto cmake-utils.eclass with fix builds that use that eclass. Though not all ebuilds use cmake-utils.Excellent explanation Mr. Eyes. Please, less hating on cmake. They are trying to improve an excellent program, have bugs like everyone else, and could use bug reports from smart fellows like yourself.

  3. Oh I reported a bug before to kitware, with a solution attached too. It was left ignored without even a comment until someone with a @kde.org address noted the same problem, months later.And this particular problem is, once again, known from _before_ I actually hit it, because I only hit it with 2.6.0 final and it was known during RCs.The problem is, Kitware is not trying to “improve an excellent program” but rather trying to “sell” cmake. They are not getting paid for it directly but I’m sure they wouldn’t avoid making money once they had enough “market”. Which is not wrong by itself, kudos to them if they can provide a free software product and get money out of it, the problem is that they won’t listen to anybody unless it has enough critical mass to be “useful” to them.In that regard, I think very bad of CMake. I would invert this tendency if they actually started _trying_ to be less obnoxious to distributions, for instance allowing to disable the xmlrpc-c dependency, or starting not to bundle so many internal libraries. Up to now, I only see CMake is getting worse, rather than better.

  4. I hope they can make a bunch of money to support the project. My impression is that it originally was developed to scratch a personal itch, and it still has a lot of focus in that direction. They do have a book available for purchase. Hopefully it is better than Kitware’s VTK books, because I bought those and file them under the horror section of my bookshelf they are so bad :PI doubt not having an @kde.org address really made a difference. My impression is that they are a little swamped in maintenance.Embedded libs certainly is a troublesome issue. Another problem, given the limited manpower of official devs, is module maintenance. The ‘apply knowledge’ principle, as you put it, requires constant updates of the knowledge. Because of time constraits, only the critical mass modules, like KDE, are going to get brought in or updated.Not sure about the solution to this problem. Individual projects should probably distribution their own FindXXX.cmake, e.g., but individual projects with modules for other projects has the sour taste of embedded libs in a program. Maybe a repository using one of the new distributed version control systems.

  5. I am trying to figure out where you reported this issue to Kitware. I am sure you reported it somewhere. I did a search on the cmake bug tracker: http://www.cmake.org/Bug for rpath and was unable to find your posting.I was certainly not aware of this issue. I just found this blog from a google alert on CMake. It is unfortunate since I just released 2.6.1 after about 16 release candidates… Had I personally known about this issue I would have held off on 2.6.1. If you have serious issues with CMake, please report them to the CMake bug tracker or to the CMake mailing list. Anyway, I will investigate it now, and there is always CMake 2.6.2. :)The embedded libs allow us to build on platforms out of the box without folks having to go on an Easter egg hunt to get required software (very helpful on Windows, and UNIX systems like Sun,HP, or IRIX). We did add support to disable them in the build, and use system libraries (CMAKE_USE_SYSTEM_LIBRARIES=TRUE). Which BTW, has caused bugs in CMake as the system libraries can have subtle changes that break CMake. The ones shipped with CMake are tested nightly.The CMake work was originally started for the itk project(http://www.itk.org). Several other groups have contributed to the effort. You can find them here: http://www.cmake.org/HTML/i… in the Sponsors tab.As far as being less “obnoxious”, if we disable the use of a library for a distribution, then that distribution will have missing features. Once we add a feature we like to keep it around for backwards compatibility. It seems to me if you allowed too much variation in the feature set that was CMake, it would become inconstant for users when they used CMake on different distributions. We don’t link in libraries if something is not using them.Again, if you have issues with CMake, please bring them to the cmake bug tracker or mailing list so they can be discussed with the CMake community.Thanks.

  6. CMake 2.6.0 did address the problem you describe. When a binary is *installed* it never ends up with an empty RPATH created by CMake. If the user-specified RPATH is the empty string the file will end up with no RPATH entry at all.Only files in the *build* tree have empty RPATH entries. These entries are of the form ‘/original/rpath:::::::’, and this has not changed from Alex’s original chrpath version. They are needed to reserve space for the RPATH in the to-be-installed binary if it is longer than the build tree RPATH.If you still think there is a problem, please report it to our bug tracker.

  7. As the QA tests from Gentoo are applied _after_ the install phase, I do think there is still a problem, as the files coming up with empty RPATH are the ones that are installed.Feel free to try yourself with the scanelf tool, it’s available in Debian too as pax-utils and you can simply download the source and build them (mind you, with simple GNU make) and see by yourself..

  8. I’ve used “readelf -d” to confirm that installed binaries have no RPATH entry at all. Please submit a bug report here:http://www.cmake.org/Bugwith instructions to reproduce the problem (a CMakeLists.txt file and sources or a pointer at a real project).

  9. I tried getting scanelf and running: scanelf -rq <file>I get the error:scanelf: rpath_security_checks(): Security problem NULL DT_RPATH in <file>for the files with ‘::::’ in the build tree (as expected), but no error for files in the install tree.————————————-As far as why we decided not to use chrpath, see here:http://sourceware.org/ml/bi

  10. > Nevermind there is an open security> issue related to the code it builds.Well, I don’t follow all bug trackers out there, and I can’t remember the notification you mention (lot’s of emails to process every day, so, maybe I forgot it, maybe it wasn’t stated explicitely enough, maybe a spam filter caught it, I don’t know).If you find problem with cmake, please report it in the cmake bug tracker, or on the cmake list.If it’s a cmake-in-kde related error, please report it on kde-buildsystem@kde.org, or on bugs.kde.org -> buildsystem -> cmake, or directly to me if nothing else helps.If nothing happens about it, send a reminder.AlexP.S. writing in a public blog “Mr. King doesn’t know ELF” is not a very nice way to communicate. Personally I know nobody who is working more carefully and thoroughly than he does. Seriously.

  11. OK, we found the issue. It will be fixed in cmake 2.6.2, and is fixed in CVS cmake right now. The issue was that on gentoo both RPATH and RUNPATH were being set and cmake was only handling RPATH. In the future if you find serious issues with CMake, we (the CMake team) would really appreciate it if you reported them to the CMake bug tracker. Thanks.Bill

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.