Skip to content
This repository has been archived by the owner on Aug 14, 2020. It is now read-only.

Commit

Permalink
schema/types: implement linux-specific seccomp isolators
Browse files Browse the repository at this point in the history
  • Loading branch information
lucab committed Jun 3, 2016
1 parent 95e8be1 commit e407925
Show file tree
Hide file tree
Showing 2 changed files with 244 additions and 7 deletions.
141 changes: 134 additions & 7 deletions schema/types/isolator_linux_specific.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@ package types
import (
"encoding/json"
"errors"
"unicode"
)

const (
LinuxCapabilitiesRetainSetName = "os/linux/capabilities-retain-set"
LinuxCapabilitiesRevokeSetName = "os/linux/capabilities-remove-set"
LinuxNoNewPrivilegesName = "os/linux/no-new-privileges"
LinuxSeccompRemoveSetName = "os/linux/seccomp-remove-set"
LinuxSeccompRetainSetName = "os/linux/seccomp-retain-set"
)

var LinuxIsolatorNames = make(map[ACIdentifier]struct{})
Expand All @@ -32,6 +35,8 @@ func init() {
LinuxCapabilitiesRevokeSetName: func() IsolatorValue { return &LinuxCapabilitiesRevokeSet{} },
LinuxCapabilitiesRetainSetName: func() IsolatorValue { return &LinuxCapabilitiesRetainSet{} },
LinuxNoNewPrivilegesName: func() IsolatorValue { v := LinuxNoNewPrivileges(false); return &v },
LinuxSeccompRemoveSetName: func() IsolatorValue { return &LinuxSeccompRemoveSet{} },
LinuxSeccompRetainSetName: func() IsolatorValue { return &LinuxSeccompRetainSet{} },
} {
AddIsolatorName(name, LinuxIsolatorNames)
AddIsolatorValueConstructor(name, con)
Expand All @@ -56,6 +61,10 @@ func (l *LinuxNoNewPrivileges) UnmarshalJSON(b []byte) error {
return nil
}

type AsIsolator interface {
AsIsolator() (*Isolator, error)
}

type LinuxCapabilitiesSet interface {
Set() []LinuxCapability
AssertValid() error
Expand Down Expand Up @@ -115,17 +124,17 @@ func NewLinuxCapabilitiesRetainSet(caps ...string) (*LinuxCapabilitiesRetainSet,
return &l, nil
}

func (l LinuxCapabilitiesRetainSet) AsIsolator() Isolator {
func (l LinuxCapabilitiesRetainSet) AsIsolator() (*Isolator, error) {
b, err := json.Marshal(l.linuxCapabilitiesSetBase.val)
if err != nil {
panic(err)
return nil, err
}
rm := json.RawMessage(b)
return Isolator{
return &Isolator{
Name: LinuxCapabilitiesRetainSetName,
ValueRaw: &rm,
value: &l,
}
}, nil
}

type LinuxCapabilitiesRevokeSet struct {
Expand All @@ -149,15 +158,133 @@ func NewLinuxCapabilitiesRevokeSet(caps ...string) (*LinuxCapabilitiesRevokeSet,
return &l, nil
}

func (l LinuxCapabilitiesRevokeSet) AsIsolator() Isolator {
func (l LinuxCapabilitiesRevokeSet) AsIsolator() (*Isolator, error) {
b, err := json.Marshal(l.linuxCapabilitiesSetBase.val)
if err != nil {
panic(err)
return nil, err
}
rm := json.RawMessage(b)
return Isolator{
return &Isolator{
Name: LinuxCapabilitiesRevokeSetName,
ValueRaw: &rm,
value: &l,
}, nil
}

type LinuxSeccompSet interface {
Set() []LinuxSeccompEntry
Errno() LinuxSeccompErrno
AssertValid() error
}

type LinuxSeccompEntry string
type LinuxSeccompErrno string

type linuxSeccompValue struct {
Set []LinuxSeccompEntry `json:"set"`
Errno LinuxSeccompErrno `json:"errno"`
}

type linuxSeccompBase struct {
val linuxSeccompValue
}

func (l linuxSeccompBase) AssertValid() error {
if l.val.Errno == "" {
return nil
}
for _, c := range l.val.Errno {
if !unicode.IsUpper(c) {
return errors.New("invalid errno")
}
}
return nil
}

func (l *linuxSeccompBase) UnmarshalJSON(b []byte) error {
var v linuxSeccompValue
err := json.Unmarshal(b, &v)
if err != nil {
return err
}
l.val = v
return nil
}

func (l linuxSeccompBase) Set() []LinuxSeccompEntry {
return l.val.Set
}

func (l linuxSeccompBase) Errno() LinuxSeccompErrno {
return l.val.Errno
}

type LinuxSeccompRetainSet struct {
linuxSeccompBase
}

func NewLinuxSeccompRetainSet(errno string, syscall ...string) (*LinuxSeccompRetainSet, error) {
l := LinuxSeccompRetainSet{
linuxSeccompBase{
linuxSeccompValue{
make([]LinuxSeccompEntry, len(syscall)),
LinuxSeccompErrno(errno),
},
},
}
for i, c := range syscall {
l.linuxSeccompBase.val.Set[i] = LinuxSeccompEntry(c)
}
if err := l.AssertValid(); err != nil {
return nil, err
}
return &l, nil
}

func (l LinuxSeccompRetainSet) AsIsolator() (*Isolator, error) {
b, err := json.Marshal(l.linuxSeccompBase.val)
if err != nil {
return nil, err
}
rm := json.RawMessage(b)
return &Isolator{
Name: LinuxSeccompRetainSetName,
ValueRaw: &rm,
value: &l,
}, nil
}

type LinuxSeccompRemoveSet struct {
linuxSeccompBase
}

func NewLinuxSeccompRemoveSet(errno string, syscall ...string) (*LinuxSeccompRemoveSet, error) {
l := LinuxSeccompRemoveSet{
linuxSeccompBase{
linuxSeccompValue{
make([]LinuxSeccompEntry, len(syscall)),
LinuxSeccompErrno(errno),
},
},
}
for i, c := range syscall {
l.linuxSeccompBase.val.Set[i] = LinuxSeccompEntry(c)
}
if err := l.AssertValid(); err != nil {
return nil, err
}
return &l, nil
}

func (l LinuxSeccompRemoveSet) AsIsolator() (*Isolator, error) {
b, err := json.Marshal(l.linuxSeccompBase.val)
if err != nil {
return nil, err
}
rm := json.RawMessage(b)
return &Isolator{
Name: LinuxSeccompRemoveSetName,
ValueRaw: &rm,
value: &l,
}, nil
}
110 changes: 110 additions & 0 deletions schema/types/isolator_linux_specific_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,113 @@ func TestNewLinuxCapabilitiesRevokeSet(t *testing.T) {
}

}

func TestNewLinuxSeccompRemoveSet(t *testing.T) {
tests := []struct {
set []string
errno string

wset []LinuxSeccompEntry
werrno LinuxSeccompErrno
werr bool
}{
{
[]string{},
"-EPERM",
nil,
"",
true,
},
{
[]string{"@appc/empty"},
"EACCESS",
[]LinuxSeccompEntry{"@appc/empty"},
LinuxSeccompErrno("EACCESS"),
false,
},
{
[]string{"chmod", "chown"},
"",
[]LinuxSeccompEntry{"chmod", "chown"},
LinuxSeccompErrno(""),
false,
},
{
[]string{},
"",
[]LinuxSeccompEntry{},
LinuxSeccompErrno(""),
false,
},
}
for i, tt := range tests {
c, err := NewLinuxSeccompRemoveSet(tt.errno, tt.set...)
if tt.werr {
if err == nil {
t.Errorf("#%d: did not get expected error", i)
}
continue
}
if gset := c.Set(); !reflect.DeepEqual(gset, tt.wset) {
t.Errorf("#%d: got set %#v, expected set %#v", i, gset, tt.wset)
}
if gerrno := c.Errno(); !reflect.DeepEqual(gerrno, tt.werrno) {
t.Errorf("#%d: got errno %#v, expected errno %#v", i, gerrno, tt.werrno)
}
}
}

func TestNewLinuxSeccompRetainSet(t *testing.T) {
tests := []struct {
set []string
errno string

wset []LinuxSeccompEntry
werrno LinuxSeccompErrno
werr bool
}{
{
[]string{},
"eaccess",
nil,
"",
true,
},
{
[]string{"chmod"},
"EACCESS",
[]LinuxSeccompEntry{"chmod"},
LinuxSeccompErrno("EACCESS"),
false,
},
{
[]string{"chmod", "chown"},
"",
[]LinuxSeccompEntry{"chmod", "chown"},
LinuxSeccompErrno(""),
false,
},
{
[]string{},
"",
[]LinuxSeccompEntry{},
LinuxSeccompErrno(""),
false,
},
}
for i, tt := range tests {
c, err := NewLinuxSeccompRetainSet(tt.errno, tt.set...)
if tt.werr {
if err == nil {
t.Errorf("#%d: did not get expected error", i)
}
continue
}
if gset := c.Set(); !reflect.DeepEqual(gset, tt.wset) {
t.Errorf("#%d: got set %#v, expected set %#v", i, gset, tt.wset)
}
if gerrno := c.Errno(); !reflect.DeepEqual(gerrno, tt.werrno) {
t.Errorf("#%d: got errno %#v, expected errno %#v", i, gerrno, tt.werrno)
}
}
}

0 comments on commit e407925

Please sign in to comment.