apparmor: update policy capable checks to use a label
Previously the policy capable checks assumed they were using the current task. Make them take the task label so the query can be made against an arbitrary task. Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
parent
5268d795d6
commit
92de220a7f
|
@ -1357,7 +1357,7 @@ static int rawdata_open(struct inode *inode, struct file *file)
|
||||||
struct aa_loaddata *loaddata;
|
struct aa_loaddata *loaddata;
|
||||||
struct rawdata_f_data *private;
|
struct rawdata_f_data *private;
|
||||||
|
|
||||||
if (!policy_view_capable(NULL))
|
if (!aa_current_policy_view_capable(NULL))
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
|
|
||||||
loaddata = __aa_get_loaddata(inode->i_private);
|
loaddata = __aa_get_loaddata(inode->i_private);
|
||||||
|
@ -2266,7 +2266,7 @@ static const struct seq_operations aa_sfs_profiles_op = {
|
||||||
|
|
||||||
static int profiles_open(struct inode *inode, struct file *file)
|
static int profiles_open(struct inode *inode, struct file *file)
|
||||||
{
|
{
|
||||||
if (!policy_view_capable(NULL))
|
if (!aa_current_policy_view_capable(NULL))
|
||||||
return -EACCES;
|
return -EACCES;
|
||||||
|
|
||||||
return seq_open(file, &aa_sfs_profiles_op);
|
return seq_open(file, &aa_sfs_profiles_op);
|
||||||
|
|
|
@ -148,6 +148,7 @@ do { \
|
||||||
#define __label_make_stale(X) ((X)->flags |= FLAG_STALE)
|
#define __label_make_stale(X) ((X)->flags |= FLAG_STALE)
|
||||||
#define labels_ns(X) (vec_ns(&((X)->vec[0]), (X)->size))
|
#define labels_ns(X) (vec_ns(&((X)->vec[0]), (X)->size))
|
||||||
#define labels_set(X) (&labels_ns(X)->labels)
|
#define labels_set(X) (&labels_ns(X)->labels)
|
||||||
|
#define labels_view(X) labels_ns(X)
|
||||||
#define labels_profile(X) ((X)->vec[(X)->size - 1])
|
#define labels_profile(X) ((X)->vec[(X)->size - 1])
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -301,9 +301,11 @@ static inline int AUDIT_MODE(struct aa_profile *profile)
|
||||||
return profile->audit;
|
return profile->audit;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool policy_view_capable(struct aa_ns *ns);
|
bool aa_policy_view_capable(struct aa_label *label, struct aa_ns *ns);
|
||||||
bool policy_admin_capable(struct aa_ns *ns);
|
bool aa_policy_admin_capable(struct aa_label *label, struct aa_ns *ns);
|
||||||
int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns,
|
int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns,
|
||||||
u32 mask);
|
u32 mask);
|
||||||
|
bool aa_current_policy_view_capable(struct aa_ns *ns);
|
||||||
|
bool aa_current_policy_admin_capable(struct aa_ns *ns);
|
||||||
|
|
||||||
#endif /* __AA_POLICY_H */
|
#endif /* __AA_POLICY_H */
|
||||||
|
|
|
@ -1392,7 +1392,7 @@ static int param_set_aalockpolicy(const char *val, const struct kernel_param *kp
|
||||||
{
|
{
|
||||||
if (!apparmor_enabled)
|
if (!apparmor_enabled)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (apparmor_initialized && !policy_admin_capable(NULL))
|
if (apparmor_initialized && !aa_current_policy_admin_capable(NULL))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
return param_set_bool(val, kp);
|
return param_set_bool(val, kp);
|
||||||
}
|
}
|
||||||
|
@ -1401,7 +1401,7 @@ static int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp)
|
||||||
{
|
{
|
||||||
if (!apparmor_enabled)
|
if (!apparmor_enabled)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (apparmor_initialized && !policy_view_capable(NULL))
|
if (apparmor_initialized && !aa_current_policy_view_capable(NULL))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
return param_get_bool(buffer, kp);
|
return param_get_bool(buffer, kp);
|
||||||
}
|
}
|
||||||
|
@ -1410,7 +1410,7 @@ static int param_set_aabool(const char *val, const struct kernel_param *kp)
|
||||||
{
|
{
|
||||||
if (!apparmor_enabled)
|
if (!apparmor_enabled)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (apparmor_initialized && !policy_admin_capable(NULL))
|
if (apparmor_initialized && !aa_current_policy_admin_capable(NULL))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
return param_set_bool(val, kp);
|
return param_set_bool(val, kp);
|
||||||
}
|
}
|
||||||
|
@ -1419,7 +1419,7 @@ static int param_get_aabool(char *buffer, const struct kernel_param *kp)
|
||||||
{
|
{
|
||||||
if (!apparmor_enabled)
|
if (!apparmor_enabled)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (apparmor_initialized && !policy_view_capable(NULL))
|
if (apparmor_initialized && !aa_current_policy_view_capable(NULL))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
return param_get_bool(buffer, kp);
|
return param_get_bool(buffer, kp);
|
||||||
}
|
}
|
||||||
|
@ -1445,7 +1445,7 @@ static int param_get_aauint(char *buffer, const struct kernel_param *kp)
|
||||||
{
|
{
|
||||||
if (!apparmor_enabled)
|
if (!apparmor_enabled)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (apparmor_initialized && !policy_view_capable(NULL))
|
if (apparmor_initialized && !aa_current_policy_view_capable(NULL))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
return param_get_uint(buffer, kp);
|
return param_get_uint(buffer, kp);
|
||||||
}
|
}
|
||||||
|
@ -1516,7 +1516,7 @@ static int param_get_aacompressionlevel(char *buffer,
|
||||||
{
|
{
|
||||||
if (!apparmor_enabled)
|
if (!apparmor_enabled)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (apparmor_initialized && !policy_view_capable(NULL))
|
if (apparmor_initialized && !aa_current_policy_view_capable(NULL))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
return param_get_int(buffer, kp);
|
return param_get_int(buffer, kp);
|
||||||
}
|
}
|
||||||
|
@ -1525,7 +1525,7 @@ static int param_get_audit(char *buffer, const struct kernel_param *kp)
|
||||||
{
|
{
|
||||||
if (!apparmor_enabled)
|
if (!apparmor_enabled)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (apparmor_initialized && !policy_view_capable(NULL))
|
if (apparmor_initialized && !aa_current_policy_view_capable(NULL))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
return sprintf(buffer, "%s", audit_mode_names[aa_g_audit]);
|
return sprintf(buffer, "%s", audit_mode_names[aa_g_audit]);
|
||||||
}
|
}
|
||||||
|
@ -1538,7 +1538,7 @@ static int param_set_audit(const char *val, const struct kernel_param *kp)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (!val)
|
if (!val)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (apparmor_initialized && !policy_admin_capable(NULL))
|
if (apparmor_initialized && !aa_current_policy_admin_capable(NULL))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
i = match_string(audit_mode_names, AUDIT_MAX_INDEX, val);
|
i = match_string(audit_mode_names, AUDIT_MAX_INDEX, val);
|
||||||
|
@ -1553,7 +1553,7 @@ static int param_get_mode(char *buffer, const struct kernel_param *kp)
|
||||||
{
|
{
|
||||||
if (!apparmor_enabled)
|
if (!apparmor_enabled)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (apparmor_initialized && !policy_view_capable(NULL))
|
if (apparmor_initialized && !aa_current_policy_view_capable(NULL))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
return sprintf(buffer, "%s", aa_profile_mode_names[aa_g_profile_mode]);
|
return sprintf(buffer, "%s", aa_profile_mode_names[aa_g_profile_mode]);
|
||||||
|
@ -1567,7 +1567,7 @@ static int param_set_mode(const char *val, const struct kernel_param *kp)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (!val)
|
if (!val)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (apparmor_initialized && !policy_admin_capable(NULL))
|
if (apparmor_initialized && !aa_current_policy_admin_capable(NULL))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
|
|
||||||
i = match_string(aa_profile_mode_names, APPARMOR_MODE_NAMES_MAX_INDEX,
|
i = match_string(aa_profile_mode_names, APPARMOR_MODE_NAMES_MAX_INDEX,
|
||||||
|
@ -1703,7 +1703,7 @@ static int __init alloc_buffers(void)
|
||||||
static int apparmor_dointvec(struct ctl_table *table, int write,
|
static int apparmor_dointvec(struct ctl_table *table, int write,
|
||||||
void __user *buffer, size_t *lenp, loff_t *ppos)
|
void __user *buffer, size_t *lenp, loff_t *ppos)
|
||||||
{
|
{
|
||||||
if (!policy_admin_capable(NULL))
|
if (!aa_current_policy_admin_capable(NULL))
|
||||||
return -EPERM;
|
return -EPERM;
|
||||||
if (!apparmor_enabled)
|
if (!apparmor_enabled)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
@ -632,17 +632,18 @@ static int audit_policy(struct aa_label *label, const char *op,
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* policy_view_capable - check if viewing policy in at @ns is allowed
|
* aa_policy_view_capable - check if viewing policy in at @ns is allowed
|
||||||
* ns: namespace being viewed by current task (may be NULL)
|
* label: label that is trying to view policy in ns
|
||||||
|
* ns: namespace being viewed by @label (may be NULL if @label's ns)
|
||||||
* Returns: true if viewing policy is allowed
|
* Returns: true if viewing policy is allowed
|
||||||
*
|
*
|
||||||
* If @ns is NULL then the namespace being viewed is assumed to be the
|
* If @ns is NULL then the namespace being viewed is assumed to be the
|
||||||
* tasks current namespace.
|
* tasks current namespace.
|
||||||
*/
|
*/
|
||||||
bool policy_view_capable(struct aa_ns *ns)
|
bool aa_policy_view_capable(struct aa_label *label, struct aa_ns *ns)
|
||||||
{
|
{
|
||||||
struct user_namespace *user_ns = current_user_ns();
|
struct user_namespace *user_ns = current_user_ns();
|
||||||
struct aa_ns *view_ns = aa_get_current_ns();
|
struct aa_ns *view_ns = labels_view(label);
|
||||||
bool root_in_user_ns = uid_eq(current_euid(), make_kuid(user_ns, 0)) ||
|
bool root_in_user_ns = uid_eq(current_euid(), make_kuid(user_ns, 0)) ||
|
||||||
in_egroup_p(make_kgid(user_ns, 0));
|
in_egroup_p(make_kgid(user_ns, 0));
|
||||||
bool response = false;
|
bool response = false;
|
||||||
|
@ -654,12 +655,11 @@ bool policy_view_capable(struct aa_ns *ns)
|
||||||
(unprivileged_userns_apparmor_policy != 0 &&
|
(unprivileged_userns_apparmor_policy != 0 &&
|
||||||
user_ns->level == view_ns->level)))
|
user_ns->level == view_ns->level)))
|
||||||
response = true;
|
response = true;
|
||||||
aa_put_ns(view_ns);
|
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool policy_admin_capable(struct aa_ns *ns)
|
bool aa_policy_admin_capable(struct aa_label *label, struct aa_ns *ns)
|
||||||
{
|
{
|
||||||
struct user_namespace *user_ns = current_user_ns();
|
struct user_namespace *user_ns = current_user_ns();
|
||||||
bool capable = ns_capable(user_ns, CAP_MAC_ADMIN);
|
bool capable = ns_capable(user_ns, CAP_MAC_ADMIN);
|
||||||
|
@ -667,7 +667,32 @@ bool policy_admin_capable(struct aa_ns *ns)
|
||||||
AA_DEBUG("cap_mac_admin? %d\n", capable);
|
AA_DEBUG("cap_mac_admin? %d\n", capable);
|
||||||
AA_DEBUG("policy locked? %d\n", aa_g_lock_policy);
|
AA_DEBUG("policy locked? %d\n", aa_g_lock_policy);
|
||||||
|
|
||||||
return policy_view_capable(ns) && capable && !aa_g_lock_policy;
|
return aa_policy_view_capable(label, ns) && capable &&
|
||||||
|
!aa_g_lock_policy;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool aa_current_policy_view_capable(struct aa_ns *ns)
|
||||||
|
{
|
||||||
|
struct aa_label *label;
|
||||||
|
bool res;
|
||||||
|
|
||||||
|
label = __begin_current_label_crit_section();
|
||||||
|
res = aa_policy_view_capable(label, ns);
|
||||||
|
__end_current_label_crit_section(label);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool aa_current_policy_admin_capable(struct aa_ns *ns)
|
||||||
|
{
|
||||||
|
struct aa_label *label;
|
||||||
|
bool res;
|
||||||
|
|
||||||
|
label = __begin_current_label_crit_section();
|
||||||
|
res = aa_policy_admin_capable(label, ns);
|
||||||
|
__end_current_label_crit_section(label);
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -693,7 +718,7 @@ int aa_may_manage_policy(struct aa_label *label, struct aa_ns *ns, u32 mask)
|
||||||
return audit_policy(label, op, NULL, NULL, "policy_locked",
|
return audit_policy(label, op, NULL, NULL, "policy_locked",
|
||||||
-EACCES);
|
-EACCES);
|
||||||
|
|
||||||
if (!policy_admin_capable(ns))
|
if (!aa_policy_admin_capable(label, ns))
|
||||||
return audit_policy(label, op, NULL, NULL, "not policy admin",
|
return audit_policy(label, op, NULL, NULL, "not policy admin",
|
||||||
-EACCES);
|
-EACCES);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue