Secure-memory initialization leaves Linux capabilities active
Closed, WontfixPublic

Assigned To
Authored By
werner
Tue, Aug 4, 4:48 PM
Subscribers

Description

Secure-memory initialization leaves Linux capabilities active

In USE_CAPABILITIES builds, the only capability-clearing code is in the zero-size secure-memory branch. The documented, normal GCRYCTL_INIT_SECMEM call uses a nonzero pool size, locks the pool, and returns without dropping capabilities. A file- or ambient-capability process whose real and effective UIDs are equal therefore retains all effective and permitted kernel authority.

Vulnerable code

src/secmem.c, _gcry_secmem_init_internal:

c
  if (!n)
    {
#ifdef USE_CAPABILITIES
      /* drop all capabilities */
      if (!no_priv_drop)
        {
          cap_t cap;

          cap = cap_from_text ("all-eip");
          cap_set_proc (cap);
          cap_free (cap);
        }

The ordinary path never reaches that block:

c
  else
    {
      if (n < MINIMUM_POOL_SIZE)
	n = MINIMUM_POOL_SIZE;
      if (! pool->okay)
	{
	  init_pool (pool, n);
	  lock_pool_pages (pool->mem, n);
	}

Why it matters

lock_pool_pages only performs a UID drop for the classic uid != 0 && geteuid() == 0 case. It does nothing to capability sets when real and effective UIDs match. Code running after initialization thus keeps not only CAP_IPC_LOCK, but any unrelated capabilities granted to the process, increasing the impact of a later memory-safety or command-execution flaw. The issue requires the optional --with-capabilities build and a capability-bearing application; it does not grant privileges to an otherwise unprivileged process.

Proposed fix

After the pool is locked on the nonzero path, clear effective, permitted, and inheritable capability sets unless GCRYCTL_DISABLE_PRIV_DROP was explicitly used. Check cap_from_text, cap_set_proc, and post-drop state, and fail initialization if dropping fails. Add a Linux namespace integration test that starts with a harmless capability, performs nonzero secure-memory initialization, and verifies empty CapEff, CapPrm, and CapInh sets afterward.

Related Objects

StatusAssignedTask
Wontfix werner

Event Timeline

werner created this task.
werner created this object with visibility "Public (No Login Required)".
werner created this object with edit policy "Contributor (Project)".
werner renamed this task from secure memory initialization leaves linux capabilities active to Secure-memory initialization leaves Linux capabilities active.Tue, Aug 4, 5:14 PM

My internal comment was: The proposed fix would be a semantic change. In reality we don't do any privilege dropping because running gpg or other programs as suid is out of fashion and need for 20 years.

werner lowered the priority of this task from High to Normal.Thu, Aug 6, 9:20 AM
werner added a project: Bug Report.
werner claimed this task.
werner shifted this object from the Restricted Space space to the S1 Public space.