@@ -847,51 +847,6 @@ func (c *Container) generateSpec(ctx context.Context) (s *spec.Spec, cleanupFunc
847847 return g .Config , cleanupFunc , nil
848848}
849849
850- // isWorkDirSymlink returns true if resolved workdir is symlink or a chain of symlinks,
851- // and final resolved target is present either on volume, mount or inside of container
852- // otherwise it returns false. Following function is meant for internal use only and
853- // can change at any point of time.
854- func (c * Container ) isWorkDirSymlink (resolvedPath string ) bool {
855- // We cannot create workdir since explicit --workdir is
856- // set in config but workdir could also be a symlink.
857- // If it's a symlink, check if the resolved target is present in the container.
858- // If so, that's a valid use case: return nil.
859-
860- maxSymLinks := 0
861- // Linux only supports a chain of 40 links.
862- // Reference: https://github.com/torvalds/linux/blob/master/include/linux/namei.h#L13
863- for maxSymLinks <= 40 {
864- resolvedSymlink , err := os .Readlink (resolvedPath )
865- if err != nil {
866- // End sym-link resolution loop.
867- break
868- }
869- if resolvedSymlink != "" {
870- _ , resolvedSymlinkWorkdir , _ , err := c .resolvePath (c .state .Mountpoint , resolvedSymlink )
871- if isPathOnVolume (c , resolvedSymlinkWorkdir ) || isPathOnMount (c , resolvedSymlinkWorkdir ) {
872- // Resolved symlink exists on external volume or mount
873- return true
874- }
875- if err != nil {
876- // Could not resolve path so end sym-link resolution loop.
877- break
878- }
879- if resolvedSymlinkWorkdir != "" {
880- resolvedPath = resolvedSymlinkWorkdir
881- err := fileutils .Exists (resolvedSymlinkWorkdir )
882- if err == nil {
883- // Symlink resolved successfully and resolved path exists on container,
884- // this is a valid use-case so return nil.
885- logrus .Debugf ("Workdir is a symlink with target to %q and resolved symlink exists on container" , resolvedSymlink )
886- return true
887- }
888- }
889- }
890- maxSymLinks ++
891- }
892- return false
893- }
894-
895850// resolveWorkDir resolves the container's workdir and, depending on the
896851// configuration, will create it, or error out if it does not exist.
897852// Note that the container must be mounted before.
@@ -906,7 +861,7 @@ func (c *Container) resolveWorkDir() error {
906861 return nil
907862 }
908863
909- _ , resolvedWorkdir , _ , err := c . resolvePath (c .state .Mountpoint , workdir )
864+ resolvedWorkdir , err := securejoin . SecureJoin (c .state .Mountpoint , workdir )
910865 if err != nil {
911866 return err
912867 }
@@ -923,18 +878,27 @@ func (c *Container) resolveWorkDir() error {
923878 // No need to create it (e.g., `--workdir=/foo`), so let's make sure
924879 // the path exists on the container.
925880 if errors .Is (err , os .ErrNotExist ) {
926- // If resolved Workdir path gets marked as a valid symlink,
927- // return nil cause this is valid use-case.
928- if c .isWorkDirSymlink (resolvedWorkdir ) {
881+ // Check if path is a symlink, securejoin resolves and follows the links
882+ // so the path will be different from the normal join if it is one.
883+ if resolvedWorkdir != filepath .Join (c .state .Mountpoint , workdir ) {
884+ // Path must be a symlink to non existing directory.
885+ // It could point to mounts that are only created later so that make
886+ // an assumption here and let's just continue and let the oci runtime
887+ // do its job.
929888 return nil
930889 }
890+ // If they are the same we know there is no symlink/relative path involved.
891+ // We can return a nicer error message without having to go through the OCI runtime.
931892 return fmt .Errorf ("workdir %q does not exist on container %s" , workdir , c .ID ())
932893 }
933894 // This might be a serious error (e.g., permission), so
934895 // we need to return the full error.
935896 return fmt .Errorf ("detecting workdir %q on container %s: %w" , workdir , c .ID (), err )
936897 }
937898 if err := os .MkdirAll (resolvedWorkdir , 0o755 ); err != nil {
899+ if errors .Is (err , fs .ErrExist ) {
900+ return nil
901+ }
938902 return fmt .Errorf ("creating container %s workdir: %w" , c .ID (), err )
939903 }
940904
0 commit comments