Commit 8014370f authored by John Johansen's avatar John Johansen

apparmor: move path_link mediation to using labels

Signed-off-by: default avatarJohn Johansen <john.johansen@canonical.com>
parent aebd873e
...@@ -370,66 +370,40 @@ static inline bool xindex_is_subset(u32 link, u32 target) ...@@ -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, ...@@ -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, ...@@ -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 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, ...@@ -472,8 +447,46 @@ int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry,
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, ...@@ -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_ ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment