github.com/nicocha30/gvisor-ligolo@v0.0.0-20230726075806-989fa2c0a413/runsc/boot/filter/config.go (about) 1 // Copyright 2018 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package filter 16 17 import ( 18 "os" 19 20 "golang.org/x/sys/unix" 21 "github.com/nicocha30/gvisor-ligolo/pkg/abi/linux" 22 "github.com/nicocha30/gvisor-ligolo/pkg/seccomp" 23 "github.com/nicocha30/gvisor-ligolo/pkg/tcpip/link/fdbased" 24 ) 25 26 // allowedSyscalls is the set of syscalls executed by the Sentry to the host OS. 27 var allowedSyscalls = seccomp.SyscallRules{ 28 unix.SYS_CLOCK_GETTIME: {}, 29 unix.SYS_CLOSE: {}, 30 unix.SYS_DUP: {}, 31 unix.SYS_DUP3: []seccomp.Rule{ 32 { 33 seccomp.MatchAny{}, 34 seccomp.MatchAny{}, 35 seccomp.EqualTo(unix.O_CLOEXEC), 36 }, 37 }, 38 unix.SYS_EPOLL_CREATE1: {}, 39 unix.SYS_EPOLL_CTL: {}, 40 unix.SYS_EPOLL_PWAIT: []seccomp.Rule{ 41 { 42 seccomp.MatchAny{}, 43 seccomp.MatchAny{}, 44 seccomp.MatchAny{}, 45 seccomp.MatchAny{}, 46 seccomp.EqualTo(0), 47 }, 48 }, 49 unix.SYS_EVENTFD2: []seccomp.Rule{ 50 { 51 seccomp.EqualTo(0), 52 seccomp.EqualTo(0), 53 }, 54 }, 55 unix.SYS_EXIT: {}, 56 unix.SYS_EXIT_GROUP: {}, 57 unix.SYS_FALLOCATE: {}, 58 unix.SYS_FCHMOD: {}, 59 unix.SYS_FCNTL: []seccomp.Rule{ 60 { 61 seccomp.MatchAny{}, 62 seccomp.EqualTo(unix.F_GETFL), 63 }, 64 { 65 seccomp.MatchAny{}, 66 seccomp.EqualTo(unix.F_SETFL), 67 }, 68 { 69 seccomp.MatchAny{}, 70 seccomp.EqualTo(unix.F_GETFD), 71 }, 72 }, 73 unix.SYS_FSTAT: {}, 74 unix.SYS_FSYNC: {}, 75 unix.SYS_FTRUNCATE: {}, 76 unix.SYS_FUTEX: []seccomp.Rule{ 77 { 78 seccomp.MatchAny{}, 79 seccomp.EqualTo(linux.FUTEX_WAIT | linux.FUTEX_PRIVATE_FLAG), 80 seccomp.MatchAny{}, 81 seccomp.MatchAny{}, 82 }, 83 { 84 seccomp.MatchAny{}, 85 seccomp.EqualTo(linux.FUTEX_WAKE | linux.FUTEX_PRIVATE_FLAG), 86 seccomp.MatchAny{}, 87 }, 88 // Non-private variants are included for flipcall support. They are otherwise 89 // unncessary, as the sentry will use only private futexes internally. 90 { 91 seccomp.MatchAny{}, 92 seccomp.EqualTo(linux.FUTEX_WAIT), 93 seccomp.MatchAny{}, 94 seccomp.MatchAny{}, 95 }, 96 { 97 seccomp.MatchAny{}, 98 seccomp.EqualTo(linux.FUTEX_WAKE), 99 seccomp.MatchAny{}, 100 }, 101 }, 102 // getcpu is used by some versions of the Go runtime and by the hostcpu 103 // package on arm64. 104 unix.SYS_GETCPU: []seccomp.Rule{ 105 { 106 seccomp.MatchAny{}, 107 seccomp.EqualTo(0), 108 seccomp.EqualTo(0), 109 }, 110 }, 111 unix.SYS_GETPID: {}, 112 unix.SYS_GETRANDOM: {}, 113 unix.SYS_GETSOCKOPT: []seccomp.Rule{ 114 { 115 seccomp.MatchAny{}, 116 seccomp.EqualTo(unix.SOL_SOCKET), 117 seccomp.EqualTo(unix.SO_DOMAIN), 118 }, 119 { 120 seccomp.MatchAny{}, 121 seccomp.EqualTo(unix.SOL_SOCKET), 122 seccomp.EqualTo(unix.SO_TYPE), 123 }, 124 { 125 seccomp.MatchAny{}, 126 seccomp.EqualTo(unix.SOL_SOCKET), 127 seccomp.EqualTo(unix.SO_ERROR), 128 }, 129 { 130 seccomp.MatchAny{}, 131 seccomp.EqualTo(unix.SOL_SOCKET), 132 seccomp.EqualTo(unix.SO_SNDBUF), 133 }, 134 }, 135 unix.SYS_GETTID: {}, 136 unix.SYS_GETTIMEOFDAY: {}, 137 unix.SYS_IOCTL: []seccomp.Rule{ 138 // These commands are needed for host FD. 139 { 140 seccomp.MatchAny{}, /* fd */ 141 seccomp.EqualTo(linux.FIONREAD), 142 seccomp.MatchAny{}, /* int* */ 143 }, 144 // These commands are needed for terminal support, but we only allow 145 // setting/getting termios and winsize. 146 { 147 seccomp.MatchAny{}, /* fd */ 148 seccomp.EqualTo(linux.TCGETS), 149 seccomp.MatchAny{}, /* termios struct */ 150 }, 151 { 152 seccomp.MatchAny{}, /* fd */ 153 seccomp.EqualTo(linux.TCSETS), 154 seccomp.MatchAny{}, /* termios struct */ 155 }, 156 { 157 seccomp.MatchAny{}, /* fd */ 158 seccomp.EqualTo(linux.TCSETSF), 159 seccomp.MatchAny{}, /* termios struct */ 160 }, 161 { 162 seccomp.MatchAny{}, /* fd */ 163 seccomp.EqualTo(linux.TCSETSW), 164 seccomp.MatchAny{}, /* termios struct */ 165 }, 166 { 167 seccomp.MatchAny{}, /* fd */ 168 seccomp.EqualTo(linux.TIOCSWINSZ), 169 seccomp.MatchAny{}, /* winsize struct */ 170 }, 171 { 172 seccomp.MatchAny{}, /* fd */ 173 seccomp.EqualTo(linux.TIOCGWINSZ), 174 seccomp.MatchAny{}, /* winsize struct */ 175 }, 176 { 177 seccomp.MatchAny{}, /* fd */ 178 seccomp.EqualTo(linux.SIOCGIFTXQLEN), 179 seccomp.MatchAny{}, /* ifreq struct */ 180 }, 181 }, 182 unix.SYS_LSEEK: {}, 183 unix.SYS_MADVISE: {}, 184 unix.SYS_MEMBARRIER: []seccomp.Rule{ 185 { 186 seccomp.EqualTo(linux.MEMBARRIER_CMD_GLOBAL), 187 seccomp.EqualTo(0), 188 }, 189 }, 190 unix.SYS_MINCORE: {}, 191 unix.SYS_MLOCK: {}, 192 unix.SYS_MMAP: []seccomp.Rule{ 193 { 194 seccomp.MatchAny{}, 195 seccomp.MatchAny{}, 196 seccomp.MatchAny{}, 197 seccomp.EqualTo(unix.MAP_SHARED), 198 }, 199 { 200 seccomp.MatchAny{}, 201 seccomp.MatchAny{}, 202 seccomp.MatchAny{}, 203 seccomp.EqualTo(unix.MAP_SHARED | unix.MAP_FIXED), 204 }, 205 { 206 seccomp.MatchAny{}, 207 seccomp.MatchAny{}, 208 seccomp.MatchAny{}, 209 seccomp.EqualTo(unix.MAP_PRIVATE), 210 }, 211 { 212 seccomp.MatchAny{}, 213 seccomp.MatchAny{}, 214 seccomp.MatchAny{}, 215 seccomp.EqualTo(unix.MAP_PRIVATE | unix.MAP_ANONYMOUS), 216 }, 217 { 218 seccomp.MatchAny{}, 219 seccomp.MatchAny{}, 220 seccomp.MatchAny{}, 221 seccomp.EqualTo(unix.MAP_PRIVATE | unix.MAP_ANONYMOUS | unix.MAP_STACK), 222 }, 223 { 224 seccomp.MatchAny{}, 225 seccomp.MatchAny{}, 226 seccomp.MatchAny{}, 227 seccomp.EqualTo(unix.MAP_PRIVATE | unix.MAP_ANONYMOUS | unix.MAP_NORESERVE), 228 }, 229 { 230 seccomp.MatchAny{}, 231 seccomp.MatchAny{}, 232 seccomp.EqualTo(unix.PROT_WRITE | unix.PROT_READ), 233 seccomp.EqualTo(unix.MAP_PRIVATE | unix.MAP_ANONYMOUS | unix.MAP_FIXED), 234 }, 235 }, 236 unix.SYS_MPROTECT: {}, 237 unix.SYS_MUNLOCK: {}, 238 unix.SYS_MUNMAP: {}, 239 unix.SYS_NANOSLEEP: {}, 240 unix.SYS_PPOLL: {}, 241 unix.SYS_PREAD64: {}, 242 unix.SYS_PREADV: {}, 243 unix.SYS_PREADV2: {}, 244 unix.SYS_PWRITE64: {}, 245 unix.SYS_PWRITEV: {}, 246 unix.SYS_PWRITEV2: {}, 247 unix.SYS_READ: {}, 248 unix.SYS_RECVMSG: []seccomp.Rule{ 249 { 250 seccomp.MatchAny{}, 251 seccomp.MatchAny{}, 252 seccomp.EqualTo(unix.MSG_DONTWAIT | unix.MSG_TRUNC), 253 }, 254 { 255 seccomp.MatchAny{}, 256 seccomp.MatchAny{}, 257 seccomp.EqualTo(unix.MSG_DONTWAIT | unix.MSG_TRUNC | unix.MSG_PEEK), 258 }, 259 }, 260 unix.SYS_RECVMMSG: []seccomp.Rule{ 261 { 262 seccomp.MatchAny{}, 263 seccomp.MatchAny{}, 264 seccomp.EqualTo(fdbased.MaxMsgsPerRecv), 265 seccomp.EqualTo(unix.MSG_DONTWAIT), 266 seccomp.EqualTo(0), 267 }, 268 }, 269 unix.SYS_SENDMMSG: []seccomp.Rule{ 270 { 271 seccomp.MatchAny{}, 272 seccomp.MatchAny{}, 273 seccomp.MatchAny{}, 274 seccomp.EqualTo(unix.MSG_DONTWAIT), 275 }, 276 }, 277 unix.SYS_RESTART_SYSCALL: {}, 278 unix.SYS_RT_SIGACTION: {}, 279 unix.SYS_RT_SIGPROCMASK: {}, 280 unix.SYS_RT_SIGRETURN: {}, 281 unix.SYS_SCHED_YIELD: {}, 282 unix.SYS_SENDMSG: []seccomp.Rule{ 283 { 284 seccomp.MatchAny{}, 285 seccomp.MatchAny{}, 286 seccomp.EqualTo(unix.MSG_DONTWAIT | unix.MSG_NOSIGNAL), 287 }, 288 }, 289 unix.SYS_SETITIMER: {}, 290 unix.SYS_SHUTDOWN: []seccomp.Rule{ 291 // Used by fs/host to shutdown host sockets. 292 {seccomp.MatchAny{}, seccomp.EqualTo(unix.SHUT_RD)}, 293 {seccomp.MatchAny{}, seccomp.EqualTo(unix.SHUT_WR)}, 294 // Used by unet to shutdown connections. 295 {seccomp.MatchAny{}, seccomp.EqualTo(unix.SHUT_RDWR)}, 296 }, 297 unix.SYS_SIGALTSTACK: {}, 298 unix.SYS_STATX: {}, 299 unix.SYS_SYNC_FILE_RANGE: {}, 300 unix.SYS_TEE: []seccomp.Rule{ 301 { 302 seccomp.MatchAny{}, 303 seccomp.MatchAny{}, 304 seccomp.EqualTo(1), /* len */ 305 seccomp.EqualTo(unix.SPLICE_F_NONBLOCK), /* flags */ 306 }, 307 }, 308 unix.SYS_TIMER_CREATE: []seccomp.Rule{ 309 { 310 seccomp.EqualTo(unix.CLOCK_THREAD_CPUTIME_ID), /* which */ 311 seccomp.MatchAny{}, /* sevp */ 312 seccomp.MatchAny{}, /* timerid */ 313 }, 314 }, 315 unix.SYS_TIMER_DELETE: []seccomp.Rule{}, 316 unix.SYS_TIMER_SETTIME: []seccomp.Rule{ 317 { 318 seccomp.MatchAny{}, /* timerid */ 319 seccomp.EqualTo(0), /* flags */ 320 seccomp.MatchAny{}, /* new_value */ 321 seccomp.EqualTo(0), /* old_value */ 322 }, 323 }, 324 unix.SYS_TGKILL: []seccomp.Rule{ 325 { 326 seccomp.EqualTo(uint64(os.Getpid())), 327 }, 328 }, 329 unix.SYS_UTIMENSAT: []seccomp.Rule{ 330 { 331 seccomp.MatchAny{}, 332 seccomp.EqualTo(0), /* null pathname */ 333 seccomp.MatchAny{}, 334 seccomp.EqualTo(0), /* flags */ 335 }, 336 }, 337 unix.SYS_WRITE: {}, 338 // For rawfile.NonBlockingWriteIovec. 339 unix.SYS_WRITEV: []seccomp.Rule{ 340 { 341 seccomp.MatchAny{}, 342 seccomp.MatchAny{}, 343 seccomp.GreaterThan(0), 344 }, 345 }, 346 } 347 348 func controlServerFilters(fd int) seccomp.SyscallRules { 349 return seccomp.SyscallRules{ 350 unix.SYS_ACCEPT4: []seccomp.Rule{ 351 { 352 seccomp.EqualTo(fd), 353 }, 354 }, 355 unix.SYS_LISTEN: []seccomp.Rule{ 356 { 357 seccomp.EqualTo(fd), 358 seccomp.EqualTo(16 /* unet.backlog */), 359 }, 360 }, 361 unix.SYS_GETSOCKOPT: []seccomp.Rule{ 362 { 363 seccomp.MatchAny{}, 364 seccomp.EqualTo(unix.SOL_SOCKET), 365 seccomp.EqualTo(unix.SO_PEERCRED), 366 }, 367 }, 368 } 369 } 370 371 // hostFilesystemFilters contains syscalls that are needed by directfs. 372 func hostFilesystemFilters() seccomp.SyscallRules { 373 // Directfs allows FD-based filesystem syscalls. We deny these syscalls with 374 // negative FD values (like AT_FDCWD or invalid FD numbers). We try to be as 375 // restrictive as possible because any restriction here improves security. We 376 // don't know what set of arguments will trigger a future vulnerability. 377 validFDCheck := seccomp.NonNegativeFDCheck() 378 return seccomp.SyscallRules{ 379 unix.SYS_FCHOWNAT: []seccomp.Rule{ 380 { 381 validFDCheck, 382 seccomp.MatchAny{}, 383 seccomp.MatchAny{}, 384 seccomp.MatchAny{}, 385 seccomp.EqualTo(unix.AT_EMPTY_PATH | unix.AT_SYMLINK_NOFOLLOW), 386 }, 387 }, 388 unix.SYS_FCHMODAT: []seccomp.Rule{ 389 { 390 validFDCheck, 391 seccomp.MatchAny{}, 392 seccomp.MatchAny{}, 393 }, 394 }, 395 unix.SYS_UNLINKAT: []seccomp.Rule{ 396 { 397 validFDCheck, 398 seccomp.MatchAny{}, 399 seccomp.MatchAny{}, 400 }, 401 }, 402 unix.SYS_GETDENTS64: []seccomp.Rule{ 403 { 404 validFDCheck, 405 seccomp.MatchAny{}, 406 seccomp.MatchAny{}, 407 }, 408 }, 409 unix.SYS_OPENAT: []seccomp.Rule{ 410 { 411 validFDCheck, 412 seccomp.MatchAny{}, 413 seccomp.MaskedEqual(unix.O_NOFOLLOW, unix.O_NOFOLLOW), 414 seccomp.MatchAny{}, 415 }, 416 }, 417 unix.SYS_LINKAT: []seccomp.Rule{ 418 { 419 validFDCheck, 420 seccomp.MatchAny{}, 421 validFDCheck, 422 seccomp.MatchAny{}, 423 seccomp.EqualTo(0), 424 }, 425 }, 426 unix.SYS_MKDIRAT: []seccomp.Rule{ 427 { 428 validFDCheck, 429 seccomp.MatchAny{}, 430 seccomp.MatchAny{}, 431 }, 432 }, 433 unix.SYS_MKNODAT: []seccomp.Rule{ 434 { 435 validFDCheck, 436 seccomp.MatchAny{}, 437 seccomp.MatchAny{}, 438 seccomp.MatchAny{}, 439 }, 440 }, 441 unix.SYS_SYMLINKAT: []seccomp.Rule{ 442 { 443 seccomp.MatchAny{}, 444 validFDCheck, 445 seccomp.MatchAny{}, 446 }, 447 }, 448 unix.SYS_FSTATFS: []seccomp.Rule{ 449 { 450 validFDCheck, 451 seccomp.MatchAny{}, 452 }, 453 }, 454 unix.SYS_READLINKAT: []seccomp.Rule{ 455 { 456 validFDCheck, 457 seccomp.MatchAny{}, 458 seccomp.MatchAny{}, 459 seccomp.MatchAny{}, 460 }, 461 }, 462 unix.SYS_UTIMENSAT: []seccomp.Rule{ 463 { 464 validFDCheck, 465 seccomp.MatchAny{}, 466 seccomp.MatchAny{}, 467 seccomp.MatchAny{}, 468 }, 469 }, 470 unix.SYS_RENAMEAT: []seccomp.Rule{ 471 { 472 validFDCheck, 473 seccomp.MatchAny{}, 474 validFDCheck, 475 seccomp.MatchAny{}, 476 }, 477 }, 478 archFstatAtSysNo(): []seccomp.Rule{ 479 { 480 validFDCheck, 481 seccomp.MatchAny{}, 482 seccomp.MatchAny{}, 483 seccomp.MatchAny{}, 484 }, 485 }, 486 } 487 }