Skip to content

Commit

Permalink
Merge pull request #1664 from daemon1024/add-execname-support
Browse files Browse the repository at this point in the history
Add execname support
  • Loading branch information
DelusionalOptimist authored Mar 7, 2024
2 parents c3607df + c0761bf commit 68bc93b
Show file tree
Hide file tree
Showing 26 changed files with 308 additions and 222 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-test-ginkgo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-20.04]
runtime: ["docker", "containerd", "crio"]
runtime: ["containerd", "crio"]
steps:
- uses: actions/checkout@v3
with:
Expand Down
74 changes: 43 additions & 31 deletions KubeArmor/BPF/enforcer.bpf.c
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,20 @@ int BPF_PROG(enforce_proc, struct linux_binprm *bprm, int ret) {
goto decision;
}


// match exec name
struct qstr d_name;
d_name = BPF_CORE_READ(f_path.dentry,d_name);
bpf_map_update_elem(&bufk, &two, z, BPF_ANY);
bpf_probe_read_str(pk->path, MAX_STRING_SIZE, d_name.name);

val = bpf_map_lookup_elem(inner, pk);

if (val && (val->processmask & RULE_EXEC)) {
match = true;
goto decision;
}

recursivebuthint = false;

#pragma unroll
Expand Down Expand Up @@ -311,31 +325,30 @@ static inline int match_net_rules(int type, int protocol, u32 eventID) {
fromSourceCheck = false;

void *ptr = &src_buf->buf[*src_offset];

if (type == SOCK_STREAM && (protocol == IPPROTO_TCP || protocol == 0)) {
p0 = sock_proto;
p1 = IPPROTO_TCP;
} else if (type == SOCK_DGRAM &&
(protocol == IPPROTO_UDP || protocol == 0)) {
p0 = sock_proto;
p1 = IPPROTO_UDP;
} else if (protocol == IPPROTO_ICMP &&
(type == SOCK_DGRAM || type == SOCK_RAW)) {
p0 = sock_proto;
p1 = IPPROTO_ICMP;
} else if (type == SOCK_RAW && protocol == 0) {
p0 = sock_type;
p1 = SOCK_RAW;
} else {
p0 = sock_proto;
p1 = protocol;
}
p0 = sock_proto;
p1 = IPPROTO_TCP;
} else if (type == SOCK_DGRAM && (protocol == IPPROTO_UDP || protocol == 0)) {
p0 = sock_proto;
p1 = IPPROTO_UDP;
} else if (protocol == IPPROTO_ICMP &&
(type == SOCK_DGRAM || type == SOCK_RAW)) {
p0 = sock_proto;
p1 = IPPROTO_ICMP;
} else if (type == SOCK_RAW && protocol == 0) {
p0 = sock_type;
p1 = SOCK_RAW;
} else {
p0 = sock_proto;
p1 = protocol;
}

