~ubuntu-branches/ubuntu/lucid/apparmor/lucid-proposed

« back to all changes in this revision

Viewing changes to kernel-patches/2.6.27/apparmor-network.diff

  • Committer: Bazaar Package Importer
  • Author(s): Jamie Strandboge
  • Date: 2010-11-02 13:33:15 UTC
  • mfrom: (99.1.11 maverick-proposed)
  • Revision ID: james.westby@ubuntu.com-20101102133315-jcil3cqqiz6lr0km
Tags: 2.5.1-0ubuntu0.10.04.1
* Backport 2.5.1-0ubuntu0.10.10.1 from maverick for userspace tools to work
  with newer kernels (LP: #660077)
  NOTE: user-tmp now uses 'owner' match, so non-default profiles will have
  to be adjusted when 2 separately confined applications that both use the
  user-tmp abstraction depend on being able to cooperatively share files
  with each other in /tmp or /var/tmp.
* remove the following patches (features not appropriate for SRU):
  - 0002-add-chromium-browser.patch
  - 0003-local-includes.patch
  - 0004-ubuntu-abstractions-updates.patch
* debian/rules (this makes it the same as what was shipped in 10.04 LTS
  release):
  - don't ship aa-update-browser and its man page (requires
    0004-ubuntu-abstractions-updates.patch)
  - don't ship apparmor.d/local/ (requires 0003-local-includes.patch)
  - don't use dh_apparmor (not in Ubuntu 10.04 LTS)
  - don't ship chromium profile
* remove debian/profiles/chromium-browser
* remove debian/aa-update-browser*
* debian/apparmor-profiles.postinst: revert to that in lucid release
  (requires dh_apparmor and 0002-add-chromium-browser.patch)
* remove debian/apparmor-profiles.postrm: doesn't make sense without
  0002-add-chromium-browser.patch
* debian/control:
  - revert Build-Depends on debhelper (>= 5)
  - revert Standards-Version to 3.8.4
  - revert Vcs-Bzr
  - use Conflicts/Replaces version that was in Ubuntu 10.04 LTS
* debian/patches/0011-lucid-compat-dbus.patch: move /var/lib/dbus/machine-id
  back into dbus, since profiles on 10.04 LTS expect it there
* debian/patches/0012-lucid-compat-kde.patch: add kde4-config to kde
  abstraction, since the firefox profile on Ubuntu 10.04 LTS expects it to
  be there

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
From: John Johansen <jjohansen@suse.de>
2
 
Subject: AppArmor: Simplified network controls for AppArmor
3
 
 
4
 
Simple network control determining which network families a confined
5
 
application has access to.
6
 
 
7
 
Signed-off-by: John Johansen <jjohansen@suse.de>
8
 
 
9
 
---
10
 
 security/apparmor/Makefile           |    7 +
11
 
 security/apparmor/apparmor.h         |    9 ++
12
 
 security/apparmor/lsm.c              |  129 ++++++++++++++++++++++++++++++++++-
13
 
 security/apparmor/main.c             |  107 ++++++++++++++++++++++++++++-
14
 
 security/apparmor/module_interface.c |   26 ++++++-
15
 
 5 files changed, 271 insertions(+), 7 deletions(-)
16
 
 
17
 
--- a/security/apparmor/Makefile
18
 
+++ b/security/apparmor/Makefile
19
 
@@ -8,6 +8,11 @@ apparmor-y := main.o list.o procattr.o l
20
 
 quiet_cmd_make-caps = GEN     $@
21
 
 cmd_make-caps = sed -n -e "/CAP_FS_MASK/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\$$/[\\2]  = \"\\1\",/p" $< | tr A-Z a-z > $@
22
 
 
23
 
-$(obj)/main.o : $(obj)/capability_names.h
24
 
+quiet_cmd_make-af = GEN     $@
25
 
+cmd_make-af = sed -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "s/^\#define[ \\t]\\+AF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/[\\2]  = \"\\1\",/p" $< | tr A-Z a-z > $@
26
 
+
27
 
+$(obj)/main.o : $(obj)/capability_names.h $(obj)/af_names.h
28
 
 $(obj)/capability_names.h : $(srctree)/include/linux/capability.h
