~ubuntu-branches/ubuntu/wily/apparmor/wily

« back to all changes in this revision

Viewing changes to parser/parser_yacc.y

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook
  • Date: 2011-04-27 10:38:07 UTC
  • mfrom: (5.1.118 natty)
  • Revision ID: james.westby@ubuntu.com-20110427103807-ym3rhwys6o84ith0
Tags: 2.6.1-2
debian/copyright: clarify for some full organization names.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
%{
2
 
/* $Id: parser_yacc.y 412 2007-02-27 02:29:16Z jrjohansen $ */
3
 
 
4
2
/*
5
 
 *   Copyright (c) 1999, 2000, 2001, 2002, 2004, 2005 NOVELL (All rights reserved)
 
3
 *   Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
 
4
 *   NOVELL (All rights reserved)
 
5
 *   Copyright (c) 2010
 
6
 *   Canonical, Ltd.
6
7
 *
7
8
 *   This program is free software; you can redistribute it and/or
8
9
 *   modify it under the terms of version 2 of the GNU General Public
14
15
 *   GNU General Public License for more details.
15
16
 *
16
17
 *   You should have received a copy of the GNU General Public License
17
 
 *   along with this program; if not, contact Novell, Inc.
 
18
 *   along with this program; if not, contact Canonical, Ltd.
18
19
 */
19
20
 
20
21
#define YYERROR_VERBOSE 1
31
32
/* #define DEBUG */
32
33
 
33
34
#include "parser.h"
 
35
#include "parser_include.h"
34
36
#include <unistd.h>
35
37
#include <netinet/in.h>
36
 
#include <sys/socket.h>
37
38
#include <arpa/inet.h>
38
39
 
39
40
#include <linux/capability.h>
44
45
#ifndef CAP_AUDIT_CONTROL
45
46
#define CAP_AUDIT_CONTROL 30
46
47
#endif
47
 
 
48
 
/* A few utility defines */
 
48
#ifndef CAP_SETFCAP
 
49
#define CAP_SETFCAP          31
 
50
#endif
 
51
#ifndef CAP_MAC_OVERRIDE
 
52
#define CAP_MAC_OVERRIDE     32
 
53
#endif
49
54
 
50
55
#define CIDR_32 htonl(0xffffffff)
51
56
#define CIDR_24 htonl(0xffffff00)
52
57
#define CIDR_16 htonl(0xffff0000)
53
58
#define CIDR_8  htonl(0xff000000)
54
59
 
55
 
#define CAP_TO_MASK(x) (1 << (x))
56
 
 
57
 
static struct flagval force_complain_flags = {0, 1, 0};
58
 
 
59
 
/* from lex_config, for nice error messages */
60
 
/* extern char *current_file; */
61
 
extern int current_lineno;
 
60
/* undefine linux/capability.h CAP_TO_MASK */
 
61
#ifdef CAP_TO_MASK
 
62
#undef CAP_TO_MASK
 
63
#endif
 
64
 
 
65
#define CAP_TO_MASK(x) (1ull << (x))
62
66
 
63
67
struct value_list {
64
68
        char *value;
66
70
};
67
71
 
68
72
void free_value_list(struct value_list *list);
 
73
struct cod_entry *do_file_rule(char *namespace, char *id, int mode,
 
74
                               char *link_id, char *nt);
 
75
 
 
76
void add_local_entry(struct codomain *cod);
69
77
 
70
78
%}
71
79
 
76
84
%token TOK_MODE
77
85
%token TOK_END_OF_RULE
78
86
%token TOK_EQUALS
 
87
%token TOK_ARROW
79
88
%token TOK_ADD_ASSIGN
 
89
%token TOK_LE
80
90
%token TOK_SET_VAR
81
91
%token TOK_BOOL_VAR
82
92
%token TOK_VALUE
84
94
%token TOK_ELSE
85
95
%token TOK_NOT
86
96
%token TOK_DEFINED
87
 
 
88
 
/* network tokens */
89
 
%token TOK_IP
90
 
%token TOK_IFACE
91
 
%token TOK_ACTION
92
 
%token TOK_PORT
93
 
%token TOK_PORT_IDENT
94
 
%token TOK_NUM
 
97
%token TOK_CHANGE_PROFILE
 
98
%token TOK_NETWORK
 
99
%token TOK_HAT
 
100
%token TOK_UNSAFE
 
101
%token TOK_SAFE
95
102
%token TOK_COLON
96
 
%token TOK_SLASH
97
 
%token TOK_RANGE
98
 
%token TOK_VIA
99
 
%token TOK_TO
100
 
%token TOK_FROM
101
 
%token TOK_TCP_CONN
102
 
%token TOK_TCP_ACPT
103
 
%token TOK_TCP_CONN_ESTB
104
 
%token TOK_TCP_ACPT_ESTB
105
 
%token TOK_UDP_SEND
106
 
%token TOK_UDP_RECV
 
103
%token TOK_LINK
 
104
%token TOK_OWNER
 
105
%token TOK_OTHER
 
106
%token TOK_SUBSET
 
107
%token TOK_AUDIT
 
108
%token TOK_DENY
 
109
%token TOK_PROFILE
 
110
%token TOK_SET
 
111
%token TOK_ALIAS
 
112
%token TOK_PTRACE
 
113
 
 
114
 /* rlimits */
 
115
%token TOK_RLIMIT
 
116
%token TOK_SOFT_RLIMIT
 
117
%token TOK_RLIMIT_CPU
 
118
%token TOK_RLIMIT_FSIZE
 
119
%token TOK_RLIMIT_DATA
 
120
%token TOK_RLIMIT_STACK
 
121
%token TOK_RLIMIT_CORE
 
122
%token TOK_RLIMIT_RSS
 
123
%token TOK_RLIMIT_NOFILE
 
124
%token TOK_RLIMIT_OFILE
 
125
%token TOK_RLIMIT_AS
 
126
%token TOK_RLIMIT_NPROC
 
127
%token TOK_RLIMIT_MEMLOCK
 
128
%token TOK_RLIMIT_LOCKS
 
129
%token TOK_RLIMIT_SIGPENDING
 
130
%token TOK_RLIMIT_MSGQUEUE
 
131
%token TOK_RLIMIT_NICE
 
132
%token TOK_RLIMIT_RTPRIO
107
133
 
108
134
/* capabilities */
109
135
%token TOK_CAPABILITY
110
 
%token TOK_CAP_CHOWN
111
 
%token TOK_CAP_DAC_OVERRIDE
112
 
%token TOK_CAP_DAC_READ_SEARCH
113
 
%token TOK_CAP_FOWNER
114
 
%token TOK_CAP_FSETID
115
 
%token TOK_CAP_KILL
116
 
%token TOK_CAP_SETGID
117
 
%token TOK_CAP_SETUID
118
 
%token TOK_CAP_SETPCAP
119
 
%token TOK_CAP_LINUX_IMMUTABLE
120
 
%token TOK_CAP_NET_BIND_SERVICE
121
 
%token TOK_CAP_NET_BROADCAST
122
 
%token TOK_CAP_NET_ADMIN
123
 
%token TOK_CAP_NET_RAW
124
 
%token TOK_CAP_IPC_LOCK
125
 
%token TOK_CAP_IPC_OWNER
126
 
%token TOK_CAP_SYS_MODULE
127
 
%token TOK_CAP_SYS_RAWIO
128
 
%token TOK_CAP_SYS_CHROOT
129
 
%token TOK_CAP_SYS_PTRACE
130
 
%token TOK_CAP_SYS_PACCT
131
 
%token TOK_CAP_SYS_ADMIN
132
 
%token TOK_CAP_SYS_BOOT
133
 
%token TOK_CAP_SYS_NICE
134
 
%token TOK_CAP_SYS_RESOURCE
135
 
%token TOK_CAP_SYS_TIME
136
 
%token TOK_CAP_SYS_TTY_CONFIG
137
 
%token TOK_CAP_MKNOD
138
 
%token TOK_CAP_LEASE
139
 
%token TOK_CAP_AUDIT_WRITE
140
 
%token TOK_CAP_AUDIT_CONTROL
141
136
 
