// Copyright (c) 2013, Suryandaru Triandana // All rights reserved. // // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. package capability import ( "syscall" "unsafe" ) type capHeader struct { version uint32 pid int32 } type capData struct { effective uint32 permitted uint32 inheritable uint32 } func capget(hdr *capHeader, data *capData) (err error) { _, _, e1 := syscall.Syscall(syscall.SYS_CAPGET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0) if e1 != 0 { err = e1 } return } func capset(hdr *capHeader, data *capData) (err error) { _, _, e1 := syscall.Syscall(syscall.SYS_CAPSET, uintptr(unsafe.Pointer(hdr)), uintptr(unsafe.Pointer(data)), 0) if e1 != 0 { err = e1 } return } // not yet in syscall const ( pr_CAP_AMBIENT = 47 pr_CAP_AMBIENT_IS_SET = uintptr(1) pr_CAP_AMBIENT_RAISE = uintptr(2) pr_CAP_AMBIENT_LOWER = uintptr(3) pr_CAP_AMBIENT_CLEAR_ALL = uintptr(4) ) func prctl(option int, arg2, arg3, arg4, arg5 uintptr) (err error) { _, _, e1 := syscall.Syscall6(syscall.SYS_PRCTL, uintptr(option), arg2, arg3, arg4, arg5, 0) if e1 != 0 { err = e1 } return } const ( vfsXattrName = "security.capability" vfsCapVerMask = 0xff000000 vfsCapVer1 = 0x01000000 vfsCapVer2 = 0x02000000 vfsCapFlagMask = ^vfsCapVerMask vfsCapFlageffective = 0x000001 vfscapDataSizeV1 = 4 * (1 + 2*1) vfscapDataSizeV2 = 4 * (1 + 2*2) ) type vfscapData struct { magic uint32 data [2]struct { permitted uint32 inheritable uint32 } effective [2]uint32 version int8 } var ( _vfsXattrName *byte ) func init() { _vfsXattrName, _ = syscall.BytePtrFromString(vfsXattrName) } func getVfsCap(path string, dest *vfscapData) (err error) { var _p0 *byte _p0, err = syscall.BytePtrFromString(path) if err != nil { return } r0, _, e1 := syscall.Syscall6(syscall.SYS_GETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_vfsXattrName)), uintptr(unsafe.Pointer(dest)), vfscapDataSizeV2, 0, 0) if e1 != 0 { if e1 == syscall.ENODATA { dest.version = 2 return } err = e1 } switch dest.magic & vfsCapVerMask { case vfsCapVer1: dest.version = 1 if r0 != vfscapDataSizeV1 { return syscall.EINVAL } dest.data[1].permitted = 0 dest.data[1].inheritable = 0 case vfsCapVer2: dest.version = 2 if r0 != vfscapDataSizeV2 { return syscall.EINVAL } default: return syscall.EINVAL } if dest.magic&vfsCapFlageffective != 0 { dest.effective[0] = dest.data[0].permitted | dest.data[0].inheritable dest.effective[1] = dest.data[1].permitted | dest.data[1].inheritable } else { dest.effective[0] = 0 dest.effective[1] = 0 } return } func setVfsCap(path string, data *vfscapData) (err error) { var _p0 *byte _p0, err = syscall.BytePtrFromString(path) if err != nil { return } var size uintptr if data.version == 1 { data.magic = vfsCapVer1 size = vfscapDataSizeV1 } else if data.version == 2 { data.magic = vfsCapVer2 if data.effective[0] != 0 || data.effective[1] != 0 { data.magic |= vfsCapFlageffective } size = vfscapDataSizeV2 } else { return syscall.EINVAL } _, _, e1 := syscall.Syscall6(syscall.SYS_SETXATTR, uintptr(unsafe.Pointer(_p0)), uintptr(unsafe.Pointer(_vfsXattrName)), uintptr(unsafe.Pointer(data)), size, 0, 0) if e1 != 0 { err = e1 } return }