apparmor: move path_link mediation to using labels
Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
parent
aebd873e8d
commit
8014370f12
@ -370,66 +370,40 @@ static inline bool xindex_is_subset(u32 link, u32 target)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static int profile_path_link(struct aa_profile *profile,
|
||||||
* aa_path_link - Handle hard link permission check
|
const struct path *link, char *buffer,
|
||||||
* @profile: the profile being enforced (NOT NULL)
|
const struct path *target, char *buffer2,
|
||||||
* @old_dentry: the target dentry (NOT NULL)
|
struct path_cond *cond)
|
||||||
* @new_dir: directory the new link will be created in (NOT NULL)
|
|
||||||
* @new_dentry: the link being created (NOT NULL)
|
|
||||||
*
|
|
||||||
* Handle the permission test for a link & target pair. Permission
|
|
||||||
* is encoded as a pair where the link permission is determined
|
|
||||||
* first, and if allowed, the target is tested. The target test
|
|
||||||
* is done from the point of the link match (not start of DFA)
|
|
||||||
* making the target permission dependent on the link permission match.
|
|
||||||
*
|
|
||||||
* The subset test if required forces that permissions granted
|
|
||||||
* on link are a subset of the permission granted to target.
|
|
||||||
*
|
|
||||||
* Returns: %0 if allowed else error
|
|
||||||
*/
|
|
||||||
int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
|
|
||||||
const struct path *new_dir, struct dentry *new_dentry)
|
|
||||||
{
|
{
|
||||||
struct path link = { .mnt = new_dir->mnt, .dentry = new_dentry };
|
const char *lname, *tname = NULL;
|
||||||
struct path target = { .mnt = new_dir->mnt, .dentry = old_dentry };
|
struct aa_perms lperms = {}, perms;
|
||||||
struct path_cond cond = {
|
const char *info = NULL;
|
||||||
d_backing_inode(old_dentry)->i_uid,
|
|
||||||
d_backing_inode(old_dentry)->i_mode
|
|
||||||
};
|
|
||||||
char *buffer = NULL, *buffer2 = NULL;
|
|
||||||
const char *lname, *tname = NULL, *info = NULL;
|
|
||||||
struct aa_perms lperms, perms;
|
|
||||||
u32 request = AA_MAY_LINK;
|
u32 request = AA_MAY_LINK;
|
||||||
unsigned int state;
|
unsigned int state;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
get_buffers(buffer, buffer2);
|
error = path_name(OP_LINK, &profile->label, link, profile->path_flags,
|
||||||
lperms = nullperms;
|
buffer, &lname, cond, AA_MAY_LINK);
|
||||||
|
|
||||||
/* buffer freed below, lname is pointer in buffer */
|
|
||||||
error = aa_path_name(&link, profile->path_flags, buffer, &lname,
|
|
||||||
&info, profile->disconnected);
|
|
||||||
if (error)
|
if (error)
|
||||||
goto audit;
|
goto audit;
|
||||||
|
|
||||||
/* buffer2 freed below, tname is pointer in buffer2 */
|
/* buffer2 freed below, tname is pointer in buffer2 */
|
||||||
error = aa_path_name(&target, profile->path_flags, buffer2, &tname,
|
error = path_name(OP_LINK, &profile->label, target, profile->path_flags,
|
||||||
&info, profile->disconnected);
|
buffer2, &tname, cond, AA_MAY_LINK);
|
||||||
if (error)
|
if (error)
|
||||||
goto audit;
|
goto audit;
|
||||||
|
|
||||||
error = -EACCES;
|
error = -EACCES;
|
||||||
/* aa_str_perms - handles the case of the dfa being NULL */
|
/* 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(profile->file.dfa, profile->file.start, lname,
|
||||||
&cond, &lperms);
|
cond, &lperms);
|
||||||
|
|
||||||
if (!(lperms.allow & AA_MAY_LINK))
|
if (!(lperms.allow & AA_MAY_LINK))
|
||||||
goto audit;
|
goto audit;
|
||||||
|
|
||||||
/* test to see if target can be paired with link */
|
/* test to see if target can be paired with link */
|
||||||
state = aa_dfa_null_transition(profile->file.dfa, state);
|
state = aa_dfa_null_transition(profile->file.dfa, state);
|
||||||
aa_str_perms(profile->file.dfa, state, tname, &cond, &perms);
|
aa_str_perms(profile->file.dfa, state, tname, cond, &perms);
|
||||||
|
|
||||||
/* force audit/quiet masks for link are stored in the second entry
|
/* force audit/quiet masks for link are stored in the second entry
|
||||||
* in the link pair.
|
* in the link pair.
|
||||||
@ -440,6 +414,7 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
|
|||||||
|
|
||||||
if (!(perms.allow & AA_MAY_LINK)) {
|
if (!(perms.allow & AA_MAY_LINK)) {
|
||||||
info = "target restricted";
|
info = "target restricted";
|
||||||
|
lperms = perms;
|
||||||
goto audit;
|
goto audit;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -447,10 +422,10 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
|
|||||||
if (!(perms.allow & AA_LINK_SUBSET))
|
if (!(perms.allow & AA_LINK_SUBSET))
|
||||||
goto done_tests;
|
goto done_tests;
|
||||||
|
|
||||||
/* Do link perm subset test requiring allowed permission on link are a
|
/* Do link perm subset test requiring allowed permission on link are
|
||||||
* subset of the allowed permissions on target.
|
* a subset of the allowed permissions on target.
|
||||||
*/
|
*/
|
||||||
aa_str_perms(profile->file.dfa, profile->file.start, tname, &cond,
|
aa_str_perms(profile->file.dfa, profile->file.start, tname, cond,
|
||||||
&perms);
|
&perms);
|
||||||
|
|
||||||
/* AA_MAY_LINK is not considered in the subset test */
|
/* AA_MAY_LINK is not considered in the subset test */
|
||||||
@ -472,8 +447,46 @@ done_tests:
|
|||||||
error = 0;
|
error = 0;
|
||||||
|
|
||||||
audit:
|
audit:
|
||||||
error = aa_audit_file(profile, &lperms, OP_LINK, request,
|
return aa_audit_file(profile, &lperms, OP_LINK, request, lname, tname,
|
||||||
lname, tname, NULL, cond.uid, info, error);
|
NULL, cond->uid, info, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aa_path_link - Handle hard link permission check
|
||||||
|
* @label: the label being enforced (NOT NULL)
|
||||||
|
* @old_dentry: the target dentry (NOT NULL)
|
||||||
|
* @new_dir: directory the new link will be created in (NOT NULL)
|
||||||
|
* @new_dentry: the link being created (NOT NULL)
|
||||||
|
*
|
||||||
|
* Handle the permission test for a link & target pair. Permission
|
||||||
|
* is encoded as a pair where the link permission is determined
|
||||||
|
* first, and if allowed, the target is tested. The target test
|
||||||
|
* is done from the point of the link match (not start of DFA)
|
||||||
|
* making the target permission dependent on the link permission match.
|
||||||
|
*
|
||||||
|
* The subset test if required forces that permissions granted
|
||||||
|
* on link are a subset of the permission granted to target.
|
||||||
|
*
|
||||||
|
* Returns: %0 if allowed else error
|
||||||
|
*/
|
||||||
|
int aa_path_link(struct aa_label *label, struct dentry *old_dentry,
|
||||||
|
const struct path *new_dir, struct dentry *new_dentry)
|
||||||
|
{
|
||||||
|
struct path link = { new_dir->mnt, new_dentry };
|
||||||
|
struct path target = { new_dir->mnt, old_dentry };
|
||||||
|
struct path_cond cond = {
|
||||||
|
d_backing_inode(old_dentry)->i_uid,
|
||||||
|
d_backing_inode(old_dentry)->i_mode
|
||||||
|
};
|
||||||
|
char *buffer = NULL, *buffer2 = NULL;
|
||||||
|
struct aa_profile *profile;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
/* buffer freed below, lname is pointer in buffer */
|
||||||
|
get_buffers(buffer, buffer2);
|
||||||
|
error = fn_for_each_confined(label, profile,
|
||||||
|
profile_path_link(profile, &link, buffer, &target,
|
||||||
|
buffer2, &cond));
|
||||||
put_buffers(buffer, buffer2);
|
put_buffers(buffer, buffer2);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
|
@ -197,7 +197,7 @@ int aa_path_perm(const char *op, struct aa_label *label,
|
|||||||
const struct path *path, int flags, u32 request,
|
const struct path *path, int flags, u32 request,
|
||||||
struct path_cond *cond);
|
struct path_cond *cond);
|
||||||
|
|
||||||
int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
|
int aa_path_link(struct aa_label *label, struct dentry *old_dentry,
|
||||||
const struct path *new_dir, struct dentry *new_dentry);
|
const struct path *new_dir, struct dentry *new_dentry);
|
||||||
|
|
||||||
int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
|
int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
|
||||||
|
@ -332,8 +332,7 @@ static int apparmor_path_link(struct dentry *old_dentry, const struct path *new_
|
|||||||
|
|
||||||
label = begin_current_label_crit_section();
|
label = begin_current_label_crit_section();
|
||||||
if (!unconfined(label))
|
if (!unconfined(label))
|
||||||
error = aa_path_link(labels_profile(label), old_dentry, new_dir,
|
error = aa_path_link(label, old_dentry, new_dir, new_dentry);
|
||||||
new_dentry);
|
|
||||||
end_current_label_crit_section(label);
|
end_current_label_crit_section(label);
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
|
Loading…
Reference in New Issue
Block a user