github.com/iDigitalFlame/xmt@v0.5.4/device/cpu_other_nix_crypt.go (about)

     1  //go:build !amd64 && !386 && !windows && crypt
     2  // +build !amd64,!386,!windows,crypt
     3  
     4  // Copyright (C) 2020 - 2023 iDigitalFlame
     5  //
     6  // This program is free software: you can redistribute it and/or modify
     7  // it under the terms of the GNU General Public License as published by
     8  // the Free Software Foundation, either version 3 of the License, or
     9  // any later version.
    10  //
    11  // This program is distributed in the hope that it will be useful,
    12  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  // GNU General Public License for more details.
    15  //
    16  // You should have received a copy of the GNU General Public License
    17  // along with this program.  If not, see <https://www.gnu.org/licenses/>.
    18  //
    19  
    20  package device
    21  
    22  import (
    23  	"bytes"
    24  	"os"
    25  	"strings"
    26  
    27  	"github.com/iDigitalFlame/xmt/data"
    28  	"github.com/iDigitalFlame/xmt/util/crypt"
    29  )
    30  
    31  func isVirtual() bool {
    32  	// Check for a container first
    33  	// OpenVZ
    34  	if _, err := os.Lstat(crypt.Get(49)); err == nil { // /proc/vz
    35  		if _, err := os.Lstat(crypt.Get(50)); err != nil { // /proc/bc
    36  			return true
    37  		}
    38  	}
    39  	// Docker
    40  	if _, err := os.Lstat(crypt.Get(51)); err == nil { // /.dockerenv
    41  		return true
    42  	}
    43  	if _, err := os.Lstat(crypt.Get(52)); err == nil { // /run/.containerenv
    44  		return true
    45  	}
    46  	// systemd-nspawn
    47  	if _, err := os.Lstat(crypt.Get(53)); err == nil { // /run/systemd/container
    48  		return true
    49  	}
    50  	// WSL
    51  	if b, _ := data.ReadFile(crypt.Get(54)); len(b) > 0 { // /proc/sys/kernel/osrelease
    52  		if x := bytes.IndexByte(b, 'M'); x > -1 && x+8 < len(b) {
    53  			// Microsoft
    54  			if (b[x+1] == 'I' || b[x+1] == 'i') && (b[x+2] == 'C' || b[x+2] == 'c') && (b[x+3] == 'R' || b[x+3] == 'r') && (b[x+4] == 'O' || b[x+4] == 'o') {
    55  				return true
    56  			}
    57  		}
    58  		if x := bytes.IndexByte(b, 'W'); x > -1 && x+2 < len(b) {
    59  			// WSL
    60  			if (b[x+1] == 'S' || b[x+1] == 's') && (b[x+2] == 'L' || b[x+2] == 'l') {
    61  				return true
    62  			}
    63  		}
    64  	}
    65  	// PROOT
    66  	var n string
    67  	for _, v := range data.ReadSplit(crypt.Get(34), "\n") { // /proc/self/status
    68  		if len(v) == 0 || (v[0] != 'T' && v[0] != 't') {
    69  			continue
    70  		}
    71  		// TracerPid
    72  		if (v[1] != 'R' && v[1] != 'r') || (v[3] != 'C' && v[3] != 'c') || (v[6] != 'P' && v[6] != 'p') || (v[8] != 'D' && v[8] != 'd') {
    73  			continue
    74  		}
    75  		x := strings.IndexByte(v, ':')
    76  		if x < 8 {
    77  			continue
    78  		}
    79  		n = strings.TrimSpace(v[x+1:])
    80  		break
    81  	}
    82  	if len(n) > 0 {
    83  		p, _ := data.ReadFile(
    84  			crypt.Get(11) + n + // /proc/
    85  				crypt.Get(55), // /comm
    86  		)
    87  		if len(p) > 0 {
    88  			// proot
    89  			if (p[0] == 'P' || p[0] == 'p') && (p[1] == 'R' || p[1] == 'r') && (p[2] == 'O' || p[2] == 'o') && (p[4] == 'T' || p[8] == 't') {
    90  				return true
    91  			}
    92  		}
    93  	}
    94  	if os.Getpid() == 1 {
    95  		if k, ok := os.LookupEnv(crypt.Get(56)); ok && len(k) > 0 { // CONTAINER
    96  			return true
    97  		}
    98  	}
    99  	if b, _ := data.ReadFile(crypt.Get(57)); len(b) > 0 { // /proc/1/environ
   100  		for s, e, n := 0, 0, 0; e < len(b); e++ {
   101  			if b[e] != 0 {
   102  				continue
   103  			}
   104  			if e-s > 9 {
   105  				// CONTAINER=
   106  				if b[s] == 'C' && b[s+1] == 'O' && b[s+2] == 'N' && b[s+7] == 'N' && b[s+9] == 'R' && b[s+10] == '=' {
   107  					return true
   108  				}
   109  			}
   110  			s, n = e+1, n+1
   111  		}
   112  	}
   113  	// User Mode Linux
   114  	for _, v := range data.ReadSplit(crypt.Get(58), "\n") { // /proc/cpuinfo
   115  		if len(v) == 0 || (v[0] != 'V' && v[0] != 'v') {
   116  			continue
   117  		}
   118  		// vendor_id
   119  		if (v[1] != 'E' && v[1] != 'e') || (v[3] != 'D' && v[3] != 'd') || v[6] != '_' || (v[7] != 'I' && v[7] != 'i') {
   120  			continue
   121  		}
   122  		x := strings.IndexByte(v, ':')
   123  		if x < 8 {
   124  			continue
   125  		}
   126  		if n := strings.TrimSpace(v[x+1:]); len(n) >= 15 && (n[0] == 'U' || n[0] == 'u') && (n[5] == 'M' || n[5] == 'm') && (n[8] == 'E' || n[8] == 'e') && (n[10] == 'L' || n[10] == 'l') {
   127  			return true
   128  		}
   129  	}
   130  	// Check DMI
   131  	return checkVendorFile(crypt.Get(59)) || // /sys/class/dmi/id/sys_vendor
   132  		checkVendorFile(crypt.Get(60)) || // /sys/class/dmi/id/board_vendor
   133  		checkVendorFile(crypt.Get(61)) || // /sys/class/dmi/id/bios_vendor
   134  		checkVendorFile(crypt.Get(62)) // /sys/class/dmi/id/product_version
   135  }
   136  func checkVendorFile(s string) bool {
   137  	if b, _ := data.ReadFile(s); len(b) > 0 {
   138  		return isKnownVendor(bytes.TrimSpace(b))
   139  	}
   140  	return false
   141  }