29
 
        $(call cmd,make-caps)
30
 
+$(obj)/af_names.h : $(srctree)/include/linux/socket.h
31
 
+       $(call cmd,make-af)
32
 
--- a/security/apparmor/apparmor.h
33
 
+++ b/security/apparmor/apparmor.h
34
 
@@ -16,6 +16,8 @@
35
 
 #include <linux/fs.h>
36
 
 #include <linux/binfmts.h>
37
 
 #include <linux/rcupdate.h>
38
 
+#include <linux/socket.h>
39
 
+#include <net/sock.h>
40
 
 
41
 
 /*
42
 
  * We use MAY_READ, MAY_WRITE, MAY_EXEC, MAY_APPEND and the following flags
43
 
@@ -212,6 +214,9 @@ struct aa_profile {
44
 
        struct list_head task_contexts;
45
 
        spinlock_t lock;
46
 
        unsigned long int_flags;
47
 
+       u16 network_families[AF_MAX];
48
 
+       u16 audit_network[AF_MAX];
49
 
+       u16 quiet_network[AF_MAX];
50
 
 };
51
 
 
52
 
 extern struct list_head profile_ns_list;
53
 
@@ -258,6 +263,7 @@ struct aa_audit {
54
 
        int request_mask, denied_mask, audit_mask;
55
 
        struct iattr *iattr;
56
 
        pid_t task, parent;
57
 
+       int family, type, protocol;
58
 
        int error_code;
59
 
 };
60
 
 
61
 
@@ -319,6 +325,9 @@ extern void aa_change_task_context(struc
62
 
                                   struct aa_profile *previous_profile);
63
 
 extern int aa_may_ptrace(struct aa_task_context *cxt,
64
 
                         struct aa_profile *tracee);
65
 
+extern int aa_net_perm(struct aa_profile *profile, char *operation,
66
 
+                       int family, int type, int protocol);
67
 
+extern int aa_revalidate_sk(struct sock *sk, char *operation);
68
 
 
69
 
 /* lsm.c */
70
 
 extern int apparmor_initialized;
71
 
--- a/security/apparmor/lsm.c
72
 
+++ b/security/apparmor/lsm.c
73
 
@@ -18,6 +18,7 @@
74
 
 #include <linux/ctype.h>
75
 
 #include <linux/sysctl.h>
76
 
 #include <linux/audit.h>
77
 
+#include <net/sock.h>
78
 
 
79
 
 #include "apparmor.h"
80
 
 #include "inline.h"
81
 
@@ -680,6 +681,117 @@ static void apparmor_task_free_security(
82
 
        aa_release(task);
83
 
 }
84
 
 
85
 
+static int apparmor_socket_create(int family, int type, int protocol, int kern)
86
 
+{
87
 
+       struct aa_profile *profile;
88
 
+       int error = 0;
89
 
+
90
 
+       if (kern)
91
 
+               return 0;
92
 
+
93
 
+       profile = aa_get_profile(current);
94
 
+       if (profile)
95
 
+               error = aa_net_perm(profile, "socket_create", family,
96
 
+                                                       type, protocol);
97
 
+       aa_put_profile(profile);
98
 
+
99
 
+       return error;
100
 
+}
101
 
+
102
 
+static int apparmor_socket_post_create(struct socket *sock, int family,
103
 
+                                       int type, int protocol, int kern)
104
 
+{
105
 
+       struct sock *sk = sock->sk;
106
 
+
107
 
+       if (kern)
108
 
+               return 0;
109
 
+
110
 
+       return aa_revalidate_sk(sk, "socket_post_create");
111
 
+}
112
 
+
113
 
+static int apparmor_socket_bind(struct socket *sock,
114
 
+                               struct sockaddr *address, int addrlen)
115
 
+{
116
 
+       struct sock *sk = sock->sk;
117
 
+
118
 
+       return aa_revalidate_sk(sk, "socket_bind");
119
 
+}
120
 
+
121
 
+static int apparmor_socket_connect(struct socket *sock,
122
 
+                                       struct sockaddr *address, int addrlen)
123
 
