Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Fix vulnerability caused by predictable pathnames for tcpdump packet …

…captures.

Packet captures are cached from previous runs; however this requires
the use of predictable pathnames.  To prevent this becoming a security
risk, we create a dedicated directory and ensure that we own it and
it's not writable by anyone else.

See https://bugzilla.novell.com/show_bug.cgi?id=774967
  • Loading branch information...
commit 5ea8d4ddaa4cb1ce834d36889f0fe7ac0d617bc8 1 parent 9229b03
@aspiers aspiers authored
Showing with 73 additions and 42 deletions.
  1. +73 −42 chef/cookbooks/ohai/files/default/plugins/crowbar.rb
View
115 chef/cookbooks/ohai/files/default/plugins/crowbar.rb
@@ -13,6 +13,8 @@
# limitations under the License.
#
+require 'etc'
+require 'pathname'
require 'tempfile'
require 'timeout'
@@ -43,6 +45,32 @@ def self.background_time_command(timeout, background, name, command)
crowbar_ohai Mash.new
crowbar_ohai[:switch_config] = Mash.new unless crowbar_ohai[:switch_config]
+# Packet captures are cached from previous runs; however this requires
+# the use of predictable pathnames. To prevent this becoming a security
+# risk, we create a dedicated directory and ensure that we own it and
+# it's not writable by anyone else.
+#
+# See https://bugzilla.novell.com/show_bug.cgi?id=774967
+@tcpdump_dir = '/tmp/ohai-tcpdump'
+
+begin
+ Dir.mkdir(@tcpdump_dir, 0700)
+rescue Errno::EEXIST
+ # already created by previous run
+rescue
+ raise "Failed to mkdir #{@tcpdump_dir}: #$!"
+end
+
+me = Etc.getpwuid(Process.uid).name
+unless File.owned? @tcpdump_dir
+ raise "#{@tcpdump_dir} must be owned by #{me}"
+end
+File::chmod(0700, @tcpdump_dir)
+
+def tcpdump_file(network)
+ Pathname(@tcpdump_dir) + "#{network}.out"
+end
+
networks = []
mac_map = {}
bus_found=false
@@ -53,64 +81,67 @@ def self.background_time_command(timeout, background, name, command)
next if entry =~ /\./
# We only care about actual physical devices.
next unless File.exists? "/sys/class/net/#{entry}/device"
+ Chef::Log.debug("examining network interface: " + entry)
+
type = File::open("/sys/class/net/#{entry}/type").readline.strip rescue "0"
- if type == "1"
- s1 = File.readlink("/sys/class/net/#{entry}") rescue ""
- spath = File.readlink("/sys/class/net/#{entry}/device") rescue "Unknown"
- spath = s1 if s1 =~ /pci/
- spath = spath.gsub(/.*pci/, "").gsub(/\/net\/.*/, "")
-
- crowbar_ohai[:detected] = Mash.new unless crowbar_ohai[:detected]
- crowbar_ohai[:detected][:network] = Mash.new unless crowbar_ohai[:detected][:network]
- crowbar_ohai[:detected][:network][entry] = spath
-
- logical_name = entry
- networks << logical_name
- f = File.open("/sys/class/net/#{entry}/address", "r")
- mac_addr = f.gets()
- mac_map[logical_name] = mac_addr.strip
- f.close
- if !File.exists?("/tmp/tcpdump.#{logical_name}.out")
- System.background_time_command(45, true, logical_name, "ifconfig #{logical_name} up ; tcpdump -c 1 -lv -v -i #{logical_name} -a -e -s 1514 ether proto 0x88cc > /tmp/tcpdump.#{logical_name}.out")
- wait=true
- end
+ Chef::Log.debug("#{entry} is type #{type}")
+ next unless type == "1"
+
+ s1 = File.readlink("/sys/class/net/#{entry}") rescue ""
+ spath = File.readlink("/sys/class/net/#{entry}/device") rescue "Unknown"
+ spath = s1 if s1 =~ /pci/
+ spath = spath.gsub(/.*pci/, "").gsub(/\/net\/.*/, "")
+ Chef::Log.debug("#{entry} spath is #{spath}")
+
+ crowbar_ohai[:detected] = Mash.new unless crowbar_ohai[:detected]
+ crowbar_ohai[:detected][:network] = Mash.new unless crowbar_ohai[:detected][:network]
+ crowbar_ohai[:detected][:network][entry] = spath
+
+ logical_name = entry
+ networks << logical_name
+ f = File.open("/sys/class/net/#{entry}/address", "r")
+ mac_addr = f.gets()
+ mac_map[logical_name] = mac_addr.strip
+ f.close
+ Chef::Log.debug("MAC is #{mac_addr.strip}")
+
+ tcpdump_out = tcpdump_file(logical_name)
+ Chef::Log.debug("tcpdump to: #{tcpdump_out}")
+
+ if ! File.exists? tcpdump_out
+ cmd = "ifconfig #{logical_name} up ; tcpdump -c 1 -lv -v -i #{logical_name} -a -e -s 1514 ether proto 0x88cc > #{tcpdump_out}"
+ Chef::Log.debug("cmd: #{cmd}")
+ System.background_time_command(45, true, logical_name, cmd)
+ wait=true
end
end
system("sleep 45") if wait
networks.each do |network|
- sw_port = -1
- line = %x[cat /tmp/tcpdump.#{network}.out | grep "Subtype Interface Name"]
- if line =~ /[\d]+\/[\d]+\/([\d]+)/
- sw_port = $1
- end
- if line =~ /: Unit [\d]+ Port ([\d]+)/
- sw_port = $1
- end
- if line =~ /: [\S]+ [\d]+\/([\d]+)/
- sw_port = $1
- end
+ tcpdump_out = tcpdump_file(network)
sw_unit = -1
- line = %x[cat /tmp/tcpdump.#{network}.out | grep "Subtype Interface Name"]
- if line =~ /([\d]+)\/[\d]+\/[\d]+/
- sw_unit = $1
+ sw_port = -1
+ sw_port_name = nil
+
+ line = IO.readlines(tcpdump_out).grep(/Subtype Interface Name/).join ''
+ Chef::Log.debug("subtype intf name line: #{line}")
+ if line =~ %r!(\d+)/\d+/(\d+)!
+ sw_unit, sw_port = $1, $2
end
- if line =~ /: Unit ([\d]+) Port [\d]+/
- sw_unit = $1
+ if line =~ /: Unit (\d+) Port (\d+)/
+ sw_unit, sw_port = $1, $2
end
-
- sw_port_name = nil
- line = %x[cat /tmp/tcpdump.#{network}.out | grep "Subtype Interface Name"]
- if line =~ /: ([\S]+ [\d]+\/[\d]+)/
- sw_port_name = $1
+ if line =~ %r!: (\S+ \d+/(\d+))!
+ sw_port_name, sw_port = $1, $2
else
sw_port_name = "#{sw_unit}/0/#{sw_port}"
end
sw_name = -1
# Using mac for now, but should change to something else later.
- line = %x[cat /tmp/tcpdump.#{network}.out | grep "Subtype MAC address"]
+ line = IO.readlines(tcpdump_out).grep(/Subtype MAC address/).join ''
+ Chef::Log.debug("subtype MAC line: #{line}")
if line =~ /: (.*) \(oui/
sw_name = $1
end
Please sign in to comment.
Something went wrong with that request. Please try again.