aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn Johansen <john.johansen@canonical.com>2010-07-29 17:48:05 -0400
committerJames Morris <jmorris@namei.org>2010-08-02 01:38:35 -0400
commit0ed3b28ab8bf460a3a026f3f1782bf4c53840184 (patch)
tree9da3a2c6d9f55d3166726fe7c51671a6029c1269
parentb5e95b48685e3481139a5634d14d630d12c7d5ce (diff)
AppArmor: mediation of non file objects
ipc: AppArmor ipc is currently limited to mediation done by file mediation and basic ptrace tests. Improved mediation is a wip. rlimits: AppArmor provides basic abilities to set and control rlimits at a per profile level. Only resources specified in a profile are controled or set. AppArmor rules set the hard limit to a value <= to the current hard limit (ie. they can not currently raise hard limits), and if necessary will lower the soft limit to the new hard limit value. AppArmor does not track resource limits to reset them when a profile is left so that children processes inherit the limits set by the parent even if they are not confined by the same profile. Capabilities: AppArmor provides a per profile mask of capabilities, that will further restrict. Signed-off-by: John Johansen <john.johansen@canonical.com> Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r--security/apparmor/capability.c141
-rw-r--r--security/apparmor/include/capability.h45
-rw-r--r--security/apparmor/include/ipc.h28
-rw-r--r--security/apparmor/include/resource.h46
-rw-r--r--security/apparmor/ipc.c114
-rw-r--r--security/apparmor/resource.c134
6 files changed, 508 insertions, 0 deletions
diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c
new file mode 100644
index 000000000000..9982c48def4e
--- /dev/null
+++ b/security/apparmor/capability.c
@@ -0,0 +1,141 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor capability mediation functions
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#include <linux/capability.h>
16#include <linux/errno.h>
17#include <linux/gfp.h>
18
19#include "include/apparmor.h"
20#include "include/capability.h"
21#include "include/context.h"
22#include "include/policy.h"
23#include "include/audit.h"
24
25/*
26 * Table of capability names: we generate it from capabilities.h.
27 */
28#include "capability_names.h"
29
30struct audit_cache {
31 struct aa_profile *profile;
32 kernel_cap_t caps;
33};
34
35static DEFINE_PER_CPU(struct audit_cache, audit_cache);
36
37/**
38 * audit_cb - call back for capability components of audit struct
39 * @ab - audit buffer (NOT NULL)
40 * @va - audit struct to audit data from (NOT NULL)
41 */
42static void audit_cb(struct audit_buffer *ab, void *va)
43{
44 struct common_audit_data *sa = va;
45 audit_log_format(ab, " capname=");
46 audit_log_untrustedstring(ab, capability_names[sa->u.cap]);
47}
48
49/**
50 * audit_caps - audit a capability
51 * @profile: profile confining task (NOT NULL)
52 * @task: task capability test was performed against (NOT NULL)
53 * @cap: capability tested
54 * @error: error code returned by test
55 *
56 * Do auditing of capability and handle, audit/complain/kill modes switching
57 * and duplicate message elimination.
58 *
59 * Returns: 0 or sa->error on success, error code on failure
60 */
61static int audit_caps(struct aa_profile *profile, struct task_struct *task,
62 int cap, int error)
63{
64 struct audit_cache *ent;
65 int type = AUDIT_APPARMOR_AUTO;
66 struct common_audit_data sa;
67 COMMON_AUDIT_DATA_INIT(&sa, CAP);
68 sa.tsk = task;
69 sa.u.cap = cap;
70 sa.aad.op = OP_CAPABLE;
71 sa.aad.error = error;
72
73 if (likely(!error)) {
74 /* test if auditing is being forced */
75 if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
76 !cap_raised(profile->caps.audit, cap)))
77 return 0;
78 type = AUDIT_APPARMOR_AUDIT;
79 } else if (KILL_MODE(profile) ||
80 cap_raised(profile->caps.kill, cap)) {
81 type = AUDIT_APPARMOR_KILL;
82 } else if (cap_raised(profile->caps.quiet, cap) &&
83 AUDIT_MODE(profile) != AUDIT_NOQUIET &&
84 AUDIT_MODE(profile) != AUDIT_ALL) {
85 /* quiet auditing */
86 return error;
87 }
88
89 /* Do simple duplicate message elimination */
90 ent = &get_cpu_var(audit_cache);
91 if (profile == ent->profile && cap_raised(ent->caps, cap)) {
92 put_cpu_var(audit_cache);
93 if (COMPLAIN_MODE(profile))
94 return complain_error(error);
95 return error;
96 } else {
97 aa_put_profile(ent->profile);
98 ent->profile = aa_get_profile(profile);
99 cap_raise(ent->caps, cap);
100 }
101 put_cpu_var(audit_cache);
102
103 return aa_audit(type, profile, GFP_ATOMIC, &sa, audit_cb);
104}
105
106/**
107 * profile_capable - test if profile allows use of capability @cap
108 * @profile: profile being enforced (NOT NULL, NOT unconfined)
109 * @cap: capability to test if allowed
110 *
111 * Returns: 0 if allowed else -EPERM
112 */
113static int profile_capable(struct aa_profile *profile, int cap)
114{
115 return cap_raised(profile->caps.allow, cap) ? 0 : -EPERM;
116}
117
118/**
119 * aa_capable - test permission to use capability
120 * @task: task doing capability test against (NOT NULL)
121 * @profile: profile confining @task (NOT NULL)
122 * @cap: capability to be tested
123 * @audit: whether an audit record should be generated
124 *
125 * Look up capability in profile capability set.
126 *
127 * Returns: 0 on success, or else an error code.
128 */
129int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
130 int audit)
131{
132 int error = profile_capable(profile, cap);
133
134 if (!audit) {
135 if (COMPLAIN_MODE(profile))
136 return complain_error(error);
137 return error;
138 }
139
140 return audit_caps(profile, task, cap, error);
141}
diff --git a/security/apparmor/include/capability.h b/security/apparmor/include/capability.h
new file mode 100644
index 000000000000..c24d2959ea02
--- /dev/null
+++ b/security/apparmor/include/capability.h
@@ -0,0 +1,45 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor capability mediation definitions.
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#ifndef __AA_CAPABILITY_H
16#define __AA_CAPABILITY_H
17
18#include <linux/sched.h>
19
20struct aa_profile;
21
22/* aa_caps - confinement data for capabilities
23 * @allowed: capabilities mask
24 * @audit: caps that are to be audited
25 * @quiet: caps that should not be audited
26 * @kill: caps that when requested will result in the task being killed
27 * @extended: caps that are subject finer grained mediation
28 */
29struct aa_caps {
30 kernel_cap_t allow;
31 kernel_cap_t audit;
32 kernel_cap_t quiet;
33 kernel_cap_t kill;
34 kernel_cap_t extended;
35};
36
37int aa_capable(struct task_struct *task, struct aa_profile *profile, int cap,
38 int audit);
39
40static inline void aa_free_cap_rules(struct aa_caps *caps)
41{
42 /* NOP */
43}
44
45#endif /* __AA_CAPBILITY_H */
diff --git a/security/apparmor/include/ipc.h b/security/apparmor/include/ipc.h
new file mode 100644
index 000000000000..aeda0fbc8b2f
--- /dev/null
+++ b/security/apparmor/include/ipc.h
@@ -0,0 +1,28 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor ipc mediation function definitions.
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#ifndef __AA_IPC_H
16#define __AA_IPC_H
17
18#include <linux/sched.h>
19
20struct aa_profile;
21
22int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
23 struct aa_profile *tracee, unsigned int mode);
24
25int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
26 unsigned int mode);
27
28#endif /* __AA_IPC_H */
diff --git a/security/apparmor/include/resource.h b/security/apparmor/include/resource.h
new file mode 100644
index 000000000000..3c88be946494
--- /dev/null
+++ b/security/apparmor/include/resource.h
@@ -0,0 +1,46 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor resource limits function definitions.
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#ifndef __AA_RESOURCE_H
16#define __AA_RESOURCE_H
17
18#include <linux/resource.h>
19#include <linux/sched.h>
20
21struct aa_profile;
22
23/* struct aa_rlimit - rlimit settings for the profile
24 * @mask: which hard limits to set
25 * @limits: rlimit values that override task limits
26 *
27 * AppArmor rlimits are used to set confined task rlimits. Only the
28 * limits specified in @mask will be controlled by apparmor.
29 */
30struct aa_rlimit {
31 unsigned int mask;
32 struct rlimit limits[RLIM_NLIMITS];
33};
34
35int aa_map_resource(int resource);
36int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
37 struct rlimit *new_rlim);
38
39void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new);
40
41static inline void aa_free_rlimit_rules(struct aa_rlimit *rlims)
42{
43 /* NOP */
44}
45
46#endif /* __AA_RESOURCE_H */
diff --git a/security/apparmor/ipc.c b/security/apparmor/ipc.c
new file mode 100644
index 000000000000..9013a78a1663
--- /dev/null
+++ b/security/apparmor/ipc.c
@@ -0,0 +1,114 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor ipc mediation
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#include <linux/gfp.h>
16#include <linux/ptrace.h>
17
18#include "include/audit.h"
19#include "include/capability.h"
20#include "include/context.h"
21#include "include/policy.h"
22
23/* call back to audit ptrace fields */
24static void audit_cb(struct audit_buffer *ab, void *va)
25{
26 struct common_audit_data *sa = va;
27 audit_log_format(ab, " target=");
28 audit_log_untrustedstring(ab, sa->aad.target);
29}
30
31/**
32 * aa_audit_ptrace - do auditing for ptrace
33 * @profile: profile being enforced (NOT NULL)
34 * @target: profile being traced (NOT NULL)
35 * @error: error condition
36 *
37 * Returns: %0 or error code
38 */
39static int aa_audit_ptrace(struct aa_profile *profile,
40 struct aa_profile *target, int error)
41{
42 struct common_audit_data sa;
43 COMMON_AUDIT_DATA_INIT(&sa, NONE);
44 sa.aad.op = OP_PTRACE;
45 sa.aad.target = target;
46 sa.aad.error = error;
47
48 return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_ATOMIC, &sa,
49 audit_cb);
50}
51
52/**
53 * aa_may_ptrace - test if tracer task can trace the tracee
54 * @tracer_task: task who will do the tracing (NOT NULL)
55 * @tracer: profile of the task doing the tracing (NOT NULL)
56 * @tracee: task to be traced
57 * @mode: whether PTRACE_MODE_READ || PTRACE_MODE_ATTACH
58 *
59 * Returns: %0 else error code if permission denied or error
60 */
61int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
62 struct aa_profile *tracee, unsigned int mode)
63{
64 /* TODO: currently only based on capability, not extended ptrace
65 * rules,
66 * Test mode for PTRACE_MODE_READ || PTRACE_MODE_ATTACH
67 */
68
69 if (unconfined(tracer) || tracer == tracee)
70 return 0;
71 /* log this capability request */
72 return aa_capable(tracer_task, tracer, CAP_SYS_PTRACE, 1);
73}
74
75/**
76 * aa_ptrace - do ptrace permission check and auditing
77 * @tracer: task doing the tracing (NOT NULL)
78 * @tracee: task being traced (NOT NULL)
79 * @mode: ptrace mode either PTRACE_MODE_READ || PTRACE_MODE_ATTACH
80 *
81 * Returns: %0 else error code if permission denied or error
82 */
83int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
84 unsigned int mode)
85{
86 /*
87 * tracer can ptrace tracee when
88 * - tracer is unconfined ||
89 * - tracer is in complain mode
90 * - tracer has rules allowing it to trace tracee currently this is:
91 * - confined by the same profile ||
92 * - tracer profile has CAP_SYS_PTRACE
93 */
94
95 struct aa_profile *tracer_p;
96 /* cred released below */
97 const struct cred *cred = get_task_cred(tracer);
98 int error = 0;
99 tracer_p = aa_cred_profile(cred);
100
101 if (!unconfined(tracer_p)) {
102 /* lcred released below */
103 struct cred *lcred = get_task_cred(tracee);
104 struct aa_profile *tracee_p = aa_cred_profile(lcred);
105
106 error = aa_may_ptrace(tracer, tracer_p, tracee_p, mode);
107 error = aa_audit_ptrace(tracer_p, tracee_p, error);
108
109 put_cred(lcred);
110 }
111 put_cred(cred);
112
113 return error;
114}
diff --git a/security/apparmor/resource.c b/security/apparmor/resource.c
new file mode 100644
index 000000000000..4a368f1fd36d
--- /dev/null
+++ b/security/apparmor/resource.c
@@ -0,0 +1,134 @@
1/*
2 * AppArmor security module
3 *
4 * This file contains AppArmor resource mediation and attachment
5 *
6 * Copyright (C) 1998-2008 Novell/SUSE
7 * Copyright 2009-2010 Canonical Ltd.
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License as
11 * published by the Free Software Foundation, version 2 of the
12 * License.
13 */
14
15#include <linux/audit.h>
16
17#include "include/audit.h"
18#include "include/resource.h"
19#include "include/policy.h"
20
21/*
22 * Table of rlimit names: we generate it from resource.h.
23 */
24#include "rlim_names.h"
25
26/* audit callback for resource specific fields */
27static void audit_cb(struct audit_buffer *ab, void *va)
28{
29 struct common_audit_data *sa = va;
30
31 audit_log_format(ab, " rlimit=%s value=%lu",
32 rlim_names[sa->aad.rlim.rlim], sa->aad.rlim.max);
33}
34
35/**
36 * audit_resource - audit setting resource limit
37 * @profile: profile being enforced (NOT NULL)
38 * @resoure: rlimit being auditing
39 * @value: value being set
40 * @error: error value
41 *
42 * Returns: 0 or sa->error else other error code on failure
43 */
44static int audit_resource(struct aa_profile *profile, unsigned int resource,
45 unsigned long value, int error)
46{
47 struct common_audit_data sa;
48
49 COMMON_AUDIT_DATA_INIT(&sa, NONE);
50 sa.aad.op = OP_SETRLIMIT,
51 sa.aad.rlim.rlim = resource;
52 sa.aad.rlim.max = value;
53 sa.aad.error = error;
54 return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_KERNEL, &sa,
55 audit_cb);
56}
57
58/**
59 * aa_map_resouce - map compiled policy resource to internal #
60 * @resource: flattened policy resource number
61 *
62 * Returns: resource # for the current architecture.
63 *
64 * rlimit resource can vary based on architecture, map the compiled policy
65 * resource # to the internal representation for the architecture.
66 */
67int aa_map_resource(int resource)
68{
69 return rlim_map[resource];
70}
71
72/**
73 * aa_task_setrlimit - test permission to set an rlimit
74 * @profile - profile confining the task (NOT NULL)
75 * @resource - the resource being set
76 * @new_rlim - the new resource limit (NOT NULL)
77 *
78 * Control raising the processes hard limit.
79 *
80 * Returns: 0 or error code if setting resource failed
81 */
82int aa_task_setrlimit(struct aa_profile *profile, unsigned int resource,
83 struct rlimit *new_rlim)
84{
85 int error = 0;
86
87 if (profile->rlimits.mask & (1 << resource) &&
88 new_rlim->rlim_max > profile->rlimits.limits[resource].rlim_max)
89
90 error = audit_resource(profile, resource, new_rlim->rlim_max,
91 -EACCES);
92
93 return error;
94}
95
96/**
97 * __aa_transition_rlimits - apply new profile rlimits
98 * @old: old profile on task (NOT NULL)
99 * @new: new profile with rlimits to apply (NOT NULL)
100 */
101void __aa_transition_rlimits(struct aa_profile *old, struct aa_profile *new)
102{
103 unsigned int mask = 0;
104 struct rlimit *rlim, *initrlim;
105 int i;
106
107 /* for any rlimits the profile controlled reset the soft limit
108 * to the less of the tasks hard limit and the init tasks soft limit
109 */
110 if (old->rlimits.mask) {
111 for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) {
112 if (old->rlimits.mask & mask) {
113 rlim = current->signal->rlim + i;
114 initrlim = init_task.signal->rlim + i;
115 rlim->rlim_cur = min(rlim->rlim_max,
116 initrlim->rlim_cur);
117 }
118 }
119 }
120
121 /* set any new hard limits as dictated by the new profile */
122 if (!new->rlimits.mask)
123 return;
124 for (i = 0, mask = 1; i < RLIM_NLIMITS; i++, mask <<= 1) {
125 if (!(new->rlimits.mask & mask))
126 continue;
127
128 rlim = current->signal->rlim + i;
129 rlim->rlim_max = min(rlim->rlim_max,
130 new->rlimits.limits[i].rlim_max);
131 /* soft limit should not exceed hard limit */
132 rlim->rlim_cur = min(rlim->rlim_cur, rlim->rlim_max);
133 }
134}