{"id":83002,"date":"2011-03-24T08:04:10","date_gmt":"2011-03-24T00:04:10","guid":{"rendered":"\/2011\/03\/24\/glibc_linux.html"},"modified":"2011-03-24T08:04:10","modified_gmt":"2011-03-24T00:04:10","slug":"glibc_linux","status":"publish","type":"post","link":"https:\/\/blog.zhenglei.net\/?p=83002","title":{"rendered":"Override the GNU C library &#8212; painlessly"},"content":{"rendered":"<p><a href=\"http:\/\/www.ibm.com\/developerworks\/linux\/library\/l-glibc.html?t=gr,lnxw16=GNU\">http:\/\/www.ibm.com\/developerworks\/linux\/library\/l-glibc.html?t=gr,lnxw16=GNU<\/a><\/p>\n<p>&nbsp;<\/p>\n<p><strong>Summary:<\/strong>&nbsp; A great way to debug glibc functions is to override the  function of interest with your own version. This can be done without  having root permissions and without recompiling the libc source. Imagine  the pure thrill of writing your own version of <code>open()<\/code>!<\/p>\n<p>What do you do if you don&#8217;t have the source for your application and  it&#8217;s failing because a GNU Library for C (glibc) function is returning  something bad to the application? Because glibc is open-source, you can  of course get the source code, make your changes, rebuild, and install.  This is not for the faint of heart, however, because although the API is  well documented, the internal organization of the GNU C library is not.  Finding the correct function prototypes is only the first of many  challenges. It&#8217;s a big package as well, so the first time you compile,  it will take some time (glibc 2.2.2 has 8,552 files and 1,775,440 lines  of code, including comments).<\/p>\n<p><a name=\"build\"><span class=\"atitle\">A better way<\/span><\/a><\/p>\n<p>Better than rebuilding glibc is selectively overriding a function. Many  of the modern Unixes support the concept of preloading user defined  libraries. These libraries can be either complete replacements (that is,  a private version of glibc) or subsets &#8212; even a single function. You  can use a private version of glibc by setting the <code>LD_LIBRARY_PATH<\/code> to include your private version of the library first. You can use a subset of library routines that you write by using the <code>LD_PRELOAD<\/code> environmental value. Both <code>LD_LIBRARY_PATH<\/code> and <code>LD_PRELOAD<\/code> are controlled by the dynamic ELF linker\/loader. It uses a first match  to satisfy any symbol name. By preloading your version of a library or  function you short circuit the normal path, allowing you to override it.<\/p>\n<p>Here&#8217;s an example makefile that overrides the glibc function <code>setresgid()<\/code>:<\/p>\n<p><a name=\"code1\"><strong>Makefile to override setresgid()<\/strong><\/a><\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" width=\"100%\">\n<tbody>\n<tr>\n<td class=\"code-outline\">\n<pre class=\"displaycode\"> #<br \/> # Makefile <br \/> #<br \/><br \/> all: libs setresgid-tester<br \/><br \/> #<br \/> # Make a shared Library<br \/> #<br \/> libs: libfuncs.c<br \/>         gcc -shared -Wl,-soname,libfuncs.so.1 -o libfuncs.so.1.0  libfuncs.c <br \/>         ln -s libfuncs.so.1.0 libfuncs.so.1<br \/>         ln -s libfuncs.so.1 libfuncs.so<br \/><br \/> #<br \/> # Here is a program that calls setresgid() for testing<br \/> #<br \/> setresgid-tester: setresgid-tester.c<br \/>         gcc -o setresgid-tester setresgid-tester.c<br \/><\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p>The file <code>libfuncs.c<\/code> contains my private version of <code>setresgid()<\/code>. Be careful to implement it to support the same number of arguments and in other ways act the same as the original <code>setresgid()<\/code>, although my version lies to the application and always returns 0.<\/p>\n<p>The second file of interest is <code>setresgid-tester.c<\/code>. It tries out the new function by calling <code>setresgid()<\/code>.<\/p>\n<p>This is the source code for the dynamic library:<\/p>\n<p><a name=\"code2\"><strong>Replacement library<\/strong><\/a><\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" width=\"100%\">\n<tbody>\n<tr>\n<td class=\"code-outline\">\n<pre class=\"displaycode\"> \/*<br \/>  Put all the functions you want to override here<br \/> *\/<br \/> #include &lt;sys\/types.h&gt;<br \/> #include &lt;unistd.h&gt;<br \/> #include &lt;errno.h&gt;<br \/><br \/> int errno;<br \/><br \/> int <br \/> setresgid(rgid, egid, sgid)<br \/>         gid_t rgid,egid,sgid;<br \/> {<br \/>    errno=1; <br \/>    printf(\"It me the shim, Hi there!n\");<br \/>    return(0);<br \/><br \/> }<br \/><\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p>You&#8217;ll also need a simple way to test your private version of <code>setresgid()<\/code>. You can use strace or ltrace to watch the process run. This is the source for a trivial test example:<\/p>\n<p><a name=\"code3\"><strong>Trivial test example<\/strong><\/a><\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" width=\"100%\">\n<tbody>\n<tr>\n<td class=\"code-outline\">\n<pre class=\"displaycode\"> \/* <br \/>   setresgid() system\/library call tester <br \/> *\/<br \/> #include <br \/> #include <br \/> main(){<br \/>    setresgid(0,0,0);<br \/> }<br \/><\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p>Now compile the library, set the <code>LD_PRELOAD<\/code> shell variable and run the test application. You may also need to set your <code>LD_LIBRARY_PATH<\/code>.<\/p>\n<p><a name=\"code4\"><strong>Running test application<\/strong><\/a><\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" width=\"100%\">\n<tbody>\n<tr>\n<td class=\"code-outline\">\n<pre class=\"displaycode\">export LD_PRELOAD=libfuncs.so<br \/>export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH<br \/>.\/setresgid-tester<br \/>It's me the shim, Hi there!<br \/><\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<p>You can also confirm that your private library is being used by using ldd to list the dynamically linked libraries:<\/p>\n<p><a name=\"code4\"><strong>Confirming use of private library<\/strong><\/a><\/p>\n<table border=\"0\" cellspacing=\"0\" cellpadding=\"0\" width=\"100%\">\n<tbody>\n<tr>\n<td class=\"code-outline\">\n<pre class=\"displaycode\">[jay@prion ld_preload]$ ldd setresgid-tester<br \/>        libfuncs.so =&gt; libfuncs.so (0x40018000)<br \/>        libc.so.6 =&gt; \/lib\/libc.so.6 (0x40022000)<br \/>        \/lib\/ld-linux.so.2 =&gt; \/lib\/ld-linux.so.2 (0x40000000)<br \/><\/pre>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>&nbsp;<\/p>\n<div class=\"ibm-alternate-rule\">\n<hr \/>\n<\/div>\n<p class=\"ibm-ind-link ibm-back-to-top\"><a class=\"ibm-anchor-up-link\" href=\"http:\/\/www.ibm.com\/developerworks\/linux\/library\/l-glibc.html?t=gr,lnxw16=GNU#ibm-pcon\">Back to top<\/a><\/p>\n<p><a name=\"conclusion\"><span class=\"atitle\">Conclusion<\/span><\/a><\/p>\n<p>Writing private versions of GNU C library functions is a great way to debug systems problems or make quick fixes. Using the <code>LD_PRELOAD<\/code> shell variable, you can selectively override system C library functions  with your own private versions. This technique works for both Linux and  Solaris environments.<\/p>\n<p>&nbsp;<\/p>\n<p><a name=\"author\"><span class=\"atitle\">About the author<\/span><\/a><\/p>\n<div class=\"ibm-container ibm-portrait-module ibm-alternate-two\"><a href=\"..\/media\/agdqcmRibG9ncg0LEgVNZWRpYRiD8QQM\/glibc_overload.tgz?a=download\">http:\/\/blog.zhenglei.net\/media\/agdqcmRibG9ncg0LEgVNZWRpYRiD8QQM\/glibc_overload.tgz?a=download<\/a><\/div>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A great way to debug glibc functions is to override the function of interest with your own version. This can be done without having root permissions and without recompiling the libc source. Imagine the pure thrill of writing your own version of open()!<\/p>\n<p>About the author<\/p>\n<p>Jay Allen is a programmer in IBM&#8217;s Linux for Service Providers Lab (LSPL). <a href=\"https:\/\/blog.zhenglei.net\/?p=83002\">\u7ee7\u7eed\u9605\u8bfb <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[73],"class_list":["post-83002","post","type-post","status-publish","format-standard","hentry","category-linux","tag-linux-2"],"_links":{"self":[{"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/posts\/83002","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=83002"}],"version-history":[{"count":0,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=\/wp\/v2\/posts\/83002\/revisions"}],"wp:attachment":[{"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=83002"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=83002"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.zhenglei.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=83002"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}