github.com/madlambda/nash@v0.2.2-0.20230113003044-f2284521680b/internal/sh/shell_linux_test.go (about)

     1  // +build linux
     2  
     3  package sh_test
     4  
     5  import (
     6  	"bytes"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"os"
    10  	"os/exec"
    11  	"strings"
    12  	"testing"
    13  )
    14  
    15  var (
    16  	enableUserNS bool
    17  )
    18  
    19  func init() {
    20  	const usernsOk = "1"
    21  	const kernelcfg = "CONFIG_USER_NS"
    22  
    23  	logUsernsDetection := func(err error) {
    24  		if enableUserNS {
    25  			fmt.Printf("Linux user namespaces enabled!")
    26  			return
    27  		}
    28  
    29  		fmt.Printf("Warning: Impossible to know if kernel support USER namespace.\n")
    30  		fmt.Printf("Warning: USER namespace tests will not run.\n")
    31  		if err != nil {
    32  			fmt.Printf("ERROR: %s\n", err)
    33  		}
    34  	}
    35  
    36  	usernsCfg := "/proc/sys/kernel/unprivileged_userns_clone"
    37  	val, permerr := ioutil.ReadFile(usernsCfg)
    38  
    39  	// Travis build doesn't support /proc/config.gz but kernel has userns
    40  	if os.Getenv("TRAVIS_BUILD") == "1" {
    41  		enableUserNS = permerr == nil && string(val) == usernsOk
    42  		logUsernsDetection(permerr)
    43  		return
    44  	}
    45  
    46  	if permerr == nil {
    47  		enableUserNS = string(val) == usernsOk
    48  		logUsernsDetection(permerr)
    49  		return
    50  	}
    51  
    52  	// old kernels dont have sysctl configurations
    53  	// than just checking the /proc/config suffices
    54  	usernsCmd := exec.Command("zgrep", kernelcfg, "/proc/config.gz")
    55  
    56  	content, err := usernsCmd.CombinedOutput()
    57  	if err != nil {
    58  		enableUserNS = false
    59  		logUsernsDetection(fmt.Errorf("Failed to get kernel config: %s", err))
    60  		return
    61  	}
    62  
    63  	cfgVal := strings.Trim(string(content), "\n\t ")
    64  	enableUserNS = cfgVal == kernelcfg+"=y"
    65  	logUsernsDetection(fmt.Errorf("%s not enabled in kernel config", kernelcfg))
    66  }
    67  
    68  func TestExecuteRforkUserNS(t *testing.T) {
    69  	if !enableUserNS {
    70  		t.Skip("User namespace not enabled")
    71  		return
    72  	}
    73  
    74  	f, teardown := setup(t)
    75  	defer teardown()
    76  
    77  	err := f.shell.Exec("rfork test", `
    78          rfork u {
    79              id -u
    80          }
    81          `)
    82  
    83  	if err != nil {
    84  		t.Error(err)
    85  		return
    86  	}
    87  
    88  	if string(f.shellOut.Bytes()) != "0\n" {
    89  		t.Errorf("User namespace not supported in your kernel: %s", string(f.shellOut.Bytes()))
    90  		return
    91  	}
    92  }
    93  
    94  func TestExecuteRforkEnvVars(t *testing.T) {
    95  	if !enableUserNS {
    96  		t.Skip("User namespace not enabled")
    97  		return
    98  	}
    99  
   100  	f, teardown := setup(t)
   101  	defer teardown()
   102  
   103  	sh := f.shell
   104  
   105  	err := sh.Exec("test env", `var abra = "cadabra"
   106  setenv abra
   107  rfork up {
   108  	echo $abra
   109  }`)
   110  
   111  	if err != nil {
   112  		t.Error(err)
   113  		return
   114  	}
   115  }
   116  
   117  func TestExecuteRforkUserNSNested(t *testing.T) {
   118  	if !enableUserNS {
   119  		t.Skip("User namespace not enabled")
   120  		return
   121  	}
   122  
   123  	var out bytes.Buffer
   124  	f, teardown := setup(t)
   125  	defer teardown()
   126  
   127  	sh := f.shell
   128  
   129  	sh.SetStdout(&out)
   130  
   131  	err := sh.Exec("rfork userns nested", `
   132          rfork u {
   133              id -u
   134              rfork u {
   135                  id -u
   136              }
   137          }
   138          `)
   139  
   140  	if err != nil {
   141  		t.Error(err)
   142  		return
   143  	}
   144  
   145  	if string(out.Bytes()) != "0\n0\n" {
   146  		t.Errorf("User namespace not supported in your kernel")
   147  		return
   148  	}
   149  }