Skip to content

Commit

Permalink
Adding Big Endian Support (#48)
Browse files Browse the repository at this point in the history
* Adding support for BigEndian

* Added fix for CI and s390x tests failures

* Update CHANGELOG.md
  • Loading branch information
vitt-bagal authored and andrewkroh committed Feb 28, 2019
1 parent 32a0270 commit db7d499
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 13 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ This project adheres to [Semantic Versioning](http://semver.org/).

### Changed

- Added support for big endian. #48

### Removed

## [0.4.0]
Expand Down
11 changes: 8 additions & 3 deletions audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ import (
"github.com/pkg/errors"

"github.com/elastic/go-libaudit/auparse"
"github.com/elastic/go-libaudit/sys"
)

var (
byteOrder = sys.GetEndian()
)

const (
Expand Down Expand Up @@ -537,7 +542,7 @@ func parseNetlinkAuditMessage(buf []byte) ([]syscall.NetlinkMessage, error) {

r := bytes.NewReader(buf)
m := syscall.NetlinkMessage{}
if err := binary.Read(r, binary.LittleEndian, &m.Header); err != nil {
if err := binary.Read(r, byteOrder, &m.Header); err != nil {
return nil, err
}
m.Data = buf[syscall.NLMSG_HDRLEN:]
Expand Down Expand Up @@ -596,7 +601,7 @@ type AuditStatus struct {
func (s AuditStatus) toWireFormat() []byte {
buf := bytes.NewBuffer(make([]byte, sizeofAuditStatus))
buf.Reset()
if err := binary.Write(buf, binary.LittleEndian, s); err != nil {
if err := binary.Write(buf, byteOrder, s); err != nil {
// This never returns an error.
panic(err)
}
Expand Down Expand Up @@ -631,7 +636,7 @@ func (s *AuditStatus) FromWireFormat(buf []byte) error {
return nil
}

if err := binary.Read(r, binary.LittleEndian, f); err != nil {
if err := binary.Read(r, byteOrder, f); err != nil {
return err
}
}
Expand Down
20 changes: 18 additions & 2 deletions audit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ package libaudit

import (
"encoding/base64"
"encoding/binary"
"encoding/hex"
"flag"
"fmt"
Expand All @@ -36,6 +37,7 @@ import (

"github.com/elastic/go-libaudit/rule"
"github.com/elastic/go-libaudit/rule/flags"
"github.com/elastic/go-libaudit/sys"
)

// This can be run inside of Docker with:
Expand Down Expand Up @@ -152,6 +154,10 @@ func TestListRules(t *testing.T) {
}

func TestAddRule(t *testing.T) {
if sys.GetEndian() != binary.LittleEndian {
t.Skip("testRule is for little endian, but test machine is big endian")
}

if os.Geteuid() != 0 {
t.Skip("must be root to get audit status")
}
Expand All @@ -177,6 +183,10 @@ func TestAddRule(t *testing.T) {
}

func TestAddDuplicateRule(t *testing.T) {
if sys.GetEndian() != binary.LittleEndian {
t.Skip("testRule is for little endian, but test machine is big endian")
}

if os.Geteuid() != 0 {
t.Skip("must be root to get audit status")
}
Expand Down Expand Up @@ -831,7 +841,13 @@ func kernelVersion() (major int, minor int, err error) {
return 0, 0, err
}
s := info.Release[:]
major, pos := extractDecimalNumber(s, 0)
minor, _ = extractDecimalNumber(s, pos)
// As all major non-Intel architecture return []uint8 instead of []int8 for Utsname.Release following conversion is required
temp := make([]int8, len(s))
for index, num := range s {
temp[index] = int8(num)
}

major, pos := extractDecimalNumber(temp, 0)
minor, _ = extractDecimalNumber(temp, pos)
return major, minor, nil
}
15 changes: 8 additions & 7 deletions netlink.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,15 @@
package libaudit

import (
"encoding/binary"
"fmt"
"io"
"os"
"sync/atomic"
"syscall"

"github.com/pkg/errors"

"github.com/elastic/go-libaudit/sys"
)

// Generic Netlink Client
Expand Down Expand Up @@ -142,11 +143,11 @@ func (c *NetlinkClient) Send(msg syscall.NetlinkMessage) (uint32, error) {
func serialize(msg syscall.NetlinkMessage) []byte {
msg.Header.Len = uint32(syscall.SizeofNlMsghdr + len(msg.Data))
b := make([]byte, msg.Header.Len)
binary.LittleEndian.PutUint32(b[0:4], msg.Header.Len)
binary.LittleEndian.PutUint16(b[4:6], msg.Header.Type)
binary.LittleEndian.PutUint16(b[6:8], msg.Header.Flags)
binary.LittleEndian.PutUint32(b[8:12], msg.Header.Seq)
binary.LittleEndian.PutUint32(b[12:16], msg.Header.Pid)
sys.GetEndian().PutUint32(b[0:4], msg.Header.Len)
sys.GetEndian().PutUint16(b[4:6], msg.Header.Type)
sys.GetEndian().PutUint16(b[6:8], msg.Header.Flags)
sys.GetEndian().PutUint32(b[8:12], msg.Header.Seq)
sys.GetEndian().PutUint32(b[12:16], msg.Header.Pid)
copy(b[16:], msg.Data)
return b
}
Expand Down Expand Up @@ -205,7 +206,7 @@ func (c *NetlinkClient) Close() error {
// describing the problem will be returned.
func ParseNetlinkError(netlinkData []byte) error {
if len(netlinkData) >= 4 {
errno := -binary.LittleEndian.Uint32(netlinkData[:4])
errno := -sys.GetEndian().Uint32(netlinkData[:4])
if errno == 0 {
return nil
}
Expand Down
4 changes: 3 additions & 1 deletion rule/binary.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,16 @@ import (
"io"

"github.com/pkg/errors"

"github.com/elastic/go-libaudit/sys"
)

const (
syscallBitmaskSize = 64 // AUDIT_BITMASK_SIZE
maxFields = 64 // AUDIT_MAX_FIELDS
)

var endianness = binary.LittleEndian
var endianness = sys.GetEndian()

// WireFormat is the binary representation of a rule as used to exchange rules
// (commands) with the kernel.
Expand Down
6 changes: 6 additions & 0 deletions rule/gen_testdata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package rule_test
import (
"bufio"
"bytes"
"encoding/binary"
"flag"
"io/ioutil"
"os"
Expand All @@ -34,6 +35,7 @@ import (
"gopkg.in/yaml.v2"

"github.com/elastic/go-libaudit"
"github.com/elastic/go-libaudit/sys"
)

var update = flag.Bool("update", false, "update .golden.yml files")
Expand All @@ -47,6 +49,10 @@ var update = flag.Bool("update", false, "update .golden.yml files")
// The kernel version and auditctl version used to generate the golden data
// are stored as comments in the YAML file header.
func TestUpdateGoldenData(t *testing.T) {
if sys.GetEndian() != binary.LittleEndian {
t.Skip("golden test data is for little endian, but test machine is big endian")
}

if !*update {
t.SkipNow()
}
Expand Down
6 changes: 6 additions & 0 deletions rule/rule_integ_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package rule_test

import (
"encoding/binary"
"fmt"
"io/ioutil"
"os"
Expand All @@ -32,6 +33,7 @@ import (

"github.com/elastic/go-libaudit/rule"
"github.com/elastic/go-libaudit/rule/flags"
"github.com/elastic/go-libaudit/sys"
)

var tempDir = "/tmp/audit-test"
Expand All @@ -48,6 +50,10 @@ type TestCase struct {
// TestBuild compares the WireFormat (binary data) generated by this package
// against known golden data generated on Linux with auditctl.
func TestBuildGolden(t *testing.T) {
if sys.GetEndian() != binary.LittleEndian {
t.Skip("golden test data is for little endian, but test machine is big endian")
}

goldenFiles, err := filepath.Glob("testdata/*.rules.golden.yml")
if err != nil {
t.Fatal(err)
Expand Down
35 changes: 35 additions & 0 deletions sys/endian.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you 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.

// +build linux

package sys

import (
"encoding/binary"
"unsafe"
)

func GetEndian() binary.ByteOrder {
var i int32 = 0x1
v := (*[4]byte)(unsafe.Pointer(&i))
if v[0] == 0 {
return binary.BigEndian
} else {
return binary.LittleEndian
}
}

0 comments on commit db7d499

Please sign in to comment.