<commit_before>package libaudit

import (
	"bytes"
	"encoding/json"
	"fmt"
	"os"
	"os/user"
	"path"
	"runtime"
	"strconv"
	"strings"
	"syscall"
	"unsafe"

	"github.com/lunixbochs/struc"
	"github.com/mozilla/libaudit-go/headers"
	"github.com/pkg/errors"
)

var rulesRetrieved auditRuleData

// Describes a set of audit rules; we load these from a JSON file
type auditRules struct {
	FileRules       []auditFileRule    `json:"file_rules"`
	SyscallRules    []auditSyscallRule `json:"syscall_rules"`
	StrictPathCheck bool               `json:"strict_path_check"`
	Delete          bool               `json:"delete"`
	Enable          string             `json:"enable"`
	Buffer          string             `json:"buffer"`
	Rate            string             `json:"rate"`
}

type auditFileRule struct {
	Path       string `json:"path"`
	Key        string `json:"key"`
	Permission string `json:"permission"`
}

type auditSyscallRule struct {
	Key    string `json:"key"`
	Fields []struct {
		Name  string      `json:"name"`
		Value interface{} `json:"value"` // Can be a string or int
		Op    string      `json:"op"`
	} `json:"fields"`
	Syscalls []string `json:"syscalls"`
	Actions  []string `json:"actions"`
}

// auditRuleData stores rule information
// replication of c struct audit_rule_data
type auditRuleData struct {
	Flags      uint32                     `struc:"uint32,little"` // AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND
	Action     uint32                     `struc:"uint32,little"` // AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS
	FieldCount uint32                     `struc:"uint32,little"`
	Mask       [AUDIT_BITMASK_SIZE]uint32 `struc:"[64]uint32,little"` // syscall(s) affected
	Fields     [AUDIT_MAX_FIELDS]uint32   `struc:"[64]uint32,little"`
	Values     [AUDIT_MAX_FIELDS]uint32   `struc:"[64]uint32,little"`
	Fieldflags [AUDIT_MAX_FIELDS]uint32   `struc:"[64]uint32,little"`
	Buflen     uint32                     `struc:"uint32,little,sizeof=Buf"` // total length of string fields
	Buf        []byte                     `struc:"[]byte,little"`            // string fields buffer
}

// toWireFormat converts a auditRuleData to byte stream
// relies on unsafe conversions
func (rule *auditRuleData) toWireFormat() []byte {

	newbuff := make([]byte, int(unsafe.Sizeof(*rule))-int(unsafe.Sizeof(rule.Buf))+int(rule.Buflen))
	*(*uint32)(unsafe.Pointer(&newbuff[0:4][0])) = rule.Flags
	*(*uint32)(unsafe.Pointer(&newbuff[4:8][0])) = rule.Action
	*(*uint32)(unsafe.Pointer(&newbuff[8:12][0])) = rule.FieldCount
	*(*[AUDIT_BITMASK_SIZE]uint32)(unsafe.Pointer(&newbuff[12:268][0])) = rule.Mask
	*(*[AUDIT_MAX_FIELDS]uint32)(unsafe.Pointer(&newbuff[268:524][0])) = rule.Fields
	*(*[AUDIT_MAX_FIELDS]uint32)(unsafe.Pointer(&newbuff[524:780][0])) = rule.Values
	*(*[AUDIT_MAX_FIELDS]uint32)(unsafe.Pointer(&newbuff[780:1036][0])) = rule.Fieldflags
	*(*uint32)(unsafe.Pointer(&newbuff[1036:1040][0])) = rule.Buflen
	copy(newbuff[1040:1040+rule.Buflen], rule.Buf[:])
	return newbuff
}

// auditDeleteRuleData deletes a rule from audit in kernel
func auditDeleteRuleData(s Netlink, rule *auditRuleData, flags uint32, action uint32) error {
	if flags == AUDIT_FILTER_ENTRY {
		return fmt.Errorf("use of entry filter is deprecated")
	}
	rule.Flags = flags
	rule.Action = action

	newbuff := rule.toWireFormat()
	// avoiding standard method of unwrapping the struct due to restriction on byte array in auditRuleData
	// i.e. binary.Write(buff, nativeEndian(), *rule)
	newwb := newNetlinkAuditRequest(uint16(AUDIT_DEL_RULE), syscall.AF_NETLINK, len(newbuff) /*+int(rule.Buflen)*/)
	newwb.Data = append(newwb.Data, newbuff[:]...)
	if err := s.Send(newwb); err != nil {
		return errors.Wrap(err, "auditDeleteRuleData failed")
	}
	return nil
}

