| <part id='qa'> |
| <title>Quality Assurance</title> |
| <chapter id='qa-notices'> |
| <title>QA Notices</title> |
| <para> |
| Here we'll go over each QA notice and what you (as a developer) can do to fix |
| the issue. If you're a user, you should of course go |
| <ulink url="https://bugs.gentoo.org/">file a bug</ulink>. We'll only cover the |
| non-obvious notices here. |
| </para> |
| <para> |
| In pretty much all cases, you should try and get these issues resolved |
| upstream rather than simply fixing them in our ebuilds. |
| </para> |
| |
| <sect1 id='qa-scanelf-runpath'> |
| <title>Scanelf: Insecure RUNPATHs</title> |
| <para> |
| <programlisting> |
| QA Notice: The following files contain insecure RUNPATHs |
| </programlisting> |
| </para> |
| <para> |
| Some of the ELFs that would be installed on the system have insecure dynamic |
| RUNPATH tags. RUNPATH tags are a hardcoded list of filesystem paths that |
| will be searched at runtime when the ELF is executed. If the ELF has a |
| world accessible directory hardcoded in it, then a malicious person can |
| inject code at runtime by adding their own libraries to the directory. |
| </para> |
| <para> |
| Here are some of the common problems and their solutions. |
| <itemizedlist> |
| <listitem> |
| <para>Libtool - old versions of libtool would use too many -rpath flags</para> |
| <para>Solution: Regenerate the autotool code</para> |
| </listitem> |
| <listitem> |
| <para>Perl - some versions of perl would use incorrect -rpath flags</para> |
| <para>Solution: Upgrade system perl build modules</para> |
| </listitem> |
| <listitem> |
| <para>Crappy build system - the custom build system uses -rpath incorrectly</para> |
| <para>Solution: Review the LDFLAGS in the build system and make them not suck</para> |
| </listitem> |
| <listitem> |
| <para>Crappy ebuild - the ebuild installs ELFs instead of using the package's build system</para> |
| <para>Solution: Fix the crappy ebuild to use the package's build system</para> |
| </listitem> |
| </itemizedlist> |
| </para> |
| </sect1> |
| |
| <sect1 id='qa-scanelf-textrel'> |
| <title>Scanelf: Runtime Text Relocations (TEXTRELS)</title> |
| <para> |
| <programlisting> |
| QA Notice: The following files contain runtime text relocations |
| </programlisting> |
| </para> |
| <para> |
| Please see the Gentoo Hardened <ulink url="https://wiki.gentoo.org/wiki/Hardened/Textrels_Guide">PIC Fix Guide</ulink>. |
| </para> |
| </sect1> |
| |
| <sect1 id='qa-scanelf-execstack'> |
| <title>Scanelf: Executable Stack (EXECSTACK)</title> |
| <para> |
| <programlisting> |
| QA Notice: The following files contain executable stacks |
| </programlisting> |
| </para> |
| <para> |
| Please see the Gentoo Hardened <ulink url="https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart">GNU Stack Guide</ulink>. |
| </para> |
| </sect1> |
| |
| <sect1 id='qa-scanelf-soname'> |
| <title>Scanelf: Missing Shared Object Name (SONAME)</title> |
| <para> |
| <programlisting> |
| QA Notice: The following shared libraries lack a SONAME |
| </programlisting> |
| </para> |
| <para> |
| A shared library that you would link against lacks an ELF SONAME tag. With |
| simpler libraries, this can be acceptable, but with any sort of ABI sane |
| setup, you need the SONAME tag. This tag is how the system linker tells the |
| loader what libraries a program needs at runtime. With a missing SONAME, |
| the linker needs to guess and with many cases, this guess will not work for |
| long. |
| </para> |
| <para> |
| To fix this issue, make sure the shared library is linked with the proper |
| <option>-Wl,-soname,...</option> flag. You will need to replace the |
| <replaceable>...</replaceable> part with the actual ABI name. For example, |
| if the library is named <filename>libfoo.so.1.2.3</filename>, you will |
| probably want to specify <option>-Wl,-soname,libfoo.so.1</option>. |
| </para> |
| <para> |
| Note that this warning only applies to shared libraries that you would link |
| against. It certainly does not apply to plugins that you would dynamically |
| load. However, plugins should not exist in the main library directory, but |
| rather an application specific subdirectory in the library directory. In |
| other words, it should be <filename>/usr/lib/app/plugin.so</filename> rather |
| than <filename>/usr/lib/plugin.so</filename>. |
| </para> |
| </sect1> |
| |
| <sect1 id='qa-scanelf-needed'> |
| <title>Scanelf: Missing Needed Entries</title> |
| <para> |
| <programlisting> |
| QA Notice: The following shared libraries lack NEEDED entries |
| </programlisting> |
| </para> |
| <para> |
| This warning comes up when a library does not actually seem to need any |
| other libraries in order to run. Rarely is this true as almost every |
| library will need at least the system C library. |
| </para> |
| <para> |
| Once you've determined that the library is indeed being generated |
| incorrectly, you will need to dig into the build system to make sure that |
| it pulls in the libraries it needs. Often times, this is because the |
| build system invokes the system linker (<command>ld</command>) directly |
| instead of the system compiler driver (<command>gcc</command>). |
| </para> |
| </sect1> |
| |
| <sect1 id='qa-unresolved-soname-dependencies'> |
| <title>Unresolved soname dependencies</title> |
| <para> |
| <programlisting> |
| QA Notice: Unresolved soname dependencies |
| </programlisting> |
| </para> |
| <para> |
| This warning comes up when a library or executable has one or more |
| soname dependencies (found in its NEEDED.ELF.2 metadata) that could |
| not be resolved by usual means. If you run <command>ldd</command> on |
| files like these then it will report a "not found" error for each |
| unresolved soname dependency. In order to correct problems with |
| soname dependency resolution, use one or more of the approaches |
| described in the following sections. |
| </para> |
| <para> |
| Content of the NEEDED.ELF.2 metadata file may be useful for |
| debugging purposes. Find the NEEDED.ELF.2 file in the |
| ${D}/../build-info/ directory after the ebuild src_install phase |
| completes, or in the /var/db/pkg/*/*/ directory for an installed |
| package. Each line of the NEEDED.ELF.2 file contains semicolon |
| separated values for a single ELF file. The soname dependencies are |
| found in the DT_NEEDED column: |
| <programlisting> |
| E_MACHINE;path;DT_SONAME;DT_RUNPATH;DT_NEEDED;multilib category |
| </programlisting> |
| </para> |
| <sect2 id='qa-unresolved-soname-dependencies-resolved-bu-external-dependencies'> |
| <title>External dependencies</title> |
| <para> |
| For packages that install pre-built binaries, it may be possible to |
| resolve soname dependencies simply by adding dependencies for one |
| or more other packages that are known to provide the needed sonames. |
| </para> |
| </sect2> |
| <sect2 id='qa-unresolved-soname-dependencies-resolved-by-removal-of-unecessary-files'> |
| <title>Removal of unecessary files</title> |
| <para> |
| For packages that install pre-built binaries, it may be possible to |
| resolve soname dependencies simply by removing unnecessary files |
| which have unresolved soname dependencies. For example, some pre-built |
| binary packages include binaries intended for irrelevant architectures |
| or operating systems, and these files can simply be removed because |
| they are unnecessary. |
| </para> |
| </sect2> |
| <sect2 id='qa-unresolved-soname-dependencies-resolved-by-addition-of-dt-runpath-entries'> |
| <title>Addition of DT_RUNPATH entries</title> |
| <para> |
| If the relevant dependencies are installed in a location that is not |
| included in the dynamic linker search path, then it's necessary for |
| files to include a DT_RUNPATH entry which refers to the appropriate |
| directory. The special $ORIGIN value can be used to create a relative |
| path reference in DT_RUNPATH, where $ORIGIN is a placeholder for the |
| directory where the file having the DT_RUNPATH entry is located. |
| </para> |
| <para> |
| For pre-built binaries, it may be necessary to fix up DT_RUNPATH using |
| <command>patchelf --set-rpath</command>. For example, use |
| <command>patchelf --set-rpath '$ORIGIN'</command> if a given binary |
| should link to libraries found in the same directory as the binary |
| itself, or use <command>patchelf --set-rpath '$ORIGIN/libs'</command> |
| if a given binary should link to libraries found in a subdirectory |
| named libs found in the same directory as the binary itself. |
| </para> |
| <para> |
| For binaries built from source, a flag like |
| <option>-Wl,-rpath,/path/of/directory/containing/libs</option> will |
| create binaries with the desired DT_RUNPATH entry. |
| </para> |
| </sect2> |
| <sect2 id='qa-unresolved-soname-dependencies-resolved-by-addition-of-dt-soname-settings'> |
| <title>Addition of DT_SONAME settings</title> |
| <para> |
| If a package installs dynamic libraries which do not set DT_SONAME, |
| then this can lead to unresolved soname dependencies. |
| For dynamic libraries built from source, a flag like |
| <option>-Wl,-soname=foo.so.1</option> will create a DT_SONAME setting. |
| For pre-built dynamic libraries, it may be necessary to fix up |
| DT_SONAME using <command>patchelf --set-soname</command>. |
| </para> |
| </sect2> |
| <sect2 id='qa-unresolved-soname-dependencies-resolved-by-adjustment-to-portage-soname-resolution-logic'> |
| <title>Adjustment to Portage soname resolution logic</title> |
| <para> |
| It may be necessary to adjust Portage soname resolution logic in |
| order to account for special circumstances. For example, Portage |
| soname resolution tolerates missing DT_SONAME for dynamic libraries |
| that a package installs in a directory that its binaries reference |
| via DT_RUNPATH. This behavior is useful for packages that have |
| internal dynamic libraries stored in a private directory. An example |
| is ebtables, as discussed in |
| <ulink url="https://bugs.gentoo.org/646190">bug 646190</ulink>. |
| </para> |
| </sect2> |
| </sect1> |
| |
| <sect1 id='qa-abs-lib-link'> |
| <title>Absolute Symlink In Library Directory</title> |
| <para> |
| <programlisting> |
| QA Notice: Found an absolute symlink in a library directory |
| </programlisting> |
| </para> |
| <para> |
| If you want to use symlinks in library directories, please use either a |
| relative symlink or a linker script. This can cause problems when working |
| with cross-compiler systems or when accessing systems in a different ROOT |
| directory. |
| </para> |
| <para> |
| If you have a library installed into <filename>/lib/</filename> and you want |
| to have it accessible in <filename>/usr/lib/</filename>, then you should |
| generate a linker script so that the system toolchain can handle it properly. |
| Please see the <link linkend="qa-missing-ldscript">linker script section</link> |
| for more information. |
| </para> |
| </sect1> |
| |
| <sect1 id='qa-missing-ldscript'> |
| <title>Missing Linker Script</title> |
| <para> |
| <programlisting> |
| QA Notice: Missing gen_usr_ldscript |
| </programlisting> |
| </para> |
| <para> |
| If you have a shared library in <filename>/lib/</filename> and a static |
| library in <filename>/usr/lib/</filename>, but no linker script in |
| <filename>/usr/lib/</filename>, then the toolchain will choose the incorrect |
| version when linking. The system linker will find the static library first |
| and not bother searching for a dynamic version. To overcome this, you need |
| to use the <command>gen_usr_ldscript</command> function found in the |
| toolchain-funcs.eclass. Refer to the |
| man page for information on how to use it. See this |
| <ulink url="https://bugs.gentoo.org/4411">bug report</ulink> for some history |
| on this issue. |
| </para> |
| </sect1> |
| |
| <sect1 id='qa-root-cruft'> |
| <title>Excessive Files in /</title> |
| <para> |
| <programlisting> |
| QA Notice: Excessive files found in the / partition |
| </programlisting> |
| </para> |
| <para> |
| You should not store files that are not critical to boot and recovery in |
| the root filesystem. This means that static libraries and libtool scripts do |
| not belong in the <filename>/lib/</filename> directory. Fix your ebuild so |
| it does not install there. |
| </para> |
| </sect1> |
| |
| <sect1 id='qa-tempdir-libtool'> |
| <title>Portage Tempdir In Libtool Scripts</title> |
| <para> |
| <programlisting> |
| QA Notice: ... appears to contain PORTAGE_TMPDIR paths |
| </programlisting> |
| </para> |
| <para> |
| Older versions of libtool would incorrectly record the build and/or install |
| directory in the libtool script (*.la). This would lead to problems when |
| building other things against your package as libtool would be confused by |
| the old paths. |
| </para> |
| <para> |
| You may be able to cheat and use the <command>elibtoolize</command> function |
| in the libtool.eclass. However, if |
| that does not help, you will probably need to regenerate all of the autotool |
| files. |
| </para> |
| </sect1> |
| |
| <sect1 id='qa-build-strict-aliasing'> |
| <title>Build Warning: Strict Aliasing</title> |
| <para> |
| <programlisting> |
| QA Notice: Package has poor programming practices which may compile |
| fine but exhibit random runtime failures. |
| ...: warning: dereferencing type-punned pointer will break strict-aliasing rules |
| </programlisting> |
| </para> |
| <para> |
| This warning crops up when code starts casting distinct pointer types and |
| then dereferencing them. Generally, this is a violation of aliasing rules |
| which are part of the C standard. Historically, these warnings did not show |
| up as the optimization was not turned on by default. With gcc-4.1.x and |
| newer though, the -O2 optimization level enables strict aliasing support. |
| For information, please review these links: |
| <ulink url="https://mail-index.netbsd.org/tech-kern/2003/08/11/0001.html">NetBSD Explanation</ulink>, |
| <ulink url="http://thread.gmane.org/gmane.linux.gentoo.devel/39495">Gentoo Dev Thread</ulink>, |
| <ulink url="https://gcc.gnu.org/bugs.html#nonbugs_c">GCC Docs</ulink>, |
| <ulink url="http://cellperformance.beyond3d.com/articles/2006/06/understanding-strict-aliasing.html">Practical examples</ulink>. |
| </para> |
| <para> |
| To fix this issue, use the methods proposed in the links mentioned earlier. |
| If you're unable to do so, then a work around would be to append the gcc |
| -fno-strict-aliasing flag to CFLAGS in the ebuild. |
| </para> |
| </sect1> |
| |
| <sect1 id='qa-build-implicit-decl'> |
| <title>Build Warning: Implicit Declarations</title> |
| <para> |
| <programlisting> |
| QA Notice: Package has poor programming practices which may compile |
| fine but exhibit random runtime failures. |
| ...: warning: implicit declaration of function ... |
| ...: warning: incompatible implicit declaration of built-in function ... |
| </programlisting> |
| </para> |
| <para> |
| Your code is calling functions which lack prototypes. In C++, this would |
| have been a build failure, but C is lazy so you just get a warning. This |
| can be a problem as gcc has to guess at what sort of arguments a function |
| takes based upon how it was called and often times, this is not the same |
| as what the function actually takes. The function return type is also |
| unknown so it's just assumed to be an integer (which is often times wrong). |
| This can get to be a problem when the size of the types guessed do not |
| actually match the size of the types the function expects. Generally, this |
| corresponds directly to proper coding practices (and the lack thereof). |
| Also, by including proper prototypes, the compiler often helps by checking |
| types used, proper number of arguments passed, etc... |
| </para> |
| <para> |
| To fix this, just include the proper header files for the functions in |
| question. If the function is a package-specific one, then you may have to |
| create a header/function prototype for it. |
| </para> |
| </sect1> |
| |
| <sect1 id='qa-build-uninitialized'> |
| <title>Build Warning: Used Uninitialized</title> |
| <para> |
| <programlisting> |
| QA Notice: Package has poor programming practices which may compile |
| fine but exhibit random runtime failures. |
| ...: warning: is used uninitialized in this function |
| </programlisting> |
| </para> |
| <para> |
| This means code uses a variable without actually setting it first. In other |
| words, the code is basically using random garbage. |
| </para> |
| <para> |
| The fix here is simple: make sure variables are initialized properly before |
| using them. |
| </para> |
| </sect1> |
| |
| <sect1 id='qa-build-math-compare'> |
| <title>Build Warning: Invalid X<=Y<=Z Comparisons</title> |
| <para> |
| <programlisting> |
| QA Notice: Package has poor programming practices which may compile |
| fine but exhibit random runtime failures. |
| ...: warning: comparisons like X<=Y<=Z do not have their mathematical meaning |
| </programlisting> |
| </para> |
| <para> |
| This warning crops up either when the programmer expected the expression |
| to work or they just forgot to use sufficient parentheses. For example, |
| the following code snippets are wrong (we won't get into the technical |
| argument of this being valid C code; just change the code to not be |
| ambiguous). |
| <programlisting> |
| if (x <= y <= z) |
| ...; |
| if (a < b <= c) |
| ...; |
| </programlisting> |
| </para> |
| <para> |
| To fix this, read the code to figure out what exactly the programmer meant. |
| </para> |
| </sect1> |
| |
| <sect1 id='qa-build-non-null'> |
| <title>Build Warning: Non-Null Required</title> |
| <para> |
| <programlisting> |
| QA Notice: Package has poor programming practices which may compile |
| fine but exhibit random runtime failures. |
| ...: warning: null argument where non-null required |
| </programlisting> |
| </para> |
| <para> |
| Many functions take pointers as arguments and require that the pointer never |
| be NULL. To this end, you can declare function prototypes that instruct the |
| compiler to do simple checks to make sure people do not incorrectly call the |
| function with NULL values. This warning pops up when someone calls a |
| function and they use NULL when they should not. Depending on the library, |
| the function may actually crash (they told you not to use NULL after-all, so |
| it's your fault :P). |
| </para> |
| <para> |
| You will need to read the code and fix it so that it does not incorrectly |
| call the relevant functions with NULL values. |
| </para> |
| </sect1> |
| |
| <sect1 id='qa-build-pointer-trunc'> |
| <title>Build Warning: Truncating Pointers</title> |
| <para> |
| <programlisting> |
| QA Notice: Package has poor programming practices which may compile |
| but will almost certainly crash on 64bit architectures. |
| </programlisting> |
| </para> |
| <para> |
| A large portion of code in the open source world is developed on the 32bit |
| x86 architecture. Unfortunately, this has led to many pieces of code not |
| handling pointer types properly. When compiled and run on a 64bit |
| architecture, the code in question will probably crash horribly. Some |
| common examples are assuming that an integer type is large enough to hold |
| pointers. This is true on 32bit architectures (an integer can hold 32bits |
| and a pointer is 32bits big), but not true on 64bit architectures (an |
| integer still holds just 32bits, but a pointer is 64bits big). |
| </para> |
| <para> |
| Since this issue can manifest itself in many ways (as there are many ways to |
| improperly truncate a pointer), you will need to read the source code |
| starting with the displayed warning. Make sure types are declared, used, |
| and passed properly. Make sure that all function prototypes are found (see |
| the <link linkend="qa-build-implicit-decl">Implicit Declarations</link> |
| section for more information). So on and so forth. |
| </para> |
| </sect1> |
| </chapter> |
| </part> |