Go to main content

man pages section 7: Standards, Environments, Macros, Character Sets, and Miscellany

Exit Print View

Updated: Wednesday, July 27, 2022
 
 

adi(7)

Name

adi, ADI - Application Data Integrity (ADI)

Overview

Application Data Integrity (ADI) is an extension to the SPARC instruction set which detects memory corruptions in optimized production code by adding version numbers to memory pointers and the memory they point to. The hardware does this by allowing software to mark software buffers with special versions. On execution the processor compares the version encoded in the pointer used by a load or store instruction with the version assigned to the target location and generates an exception if there is a mismatch. The ADI feature can be used by user applications that manage memory and by the operating system.

Support for ADI is available on these hardware platforms:

  • Oracle SPARC M7 series
  • Oracle SPARC S7 series
  • Oracle SPARC T7 series
  • Oracle SPARC M8 series
  • Oracle SPARC T8 series

Description

The ADI feature works in the following way:

  1. By using spare bits in the cache and in the memory hierarchy, the hardware allows the software to assign version numbers to regions of memory at the granularity of a cache line. The software sets the high bits of the virtual address pointer used to reference a data object with the same version assigned to the target memory in which the data object resides.

  2. On execution, the processor compares the version encoded in the pointer and referenced by a load or store instruction, with the version assigned to the target memory.

  3. If there is a mismatch, the processor generates a version mismatch exception and delivers the exception to Oracle Solaris either as a precise or as a disrupting trap as follows:

    • For a load instruction, the hardware delivers the exception as a precise trap.

    • For a store instruction, the hardware delivers the exception as a precise trap or as a disrupting trap depending on the current state of the ADI precise exception mode of the thread executing the store instruction. Disrupting traps are the default for performance reasons.

  4. Oracle Solaris signals the exception to a process by delivering a SIGSEGV signal.

    • For exceptions that generate precise traps, the signal information includes the exact PC (program counter), mismatching VA (virtual address), and current version assigned to the memory.

    • For exceptions that generate disrupting traps, the signal information only includes the PC (program counter) of the store instruction.

The hardware can perform ADI checking on data accesses to a given page of memory if both the following conditions are met:

  • ADI is enabled for the thread executing a virtual-addressed load or store to the memory.

  • ADI is enabled for the virtual address range mapped to the page.

The following conditions need to be met to enable the hardware to get (read) or set (write) the version associated with a cache line:

  • The thread executing the get or set is ADI-enabled.

  • The target memory is ADI-enabled.

  • The target memory is mapped with protections conducive to a successful get or set.

By default, all threads of a 64-bit application run with ADI enabled, but ADI is not enabled on the memory assigned to the application. 32-bit applications cannot use ADI. An application can enable ADI on memory segments that support ADI using the memcntl(2) or mmap(2) function. It is up to applications and libraries to decide which application memory to enable for ADI and the versions to assign to the memory.

When memory segments that have ADI enabled are written to backing store, additional metadata needs to be stored with them for the ADI version data. Controls over how much memory can be used for this purpose are available via the max-adi-metadata-memory resource controls described in resource-controls(7) and the max-adi-metadata-memory property described in zonecfg(8).

ADI is a powerful technology, but can be incompatible with applications that do low level address computations. In particular, since pointers are tagged, an application relying on pointer math needs to first normalize the pointer, as shown in the Normalizing a Versioned Address example in adi(2). In addition, accesses beyond buffer limits are also detected as fatal. Some applications are known to use these accesses as designed optimizations and can fail under ADI. If an application has run successfully under a memory checker (for example, valgrind), there is a fair chance that it won't show these problems.

Using ADI

Use of ADI for specific types of memory can be controlled via these security extensions:

ADIHEAP

ADI based protections for heap allocators

ADISTACK

ADI based protections for stacks

KADI

ADI based protections for kernel heap

See the sxadm(8) man page for details on using security extensions in Oracle Solaris.

The default malloc(3C) functions, the libumem(3LIB) functions, and the libadimalloc(3LIB) functions can use ADI to provide detection of buffer overruns, out of bounds pointers, stale pointers, and use-after-free errors. Use of ADI is enabled by default in libadimalloc, while the others only use ADI if the ADIHEAP security extension is enabled. Other malloc implementations provided in Oracle Solaris, such as libmtmalloc(3LIB) currently do not use ADI.

Developing with ADI

For more information on developing applications that use ADI, see the adi(2) and adi(3C) man pages.

The following system interfaces have been modified to support ADI:

copyin()

Returns an error value when there is a version mismatch. For more information, see the copyin(9F) man page.

copyout()

Returns an error value when there is a version mismatch. For more information, see the copyout(9F) man page.

ddi_copyin()

Returns an error value when there is a version mismatch. For more information, see the ddi_copyin(9F) man page.

ddi_copyout()

Returns an error value when there is a version mismatch. For more information, see the ddi_copyout(9F) man page.

getmsg()

Returns an error value if a version mismatch is detected while the system is writing data to the buffer. For more information, see the getmsg(2) man page.

memcntl()

Allows ADI to be enabled or disabled for specified memory pages. For more information, see the memcntl(2) man page.

meminfo()

Provides the status of ADI for a specified virtual address. For more information, see the meminfo(2) man page.

mmap()

Enables ADI for mapped pages. For more information, see the mmap(2) man page.

pmap()

Reports which process mappings have ADI enabled. For more information, see the pmap(1) man page.

proc()

Provides information about the state of a ADI process. For more information, see the proc(5) man page.

putmsg()

Returns an error value if there is a version mismatch while the system is reading data from the buffer. For more information, see the putmsg(2) man page.

read()

Returns an error value if there is a version mismatch while the system is writing data to the buffer. For more information, see the read(2) man page.

siginfo()

Defines signal values for signals raised for ADI exceptions. For more information, see the siginfo(3HEAD) man page.

uiomove()

Returns an error value if a version mismatch is detected while the system is transferring data to or from the buffer. For more information, see the uiomove(9F) man page.

write()

Returns an error value if a version mismatch is detected while the system is reading data from the buffer. For more information, see the write(2) man page.

Attributes

See attributes(7) for descriptions of the following attributes:

ATTRIBUTE TYPE
ATTRIBUTE VALUE
Architecture
SPARC

See Also

adi(2), memcntl(2), meminfo(2), adi(3C), malloc(3C), dax_adi(3DAX), attributes(7), sxadm(8)