+{
124
 
+       struct sock *sk = sock->sk;
125
 
+
126
 
+       return aa_revalidate_sk(sk, "socket_connect");
127
 
+}
128
 
+
129
 
+static int apparmor_socket_listen(struct socket *sock, int backlog)
130
 
+{
131
 
+       struct sock *sk = sock->sk;
132
 
+
133
 
+       return aa_revalidate_sk(sk, "socket_listen");
134
 
+}
135
 
+
136
 
+static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
137
 
+{
138
 
+       struct sock *sk = sock->sk;
139
 
+
140
 
+       return aa_revalidate_sk(sk, "socket_accept");
141
 
+}
142
 
+
143
 
+static int apparmor_socket_sendmsg(struct socket *sock,
144
 
+                                       struct msghdr *msg, int size)
145
 
+{
146
 
+       struct sock *sk = sock->sk;
147
 
+
148
 
+       return aa_revalidate_sk(sk, "socket_sendmsg");
149
 
+}
150
 
+
151
 
+static int apparmor_socket_recvmsg(struct socket *sock,
152
 
+                                  struct msghdr *msg, int size, int flags)
153
 
+{
154
 
+       struct sock *sk = sock->sk;
155
 
+
156
 
+       return aa_revalidate_sk(sk, "socket_recvmsg");
157
 
+}
158
 
+
159
 
+static int apparmor_socket_getsockname(struct socket *sock)
160
 
+{
161
 
+       struct sock *sk = sock->sk;
162
 
+
163
 
+       return aa_revalidate_sk(sk, "socket_getsockname");
164
 
+}
165
 
+
166
 
+static int apparmor_socket_getpeername(struct socket *sock)
167
 
+{
168
 
+       struct sock *sk = sock->sk;
169
 
+
170
 
+       return aa_revalidate_sk(sk, "socket_getpeername");
171
 
+}
172
 
+
173
 
+static int apparmor_socket_getsockopt(struct socket *sock, int level,
174
 
+                                       int optname)
175
 
+{
176
 
+       struct sock *sk = sock->sk;
177
 
+
178
 
+       return aa_revalidate_sk(sk, "socket_getsockopt");
179
 
+}
180
 
+
181
 
+static int apparmor_socket_setsockopt(struct socket *sock, int level,
182
 
+                                       int optname)
183
 
+{
184
 
+       struct sock *sk = sock->sk;
185
 
+
186
 
+       return aa_revalidate_sk(sk, "socket_setsockopt");
187
 
+}
188
 
+
189
 
+static int apparmor_socket_shutdown(struct socket *sock, int how)
190
 
+{
191
 
+       struct sock *sk = sock->sk;
192
 
+
193
 
+       return aa_revalidate_sk(sk, "socket_shutdown");
194
 
+}
195
 
+
196
 
 static int apparmor_getprocattr(struct task_struct *task, char *name,
197
 
                                char **value)
198
 
 {
199
 
@@ -780,9 +892,6 @@ struct security_operations apparmor_ops
200
 
        .capable =                      apparmor_capable,
201
 
        .syslog =                       cap_syslog,
202
 
 
203
 
-       .netlink_send =                 cap_netlink_send,
204
 
-       .netlink_recv =                 cap_netlink_recv,
205
 
-
206
 
        .bprm_apply_creds =             cap_bprm_apply_creds,
207
 
        .bprm_set_security =            apparmor_bprm_set_security,
208
 
        .bprm_secureexec =              apparmor_bprm_secureexec,
209
 
@@ -820,6 +929,20 @@ struct security_operations apparmor_ops
210
 
 
211
 
        .getprocattr =                  apparmor_getprocattr,
212
 
        .setprocattr =                  apparmor_setprocattr,
213
 
+
214
 
+       .socket_create =                apparmor_socket_create,
215
 
+       .socket_post_create =           apparmor_socket_post_create,
216
 
+       .socket_bind =                  apparmor_socket_bind,
217
 
+       .socket_connect =               apparmor_socket_connect,
218
 
+       .socket_listen =                apparmor_socket_listen,
219
 
+       .socket_accept =                apparmor_socket_accept,
220
 
+       .socket_sendmsg =               apparmor_socket_sendmsg,
221
 
+       .socket_recvmsg =               apparmor_socket_recvmsg,
222
 
+       .socket_getsockname =           apparmor_socket_getsockname,
223
 
+       .socket_getpeername =           apparmor_socket_getpeername,
224
 
+       .socket_getsockopt =            apparmor_socket_getsockopt,
225
 
+       .socket_setsockopt =            apparmor_socket_setsockopt,
226
 
+       .socket_shutdown =              apparmor_socket_shutdown,
227
 
 };
