@@ -13,6 +13,7 @@ import (
13
13
containertypes "github.com/docker/docker/api/types/container"
14
14
"github.com/docker/docker/container"
15
15
daemonconfig "github.com/docker/docker/daemon/config"
16
+ "github.com/docker/docker/errdefs"
16
17
"github.com/docker/docker/oci"
17
18
"github.com/docker/docker/oci/caps"
18
19
"github.com/docker/docker/pkg/idtools"
@@ -637,18 +638,24 @@ func setMounts(daemon *Daemon, s *specs.Spec, c *container.Container, mounts []c
637
638
638
639
func (daemon * Daemon ) populateCommonSpec (s * specs.Spec , c * container.Container ) error {
639
640
if c .BaseFS == nil {
640
- return errors .New ("populateCommonSpec: BaseFS of container " + c .ID + " is unexpectedly nil" )
641
+ // Return System, because it's unlikely that the requester screwed
642
+ // something up to cause this
643
+ return errdefs .System (errors .New ("populateCommonSpec: BaseFS of container " + c .ID + " is unexpectedly nil" ))
641
644
}
642
645
linkedEnv , err := daemon .setupLinkedContainers (c )
643
646
if err != nil {
647
+ // all of the errors returned from setupLinkedContainers should already
648
+ // be of errdefs types, so we can safely return it raw.
644
649
return err
645
650
}
646
651
s .Root = & specs.Root {
647
652
Path : c .BaseFS .Path (),
648
653
Readonly : c .HostConfig .ReadonlyRootfs ,
649
654
}
650
655
if err := c .SetupWorkingDirectory (daemon .idMapping .RootPair ()); err != nil {
651
- return err
656
+ // all of the errors in SetupWorkingDirectory are not really the
657
+ // requester's fault, so return System
658
+ return errdefs .System (err )
652
659
}
653
660
cwd := c .Config .WorkingDir
654
661
if len (cwd ) == 0 {
@@ -667,7 +674,10 @@ func (daemon *Daemon) populateCommonSpec(s *specs.Spec, c *container.Container)
667
674
if path == "" {
668
675
path , err = exec .LookPath (daemonconfig .DefaultInitBinary )
669
676
if err != nil {
670
- return err
677
+ // If we can't find the daemon's default init, then that's
678
+ // a System error, because the configuration of the daemon
679
+ // is invalid, but not the user's request.
680
+ return errdefs .System (err )
671
681
}
672
682
}
673
683
s .Mounts = append (s .Mounts , specs.Mount {
@@ -695,8 +705,13 @@ func (daemon *Daemon) populateCommonSpec(s *specs.Spec, c *container.Container)
695
705
}
696
706
697
707
func (daemon * Daemon ) createSpec (c * container.Container ) (retSpec * specs.Spec , err error ) {
708
+ // NOTE(dperny): this method has been updated so that all errors returned
709
+ // are errdefs errors. most of the errors returned have been annotated with
710
+ // comments to explain the choice of error type.
698
711
s := oci .DefaultSpec ()
699
712
if err := daemon .populateCommonSpec (& s , c ); err != nil {
713
+ // all of the errors returned by populateCommonSpec are errdefs types,
714
+ // so we can safely return the error without wrapping it
700
715
return nil , err
701
716
}
702
717
@@ -723,7 +738,7 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
723
738
s .Linux .CgroupsPath = cgroupsPath
724
739
725
740
if err := setResources (& s , c .HostConfig .Resources ); err != nil {
726
- return nil , fmt .Errorf ("linux runtime spec resources: %v" , err )
741
+ return nil , errdefs . InvalidParameter ( fmt .Errorf ("linux runtime spec resources: %v" , err ) )
727
742
}
728
743
// We merge the sysctls injected above with the HostConfig (latter takes
729
744
// precedence for backwards-compatibility reasons).
@@ -733,13 +748,15 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
733
748
734
749
p := s .Linux .CgroupsPath
735
750
if useSystemd {
751
+ // these calls don't rely on any user input, so if they fails, that's
752
+ // on us, and we should return a System error
736
753
initPath , err := cgroups .GetInitCgroup ("cpu" )
737
754
if err != nil {
738
- return nil , err
755
+ return nil , errdefs . System ( err )
739
756
}
740
757
_ , err = cgroups .GetOwnCgroup ("cpu" )
741
758
if err != nil {
742
- return nil , err
759
+ return nil , errdefs . System ( err )
743
760
}
744
761
p = filepath .Join (initPath , s .Linux .CgroupsPath )
745
762
}
@@ -751,37 +768,56 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
751
768
}
752
769
753
770
if err := daemon .initCgroupsPath (parentPath ); err != nil {
754
- return nil , fmt .Errorf ("linux init cgroups path: %v" , err )
771
+ // all of the errors in initCgroupsPath are things like failing to make
772
+ // a directory, or are otherwise the result of a function call with
773
+ // hard-coded arguments, so return a System error if it fails.
774
+ return nil , errdefs .System (fmt .Errorf ("linux init cgroups path: %v" , err ))
755
775
}
756
776
if err := setDevices (& s , c ); err != nil {
757
- return nil , fmt .Errorf ("linux runtime spec devices: %v" , err )
777
+ // The errors resulting from devices are generally more of a
778
+ // user-configured-it-wrong error, so return InvalidParameter
779
+ return nil , errdefs .InvalidParameter (fmt .Errorf ("linux runtime spec devices: %v" , err ))
758
780
}
759
781
if err := daemon .setRlimits (& s , c ); err != nil {
760
- return nil , fmt .Errorf ("linux runtime spec rlimits: %v" , err )
782
+ // as of this writing, setRlimits doesn't return any errors at all, so
783
+ // we return error type Unknown if it happens.
784
+ return nil , errdefs .Unknown (fmt .Errorf ("linux runtime spec rlimits: %v" , err ))
761
785
}
762
786
if err := setUser (& s , c ); err != nil {
763
- return nil , fmt .Errorf ("linux spec user: %v" , err )
787
+ // setUser fails if you specify a bad user, so it's an InvalidParameter
788
+ return nil , errdefs .InvalidParameter (fmt .Errorf ("linux spec user: %v" , err ))
764
789
}
765
790
if err := setNamespaces (daemon , & s , c ); err != nil {
766
- return nil , fmt .Errorf ("linux spec namespaces: %v" , err )
791
+ // setNamespaces has been fixed to return all errdefs errors, so we
792
+ // don't need to choose one here. additionally, the errdefs package is
793
+ // aware of the "causer" interface from github.com/pkg/errors, so we
794
+ // can safely wrap this error so that the actual error message still
795
+ // starts with "linux spec namespaces"
796
+ return nil , errors .Wrap (err , "linux spec namespaces" )
767
797
}
768
798
capabilities , err := caps .TweakCapabilities (oci .DefaultCapabilities (), c .HostConfig .CapAdd , c .HostConfig .CapDrop , c .HostConfig .Capabilities , c .HostConfig .Privileged )
769
799
if err != nil {
770
- return nil , fmt .Errorf ("linux spec capabilities: %v" , err )
800
+ // caps.TweakCapabilities also uses all errdefs errors
801
+ return nil , errors .Wrap (err , "linux spec capabilities" )
771
802
}
772
803
if err := oci .SetCapabilities (& s , capabilities ); err != nil {
773
- return nil , fmt .Errorf ("linux spec capabilities: %v" , err )
804
+ // SetCapabilities returned no error in this revision, so if it fails,
805
+ // we don't know why
806
+ return nil , errdefs .Unknown (fmt .Errorf ("linux spec capabilities: %v" , err ))
774
807
}
775
808
if err := setSeccomp (daemon , & s , c ); err != nil {
776
- return nil , fmt .Errorf ("linux seccomp: %v" , err )
809
+ // if setting Seccomp fails, then it's probably your fault.
810
+ return nil , errdefs .InvalidParameter (fmt .Errorf ("linux seccomp: %v" , err ))
777
811
}
778
812
779
813
if err := daemon .setupContainerMountsRoot (c ); err != nil {
780
- return nil , err
814
+ // it shouldn't be the user's fault if this fails.
815
+ return nil , errdefs .System (err )
781
816
}
782
817
783
818
if err := daemon .setupIpcDirs (c ); err != nil {
784
- return nil , err
819
+ // this will fail if the user configures it wrongly
820
+ return nil , errdefs .InvalidParameter (err )
785
821
}
786
822
787
823
defer func () {
@@ -790,13 +826,16 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
790
826
}
791
827
}()
792
828
829
+ // the next several calls only return System errors, because their failures
830
+ // are not really caused by user input.
831
+
793
832
if err := daemon .setupSecretDir (c ); err != nil {
794
- return nil , err
833
+ return nil , errdefs . System ( err )
795
834
}
796
835
797
836
ms , err := daemon .setupMounts (c )
798
837
if err != nil {
799
- return nil , err
838
+ return nil , errdefs . System ( err )
800
839
}
801
840
802
841
if ! c .HostConfig .IpcMode .IsPrivate () && ! c .HostConfig .IpcMode .IsEmpty () {
@@ -805,19 +844,19 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
805
844
806
845
tmpfsMounts , err := c .TmpfsMounts ()
807
846
if err != nil {
808
- return nil , err
847
+ return nil , errdefs . System ( err )
809
848
}
810
849
ms = append (ms , tmpfsMounts ... )
811
850
812
851
secretMounts , err := c .SecretMounts ()
813
852
if err != nil {
814
- return nil , err
853
+ return nil , errdefs . System ( err )
815
854
}
816
855
ms = append (ms , secretMounts ... )
817
856
818
857
sort .Sort (mounts (ms ))
819
858
if err := setMounts (daemon , & s , c , ms ); err != nil {
820
- return nil , fmt .Errorf ("linux mounts: %v" , err )
859
+ return nil , errdefs . System ( fmt .Errorf ("linux mounts: %v" , err ) )
821
860
}
822
861
823
862
for _ , ns := range s .Linux .Namespaces {
@@ -850,7 +889,7 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
850
889
// sure that we keep the default profile enabled we dynamically
851
890
// reload it if necessary.
852
891
if err := ensureDefaultAppArmorProfile (); err != nil {
853
- return nil , err
892
+ return nil , errdefs . System ( err )
854
893
}
855
894
}
856
895
@@ -871,7 +910,9 @@ func (daemon *Daemon) createSpec(c *container.Container) (retSpec *specs.Spec, e
871
910
872
911
if daemon .configStore .Rootless {
873
912
if err := specconv .ToRootless (& s ); err != nil {
874
- return nil , err
913
+ // in the current revision, ToRootless doesn't return any known
914
+ // error.
915
+ return nil , errdefs .Unknown (err )
875
916
}
876
917
}
877
918
return & s , nil
0 commit comments