mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-09 10:51:03 +01:00
169 lines
5.4 KiB
Diff
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)
|