228
 
 
229
 
 void info_message(const char *str)
230
 
--- a/security/apparmor/main.c
231
 
+++ b/security/apparmor/main.c
232
 
@@ -14,6 +14,9 @@
233
 
 #include <linux/audit.h>
234
 
 #include <linux/mount.h>
235
 
 #include <linux/ptrace.h>
236
 
+#include <linux/socket.h>
237
 
+#include <linux/net.h>
238
 
+#include <net/sock.h>
239
 
 
240
 
 #include "apparmor.h"
241
 
 
242
 
@@ -116,6 +119,24 @@ static void aa_audit_file_mask(struct au
243
 
        audit_log_format(ab, " %s=\"%s::%s\"", name, user, other);
244
 
 }
245
 
 
246
 
+static const char *address_families[] = {
247
 
+#include "af_names.h"
248
 
+};
249
 
+
250
 
+static const char *sock_types[] = {
251
 
+       "unknown(0)",
252
 
+       "stream",
253
 
+       "dgram",
254
 
+       "raw",
255
 
+       "rdm",
256
 
+       "seqpacket",
257
 
+       "dccp",
258
 
+       "unknown(7)",
259
 
+       "unknown(8)",
260
 
+       "unknown(9)",
261
 
+       "packet",
262
 
+};
263
 
+
264
 
 /**
265
 
  * aa_audit - Log an audit event to the audit subsystem
266
 
  * @profile: profile to check against
267
 
@@ -187,7 +208,25 @@ static int aa_audit_base(struct aa_profi
268
 
                audit_log_untrustedstring(ab, sa->name2);
269
 
        }
270
 
 
271
 
-       audit_log_format(ab, " pid=%d", current->pid);
272
 
+       if (sa->family || sa->type) {
273
 
+               if (address_families[sa->family])
274
 
+                       audit_log_format(ab, " family=\"%s\"",
275
 
+                                        address_families[sa->family]);
276
 
+               else
277
 
+                       audit_log_format(ab, " family=\"unknown(%d)\"",
278
 
+                                        sa->family);
279
 
+
280
 
+               if (sock_types[sa->type])
281
 
+                       audit_log_format(ab, " sock_type=\"%s\"",
282
 
+                                        sock_types[sa->type]);
283
 
+               else
284
 
+                       audit_log_format(ab, " sock_type=\"unknown(%d)\"",
285
 
+                                        sa->type);
286
 
+
287
 
+               audit_log_format(ab, " protocol=%d", sa->protocol);
288
 
+       }
289
 
+
290
 
+        audit_log_format(ab, " pid=%d", current->pid);
291
 
 
292
 
        if (profile) {
293
 
                audit_log_format(ab, " profile=");
294
 
@@ -768,6 +807,72 @@ int aa_link(struct aa_profile *profile,
295
 
 
296
 
        return error;
297
 
 }
298
 
+
299
 
+int aa_net_perm(struct aa_profile *profile, char *operation,
300
 
+               int family, int type, int protocol)
301
 
+{
302
 
+       struct aa_audit sa;
303
 
+       int error = 0;
304
 
+       u16 family_mask, audit_mask, quiet_mask;
305
 
+
306
 
+       if ((family < 0) || (family >= AF_MAX))
307
 
+               return -EINVAL;
308
 
+
309
 
+       if ((type < 0) || (type >= SOCK_MAX))
310
 
+               return -EINVAL;
311
 
+
312
 
+       /* unix domain and netlink sockets are handled by ipc */
313
 