142
137
/* debug flag values */
143
138
%token TOK_FLAGS
144
139
%token TOK_FLAG_OPENPAREN
145
140
%token TOK_FLAG_CLOSEPAREN
146
141
%token TOK_FLAG_SEP
147
 
%token TOK_FLAG_DEBUG
148
 
%token TOK_FLAG_COMPLAIN
149
 
%token TOK_FLAG_AUDIT
 
142
%token TOK_FLAG_ID
150
143
 
151
144
%union {
152
145
        char *id;
153
 
        char *ip;
154
 
        char *iface;
 
146
        char *flag_id;
155
147
        char *mode;
156
 
        char *eth;
157
 
        /* char * action; */
158
 
        char *via;
159
 
        /* char * port; */
160
 
        unsigned long int num;
 
148
        struct aa_network_entry *network_entry;
161
149
        struct codomain *cod;
162
 
        struct cod_global_entry *entry;
163
150
        struct cod_net_entry *net_entry;
164
151
        struct cod_entry *user_entry;
165
 
        struct ipv4_desc *ipv4;
166
 
        struct ipv4_endpoints *endpoints;
167
 
        unsigned short (*port)[2];
168
 
        int action;
169
152
        struct flagval flags;
170
 
        unsigned int cap;
 
153
        int fmode;
 
154
        uint64_t cap;
 
155
        unsigned int allowed_protocol;
171
156
        char *set_var;
172
157
        char *bool_var;
173
158
        char *var_val;
174
159
        struct value_list *val_list;
175
160
        int boolean;
 
161
        struct named_transition transition;
176
162
}
177
163
 
178
164
%type <id>      TOK_ID
179
165
%type <mode>    TOK_MODE
 
166
%type <fmode>   file_mode
 
167
%type <cod>     profile_base
180
168
%type <cod>     profile
181
169
%type <cod>     rules
182
170
%type <cod>     hat
 
171
%type <cod>     local_profile
183
172
%type <cod>     cond_rule
184
 
%type <net_entry> netrule
 
173
%type <network_entry> network_rule
185
174
%type <user_entry> rule
186
 
%type <ipv4>    address
187
 
%type <endpoints> addresses
188
 
%type <num>     mask
189
 
%type <port>    ports
190
 
%type <ip>      TOK_IP
191
 
%type <iface>   TOK_IFACE interface
192
 
%type <action>  TOK_ACTION
193
 
%type <via>     TOK_VIA
194
 
%type <port>    TOK_PORT_IDENT
195
 
%type <num>     TOK_NUM
196
 
%type <action>  action
 
175
%type <user_entry> frule
197
176
%type <flags>   flags
198
177
%type <flags>   flagvals
199
178
%type <flags>   flagval
200
 
%type <cap>     cap
 
179
%type <flag_id> TOK_FLAG_ID
 
180
%type <cap>     caps
201
181
%type <cap>     capability
 
182
%type <cap>     set_caps
 
183
%type <user_entry> change_profile
202
184
%type <set_var> TOK_SET_VAR
203
185
%type <bool_var> TOK_BOOL_VAR
204
186
%type <var_val> TOK_VALUE
205
187
%type <val_list> valuelist
206
188
%type <boolean> expr
207
 
 
 
189
%type <id>      id_or_var
 
190
%type <boolean> opt_subset_flag
 
191
%type <boolean> opt_audit_flag
 
192
%type <boolean> opt_owner_flag
 
193
%type <boolean> opt_profile_flag
 
194
%type <id>      opt_namespace
 
195
%type <id>      opt_id
 
196
%type <transition> opt_named_transition
 
197
%type <boolean> opt_unsafe
208
198
%%
209
199
 
210
200
 
211
 
list:    varlist profilelist
 
201
list:    preamble profilelist
212
202
        { /* nothing */ };
213
203
 
214
204
profilelist:    { /* nothing */ };
219
209
                add_to_list($2);
220
210
        };
221
211
 
222
 
profile:        TOK_ID flags TOK_OPEN rules TOK_CLOSE
 
212
opt_profile_flag: { /* nothing */ $$ = 0; }
 
213
        | TOK_PROFILE { $$ = 1; }
 
214
        | hat_start { $$ = 2; }
 
215
 
 
216
opt_namespace: { /* nothing */ $$ = NULL; }
 
217
        | TOK_COLON TOK_ID TOK_COLON { $$ = $2; }
 
218
 
 
219
opt_id: { /* nothing */ $$ = NULL; }
 
220
        | TOK_ID { $$ = $1; }
 
221
 
 
222
profile_base: TOK_ID opt_id flags TOK_OPEN rules TOK_CLOSE
223
223
        {
224
 
                struct codomain *cod = $4;
225
 
                PDEBUG("Matched: id (%s) open rules close\n", $1);
 
224
                struct codomain *cod = $5;
 
225
 
226
226
                if (!cod) {
227
227
                        yyerror(_("Memory allocation error."));
228
228
                }
 
229
 
229
230
                cod->name = $1;
230
 
                cod->flags = $2;
 
231
                cod->attachment = $2;
 
232
                if ($2 && $2[0] != '/')
 
233
                        /* we don't support variables as part of the profile
 
234
                         * name or attachment atm
 
235
                         */
 
236
                        yyerror(_("Profile attachment must begin with a '/'."));
 
237
                cod->flags = $3;
231
238
                if (force_complain)
232
 
                        cod->flags = force_complain_flags;
 
239
                        cod->flags.complain = 1;
233
240
 
 
241
                post_process_nt_entries(cod);
234
242
                PDEBUG("%s: flags='%s%s'\n",
235
 
                       $1,
 
243
                       $3,
236
244
                       cod->flags.complain ? "complain, " : "",
237
245
                       cod->flags.audit ? "audit" : "");
238
246
 
239
247
                $$ = cod;
240
 
        };
241
 
 
242
 
varlist:        { /* nothing */ }
243
 
 
244
 
varlist:        varlist varassign
245
 
                { /* nothing */ }
 
248
 
 
249
        };
 
250
 
 
251
profile:  opt_profile_flag opt_namespace profile_base
 
252
        {
 
253
                struct codomain *cod = $3;
 
254
                if ($2)
 
255
                        PDEBUG("Matched: %s://%s { ... }\n", $2, $3->name);
 
256
                else
 
257
                        PDEBUG("Matched: %s { ... }\n", $3->name);
 
258
 
 
259
                if ($3->name[0] != '/' && !($1 || $2))
 
260
                        yyerror(_("Profile names must begin with a '/', namespace or keyword 'profile' or 'hat'."));
 
261
 
 
262
                cod->namespace = $2;
 
263
                if ($1 == 2)
 
264
                        cod->flags.hat = 1;
 
265
                $$ = cod;
 
266
        };
 
267
 
 
268
local_profile:   TOK_PROFILE profile_base
 
269
        {
 
270
 
 
271
                struct codomain *cod = $2;
 
272
 
 
273
                if ($2)
 
274
                        PDEBUG("Matched: local profile %s { ... }\n", cod->name);
 
275
                cod->local = 1;
 
276
                $$ = cod;
 
277
        };
 
278
 
 
279
hat: hat_start profile_base
 
280
        {
 
281
                struct codomain *cod = $2;
 
282
                if ($2)
 
283
                        PDEBUG("Matched: hat %s { ... }\n", code->name);
 
284
 
 
285
                cod->flags.hat = 1;
 
286
                $$ = cod;
 
287
        };
 
288
 
 
289
preamble: { /* nothing */ }
 
290
        | preamble alias { /* nothing */ };
 
291
        | preamble varassign { /* nothing */ };
 
292
 
 
293
alias: TOK_ALIAS TOK_ID TOK_ARROW TOK_ID TOK_END_OF_RULE
 
294
        {
 
295
                if (!new_alias($2, $4))
 
296
                        yyerror(_("Failed to create alias %s -> %s\n"), $2, $4);
 
297
                free($2);
 
298
                free($4);
 
299
        };
246
300
 
