Class: OsCtl::Lib::Sys
- Inherits:
-
Object
- Object
- OsCtl::Lib::Sys
- Defined in:
- lib/libosctl/sys.rb
Defined Under Namespace
Modules: Int
Constant Summary collapse
- SYS_OPENAT2 =
vpsAdminOS currently supports x86_64-linux only. Keep the syscall number here until libc exposes an openat2(2) wrapper.
437- O_CLOEXEC =
0x0008_0000- O_DIRECTORY =
0x0001_0000- RESOLVE_NO_MAGICLINKS =
0x02- RESOLVE_NO_SYMLINKS =
0x04- RESOLVE_BENEATH =
0x08- CLONE_NEWNS =
0x00020000- CLONE_NEWUTS =
0x04000000- CLONE_NEWUSER =
0x10000000- CLONE_NEWPID =
0x20000000- CLONE_NEWNET =
0x40000000- CLONE_NEWIPC =
0x08000000- MS_MGC_VAL =
0xc0ed0000- MS_RDONLY =
1- MS_NOSUID =
2- MS_NODEV =
4- MS_NOEXEC =
8- MS_REMOUNT =
32- MS_BIND =
4096- MS_MOVE =
8192- MS_REC =
16_384- MS_PRIVATE =
1 << 18
- MS_SLAVE =
1 << 19
- MS_SHARED =
1 << 20
- SYSLOGNS_MAX_TAG_BYTESIZE =
12
Instance Method Summary collapse
- #attach_syslogns(pid) ⇒ Object
- #bind_mount(src, dst) ⇒ Object
- #bind_mount_readonly(src, dst) ⇒ Object
- #chroot(path) ⇒ Object
- #create_syslogns(tag) ⇒ Object
- #fchdir_io(io) ⇒ Object
- #make_private(dst) ⇒ Object
- #make_rprivate(dst) ⇒ Object
- #make_rshared(dst) ⇒ Object
- #make_rslave(dst) ⇒ Object
- #make_shared(dst) ⇒ Object
- #make_slave(dst) ⇒ Object
- #mount_proc(dst) ⇒ Object
- #mount_sysfs(dst) ⇒ Object
- #mount_tmpfs(dst, name: 'none', flags: MS_MGC_VAL, options: 0) ⇒ Object
- #move_mount(src, dst) ⇒ Object
-
#namespace_userns(namespace) ⇒ Object
NS_GET_USERNS: query the kernel owner, not a caller-provided namespace.
-
#open_beneath(dir, path, flags: File::RDONLY) ⇒ Object
Open
pathbelow an already-open directory without permitting symlink or magic-link traversal. -
#openat_io(dir, path, flags: File::RDONLY, mode: 0) ⇒ Object
Open a path relative to an already-open directory.
- #pidfd_alive?(pidfd) ⇒ Boolean
- #pidfd_open(pid) ⇒ Object
- #rbind_mount(src, dst) ⇒ Object
- #setns_io(io, nstype) ⇒ Object
- #setns_path(path, nstype) ⇒ Object
- #setresgid(rgid, egid, sgid) ⇒ Object
- #setresuid(ruid, euid, suid) ⇒ Object
- #syncfs(path) ⇒ Object
- #unmount(mountpoint) ⇒ Object
- #unmount_lazy(mountpoint) ⇒ Object
- #unshare_ns(type) ⇒ Object
Instance Method Details
#attach_syslogns(pid) ⇒ Object
296 297 298 |
# File 'lib/libosctl/sys.rb', line 296 def attach_syslogns(pid) setns_path(File.join('/proc', pid.to_s, 'ns/syslog'), 0) end |
#bind_mount(src, dst) ⇒ Object
147 148 149 150 151 152 |
# File 'lib/libosctl/sys.rb', line 147 def bind_mount(src, dst) ret = Int.mount(src, dst, 0, MS_MGC_VAL | MS_BIND, 0) raise SystemCallError, Fiddle.last_error if ret != 0 ret end |
#bind_mount_readonly(src, dst) ⇒ Object
154 155 156 157 158 159 160 161 |
# File 'lib/libosctl/sys.rb', line 154 def bind_mount_readonly(src, dst) bind_mount(src, dst) ret = Int.mount('none', dst, 0, MS_MGC_VAL | MS_BIND | MS_REMOUNT | MS_RDONLY, 0) raise SystemCallError, Fiddle.last_error if ret != 0 ret end |
#chroot(path) ⇒ Object
266 267 268 269 270 271 |
# File 'lib/libosctl/sys.rb', line 266 def chroot(path) ret = Int.chroot(path) raise SystemCallError, Fiddle.last_error if ret != 0 ret end |
#create_syslogns(tag) ⇒ Object
281 282 283 284 285 286 287 288 289 290 291 292 293 |
# File 'lib/libosctl/sys.rb', line 281 def create_syslogns(tag) if tag.bytesize > SYSLOGNS_MAX_TAG_BYTESIZE raise ArgumentError, "tag can have at most #{SYSLOGNS_MAX_TAG_BYTESIZE} bytes" end klogctl_ret = Int.klogctl(11, tag, tag.bytesize) raise SystemCallError, Fiddle.last_error if klogctl_ret != 0 unshare_ret = Int.unshare(0) raise SystemCallError, Fiddle.last_error if unshare_ret != 0 0 end |
#fchdir_io(io) ⇒ Object
273 274 275 276 277 278 |
# File 'lib/libosctl/sys.rb', line 273 def fchdir_io(io) ret = Int.fchdir(io.fileno) raise SystemCallError, Fiddle.last_error if ret != 0 ret end |
#make_private(dst) ⇒ Object
198 199 200 201 202 203 |
# File 'lib/libosctl/sys.rb', line 198 def make_private(dst) ret = Int.mount('none', dst, 0, MS_PRIVATE, 0) raise SystemCallError, Fiddle.last_error if ret != 0 ret end |
#make_rprivate(dst) ⇒ Object
205 206 207 208 209 210 |
# File 'lib/libosctl/sys.rb', line 205 def make_rprivate(dst) ret = Int.mount('none', dst, 0, MS_REC | MS_PRIVATE, 0) raise SystemCallError, Fiddle.last_error if ret != 0 ret end |
#make_rshared(dst) ⇒ Object
212 213 214 215 216 217 |
# File 'lib/libosctl/sys.rb', line 212 def make_rshared(dst) ret = Int.mount('none', dst, 0, MS_REC | MS_SHARED, 0) raise SystemCallError, Fiddle.last_error if ret != 0 ret end |
#make_rslave(dst) ⇒ Object
226 227 228 229 230 231 |
# File 'lib/libosctl/sys.rb', line 226 def make_rslave(dst) ret = Int.mount('none', dst, 0, MS_REC | MS_SLAVE, 0) raise SystemCallError, Fiddle.last_error if ret != 0 ret end |
#make_shared(dst) ⇒ Object
191 192 193 194 195 196 |
# File 'lib/libosctl/sys.rb', line 191 def make_shared(dst) ret = Int.mount('none', dst, 0, MS_SHARED, 0) raise SystemCallError, Fiddle.last_error if ret != 0 ret end |
#make_slave(dst) ⇒ Object
219 220 221 222 223 224 |
# File 'lib/libosctl/sys.rb', line 219 def make_slave(dst) ret = Int.mount('none', dst, 0, MS_SLAVE, 0) raise SystemCallError, Fiddle.last_error if ret != 0 ret end |
#mount_proc(dst) ⇒ Object
177 178 179 180 181 182 |
# File 'lib/libosctl/sys.rb', line 177 def mount_proc(dst) ret = Int.mount('none', dst, 'proc', MS_MGC_VAL, 0) raise SystemCallError, Fiddle.last_error if ret != 0 ret end |
#mount_sysfs(dst) ⇒ Object
184 185 186 187 188 189 |
# File 'lib/libosctl/sys.rb', line 184 def mount_sysfs(dst) ret = Int.mount('none', dst, 'sysfs', MS_NOSUID | MS_NODEV | MS_NOEXEC, 0) raise SystemCallError, Fiddle.last_error if ret != 0 ret end |
#mount_tmpfs(dst, name: 'none', flags: MS_MGC_VAL, options: 0) ⇒ Object
170 171 172 173 174 175 |
# File 'lib/libosctl/sys.rb', line 170 def mount_tmpfs(dst, name: 'none', flags: MS_MGC_VAL, options: 0) ret = Int.mount(name, dst, 'tmpfs', flags, ) raise SystemCallError, Fiddle.last_error if ret != 0 ret end |
#move_mount(src, dst) ⇒ Object
140 141 142 143 144 145 |
# File 'lib/libosctl/sys.rb', line 140 def move_mount(src, dst) ret = Int.mount(src, dst, 0, MS_MGC_VAL | MS_MOVE, 0) raise SystemCallError, Fiddle.last_error if ret != 0 ret end |
#namespace_userns(namespace) ⇒ Object
NS_GET_USERNS: query the kernel owner, not a caller-provided namespace.
80 81 82 83 84 |
# File 'lib/libosctl/sys.rb', line 80 def namespace_userns(namespace) io = IO.for_fd(namespace.ioctl(0xb701, 0), autoclose: true) io.close_on_exec = true io end |
#open_beneath(dir, path, flags: File::RDONLY) ⇒ Object
Open path below an already-open directory without permitting symlink
or magic-link traversal. The returned IO owns the new descriptor.
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
# File 'lib/libosctl/sys.rb', line 116 def open_beneath(dir, path, flags: File::RDONLY) relative_path = path.to_s if relative_path.empty? || relative_path.start_with?('/') || relative_path.include?("\0") raise ArgumentError, 'path has to be a non-empty relative path' end how = [ Integer(flags) | O_CLOEXEC | O_DIRECTORY, 0, RESOLVE_BENEATH | RESOLVE_NO_MAGICLINKS | RESOLVE_NO_SYMLINKS ].pack('Q<Q<Q<') fd = Int.syscall( SYS_OPENAT2, dir.fileno, relative_path, how, how.bytesize ) raise SystemCallError, Fiddle.last_error if fd < 0 IO.for_fd(fd, autoclose: true).tap { |io| io.close_on_exec = true } end |
#openat_io(dir, path, flags: File::RDONLY, mode: 0) ⇒ Object
Open a path relative to an already-open directory. Unlike
#open_beneath, this helper permits procfs magic links, which are needed
to reopen root and namespace descriptors through a retained /proc/
101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/libosctl/sys.rb', line 101 def openat_io(dir, path, flags: File::RDONLY, mode: 0) relative_path = path.to_s if relative_path.empty? || relative_path.start_with?('/') || relative_path.include?("\0") || relative_path.split('/').include?('..') raise ArgumentError, 'path has to be a safe relative path' end fd = Int.openat(dir.fileno, relative_path, Integer(flags) | O_CLOEXEC, Integer(mode)) raise SystemCallError, Fiddle.last_error if fd < 0 IO.for_fd(fd, autoclose: true).tap { |io| io.close_on_exec = true } end |
#pidfd_alive?(pidfd) ⇒ Boolean
93 94 95 |
# File 'lib/libosctl/sys.rb', line 93 def pidfd_alive?(pidfd) pidfd.wait_readable(0).nil? end |
#pidfd_open(pid) ⇒ Object
86 87 88 89 90 91 |
# File 'lib/libosctl/sys.rb', line 86 def pidfd_open(pid) fd = Int.pidfd_open(pid, 0) raise SystemCallError, Fiddle.last_error if fd < 0 IO.for_fd(fd, autoclose: true) end |
#rbind_mount(src, dst) ⇒ Object
163 164 165 166 167 168 |
# File 'lib/libosctl/sys.rb', line 163 def rbind_mount(src, dst) ret = Int.mount(src, dst, 0, MS_MGC_VAL | MS_BIND | MS_REC, 0) raise SystemCallError, Fiddle.last_error if ret != 0 ret end |
#setns_io(io, nstype) ⇒ Object
256 257 258 259 |
# File 'lib/libosctl/sys.rb', line 256 def setns_io(io, nstype) Native.setns(io.fileno, nstype) nil end |
#setns_path(path, nstype) ⇒ Object
247 248 249 250 251 252 253 254 |
# File 'lib/libosctl/sys.rb', line 247 def setns_path(path, nstype) f = File.open(path) Native.setns(f.fileno, nstype) nil ensure f.close if f end |
#setresgid(rgid, egid, sgid) ⇒ Object
72 73 74 75 76 77 |
# File 'lib/libosctl/sys.rb', line 72 def setresgid(rgid, egid, sgid) ret = Int.setresgid(rgid, egid, sgid) raise SystemCallError, Fiddle.last_error if ret != 0 ret end |
#setresuid(ruid, euid, suid) ⇒ Object
65 66 67 68 69 70 |
# File 'lib/libosctl/sys.rb', line 65 def setresuid(ruid, euid, suid) ret = Int.setresuid(ruid, euid, suid) raise SystemCallError, Fiddle.last_error if ret != 0 ret end |
#syncfs(path) ⇒ Object
301 302 303 304 305 306 307 308 309 310 |
# File 'lib/libosctl/sys.rb', line 301 def syncfs(path) f = Tempfile.new('.syncfs', path) ret = Int.syncfs(f.fileno) raise SystemCallError, Fiddle.last_error if ret != 0 ret ensure f.close f.unlink end |
#unmount(mountpoint) ⇒ Object
233 234 235 236 237 238 |
# File 'lib/libosctl/sys.rb', line 233 def unmount(mountpoint) ret = Int.umount2(mountpoint, 0) # force unmount returns EACCESS raise SystemCallError, Fiddle.last_error if ret != 0 ret end |
#unmount_lazy(mountpoint) ⇒ Object
240 241 242 243 244 245 |
# File 'lib/libosctl/sys.rb', line 240 def unmount_lazy(mountpoint) ret = Int.umount2(mountpoint, Int::MNT_DETACH) raise SystemCallError, Fiddle.last_error if ret != 0 ret end |
#unshare_ns(type) ⇒ Object
261 262 263 264 |
# File 'lib/libosctl/sys.rb', line 261 def unshare_ns(type) Native.unshare(type) nil end |