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  }