247
301
varassign:      TOK_SET_VAR TOK_EQUALS valuelist
248
302
        {
315
369
 
316
370
valuelist:      TOK_VALUE
317
371
        {
318
 
                struct value_list *new = malloc(sizeof(struct value_list));
 
372
                struct value_list *new = calloc(1, sizeof(struct value_list));
319
373
                if (!new)
320
374
                        yyerror(_("Memory allocation error."));
321
375
                PDEBUG("Matched: value (%s)\n", $1);
327
381
 
328
382
valuelist:      valuelist TOK_VALUE
329
383
        {
330
 
                struct value_list *new = malloc(sizeof(struct value_list));
 
384
                struct value_list *new = calloc(1, sizeof(struct value_list));
331
385
                if (!new)
332
386
                        yyerror(_("Memory allocation error."));
333
387
                PDEBUG("Matched: value (%s)\n", $1);
338
392
        }
339
393
 
340
394
flags:  { /* nothing */
341
 
                struct flagval fv = { 0, 0, 0 };
 
395
        struct flagval fv = { 0, 0, 0, 0 };
342
396
 
343
397
                $$ = fv;
344
398
        };
348
402
                $$ = $4;
349
403
        };
350
404
 
 
405
flags: TOK_FLAG_OPENPAREN flagvals TOK_FLAG_CLOSEPAREN
 
406
        {
 
407
                $$ = $2;
 
408
        }
 
409
 
351
410
flagvals:       flagvals TOK_FLAG_SEP flagval
352
411
        {
353
412
                $1.complain = $1.complain || $3.complain;
354
413
                $1.audit = $1.audit || $3.audit;
 
414
                $1.path = $1.path | $3.path;
 
415
                if (($1.path & (PATH_CHROOT_REL | PATH_NS_REL)) ==
 
416
                    (PATH_CHROOT_REL | PATH_NS_REL))
 
417
                        yyerror(_("Profile flag chroot_relative conflicts with namespace_relative"));
 
418
 
 
419
                if (($1.path & (PATH_MEDIATE_DELETED | PATH_DELEGATE_DELETED)) ==
 
420
                    (PATH_MEDIATE_DELETED | PATH_DELEGATE_DELETED))
 
421
                        yyerror(_("Profile flag mediate_deleted conflicts with delegate_deleted"));
 
422
                if (($1.path & (PATH_ATTACH | PATH_NO_ATTACH)) ==
 
423
                    (PATH_ATTACH | PATH_NO_ATTACH))
 
424
                        yyerror(_("Profile flag attach_disconnected conflicts with no_attach_disconnected"));
 
425
                if (($1.path & (PATH_CHROOT_NSATTACH | PATH_CHROOT_NO_ATTACH)) ==
 
426
                    (PATH_CHROOT_NSATTACH | PATH_CHROOT_NO_ATTACH))
 
427
                        yyerror(_("Profile flag chroot_attach conflicts with chroot_no_attach"));
355
428
 
356
429
                $$ = $1;
357
430
        };
361
434
                $$ = $1;
362
435
        };
363
436
 
364
 
flagval:        TOK_FLAG_DEBUG 
365
 
        {
366
 
                PDEBUG("Matched: flag debug\n");
367
 
                yyerror(_("flags=(debug) is no longer supported, sorry."));
368
 
        };
369
 
 
370
 
flagval:        TOK_FLAG_COMPLAIN
371
 
        {
372
 
                struct flagval fv = { 0, 1, 0 };
373
 
 
374
 
                PDEBUG("Matched: flag complain\n");
375
 
 
376
 
                $$ = fv;
377
 
        };
378
 
 
379
 
flagval:        TOK_FLAG_AUDIT
380
 
        {
381
 
                struct flagval fv = { 0, 0, 1 };
382
 
 
383
 
                PDEBUG("Matched: flag audit\n");
384
 
 
385
 
                $$ = fv;
386
 
        };
 
437
flagval:        TOK_FLAG_ID
 
438
        {
 
439
                struct flagval fv = { 0, 0, 0, 0 };
 
440
                if (strcmp($1, "debug") == 0) {
 
441
                        yyerror(_("Profile flag 'debug' is no longer valid."));
 
442
                } else if (strcmp($1, "complain") == 0) {
 
443
                        fv.complain = 1;
 
444
                } else if (strcmp($1, "audit") == 0) {
 
445
                        fv.audit = 1;
 
446
                } else if (strcmp($1, "chroot_relative") == 0) {
 
447
                        fv.path |= PATH_CHROOT_REL;
 
448
                } else if (strcmp($1, "namespace_relative") == 0) {
 
449
                        fv.path |= PATH_NS_REL;
 
450
                } else if (strcmp($1, "mediate_deleted") == 0) {
 
451
                        fv.path |= PATH_MEDIATE_DELETED;
 
452
                } else if (strcmp($1, "delegate_deleted") == 0) {
 
453
                        fv.path |= PATH_DELEGATE_DELETED;
 
454
                } else if (strcmp($1, "attach_disconnected") == 0) {
 
455
                        fv.path |= PATH_ATTACH;
 
456
                } else if (strcmp($1, "no_attach_disconnected") == 0) {
 
457
                        fv.path |= PATH_NO_ATTACH;
 
458
                } else if (strcmp($1, "chroot_attach") == 0) {
 
459
                        fv.path |= PATH_CHROOT_NSATTACH;
 
460
                } else if (strcmp($1, "chroot_no_attach") == 0) {
 
461
                        fv.path |= PATH_CHROOT_NO_ATTACH;
 
462
                } else {
 
463
                        yyerror(_("Invalid profile flag: %s."), $1);
 
464
                }
 
465
                free($1);
 
466
                $$ = fv;
 
467
        };
 
468
 
 
469
opt_subset_flag: { /* nothing */ $$ = 0; }
 
470
        | TOK_SUBSET { $$ = 1; }
 
471
        | TOK_LE { $$ = 1; }
 
472
 
 
473
opt_audit_flag: { /* nothing */ $$ = 0; }
 
474
        | TOK_AUDIT { $$ = 1; };
 
475
 
 
476
opt_owner_flag: { /* nothing */ $$ = 0; }
 
477
        | TOK_OWNER { $$ = 1; };
 
478
        | TOK_OTHER { $$ = 2; };
387
479
 
388
480
rules:  { /* nothing */ 
389
481
                struct codomain *cod = NULL;
395
487
                $$ = cod;
396
488
        };
397
489
 
398
 