// Purge all audit rules currently in use in the audit system
func DeleteAllRules(s Netlink) error {
	wb := newNetlinkAuditRequest(uint16(AUDIT_LIST_RULES), syscall.AF_NETLINK, 0)
	if err := s.Send(wb); err != nil {
		return err
	}
<commit_msg>remove use of unsafe in toWireFormat and use binary write<commit_after>package libaudit

import (
	"bytes"
	"encoding/binary"
	"encoding/json"
	"fmt"
	"os"
	"os/user"
	"path"
	"runtime"
	"strconv"
	"strings"
	"syscall"

	"github.com/lunixbochs/struc"
	"github.com/mozilla/libaudit-go/headers"
	"github.com/pkg/errors"
)

var rulesRetrieved auditRuleData

// Describes a set of audit rules; we load these from a JSON file
type auditRules struct {
	FileRules       []auditFileRule    `json:"file_rules"`
	SyscallRules    []auditSyscallRule `json:"syscall_rules"`
	StrictPathCheck bool               `json:"strict_path_check"`
	Delete          bool               `json:"delete"`
	Enable          string             `json:"enable"`
	Buffer          string             `json:"buffer"`
	Rate            string             `json:"rate"`
}

type auditFileRule struct {
	Path       string `json:"path"`
	Key        string `json:"key"`
	Permission string `json:"permission"`
}

type auditSyscallRule struct {
	Key    string `json:"key"`
	Fields []struct {
		Name  string      `json:"name"`
		Value interface{} `json:"value"` // Can be a string or int
		Op    string      `json:"op"`
	} `json:"fields"`
	Syscalls []string `json:"syscalls"`
	Actions  []string `json:"actions"`
}

// auditRuleData stores rule information
// replication of c struct audit_rule_data
type auditRuleData struct {
	Flags      uint32                     `struc:"uint32,little"` // AUDIT_PER_{TASK,CALL}, AUDIT_PREPEND
	Action     uint32                     `struc:"uint32,little"` // AUDIT_NEVER, AUDIT_POSSIBLE, AUDIT_ALWAYS
	FieldCount uint32                     `struc:"uint32,little"`
	Mask       [AUDIT_BITMASK_SIZE]uint32 `struc:"[64]uint32,little"` // syscall(s) affected
	Fields     [AUDIT_MAX_FIELDS]uint32   `struc:"[64]uint32,little"`
	Values     [AUDIT_MAX_FIELDS]uint32   `struc:"[64]uint32,little"`
	Fieldflags [AUDIT_MAX_FIELDS]uint32   `struc:"[64]uint32,little"`
	Buflen     uint32                     `struc:"uint32,little,sizeof=Buf"` // total length of string fields
	Buf        []byte                     `struc:"[]byte,little"`            // string fields buffer
}

// toWireFormat converts a auditRuleData to byte stream
// relies on unsafe conversions
func (rule *auditRuleData) toWireFormat() []byte {
	buf := new(bytes.Buffer)
	err := binary.Write(buf, nativeEndian(), rule.Flags)
	if err != nil {
		return nil
	}
	err = binary.Write(buf, nativeEndian(), rule.Action)
	if err != nil {
		return nil
	}
	err = binary.Write(buf, nativeEndian(), rule.FieldCount)
	if err != nil {
		return nil
	}
	err = binary.Write(buf, nativeEndian(), rule.Mask)
	if err != nil {
		return nil
	}
	err = binary.Write(buf, nativeEndian(), rule.Fields)
	if err != nil {
		return nil
	}
	err = binary.Write(buf, nativeEndian(), rule.Values)
	if err != nil {
		return nil
	}
	err = binary.Write(buf, nativeEndian(), rule.Fieldflags)
	if err != nil {
		return nil
	}
	err = binary.Write(buf, nativeEndian(), rule.Buflen)
	if err != nil {
		return nil
	}
	err = binary.Write(buf, nativeEndian(), rule.Buf)
	if err != nil {
		return nil
	}
	return buf.Bytes()
}

// auditDeleteRuleData deletes a rule from audit in kernel
func auditDeleteRuleData(s Netlink, rule *auditRuleData, flags uint32, action uint32) error {
	if flags == AUDIT_FILTER_ENTRY {
		return fmt.Errorf("use of entry filter is deprecated")
	}
	rule.Flags = flags
	rule.Action = action

	newbuff := rule.toWireFormat()
	// avoiding standard method of unwrapping the struct due to restriction on byte array in auditRuleData
	// i.e. binary.Write(buff, nativeEndian(), *rule)
	newwb := newNetlinkAuditRequest(uint16(AUDIT_DEL_RULE), syscall.AF_NETLINK, len(newbuff) /*+int(rule.Buflen)*/)
	newwb.Data = append(newwb.Data, newbuff[:]...)
	if err := s.Send(newwb); err != nil {
		return errors.Wrap(err, "auditDeleteRuleData failed")
	}
	return nil
}

// Purge all audit rules currently in use in the audit system
func DeleteAllRules(s Netlink) error {
	wb := newNetlinkAuditRequest(uint16(AUDIT_LIST_RULES), syscall.AF_NETLINK, 0)
	if err := s.Send(wb); err != nil {
		return err
	}

{'fraction_non_alphanumeric': 0.1325003092911048, 'fraction_numerical': 0.020908078683657058, 'mean_word_length': 3.569813453928773, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4498372', 'n_tokens_mistral': 2943, 'n_tokens_neox': 2716, 'n_words': 651}