Arch package guidelines/Security - ArchWiki

Jump to content

# Arch package guidelines/Security

From ArchWiki
< Arch package guidelines

This page describes security packaging guidelines for Arch Linux packages. For C/C++ projects the compiler and linker can apply security hardening options. Arch Linux applies PIE, Fortify source, stack protector, nx and relro by default.

## Usage

Hardening protections can be reviewed by running checksec.

    $ checksec --file=/usr/bin/cat

## RELRO

RELRO is a generic mitigation technique to harden the data sections of an ELF binary/process. When a program is loaded several ELF memory sections need to be written to by the linker but can be turned read-only before turning control over to the program. This prevents attackers of overriding some ELF sections. There are two different RELRO modes:

- Partial RELRO (`-Wl,-z,relro`) some sections are marked as read-only after program load except the GOT (`.got.plt`) is still writeable.
- Full RELRO (`-Wl,-z,now`) during program load all dynamic symbols are resolved, allowing for the complete GOT to be marked read-only.

If an application reports partial relro, investigate if the build toolchain passes our LDFLAGS or allows overriding LDFLAGS. For Go packages investigate if the build method uses `build.go` as pure golang Makefile replacement which does not allow passing of LDFLAGS.

### Haskell

For Haskell it is not clear how to achieve Full RELRO at the moment.

## Stack canary

A stack canary is added by the compiler between the buffer and control data on the stack. If this well known value is corrupted, a buffer overflow occurred and the running program segfaults to prevent possible arbitrary code execution.

The gcc package has it enabled stack protection by default with the --enable-default-ssp compile option.

## NX

### C/C++

Executable-space protection marks memory regions as non-executable, such that an attempt to execute machine code in these regions will cause an exception. It makes use of hardware features such as the NX bit (no-execute bit), or in some cases software emulation of those features.

## PIE

### C/C++

The gcc package has it enabled by default for C/C++ with --enable-default-pie.

### Golang

Pass the following flags to `go build`:

    export GOFLAGS='-buildmode=pie'
    export CGO_CPPFLAGS="-D_FORTIFY_SOURCE=2"
    export CGO_LDFLAGS="-Wl,-z,relro,-z,now"

### Haskell

Pass the following flag to `runhaskell Setup.hs configure`:

    --ghc-option='-pie'

## RPATH/RUNPATH

RUNPATH/RPATH provides further search paths for the object it is listed in (it can be used both for executable and for shared objects).

    $ objdump -x /usr/bin/perl | egrep 'RPATH|RUNPATH'

If the RPATH value contains a path within an attackers control it can possibly execute code by installing a malicious library in that directory for example CVE-2006-1566 CVE-2005-4280. See Debian:RpathIssue.

The RPATH entry is set by the linker by passing for example the following string to LDFLAGS `-Wl,-rpath -Wl,/usr/local/lib`. To make an RUNPATH entry append `--enable-new-dtags` to the linker flags.

## FORTIFY

Fortify source is a macro that adds buffer overflow protection in various functions that perform operations on memory and strings. It checks whether an attacker tries to copy more bytes to overflow a buffer and then stops the execution of the program. This protection is enabled with the default `CPPFLAGS`:

    makepkg.conf

    CPPFLAGS="-D_FORTIFY_SOURCE=2"

See makepkg#Configuration.

## systemd services

This article or section is a candidate for moving to systemd/Sandboxing.

Notes: Covers the same topic as systemd#Sandboxing application environments. Both could be merged and moved to a dedicated page. See User:NetSysFire/systemd sandboxing for a proposed draft. (Discuss in Talk:Security#systemd unit hardening and system.conf tweaks)

If a systemd service file is shipped with the package due to upstream not providing any, look into applying the following systemd service hardening features. Systemd provides a way to analyse security features which are enabled for a service.

    $ systemd-analyze security reflector.service

### File access

A service can be hardened by restricting file system access.

Set up a new file system namespace for the executed process and mounts private `/tmp` and `var/tmp` directories inside it that is not shared by processes outside the namespace. Useful for programs which write data to `/tmp`.

    PrivateTmp=true

ProtectSystem has three different varieties of mounting directories as read-only for the executed process. The "full" option mounts `/usr`, `/boot` and `/etc` read only. ProtectHome makes `/home`, `/root` and `/run/user` inaccessible to the executed process.

    ProtectSystem=strict
    ProtectHome=true

Sets up a new `/dev` namespace for the executed process and only adds API pseudo devices such as `/dev/null`, `/dev/zero` or `/dev/random`, but not for physical devices or system memory, system ports and others. This is useful to secure the execute process from writing directly to physical devices, systemd also adds a system call filter for calls within the `@raw-io` set.

    PrivateDevices=true

These options make the executed process unable to change kernel variables accessible through `/proc/sys`, `/sys`, etc. ProtectControlGroups makes the `/sys/fs/cgroup` hierarchy read-only.

    ProtectKernelTunables=true
    ProtectControlGroups=true

Making file paths inaccessible can be done as following:

    InaccessiblePaths=/etc

More detailed information can be found in systemd.exec(5).

### User

Ensure that the executed process and its children can never gain new privileges through execve(2).

    NoNewPrivileges=true

### Memory

Prohibit attempts to create memory mappings that are both writable and executable, to change mappings to be executable or to create executable shared memory. This sandboxes a process against allowing an attacker to write in to memory which is also executed. Note that enabling this is not compatible with all applications which rely on a JIT.

    MemoryDenyWriteExecute=true

### System calls

Locks down the personality(2) system call so that the kernel execution domain can not be changed.

    LockPersonality=true

System calls can be restricted in a service as well, systemd can display syscalls to filter on:

    $ systemd-analyze syscall-filter

Predefined groups are available, e.g. to use the recommended starting point for whitelisting system calls for system services use:

    SystemCallFilter=@system-service

### Network

If the running process does not require any network access it can be fully disabled by setting up a new network namespace for the process and only configuration a loopback interface.

    PrivateNetwork=true

If network is required, the type of address families used can be restricted for the socket(2) system call by for example only allowing UNIX sockets.

    RestrictAddressFamilies=AF_UNIX

For when only network to localhost or specific IP ranges is required a process can be restricted by only allowing network access to localhost.

    IPAddressAllow=localhost
    IPAddressDeny=any

More information about network filtering can be found in systemd.resource-control(5).

### Various

Sets up a new UTS namespace for the execute process and disallows changing the hostname or domainname.

    ProtectHostname=true

Categories:

- Arch package guidelines
- Security

Hidden category:

- Pages or sections flagged with Template:Move