rules:  rules rule
399
 
        {
400
 
                PDEBUG("matched: rules rule\n");
401
 
                PDEBUG("rules rule: (%s)\n", $2->name);
402
 
                if (!$2)
403
 
                        yyerror(_("Assert: `rule' returned NULL."));
 
490
/*  can't fold TOK_DENY in as opt_deny_flag as it messes up the generated
 
491
 * parser, even though it shouldn't
 
492
 */
 
493
rules:  rules opt_audit_flag TOK_DENY opt_owner_flag rule
 
494
        {
 
495
                PDEBUG("matched: rules rule\n");
 
496
                PDEBUG("rules rule: (%s)\n", $5->name);
 
497
                if (!$5)
 
498
                        yyerror(_("Assert: `rule' returned NULL."));
 
499
                $5->deny = 1;
 
500
                if (($5->mode & AA_EXEC_BITS) && ($5->mode & ALL_AA_EXEC_TYPE))
 
501
                        yyerror(_("Invalid mode, in deny rules 'x' must not be preceded by exec qualifier 'i', 'p', or 'u'"));
 
502
 
 
503
                if ($4 == 1)
 
504
                        $5->mode &= (AA_USER_PERMS | AA_SHARED_PERMS | AA_USER_PTRACE);
 
505
                else if ($4 == 2)
 
506
                        $5->mode &= (AA_OTHER_PERMS | AA_SHARED_PERMS | AA_OTHER_PTRACE);
 
507
                /* only set audit ctl quieting if the rule is not audited */
 
508
                if (!$2)
 
509
                        $5->audit = $5->mode & ~ALL_AA_EXEC_TYPE;
 
510
 
 
511
                add_entry_to_policy($1, $5);
 
512
                $$ = $1;
 
513
        };
 
514
 
 
515
rules:  rules opt_audit_flag opt_owner_flag rule
 
516
        {
 
517
                PDEBUG("matched: rules rule\n");
 
518
                PDEBUG("rules rule: (%s)\n", $4->name);
 
519
                if (!$4)
 
520
                        yyerror(_("Assert: `rule' returned NULL."));
 
521
                if (($4->mode & AA_EXEC_BITS) &&
 
522
                    !($4->mode & ALL_AA_EXEC_TYPE) &&
 
523
                    !($4->nt_name))
 
524
                        yyerror(_("Invalid mode, 'x' must be preceded by exec qualifier 'i', 'p', 'c', or 'u'"));
 
525
 
 
526
                if ($3 == 1)
 
527
                        $4->mode &= (AA_USER_PERMS | AA_SHARED_PERMS | AA_USER_PTRACE);
 
528
                else if ($3 == 2)
 
529
                        $4->mode &= (AA_OTHER_PERMS | AA_SHARED_PERMS | AA_OTHER_PTRACE);
 
530
                if ($2)
 
531
                        $4->audit = $4->mode & ~ALL_AA_EXEC_TYPE;
 
532
 
 
533
                add_entry_to_policy($1, $4);
 
534
                $$ = $1;
 
535
        };
 
536
 
 
537
rules: rules opt_audit_flag opt_owner_flag TOK_OPEN rules TOK_CLOSE
 
538
        {
 
539
                struct cod_entry *entry, *tmp;
 
540
                PDEBUG("matched: audit block\n");
 
541
                list_for_each_safe($5->entries, entry, tmp) {
 
542
                        entry->next = NULL;
 
543
                        if (entry->mode & AA_EXEC_BITS) {
 
544
                                if (entry->deny &&
 
545
                                    (entry->mode & ALL_AA_EXEC_TYPE))
 
546
                                        yyerror(_("Invalid mode, in deny rules 'x' must not be preceded by exec qualifier 'i', 'p', or 'u'"));
 
547
                                else if (!entry->deny &&
 
548
                                         !(entry->mode & ALL_AA_EXEC_TYPE))
 
549
                                        yyerror(_("Invalid mode, 'x' must be preceded by exec qualifier 'i', 'p', or 'u'"));
 
550
                        }
 
551
                        if ($3 == 1)
 
552
                                entry->mode &= (AA_USER_PERMS | AA_SHARED_PERMS | AA_USER_PTRACE);
 
553
                        else if ($3 == 2)
 
554
                                entry->mode &= (AA_OTHER_PERMS | AA_SHARED_PERMS | AA_OTHER_PTRACE);
 
555
 
 
556
                        if ($2 && !entry->deny)
 
557
                                entry->audit = entry->mode & ~ALL_AA_EXEC_TYPE;
 
558
                        else if (!$2 && entry->deny)
 
559
                                 entry->audit = entry->mode & ~ALL_AA_EXEC_TYPE;
 
560
                        add_entry_to_policy($1, entry);
 
561
                }
 
562
                $5->entries = NULL;
 
563
                // fix me transfer rules and free sub codomain
 
564
                free_policy($5);
 
565
                $$ = $1;
 
566
        };
 
567
 
 
568
rules: rules opt_audit_flag TOK_DENY network_rule
 
569
        {
 
570
                struct aa_network_entry *entry, *tmp;
 
571
 
 
572
                PDEBUG("Matched: network rule\n");
 
573
                if (!$4)
 
574
                        yyerror(_("Assert: `network_rule' return invalid protocol."));
 
575
                if (!$1->network_allowed) {
 
576
                        $1->network_allowed = calloc(get_af_max(),
 
577
                                                     sizeof(unsigned int));
 
578
                        $1->audit_network = calloc(get_af_max(),
 
579
                                                   sizeof(unsigned int));
 
580
                        $1->deny_network = calloc(get_af_max(),
 
581
                                                     sizeof(unsigned int));
 
582
                        $1->quiet_network = calloc(get_af_max(),
 
583
                                                     sizeof(unsigned int));
 
584
                        if (!$1->network_allowed || !$1->audit_network ||
 
585
                            !$1->deny_network || !$1->quiet_network)
 
586
                                yyerror(_("Memory allocation error."));
 
587
                }
 
588
                list_for_each_safe($4, entry, tmp) {
 
589
                        if (entry->type > SOCK_PACKET) {
 
590
                                /* setting mask instead of a bit */
 
591
                                $1->deny_network[entry->family] |= entry->type;
 
592
                                if (!$2)
 
593
                                        $1->quiet_network[entry->family] |= entry->type;
 
594
 
 
595
                        } else {
 
596
                                $1->deny_network[entry->family] |= 1 << entry->type;
 
597
                                if (!$2)
 
598
                                        $1->quiet_network[entry->family] |= 1 << entry->type;
 
599
                        }
 
600
                        free(entry);
 
601
                }
 
602
 
 
603
                $$ = $1;
 
604
        }
 
605
 
 
606
rules: rules opt_audit_flag network_rule
 
607
        {
 
608
                struct aa_network_entry *entry, *tmp;
 
609
 
 
610
                PDEBUG("Matched: network rule\n");
 
611
                if (!$3)
 
612
                        yyerror(_("Assert: `network_rule' return invalid protocol."));
 
613
                if (!$1->network_allowed) {
 
614
                        $1->network_allowed = calloc(get_af_max(),
 
615
                                                     sizeof(unsigned int));
 
616
                        $1->audit_network = calloc(get_af_max(),
 
617
                                                   sizeof(unsigned int));
 
618
                        $1->deny_network = calloc(get_af_max(),
 
619
                                                     sizeof(unsigned int));
 
620
                        $1->quiet_network = calloc(get_af_max(),
 
621
                                                     sizeof(unsigned int));
 
622
                        if (!$1->network_allowed || !$1->audit_network ||
 
623
                            !$1->deny_network || !$1->quiet_network)
 
624
                                yyerror(_("Memory allocation error."));
 
625
                }
 
626
                list_for_each_safe($3, entry, tmp) {
 
627
                        if (entry->type > SOCK_PACKET) {
 
628
                                /* setting mask instead of a bit */
 
629
                                $1->network_allowed[entry->family] |= entry->type;
 
630
                                if ($2)
 
631
                                        $1->audit_network[entry->family] |= entry->type;
 
632
 
 
633
                        } else {
 
634
                                $1->network_allowed[entry->family] |= 1 << entry->type;
 
635
                                if ($2)
 
636
                                        $1->audit_network[entry->family] |= 1 << entry->type;
 
637
                        }
 
638
                        free(entry);
 
639
                }
 
640
 
 
641
                $$ = $1;
 
642
        }
 
643
 
 
644
rules:  rules change_profile
 
645
        {
 
646
                PDEBUG("matched: rules change_profile\n");
 
647
                PDEBUG("rules change_profile: (%s)\n", $2->name);
 
648
                if (!$2)
 
649
                        yyerror(_("Assert: `change_profile' returned NULL."));
404
650
                add_entry_to_policy($1, $2);
405
651
                $$ = $1;
406
652
        };
407
653
 
408
 
rules: rules netrule 
 
654
rules:  rules opt_audit_flag TOK_DENY capability
409
655
        {
410
 
                PDEBUG("Matched: netrules rule\n");
 
656
                $1->deny_caps |= $4;
411
657
                if (!$2)
412
 
                        yyerror(_("Assert: `netrule' returned NULL."));
413
 
                PDEBUG("Assigning %s\n", inet_ntoa(*$2->saddr));
414
 
                PDEBUG("Assigning %s\n", inet_ntoa(*$2->daddr));
415
 
                add_netrule_to_policy($1, $2);
416
 
                $$ = $1;
417
 
        };
418
 
 
419
 
rules:  rules capability
420
 
        {
421
 
                $1->capabilities = $1->capabilities | CAP_TO_MASK($2);
 
658
                        $1->quiet_caps |= $4;
 
659
                $$ = $1;
 
660
        };
 
661
 
 
662
rules:  rules opt_audit_flag capability
 
663
        {
 
664
                $1->capabilities |= $3;
 
665
                if ($2)
 
666
                        $1->audit_caps |= $3;
 
667
                $$ = $1;
 
668
        };
 
669
 
 
670
rules: rules set_caps
 
671
        {
 
672
                $1->set_caps |= $2;
422
673
                $$ = $1;
423
674
        };
424
675
 
431
682
                $$ = $1;
432
683
        };
