github.com/moby/docker@v26.1.3+incompatible/daemon/exec_linux.go (about)

     1  package daemon // import "github.com/docker/docker/daemon"
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/containerd/containerd"
     7  	coci "github.com/containerd/containerd/oci"
     8  	"github.com/containerd/containerd/pkg/apparmor"
     9  	"github.com/docker/docker/container"
    10  	"github.com/docker/docker/daemon/config"
    11  	"github.com/docker/docker/oci/caps"
    12  	specs "github.com/opencontainers/runtime-spec/specs-go"
    13  )
    14  
    15  func getUserFromContainerd(ctx context.Context, containerdCli *containerd.Client, ec *container.ExecConfig) (specs.User, error) {
    16  	ctr, err := containerdCli.LoadContainer(ctx, ec.Container.ID)
    17  	if err != nil {
    18  		return specs.User{}, err
    19  	}
    20  
    21  	cinfo, err := ctr.Info(ctx)
    22  	if err != nil {
    23  		return specs.User{}, err
    24  	}
    25  
    26  	spec, err := ctr.Spec(ctx)
    27  	if err != nil {
    28  		return specs.User{}, err
    29  	}
    30  
    31  	opts := []coci.SpecOpts{
    32  		coci.WithUser(ec.User),
    33  		coci.WithAdditionalGIDs(ec.User),
    34  		coci.WithAppendAdditionalGroups(ec.Container.HostConfig.GroupAdd...),
    35  	}
    36  	for _, opt := range opts {
    37  		if err := opt(ctx, containerdCli, &cinfo, spec); err != nil {
    38  			return specs.User{}, err
    39  		}
    40  	}
    41  
    42  	return spec.Process.User, nil
    43  }
    44  
    45  func (daemon *Daemon) execSetPlatformOpt(ctx context.Context, daemonCfg *config.Config, ec *container.ExecConfig, p *specs.Process) error {
    46  	if len(ec.User) > 0 {
    47  		var err error
    48  		if daemon.UsesSnapshotter() {
    49  			p.User, err = getUserFromContainerd(ctx, daemon.containerdClient, ec)
    50  			if err != nil {
    51  				return err
    52  			}
    53  		} else {
    54  			p.User, err = getUser(ec.Container, ec.User)
    55  			if err != nil {
    56  				return err
    57  			}
    58  		}
    59  	}
    60  
    61  	if ec.Privileged {
    62  		p.Capabilities = &specs.LinuxCapabilities{
    63  			Bounding:  caps.GetAllCapabilities(),
    64  			Permitted: caps.GetAllCapabilities(),
    65  			Effective: caps.GetAllCapabilities(),
    66  		}
    67  	}
    68  
    69  	if apparmor.HostSupports() {
    70  		var appArmorProfile string
    71  		if ec.Container.AppArmorProfile != "" {
    72  			appArmorProfile = ec.Container.AppArmorProfile
    73  		} else if ec.Container.HostConfig.Privileged {
    74  			// `docker exec --privileged` does not currently disable AppArmor
    75  			// profiles. Privileged configuration of the container is inherited
    76  			appArmorProfile = unconfinedAppArmorProfile
    77  		} else {
    78  			appArmorProfile = defaultAppArmorProfile
    79  		}
    80  
    81  		if appArmorProfile == defaultAppArmorProfile {
    82  			// Unattended upgrades and other fun services can unload AppArmor
    83  			// profiles inadvertently. Since we cannot store our profile in
    84  			// /etc/apparmor.d, nor can we practically add other ways of
    85  			// telling the system to keep our profile loaded, in order to make
    86  			// sure that we keep the default profile enabled we dynamically
    87  			// reload it if necessary.
    88  			if err := ensureDefaultAppArmorProfile(); err != nil {
    89  				return err
    90  			}
    91  		}
    92  		p.ApparmorProfile = appArmorProfile
    93  	}
    94  	s := &specs.Spec{Process: p}
    95  	return withRlimits(daemon, daemonCfg, ec.Container)(ctx, nil, nil, s)
    96  }