@@ -22,6 +22,7 @@ import (
2222 "encoding/json"
2323 "errors"
2424 "fmt"
25+ "math"
2526 "os"
2627 "path/filepath"
2728 "runtime"
@@ -593,6 +594,20 @@ func WithUser(userstr string) SpecOpts {
593594 defer ensureAdditionalGids (s )
594595 setProcess (s )
595596 s .Process .User .AdditionalGids = nil
597+ // While the Linux kernel allows the max UID to be MaxUint32 - 2,
598+ // and the OCI Runtime Spec has no definition about the max UID,
599+ // the runc implementation is known to require the UID to be <= MaxInt32.
600+ //
601+ // containerd follows runc's limitation here.
602+ //
603+ // In future we may relax this limitation to allow MaxUint32 - 2,
604+ // or, amend the OCI Runtime Spec to codify the implementation limitation.
605+ const (
606+ minUserID = 0
607+ maxUserID = math .MaxInt32
608+ minGroupID = 0
609+ maxGroupID = math .MaxInt32
610+ )
596611
597612 // For LCOW it's a bit harder to confirm that the user actually exists on the host as a rootfs isn't
598613 // mounted on the host and shared into the guest, but rather the rootfs is constructed entirely in the
@@ -611,8 +626,8 @@ func WithUser(userstr string) SpecOpts {
611626 switch len (parts ) {
612627 case 1 :
613628 v , err := strconv .Atoi (parts [0 ])
614- if err != nil {
615- // if we cannot parse as a uint they try to see if it is a username
629+ if err != nil || v < minUserID || v > maxUserID {
630+ // if we cannot parse as an int32 then try to see if it is a username
616631 return WithUsername (userstr )(ctx , client , c , s )
617632 }
618633 return WithUserID (uint32 (v ))(ctx , client , c , s )
@@ -623,12 +638,13 @@ func WithUser(userstr string) SpecOpts {
623638 )
624639 var uid , gid uint32
625640 v , err := strconv .Atoi (parts [0 ])
626- if err != nil {
641+ if err != nil || v < minUserID || v > maxUserID {
627642 username = parts [0 ]
628643 } else {
629644 uid = uint32 (v )
630645 }
631- if v , err = strconv .Atoi (parts [1 ]); err != nil {
646+ v , err = strconv .Atoi (parts [1 ])
647+ if err != nil || v < minGroupID || v > maxGroupID {
632648 groupname = parts [1 ]
633649 } else {
634650 gid = uint32 (v )
0 commit comments