Skip to content

Commit

Permalink
(PUP-2738) Puppet::Util::Windows::Process FFI clean
Browse files Browse the repository at this point in the history
 - Refactor wait_process so that the FFI::MemoryPointer for the exit
   code is cleaned up immediately after use.  Note that we capture the
   exit_status within the block, and return it outside of the block
 - Fix bug in Puppet::Util::Windows::Process.process_privilege_symlink?
   that could result in the wrong value being returned.
 - Fix bug in Puppet::Util::Windows::Process.elevated_security?
   that could result in the wrong value being returned.
  • Loading branch information
Iristyle committed Jun 18, 2014
1 parent 2631a6f commit 006339b
Showing 1 changed file with 22 additions and 17 deletions.
39 changes: 22 additions & 17 deletions lib/puppet/util/windows/process.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,19 @@ def wait_process(handle)
sleep(1)
end

exit_status = FFI::MemoryPointer.new(:dword, 1)
if GetExitCodeProcess(handle, exit_status) == FFI::WIN32_FALSE
raise Puppet::Util::Windows::Error.new("Failed to get child process exit code")
exit_status = -1
FFI::MemoryPointer.new(:dword, 1) do |exit_status_ptr|
if GetExitCodeProcess(handle, exit_status_ptr) == FFI::WIN32_FALSE
raise Puppet::Util::Windows::Error.new("Failed to get child process exit code")
end
exit_status = exit_status_ptr.read_dword

# $CHILD_STATUS is not set when calling win32/process Process.create
# and since it's read-only, we can't set it. But we can execute a
# a shell that simply returns the desired exit status, which has the
# desired effect.
%x{#{ENV['COMSPEC']} /c exit #{exit_status}}
end
exit_status = exit_status.read_dword

# $CHILD_STATUS is not set when calling win32/process Process.create
# and since it's read-only, we can't set it. But we can execute a
# a shell that simply returns the desired exit status, which has the
# desired effect.
%x{#{ENV['COMSPEC']} /c exit #{exit_status}}

exit_status
end
Expand Down Expand Up @@ -120,13 +122,16 @@ def parse_token_information_as_token_elevation(token_information_buf)
TOKEN_ALL_ACCESS = 0xF01FF
ERROR_NO_SUCH_PRIVILEGE = 1313
def process_privilege_symlink?
privilege_symlink = false
handle = get_current_process
open_process_token(handle, TOKEN_ALL_ACCESS) do |token_handle|
luid = lookup_privilege_value('SeCreateSymbolicLinkPrivilege')
token_info = get_token_information(token_handle, :TokenPrivileges)
token_privileges = parse_token_information_as_token_privileges(token_info)
token_privileges[:privileges].any? { |p| p[:Luid].values == luid.values }
privilege_symlink = token_privileges[:privileges].any? { |p| p[:Luid].values == luid.values }
end

privilege_symlink
rescue Puppet::Util::Windows::Error => e
if e.code == ERROR_NO_SUCH_PRIVILEGE
false # pre-Vista
Expand All @@ -143,19 +148,19 @@ def process_privilege_symlink?
# Only supported on Windows Vista or later.
#
def elevated_security?
# default / pre-Vista
elevated = false
handle = get_current_process
open_process_token(handle, TOKEN_QUERY) do |token_handle|
token_info = get_token_information(token_handle, :TokenElevation)
token_elevation = parse_token_information_as_token_elevation(token_info)
# TokenIsElevated member of the TOKEN_ELEVATION struct
token_elevation[:TokenIsElevated] != 0
elevated = token_elevation[:TokenIsElevated] != 0
end

elevated
rescue Puppet::Util::Windows::Error => e
if e.code == ERROR_NO_SUCH_PRIVILEGE
false # pre-Vista
else
raise e
end
raise e if e.code != ERROR_NO_SUCH_PRIVILEGE
ensure
CloseHandle(handle)
end
Expand Down

0 comments on commit 006339b

Please sign in to comment.