if (fromSourceCheck) {
if (fromSourceCheck) {
bpf_probe_read_str(p->source, MAX_STRING_SIZE, ptr);
p->path[0] = p0;
p->path[1] = p1;
bpf_probe_read_str(store->source, MAX_STRING_SIZE, p->source);
bpf_probe_read_str(store->source, MAX_STRING_SIZE, p->source);
val = bpf_map_lookup_elem(inner, p);
if (val) {
match = true;
Expand All @@ -346,7 +359,7 @@ static inline int match_net_rules(int type, int protocol, u32 eventID) {
bpf_map_update_elem(&bufk, &one, z, BPF_ANY);
p->path[0] = p0;
p->path[1] = p1;

val = bpf_map_lookup_elem(inner, p);

if (val) {
Expand All @@ -364,12 +377,11 @@ static inline int match_net_rules(int type, int protocol, u32 eventID) {
}
}

bpf_map_update_elem(&bufk, &one, z, BPF_ANY);
p->path[0] = dnet ;
bpf_map_update_elem(&bufk, &one, z, BPF_ANY);
p->path[0] = dnet;

struct data_t *allow = bpf_map_lookup_elem(inner, p);


if (allow) {
if (!match) {
if (allow->processmask == BLOCK_POSTURE) {
Expand Down Expand Up @@ -437,7 +449,8 @@ int BPF_PROG(enforce_file_perm, struct file *file, int mask) {
return match_and_enforce_path_hooks(&f_path, dfilewrite, _FILE_PERMISSION);
}
SEC("lsm/capable")
int BPF_PROG(enforce_cap, const struct cred *cred, struct user_namespace *ns ,int cap, int ret){
int BPF_PROG(enforce_cap, const struct cred *cred, struct user_namespace *ns,
int cap, int ret) {

event *task_info;
int retval = 0;
Expand Down Expand Up @@ -493,20 +506,20 @@ int BPF_PROG(enforce_cap, const struct cred *cred, struct user_namespace *ns ,i
void *ptr = &src_buf->buf[*src_offset];
p0 = CAPABLE_KEY;
p1 = cap;

if (fromSourceCheck) {
bpf_probe_read_str(p->source, MAX_STRING_SIZE, ptr);
bpf_probe_read_str(store->source, MAX_STRING_SIZE, p->source);
p->path[0] = p0 ;
p->path[1] = p1 ;
p->path[0] = p0;
p->path[1] = p1;
val = bpf_map_lookup_elem(inner, p);

if (val) {
match = true;
goto decision;
}
}

bpf_map_update_elem(&bufk, &one, z, BPF_ANY);
// check for rules without fromsource
p->path[0] = p0;
Expand All @@ -518,7 +531,7 @@ int BPF_PROG(enforce_cap, const struct cred *cred, struct user_namespace *ns ,i
match = true;
goto decision;
}

decision:
bpf_probe_read_str(store->path, MAX_STRING_SIZE, p->path);
if (match) {
Expand Down Expand Up @@ -561,5 +574,4 @@ int BPF_PROG(enforce_cap, const struct cred *cred, struct user_namespace *ns ,i
task_info->retval = retval;
bpf_ringbuf_submit(task_info, 0);
return retval;

}
8 changes: 6 additions & 2 deletions KubeArmor/core/kubeUpdate.go
Original file line number Diff line number Diff line change
Expand Up @@ -1568,7 +1568,9 @@ func (dm *KubeArmorDaemon) ParseAndUpdateHostSecurityPolicy(event tp.K8sKubeArmo
}
}
}
} else if len(secPolicy.Spec.Process.MatchDirectories) > 0 {
}

if len(secPolicy.Spec.Process.MatchDirectories) > 0 {
for idx, dir := range secPolicy.Spec.Process.MatchDirectories {
if dir.Severity == 0 {
if secPolicy.Spec.Process.Severity != 0 {
Expand Down Expand Up @@ -1602,7 +1604,9 @@ func (dm *KubeArmorDaemon) ParseAndUpdateHostSecurityPolicy(event tp.K8sKubeArmo
}
}
}
} else if len(secPolicy.Spec.Process.MatchPatterns) > 0 {
}

if len(secPolicy.Spec.Process.MatchPatterns) > 0 {
for idx, pat := range secPolicy.Spec.Process.MatchPatterns {
if pat.Severity == 0 {
if secPolicy.Spec.Process.Severity != 0 {
Expand Down
14 changes: 7 additions & 7 deletions KubeArmor/core/unorchestratedUpdates.go
Original file line number Diff line number Diff line change
Expand Up @@ -677,21 +677,21 @@ func (dm *KubeArmorDaemon) restoreKubeArmorPolicies() {
}

} else { // HostSecurityPolicy
var hostPolicy tp.HostSecurityPolicy
var hostPolicy tp.K8sKubeArmorHostPolicy
if err := json.Unmarshal(data, &hostPolicy); err == nil {
dm.HostSecurityPolicies = append(dm.HostSecurityPolicies, hostPolicy)
hostPolicy.Metadata.Name = k.Metadata["policyName"]
dm.ParseAndUpdateHostSecurityPolicy(tp.K8sKubeArmorHostPolicyEvent{
Type: "ADDED",
Object: hostPolicy,
})
} else {
kg.Errf("Failed to unmarshal host policy: %v", err)
}
}
}
}

if len(policyFiles) != 0 {
if len(dm.HostSecurityPolicies) != 0 {
dm.UpdateHostSecurityPolicies()
}
} else {
if len(policyFiles) == 0 {
kg.Warn("No policies found for restoration")
}
}
Expand Down
20 changes: 16 additions & 4 deletions KubeArmor/enforcer/appArmorHostProfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
// AllowedHostProcessMatchPaths Function
func (ae *AppArmorEnforcer) AllowedHostProcessMatchPaths(path tp.ProcessPathType, fromSources map[string][]string) {
if len(path.FromSource) == 0 {
// TODO: Why are we not handling whitelist rules without fromsource
return
}

Expand Down Expand Up @@ -212,13 +213,24 @@ func (ae *AppArmorEnforcer) AllowedHostCapabilitiesMatchCapabilities(cap tp.Capa

// BlockedHostProcessMatchPaths Function
func (ae *AppArmorEnforcer) BlockedHostProcessMatchPaths(path tp.ProcessPathType, processBlackList *[]string, fromSources map[string][]string) {
proc := ""
if len(path.ExecName) > 0 {
proc = "/**/" + path.ExecName
} else {
proc = path.Path
}

if proc == "" {
return
}

if len(path.FromSource) == 0 {
line := ""

if path.OwnerOnly {
line = fmt.Sprintf(" owner %s ix,\n deny other %s x,\n", path.Path, path.Path)
line = fmt.Sprintf(" owner %s ix,\n deny other %s x,\n", proc, proc)
} else { // !path.OwnerOnly
line = fmt.Sprintf(" deny %s x,\n", path.Path)
line = fmt.Sprintf(" deny %s x,\n", proc)
}

if !kl.ContainsElement(*processBlackList, line) {
Expand All @@ -241,9 +253,9 @@ func (ae *AppArmorEnforcer) BlockedHostProcessMatchPaths(path tp.ProcessPathType
}

if path.OwnerOnly {
line = fmt.Sprintf(" owner %s ix,\n deny other %s x,\n", path.Path, path.Path)
line = fmt.Sprintf(" owner %s ix,\n deny other %s x,\n", proc, proc)
} else { // !path.OwnerOnly
line = fmt.Sprintf(" deny %s x,\n", path.Path)
line = fmt.Sprintf(" deny %s x,\n", proc)
}

if !kl.ContainsElement(fromSources[source], line) {
Expand Down
13 changes: 10 additions & 3 deletions KubeArmor/enforcer/appArmorProfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func (ae *AppArmorEnforcer) ResolvedProcessWhiteListConflicts(prof *Profile) {

// SetProcessMatchPaths Function
func (ae *AppArmorEnforcer) SetProcessMatchPaths(path tp.ProcessPathType, prof *Profile, deny bool, head bool) {
if deny == false {
if !deny {
prof.File = head
}
rule := RuleConfig{}
Expand All @@ -41,8 +41,11 @@ func (ae *AppArmorEnforcer) SetProcessMatchPaths(path tp.ProcessPathType, prof *
rule.OwnerOnly = path.OwnerOnly

if len(path.FromSource) == 0 {
if len(path.ExecName) > 0 {
addRuletoMap(rule, "/**/"+path.ExecName, prof.ProcessPaths)
return
}
addRuletoMap(rule, path.Path, prof.ProcessPaths)

return
}

Expand All @@ -58,12 +61,16 @@ func (ae *AppArmorEnforcer) SetProcessMatchPaths(path tp.ProcessPathType, prof *
fromsource.Rules.Init()
prof.FromSource[source] = fromsource
}
if deny == false {
if !deny {
if val, ok := prof.FromSource[source]; ok {
val.File = head
prof.FromSource[source] = val
}
}
if len(path.ExecName) > 0 {
addRuletoMap(rule, "/**/"+path.ExecName, prof.FromSource[source].ProcessPaths)
continue
}
addRuletoMap(rule, path.Path, prof.FromSource[source].ProcessPaths)
}
}
Expand Down
Binary file modified KubeArmor/enforcer/bpflsm/enforcer_bpfeb.o
Binary file not shown.
Binary file modified KubeArmor/enforcer/bpflsm/enforcer_bpfel.o
Binary file not shown.
Binary file modified KubeArmor/enforcer/bpflsm/enforcer_path_bpfeb.o
Binary file not shown.
Binary file modified KubeArmor/enforcer/bpflsm/enforcer_path_bpfel.o
Binary file not shown.
15 changes: 10 additions & 5 deletions KubeArmor/enforcer/bpflsm/rulesHandling.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,24 +115,29 @@ func (be *BPFEnforcer) UpdateContainerRules(id string, securityPolicies []tp.Sec
}
if len(path.FromSource) == 0 {
var key InnerKey
copy(key.Path[:], []byte(path.Path))
if len(path.ExecName) > 0 {
copy(key.Path[:], []byte(path.ExecName))
} else {
copy(key.Path[:], []byte(path.Path))
}
if path.Action == "Allow" {
newrules.ProcWhiteListPosture = true
newrules.ProcessRuleList[key] = val

} else if path.Action == "Block" {
val[PROCESS] = val[PROCESS] | DENY
newrules.ProcessRuleList[key] = val
}
} else {
for _, src := range path.FromSource {
var key InnerKey
copy(key.Path[:], []byte(path.Path))
if len(path.ExecName) > 0 {
copy(key.Path[:], []byte(path.ExecName))
} else {
copy(key.Path[:], []byte(path.Path))
}
copy(key.Source[:], []byte(src.Path))
if path.Action == "Allow" {

newrules.ProcWhiteListPosture = true

newrules.ProcessRuleList[key] = val
} else if path.Action == "Block" {
val[PROCESS] = val[PROCESS] | DENY
Expand Down
11 changes: 9 additions & 2 deletions KubeArmor/feeder/policyMatcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,13 @@ func (fd *Feeder) newMatchPolicy(policyEnabled int, policyName, src string, mp i
match.Message = ppt.Message

match.Operation = "Process"
match.Resource = ppt.Path
match.ResourceType = "Path"
if len(ppt.ExecName) > 0 {
match.Resource = ppt.ExecName
match.ResourceType = "ExecName"
} else {
match.Resource = ppt.Path
match.ResourceType = "Path"
}

match.OwnerOnly = ppt.OwnerOnly

Expand Down Expand Up @@ -1023,6 +1028,8 @@ func (fd *Feeder) UpdateMatchedPolicy(log tp.Log) tp.Log {
procMatch := secPolicy.Regexp.MatchString(log.ProcessName) // pattern (secPolicy.Resource) -> string (log.Resource)
matchedRegex = fileMatch || procMatch
}
case "ExecName":
matchedRegex = strings.HasSuffix(log.ProcessName, "/"+secPolicy.Resource) // processpath = */execname
}

// match resources
Expand Down
3 changes: 2 additions & 1 deletion KubeArmor/types/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -333,7 +333,8 @@ type MatchSourceType struct {

// ProcessPathType Structure
type ProcessPathType struct {
Path string `json:"path"`
Path string `json:"path,omitempty"`
ExecName string `json:"execname,omitempty"`
OwnerOnly bool `json:"ownerOnly,omitempty"`
FromSource []MatchSourceType `json:"fromSource,omitempty"`

Expand Down
5 changes: 3 additions & 2 deletions deployments/CRD/KubeArmorHostPolicy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,9 @@ spec:
- Audit
- Block
type: string
execname:
pattern: ^[^\/]+$
type: string
fromSource:
items:
properties:
Expand All @@ -368,8 +371,6 @@ spec:
items:
type: string
type: array
required:
- path
type: object
type: array
matchPatterns:
Expand Down
Loading

0 comments on commit 68bc93b

Please sign in to comment.