@@ -23,6 +23,7 @@ import (
2323 "gvisor.dev/gvisor/pkg/log"
2424 "gvisor.dev/gvisor/pkg/refs"
2525 "gvisor.dev/gvisor/pkg/sentry/inet"
26+ "gvisor.dev/gvisor/pkg/sentry/kernel/auth"
2627 "gvisor.dev/gvisor/pkg/sentry/socket/netlink/nlmsg"
2728 "gvisor.dev/gvisor/pkg/syserr"
2829 "gvisor.dev/gvisor/pkg/tcpip"
@@ -253,7 +254,10 @@ func (s *Stack) SetInterface(ctx context.Context, msg *nlmsg.Message) *syserr.Er
253254//
254255// If instead the linkAttrs map does not contain IFLA_NET_NS_FD, or if it
255256// points to the same netns as the source stack, only locks the source stack
256- // and returns nil. And if the netns fd is invalid, returns an error.
257+ // and returns nil.
258+ //
259+ // If the netns fd is invalid, or the calling context lacks CAP_NET_ADMIN,
260+ // returns an error.
257261func (s * Stack ) lockSrcAndDst (ctx context.Context , linkAttrs map [uint16 ]nlmsg.BytesView ) (* inet.Namespace , * syserr.Error ) {
258262 if linkAttrs == nil {
259263 s .linkMu .Lock ()
@@ -273,17 +277,22 @@ func (s *Stack) lockSrcAndDst(ctx context.Context, linkAttrs map[uint16]nlmsg.By
273277 if f == nil {
274278 return nil , syserr .ErrInvalidArgument
275279 }
276- ns , err := f (int32 (fd )) // ns.DecRef() is called in unlockSrcAndDst().
280+ ns , err := f (int32 (fd ))
277281 if err != nil {
278282 return nil , syserr .FromError (err )
279283 }
284+ if ! auth .CredentialsFromContext (ctx ).HasCapabilityIn (linux .CAP_NET_ADMIN , ns .UserNamespace ()) {
285+ ns .DecRef (ctx )
286+ return nil , syserr .ErrNotPermittedNet
287+ }
280288
281289 dst := ns .Stack ().(* Stack )
282290 if s == dst {
283291 ns .DecRef (ctx )
284292 s .linkMu .Lock ()
285293 return nil , nil
286294 }
295+ // No failures from this point on, ns.DecRef() is called in unlockSrcAndDst().
287296
288297 if s .id < dst .id {
289298 s .linkMu .Lock ()
0 commit comments