2
* Copyright (C) 1998-2005 Novell/SUSE
4
* This program is free software; you can redistribute it and/or
5
* modify it under the terms of the GNU General Public License as
6
* published by the Free Software Foundation, version 2 of the
9
* AppArmor userspace policy interface
12
#include <asm/unaligned.h>
16
#include "module_interface.h"
17
#include "match/match.h"
19
/* aa_code defined in module_interface.h */
21
const int aacode_datasize[] = { 1, 2, 4, 8, 2, 2, 4, 0, 0, 0, 0, 0, 0 };
23
struct aa_taskreplace_data {
24
struct aaprofile *old_profile;
25
struct aaprofile *new_profile;
28
/* inlines must be forward of there use in newer version of gcc,
29
just forward declaring with a prototype won't work anymore */
31
static inline void free_aa_entry(struct aa_entry *entry)
34
kfree(entry->filename);
35
aamatch_free(entry->extradata);
41
* alloc_aa_entry - create new empty aa_entry
42
* This routine allocates, initializes, and returns a new aa_entry
43
* file entry structure. Structure is zeroed. Returns new structure on
44
* success, %NULL on failure.
46
static inline struct aa_entry *alloc_aa_entry(void)
48
struct aa_entry *entry;
50
AA_DEBUG("%s\n", __FUNCTION__);
51
entry = kzalloc(sizeof(struct aa_entry), GFP_KERNEL);
54
INIT_LIST_HEAD(&entry->list);
55
for (i = 0; i <= POS_AA_FILE_MAX; i++) {
56
INIT_LIST_HEAD(&entry->listp[i]);
63
* free_aaprofile_rcu - rcu callback for free profiles
64
* @head: rcu_head struct of the profile whose reference is being put.
66
* the rcu callback routine, which delays the freeing of a profile when
67
* its last reference is put.
69
static void free_aaprofile_rcu(struct rcu_head *head)
71
struct aaprofile *p = container_of(head, struct aaprofile, rcu);
72
/* check that the reference count is still 0. There is a
73
* race where a reference can be gotten after the profile is
74
* put on the rcu callback
75
* If it is not 0 here who ever has the reference will
76
* put it causing the profile to be freed.
79
p->on_rcu_callback = 0;
80
if (atomic_read(&p->count.refcount) == 0) {
81
spin_unlock(&sd_lock);
84
INIT_RCU_HEAD(&p->rcu);
85
spin_unlock(&sd_lock);
90
* task_remove - remove profile from a task's subdomain
91
* @sd: task's subdomain
93
* remove the active profile from a task's subdomain, switching the task
94
* to an unconfined state.
96
static inline void task_remove(struct subdomain *sd)
98
/* spin_lock(&sd_lock) held here */
99
AA_DEBUG("%s: removing profile from task %s(%d) profile %s active %s\n",
103
BASE_PROFILE(sd->active)->name,
106
aa_switch_unconfined(sd);
109
/** taskremove_iter - Iterator to unconfine subdomains which match cookie
110
* @sd: subdomain to consider for profile removal
111
* @cookie: pointer to the oldprofile which is being removed
113
* If the subdomain's active profile matches old_profile, then call
114
* task_remove() to remove the profile leaving the task (subdomain) unconfined.
116
static int taskremove_iter(struct subdomain *sd, void *cookie)
118
struct aaprofile *old_profile = (struct aaprofile *)cookie;
121
spin_lock_irqsave(&sd_lock, flags);
123
if (__aa_is_confined(sd) && BASE_PROFILE(sd->active) == old_profile) {
127
spin_unlock_irqrestore(&sd_lock, flags);
132
/** task_replace - replace subdomain's current profile with a new profile
133
* @sd: subdomain to replace the profile on
136
* Replace a task's (subdomain's) active profile with a new profile. If
137
* task was in a hat then the new profile will also be in the equivalent
138
* hat in the new profile if it exists. If it doesn't exist the
139
* task will be placed in the special null_profile state.
141
static inline void task_replace(struct subdomain *sd, struct aaprofile *new)
143
AA_DEBUG("%s: replacing profile for task %s(%d) "
144
"profile=%s (%p) active=%s (%p)\n",
146
sd->task->comm, sd->task->pid,
147
BASE_PROFILE(sd->active)->name, BASE_PROFILE(sd->active),
148
sd->active->name, sd->active);
153
if (IN_SUBPROFILE(sd->active)) {
154
struct aaprofile *nactive;
156
/* The old profile was in a hat, check to see if the new
157
* profile has an equivalent hat */
158
nactive = __aa_find_profile(sd->active->name, &new->sub);
161
nactive = get_aaprofile(new->null_profile);
163
aa_switch(sd, nactive);
164
put_aaprofile(nactive);
173
/** taskreplace_iter - Iterator to replace a subdomain's profile
174
* @sd: subdomain to consider for profile replacement
175
* @cookie: pointer to the old profile which is being replaced.
177
* If the subdomain's active profile matches old_profile call
178
* task_replace() to replace with the subdomain's active profile with
181
static int taskreplace_iter(struct subdomain *sd, void *cookie)
183
struct aa_taskreplace_data *data = (struct aa_taskreplace_data *)cookie;
186
spin_lock_irqsave(&sd_lock, flags);
188
if (__aa_is_confined(sd) &&
189
BASE_PROFILE(sd->active) == data->old_profile)
190
task_replace(sd, data->new_profile);
192
spin_unlock_irqrestore(&sd_lock, flags);
197
static inline int aa_inbounds(struct aa_ext *e, size_t size)
199
return (e->pos + size <= e->end);
203
* aaconvert - convert trailing values of serialized type codes
205
* @dest: pointer to object to receive the converted value
206
* @src: pointer to value to convert
208
* for serialized type codes which have a trailing value, convert it
209
* and place it in @dest. If a code does not have a trailing value nop.
211
static void aaconvert(enum aa_code code, void *dest, void *src)
215
*(u8 *)dest = *(u8 *) src;
220
*(u16 *)dest = le16_to_cpu(get_unaligned((u16 *)src));
224
*(u32 *)dest = le32_to_cpu(get_unaligned((u32 *)src));
227
*(u64 *)dest = le64_to_cpu(get_unaligned((u64 *)src));
230
/* nop - all other type codes do not have a trailing value */
236
* aa_is_X - check if the next element is of type X
237
* @e: serialized data extent information
239
* @data: object located at @e->pos (of type @code) is written into @data
240
* if @data is non-null. if data is null it means skip this
242
* check to see if the next element in the serialized data stream is of type
243
* X and check that it is with in bounds, if so put the associated value in
245
* return the size of bytes associated with the returned data
246
* for complex object like blob and string a pointer to the allocated
247
* data is returned in data, but the size of the blob or string is
250
static u32 aa_is_X(struct aa_ext *e, enum aa_code code, void *data)
254
if (!aa_inbounds(e, AA_CODE_BYTE + aacode_datasize[code]))
256
if (code != *(u8 *)e->pos)
258
e->pos += AA_CODE_BYTE;
259
if (code == AA_NAME) {
261
/* name codes are followed by X bytes */
262
size = le16_to_cpu(get_unaligned((u16 *)e->pos));
263
if (!aa_inbounds(e, (size_t) size))
267
e->pos += aacode_datasize[code];
268
ret = 1 + aacode_datasize[code];
269
} else if (code == AA_DYN_STRING) {
272
/* strings codes are followed by X bytes */
273
size = le16_to_cpu(get_unaligned((u16 *)e->pos));
274
e->pos += aacode_datasize[code];
275
if (!aa_inbounds(e, (size_t) size))
278
* (char **)data = NULL;
279
str = kmalloc(size, GFP_KERNEL);
282
memcpy(str, e->pos, (size_t) size);
284
* (char **)data = str;
288
} else if (code == AA_STATIC_BLOB) {
290
/* blobs are followed by X bytes, that can be 2^32 */
291
size = le32_to_cpu(get_unaligned((u32 *)e->pos));
292
e->pos += aacode_datasize[code];
293
if (!aa_inbounds(e, (size_t) size))
296
memcpy(data, e->pos, (size_t) size);
301
aaconvert(code, data, e->pos);
302
e->pos += aacode_datasize[code];
303
ret = 1 + aacode_datasize[code];
313
* aa_is_nameX - check is the next element is of type X with a name of @name
314
* @e: serialized data extent information
316
* @data: location to store deserialized data if match isX criteria
317
* @name: name to match to the serialized element.
319
* check that the next serialized data element is of type X and has a tag
320
* name @name. If the code matches and name (if specified) matches then
321
* the packed data is unpacked into *data. (Note for strings this is the
322
* size, and the next data in the stream is the string data)
323
* returns %0 if either match failes
325
static int aa_is_nameX(struct aa_ext *e, enum aa_code code, void *data,
331
/* check for presence of a tagname, and if present name size
332
* AA_NAME tag value is a u16 */
333
if (aa_is_X(e, AA_NAME, &size)) {
334
/* if a name is specified it must match. otherwise skip tag */
335
if (name && ((strlen(name) != size-1) ||
336
strncmp(name, (char *)e->pos, (size_t)size-1)))
343
/* now check if data actually matches */
344
ret = aa_is_X(e, code, data);
354
/* macro to wrap error case to make a block of reads look nicer */
355
#define AA_READ_X(E, C, D, N) \
358
__ret = aa_is_nameX((E), (C), (D), (N)); \
364
* aa_activate_net_entry - unpacked serialized net entries
365
* @e: serialized data extent information
367
* Ignore/skips net entries if they are present in the serialized data
368
* stream. Network confinement rules are currently unsupported but some
369
* user side tools can generate them so they are currently ignored.
371
static inline int aa_activate_net_entry(struct aa_ext *e)
373
AA_READ_X(e, AA_STRUCT, NULL, "ne");
374
AA_READ_X(e, AA_U32, NULL, NULL);
375
AA_READ_X(e, AA_U32, NULL, NULL);
376
AA_READ_X(e, AA_U32, NULL, NULL);
377
AA_READ_X(e, AA_U16, NULL, NULL);
378
AA_READ_X(e, AA_U16, NULL, NULL);
379
AA_READ_X(e, AA_U32, NULL, NULL);
380
AA_READ_X(e, AA_U32, NULL, NULL);
381
AA_READ_X(e, AA_U16, NULL, NULL);
382
AA_READ_X(e, AA_U16, NULL, NULL);
383
/* interface name is optional so just ignore return code */
384
aa_is_nameX(e, AA_DYN_STRING, NULL, NULL);
385
AA_READ_X(e, AA_STRUCTEND, NULL, NULL);
393
* aa_activate_file_entry - unpack serialized file entry
394
* @e: serialized data extent information
396
* unpack the information used for a file ACL entry.
398
static inline struct aa_entry *aa_activate_file_entry(struct aa_ext *e)
400
struct aa_entry *entry = NULL;
402
if (!(entry = alloc_aa_entry()))
405
AA_READ_X(e, AA_STRUCT, NULL, "fe");
406
AA_READ_X(e, AA_DYN_STRING, &entry->filename, NULL);
407
AA_READ_X(e, AA_U32, &entry->mode, NULL);
408
AA_READ_X(e, AA_U32, &entry->type, NULL);
410
entry->extradata = aamatch_alloc(entry->type);
411
if (IS_ERR(entry->extradata)) {
412
entry->extradata = NULL;
416
if (entry->extradata &&
417
aamatch_serialize(entry->extradata, e, aa_is_nameX) != 0) {
420
AA_READ_X(e, AA_STRUCTEND, NULL, NULL);
422
switch (entry->type) {
423
case aa_entry_literal:
424
AA_DEBUG("%s: %s [no pattern] mode=0x%x\n",
429
case aa_entry_tailglob:
430
AA_DEBUG("%s: %s [tailglob] mode=0x%x\n",
435
case aa_entry_pattern:
436
AA_DEBUG("%s: %s mode=0x%x\n",
442
AA_WARN("%s: INVALID entry_match_type %d\n",
451
free_aa_entry(entry);
456
* check_rule_and_add - check a file rule is valid and add to a profile
457
* @file_entry: file rule to add
458
* @profile: profile to add the rule to
459
* @message: error message returned if the addition failes.
461
* perform consistency check to ensure that a file rule entry is valid.
462
* If the rule is valid it is added to the profile.
464
static inline int check_rule_and_add(struct aa_entry *file_entry,
465
struct aaprofile *profile,
466
const char **message)
468
/* verify consistency of x, px, ix, ux for entry against
469
possible duplicates for this entry */
470
int mode = AA_EXEC_MODIFIER_MASK(file_entry->mode);
473
if (mode && !(AA_MAY_EXEC & file_entry->mode)) {
474
*message = "inconsistent rule, x modifiers without x";
478
/* check that only 1 of the modifiers is set */
479
if (mode && (mode & (mode - 1))) {
480
*message = "inconsistent rule, multiple x modifiers";
484
/* ix -> m (required so that target exec binary may map itself) */
485
if (mode & AA_EXEC_INHERIT)
486
file_entry->mode |= AA_EXEC_MMAP;
488
list_add(&file_entry->list, &profile->file_entry);
489
profile->num_file_entries++;
491
mode = file_entry->mode;
493
/* Handle partitioned lists
494
* Chain entries onto sublists based on individual
495
* permission bits. This allows more rapid searching.
497
for (i = 0; i <= POS_AA_FILE_MAX; i++) {
499
/* profile->file_entryp[i] initially set to
500
* NULL in alloc_aaprofile() */
501
list_add(&file_entry->listp[i],
502
&profile->file_entryp[i]);
508
free_aa_entry(file_entry);
512
#define AA_ENTRY_LIST(NAME) \
514
if (aa_is_nameX(e, AA_LIST, NULL, (NAME))) { \
516
error_string = "Invalid file entry"; \
517
while (!aa_is_nameX(e, AA_LISTEND, NULL, NULL)) { \
518
struct aa_entry *file_entry; \
519
file_entry = aa_activate_file_entry(e); \
522
if (!check_rule_and_add(file_entry, profile, \
524
rulename = file_entry->filename; \
532
* aa_activate_profile - unpack a serialized profile
533
* @e: serialized data extent information
534
* @error: error code returned if unpacking fails
536
static struct aaprofile *aa_activate_profile(struct aa_ext *e, ssize_t *error)
538
struct aaprofile *profile = NULL;
539
const char *rulename = "";
540
const char *error_string = "Invalid Profile";
544
profile = alloc_aaprofile();
546
error_string = "Could not allocate profile";
551
/* check that we have the right struct being passed */
552
AA_READ_X(e, AA_STRUCT, NULL, "profile");
553
AA_READ_X(e, AA_DYN_STRING, &profile->name, NULL);
555
error_string = "Invalid flags";
556
/* per profile debug flags (debug, complain, audit) */
557
AA_READ_X(e, AA_STRUCT, NULL, "flags");
558
AA_READ_X(e, AA_U32, &(profile->flags.debug), NULL);
559
AA_READ_X(e, AA_U32, &(profile->flags.complain), NULL);
560
AA_READ_X(e, AA_U32, &(profile->flags.audit), NULL);
561
AA_READ_X(e, AA_STRUCTEND, NULL, NULL);
563
error_string = "Invalid capabilities";
564
AA_READ_X(e, AA_U32, &(profile->capabilities), NULL);
566
/* get the file entries. */
567
AA_ENTRY_LIST("pgent"); /* pcre rules */
568
AA_ENTRY_LIST("sgent"); /* simple globs */
569
AA_ENTRY_LIST("fent"); /* regular file entries */
571
/* get the net entries */
572
if (aa_is_nameX(e, AA_LIST, NULL, "net")) {
573
error_string = "Invalid net entry";
574
while (!aa_is_nameX(e, AA_LISTEND, NULL, NULL)) {
575
if (!aa_activate_net_entry(e))
581
/* get subprofiles */
582
if (aa_is_nameX(e, AA_LIST, NULL, "hats")) {
583
error_string = "Invalid profile hat";
584
while (!aa_is_nameX(e, AA_LISTEND, NULL, NULL)) {
585
struct aaprofile *subprofile;
586
subprofile = aa_activate_profile(e, error);
589
subprofile->parent = profile;
590
list_add(&subprofile->list, &profile->sub);
594
error_string = "Invalid end of profile";
595
AA_READ_X(e, AA_STRUCTEND, NULL, NULL);
600
AA_WARN("%s: %s %s in profile %s\n", INTERFACE_ID, rulename,
601
error_string, profile && profile->name ? profile->name
605
free_aaprofile(profile);
613
* aa_activate_top_profile - unpack a serialized base profile
614
* @e: serialized data extent information
615
* @error: error code returned if unpacking fails
617
* check interface version unpack a profile and all its hats and patch
618
* in any extra information that the profile needs.
620
static void *aa_activate_top_profile(struct aa_ext *e, ssize_t *error)
622
struct aaprofile *profile = NULL;
624
/* get the interface version */
625
if (!aa_is_nameX(e, AA_U32, &e->version, "version")) {
626
AA_WARN("%s: version missing\n", INTERFACE_ID);
627
*error = -EPROTONOSUPPORT;
631
/* check that the interface version is currently supported */
632
if (e->version != 2) {
633
AA_WARN("%s: unsupported interface version (%d)\n",
634
INTERFACE_ID, e->version);
635
*error = -EPROTONOSUPPORT;
639
profile = aa_activate_profile(e, error);
643
if (!list_empty(&profile->sub) || profile->flags.complain) {
644
if (attach_nullprofile(profile))
650
free_aaprofile(profile);
655
* aa_file_prof_add - add a new profile to the profile list
656
* @data: serialized data stream
657
* @size: size of the serialized data stream
659
* unpack and add a profile to the profile list. Return %0 or error
661
ssize_t aa_file_prof_add(void *data, size_t size)
663
struct aaprofile *profile = NULL;
672
profile = aa_activate_top_profile(&e, &error);
674
AA_DEBUG("couldn't activate profile\n");
678
/* aa_activate_top_profile allocates profile with initial 1 count
679
* aa_profilelist_add transfers that ref to profile list without
680
* further incrementing
682
if (aa_profilelist_add(profile)) {
685
AA_WARN("trying to add profile (%s) that already exists.\n",
687
put_aaprofile(profile);
696
* aa_file_prof_repl - replace a profile on the profile list
697
* @udata: serialized data stream
698
* @size: size of the serialized data stream
700
* unpack and replace a profile on the profile list and uses of that profile
701
* by any subdomain. If the profile does not exist on the profile list
702
* it is added. Return %0 or error.
704
ssize_t aa_file_prof_repl(void *udata, size_t size)
706
struct aa_taskreplace_data data;
715
data.new_profile = aa_activate_top_profile(&e, &error);
716
if (!data.new_profile) {
717
AA_DEBUG("couldn't activate profile\n");
721
/* Refcount on data.new_profile is 1 (aa_activate_top_profile).
723
* This reference will be inherited by aa_profilelist_replace for it's
724
* profile list reference but this isn't sufficient.
726
* Another replace (*for-same-profile*) may race us here.
727
* Task A calls aa_profilelist_replace(new_profile) and is interrupted.
728
* Task B old_profile = aa_profilelist_replace() will return task A's
729
* new_profile with the count of 1. If task B proceeeds to put this
730
* profile it will dissapear from under task A.
732
* Grab extra reference on new_profile to prevent this
735
get_aaprofile(data.new_profile);
737
data.old_profile = aa_profilelist_replace(data.new_profile);
739
/* If there was an old profile, find all currently executing tasks
740
* using this profile and replace the old profile with the new.
742
if (data.old_profile) {
743
AA_DEBUG("%s: try to replace profile (%p)%s\n",
746
data.old_profile->name);
748
aa_subdomainlist_iterate(taskreplace_iter, (void *)&data);
750
/* it's off global list, and we are done replacing */
751
put_aaprofile(data.old_profile);
754
/* release extra reference obtained above (race) */
755
put_aaprofile(data.new_profile);
764
* aa_file_prof_remove - remove a profile from the system
765
* @name: name of the profile to remove
766
* @size: size of the name
768
* remove a profile from the profile list and all subdomain references
769
* to said profile. Return %0 on success, else error.
771
ssize_t aa_file_prof_remove(const char *name, size_t size)
773
struct aaprofile *old_profile;
775
/* if the old profile exists it will be removed from the list and
776
* a reference is returned.
778
old_profile = aa_profilelist_remove(name);
781
/* remove profile from any tasks using it */
782
aa_subdomainlist_iterate(taskremove_iter, (void *)old_profile);
784
/* drop reference obtained by aa_profilelist_remove */
785
put_aaprofile(old_profile);
787
AA_WARN("%s: trying to remove profile (%s) that "
788
"doesn't exist - skipping.\n", __FUNCTION__, name);
796
* free_aaprofile_kref - free aaprofile by kref (called by put_aaprofile)
797
* @kr: kref callback for freeing of a profile
799
void free_aaprofile_kref(struct kref *kr)
801
struct aaprofile *p=container_of(kr, struct aaprofile, count);
803
/* The is a race between getting the rcu ref of profile from
804
* the subdomain and putting it, so check that the rcu list
805
* entry is not in use, before putting it on the list.
806
* If it is we have raced, it is already there and we don't
807
* have to do anything.
810
if (!p->on_rcu_callback) {
811
p->on_rcu_callback = 1;
812
call_rcu(&p->rcu, free_aaprofile_rcu);
814
spin_unlock(&sd_lock);
818
* free_aaprofile - free aaprofile structure
819
* @profile: the profile to free
821
* free a profile, its file entries hats and null_profile. All references
822
* to the profile, its hats and null_profile must have been put.
823
* If the profile was referenced by a subdomain free_aaprofile should be
824
* called from an rcu callback routine.
826
void free_aaprofile(struct aaprofile *profile)
828
struct aa_entry *ent, *tmp;
829
struct aaprofile *p, *ptmp;
831
AA_DEBUG("%s(%p)\n", __FUNCTION__, profile);
836
/* profile is still on global profile list -- invalid */
837
if (!list_empty(&profile->list)) {
838
AA_ERROR("%s: internal error, "
839
"profile '%s' still on global list\n",
845
list_for_each_entry_safe(ent, tmp, &profile->file_entry, list) {
847
AA_DEBUG("freeing aa_entry: %p %s\n",
848
ent->filename, ent->filename);
849
list_del_init(&ent->list);
853
/* use free_aaprofile instead of put_aaprofile to destroy the
854
* null_profile, because the null_profile use the same reference
855
* counting as hats, ie. the count goes to the base profile.
857
free_aaprofile(profile->null_profile);
858
list_for_each_entry_safe(p, ptmp, &profile->sub, list) {
859
list_del_init(&p->list);
865
AA_DEBUG("%s: %s\n", __FUNCTION__, profile->name);
866
kfree(profile->name);