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