Sign Up
Log In
Sign Up
Username:
*
Email:
*
Password:
*
Password confirmation:
*
or
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
AppArmor
smar-apparmor-profiles
systemd_override.rb
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File systemd_override.rb of Package smar-apparmor-profiles
# This file is included by generate_spec.rb class OverrideFile attr_accessor :conditional def initialize profile_name # Matches if profile_name is a a collection of # key-value pairs. # # This means, the data is something like: # # load_profile_by_systemd: # user: # pulseaudio: # profile: pulseaudio # # Here key of `profile_name` would be “profile” # and value would be “pulseaudio”. if profile_name.respond_to? :each_pair @profile_name = profile_name["profile"] # Safeguard. raise "Empty profile name" if @profile_name.empty? @no_new_privs = profile_name["no_new_privs"] else @profile_name = profile_name end end def to_s return to_s_conditional if @conditional output = <<~EOF [Service] AppArmorProfile=#{@profile_name} EOF output += no_new_privs_to_s output end # Conditional profiles shouldn’t be used but where # absolutely needed (systemd-udevd load during boot # seems to be broken, so it needs to be conditional), # so log these. private def to_s_conditional verb "Conditional profile for #{@profile_name}" output = <<~EOF [Service] AppArmorProfile=-#{@profile_name} EOF output += no_new_privs_to_s output end private def no_new_privs_to_s return "" if @no_new_privs.nil? # If `NoNewPrivileges=yes`, systemd practically # won’t transition to the profile mentioned in # `AppArmorProfile=`. output = "NoNewPrivileges=#{ @no_new_privs ? "yes" : "no" }" output += "\n" output end end class SystemdOverride SYSTEMD_OVERRIDES_DIR_NAME = "systemd_overrides" SYSTEMD_OVERRIDES_DIR = "#{__dir__}/#{SYSTEMD_OVERRIDES_DIR_NAME}" SYSTEMD_OVERRIDES_TAR = "systemd_overrides.tar" at_exit do if Dir.exist? SYSTEMD_OVERRIDES_DIR FileUtils.rm_r SYSTEMD_OVERRIDES_DIR end end def initialize Dir.mkdir SYSTEMD_OVERRIDES_DIR end def finalize return unless Dir.exists? SYSTEMD_OVERRIDES_DIR return unless systemd_overrides_changed? # Try to create reproducible tar. # NOTE: --mtime is not specified here, so archive actually will be different in # each generation, but that can be added to reproduce archive from certain time. tar_command = "tar" tar_command = "#{tar_command} --sort=name --owner=0 --group=0 --numeric-owner" tar_command = "#{tar_command} --pax-option=exthdr.name=%d/PaxHeaders/%f,delete=atime,delete=ctime" tar_command = "#{tar_command} -cf #{SYSTEMD_OVERRIDES_TAR} systemd_overrides/" debug "Executing “#{tar_command}”." result = `#{tar_command}` unless $?.success? puts "Failed to execute “#{tar_command}”. Output:" puts result exit 21 end File.delete "#{SYSTEMD_OVERRIDES_TAR}.xz" if File.exist? "#{SYSTEMD_OVERRIDES_TAR}.xz" # Using single thread should make xz archives reproducible across systems. # Though since I always regenerate the files, metadata won’t match, so there will always # be new archive. # But since this is so small, this has no harm. xz_command = "xz --threads=1 #{SYSTEMD_OVERRIDES_TAR}" `#{xz_command}` # Now there should be archive systemd_overrides.tar.xz. end def install_lines_for_load_profile_by_systemd(definition, package, service_name, profile_name, user: false, conditional: false) return if redirect_to_service definition, package, service_name, profile_name write_systemd_override_file package, service_name, profile_name, user: user, conditional: conditional # Matches if profile_name is a a collection of # key-value pairs. # # This means, the data is something like: # # load_profile_by_systemd: # user: # pulseaudio: # profile: pulseaudio # # Here key of `profile_name` would be “profile” # and value would be “pulseaudio”. if profile_name.respond_to? :each_pair profile_name = profile_name["profile"] end if user override_file = Pathname.new("systemd_overrides") / "user" / package["name"] / service_name / "#{profile_name}.conf" unitdir_tag = "%{_userunitdir}" else override_file = Pathname.new("systemd_overrides") / package["name"] / service_name / "#{profile_name}.conf" unitdir_tag = "%{_unitdir}" end definition << "mkdir -p %{buildroot}#{unitdir_tag}/#{service_name}.service.d/" definition << "mv #{override_file} %{buildroot}#{unitdir_tag}/#{service_name}.service.d/" end # Returns true if service name is something like “user”. private def redirect_to_service definition, package, service_name, profile_name if service_name == "system" profile_name.each do |service_name, profile_name| install_lines_for_load_profile_by_systemd definition, package, service_name, profile_name end return true end if service_name == "system_conditional" profile_name.each do |service_name, profile_name| install_lines_for_load_profile_by_systemd definition, package, service_name, profile_name, conditional: true end return true end if service_name == "user" profile_name.each do |service_name, profile_name| install_lines_for_load_profile_by_systemd definition, package, service_name, profile_name, user: true end return true end if service_name == "user_conditional" profile_name.each do |service_name, profile_name| install_lines_for_load_profile_by_systemd definition, package, service_name, profile_name, user: true, conditional: true end return true end false end private def write_systemd_override_file package, service_name, profile_name, user: false, conditional: false if user package_dir = Pathname.new(SYSTEMD_OVERRIDES_DIR) / "user" / package["name"] Dir.mkdir package_dir.parent unless Dir.exist? package_dir.parent else package_dir = Pathname.new(SYSTEMD_OVERRIDES_DIR) / package["name"] end Dir.mkdir package_dir unless Dir.exist? package_dir service_dir = package_dir / service_name Dir.mkdir service_dir unless Dir.exist? service_dir profile = generate_service_override_conf profile_name, conditional: conditional # Matches if profile_name is a a collection of # key-value pairs. # # This means, the data is something like: # # load_profile_by_systemd: # user: # pulseaudio: # profile: pulseaudio # # Here key of `profile_name` would be “profile” # and value would be “pulseaudio”. if profile_name.respond_to? :each_pair profile_name = profile_name["profile"] end debug "Writing #{service_dir / "#{profile_name}.conf"}" File.open(service_dir / "#{profile_name}.conf", "w") do |f| f.write profile end end private def generate_service_override_conf profile_name, conditional: false override = OverrideFile.new profile_name override.conditional = conditional override.to_s end private def systemd_overrides_changed? # First check if there is missing files. files = Dir.glob "#{SYSTEMD_OVERRIDES_DIR_NAME}/**/*", base: __dir__ files = files.delete_if do |path| File.directory? path end missing_files_command = "tar" missing_files_args = %W{ tf #{SYSTEMD_OVERRIDES_TAR}.xz } + files debug "Executing missing_files_command: “#{missing_files_command} #{missing_files_args.join(" ")}”." # err: :close == Don’t output command STDERR to generate_spec.rb’s STDERR. # # HINT: Use latter for debugging. if DEBUG result = system(missing_files_command, *missing_files_args) else result = system(missing_files_command, *missing_files_args, out: File::NULL, err: File::NULL) end debug "missing_files_command exitstatus=#{$?.exitstatus}, result=#{result}" if $?.exitstatus == 2 # A file is missing from overrides archive. return true end if $?.exitstatus != 0 puts "ERROR: Got an exit code from tar that is not handled: #{$?.exitstatus}" exit 23 end # Then try to compare contents. # # This is a bit flaky. compare_command = %{env LANG=C tar --compare --file='#{SYSTEMD_OVERRIDES_TAR}.xz'} compare_command = %{#{compare_command} | grep -v 'Uid differs$' | grep -v 'Gid differs$'} compare_command = %{#{compare_command} | grep -v 'Mod time differs$'} debug "Executing compare_command: “#{compare_command}”." output = nil IO.pipe do |read_io, write_io| result = system(compare_command, out: write_io, err: write_io) write_io.close output = read_io.read end debug "compare_command exitstatus=#{$?.exitstatus}, result=#{result}" # 0 is everything is same, 1 means some files differs. unless [0, 1].include? $?.exitstatus puts "Failed to execute compare command. Result:" puts puts output exit 22 end debug "compare_command output: #{output}" # If yes, there is no changed content in the archive. if output.empty? return false end true end end
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Contact
Support
@OBShq
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor