apparmor/kernel-patches/for-mainline/change_profile-permenent.diff
2007-06-21 18:27:17 +00:00

169 lines
5.4 KiB
Diff

Give change_profile the ability to do a permanent transition
---
security/apparmor/apparmor.h | 2 +-
security/apparmor/main.c | 33 +++++++++++++++++++++++++--------
security/apparmor/procattr.c | 18 +++++++++++++-----
3 files changed, 39 insertions(+), 14 deletions(-)
--- a/security/apparmor/apparmor.h
+++ b/security/apparmor/apparmor.h
@@ -215,7 +215,7 @@ extern int aa_clone(struct task_struct *
extern int aa_register(struct linux_binprm *bprm);
extern void aa_release(struct task_struct *task);
extern int aa_change_hat(const char *id, u64 hat_magic);
-extern int aa_change_profile(const char *name, u64 cookie);
+extern int aa_change_profile(const char *name, u64 cookie, int permanent);
extern struct aa_profile *__aa_find_profile(const char *name,
struct list_head *list);
extern struct aa_profile *__aa_find_profile2(const char *name,
--- a/security/apparmor/main.c
+++ b/security/apparmor/main.c
@@ -929,7 +929,9 @@ repeat:
}
}
-static int do_change_profile(const char *name, u64 cookie, int restore_profile,
+enum { change_profile, permanent_change_profile, restore_profile };
+
+static int do_change_profile(const char *name, u64 cookie, int mode,
struct aa_audit *sa)
{
struct aa_profile *profile = NULL, *previous_profile = NULL;
@@ -943,7 +945,7 @@ static int do_change_profile(const char
return -ENOMEM;
profile = aa_find_profile(name);
- if (!profile && !restore_profile)
+ if (!profile && mode != restore_profile)
profile = aa_dup_profile(null_complain_profile);
cxt = lock_task_and_profiles(current, profile);
@@ -967,6 +969,12 @@ static int do_change_profile(const char
previous_profile = cxt->profile;
}
+ if (mode == permanent_change_profile) {
+ previous_profile = NULL;
+ cookie = 0;
+ sa->info = "permanent";
+ }
+
if ((current->ptrace & PT_PTRACED) && aa_may_ptrace(cxt, profile)) {
error = -EACCES;
goto out;
@@ -983,7 +991,7 @@ static int do_change_profile(const char
if (APPARMOR_AUDIT(cxt))
aa_audit_message(cxt->profile, sa, AUDIT_APPARMOR_AUDIT);
- if (restore_profile)
+ if (mode == restore_profile)
aa_change_task_context(current, new_cxt, profile, 0, NULL);
else
aa_change_task_context(current, new_cxt, profile, cookie,
@@ -1002,6 +1010,7 @@ out:
* aa_change_profile - change profile to/from previous stored profile
* @name: name of profile to change to
* @cookie: magic value to validate the profile change
+ * @permanent: whether the profile change is permanent
*
* Change to new profile @name, and store the @cookie in the current task
* context. If the new @name is %NULL and the @cookie matches that
@@ -1009,7 +1018,7 @@ out:
*
* Returns %0 on success, error otherwise.
*/
-int aa_change_profile(const char *name, u64 cookie)
+int aa_change_profile(const char *name, u64 cookie, int permanent)
{
struct aa_task_context *cxt;
struct aa_audit sa;
@@ -1036,11 +1045,18 @@ int aa_change_profile(const char *name,
mutex_unlock(&aa_interface_lock);
return -EACCES;
}
- error = do_change_profile(name, cookie, 0, &sa);
+ if (permanent)
+ error = do_change_profile(name, cookie,
+ permanent_change_profile,
+ &sa);
+ else
+ error = do_change_profile(name, cookie, change_profile,
+ &sa);
} else {
if (cxt->previous_profile)
error = do_change_profile(cxt->previous_profile->name,
- cookie, 1, &sa);
+ cookie, restore_profile,
+ &sa);
/* else
* Ignore change_profile to restore_previous profile when
* it doesn't exist
@@ -1097,12 +1113,13 @@ int aa_change_hat(const char *hat_name,
return -ENOMEM;
}
sprintf(name, "%s//%s", profile_name, hat_name);
- error = do_change_profile(name, cookie, 0, &sa);
+ error = do_change_profile(name, cookie, change_profile, &sa);
kfree(name);
} else {
if (cxt->previous_profile)
error = do_change_profile(cxt->previous_profile->name,
- cookie, 1, &sa);
+ cookie, restore_profile,
+ &sa);
/* else
* Ignore change_hat to restore profile when there is
* no profile to restore
--- a/security/apparmor/procattr.c
+++ b/security/apparmor/procattr.c
@@ -50,14 +50,19 @@ int aa_getprocattr(struct aa_profile *pr
return 0;
}
-static char *split_token_from_name(const char *op, char *args, u64 *cookie)
+static char *split_token_from_name(const char *op, int *cookie_set,
+ char *args, u64 *cookie)
{
char *name;
*cookie = simple_strtoull(args, &name, 16);
- if (name == args || *name != '^') {
+ if ((name == args && *cookie_set) || *name != '^') {
AA_ERROR("%s: Invalid input '%s'", op, args);
return ERR_PTR(-EINVAL);
+ } else if (name == args) {
+ *cookie_set = 0;
+ } else {
+ *cookie_set = 1;
}
name++; /* skip ^ */
if (!*name)
@@ -69,8 +74,9 @@ int aa_setprocattr_changehat(char *args)
{
char *hat;
u64 cookie;
+ int cookie_set = 1;
- hat = split_token_from_name("change_hat", args, &cookie);
+ hat = split_token_from_name("change_hat", &cookie_set, args, &cookie);
if (IS_ERR(hat))
return PTR_ERR(hat);
@@ -89,12 +95,14 @@ int aa_setprocattr_changeprofile(char *a
{
char *name;
u64 cookie;
+ int cookie_set = 0;
- name = split_token_from_name("change_profile", args, &cookie);
+ name = split_token_from_name("change_profile", &cookie_set, args,
+ &cookie);
if (IS_ERR(name))
return PTR_ERR(name);
- return aa_change_profile(name, cookie);
+ return aa_change_profile(name, cookie, !cookie_set);
}
int aa_setprocattr_setprofile(struct task_struct *task, char *args)