Follow @Openwall on Twitter for new release announcements and other news
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Date: Tue, 16 May 2023 11:39:16 +0200
From: Solar Designer <>
Cc: "Andrew G. Morgan" <>
Subject: Re: libcap-2.69 addresses 2 CVEs

On Mon, May 15, 2023 at 08:45:33AM -0700, Andrew G. Morgan wrote:
> The release of libcap-2.69, announced here:
> addresses the following:
> - LCAP-CR-23-01 (SEVERITY) LOW (CVE-2023-2602) - found by David Gstir
> - LCAP-CR-23-02 (SEVERITY) MEDIUM (CVE-2023-2603) - found by Richard Weinberger
> The full details of both issues are provided in this audit report:

Here's plain text export of the relevant part from the PDF file above:

    4.1.1        LCAP-CR-23-01: Memory Leak on pthread_create() Error

        Severity:                   LOW
        CWE:                      401 - Improper Release of Memory Before Removing Last Reference
                                  ('Memory Leak')
        Affected Component:        libcap/psx/psx.c:__wrap_pthread_create()       Description

    X41 found that the error handling in __wrap_pthread_create() function is wrong and will leak mem-
    ory in case of an error.

    Function libpsx hooks the pthread_create() function and replaces it with __wrap_pthread_create().
    This wrapping function will then register the required signal handler and call the actual pthread_create()
    (__real_pthread_create()). Here, the error handling for __real_pthread_create() is faulty as it checks
    for a negative return value which cannot happen. Instead, pthread_create() will return a value
    > 0 in case of an error1 . Thus, for every error in __real_pthread_create() where the tread routine
    (_psx_start_fn) is not called, the buffer starter will not be freed and thus this memory will be leaked
    once __wrap_pthread_create() returns.

    A malicious actor who is in the position to cause __real_pthread_create() to return an error, can
    potentially abuse this to exhaust the process memory. As libpsx hooks all pthread_create() calls
    of a process, this affects every thread.

1    *
2    * __wrap_pthread_create is the wrapped destination of all regular
3    * pthread_create calls.
4    */
5   int __wrap_pthread_create(pthread_t *thread, const pthread_attr_t *attr,
6                 void *(*start_routine) (void *), void *arg) {
7       psx_starter_t *starter = calloc(1, sizeof(psx_starter_t));

9           // [...]


    X41 D-Sec GmbH                                     PUBLIC                                           Page 14 of 28
    Source Code Audit on libcap                                    for Open Source Technology Improvement Fund (OSTIF)


11        int ret = __real_pthread_create(thread, attr, _psx_start_fn, starter);
12        if (ret == -1) {
13            psx_new_state(_PSX_CREATE, _PSX_IDLE);
14            memset(starter, 0, sizeof(*starter));
15            free(starter);
16        } /* else unlock happens in _psx_start_fn */

18        /* the parent can once again receive psx interrupt signals */
19        pthread_sigmask(SIG_SETMASK, &orig_sigbits, NULL);

21        return ret;
22   }

                     Listing 4.1: Code Snippet Showing the Affected Part of __wrap_pthread_create()     Solution Advice

     While not critical, X41 advises fixing the error handling code to prevent any abuse from being

     X41 D-Sec GmbH                                     PUBLIC                                            Page 15 of 28
     Source Code Audit on libcap                                      for Open Source Technology Improvement Fund (OSTIF)

     4.1.2       LCAP-CR-23-02: Integer Overflow in _libcap_strdup()

         Severity:                  MEDIUM
         CWE:                      190 - Integer Overflow or Wraparound
         Affected Component:        libcap/cap_alloc.c:_libcap_strdup()     Description

     X41 found that in 32 bits execution mode, where sizeof(size_t) equals 4, the _libcap_strdup() func-
     tion can suffer from an integer overflow of the input string is close to a length of 4GiB. In this
     case len = strlen(old) + 1 + 2*sizeof(__u32); will overflow and results into a value much smaller than

     As consequence the overflow check len & 0xffffffff) != len will have no effect and the strcpy() func-
     tion at the end of the function will overwrite the heap.

1    __attribute__((visibility ("hidden"))) char *_libcap_strdup(const char *old)
2    {
3        struct _cap_alloc_s *header;
4        char *raw_data;
5        size_t len;

7    [...]

9          len = strlen(old) + 1 + 2*sizeof(__u32);
10         if (len < sizeof(struct _cap_alloc_s)) {
11             len = sizeof(struct _cap_alloc_s);
12         }
13         if ((len & 0xffffffff) != len) {
14             _cap_debug("len is too long for libcap to manage");
15             errno = EINVAL;
16             return NULL;
17         }

19         raw_data = calloc(1, len);

21   [...]

23         strcpy(raw_data, old);
24         return raw_data;
25   }

                          Listing 4.2: Code Snippet Showing the Affected Part of _libcap_strdup()

     X41 D-Sec GmbH                                       PUBLIC                                            Page 16 of 28
     Source Code Audit on libcap                             for Open Source Technology Improvement Fund (OSTIF)     Solution Advice

While the overflow is impossible to exploit on a pure 32 bits system because no user space ap-
plication can use the whole 32 bits address space it might be possible on a 64 bits kernel in 32
bits compat mode. In this mode user space is allowed to use the full 32 bits address space. X41
advises checking whether strlen() returns a sufficient large number to overflow the addition.


Powered by blists - more mailing lists

Please check out the Open Source Software Security Wiki, which is counterpart to this mailing list.

Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.