433
684
 
 
685
rules:  rules local_profile
 
686
        {
 
687
                PDEBUG("Matched: hat rule\n");
 
688
                if (!$2)
 
689
                        yyerror(_("Assert: 'local_profile rule' returned NULL."));
 
690
                add_hat_to_policy($1, $2);
 
691
                add_local_entry($2);
 
692
                $$ = $1;
 
693
        };
 
694
 
434
695
rules:  rules cond_rule
435
696
        {
436
697
                PDEBUG("Matched: conditional rules\n");
437
698
                $$ = merge_policy($1, $2);
438
699
        }
439
700
 
 
701
rules: rules TOK_SET TOK_RLIMIT TOK_ID TOK_LE TOK_VALUE TOK_END_OF_RULE
 
702
        {
 
703
                rlim_t value = RLIM_INFINITY;
 
704
                long long tmp;
 
705
                char *end;
 
706
 
 
707
                int limit = get_rlimit($4);
 
708
                if (limit == -1)
 
709
                        yyerror("INVALID RLIMIT '%s'\n", $4);
 
710
 
 
711
                if (strcmp($6, "infinity") == 0) {
 
712
                        value = RLIM_INFINITY;
 
713
                } else {
 
714
                        tmp = strtoll($6, &end, 0);
 
715
                        switch (limit) {
 
716
                        case RLIMIT_CPU:
 
717
                                yyerror("RLIMIT '%s' is currently unsupported\n", $4);
 
718
                                break;
 
719
                        case RLIMIT_NOFILE:
 
720
                        case RLIMIT_NPROC:
 
721
                        case RLIMIT_LOCKS:
 
722
                        case RLIMIT_SIGPENDING:
 
723
#ifdef RLIMIT_RTPRIO
 
724
                        case RLIMIT_RTPRIO:
 
725
                                if ($6 == end || *end != '\0' || tmp < 0)
 
726
                                        yyerror("RLIMIT '%s' invalid value %s\n", $4, $6);
 
727
                                value = tmp;
 
728
                                break;
 
729
#endif
 
730
#ifdef RLIMIT_NICE
 
731
                        case RLIMIT_NICE:
 
732
                                if ($6 == end || *end != '\0')
 
733
                                        yyerror("RLIMIT '%s' invalid value %s\n", $4, $6);
 
734
                                if (tmp < -20 || tmp > 19)
 
735
                                        yyerror("RLIMIT '%s' out of range (-20 .. 19) %d\n", $4, tmp);
 
736
                                value = tmp + 20;
 
737
                                break;
 
738
#endif
 
739
                        case RLIMIT_FSIZE:
 
740
                        case RLIMIT_DATA:
 
741
                        case RLIMIT_STACK:
 
742
                        case RLIMIT_CORE:
 
743
                        case RLIMIT_RSS:
 
744
                        case RLIMIT_AS:
 
745
                        case RLIMIT_MEMLOCK:
 
746
                        case RLIMIT_MSGQUEUE:
 
747
                                if ($6 == end || tmp < 0)
 
748
                                        yyerror("RLIMIT '%s' invalid value %s\n", $4, $6);
 
749
                                if (strcmp(end, "K") == 0) {
 
750
                                        tmp *= 1024;
 
751
                                } else if (strcmp(end, "M") == 0) {
 
752
                                        tmp *= 1024*1024;
 
753
                                } else if (strcmp(end, "G") == 0) {
 
754
                                        tmp *= 1024*1024*1024;
 
755
                                } else if (*end != '\0') {
 
756
                                        yyerror("RLIMIT '%s' invalid value %s\n", $4, $6);
 
757
                                }
 
758
                                value = tmp;
 
759
                                break;
 
760
                        default:
 
761
                                yyerror("Unknown RLIMIT %d\n", $4);
 
762
                        }
 
763
                }
 
764
                $1->rlimits.specified |= 1 << limit;
 
765
                $1->rlimits.limits[limit] = value;
 
766
                free($4);
 
767
                free($6);
 
768
                $$ = $1;
 
769
        };
 
770
 
 
771
 
440
772
cond_rule: TOK_IF expr TOK_OPEN rules TOK_CLOSE
441
773
        {
442
774
                struct codomain *ret = NULL;
517
849
                free($2);
518
850
        }
519
851
 
520
 
rule:   TOK_ID TOK_MODE TOK_END_OF_RULE
521
 
        {
522
 
                struct cod_entry *entry;
523
 
                PDEBUG("Matched: tok_id (%s) tok_mode (%s)\n", $1, $2);
524
 
                entry = new_entry($1, $2);
525
 
                if (!entry)
526
 
                        yyerror(_("Memory allocation error."));
527
 
                PDEBUG("rule.entry: (%s)\n", entry->name);
528
 
                free($2);
529
 
                $$ = entry;
530
 
        };
531
 
 
532
 
rule:   TOK_SET_VAR TOK_MODE TOK_END_OF_RULE
533
 
        {
534
 
                struct cod_entry *entry;
535
 
                PDEBUG("Matched: tok_id (%s) tok_mode (%s)\n", $1, $2);
536
 
                entry = new_entry($1, $2);
537
 
                if (!entry)
538
 
                        yyerror(_("Memory allocation error."));
539
 
                PDEBUG("rule.entry: (%s)\n", entry->name);
540
 
                free($2);
541
 
                $$ = entry;
542
 
        };
543
 
 
544
 
rule:  TOK_ID TOK_MODE TOK_ID
 
852
id_or_var: TOK_ID { $$ = $1; }
 
853
id_or_var: TOK_SET_VAR { $$ = $1; };
 
854
 
 
855
opt_named_transition:
 
856
        { /* nothing */
 
857
                $$.present = 0;
 
858
                $$.namespace = NULL;
 
859
                $$.name = NULL;
 
860
        }
 
861
        | TOK_ARROW id_or_var
 
862
        {
 
863
                $$.present = 1;
 
864
                $$.namespace = NULL;
 
865
                $$.name = $2;
 
866
        }
 
867
        | TOK_ARROW TOK_COLON id_or_var TOK_COLON id_or_var
 
868
        {
 
869
                $$.present = 1;
 
870
                $$.namespace = $3;
 
871
                $$.name = $5;
 
872
        };
 
873
 
 
874
opt_unsafe: { /* nothing */ $$ = 0; }
 
875
        | TOK_UNSAFE { $$ = 1; };
 
876
        | TOK_SAFE { $$ = 2; };
 
877
 
 
878
rule:   opt_unsafe frule
 
879
        {
 
880
                if ($1) {
 
881
                        if (!($2->mode & AA_EXEC_BITS))
 
882
                                yyerror(_("unsafe rule missing exec permissions"));
 
883
                        if ($1 == 1) {
 
884
                                $2->mode |= (($2->mode & AA_EXEC_BITS) << 8) &
 
885
                                         ALL_AA_EXEC_UNSAFE;
 
886
                        }
 
887
                        else if ($1 == 2)
 
888
                                $2->mode &= ~ALL_AA_EXEC_UNSAFE;
 
889
                }
 
890
                $$ = $2;
 
891
        };
 
892
 
 
893
frule:  id_or_var file_mode opt_named_transition TOK_END_OF_RULE
 
894
        {
 
895
                $$ = do_file_rule($3.namespace, $1, $2, NULL, $3.name);
 
896
        };
 
897
 
 
898
frule:  file_mode opt_subset_flag id_or_var opt_named_transition TOK_END_OF_RULE
 
899
        {
 
900
                if ($2 && ($1 & ~AA_LINK_BITS))
 
901
                        yyerror(_("subset can only be used with link rules."));
 
902
                if ($4.present && ($1 & AA_LINK_BITS) && ($1 & AA_EXEC_BITS))
 
903
                        yyerror(_("link and exec perms conflict on a file rule using ->"));
 
904
                if ($4.present && $4.namespace && ($1 & AA_LINK_BITS))
 
905
                        yyerror(_("link perms are not allowed on a named profile transition.\n"));
 
906
                if (($1 & AA_LINK_BITS)) {
 
907
                        $$ = do_file_rule(NULL, $3, $1, $4.name, NULL);
 
908
                        $$->subset = $2;
 
909
 
 
910
                } else {
 
911
                        $$ = do_file_rule($4.namespace, $3, $1, NULL, $4.name);
 
912
                }
 
913
        };
 
