Bugzilla – Bug 831
[FreeBSD]: Cryptographic digest doesn't work with shell script
Last modified: 2018-04-24 09:54:09 MDT
A FreeBSD user reported he is seeing a problem when he tries to use crypto digest in command specification on FreeBSD. After some tests I noted it was working as expected with binaries but failing as he described with shell scripts. Here is FreeBSD bug for more details: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=223587 In order to reproduce it on a FreeBSD system it's just needed a configuration like this: $USER ALL = (ALL) NOPASSWD: sha256:$HASH /usr/local/bin/foo $USER is testing username %HASH is sha256 hash of /usr/local/bin/foo /usr/local/bin/foo is a shell script After login as $USER and run 'sudo /usr/local/bin/foo' it fails with following error: /bin/sh: cannot open /dev/fd/4: No such file or directory
This is a bug in FreeBSD, not sudo. Unlike Linux and Solaris, FreeBSD seems unable to execute a script using the fexecve() system call. You can work around this limitation by adding the following in your sudoers file: Defaults fdexec=never At compile time, if you set ac_cv_func_fexecve=no in the environment, fexecve() support will not be built-in to sudo. That may be best from a ports perspective.
Created attachment 508 [details] fexecve() test program The following program can be used to reproduce the problem on FreeBSD. Works: ./fdexec /bin/ls Fails: ./fdexec /some/script.sh
(In reply to Todd C. Miller from comment #1) > This is a bug in FreeBSD, not sudo. Unlike Linux and Solaris, > FreeBSD seems unable to execute a script using the fexecve() system > call. > > You can work around this limitation by adding the following in your > sudoers file: > > Defaults fdexec=never > > At compile time, if you set ac_cv_func_fexecve=no in the > environment, fexecve() support will not be built-in to sudo. That > may be best from a ports perspective. Thanks for the advice, Todd. JFYI, as documented in fexecve manpage: CAVEATS If a program is setuid to a non-super-user, but is executed when the real uid is ``root'', then the program has some of the powers of a super-user as well. When executing an interpreted program through fexecve(), kernel supplies /dev/fd/n as a second argument to the interpreter, where n is the file descriptor passed in the fd argument to fexecve(). For this construction to work correctly, the fdescfs(5) filesystem shall be mounted on /dev/fd. so I tested it and when /dev/fd is mounted, fexecve is cappable of running a shell script. I'm considering to add, as you suggested, ac_cv_func_fexecve=no to build environment to get it disabled and keep things working. Do you see any negative side effect of it? Thanks
I've added a workaround in https://www.sudo.ws/repos/sudo/rev/30f7c5d64104 This checks that /dev/fd/N is be present before using fexecve() on a script.
The downside of disabling fexdcve() entirely is that it creates a time of check vs. time of use race condition. That TOCTOU already exists when the file is writable by the user but disabling fexecve() means it is an issue when the directory is writable even if the command is not.
I accidentally committed it to FreeBSD ports, but I reverted after a few secondes. This patch silenced the error but I can't see the shell script output now. sipessatti@x230:~ % poudriere Usage: poudriere [-e etcdir] [-N] command [options] Options: -A -- Force colors, even if not in a TTY -e etcdir -- Specify an alternate etc/ dir where poudriere configuration resides. -N -- Disable colors -v -- Be verbose; show more information. Use twice to enable debug output Commands: bulk -- Generate packages for given ports distclean -- Remove old distfiles daemon -- Launch the poudriere daemon help -- Show usage image -- Generate images jail -- Manage the jails used by poudriere logclean -- Remove old logfiles ports -- Create, update or delete the portstrees used by poudriere pkgclean -- Remove packages that are no longer needed options -- Configure ports options queue -- Queue a build request status -- Get the status of builds testport -- Launch a test build of a given port version -- Show the version of poudriere sipessatti@x230:~ % sudo poudriere sipessatti@x230:~ % sudo -l User sipessatti may run the following commands on x230: (ALL) NOPASSWD: /usr/local/bin/poudriere
I get missing output when fdescfs is mounted on /dev/fd with or without the patch. If fdescfs is not mounted I get the expacted behavior. It seems there are still issues remaining with sudo, fexecve() and scripts on FreeBSD. You may just wish to disable fexecve use in sudo for now on FreeBSD.
If you apply the following two commits sudo should be able to fexecve(2) a script on FreeBSD when a digest is specified in sudoers: https://www.sudo.ws/repos/sudo/rev/72c4b499c019 https://www.sudo.ws/repos/sudo/rev/d79f5125cc73 These changes will be in sudo 1.8.23.
This one worked as expected. Thanks!
Created attachment 509 [details] Fix for fexecve() of scripts on FreeBSD There was a regression caused by the previous commits that is fixed by https://www.sudo.ws/repos/sudo/rev/e0e086b4e764. Attached is a diff against 1.8 that includes all the relevant changes in one patch.