summaryrefslogtreecommitdiffstats
path: root/security/apparmor/file.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/apparmor/file.c')
-rw-r--r--security/apparmor/file.c125
1 files changed, 37 insertions, 88 deletions
diff --git a/security/apparmor/file.c b/security/apparmor/file.c
index d43679894d23..cb3d3060d104 100644
--- a/security/apparmor/file.c
+++ b/security/apparmor/file.c
@@ -95,7 +95,7 @@ int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms,
kuid_t ouid, const char *info, int error)
{
int type = AUDIT_APPARMOR_AUTO;
- DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_TASK, op);
+ DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_TASK, AA_CLASS_FILE, op);
sa.u.tsk = NULL;
aad(&sa)->request = request;
@@ -141,19 +141,6 @@ int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms,
return aa_audit(type, profile, &sa, file_audit_cb);
}
-/**
- * is_deleted - test if a file has been completely unlinked
- * @dentry: dentry of file to test for deletion (NOT NULL)
- *
- * Returns: true if deleted else false
- */
-static inline bool is_deleted(struct dentry *dentry)
-{
- if (d_unlinked(dentry) && d_backing_inode(dentry)->i_nlink == 0)
- return true;
- return false;
-}
-
static int path_name(const char *op, struct aa_label *label,
const struct path *path, int flags, char *buffer,
const char **name, struct path_cond *cond, u32 request)
@@ -175,73 +162,28 @@ static int path_name(const char *op, struct aa_label *label,
}
/**
- * map_old_perms - map old file perms layout to the new layout
- * @old: permission set in old mapping
- *
- * Returns: new permission mapping
- */
-static u32 map_old_perms(u32 old)
-{
- u32 new = old & 0xf;
- if (old & MAY_READ)
- new |= AA_MAY_GETATTR | AA_MAY_OPEN;
- if (old & MAY_WRITE)
- new |= AA_MAY_SETATTR | AA_MAY_CREATE | AA_MAY_DELETE |
- AA_MAY_CHMOD | AA_MAY_CHOWN | AA_MAY_OPEN;
- if (old & 0x10)
- new |= AA_MAY_LINK;
- /* the old mapping lock and link_subset flags where overlaid
- * and use was determined by part of a pair that they were in
- */
- if (old & 0x20)
- new |= AA_MAY_LOCK | AA_LINK_SUBSET;
- if (old & 0x40) /* AA_EXEC_MMAP */
- new |= AA_EXEC_MMAP;
-
- return new;
-}
-
-/**
- * aa_compute_fperms - convert dfa compressed perms to internal perms
- * @dfa: dfa to compute perms for (NOT NULL)
+ * aa_lookup_fperms - convert dfa compressed perms to internal perms
+ * @dfa: dfa to lookup perms for (NOT NULL)
* @state: state in dfa
* @cond: conditions to consider (NOT NULL)
*
- * TODO: convert from dfa + state to permission entry, do computation conversion
- * at load time.
+ * TODO: convert from dfa + state to permission entry
*
- * Returns: computed permission set
+ * Returns: a pointer to a file permission set
*/
-struct aa_perms aa_compute_fperms(struct aa_dfa *dfa, unsigned int state,
- struct path_cond *cond)
+struct aa_perms default_perms = {};
+struct aa_perms *aa_lookup_fperms(struct aa_policydb *file_rules,
+ aa_state_t state, struct path_cond *cond)
{
- /* FIXME: change over to new dfa format
- * currently file perms are encoded in the dfa, new format
- * splits the permissions from the dfa. This mapping can be
- * done at profile load
- */
- struct aa_perms perms = { };
+ unsigned int index = ACCEPT_TABLE(file_rules->dfa)[state];
- if (uid_eq(current_fsuid(), cond->uid)) {
- perms.allow = map_old_perms(dfa_user_allow(dfa, state));
- perms.audit = map_old_perms(dfa_user_audit(dfa, state));
- perms.quiet = map_old_perms(dfa_user_quiet(dfa, state));
- perms.xindex = dfa_user_xindex(dfa, state);
- } else {
- perms.allow = map_old_perms(dfa_other_allow(dfa, state));
- perms.audit = map_old_perms(dfa_other_audit(dfa, state));
- perms.quiet = map_old_perms(dfa_other_quiet(dfa, state));
- perms.xindex = dfa_other_xindex(dfa, state);
- }
- perms.allow |= AA_MAY_GETATTR;
+ if (!(file_rules->perms))
+ return &default_perms;
- /* change_profile wasn't determined by ownership in old mapping */
- if (ACCEPT_TABLE(dfa)[state] & 0x80000000)
- perms.allow |= AA_MAY_CHANGE_PROFILE;
- if (ACCEPT_TABLE(dfa)[state] & 0x40000000)
- perms.allow |= AA_MAY_ONEXEC;
+ if (uid_eq(current_fsuid(), cond->uid))
+ return &(file_rules->perms[index]);
- return perms;
+ return &(file_rules->perms[index + 1]);
}
/**
@@ -254,26 +196,30 @@ struct aa_perms aa_compute_fperms(struct aa_dfa *dfa, unsigned int state,
*
* Returns: the final state in @dfa when beginning @start and walking @name
*/
-unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start,
- const char *name, struct path_cond *cond,
- struct aa_perms *perms)
+aa_state_t aa_str_perms(struct aa_policydb *file_rules, aa_state_t start,
+ const char *name, struct path_cond *cond,
+ struct aa_perms *perms)
{
- unsigned int state;
- state = aa_dfa_match(dfa, start, name);
- *perms = aa_compute_fperms(dfa, state, cond);
+ aa_state_t state;
+ state = aa_dfa_match(file_rules->dfa, start, name);
+ *perms = *(aa_lookup_fperms(file_rules, state, cond));
return state;
}
-int __aa_path_perm(const char *op, struct aa_profile *profile, const char *name,
- u32 request, struct path_cond *cond, int flags,
- struct aa_perms *perms)
+static int __aa_path_perm(const char *op, struct aa_profile *profile,
+ const char *name, u32 request,
+ struct path_cond *cond, int flags,
+ struct aa_perms *perms)
{
+ struct aa_ruleset *rules = list_first_entry(&profile->rules,
+ typeof(*rules), list);
int e = 0;
if (profile_unconfined(profile))
return 0;
- aa_str_perms(profile->file.dfa, profile->file.start, name, cond, perms);
+ aa_str_perms(&(rules->file), rules->file.start[AA_CLASS_FILE],
+ name, cond, perms);
if (request & ~perms->allow)
e = -EACCES;
return aa_audit_file(profile, perms, op, request, name, NULL, NULL,
@@ -360,11 +306,13 @@ static int profile_path_link(struct aa_profile *profile,
const struct path *target, char *buffer2,
struct path_cond *cond)
{
+ struct aa_ruleset *rules = list_first_entry(&profile->rules,
+ typeof(*rules), list);
const char *lname, *tname = NULL;
struct aa_perms lperms = {}, perms;
const char *info = NULL;
u32 request = AA_MAY_LINK;
- unsigned int state;
+ aa_state_t state;
int error;
error = path_name(OP_LINK, &profile->label, link, profile->path_flags,
@@ -380,15 +328,16 @@ static int profile_path_link(struct aa_profile *profile,
error = -EACCES;
/* aa_str_perms - handles the case of the dfa being NULL */
- state = aa_str_perms(profile->file.dfa, profile->file.start, lname,
+ state = aa_str_perms(&(rules->file),
+ rules->file.start[AA_CLASS_FILE], lname,
cond, &lperms);
if (!(lperms.allow & AA_MAY_LINK))
goto audit;
/* test to see if target can be paired with link */
- state = aa_dfa_null_transition(profile->file.dfa, state);
- aa_str_perms(profile->file.dfa, state, tname, cond, &perms);
+ state = aa_dfa_null_transition(rules->file.dfa, state);
+ aa_str_perms(&(rules->file), state, tname, cond, &perms);
/* force audit/quiet masks for link are stored in the second entry
* in the link pair.
@@ -410,8 +359,8 @@ static int profile_path_link(struct aa_profile *profile,
/* Do link perm subset test requiring allowed permission on link are
* a subset of the allowed permissions on target.
*/
- aa_str_perms(profile->file.dfa, profile->file.start, tname, cond,
- &perms);
+ aa_str_perms(&(rules->file), rules->file.start[AA_CLASS_FILE],
+ tname, cond, &perms);
/* AA_MAY_LINK is not considered in the subset test */
request = lperms.allow & ~AA_MAY_LINK;