// Copyright 2018 The gVisor Authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package linux import ( "gvisor.dev/gvisor/pkg/errors/linuxerr" "gvisor.dev/gvisor/pkg/sentry/arch" "gvisor.dev/gvisor/pkg/sentry/kernel" "gvisor.dev/gvisor/pkg/sentry/kernel/auth" ) const ( // As NGROUPS_MAX in include/uapi/linux/limits.h. maxNGroups = 65536 ) // Getuid implements the Linux syscall getuid. func Getuid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { c := t.Credentials() ruid := c.RealKUID.In(c.UserNamespace).OrOverflow() return uintptr(ruid), nil, nil } // Geteuid implements the Linux syscall geteuid. func Geteuid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { c := t.Credentials() euid := c.EffectiveKUID.In(c.UserNamespace).OrOverflow() return uintptr(euid), nil, nil } // Getresuid implements the Linux syscall getresuid. func Getresuid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { ruidAddr := args[0].Pointer() euidAddr := args[1].Pointer() suidAddr := args[2].Pointer() c := t.Credentials() ruid := c.RealKUID.In(c.UserNamespace).OrOverflow() euid := c.EffectiveKUID.In(c.UserNamespace).OrOverflow() suid := c.SavedKUID.In(c.UserNamespace).OrOverflow() if _, err := ruid.CopyOut(t, ruidAddr); err != nil { return 0, nil, err } if _, err := euid.CopyOut(t, euidAddr); err != nil { return 0, nil, err } if _, err := suid.CopyOut(t, suidAddr); err != nil { return 0, nil, err } return 0, nil, nil } // Getgid implements the Linux syscall getgid. func Getgid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { c := t.Credentials() rgid := c.RealKGID.In(c.UserNamespace).OrOverflow() return uintptr(rgid), nil, nil } // Getegid implements the Linux syscall getegid. func Getegid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { c := t.Credentials() egid := c.EffectiveKGID.In(c.UserNamespace).OrOverflow() return uintptr(egid), nil, nil } // Getresgid implements the Linux syscall getresgid. func Getresgid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { rgidAddr := args[0].Pointer() egidAddr := args[1].Pointer() sgidAddr := args[2].Pointer() c := t.Credentials() rgid := c.RealKGID.In(c.UserNamespace).OrOverflow() egid := c.EffectiveKGID.In(c.UserNamespace).OrOverflow() sgid := c.SavedKGID.In(c.UserNamespace).OrOverflow() if _, err := rgid.CopyOut(t, rgidAddr); err != nil { return 0, nil, err } if _, err := egid.CopyOut(t, egidAddr); err != nil { return 0, nil, err } if _, err := sgid.CopyOut(t, sgidAddr); err != nil { return 0, nil, err } return 0, nil, nil } // Setuid implements the Linux syscall setuid. func Setuid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { uid := auth.UID(args[0].Int()) return 0, nil, t.SetUID(uid) } // Setreuid implements the Linux syscall setreuid. func Setreuid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { ruid := auth.UID(args[0].Int()) euid := auth.UID(args[1].Int()) return 0, nil, t.SetREUID(ruid, euid) } // Setresuid implements the Linux syscall setreuid. func Setresuid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { ruid := auth.UID(args[0].Int()) euid := auth.UID(args[1].Int()) suid := auth.UID(args[2].Int()) return 0, nil, t.SetRESUID(ruid, euid, suid) } // Setgid implements the Linux syscall setgid. func Setgid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { gid := auth.GID(args[0].Int()) return 0, nil, t.SetGID(gid) } // Setregid implements the Linux syscall setregid. func Setregid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { rgid := auth.GID(args[0].Int()) egid := auth.GID(args[1].Int()) return 0, nil, t.SetREGID(rgid, egid) } // Setresgid implements the Linux syscall setregid. func Setresgid(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { rgid := auth.GID(args[0].Int()) egid := auth.GID(args[1].Int()) sgid := auth.GID(args[2].Int()) return 0, nil, t.SetRESGID(rgid, egid, sgid) } // Getgroups implements the Linux syscall getgroups. func Getgroups(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { size := int(args[0].Int()) if size < 0 { return 0, nil, linuxerr.EINVAL } kgids := t.Credentials().ExtraKGIDs // "If size is zero, list is not modified, but the total number of // supplementary group IDs for the process is returned." - getgroups(2) if size == 0 { return uintptr(len(kgids)), nil, nil } if size < len(kgids) { return 0, nil, linuxerr.EINVAL } gids := make([]auth.GID, len(kgids)) for i, kgid := range kgids { gids[i] = kgid.In(t.UserNamespace()).OrOverflow() } if _, err := auth.CopyGIDSliceOut(t, args[1].Pointer(), gids); err != nil { return 0, nil, err } return uintptr(len(gids)), nil, nil } // Setgroups implements the Linux syscall setgroups. func Setgroups(t *kernel.Task, args arch.SyscallArguments) (uintptr, *kernel.SyscallControl, error) { size := args[0].Int() if size < 0 || size > maxNGroups { return 0, nil, linuxerr.EINVAL } if size == 0 { return 0, nil, t.SetExtraGIDs(nil) } gids := make([]auth.GID, size) if _, err := auth.CopyGIDSliceIn(t, args[1].Pointer(), gids); err != nil { return 0, nil, err } return 0, nil, t.SetExtraGIDs(gids) }