Loading security/apparmor/file.c +77 −35 Original line number Diff line number Diff line Loading @@ -152,6 +152,39 @@ int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, return aa_audit(type, profile, &sa, file_audit_cb); } /** * is_deleted - test if a file has been completely unlinked * @dentry: dentry of file to test for deletion (NOT NULL) * * Returns: %1 if deleted else %0 */ static inline bool is_deleted(struct dentry *dentry) { if (d_unlinked(dentry) && d_backing_inode(dentry)->i_nlink == 0) return 1; return 0; } static int path_name(const char *op, struct aa_label *label, const struct path *path, int flags, char *buffer, const char **name, struct path_cond *cond, u32 request) { struct aa_profile *profile; const char *info = NULL; int error; error = aa_path_name(path, flags, buffer, name, &info, labels_profile(label)->disconnected); if (error) { fn_for_each_confined(label, profile, aa_audit_file(profile, &nullperms, op, request, *name, NULL, NULL, cond->uid, info, error)); return error; } return 0; } /** * map_old_perms - map old file perms layout to the new layout * @old: permission set in old mapping Loading Loading @@ -249,23 +282,46 @@ unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start, return state; } /** * is_deleted - test if a file has been completely unlinked * @dentry: dentry of file to test for deletion (NOT NULL) * * Returns: %1 if deleted else %0 */ static inline bool is_deleted(struct dentry *dentry) int __aa_path_perm(const char *op, struct aa_profile *profile, const char *name, u32 request, struct path_cond *cond, int flags, struct aa_perms *perms) { if (d_unlinked(dentry) && d_backing_inode(dentry)->i_nlink == 0) return 1; int e = 0; if (profile_unconfined(profile)) return 0; aa_str_perms(profile->file.dfa, profile->file.start, name, cond, perms); if (request & ~perms->allow) e = -EACCES; return aa_audit_file(profile, perms, op, request, name, NULL, NULL, cond->uid, NULL, e); } static int profile_path_perm(const char *op, struct aa_profile *profile, const struct path *path, char *buffer, u32 request, struct path_cond *cond, int flags, struct aa_perms *perms) { const char *name; int error; if (profile_unconfined(profile)) return 0; error = path_name(op, &profile->label, path, flags | profile->path_flags, buffer, &name, cond, request); if (error) return error; return __aa_path_perm(op, profile, name, request, cond, flags, perms); } /** * aa_path_perm - do permissions check & audit for @path * @op: operation being checked * @profile: profile being enforced (NOT NULL) * @label: profile being enforced (NOT NULL) * @path: path to check permissions of (NOT NULL) * @flags: any additional path flags beyond what the profile specifies * @request: requested permissions Loading @@ -273,36 +329,22 @@ static inline bool is_deleted(struct dentry *dentry) * * Returns: %0 else error if access denied or other error */ int aa_path_perm(const char *op, struct aa_profile *profile, int aa_path_perm(const char *op, struct aa_label *label, const struct path *path, int flags, u32 request, struct path_cond *cond) { char *buffer = NULL; struct aa_perms perms = {}; const char *name, *info = NULL; struct aa_profile *profile; char *buffer = NULL; int error; flags |= profile->path_flags | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0); flags |= PATH_DELEGATE_DELETED | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0); get_buffers(buffer); error = aa_path_name(path, flags, buffer, &name, &info, profile->disconnected); if (error) { if (error == -ENOENT && is_deleted(path->dentry)) { /* Access to open files that are deleted are * give a pass (implicit delegation) */ error = 0; info = NULL; perms.allow = request; } } else { aa_str_perms(profile->file.dfa, profile->file.start, name, cond, &perms); if (request & ~perms.allow) error = -EACCES; } error = aa_audit_file(profile, &perms, op, request, name, NULL, NULL, cond->uid, info, error); error = fn_for_each_confined(label, profile, profile_path_perm(op, profile, path, buffer, request, cond, flags, &perms)); put_buffers(buffer); return error; Loading Loading @@ -482,7 +524,7 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file, /* TODO: label cross check */ if (file->f_path.mnt && path_mediated_fs(file->f_path.dentry)) error = aa_path_perm(op, labels_profile(label), &file->f_path, error = aa_path_perm(op, label, &file->f_path, PATH_DELEGATE_DELETED, request, &cond); done: Loading security/apparmor/include/file.h +4 −1 Original line number Diff line number Diff line Loading @@ -190,7 +190,10 @@ unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start, const char *name, struct path_cond *cond, struct aa_perms *perms); int aa_path_perm(const char *op, struct aa_profile *profile, int __aa_path_perm(const char *op, struct aa_profile *profile, const char *name, u32 request, struct path_cond *cond, int flags, struct aa_perms *perms); int aa_path_perm(const char *op, struct aa_label *label, const struct path *path, int flags, u32 request, struct path_cond *cond); Loading security/apparmor/lsm.c +4 −9 Original line number Diff line number Diff line Loading @@ -196,8 +196,7 @@ static int common_perm(const char *op, const struct path *path, u32 mask, label = __begin_current_label_crit_section(); if (!unconfined(label)) error = aa_path_perm(op, labels_profile(label), path, 0, mask, cond); error = aa_path_perm(op, label, path, 0, mask, cond); __end_current_label_crit_section(label); return error; Loading Loading @@ -359,15 +358,12 @@ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_d d_backing_inode(old_dentry)->i_mode }; error = aa_path_perm(OP_RENAME_SRC, labels_profile(label), &old_path, 0, error = aa_path_perm(OP_RENAME_SRC, label, &old_path, 0, MAY_READ | AA_MAY_GETATTR | MAY_WRITE | AA_MAY_SETATTR | AA_MAY_DELETE, &cond); if (!error) error = aa_path_perm(OP_RENAME_DEST, labels_profile(label), &new_path, error = aa_path_perm(OP_RENAME_DEST, label, &new_path, 0, MAY_WRITE | AA_MAY_SETATTR | AA_MAY_CREATE, &cond); Loading Loading @@ -416,8 +412,7 @@ static int apparmor_file_open(struct file *file, const struct cred *cred) struct inode *inode = file_inode(file); struct path_cond cond = { inode->i_uid, inode->i_mode }; error = aa_path_perm(OP_OPEN, labels_profile(label), &file->f_path, 0, error = aa_path_perm(OP_OPEN, label, &file->f_path, 0, aa_map_file_to_perms(file), &cond); /* todo cache full allowed permissions set and state */ fctx->allow = aa_map_file_to_perms(file); Loading Loading
security/apparmor/file.c +77 −35 Original line number Diff line number Diff line Loading @@ -152,6 +152,39 @@ int aa_audit_file(struct aa_profile *profile, struct aa_perms *perms, return aa_audit(type, profile, &sa, file_audit_cb); } /** * is_deleted - test if a file has been completely unlinked * @dentry: dentry of file to test for deletion (NOT NULL) * * Returns: %1 if deleted else %0 */ static inline bool is_deleted(struct dentry *dentry) { if (d_unlinked(dentry) && d_backing_inode(dentry)->i_nlink == 0) return 1; return 0; } static int path_name(const char *op, struct aa_label *label, const struct path *path, int flags, char *buffer, const char **name, struct path_cond *cond, u32 request) { struct aa_profile *profile; const char *info = NULL; int error; error = aa_path_name(path, flags, buffer, name, &info, labels_profile(label)->disconnected); if (error) { fn_for_each_confined(label, profile, aa_audit_file(profile, &nullperms, op, request, *name, NULL, NULL, cond->uid, info, error)); return error; } return 0; } /** * map_old_perms - map old file perms layout to the new layout * @old: permission set in old mapping Loading Loading @@ -249,23 +282,46 @@ unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start, return state; } /** * is_deleted - test if a file has been completely unlinked * @dentry: dentry of file to test for deletion (NOT NULL) * * Returns: %1 if deleted else %0 */ static inline bool is_deleted(struct dentry *dentry) int __aa_path_perm(const char *op, struct aa_profile *profile, const char *name, u32 request, struct path_cond *cond, int flags, struct aa_perms *perms) { if (d_unlinked(dentry) && d_backing_inode(dentry)->i_nlink == 0) return 1; int e = 0; if (profile_unconfined(profile)) return 0; aa_str_perms(profile->file.dfa, profile->file.start, name, cond, perms); if (request & ~perms->allow) e = -EACCES; return aa_audit_file(profile, perms, op, request, name, NULL, NULL, cond->uid, NULL, e); } static int profile_path_perm(const char *op, struct aa_profile *profile, const struct path *path, char *buffer, u32 request, struct path_cond *cond, int flags, struct aa_perms *perms) { const char *name; int error; if (profile_unconfined(profile)) return 0; error = path_name(op, &profile->label, path, flags | profile->path_flags, buffer, &name, cond, request); if (error) return error; return __aa_path_perm(op, profile, name, request, cond, flags, perms); } /** * aa_path_perm - do permissions check & audit for @path * @op: operation being checked * @profile: profile being enforced (NOT NULL) * @label: profile being enforced (NOT NULL) * @path: path to check permissions of (NOT NULL) * @flags: any additional path flags beyond what the profile specifies * @request: requested permissions Loading @@ -273,36 +329,22 @@ static inline bool is_deleted(struct dentry *dentry) * * Returns: %0 else error if access denied or other error */ int aa_path_perm(const char *op, struct aa_profile *profile, int aa_path_perm(const char *op, struct aa_label *label, const struct path *path, int flags, u32 request, struct path_cond *cond) { char *buffer = NULL; struct aa_perms perms = {}; const char *name, *info = NULL; struct aa_profile *profile; char *buffer = NULL; int error; flags |= profile->path_flags | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0); flags |= PATH_DELEGATE_DELETED | (S_ISDIR(cond->mode) ? PATH_IS_DIR : 0); get_buffers(buffer); error = aa_path_name(path, flags, buffer, &name, &info, profile->disconnected); if (error) { if (error == -ENOENT && is_deleted(path->dentry)) { /* Access to open files that are deleted are * give a pass (implicit delegation) */ error = 0; info = NULL; perms.allow = request; } } else { aa_str_perms(profile->file.dfa, profile->file.start, name, cond, &perms); if (request & ~perms.allow) error = -EACCES; } error = aa_audit_file(profile, &perms, op, request, name, NULL, NULL, cond->uid, info, error); error = fn_for_each_confined(label, profile, profile_path_perm(op, profile, path, buffer, request, cond, flags, &perms)); put_buffers(buffer); return error; Loading Loading @@ -482,7 +524,7 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file, /* TODO: label cross check */ if (file->f_path.mnt && path_mediated_fs(file->f_path.dentry)) error = aa_path_perm(op, labels_profile(label), &file->f_path, error = aa_path_perm(op, label, &file->f_path, PATH_DELEGATE_DELETED, request, &cond); done: Loading
security/apparmor/include/file.h +4 −1 Original line number Diff line number Diff line Loading @@ -190,7 +190,10 @@ unsigned int aa_str_perms(struct aa_dfa *dfa, unsigned int start, const char *name, struct path_cond *cond, struct aa_perms *perms); int aa_path_perm(const char *op, struct aa_profile *profile, int __aa_path_perm(const char *op, struct aa_profile *profile, const char *name, u32 request, struct path_cond *cond, int flags, struct aa_perms *perms); int aa_path_perm(const char *op, struct aa_label *label, const struct path *path, int flags, u32 request, struct path_cond *cond); Loading
security/apparmor/lsm.c +4 −9 Original line number Diff line number Diff line Loading @@ -196,8 +196,7 @@ static int common_perm(const char *op, const struct path *path, u32 mask, label = __begin_current_label_crit_section(); if (!unconfined(label)) error = aa_path_perm(op, labels_profile(label), path, 0, mask, cond); error = aa_path_perm(op, label, path, 0, mask, cond); __end_current_label_crit_section(label); return error; Loading Loading @@ -359,15 +358,12 @@ static int apparmor_path_rename(const struct path *old_dir, struct dentry *old_d d_backing_inode(old_dentry)->i_mode }; error = aa_path_perm(OP_RENAME_SRC, labels_profile(label), &old_path, 0, error = aa_path_perm(OP_RENAME_SRC, label, &old_path, 0, MAY_READ | AA_MAY_GETATTR | MAY_WRITE | AA_MAY_SETATTR | AA_MAY_DELETE, &cond); if (!error) error = aa_path_perm(OP_RENAME_DEST, labels_profile(label), &new_path, error = aa_path_perm(OP_RENAME_DEST, label, &new_path, 0, MAY_WRITE | AA_MAY_SETATTR | AA_MAY_CREATE, &cond); Loading Loading @@ -416,8 +412,7 @@ static int apparmor_file_open(struct file *file, const struct cred *cred) struct inode *inode = file_inode(file); struct path_cond cond = { inode->i_uid, inode->i_mode }; error = aa_path_perm(OP_OPEN, labels_profile(label), &file->f_path, 0, error = aa_path_perm(OP_OPEN, label, &file->f_path, 0, aa_map_file_to_perms(file), &cond); /* todo cache full allowed permissions set and state */ fctx->allow = aa_map_file_to_perms(file); Loading