libshit

Just some random shit
git clone https://git.neptards.moe/neptards/libshit.git
Log | Files | Refs | Submodules | README | LICENSE

linux.rb (3209B)


      1 # frozen_string_literal: true
      2 
      3 require 'fileutils'
      4 require 'set'
      5 
      6 linux_rb_so = File.join __dir__, 'linux_rb.so'
      7 linux_rb_c = File.join __dir__, 'linux_rb.c'
      8 if File.exist?(linux_rb_c) && (!File.exist?(linux_rb_so) ||
      9                                File.mtime(linux_rb_so) < File.mtime(linux_rb_c))
     10   require 'rbconfig'
     11   cfg = RbConfig::CONFIG
     12   cmd = "#{cfg['DLDSHARED']} #{cfg['CCDLFLAGS']} #{cfg['CFLAGS']} #{cfg['LDFLAGS']}".
     13           split(/ +/)
     14   cmd += %W(-I#{cfg['rubyarchhdrdir']} -I#{cfg['rubyhdrdir']} -g -o #{linux_rb_so}
     15             #{linux_rb_c})
     16   system *cmd or fail 'Failed to compile linux_rb'
     17 end
     18 require linux_rb_so
     19 
     20 module Linux
     21   extend self
     22   def clonens &blk
     23     uid = Process.uid
     24     gid = Process.gid
     25 
     26     clone CLONE_NEWUSER | CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | \
     27           CLONE_NEWNET do
     28       uid_gid_map uid, gid
     29       mount '/', '/', nil, MS_REC | MS_PRIVATE
     30       mount 'none', '/proc', 'proc', MS_NOSUID | MS_NODEV | MS_RDONLY
     31 
     32       FileUtils.mkdir_p 'tmp'
     33       mount 'tmp', '/tmp', nil, MS_BIND
     34       mount nil, '/tmp', nil, MS_BIND | MS_REMOUNT | MS_NOSUID | MS_NODEV
     35 
     36       # Make home unwriteable
     37       cwd = File.expand_path('.')
     38       mount cwd, cwd, nil, MS_BIND rescue nil
     39       mount nil, cwd, nil, MS_BIND | MS_REMOUNT | MS_NOSUID | MS_NODEV
     40       make_ro [cwd, '/tmp']
     41 
     42       # Try to automatically reap children. This does some magic so normal wait
     43       # still works while still reaping most children. A single zombie
     44       # conhost.exe seem to remain after executing wine, but it's much better
     45       # that the 4 zombie processes I see without this.
     46       Signal.trap 'CHLD', 'IGNORE'
     47       blk.call
     48     rescue Exception
     49       puts $!.full_message
     50       exit! 1
     51     end
     52   end
     53 
     54   def uid_gid_map uid, gid, pid = 'self'
     55     File.write "/proc/#{pid}/setgroups", 'deny'
     56     File.write "/proc/#{pid}/gid_map", "#{gid} #{gid} 1\n"
     57     File.write "/proc/#{pid}/uid_map", "#{uid} #{uid} 1\n"
     58   end
     59 
     60   def make_ro except
     61     # read the full file in advance, because we will change the mounts that can
     62     # change the file, and I have no freakin idea what happens in that case.
     63     # Also mount points can be hidden by later mounts, ignore them as trying to
     64     # remount them gives an EINVAL
     65     points = {}
     66     File.foreach('/proc/self/mountinfo').each do |l|
     67       fields = l.split ' '
     68       opts = fields[5].split ','
     69 
     70       point = fields[4]
     71       point_slash = point.end_with?('/') ? point : point + '/'
     72       points.reject! {|p,ro| p.start_with? point_slash }
     73       points[point] = opts.member? 'ro'
     74     end
     75 
     76     points.each do |point,ro|
     77       next if except.include? point
     78       # skip already RO mounts, depending on the sandbox sometimes they can't be
     79       # remounted as RO, but that's not a problem...
     80       next if ro
     81 
     82       begin
     83         mount nil, point, nil, MS_BIND | MS_REMOUNT | MS_RDONLY
     84       rescue Errno::EPERM, Errno::EACCES
     85         # /sys usually gives EPERM when trying to remount, ignore it...
     86         $stderr.puts " \e[31;1m*\e[0m Failed to make #{point.inspect} ro"
     87       end
     88     end
     89   end
     90 
     91   def clonens_wait &blk
     92     pid = clonens &blk
     93     Process.wait pid
     94     fail "Subprocess failed: #{$?}" unless $?.success?
     95   end
     96 end