github.com/iDigitalFlame/xmt@v0.5.4/device/cpu_other_nix_no_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  )
    29  
    30  func isVirtual() bool {
    31  	// Check for a container first
    32  	// OpenVZ
    33  	if _, err := os.Lstat("/proc/vz"); err == nil {
    34  		if _, err := os.Lstat("/proc/bc"); err != nil {
    35  			return true
    36  		}
    37  	}
    38  	// Docker
    39  	if _, err := os.Lstat("/.dockerenv"); err == nil {
    40  		return true
    41  	}
    42  	if _, err := os.Lstat("/run/.containerenv"); err == nil {
    43  		return true
    44  	}
    45  	// systemd-nspawn
    46  	if _, err := os.Lstat("/run/systemd/container"); err == nil {
    47  		return true
    48  	}
    49  	// WSL
    50  	if b, _ := data.ReadFile("/proc/sys/kernel/osrelease"); len(b) > 0 {
    51  		if x := bytes.IndexByte(b, 'M'); x > -1 && x+8 < len(b) {
    52  			// Microsoft
    53  			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') {
    54  				return true
    55  			}
    56  		}
    57  		if x := bytes.IndexByte(b, 'W'); x > -1 && x+2 < len(b) {
    58  			// WSL
    59  			if (b[x+1] == 'S' || b[x+1] == 's') && (b[x+2] == 'L' || b[x+2] == 'l') {
    60  				return true
    61  			}
    62  		}
    63  	}
    64  	// PROOT
    65  	var n string
    66  	for _, v := range data.ReadSplit("/proc/self/status", "\n") {
    67  		if len(v) == 0 || (v[0] != 'T' && v[0] != 't') {
    68  			continue
    69  		}
    70  		// TracerPid
    71  		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') {
    72  			continue
    73  		}
    74  		x := strings.IndexByte(v, ':')
    75  		if x < 8 {
    76  			continue
    77  		}
    78  		n = strings.TrimSpace(v[x+1:])
    79  		break
    80  	}
    81  	if len(n) > 0 {
    82  		if p, _ := data.ReadFile("/proc/" + n + "/comm"); len(p) > 0 {
    83  			// proot
    84  			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') {
    85  				return true
    86  			}
    87  		}
    88  	}
    89  	if os.Getpid() == 1 {
    90  		if k, ok := os.LookupEnv("CONTAINER"); ok && len(k) > 0 {
    91  			return true
    92  		}
    93  	}
    94  	if b, _ := data.ReadFile("/proc/1/environ"); len(b) > 0 {
    95  		for s, e, n := 0, 0, 0; e < len(b); e++ {
    96  			if b[e] != 0 {
    97  				continue
    98  			}
    99  			if e-s > 9 {
   100  				// CONTAINER=
   101  				if b[s] == 'C' && b[s+1] == 'O' && b[s+2] == 'N' && b[s+7] == 'N' && b[s+9] == 'R' && b[s+10] == '=' {
   102  					return true
   103  				}
   104  			}
   105  			s, n = e+1, n+1
   106  		}
   107  	}
   108  	// User Mode Linux
   109  	for _, v := range data.ReadSplit("/proc/cpuinfo", "\n") {
   110  		if len(v) == 0 || (v[0] != 'V' && v[0] != 'v') {
   111  			continue
   112  		}
   113  		// vendor_id
   114  		if (v[1] != 'E' && v[1] != 'e') || (v[3] != 'D' && v[3] != 'd') || v[6] != '_' || (v[7] != 'I' && v[7] != 'i') {
   115  			continue
   116  		}
   117  		x := strings.IndexByte(v, ':')
   118  		if x < 8 {
   119  			continue
   120  		}
   121  		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') {
   122  			return true
   123  		}
   124  	}
   125  	// Check DMI
   126  	return checkVendorFile("/sys/class/dmi/id/sys_vendor") ||
   127  		checkVendorFile("/sys/class/dmi/id/board_vendor") ||
   128  		checkVendorFile("/sys/class/dmi/id/bios_vendor") ||
   129  		checkVendorFile("/sys/class/dmi/id/product_version")
   130  }
   131  func checkVendorFile(s string) bool {
   132  	if b, _ := data.ReadFile(s); len(b) > 0 {
   133  		return isKnownVendor(bytes.TrimSpace(b))
   134  	}
   135  	return false
   136  }