Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add execname support #1664

Merged
merged 10 commits into from
Mar 7, 2024
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);
daemon1024 marked this conversation as resolved.
Show resolved Hide resolved
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 @@ -918,7 +918,7 @@
new := true
for _, policy := range endPoint.SecurityPolicies {
if policy.Metadata["namespaceName"] == secPolicy.Metadata["namespaceName"] && policy.Metadata["policyName"] == secPolicy.Metadata["policyName"] {
new = false

Check warning on line 921 in KubeArmor/core/kubeUpdate.go

View workflow job for this annotation

GitHub Actions / go-lint

redefinition of the built-in function new
break
}
}
Expand Down Expand Up @@ -1568,7 +1568,9 @@
}
}
}
} 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 @@
}
}
}
} 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
daemon1024 marked this conversation as resolved.
Show resolved Hide resolved
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
Loading