-
-
Notifications
You must be signed in to change notification settings - Fork 10.4k
brew.sh: enforce HOMEBREW_FORCE_BREW_WRAPPER
more strictly
#20400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
`HOMEBREW_FORCE_BREW_WRAPPER` can be used as a security/compliance feature, but allowing it to be disabled by setting `HOMEBREW_NO_FORCE_BREW_WRAPPER` leaves a pretty large hole in it that allows it to be sidestepped. Let's fix that by actually checking the path of the process that called `brew`, and the verify that that path matches the configured value of `HOMEBREW_NO_FORCE_BREW_WRAPPER`.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @carlocab! A bunch of comments, sorry!
HOMEBREW_BREW_WRAPPER: { | ||
description: "If set, use wrapper to call `brew` rather than auto-detecting it.", | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to go through a deprecation cycle before dropping this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, will do that.
HOMEBREW_NO_FORCE_BREW_WRAPPER: { | ||
description: "If set, disables `$HOMEBREW_FORCE_BREW_WRAPPER` behaviour, even if set.", | ||
boolean: true, | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here.
Could add something HOMEBREW_DISABLE_NO_FORCE_BREW_WRAPPER
if you want the ability to disable this functionality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, sounds good.
|
||
require "fiddle" | ||
|
||
libproc = Fiddle.dlopen("/usr/lib/libproc.dylib") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if this file doesn't exist?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It actually won't; it lives in the dyld
cache. But, I suppose you were asking what happens if it fails. It exits immediately with an error like:
❯ ./test.rb
/Users/carlocab/.rbenv/versions/3.4.5/lib/ruby/3.4.0/fiddle.rb:93:in 'Fiddle::Handle#initialize': dlopen(/path/to/nonexistent.dylib, 0x0009): tried: '/path/to/nonexistent.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/path/to/nonexistent.dylib' (no such file), '/path/to/nonexistent.dylib' (no such file) (Fiddle::DLError)
from /Users/carlocab/.rbenv/versions/3.4.5/lib/ruby/3.4.0/fiddle.rb:93:in 'Class#new'
from /Users/carlocab/.rbenv/versions/3.4.5/lib/ruby/3.4.0/fiddle.rb:93:in 'Fiddle.dlopen'
from ./test.rb:4:in '<main>'
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, thanks. Does the caller handle this case appropriately i.e. the exit code is as expected?
|
||
libproc = Fiddle.dlopen("/usr/lib/libproc.dylib") | ||
|
||
proc_pidpath = Fiddle::Function.new( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
proc_pidpath = Fiddle::Function.new( | |
libproc_proc_pidpath_function = Fiddle::Function.new( |
pid = ARGV[0]&.to_i | ||
exit 1 unless pid |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do this before anything else. Should produce an error message if there's no argument passed.
bufsize = 4 * 1024 # PROC_PIDPATHINFO_MAXSIZE = 4 * MAXPATHLEN | ||
buf = "\0" * bufsize | ||
ptr = Fiddle::Pointer.to_ptr(buf) | ||
|
||
ret = proc_pidpath.call(pid, ptr, bufsize) | ||
puts ptr.to_s.strip if ret.positive? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs better comments here.
bufsize = 4 * 1024 # PROC_PIDPATHINFO_MAXSIZE = 4 * MAXPATHLEN | ||
buf = "\0" * bufsize | ||
ptr = Fiddle::Pointer.to_ptr(buf) | ||
|
||
ret = proc_pidpath.call(pid, ptr, bufsize) | ||
puts ptr.to_s.strip if ret.positive? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
bufsize = 4 * 1024 # PROC_PIDPATHINFO_MAXSIZE = 4 * MAXPATHLEN | |
buf = "\0" * bufsize | |
ptr = Fiddle::Pointer.to_ptr(buf) | |
ret = proc_pidpath.call(pid, ptr, bufsize) | |
puts ptr.to_s.strip if ret.positive? | |
buffer_size = 4 * 1024 # PROC_PIDPATHINFO_MAXSIZE = 4 * MAXPATHLEN | |
null_buffer = "\0" * buffer_size | |
pointer = Fiddle::Pointer.to_ptr(buffer) | |
return_value = proc_pidpath.call(pid, pointer, buffer_size) | |
puts pointer.to_s.strip if return_value.positive? |
brew style
with your changes locally?brew typecheck
with your changes locally?brew tests
with your changes locally?HOMEBREW_FORCE_BREW_WRAPPER
can be used as a security/compliancefeature, but allowing it to be disabled by setting
HOMEBREW_NO_FORCE_BREW_WRAPPER
leaves a pretty large hole in it thatallows it to be sidestepped.
Let's fix that by actually checking the path of the process that called
brew
, and the verify that that path matches the configured value ofHOMEBREW_NO_FORCE_BREW_WRAPPER
.