914
 
 
915
rule:  opt_unsafe id_or_var file_mode id_or_var
545
916
        {
546
917
                /* Oopsie, we appear to be missing an EOL marker. If we
547
918
                 * were *smart*, we could work around it. Since we're
550
921
                yyerror(_("missing an end of line character? (entry: %s)"), $1);
551
922
        };
552
923
 
553
 
hat: TOK_SEP TOK_ID flags TOK_OPEN rules TOK_CLOSE 
554
 
        {
555
 
                struct codomain *cod = $5;
556
 
                PDEBUG("Matched: sep id (%s) open rules close\n", $2);
557
 
                if (!cod) {
558
 
                        yyerror(_("Memory allocation error."));
 
924
rule: TOK_LINK opt_subset_flag TOK_ID TOK_ARROW TOK_ID TOK_END_OF_RULE
 
925
        {
 
926
                struct cod_entry *entry;
 
927
                PDEBUG("Matched: link tok_id (%s) -> (%s)\n", $3, $5);
 
928
                entry = new_entry(NULL, $3, AA_LINK_BITS, $5);
 
929
                entry->subset = $2;
 
930
                PDEBUG("rule.entry: link (%s)\n", entry->name);
 
931
                $$ = entry;
 
932
        };
 
933
 
 
934
rule: TOK_PTRACE TOK_ID TOK_END_OF_RULE
 
935
        {
 
936
                struct cod_entry *entry;
 
937
                entry = new_entry(NULL, $2, AA_USER_PTRACE | AA_OTHER_PTRACE, NULL);
 
938
                if (!entry)
 
939
                        yyerror(_("Memory allocation error."));
 
940
                $$ = entry;
 
941
        };
 
942
 
 
943
rule: TOK_PTRACE TOK_COLON TOK_ID TOK_COLON TOK_ID TOK_END_OF_RULE
 
944
        {
 
945
                struct cod_entry *entry;
 
946
                entry = new_entry($3, $5, AA_USER_PTRACE | AA_OTHER_PTRACE, NULL);
 
947
                if (!entry)
 
948
                        yyerror(_("Memory allocation error."));
 
949
                $$ = entry;
 
950
        };
 
951
 
 
952
network_rule: TOK_NETWORK TOK_END_OF_RULE
 
953
        {
 
954
                size_t family;
 
955
                struct aa_network_entry *new_entry, *entry = NULL;
 
956
                for (family = AF_UNSPEC; family < get_af_max(); family++) {
 
957
                        new_entry = new_network_ent(family, 0xffffffff,
 
958
                                                    0xffffffff);
 
959
                        if (!new_entry)
 
960
                                yyerror(_("Memory allocation error."));
 
961
                        new_entry->next = entry;
 
962
                        entry = new_entry;
559
963
                }
560
 
                cod->name = $2;
561
 
                cod->flags = $3;
562
 
                if (force_complain)
563
 
                        cod->flags = force_complain_flags;
564
 
                PDEBUG("^%s: flags='%s%s'\n",
565
 
                       $2,
566
 
                       cod->flags.complain ? "complain, " : "",
567
 
                       cod->flags.audit ? "audit" : "");
568
 
                $$ = cod;
569
 
        };
570
 
 
571
 
 
572
 
/*
573
 
 * The addition of an entirely new grammer set to our (previously) slim 
574
 
 * profile spec is below.  It's designed to look quite similar to 
575
 
 * (Free|Open)BSD's ipfw rules:
576
 
 * 
577
 
 * 'tcp_connect to 10.0.0.40:80 via eth0' for example.
578
 
 * 
579
 
 * 
580
 
 * mb:
581
 
 * We need to verify the following rules:
582
 
 */
583
 
  
584
 
netrule:   action addresses interface TOK_END_OF_RULE
585
 
        {
586
 
                struct cod_net_entry *entry;
587
 
 
588
 
                entry = NULL;
589
 
                
590
 
                if (!$2)
591
 
                        yyerror(_("Assert: `addresses' returned NULL."));
592
 
 
593
 
                PDEBUG("Matched action (%d) via (%s)\n", $1, $3);
594
 
                entry = new_network_entry($1, $2, $3);
595
 
                if (!entry)
596
 
                        yyerror(_("Memory allocation error."));
597
 
 
598
 
                free_ipv4_endpoints($2);
599
 
                $$ = entry;
600
 
        };
601
 
        
602
 
action:         TOK_TCP_CONN { $$ = AA_TCP_CONNECT; }
603
 
        |       TOK_TCP_ACPT { $$ = AA_TCP_ACCEPT; }
604
 
        |       TOK_TCP_CONN_ESTB { $$ = AA_TCP_CONNECTED; }
605
 
        |       TOK_TCP_ACPT_ESTB { $$ = AA_TCP_ACCEPTED; }
606
 
        |       TOK_UDP_SEND { $$ = AA_UDP_SEND; }
607
 
        |       TOK_UDP_RECV { $$ = AA_UDP_RECEIVE; }
608
 
        ;
609
 
        
610
 
 
611
 
interface:      /* nothing, no interface specified */
612
 
        {
613
 
                $$ = NULL;
614
 
        };
615
 
interface:      TOK_VIA TOK_IFACE
616
 
        {
617
 
                PDEBUG ("Matched an interface (%s)\n", $2);
 
964
                $$ = entry;
 
965
        }
 
966
 
 
967
network_rule: TOK_NETWORK TOK_ID TOK_END_OF_RULE
 
968
        {
 
969
                struct aa_network_entry *entry;
 
970
                entry = network_entry($2, NULL, NULL);
 
971
                if (!entry)
 
972
                        /* test for short circuiting of family */
 
973
                        entry = network_entry(NULL, $2, NULL);
 
974
                if (!entry)
 
975
                        yyerror(_("Invalid network entry."));
 
976
                free($2);
 
977
                $$ = entry;
 
978
        }
 
979
 
 
980
network_rule: TOK_NETWORK TOK_ID TOK_ID TOK_END_OF_RULE
 
981
        {
 
982
                struct aa_network_entry *entry;
 
983
                entry = network_entry($2, $3, NULL);
 
984
                if (!entry)
 
985
                        yyerror(_("Invalid network entry."));
 
986
                free($2);
 
987
                free($3);
 
988
                $$ = entry;
 
989
        }
 
990
 
 
991
hat_start: TOK_SEP {}
 
992
        | TOK_HAT {}
 
993
 
 
994
file_mode: TOK_MODE
 
995
        {
 
996
                /* A single TOK_MODE maps to the same permission in all
 
997
                 * of user::other */
 
998
                $$ = parse_mode($1);
 
999
                free($1);
 
1000
        }
 
1001
 
 
1002
change_profile: TOK_CHANGE_PROFILE TOK_ARROW TOK_ID TOK_END_OF_RULE
 
1003
        {
 
1004
                struct cod_entry *entry;
 
1005
                PDEBUG("Matched change_profile: tok_id (%s)\n", $3);
 
1006
                entry = new_entry(NULL, $3, AA_CHANGE_PROFILE, NULL);
 
1007
                if (!entry)
 
1008
                        yyerror(_("Memory allocation error."));
 
1009
                PDEBUG("change_profile.entry: (%s)\n", entry->name);
 
1010
                $$ = entry;
 
1011
        };
 
1012
 
 
1013
change_profile: TOK_CHANGE_PROFILE TOK_ARROW TOK_COLON TOK_ID TOK_COLON TOK_ID TOK_END_OF_RULE
 
1014
        {
 
1015
                struct cod_entry *entry;
 
1016
                PDEBUG("Matched change_profile: tok_id (%s:%s)\n", $4, $6);
 
1017
                entry = new_entry($4, $6, AA_CHANGE_PROFILE, NULL);
 
1018
                if (!entry)
 
1019
                        yyerror(_("Memory allocation error."));
 
1020
                PDEBUG("change_profile.entry: (%s)\n", entry->name);
 
1021
                $$ = entry;
 
1022
        };
 
1023
 
 
1024
 
 
1025
set_caps:       TOK_SET TOK_CAPABILITY caps TOK_END_OF_RULE
 
1026
        {
 
1027
                $$ = $3;
 
1028
        };
 
1029
 
 
1030
capability:     TOK_CAPABILITY caps TOK_END_OF_RULE
 
1031
        {
618
1032
                $$ = $2;
619
1033
        };
620
1034
 
621
 
addresses:      /* Nothing */
622
 
        {
623
 
                struct ipv4_endpoints *addresses;
624
 
 
625
 
                addresses = (struct ipv4_endpoints *) 
626
 
                                malloc (sizeof (struct ipv4_endpoints));
627
 
                if (!addresses)
628
 
                        yyerror(_("Memory allocation error."));
629
 
                addresses->src = NULL;
630
 
                addresses->dest = NULL;
631
 
 
632
 
                $$ = addresses;
633
 
        };
634
 
 
635
 
addresses:      TOK_TO address
636
 
        {
637
 
                struct ipv4_endpoints *addresses;
638
 
 
639
 
                addresses = (struct ipv4_endpoints *) 
640
 
                                malloc(sizeof (struct ipv4_endpoints));
641
 
                if (!addresses)
642
 
                        yyerror(_("Memory allocation error."));
643
 
                addresses->src = NULL;
644
 
                addresses->dest = $2;
645
 
 
646
 
                $$ = addresses;
647
 
        };
648
 
                
649
 
addresses:      TOK_FROM address
650
 
        {
651
 
                struct ipv4_endpoints *addresses;
652
 
 
653
 
                addresses = (struct ipv4_endpoints *) 
654
 
                                malloc(sizeof (struct ipv4_endpoints));
655
 
                if (!addresses)
656
 
                        yyerror(_("Memory allocation error."));
657
 
                addresses->src = $2;
658
 
                addresses->dest = NULL;
659
 
 
660
 
                $$ = addresses;
661
 
        };
662
 
                
663
 
addresses:      TOK_FROM address TOK_TO address
664
 
        {
665
 
                struct ipv4_endpoints *addresses;
666
 
 
667
 
                addresses = (struct ipv4_endpoints *) 
668
 
                                malloc (sizeof (struct ipv4_endpoints));
669
 
                if (!addresses)
670
 
                        yyerror(_("Memory allocation error."));
671
 
                addresses->src = $2;
672
 
                addresses->dest = $4;
673
 
 
674
 
                $$ = addresses;
675
 
        };
676
 
                
677
 
addresses:      TOK_TO address TOK_FROM address
678
 
        {
679
 
                struct ipv4_endpoints *addresses;
680
 
 
681
 
                addresses = (struct ipv4_endpoints *) 
682
 
                                malloc(sizeof (struct ipv4_endpoints));
683
 
                if (!addresses)
684
 
                        yyerror(_("Memory allocation error."));
685
 
                addresses->src = $4;
686
 
                addresses->dest = $2;
687
 
 
688
 
                $$ = addresses;
689
 
        };
690
 
                
691
 
addresses:      TOK_TO address TOK_TO
692
 
        {
693
 
                /* better error warnings (hopefully) */
694
 
                yyerror(_("Network entries can only have one TO address."));
695
 
        };
696
 
addresses:      TOK_FROM address TOK_FROM
697
 
        {
698
 
                /* better error warnings (hopefully) */
699
 
                yyerror(_("Network entries can only have one FROM address."));
700
 
        };
701
 
address:        TOK_IP ports
702
 
        {
703
 
                /* Bleah, I have to handle address as two rules, because
704
 
                 * if the user provides an ip of 0.0.0.0 and no mask, we
705
 
                 * treat it as 0.0.0.0/0 instead of 0.0.0.0/32. */
706
 
 
707
 
                struct ipv4_desc *address;
708
 
 
709
 
                address = (struct ipv4_desc *) 
710
 
                                malloc (sizeof (struct ipv4_desc));
711
 
                if (!address)
712
 
                        yyerror(_("Memory allocation error."));
713
 
 
714
 
                address->port[0] = (*$2)[0];
715
 
                address->port[1] = (*$2)[1];
716
 
                if (inet_aton($1, &(address->addr)) == 0)
717
 
                        yyerror(_("`%s' is not a valid ip address."), $1);
718
 
                if (address->addr.s_addr == 0) {
719
 
                        /* the user specified 0.0.0.0 without giving an
720
 
                         * explicit mask, so treat it as 0.0.0.0/0 */
721
 
                        address->mask = htonl (0UL);
722
 
                } else {
723
 
                        /* otherwise, treat it as /32 */
724
 
                        address->mask = htonl (0xffffffff);
725
 
                }
726
 
                PDEBUG("Matched an IP (%s/%d:%d-%d)\n",
727
 
                                inet_ntoa(address->addr), address->mask,
728
 
                                address->port[0], address->port[1]);
729
 
 
730
 
                free($1);
731
 
                free(*$2);
732
 
                $$ = address;
733
 
        };
734
 
                
735
 
address:        TOK_IP mask ports
736
 
        {
737
 
                struct ipv4_desc *address;
738
 
 
739
 
                address = (struct ipv4_desc *) 
740
 
                                malloc(sizeof (struct ipv4_desc));
741
 
                if (!address)
742
 
                        yyerror(_("Memory allocation error."));
743
 
 
744
 
                address->mask = $2;
745
 
                address->port[0] = (*$3)[0];
746
 
                address->port[1] = (*$3)[1];
747
 
                if (inet_aton($1, &(address->addr)) == 0)
748
 
                        yyerror(_("`%s' is not a valid ip address."), $1);
749
 
                PDEBUG("Matched an IP (%s/%d:%d-%d)\n",
750
 
                                inet_ntoa(address->addr), address->mask,
751
 
                                address->port[0], address->port[1]);
752
 
                free($1);
753
 
                free(*$3);
754
 
                $$ = address;
755
 
        };
756
 
                
757
 
mask:           TOK_SLASH TOK_NUM
758
 
        {
759
 
                PDEBUG("Matched a netmask (%d)\n", $2);
760
 
                if (($2 < 0) || ($2 > 32))
761
 
                        yyerror(_("`/%d' is not a valid netmask."), $2);
762
 
                $$ = htonl(0xffffffff << (32 - $2));
763
 
        };
764
 
mask:           TOK_SLASH TOK_IP
765
 
        {
766
 
                struct in_addr mask;
767
 
                if (inet_aton($2, &mask) == 0)
768
 
                        yyerror(_("`%s' is not a valid netmask."), $2);
769
 
                PDEBUG("Matched a netmask (%d)\n", mask.s_addr);
770
 
                $$ = mask.s_addr;
771
 
        };
772
 
                
773
 
ports:  {
774
 
                /* nothing, return all ports */
775
 
                unsigned short (*ports)[2];
776
 
 
777
 
                ports = (unsigned short (*)[2]) 
778
 
                                malloc(sizeof (unsigned short [2]));
779
 
                if (!ports)
780
 
                        yyerror(_("Memory allocation error."));
781
 
                (*ports)[0] = MIN_PORT;
782
 
                (*ports)[1] = MAX_PORT;
783
 
                
784
 
                $$ = ports;
785
 
        };
786
 
ports:          TOK_COLON TOK_NUM
787
 
        {
788
 
                unsigned short (*ports)[2];
789
 
                
790
 
                PDEBUG("Matched a single port (%d)\n", $2);
791
 
                ports = (unsigned short (*)[2]) 
792
 
                                malloc(sizeof (unsigned short [2]));
793
 
                if (($2 < MIN_PORT) || ($2 > MAX_PORT))
794
 
                        yyerror(_("ports must be between %d and %d"),
795
 
                                MIN_PORT, MAX_PORT);
796
 
                if (!ports)
797
 
                        yyerror(_("Memory allocation error."));
798
 
                (*ports)[0] = $2;
799
 
                (*ports)[1] = $2;
800
 
                
801
 
                $$ = ports;
802
 
        };
803
 
ports:          TOK_COLON TOK_NUM TOK_RANGE TOK_NUM
804
 
        {
805
 
                unsigned short (*ports)[2];
806
 
 
807
 
                PDEBUG("Matched a port range (%d,%d)\n", $2, $4);
808
 
                ports = (unsigned short (*)[2]) 
809
 
                                malloc(sizeof (unsigned short [2]));
810
 
                if (!ports)
811
 
                        yyerror(_("Memory allocation error."));
812
 
                if (($2 < MIN_PORT) || ($4 > MAX_PORT) 
813
 
                 || ($2 < MIN_PORT) || ($4 > MAX_PORT))
814
 
                        yyerror(_("ports must be between %d and %d"),
815
 
                                 MIN_PORT, MAX_PORT);
816
 
                (*ports)[0] = $2;
817
 
                (*ports)[1] = $4;
818
 
 
819
 
                if ((*ports)[0] > (*ports)[1])
820
 
                {
821
 
                        unsigned short tmp;
822
 
                        pwarn("expected first port number to be less than the second, swapping (%ld,%ld)\n",
823
 
                                $2, $4);
824
 
                        tmp = (*ports)[0];
825
 
                        (*ports)[0] = (*ports)[1];
826
 
                        (*ports)[1] = tmp;
827
 
                }
828
 
                
829
 
                $$ = ports;
830
 
        };
831
 
 
832
 
capability:     TOK_CAPABILITY cap TOK_END_OF_RULE
833
 
        {
834
 
                $$ = $2;                
835
 
        };
836
 
 
837
 
cap:    TOK_CAP_CHOWN                   { $$ = CAP_CHOWN; }
838
 
        | TOK_CAP_DAC_OVERRIDE          { $$ = CAP_DAC_OVERRIDE; }
839
 
        | TOK_CAP_DAC_READ_SEARCH       { $$ = CAP_DAC_READ_SEARCH; }
840
 
        | TOK_CAP_FOWNER                { $$ = CAP_FOWNER; }
841
 
        | TOK_CAP_FSETID                { $$ = CAP_FSETID; }
842
 
        | TOK_CAP_KILL                  { $$ = CAP_KILL; }
843
 
        | TOK_CAP_SETGID                { $$ = CAP_SETGID; }
844
 
        | TOK_CAP_SETUID                { $$ = CAP_SETUID; }
845
 
        | TOK_CAP_SETPCAP               { $$ = CAP_SETPCAP; }
846
 
        | TOK_CAP_LINUX_IMMUTABLE       { $$ = CAP_LINUX_IMMUTABLE; }
847
 
        | TOK_CAP_NET_BIND_SERVICE      { $$ = CAP_NET_BIND_SERVICE; }
848
 
        | TOK_CAP_NET_BROADCAST         { $$ = CAP_NET_BROADCAST; }
849
 
        | TOK_CAP_NET_ADMIN             { $$ = CAP_NET_ADMIN; }
850
 
        | TOK_CAP_NET_RAW               { $$ = CAP_NET_RAW; }
851
 
        | TOK_CAP_IPC_LOCK              { $$ = CAP_IPC_LOCK; }
852
 
        | TOK_CAP_IPC_OWNER             { $$ = CAP_IPC_OWNER; }
853
 
        | TOK_CAP_SYS_MODULE            { $$ = CAP_SYS_MODULE; }
854
 
        | TOK_CAP_SYS_RAWIO             { $$ = CAP_SYS_RAWIO; }
855
 
        | TOK_CAP_SYS_CHROOT            { $$ = CAP_SYS_CHROOT; }
856
 
        | TOK_CAP_SYS_PTRACE            { $$ = CAP_SYS_PTRACE; }
857
 
        | TOK_CAP_SYS_PACCT             { $$ = CAP_SYS_PACCT; }
858
 
        | TOK_CAP_SYS_ADMIN             { $$ = CAP_SYS_ADMIN; }
859
 
        | TOK_CAP_SYS_BOOT              { $$ = CAP_SYS_BOOT; }
860
 
        | TOK_CAP_SYS_NICE              { $$ = CAP_SYS_NICE; }
861
 
        | TOK_CAP_SYS_RESOURCE          { $$ = CAP_SYS_RESOURCE; }
862
 
        | TOK_CAP_SYS_TIME              { $$ = CAP_SYS_TIME; }
863
 
        | TOK_CAP_SYS_TTY_CONFIG        { $$ = CAP_SYS_TTY_CONFIG; }
864
 
        | TOK_CAP_MKNOD                 { $$ = CAP_MKNOD; }
865
 
        | TOK_CAP_LEASE                 { $$ = CAP_LEASE; }
866
 
        | TOK_CAP_AUDIT_WRITE           { $$ = CAP_AUDIT_WRITE; }
867
 
        | TOK_CAP_AUDIT_CONTROL         { $$ = CAP_AUDIT_CONTROL; }
868
 
                
 
1035
caps: caps TOK_ID
 
1036
        {
 
1037
                int cap = name_to_capability($2);
 
1038
                if (cap == -1)
 
1039
                        yyerror(_("Invalid capability %s."), $2);
 
1040
                free($2);
 
1041
                $$ = $1 | CAP_TO_MASK(cap);
 
1042
        }
 
1043
 
 
1044
caps: TOK_ID
 
1045
        {
 
1046
                int cap = name_to_capability($1);
 
1047
                if (cap == -1)
 
1048
                        yyerror(_("Invalid capability %s."), $1);
 
1049
                free($1);
 
1050
                $$ = CAP_TO_MASK(cap);
 
1051
        };
 
1052
 
869
1053
%%
870
1054
#define MAXBUFSIZE 4096
871
1055
 
879
1063
        va_end(arg);
880
1064
 
881
1065
        if (profilename) {
882
 
                PERROR(_("AppArmor parser error in %s at line %d: %s\n"),
883
 
                       profilename, current_lineno, buf);
 
1066
                PERROR(_("AppArmor parser error for %s%s%s at line %d: %s\n"),
 
1067
                       profilename,
 
1068
                       current_filename ? " in " : "",
 
1069
                       current_filename ? current_filename : "",
 
1070
                       current_lineno, buf);
884
1071
        } else {
885
 
                PERROR(_("AppArmor parser error, line %d: %s\n"),
 
1072
                PERROR(_("AppArmor parser error,%s%s line %d: %s\n"),
 
1073
                       current_filename ? " in " : "",
 
1074
                       current_filename ? current_filename : "",
886
1075
                       current_lineno, buf);
887
1076
        }
888
1077
 
902
1091
        }
903
1092
}
904
1093
 
 
1094
struct cod_entry *do_file_rule(char *namespace, char *id, int mode,
 
1095
                               char *link_id, char *nt)
 
