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 "aamatch/match.h"
19
/* sd_code defined in module_interface.h */
21
const int sdcode_datasize[] = { 1, 2, 4, 8, 2, 2, 4, 0, 0, 0, 0, 0, 0 };
23
struct sd_taskreplace_data {
24
struct sdprofile *old_profile;
25
struct sdprofile *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_sd_entry(struct sd_entry *entry)
34
kfree(entry->filename);
35
sdmatch_free(entry->extradata);
41
* alloc_sd_entry - create new empty sd_entry
43
* This routine allocates, initializes, and returns a new subdomain
44
* file entry structure. Structure is zeroed. Returns new structure on
45
* success, NULL on failure.
47
static inline struct sd_entry *alloc_sd_entry(void)
49
struct sd_entry *entry;
51
SD_DEBUG("%s\n", __FUNCTION__);
52
entry = kmalloc(sizeof(struct sd_entry), GFP_KERNEL);
55
memset(entry, 0, sizeof(struct sd_entry));
56
INIT_LIST_HEAD(&entry->list);
57
for (i = 0; i <= POS_SD_FILE_MAX; i++) {
58
INIT_LIST_HEAD(&entry->listp[i]);
65
* free_sdprofile - free sdprofile structure
67
void free_sdprofile(struct sdprofile *profile)
69
struct sd_entry *sdent, *tmp;
70
struct sdprofile *p, *ptmp;
72
SD_DEBUG("%s(%p)\n", __FUNCTION__, profile);
77
/* profile is still on global profile list -- invalid */
78
if (!list_empty(&profile->list)) {
79
SD_ERROR("%s: internal error, "
80
"profile '%s' still on global list\n",
86
list_for_each_entry_safe(sdent, tmp, &profile->file_entry, list) {
88
SD_DEBUG("freeing sd_entry: %p %s\n",
89
sdent->filename, sdent->filename);
90
list_del_init(&sdent->list);
94
list_for_each_entry_safe(p, ptmp, &profile->sub, list) {
95
list_del_init(&p->list);
100
SD_DEBUG("%s: %s\n", __FUNCTION__, profile->name);
101
kfree(profile->name);
109
* remove profile in a task's subdomain leaving the task unconfined
111
* @sd: task's subdomain
113
static inline void task_remove(struct subdomain *sd)
115
/* write_lock(&sd_lock) held here */
116
SD_DEBUG("%s: removing profile from task %s(%d) profile %s active %s\n",
123
sd_switch_unconfined(sd);
128
* Iterate over all subdomains.
130
* If any matches old_profile, then call task_remove to remove it.
131
* This leaves the task (subdomain) unconfined.
133
static int taskremove_iter(struct subdomain *sd, void *cookie)
135
struct sdprofile *old_profile = (struct sdprofile *)cookie;
138
write_lock_irqsave(&sd_lock, flags);
140
if (__sd_is_confined(sd) && sd->profile == old_profile)
143
write_unlock_irqrestore(&sd_lock, flags);
150
* replace profile in a task's subdomain with newly loaded profile
152
* @sd: task's subdomain
155
static inline void task_replace(struct subdomain *sd, struct sdprofile *new)
157
struct sdprofile *nactive = NULL;
159
SD_DEBUG("%s: replacing profile for task %s(%d) "
160
"profile=%s (%p) active=%s (%p)\n",
162
sd->task->comm, sd->task->pid,
163
sd->profile->name, sd->profile,
164
sd->active->name, sd->active);
166
if (sd->profile == sd->active)
167
nactive = get_sdprofile(new);
168
else if (sd->active) {
169
/* old in hat, new profile has hats */
170
nactive = __sd_find_profile(sd->active->name, &new->sub);
173
if (new->flags.complain)
174
nactive = get_sdprofile(null_complain_profile);
176
nactive = get_sdprofile(null_profile);
179
sd_switch(sd, new, nactive);
181
put_sdprofile(nactive);
186
* Iterate over all subdomains.
188
* If any matches old_profile, then call task_replace to replace with
191
static int taskreplace_iter(struct subdomain *sd, void *cookie)
193
struct sd_taskreplace_data *data = (struct sd_taskreplace_data *)cookie;
196
write_lock_irqsave(&sd_lock, flags);
198
if (__sd_is_confined(sd) && sd->profile == data->old_profile)
199
task_replace(sd, data->new_profile);
201
write_unlock_irqrestore(&sd_lock, flags);
206
static inline int sd_inbounds(struct sd_ext *e, size_t size)
208
return (e->pos + size <= e->end);
212
* sdconvert - for codes that have a trailing value, convert that value
213
* and put it in dest.
214
* if a code does not have a trailing value nop
216
* @dest: pointer to object to receive the converted value
217
* @src: pointer to value to convert
219
static void sdconvert(enum sd_code code, void *dest, void *src)
223
*(u8 *)dest = *(u8 *) src;
228
*(u16 *)dest = le16_to_cpu(get_unaligned((u16 *)src));
232
*(u32 *)dest = le32_to_cpu(get_unaligned((u32 *)src));
235
*(u64 *)dest = le64_to_cpu(get_unaligned((u64 *)src));
238
/* nop - all other type codes do not have a trailing value */
244
* sd_is_X - check if the next element is of type X and if it is within
245
* bounds. If it is put the associated value in data.
246
* @e: extent information
248
* @data: object located at @e->pos (of type @code) is written into @data
249
* if @data is non-null. if data is null it means skip this
251
* return the size of bytes associated with the returned data
252
* for complex object like blob and string a pointer to the allocated
253
* data is returned in data, but the size of the blob or string is
256
static u32 sd_is_X(struct sd_ext *e, enum sd_code code, void *data)
260
if (!sd_inbounds(e, SD_CODE_BYTE + sdcode_datasize[code]))
262
if (code != *(u8 *)e->pos)
264
e->pos += SD_CODE_BYTE;
265
if (code == SD_NAME) {
267
/* name codes are followed by X bytes */
268
size = le16_to_cpu(get_unaligned((u16 *)e->pos));
269
if (!sd_inbounds(e, (size_t) size))
273
e->pos += sdcode_datasize[code];
274
ret = 1 + sdcode_datasize[code];
275
} else if (code == SD_DYN_STRING) {
278
/* strings codes are followed by X bytes */
279
size = le16_to_cpu(get_unaligned((u16 *)e->pos));
280
e->pos += sdcode_datasize[code];
281
if (!sd_inbounds(e, (size_t) size))
284
* (char **)data = NULL;
285
str = kmalloc(size, GFP_KERNEL);
288
memcpy(str, e->pos, (size_t) size);
290
* (char **)data = str;
294
} else if (code == SD_STATIC_BLOB) {
296
/* blobs are followed by X bytes, that can be 2^32 */
297
size = le32_to_cpu(get_unaligned((u32 *)e->pos));
298
e->pos += sdcode_datasize[code];
299
if (!sd_inbounds(e, (size_t) size))
302
memcpy(data, e->pos, (size_t) size);
307
sdconvert(code, data, e->pos);
308
e->pos += sdcode_datasize[code];
309
ret = 1 + sdcode_datasize[code];
318
/* sd_is_nameX - check is the next element is X, and its tag is name.
319
* if the code matches and name (if specified) matches then the packed data
320
* is unpacked into *data. (Note for strings this is the size, and the next
321
* data in the stream is the string data)
322
* returns 0 if either match failes
324
static int sd_is_nameX(struct sd_ext *e, enum sd_code code, void *data,
330
/* check for presence of a tagname, and if present name size
331
* SD_NAME tag value is a u16 */
332
if (sd_is_X(e, SD_NAME, &size)) {
333
/* if a name is specified it must match. otherwise skip tag */
334
if (name && ((strlen(name) != size-1) ||
335
strncmp(name, (char *)e->pos, (size_t)size-1)))
339
/* now check if data actually matches */
340
ret = sd_is_X(e, code, data);
350
/* macro to wrap error case to make a block of reads look nicer */
351
#define SD_READ_X(E, C, D, N) \
354
__ret = sd_is_nameX((E), (C), (D), (N)); \
360
* sd_activate_net_entry - ignores/skips net entries if the they are present
361
* in the data stream.
362
* @e: extent information
364
static inline int sd_activate_net_entry(struct sd_ext *e)
366
SD_READ_X(e, SD_STRUCT, NULL, "ne");
367
SD_READ_X(e, SD_U32, NULL, NULL);
368
SD_READ_X(e, SD_U32, NULL, NULL);
369
SD_READ_X(e, SD_U32, NULL, NULL);
370
SD_READ_X(e, SD_U16, NULL, NULL);
371
SD_READ_X(e, SD_U16, NULL, NULL);
372
SD_READ_X(e, SD_U32, NULL, NULL);
373
SD_READ_X(e, SD_U32, NULL, NULL);
374
SD_READ_X(e, SD_U16, NULL, NULL);
375
SD_READ_X(e, SD_U16, NULL, NULL);
376
/* interface name is optional so just ignore return code */
377
sd_is_nameX(e, SD_DYN_STRING, NULL, NULL);
378
SD_READ_X(e, SD_STRUCTEND, NULL, NULL);
385
static inline struct sd_entry *sd_activate_file_entry(struct sd_ext *e)
387
struct sd_entry *entry = NULL;
389
if (!(entry = alloc_sd_entry()))
392
SD_READ_X(e, SD_STRUCT, NULL, "fe");
393
SD_READ_X(e, SD_DYN_STRING, &entry->filename, NULL);
394
SD_READ_X(e, SD_U32, &entry->mode, "file.mode");
395
SD_READ_X(e, SD_U32, &entry->entry_type, "file.pattern_type");
397
entry->extradata = sdmatch_alloc(entry->entry_type);
398
if (IS_ERR(entry->extradata)) {
399
entry->extradata = NULL;
403
if (entry->extradata &&
404
sdmatch_serialize(entry->extradata, e, sd_is_nameX) != 0) {
407
SD_READ_X(e, SD_STRUCTEND, NULL, NULL);
409
switch (entry->entry_type) {
410
case sd_entry_literal:
411
SD_DEBUG("%s: %s [no pattern] mode=0x%x\n",
416
case sd_entry_tailglob:
417
SD_DEBUG("%s: %s [tailglob] mode=0x%x\n",
422
case sd_entry_pattern:
423
SD_DEBUG("%s: %s mode=0x%x\n",
429
SD_WARN("%s: INVALID entry_type %d\n",
431
(int)entry->entry_type);
438
sdmatch_free(entry->extradata);
439
free_sd_entry(entry);
443
static inline int check_rule_and_add(struct sd_entry *file_entry,
444
struct sdprofile *profile,
445
const char **message)
447
/* verify consistency of x, px, ix, ux for entry against
448
possible duplicates for this entry */
449
int mode = SD_EXEC_MODIFIER_MASK(file_entry->mode);
452
if (mode && !(SD_MAY_EXEC & file_entry->mode)) {
453
*message = "inconsistent rule, x modifiers without x";
457
/* check that only 1 of the modifiers is set */
458
if (mode && (mode & (mode - 1))) {
459
*message = "inconsistent rule, multiple x modifiers";
463
/* ix -> m (required so that target exec binary may map itself) */
464
if (mode & SD_EXEC_INHERIT)
465
file_entry->mode |= SD_EXEC_MMAP;
467
list_add(&file_entry->list, &profile->file_entry);
468
profile->num_file_entries++;
470
mode = file_entry->mode;
472
/* Handle partitioned lists
473
* Chain entries onto sublists based on individual
474
* permission bits. This allows more rapid searching.
476
for (i = 0; i <= POS_SD_FILE_MAX; i++) {
478
/* profile->file_entryp[i] initially set to
479
* NULL in alloc_sdprofile() */
480
list_add(&file_entry->listp[i],
481
&profile->file_entryp[i]);
487
free_sd_entry(file_entry);
491
#define SD_ENTRY_LIST(NAME) \
493
if (sd_is_nameX(e, SD_LIST, NULL, (NAME))) { \
495
error_string = "Invalid file entry"; \
496
while (!sd_is_nameX(e, SD_LISTEND, NULL, NULL)) { \
497
struct sd_entry *file_entry; \
498
file_entry = sd_activate_file_entry(e); \
501
if (!check_rule_and_add(file_entry, profile, \
503
rulename = file_entry->filename; \
510
struct sdprofile *sd_activate_profile(struct sd_ext *e, ssize_t *error)
512
struct sdprofile *profile = NULL;
513
const char *rulename = "";
514
const char *error_string = "Invalid Profile";
518
profile = alloc_sdprofile();
520
error_string = "Could not allocate profile";
525
/* check that we have the right struct being passed */
526
SD_READ_X(e, SD_STRUCT, NULL, "profile");
527
SD_READ_X(e, SD_DYN_STRING, &profile->name, NULL);
529
error_string = "Invalid flags";
530
/* per profile debug flags (debug, complain, audit) */
531
SD_READ_X(e, SD_STRUCT, NULL, "flags");
532
SD_READ_X(e, SD_U32, &(profile->flags.debug), "profile.flags.debug");
533
SD_READ_X(e, SD_U32, &(profile->flags.complain),
534
"profile.flags.complain");
535
SD_READ_X(e, SD_U32, &(profile->flags.audit), "profile.flags.audit");
536
SD_READ_X(e, SD_STRUCTEND, NULL, NULL);
538
error_string = "Invalid capabilities";
539
SD_READ_X(e, SD_U32, &(profile->capabilities), "profile.capabilities");
541
/* get the file entries. */
542
SD_ENTRY_LIST("pgent"); /* pcre rules */
543
SD_ENTRY_LIST("sgent"); /* simple globs */
544
SD_ENTRY_LIST("fent"); /* regular file entries */
546
/* get the net entries */
547
if (sd_is_nameX(e, SD_LIST, NULL, "net")) {
548
error_string = "Invalid net entry";
549
while (!sd_is_nameX(e, SD_LISTEND, NULL, NULL)) {
550
if (!sd_activate_net_entry(e))
556
/* get subprofiles */
557
if (sd_is_nameX(e, SD_LIST, NULL, "hats")) {
558
error_string = "Invalid profile hat";
559
while (!sd_is_nameX(e, SD_LISTEND, NULL, NULL)) {
560
struct sdprofile *subprofile;
561
subprofile = sd_activate_profile(e, error);
564
get_sdprofile(subprofile);
565
list_add(&subprofile->list, &profile->sub);
569
error_string = "Invalid end of profile";
570
SD_READ_X(e, SD_STRUCTEND, NULL, NULL);
575
SD_WARN("%s: %s %s in profile %s\n", INTERFACE_ID, rulename,
576
error_string, profile && profile->name ? profile->name
580
free_sdprofile(profile);
587
void *sd_activate_top_profile(struct sd_ext *e, ssize_t *error)
589
/* get the interface version */
590
if (!sd_is_nameX(e, SD_U32, &e->version, "version")) {
591
SD_WARN("%s: version missing\n", INTERFACE_ID);
592
*error = -EPROTONOSUPPORT;
596
/* check that the interface version is currently supported */
597
if (e->version != 2) {
598
SD_WARN("%s: unsupported interface version (%d)\n",
599
INTERFACE_ID, e->version);
600
*error = -EPROTONOSUPPORT;
604
return sd_activate_profile(e, error);
609
ssize_t sd_file_prof_add(void *data, size_t size)
611
struct sdprofile *profile = NULL;
613
struct sd_ext e = { data, data + size, data };
616
profile = sd_activate_top_profile(&e, &error);
618
SD_DEBUG("couldn't activate profile\n");
622
if (!sd_profilelist_add(profile)) {
623
SD_WARN("trying to add profile (%s) that already exists.\n",
625
free_sdprofile(profile);
632
ssize_t sd_file_prof_repl(void *udata, size_t size)
634
struct sd_taskreplace_data data;
635
struct sd_ext e = { udata, udata + size, udata };
638
data.new_profile = sd_activate_top_profile(&e, &error);
639
if (!data.new_profile) {
640
SD_DEBUG("couldn't activate profile\n");
643
/* Grab reference to close race window (see comment below) */
644
get_sdprofile(data.new_profile);
646
/* Replace the profile on the global profile list.
647
* This list is used by all new exec's to find the correct profile.
648
* If there was a previous profile, it is returned, else NULL.
650
* N.B sd_profilelist_replace does not drop the refcnt on
651
* old_profile when removing it from the global list, otherwise it
652
* could reach zero and be automatically free'd. We nust manually
653
* drop it at the end of this function when we are finished with it.
655
data.old_profile = sd_profilelist_replace(data.new_profile);
658
* At this point another task could preempt us trying to replace
659
* the SAME profile. If it makes it to this point, it has removed
660
* the original tasks new_profile from the global list and holds a
661
* reference of 1 to it in it's old_profile. If the new task
662
* reaches the end of the function it will put old_profile causing
663
* the profile to be deleted.
664
* When the original task is rescheduled it will continue calling
665
* sd_subdomainlist_iterate relabelling tasks with a profile
666
* which points to free'd memory.
669
/* If there was an old profile, find all currently executing tasks
670
* using this profile and replace the old profile with the new.
672
if (data.old_profile) {
673
SD_DEBUG("%s: try to replace profile (%p)%s\n",
676
data.old_profile->name);
678
sd_subdomainlist_iterate(taskreplace_iter, (void *)&data);
680
/* it's off global list, and we are done replacing */
681
put_sdprofile(data.old_profile);
684
/* Free reference obtained above */
685
put_sdprofile(data.new_profile);
690
ssize_t sd_file_prof_remove(const char *name, size_t size)
692
struct sdprofile *old_profile;
694
/* if the old profile exists it will be removed from the list and
695
* a reference is returned.
697
old_profile = sd_profilelist_remove(name);
700
/* remove profile from any tasks using it */
701
sd_subdomainlist_iterate(taskremove_iter, (void *)old_profile);
703
/* drop reference obtained by sd_profilelist_remove */
704
put_sdprofile(old_profile);
706
SD_WARN("%s: trying to remove profile (%s) that "
707
"doesn't exist - skipping.\n", __FUNCTION__, name);