github.com/MerlinKodo/gvisor@v0.0.0-20231110090155-957f62ecf90e/pkg/sentry/inet/namespace.go (about)

     1  // Copyright 2020 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 inet
    16  
    17  import (
    18  	"github.com/MerlinKodo/gvisor/pkg/context"
    19  	"github.com/MerlinKodo/gvisor/pkg/sentry/fsimpl/nsfs"
    20  	"github.com/MerlinKodo/gvisor/pkg/sentry/kernel/auth"
    21  )
    22  
    23  // Namespace represents a network namespace. See network_namespaces(7).
    24  //
    25  // +stateify savable
    26  type Namespace struct {
    27  	inode *nsfs.Inode
    28  
    29  	// stack is the network stack implementation of this network namespace.
    30  	stack Stack `state:"nosave"`
    31  
    32  	// creator allows kernel to create new network stack for network namespaces.
    33  	// If nil, no networking will function if network is namespaced.
    34  	//
    35  	// At afterLoad(), creator will be used to create network stack. Stateify
    36  	// needs to wait for this field to be loaded before calling afterLoad().
    37  	creator NetworkStackCreator `state:"wait"`
    38  
    39  	// isRoot indicates whether this is the root network namespace.
    40  	isRoot bool
    41  
    42  	userNS *auth.UserNamespace
    43  }
    44  
    45  // NewRootNamespace creates the root network namespace, with creator
    46  // allowing new network namespaces to be created. If creator is nil, no
    47  // networking will function if the network is namespaced.
    48  func NewRootNamespace(stack Stack, creator NetworkStackCreator, userNS *auth.UserNamespace) *Namespace {
    49  	n := &Namespace{
    50  		stack:   stack,
    51  		creator: creator,
    52  		isRoot:  true,
    53  		userNS:  userNS,
    54  	}
    55  	return n
    56  }
    57  
    58  // UserNamespace returns the user namespace associated with this namespace.
    59  func (n *Namespace) UserNamespace() *auth.UserNamespace {
    60  	return n.userNS
    61  }
    62  
    63  // SetInode sets the nsfs `inode` to the namespace.
    64  func (n *Namespace) SetInode(inode *nsfs.Inode) {
    65  	n.inode = inode
    66  }
    67  
    68  // GetInode returns the nsfs inode associated with this namespace.
    69  func (n *Namespace) GetInode() *nsfs.Inode {
    70  	return n.inode
    71  }
    72  
    73  // NewNamespace creates a new network namespace from the root.
    74  func NewNamespace(root *Namespace, userNS *auth.UserNamespace) *Namespace {
    75  	n := &Namespace{
    76  		creator: root.creator,
    77  		userNS:  userNS,
    78  	}
    79  	n.init()
    80  	return n
    81  }
    82  
    83  // Destroy implements nsfs.Namespace.Destroy.
    84  func (n *Namespace) Destroy(ctx context.Context) {
    85  	if s := n.Stack(); s != nil {
    86  		s.Destroy()
    87  	}
    88  }
    89  
    90  // Type implements nsfs.Namespace.Type.
    91  func (n *Namespace) Type() string {
    92  	return "net"
    93  }
    94  
    95  // IncRef increments the Namespace's refcount.
    96  func (n *Namespace) IncRef() {
    97  	n.inode.IncRef()
    98  }
    99  
   100  // DecRef decrements the Namespace's refcount.
   101  func (n *Namespace) DecRef(ctx context.Context) {
   102  	n.inode.DecRef(ctx)
   103  }
   104  
   105  // Stack returns the network stack of n. Stack may return nil if no network
   106  // stack is configured.
   107  func (n *Namespace) Stack() Stack {
   108  	return n.stack
   109  }
   110  
   111  // IsRoot returns whether n is the root network namespace.
   112  func (n *Namespace) IsRoot() bool {
   113  	return n.isRoot
   114  }
   115  
   116  // RestoreRootStack restores the root network namespace with stack. This should
   117  // only be called when restoring kernel.
   118  func (n *Namespace) RestoreRootStack(stack Stack) {
   119  	if !n.isRoot {
   120  		panic("RestoreRootStack can only be called on root network namespace")
   121  	}
   122  	if n.stack != nil {
   123  		panic("RestoreRootStack called after a stack has already been set")
   124  	}
   125  	n.stack = stack
   126  }
   127  
   128  func (n *Namespace) init() {
   129  	// Root network namespace will have stack assigned later.
   130  	if n.isRoot {
   131  		return
   132  	}
   133  	if n.creator != nil {
   134  		var err error
   135  		n.stack, err = n.creator.CreateStack()
   136  		if err != nil {
   137  			panic(err)
   138  		}
   139  	}
   140  }
   141  
   142  // afterLoad is invoked by stateify.
   143  func (n *Namespace) afterLoad() {
   144  	n.init()
   145  }
   146  
   147  // NetworkStackCreator allows new instances of a network stack to be created. It
   148  // is used by the kernel to create new network namespaces when requested.
   149  type NetworkStackCreator interface {
   150  	// CreateStack creates a new network stack for a network namespace.
   151  	CreateStack() (Stack, error)
   152  }