1096
{
 
1097
                struct cod_entry *entry;
 
1098
                PDEBUG("Matched: tok_id (%s) tok_mode (0x%x)\n", id, mode);
 
1099
                entry = new_entry(namespace, id, mode, link_id);
 
1100
                if (!entry)
 
1101
                        yyerror(_("Memory allocation error."));
 
1102
                entry->nt_name = nt;
 
1103
                PDEBUG("rule.entry: (%s)\n", entry->name);
 
1104
                return entry;
 
1105
}
 
1106
 
 
1107
/* Note: NOT currently in use, used for 
 
1108
 * /foo x -> { /bah, }   style transitions
 
1109
 */
 
1110
void add_local_entry(struct codomain *cod)
 
1111
{
 
1112
        /* ugh this has to be called after the hat is attached to its parent */
 
1113
        if (cod->local_mode) {
 
1114
                struct cod_entry *entry;
 
1115
                char *trans = malloc(strlen(cod->parent->name) +
 
1116
                                    strlen(cod->name) + 3);
 
1117
                char *name = strdup(cod->name);
 
1118
                if (!trans)
 
1119
                        yyerror(_("Memory allocation error."));
 
1120
                sprintf(name, "%s//%s", cod->parent->name, cod->name);
 
1121
 
 
1122
                entry = new_entry(NULL, name, cod->local_mode, NULL);
 
1123
                entry->audit = cod->local_audit;
 
1124
                entry->nt_name = trans;
 
1125
                if (!entry)
 
1126
                        yyerror(_("Memory allocation error."));
 
1127
 
 
1128
                add_entry_to_policy(cod, entry);
 
1129
        }
 
1130
}