dynamic-stack-buffer-overflow in apt-pkg/contrib/cmdnline.cc

Ilia Kashintsev <[email protected]>
Newsgroups gmane.linux.debian.apt.devel
Message-ID <[email protected]>
Hello mainteiners!

When apt is built with clang-19 and ASAN sanitizer error
dynamic-stack-buffer-overflow arises in apt-pkg/contrib/cmdnline.cc in
CommandLine::SaveInConfig() because length becomes equal to
100 + argc * 50 on the last iteration of the for loop at line 402.

Sanitizer report:

==6090==ERROR: AddressSanitizer: dynamic-stack-buffer-overflow on 
address 0x7ffc1e99003a at pc 0x73a05287672c bp 0x7ffc1e98ff10 sp 
0x7ffc1e98ff08
WRITE of size 1 at 0x7ffc1e99003a thread T0
     #0 0x73a05287672b in CommandLine::SaveInConfig(unsigned int const&, 
char const* const*) /apt_ASAN/apt-pkg/contrib/cmndline.cc:428:23
     #1 0x73a052871043 in CommandLine::Parse(int, char const**) 
/apt_ASAN/apt-pkg/contrib/cmndline.cc:192:4
     #2 0x73a052ee359d in ParseCommandLine(CommandLine&, APT_CMD, 
Configuration* const*, pkgSystem**, int, char const**, bool 
(*)(CommandLine&), std::vector<aptDispatchWithHelp, 
std::allocator<aptDispatchWithHelp>> (*)()) 
/apt_ASAN/apt-private/private-cmndline.cc:557:13
     #3 0x5d93f23de7c8 in main /apt_ASAN/cmdline/apt.cc:106:22
     #4 0x73a051f69249 in __libc_start_call_main 
csu/../sysdeps/nptl/libc_start_call_main.h:58:16
     #5 0x73a051f69304 in __libc_start_main csu/../csu/libc-start.c:360:3
     #6 0x5d93f22f91a0 in _start (/apt_ASAN/cmdline/apt+0x6d1a0) 
(BuildId: 4b9c96fa8ff70664cdda54c4eb53fc3413f5c349)

Address 0x7ffc1e99003a is located in stack of thread T0
SUMMARY: AddressSanitizer: dynamic-stack-buffer-overflow 
/apt_ASAN/apt-pkg/contrib/cmndline.cc:428:23 in 
CommandLine::SaveInConfig(unsigned int const&, char const* const*)
Shadow bytes around the buggy address:
   0x7ffc1e98fd80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
   0x7ffc1e98fe00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
   0x7ffc1e98fe80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
   0x7ffc1e98ff00: 00 00 00 00 ca ca ca ca 00 00 00 00 00 00 00 00
   0x7ffc1e98ff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x7ffc1e990000: 00 00 00 00 00 00 00[02]cb cb cb cb 00 00 00 00
   0x7ffc1e990080: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
   0x7ffc1e990100: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
   0x7ffc1e990180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
   0x7ffc1e990200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
   0x7ffc1e990280: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):
   Addressable:           00
   Partially addressable: 01 02 03 04 05 06 07
   Heap left redzone:       fa
   Freed heap region:       fd
   Stack left redzone:      f1
   Stack mid redzone:       f2
   Stack right redzone:     f3
   Stack after return:      f5
   Stack use after scope:   f8
   Global redzone:          f9
   Global init order:       f6
   Poisoned by user:        f7
   Container overflow:      fc
   Array cookie:            ac
   Intra object redzone:    bb
   ASan internal:           fe
   Left alloca redzone:     ca
   Right alloca redzone:    cb
==6090==ABORTING

Reproducing:

To reproduce build the project with ASAN and in cmdline/  do

./apt 0o 
"000000000000==================================================================================================================== 
"

Quotation marks are present to preserve a space in argv[2].

Suggested fixes:

I don't know how exactly to fix it, but there are a couple suggestions:
Option 1) Add an extra length check.
Diff:
--- a/apt-pkg/contrib/cmndline.cc
+++ b/apt-pkg/contrib/cmndline.cc
@@ -417,6 +417,8 @@ void CommandLine::SaveInConfig(unsigned int const 
&argc, char const * const * co
             closeQuote = true;
          }
        }
+      if (length >= sizeof(cmdline) -2)
+         continue;
        if (closeQuote == true)
        {
          cmdline[length++] = '\'';

Option 2) Allocate more memory for the cmdline variable based on
           argv length (could be excessive in the suggestion below).
Diff:

--- a/apt-pkg/contrib/cmndline.cc
+++ b/apt-pkg/contrib/cmndline.cc
@@ -394,7 +394,11 @@ bool CommandLine::DispatchArg(Dispatch const * 
const Map,bool NoMatch)
     than nothing after all. */
  void CommandLine::SaveInConfig(unsigned int const &argc, char const * 
const * const argv)
  {
-   char cmdline[100 + argc * 50];
+   unsigned int argvLength = 0;
+   for (int i = 0; i < argc; i++)
+   {
+     argvLength += strlen(argv[i]) + 1;
+   }
+   char cmdline[100 + argvLength * 3];
     memset(cmdline, 0, sizeof(cmdline));
     unsigned int length = 0;
     bool lastWasOption = false;
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.