Repository: opencontainers/runc
File: exec.go (Go)

Code before:
	// process via cli flags
	if err := os.Chdir(bundle); err != nil {
		return nil, err
	}
	spec, err := loadSpec(specConfig)
	if err != nil {
		return nil, err
	}
	p := spec.Process
	p.Args = context.Args()[1:]
	// Override the cwd, if passed.
	if cwd := context.String("cwd"); cwd != "" {
		p.Cwd = cwd
	}
	if ap := context.String("apparmor"); ap != "" {
		p.ApparmorProfile = ap
	}
	if l := context.String("process-label"); l != "" {
		p.SelinuxLabel = l
	}
	if caps := context.StringSlice("cap"); len(caps) > 0 {
		for _, c := range caps {
			p.Capabilities.Bounding = append(p.Capabilities.Bounding, c)
			p.Capabilities.Effective = append(p.Capabilities.Effective, c)
			p.Capabilities.Permitted = append(p.Capabilities.Permitted, c)
		}
	}
	// append the passed env variables
	p.Env = append(p.Env, context.StringSlice("env")...)

	// Always set tty to false, unless explicitly enabled from CLI.
	p.Terminal = context.Bool("tty")
	if context.IsSet("no-new-privs") {
		p.NoNewPrivileges = context.Bool("no-new-privs")
	}
	// Override the user, if passed.
	if user := context.String("user"); user != "" {
		u := strings.SplitN(user, ":", 2)
		if len(u) > 1 {
			gid, err := strconv.Atoi(u[1])
			if err != nil {
				return nil, fmt.Errorf("bad gid: %w", err)
			}
			p.User.GID = uint32(gid)
		}
		uid, err := strconv.Atoi(u[0])
		if err != nil {
			return nil, fmt.Errorf("bad uid: %w", err)
		}
		p.User.UID = uint32(uid)
	}

Review comment (suggestion):
I think we should add a check here:
```
if p.Capabilities.Inheritable != nil {
  p.Capabilities.Ambient = append(p.Capabilities.Ambient, c)
}
```
Or else it will cause a compatibility issue.

Furthermore, maybe the patch of `GHSA-f3fp-gc8g-vw66` also should be like this:
```
if p.Capabilities.Inheritable != nil {
  p.Capabilities.Inheritable = append(p.Capabilities.Inheritable, c)
  p.Capabilities.Ambient = append(p.Capabilities.Ambient, c)
}
```
But this is not very important, because It depends on our understanding of `runc exec --cap`: `add a capability to the bounding set for the process`. The important one is the compatibility issue metioned above.

Code after:
	// process via cli flags
	if err := os.Chdir(bundle); err != nil {
		return nil, err
	}
	spec, err := loadSpec(specConfig)
	if err != nil {
		return nil, err
	}
	p := spec.Process
	p.Args = context.Args()[1:]
	// Override the cwd, if passed.
	if cwd := context.String("cwd"); cwd != "" {
		p.Cwd = cwd
	}
	if ap := context.String("apparmor"); ap != "" {
		p.ApparmorProfile = ap
	}
	if l := context.String("process-label"); l != "" {
		p.SelinuxLabel = l
	}
	if caps := context.StringSlice("cap"); len(caps) > 0 {
		for _, c := range caps {
			p.Capabilities.Bounding = append(p.Capabilities.Bounding, c)
			p.Capabilities.Effective = append(p.Capabilities.Effective, c)
			p.Capabilities.Permitted = append(p.Capabilities.Permitted, c)
			// Since ambient capabilities can't be set without inherritable,
			// and runc exec --cap don't set inheritable, let's only set
			// ambient if we already have some inheritable bits set from spec.
			if p.Capabilities.Inheritable != nil {
				p.Capabilities.Ambient = append(p.Capabilities.Ambient, c)
			}
		}
	}
	// append the passed env variables
	p.Env = append(p.Env, context.StringSlice("env")...)

	// Always set tty to false, unless explicitly enabled from CLI.
	p.Terminal = context.Bool("tty")
	if context.IsSet("no-new-privs") {
		p.NoNewPrivileges = context.Bool("no-new-privs")
	}
	// Override the user, if passed.
	if user := context.String("user"); user != "" {
		u := strings.SplitN(user, ":", 2)
		if len(u) > 1 {
			gid, err := strconv.Atoi(u[1])
			if err != nil {
				return nil, fmt.Errorf("bad gid: %w", err)
			}
			p.User.GID = uint32(gid)
		}