Skip to content

la_version() returns hardcoded 1, incompatible with glibc ≥ 2.35 audit interface version 2 #143

@SamHerts

Description

@SamHerts

Spindle's audit libraries (libspindle_audit_pipe.so and libspindle_subaudit_pipe.so) return a hardcoded value of 1 from la_version(). Glibc 2.35 (released February 2022) bumped LAV_CURRENT to 2. On platforms where glibc enforces a minimum accepted version of 2, Spindle's audit libraries are silently rejected at
load time with the following error:

ERROR: audit interface 'libspindle_audit_pipe.so' requires version 1
       (maximum supported version 2); ignored.

When the audit library is ignored, all symbol interception fails and any spawned process that depends on LD_AUDIT pointing to a Spindle library hangs indefinitely waiting for server communication that never
arrives, causing test timeouts.

Affected platforms

This is currently observed on Ubuntu 24.04 arm64 (aarch64). Ubuntu 24.04 x86_64 is not affected at this time, believed to be due to a difference in patch level between the amd64 and arm64 libc6 packages within
Ubuntu 24.04 Noble.

Root cause

spindle_la_version() is implemented in two places, both returning 1 unconditionally and discarding the version argument that glibc passes:

unsigned int spindle_la_version(unsigned int version)
{
(void)version;
patchDTV_init();
return 1;
}

unsigned int spindle_la_version(unsigned int version)
{
(void)version;
int result;
int binding_offset = 0;
result = get_ldso_metadata_bindingoffset(&binding_offset);
if (result == -1) {
err_printf("Unable to lookup binding offset\n");
return -1;
}
debug_printf3("Updating subaudit bindings with offset %d\n", binding_offset);
init_plt_binding_func(binding_offset);
return 1;
}

Additionally, the return -1 error path in subaudit.c is typed as unsigned int, so it silently returns 0xFFFFFFFF rather than -1, which would also be rejected by glibc (lav > LAV_CURRENT). Replacing with 0 would automatically disable the audit interface:

if (lav == 0)
    ...
    unload_audit_module (dlmargs.map, original_tls_idx);
    return;
}

GLibC 2.35 Source Reference

Fix

In both spindle_la_version implementations, replace return 1 with return version, and remove the (void)version suppression. The error path in subaudit.c should return 0 (which glibc treats as an explicit
rejection) rather than -1.

auditclient.c:

unsigned int spindle_la_version(unsigned int version) 
 { 
    patchDTV_init(); 
    return version; 
 } 

subaudit.c:

unsigned int spindle_la_version(unsigned int version) 
 { 
    int result; 
    int binding_offset = 0; 
  
    result = get_ldso_metadata_bindingoffset(&binding_offset); 
    if (result == -1) { 
       err_printf("Unable to lookup binding offset\n"); 
       return 0; 
    } 
    debug_printf3("Updating subaudit bindings with offset %d\n", binding_offset); 
    init_plt_binding_func(binding_offset); 
  
    return version; 
 } 

Reference

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions