Addressing failed setrlimit calls in sudo

Written in the mid-afternoon in English • Tags: ,

After installing sudo 1.8.29 from pkgsrc (security/sudo) I started frequently seeing this warning message:

sudo: setrlimit(3): Invalid argument

It took a few rounds, but eventually I applied an acceptable patch for the pkgsrc-2019Q4 release. Later an upstream workaround was committed and included in the sudo 1.8.30 release.

Looking at <sys/resource.h> I saw that 3 is RLIMIT_STACK. I wrote some code to display the resource name instead of the corresponding number, just to make the message more user-friendly.

Then I tried using src/limits.c from the tip of the sudo 1.8 branch as I saw that RLIMIT_STACK was no longer set to RLIM_INFINITY in it. However, it only resulted in these errors appearing less often rather than eliminating them.

I then added output of rlim_cur and rlim_max to see if we were trying to increase the soft limit beyond the hard limit — I did not see that ever being the case.

The other reason for setrlimit(2) returning EINVAL is that the call is trying to lower the limit below the current usage for the resource. I thought1 that it is not reasonable to simply try to reduce a soft limit to its previous value after having increased it. Instead, one would also need to (somehow) ascertain that resource usage is also shrunk back down below the old limit first.

I also wondered — and likely hit the target with it — that the cause could be some security or protection method such as allocating the stack “all over the place” (as my brain failed to recall what ASLR was called). PR/51158 about ntpd would appear to be about the same issue, and in the ticket it is hypothesized that resource accounting when it comes to stack allocation might no longer be correct or accurate.

Until PR/51158 is resolved, I think it might be better not to touch RLIMIT_STACK, but I would also rather not deviate from the upstream codebase. Therefore I updated sudo to the 1.8.30b3 beta version as it included a different workaround from Todd C. Miller, the author of sudo. He had also merged in all the portability patches from the security/sudo package, which I found wonderful.

The 1.8.30beta3 release also addressed a couple of other interesting issues:

  • Add runas_check_shell flag to require a runas user to have a valid shell. Not enabled by default.

  • Add a new flag allow_unknown_runas_id to control matching of unknown IDs. Previous, sudo would always allow unknown user or group IDs if the sudoers entry permitted it. This included the ALL alias. With this change, the admin must explicitly enable support for unknown IDs.

  • Transparently handle the “sudo sudoedit” problem. Some admin are confused about how to give users sudoedit permission and many users try to run sudoedit via sudo instead of directly. If the user runs “sudo sudoedit” sudo will now treat it as plain “sudoedit” after issuing a warning. If the admin has specified a fully-qualified path for sudoedit in sudoers, sudo will treat it as just “sudoedit” and match accordingly. In visudo (but not sudo), a fully-qualified path for sudoedit is now treated as an error.

  • When restoring old resource limits, try to recover if we receive EINVAL. On NetBSD, setrlimit(2) can return EINVAL if the new soft limit is lower than the current resource usage. This can be a problem when restoring the old stack limit if sudo has raised it.

  • Restore resource limits before executing the askpass program. Linux with docker seems to have issues executing a program when the stack size is unlimited. Bug #908

  • macOS does not allow rlim_cur to be set to RLIM_INFINITY for RLIMIT_NOFILE. We need to use OPEN_MAX instead as per the macOS setrlimit manual. Bug #904

  • Use 64-bit resource limits on AIX.

The first two address CVE-2019-19234 and CVE-2019-19232 respectively.

The sudo 1.8.30 release is functionally equivalent to 1.8.30beta3 and I updated pkgsrc to use it about 4 hours after its release, so nobody needs to worry about using a beta release.