/[gentoo-projects]/pax-utils/scanelf.c
Gentoo

Diff of /pax-utils/scanelf.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1.239 Revision 1.240
1/* 1/*
2 * Copyright 2003-2007 Gentoo Foundation 2 * Copyright 2003-2007 Gentoo Foundation
3 * Distributed under the terms of the GNU General Public License v2 3 * Distributed under the terms of the GNU General Public License v2
4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.239 2012/01/23 22:28:17 vapier Exp $ 4 * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.240 2012/01/23 23:48:54 vapier Exp $
5 * 5 *
6 * Copyright 2003-2007 Ned Ludd - <solar@gentoo.org> 6 * Copyright 2003-2007 Ned Ludd - <solar@gentoo.org>
7 * Copyright 2004-2007 Mike Frysinger - <vapier@gentoo.org> 7 * Copyright 2004-2007 Mike Frysinger - <vapier@gentoo.org>
8 */ 8 */
9 9
10static const char rcsid[] = "$Id: scanelf.c,v 1.239 2012/01/23 22:28:17 vapier Exp $"; 10static const char rcsid[] = "$Id: scanelf.c,v 1.240 2012/01/23 23:48:54 vapier Exp $";
11const char argv0[] = "scanelf"; 11const char argv0[] = "scanelf";
12 12
13#include "paxinc.h" 13#include "paxinc.h"
14 14
15#define IS_MODIFIER(c) (c == '%' || c == '#' || c == '+') 15#define IS_MODIFIER(c) (c == '%' || c == '#' || c == '+')
53static char *out_format = NULL; 53static char *out_format = NULL;
54static char *search_path = NULL; 54static char *search_path = NULL;
55static char fix_elf = 0; 55static char fix_elf = 0;
56static char g_match = 0; 56static char g_match = 0;
57static char use_ldcache = 0; 57static char use_ldcache = 0;
58static char use_ldpath = 0;
58 59
59static char **qa_textrels = NULL; 60static char **qa_textrels = NULL;
60static char **qa_execstack = NULL; 61static char **qa_execstack = NULL;
61static char **qa_wx_load = NULL; 62static char **qa_wx_load = NULL;
62static int root_fd = AT_FDCWD; 63static int root_fd = AT_FDCWD;
799#define FLAG_MIPS64_LIBN32 0x0600 800#define FLAG_MIPS64_LIBN32 0x0600
800#define FLAG_MIPS64_LIBN64 0x0700 801#define FLAG_MIPS64_LIBN64 0x0700
801 802
802#if defined(__GLIBC__) || defined(__UCLIBC__) 803#if defined(__GLIBC__) || defined(__UCLIBC__)
803 804
804static char *lookup_cache_lib(elfobj *elf, char *fname) 805static char *lookup_cache_lib(elfobj *elf, const char *fname)
805{ 806{
806 int fd; 807 int fd;
807 char *strs; 808 char *strs;
808 static char buf[__PAX_UTILS_PATH_MAX] = ""; 809 static char buf[__PAX_UTILS_PATH_MAX] = "";
809 const char *cachefile = root_rel_path("/etc/ld.so.cache"); 810 const char *cachefile = root_rel_path("/etc/ld.so.cache");
877 878
878 return buf; 879 return buf;
879} 880}
880 881
881#elif defined(__NetBSD__) 882#elif defined(__NetBSD__)
882static char *lookup_cache_lib(elfobj *elf, char *fname) 883static char *lookup_cache_lib(elfobj *elf, const char *fname)
883{ 884{
884 static char buf[__PAX_UTILS_PATH_MAX] = ""; 885 static char buf[__PAX_UTILS_PATH_MAX] = "";
885 static struct stat st; 886 static struct stat st;
886 size_t n; 887 size_t n;
887 char *ldpath; 888 char *ldpath;
906} 907}
907#else 908#else
908#ifdef __ELF__ 909#ifdef __ELF__
909#warning Cache support not implemented for your target 910#warning Cache support not implemented for your target
910#endif 911#endif
911static char *lookup_cache_lib(elfobj *elf, char *fname) 912static char *lookup_cache_lib(elfobj *elf, const char *fname)
912{ 913{
913 return NULL; 914 return NULL;
914} 915}
915#endif 916#endif
917
918static char *lookup_config_lib(elfobj *elf, char *fname)
919{
920 static char buf[__PAX_UTILS_PATH_MAX] = "";
921 const char *ldpath;
922 size_t n;
923
924 array_for_each(ldpaths, n, ldpath) {
925 snprintf(buf, sizeof(buf), "%s/%s", root_rel_path(ldpath), fname);
926 if (faccessat(root_fd, buf, F_OK, AT_SYMLINK_NOFOLLOW) == 0)
927 return buf;
928 }
929
930 return NULL;
931}
916 932
917static const char *scanelf_file_needed_lib(elfobj *elf, char *found_needed, char *found_lib, int op, char **ret, size_t *ret_len) 933static const char *scanelf_file_needed_lib(elfobj *elf, char *found_needed, char *found_lib, int op, char **ret, size_t *ret_len)
918{ 934{
919 unsigned long i; 935 unsigned long i;
920 char *needed; 936 char *needed;
958 needed = elf->data + offset; \ 974 needed = elf->data + offset; \
959 if (op == 0) { \ 975 if (op == 0) { \
960 /* -n -> print all entries */ \ 976 /* -n -> print all entries */ \
961 if (!be_wewy_wewy_quiet) { \ 977 if (!be_wewy_wewy_quiet) { \
962 if (*found_needed) xchrcat(ret, ',', ret_len); \ 978 if (*found_needed) xchrcat(ret, ',', ret_len); \
963 if (use_ldcache) \ 979 if (use_ldpath) { \
980 if ((p = lookup_config_lib(elf, needed)) != NULL) \
981 needed = p; \
982 } else if (use_ldcache) { \
964 if ((p = lookup_cache_lib(elf, needed)) != NULL) \ 983 if ((p = lookup_cache_lib(elf, needed)) != NULL) \
965 needed = p; \ 984 needed = p; \
985 } \
966 xstrcat(ret, needed, ret_len); \ 986 xstrcat(ret, needed, ret_len); \
967 } \ 987 } \
968 *found_needed = 1; \ 988 *found_needed = 1; \
969 } else { \ 989 } else { \
970 /* -N -> print matching entries */ \ 990 /* -N -> print matching entries */ \
1419 case 'x': prints(" PAX "); break; 1439 case 'x': prints(" PAX "); break;
1420 case 'e': prints("STK/REL/PTL "); break; 1440 case 'e': prints("STK/REL/PTL "); break;
1421 case 't': prints("TEXTREL "); break; 1441 case 't': prints("TEXTREL "); break;
1422 case 'r': prints("RPATH "); break; 1442 case 'r': prints("RPATH "); break;
1423 case 'M': prints("CLASS "); break; 1443 case 'M': prints("CLASS "); break;
1444 case 'l':
1424 case 'n': prints("NEEDED "); break; 1445 case 'n': prints("NEEDED "); break;
1425 case 'i': prints("INTERP "); break; 1446 case 'i': prints("INTERP "); break;
1426 case 'b': prints("BIND "); break; 1447 case 'b': prints("BIND "); break;
1427 case 'Z': prints("SIZE "); break; 1448 case 'Z': prints("SIZE "); break;
1428 case 'S': prints("SONAME "); break; 1449 case 'S': prints("SONAME "); break;
1745 return ret; 1766 return ret;
1746} 1767}
1747 1768
1748#if defined(__GLIBC__) || defined(__UCLIBC__) || defined(__NetBSD__) 1769#if defined(__GLIBC__) || defined(__UCLIBC__) || defined(__NetBSD__)
1749 1770
1750static int load_ld_cache_config(int i, const char *fname) 1771static int _load_ld_cache_config(const char *fname)
1751{ 1772{
1752 FILE *fp = NULL; 1773 FILE *fp = NULL;
1753 char *p, *path; 1774 char *p, *path;
1754 size_t len; 1775 size_t len;
1755 int curr_fd = -1; 1776 int curr_fd = -1;
1756 1777
1757 fp = fopenat_r(root_fd, root_rel_path(fname)); 1778 fp = fopenat_r(root_fd, root_rel_path(fname));
1758 if (fp == NULL) 1779 if (fp == NULL)
1759 return i; 1780 return -1;
1760 1781
1761 path = NULL; 1782 path = NULL;
1762 len = 0; 1783 len = 0;
1763 while (getline(&path, &len, fp) != -1) { 1784 while (getline(&path, &len, fp) != -1) {
1764 if ((p = strrchr(path, '\r')) != NULL) 1785 if ((p = strrchr(path, '\r')) != NULL)
1789 if (glob(gpath, 0, NULL, &gl) == 0) { 1810 if (glob(gpath, 0, NULL, &gl) == 0) {
1790 for (x = 0; x < gl.gl_pathc; ++x) { 1811 for (x = 0; x < gl.gl_pathc; ++x) {
1791 /* try to avoid direct loops */ 1812 /* try to avoid direct loops */
1792 if (strcmp(gl.gl_pathv[x], fname) == 0) 1813 if (strcmp(gl.gl_pathv[x], fname) == 0)
1793 continue; 1814 continue;
1794 i = load_ld_cache_config(i, gl.gl_pathv[x]); 1815 _load_ld_cache_config(gl.gl_pathv[x]);
1795 } 1816 }
1796 globfree(&gl); 1817 globfree(&gl);
1797 } 1818 }
1798 1819
1799 /* failed globs are ignored by glibc */ 1820 /* failed globs are ignored by glibc */
1813 if (fchdir(curr_fd)) 1834 if (fchdir(curr_fd))
1814 /* don't care */; 1835 /* don't care */;
1815 close(curr_fd); 1836 close(curr_fd);
1816 } 1837 }
1817 1838
1818 return i; 1839 return 0;
1819} 1840}
1820 1841
1821#elif defined(__FreeBSD__) || defined(__DragonFly__) 1842#elif defined(__FreeBSD__) || defined(__DragonFly__)
1822 1843
1823static int load_ld_cache_config(int i, const char *fname) 1844static int _load_ld_cache_config(const char *fname)
1824{ 1845{
1825 FILE *fp = NULL; 1846 FILE *fp = NULL;
1826 char *b = NULL, *p; 1847 char *b = NULL, *p;
1827 struct elfhints_hdr hdr; 1848 struct elfhints_hdr hdr;
1828 1849
1829 fp = fopenat_r(root_fd, root_rel_path(fname)); 1850 fp = fopenat_r(root_fd, root_rel_path(fname));
1830 if (fp == NULL) 1851 if (fp == NULL)
1831 return i; 1852 return -1;
1832 1853
1833 if (fread(&hdr, 1, sizeof(hdr), fp) != sizeof(hdr) || 1854 if (fread(&hdr, 1, sizeof(hdr), fp) != sizeof(hdr) ||
1834 hdr.magic != ELFHINTS_MAGIC || hdr.version != 1 || 1855 hdr.magic != ELFHINTS_MAGIC || hdr.version != 1 ||
1835 fseek(fp, hdr.strtab + hdr.dirlist, SEEK_SET) == -1) 1856 fseek(fp, hdr.strtab + hdr.dirlist, SEEK_SET) == -1)
1836 { 1857 {
1837 fclose(fp); 1858 fclose(fp);
1838 return i; 1859 return -1;
1839 } 1860 }
1840 1861
1841 b = xmalloc(hdr.dirlistlen + 1); 1862 b = xmalloc(hdr.dirlistlen + 1);
1842 if (fread(b, 1, hdr.dirlistlen+1, fp) != hdr.dirlistlen+1) { 1863 if (fread(b, 1, hdr.dirlistlen+1, fp) != hdr.dirlistlen+1) {
1843 fclose(fp); 1864 fclose(fp);
1844 free(b); 1865 free(b);
1845 return i; 1866 return -1;
1846 } 1867 }
1847 1868
1848 while ((p = strsep(&b, ":"))) { 1869 while ((p = strsep(&b, ":"))) {
1849 if (*p == '\0') 1870 if (*p == '\0')
1850 continue; 1871 continue;
1851 xarraypush_str(ldpaths, p); 1872 xarraypush_str(ldpaths, p);
1852 } 1873 }
1853 1874
1854 free(b); 1875 free(b);
1855 fclose(fp); 1876 fclose(fp);
1856 return i; 1877 return 0;
1857} 1878}
1858 1879
1859#else 1880#else
1860#ifdef __ELF__ 1881#ifdef __ELF__
1861#warning Cache config support not implemented for your target 1882#warning Cache config support not implemented for your target
1862#endif 1883#endif
1863static int load_ld_cache_config(int i, const char *fname) 1884static int _load_ld_cache_config(const char *fname)
1864{ 1885{
1865 return 0; 1886 return 0;
1866} 1887}
1867#endif 1888#endif
1889
1890static void load_ld_cache_config(const char *fname)
1891{
1892 bool scan_l, scan_ul, scan_ull;
1893 size_t n;
1894 const char *ldpath;
1895
1896 _load_ld_cache_config(fname);
1897
1898 scan_l = scan_ul = scan_ull = false;
1899 if (array_cnt(ldpaths)) {
1900 array_for_each(ldpaths, n, ldpath) {
1901 if (!scan_l && !strcmp(ldpath, "/lib")) scan_l = true;
1902 if (!scan_ul && !strcmp(ldpath, "/usr/lib")) scan_ul = true;
1903 if (!scan_ull && !strcmp(ldpath, "/usr/local/lib")) scan_ull = true;
1904 }
1905 }
1906
1907 if (!scan_l) xarraypush_str(ldpaths, "/lib");
1908 if (!scan_ul) xarraypush_str(ldpaths, "/usr/lib");
1909 if (!scan_ull) xarraypush_str(ldpaths, "/usr/local/lib");
1910}
1868 1911
1869/* scan /etc/ld.so.conf for paths */ 1912/* scan /etc/ld.so.conf for paths */
1870static void scanelf_ldpath(void) 1913static void scanelf_ldpath(void)
1871{ 1914{
1872 char scan_l, scan_ul, scan_ull;
1873 size_t n; 1915 size_t n;
1874 const char *ldpath; 1916 const char *ldpath;
1875 int i = 0;
1876 1917
1877 if (array_cnt(ldpaths) == 0)
1878 err("Unable to load any paths from ld.so.conf");
1879
1880 scan_l = scan_ul = scan_ull = 0;
1881
1882 array_for_each(ldpaths, n, ldpath) { 1918 array_for_each(ldpaths, n, ldpath)
1883 if (!scan_l && !strcmp(ldpath, "/lib")) scan_l = 1;
1884 if (!scan_ul && !strcmp(ldpath, "/usr/lib")) scan_ul = 1;
1885 if (!scan_ull && !strcmp(ldpath, "/usr/local/lib")) scan_ull = 1;
1886 scanelf_dir(ldpath); 1919 scanelf_dir(ldpath);
1887 ++i;
1888 }
1889
1890 if (!scan_l) scanelf_dir("/lib");
1891 if (!scan_ul) scanelf_dir("/usr/lib");
1892 if (!scan_ull) scanelf_dir("/usr/local/lib");
1893} 1920}
1894 1921
1895/* scan env PATH for paths */ 1922/* scan env PATH for paths */
1896static void scanelf_envpath(void) 1923static void scanelf_envpath(void)
1897{ 1924{
1914#define PARSE_FLAGS "plRmyAXz:xetrnLibSs:k:gN:TaqvF:f:o:E:M:DIYO:ZCBhV" 1941#define PARSE_FLAGS "plRmyAXz:xetrnLibSs:k:gN:TaqvF:f:o:E:M:DIYO:ZCBhV"
1915#define a_argument required_argument 1942#define a_argument required_argument
1916static struct option const long_opts[] = { 1943static struct option const long_opts[] = {
1917 {"path", no_argument, NULL, 'p'}, 1944 {"path", no_argument, NULL, 'p'},
1918 {"ldpath", no_argument, NULL, 'l'}, 1945 {"ldpath", no_argument, NULL, 'l'},
1946 {"use-ldpath",no_argument, NULL, 129},
1919 {"root", a_argument, NULL, 128}, 1947 {"root", a_argument, NULL, 128},
1920 {"recursive", no_argument, NULL, 'R'}, 1948 {"recursive", no_argument, NULL, 'R'},
1921 {"mount", no_argument, NULL, 'm'}, 1949 {"mount", no_argument, NULL, 'm'},
1922 {"symlink", no_argument, NULL, 'y'}, 1950 {"symlink", no_argument, NULL, 'y'},
1923 {"archives", no_argument, NULL, 'A'}, 1951 {"archives", no_argument, NULL, 'A'},
1958}; 1986};
1959 1987
1960static const char * const opts_help[] = { 1988static const char * const opts_help[] = {
1961 "Scan all directories in PATH environment", 1989 "Scan all directories in PATH environment",
1962 "Scan all directories in /etc/ld.so.conf", 1990 "Scan all directories in /etc/ld.so.conf",
1991 "Use ld.so.conf to show full path (use with -r/-n)",
1963 "Root directory (use with -l or -p)", 1992 "Root directory (use with -l or -p)",
1964 "Scan directories recursively", 1993 "Scan directories recursively",
1965 "Don't recursively cross mount points", 1994 "Don't recursively cross mount points",
1966 "Don't scan symlinks", 1995 "Don't scan symlinks",
1967 "Scan archives (.a files)", 1996 "Scan archives (.a files)",
2035static int parseargs(int argc, char *argv[]) 2064static int parseargs(int argc, char *argv[])
2036{ 2065{
2037 int i; 2066 int i;
2038 const char *from_file = NULL; 2067 const char *from_file = NULL;
2039 int ret = 0; 2068 int ret = 0;
2069 char load_cache_config = 0;
2040 2070
2041 opterr = 0; 2071 opterr = 0;
2042 while ((i=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) { 2072 while ((i=getopt_long(argc, argv, PARSE_FLAGS, long_opts, NULL)) != -1) {
2043 switch (i) { 2073 switch (i) {
2044 2074
2133 setpax = flags; 2163 setpax = flags;
2134 break; 2164 break;
2135 } 2165 }
2136 case 'Z': show_size = 1; break; 2166 case 'Z': show_size = 1; break;
2137 case 'g': g_match = 1; break; 2167 case 'g': g_match = 1; break;
2138 case 'L': use_ldcache = 1; break; 2168 case 'L': load_cache_config = use_ldcache = 1; break;
2139 case 'y': scan_symlink = 0; break; 2169 case 'y': scan_symlink = 0; break;
2140 case 'A': scan_archives = 1; break; 2170 case 'A': scan_archives = 1; break;
2141 case 'C': color_init(true); break; 2171 case 'C': color_init(true); break;
2142 case 'B': show_banner = 0; break; 2172 case 'B': show_banner = 0; break;
2143 case 'l': scan_ldpath = 1; break; 2173 case 'l': load_cache_config = scan_ldpath = 1; break;
2144 case 'p': scan_envpath = 1; break; 2174 case 'p': scan_envpath = 1; break;
2145 case 'R': dir_recurse = 1; break; 2175 case 'R': dir_recurse = 1; break;
2146 case 'm': dir_crossmount = 0; break; 2176 case 'm': dir_crossmount = 0; break;
2147 case 'X': ++fix_elf; break; 2177 case 'X': ++fix_elf; break;
2148 case 'x': show_pax = 1; break; 2178 case 'x': show_pax = 1; break;
2163 case 128: 2193 case 128:
2164 root_fd = open(optarg, O_RDONLY|O_CLOEXEC); 2194 root_fd = open(optarg, O_RDONLY|O_CLOEXEC);
2165 if (root_fd == -1) 2195 if (root_fd == -1)
2166 err("Could not open root: %s", optarg); 2196 err("Could not open root: %s", optarg);
2167 break; 2197 break;
2198 case 129: load_cache_config = use_ldpath = 1; break;
2168 case ':': 2199 case ':':
2169 err("Option '%c' is missing parameter", optopt); 2200 err("Option '%c' is missing parameter", optopt);
2170 case '?': 2201 case '?':
2171 err("Unknown option '%c' or argument missing", optopt); 2202 err("Unknown option '%c' or argument missing", optopt);
2172 default: 2203 default:
2215 case 'i': show_interp = 1; break; 2246 case 'i': show_interp = 1; break;
2216 case 'b': show_bind = 1; break; 2247 case 'b': show_bind = 1; break;
2217 case 'S': show_soname = 1; break; 2248 case 'S': show_soname = 1; break;
2218 case 'T': show_textrels = 1; break; 2249 case 'T': show_textrels = 1; break;
2219 default: 2250 default:
2220 err("Invalid format specifier '%c' (byte %i)", 2251 err("invalid format specifier '%c' (byte %i)",
2221 out_format[i], i+1); 2252 out_format[i], i+1);
2222 } 2253 }
2223 } 2254 }
2224 2255
2225 /* construct our default format */ 2256 /* construct our default format */
2248 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len); 2279 if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len);
2249 } 2280 }
2250 if (be_verbose > 2) printf("Format: %s\n", out_format); 2281 if (be_verbose > 2) printf("Format: %s\n", out_format);
2251 2282
2252 /* now lets actually do the scanning */ 2283 /* now lets actually do the scanning */
2253 if (scan_ldpath || use_ldcache) 2284 if (load_cache_config)
2254 load_ld_cache_config(0, __PAX_UTILS_DEFAULT_LD_CACHE_CONFIG); 2285 load_ld_cache_config(__PAX_UTILS_DEFAULT_LD_CACHE_CONFIG);
2255 if (scan_ldpath) scanelf_ldpath(); 2286 if (scan_ldpath) scanelf_ldpath();
2256 if (scan_envpath) scanelf_envpath(); 2287 if (scan_envpath) scanelf_envpath();
2257 if (!from_file && optind == argc && ttyname(0) == NULL && !scan_ldpath && !scan_envpath) 2288 if (!from_file && optind == argc && ttyname(0) == NULL && !scan_ldpath && !scan_envpath)
2258 from_file = "-"; 2289 from_file = "-";
2259 if (from_file) { 2290 if (from_file) {

Legend:
Removed from v.1.239  
changed lines
  Added in v.1.240

  ViewVC Help
Powered by ViewVC 1.1.20