)]}'
{
  "commit": "71ad7fe1bcec2a115bd0ab187240348358aa7f21",
  "tree": "c799bad35e242bcede4dfb23476d85eab048c89b",
  "parents": [
    "32696a4cbe90929ae79ea442f5102c513ce3dfaa"
  ],
  "author": {
    "name": "Jeff King",
    "email": "peff@peff.net",
    "time": "Wed Sep 28 18:52:48 2022 -0400"
  },
  "committer": {
    "name": "Taylor Blau",
    "email": "me@ttaylorr.com",
    "time": "Sat Oct 01 00:23:38 2022 -0400"
  },
  "message": "shell: limit size of interactive commands\n\nWhen git-shell is run in interactive mode (which must be enabled by\ncreating $HOME/git-shell-commands), it reads commands from stdin, one\nper line, and executes them.\n\nWe read the commands with git_read_line_interactively(), which uses a\nstrbuf under the hood. That means we\u0027ll accept an input of arbitrary\nsize (limited only by how much heap we can allocate). That creates two\nproblems:\n\n  - the rest of the code is not prepared to handle large inputs. The\n    most serious issue here is that split_cmdline() uses \"int\" for most\n    of its types, which can lead to integer overflow and out-of-bounds\n    array reads and writes. But even with that fixed, we assume that we\n    can feed the command name to snprintf() (via xstrfmt()), which is\n    stuck for historical reasons using \"int\", and causes it to fail (and\n    even trigger a BUG() call).\n\n  - since the point of git-shell is to take input from untrusted or\n    semi-trusted clients, it\u0027s a mild denial-of-service. We\u0027ll allocate\n    as many bytes as the client sends us (actually twice as many, since\n    we immediately duplicate the buffer).\n\nWe can fix both by just limiting the amount of per-command input we\u0027re\nwilling to receive.\n\nWe should also fix split_cmdline(), of course, which is an accident\nwaiting to happen, but that can come on top. Most calls to\nsplit_cmdline(), including the other one in git-shell, are OK because\nthey are reading from an OS-provided argv, which is limited in practice.\nThis patch should eliminate the immediate vulnerabilities.\n\nI picked 4MB as an arbitrary limit. It\u0027s big enough that nobody should\never run into it in practice (since the point is to run the commands via\nexec, we\u0027re subject to OS limits which are typically much lower). But\nit\u0027s small enough that allocating it isn\u0027t that big a deal.\n\nThe code is mostly just swapping out fgets() for the strbuf call, but we\nhave to add a few niceties like flushing and trimming line endings. We\ncould simplify things further by putting the buffer on the stack, but\n4MB is probably a bit much there. Note that we\u0027ll _always_ allocate 4MB,\nwhich for normal, non-malicious requests is more than we would before\nthis patch. But on the other hand, other git programs are happy to use\n96MB for a delta cache. And since we\u0027d never touch most of those pages,\non a lazy-allocating OS like Linux they won\u0027t even get allocated to\nactual RAM.\n\nThe ideal would be a version of strbuf_getline() that accepted a maximum\nvalue. But for a minimal vulnerability fix, let\u0027s keep things localized\nand simple. We can always refactor further on top.\n\nThe included test fails in an obvious way with ASan or UBSan (which\nnotice the integer overflow and out-of-bounds reads). Without them, it\nfails in a less obvious way: we may segfault, or we may try to xstrfmt()\na long string, leading to a BUG(). Either way, it fails reliably before\nthis patch, and passes with it. Note that we don\u0027t need an EXPENSIVE\nprereq on it. It does take 10-15s to fail before this patch, but with\nthe new limit, we fail almost immediately (and the perl process\ngenerating 2GB of data exits via SIGPIPE).\n\nSigned-off-by: Jeff King \u003cpeff@peff.net\u003e\nSigned-off-by: Taylor Blau \u003cme@ttaylorr.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "cef7ffdc9e1d3040930841134577c591cf02f650",
      "old_mode": 33188,
      "old_path": "shell.c",
      "new_id": "02cfd9627fa2180c0ab2f9b7009c50b6a4a87ded",
      "new_mode": 33188,
      "new_path": "shell.c"
    },
    {
      "type": "modify",
      "old_id": "2af476c3afcf0a1ca863f96ba832969152d3ad40",
      "old_mode": 33261,
      "old_path": "t/t9850-shell.sh",
      "new_id": "cfc71c3bd4318758570f0aa7206d63fa71fedb4e",
      "new_mode": 33261,
      "new_path": "t/t9850-shell.sh"
    }
  ]
}
