# Quality Assurance

## QA Notices

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 file a bug. We'll only cover the non-obvious notices here.

In pretty much all cases, you should try and get these issues resolved upstream rather than simply fixing them in our ebuilds.

### Scanelf: Insecure RUNPATHs

        QA Notice: The following files contain insecure RUNPATHs

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.

Here are some of the common problems and their solutions.

- Libtool - old versions of libtool would use too many -rpath flags

  Solution: Regenerate the autotool code

- Perl - some versions of perl would use incorrect -rpath flags

  Solution: Upgrade system perl build modules

- Crappy build system - the custom build system uses -rpath incorrectly

  Solution: Review the LDFLAGS in the build system and make them not suck

- Crappy ebuild - the ebuild installs ELFs instead of using the package's build system

  Solution: Fix the crappy ebuild to use the package's build system

### Scanelf: Runtime Text Relocations (TEXTRELS)

        QA Notice: The following files contain runtime text relocations

Please see the Gentoo Hardened PIC Fix Guide.

### Scanelf: Executable Stack (EXECSTACK)

        QA Notice: The following files contain executable stacks

Please see the Gentoo Hardened GNU Stack Guide.

### Scanelf: Missing Shared Object Name (SONAME)

        QA Notice: The following shared libraries lack a SONAME

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.

To fix this issue, make sure the shared library is linked with the proper `-Wl,-soname,...` flag. You will need to replace the `...` part with the actual ABI name. For example, if the library is named `libfoo.so.1.2.3`, you will probably want to specify `-Wl,-soname,libfoo.so.1`.

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 `/usr/lib/app/plugin.so` rather than `/usr/lib/plugin.so`.

### Scanelf: Missing Needed Entries

        QA Notice: The following shared libraries lack NEEDED entries

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.

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 (`ld`) directly instead of the system compiler driver (`gcc`).

### Unresolved soname dependencies

        QA Notice: Unresolved soname dependencies

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 `ldd` 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.

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:

       E_MACHINE;path;DT_SONAME;DT_RUNPATH;DT_NEEDED;multilib category

#### External dependencies

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.

#### Removal of unnecessary files

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.

#### Addition of DT_RUNPATH entries

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.

For pre-built binaries, it may be necessary to fix up DT_RUNPATH using `patchelf --set-rpath`. For example, use `patchelf --set-rpath '$ORIGIN'` if a given binary should link to libraries found in the same directory as the binary itself, or use `patchelf --set-rpath '$ORIGIN/libs'` if a given binary should link to libraries found in a subdirectory named libs found in the same directory as the binary itself.

For binaries built from source, a flag like `-Wl,-rpath,/path/of/directory/containing/libs` will create binaries with the desired DT_RUNPATH entry.

#### Addition of DT_SONAME settings

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 `-Wl,-soname=foo.so.1` will create a DT_SONAME setting. For pre-built dynamic libraries, it may be necessary to fix up DT_SONAME using `patchelf --set-soname`.

#### Adjustment to Portage soname resolution logic

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 bug 646190.

### Absolute Symlink In Library Directory

        QA Notice: Found an absolute symlink in a library directory

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.

If you have a library installed into `/lib/` and you want to have it accessible in `/usr/lib/`, then you should generate a linker script so that the system toolchain can handle it properly. Please see the linker script section for more information.

### Missing Linker Script

        QA Notice: Missing gen_usr_ldscript

If you have a shared library in `/lib/` and a static library in `/usr/lib/`, but no linker script in `/usr/lib/`, 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 `gen_usr_ldscript` function found in the toolchain-funcs.eclass. Refer to the man page for information on how to use it. See this bug report for some history on this issue.

### Excessive Files in /

        QA Notice: Excessive files found in the / partition

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 `/lib/` directory. Fix your ebuild so it does not install there.

### Portage Tempdir In Libtool Scripts

        QA Notice: ... appears to contain PORTAGE_TMPDIR paths

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.

You may be able to cheat and use the `elibtoolize` function in the libtool.eclass. However, if that does not help, you will probably need to regenerate all of the autotool files.

### Build Warning: Strict Aliasing

        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

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: NetBSD Explanation, Gentoo Dev Thread, GCC Docs, Practical examples.

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.

### Build Warning: Implicit Declarations

        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 ...

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...

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.

### Build Warning: Used Uninitialized

        QA Notice: Package has poor programming practices which may compile
                   fine but exhibit random runtime failures.
        ...: warning: is used uninitialized in this function

This means code uses a variable without actually setting it first. In other words, the code is basically using random garbage.

The fix here is simple: make sure variables are initialized properly before using them.

### Build Warning: Invalid X<=Y<=Z Comparisons

        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

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).

        if (x <= y <= z)
          ...;
        if (a < b <= c)
          ...;

To fix this, read the code to figure out what exactly the programmer meant.

### Build Warning: Non-Null Required

        QA Notice: Package has poor programming practices which may compile
                   fine but exhibit random runtime failures.
        ...: warning: null argument where non-null required

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).

You will need to read the code and fix it so that it does not incorrectly call the relevant functions with NULL values.

### Build Warning: Truncating Pointers

        QA Notice: Package has poor programming practices which may compile
                   but will almost certainly crash on 64bit architectures.

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).

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 Implicit Declarations section for more information). So on and so forth.