+       if (family == AF_UNIX || family == AF_NETLINK)
314
 
+               return 0;
315
 
+
316
 
+       family_mask = profile->network_families[family];
317
 
+       audit_mask = profile->audit_network[family];
318
 
+       quiet_mask = profile->quiet_network[family];
319
 
+
320
 
+       error = (family_mask & (1 << type)) ? 0 : -EACCES;
321
 
+
322
 
+       memset(&sa, 0, sizeof(sa));
323
 
+       sa.operation = operation;
324
 
+       sa.gfp_mask = GFP_KERNEL;
325
 
+       sa.family = family;
326
 
+       sa.type = type;
327
 
+       sa.protocol = protocol;
328
 
+       sa.error_code = error;
329
 
+
330
 
+       if (likely(!error)) {
331
 
+               if (!PROFILE_AUDIT(profile) && !(family_mask & audit_mask))
332
 
+                       return 0;
333
 
+       } else if (!((1 << type) & ~quiet_mask)) {
334
 
+               return error;
335
 
+       }
336
 
+
337
 
+       error = aa_audit(profile, &sa);
338
 
+
339
 
+       return error;
340
 
+}
341
 
+
342
 
+int aa_revalidate_sk(struct sock *sk, char *operation)
343
 
+{
344
 
+       struct aa_profile *profile;
345
 
+       int error = 0;
346
 
+
347
 
+       /* this is some debugging code to flush out the network hooks that
348
 
+          that are called in interrupt context */
349
 
+       if (in_interrupt()) {
350
 
+               printk("AppArmor Debug: Hook being called from interrupt context\n");
351
 
+               dump_stack();
352
 
+               return 0;
353
 
+       }
354
 
+
355
 
+       profile = aa_get_profile(current);
356
 
+       if (profile)
357
 
+               error = aa_net_perm(profile, operation,
358
 
+                                   sk->sk_family, sk->sk_type,
359
 
+                                   sk->sk_protocol);
360
 
+       aa_put_profile(profile);
361
 
+
362
 
+       return error;
363
 
+}
364
 
 
365
 
 /*******************************
366
 
  * Global task related functions
367
 
--- a/security/apparmor/module_interface.c
368
 
+++ b/security/apparmor/module_interface.c
369
 
@@ -321,8 +321,8 @@ static struct aa_profile *aa_unpack_prof
370
 
                                            struct aa_audit *sa)
371
 
 {
372
 
        struct aa_profile *profile = NULL;
373
 
-
374
 
-       int error = -EPROTO;
375
 
+       size_t size = 0;
376
 
+       int i, error = -EPROTO;
377
 
 
378
 
        profile = alloc_aa_profile();
379
 
        if (!profile)
380
 
@@ -355,6 +355,28 @@ static struct aa_profile *aa_unpack_prof
381
 
        if (!aa_is_u32(e, &(profile->set_caps), NULL))
382
 
                goto fail;
383
 
 
384
 
+       size = aa_is_array(e, "net_allowed_af");
385
 
+       if (size) {
386
 
+               if (size > AF_MAX)
387
 
+                       goto fail;
388
 
+
389
 
+               for (i = 0; i < size; i++) {
390
 
+                       if (!aa_is_u16(e, &profile->network_families[i], NULL))
391
 
+                               goto fail;
392
 
+                       if (!aa_is_u16(e, &profile->audit_network[i], NULL))
393
 
+                               goto fail;
394
 
+                       if (!aa_is_u16(e, &profile->quiet_network[i], NULL))
395
 
+                               goto fail;
396
 
+               }
397
 
+               if (!aa_is_nameX(e, AA_ARRAYEND, NULL))
398
 
+                       goto fail;
399
 
+               /* allow unix domain and netlink sockets they are handled
400
 
+                * by IPC
401
 
+                */
402
 
+       }
403
 
+       profile->network_families[AF_UNIX] = 0xffff;
404
 
+       profile->network_families[AF_NETLINK] = 0xffff;
405
 
+
406
 
        /* get file rules */
407
 
        profile->file_rules = aa_unpack_dfa(e);
408
 
        if (IS_ERR(profile->file_rules)) {