apparmor: move aa_file_perm() to use labels
Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
		
							parent
							
								
									290f458a4f
								
							
						
					
					
						commit
						190a95189e
					
				| @ -23,6 +23,7 @@ | ||||
| #include "include/match.h" | ||||
| #include "include/path.h" | ||||
| #include "include/policy.h" | ||||
| #include "include/label.h" | ||||
| 
 | ||||
| static u32 map_mask_to_chr_mask(u32 mask) | ||||
| { | ||||
| @ -433,22 +434,55 @@ audit: | ||||
| /**
 | ||||
|  * aa_file_perm - do permission revalidation check & audit for @file | ||||
|  * @op: operation being checked | ||||
|  * @profile: profile being enforced   (NOT NULL) | ||||
|  * @label: label being enforced   (NOT NULL) | ||||
|  * @file: file to revalidate access permissions on  (NOT NULL) | ||||
|  * @request: requested permissions | ||||
|  * | ||||
|  * Returns: %0 if access allowed else error | ||||
|  */ | ||||
| int aa_file_perm(const char *op, struct aa_profile *profile, struct file *file, | ||||
| int aa_file_perm(const char *op, struct aa_label *label, struct file *file, | ||||
| 		 u32 request) | ||||
| { | ||||
| 	struct path_cond cond = { | ||||
| 		.uid = file_inode(file)->i_uid, | ||||
| 		.mode = file_inode(file)->i_mode | ||||
| 	}; | ||||
| 	struct aa_file_ctx *fctx; | ||||
| 	struct aa_label *flabel; | ||||
| 	u32 denied; | ||||
| 	int error = 0; | ||||
| 
 | ||||
| 	return aa_path_perm(op, profile, &file->f_path, PATH_DELEGATE_DELETED, | ||||
| 			    request, &cond); | ||||
| 	AA_BUG(!label); | ||||
| 	AA_BUG(!file); | ||||
| 
 | ||||
| 	fctx = file_ctx(file); | ||||
| 
 | ||||
| 	rcu_read_lock(); | ||||
| 	flabel  = rcu_dereference(fctx->label); | ||||
| 	AA_BUG(!flabel); | ||||
| 
 | ||||
| 	/* revalidate access, if task is unconfined, or the cached cred
 | ||||
| 	 * doesn't match or if the request is for more permissions than | ||||
| 	 * was granted. | ||||
| 	 * | ||||
| 	 * Note: the test for !unconfined(flabel) is to handle file | ||||
| 	 *       delegation from unconfined tasks | ||||
| 	 */ | ||||
| 	denied = request & ~fctx->allow; | ||||
| 	if (unconfined(label) || unconfined(flabel) || | ||||
| 	    (!denied && aa_label_is_subset(flabel, label))) | ||||
| 		goto done; | ||||
| 
 | ||||
| 	/* 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, | ||||
| 				     PATH_DELEGATE_DELETED, request, &cond); | ||||
| 
 | ||||
| done: | ||||
| 	rcu_read_unlock(); | ||||
| 
 | ||||
| 	return error; | ||||
| } | ||||
| 
 | ||||
| static void revalidate_tty(struct aa_label *label) | ||||
| @ -469,8 +503,7 @@ static void revalidate_tty(struct aa_label *label) | ||||
| 					     struct tty_file_private, list); | ||||
| 		file = file_priv->file; | ||||
| 
 | ||||
| 		if (aa_file_perm(OP_INHERIT, labels_profile(label), file, | ||||
| 				 MAY_READ | MAY_WRITE)) | ||||
| 		if (aa_file_perm(OP_INHERIT, label, file, MAY_READ | MAY_WRITE)) | ||||
| 			drop_tty = 1; | ||||
| 	} | ||||
| 	spin_unlock(&tty->files_lock); | ||||
| @ -484,8 +517,7 @@ static int match_file(const void *p, struct file *file, unsigned int fd) | ||||
| { | ||||
| 	struct aa_label *label = (struct aa_label *)p; | ||||
| 
 | ||||
| 	if (aa_file_perm(OP_INHERIT, labels_profile(label), file, | ||||
| 			 aa_map_file_to_perms(file))) | ||||
| 	if (aa_file_perm(OP_INHERIT, label, file, aa_map_file_to_perms(file))) | ||||
| 		return fd + 1; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| @ -15,6 +15,8 @@ | ||||
| #ifndef __AA_FILE_H | ||||
| #define __AA_FILE_H | ||||
| 
 | ||||
| #include <linux/spinlock.h> | ||||
| 
 | ||||
| #include "domain.h" | ||||
| #include "match.h" | ||||
| #include "perms.h" | ||||
| @ -33,13 +35,13 @@ struct path; | ||||
| #define file_ctx(X) ((struct aa_file_ctx *)(X)->f_security) | ||||
| 
 | ||||
| /* struct aa_file_ctx - the AppArmor context the file was opened in
 | ||||
|  * @lock: lock to update the ctx | ||||
|  * @label: label currently cached on the ctx | ||||
|  * @perms: the permission the file was opened with | ||||
|  * | ||||
|  * The file_ctx could currently be directly stored in file->f_security | ||||
|  * as the profile reference is now stored in the f_cred.  However the | ||||
|  * ctx struct will expand in the future so we keep the struct. | ||||
|  */ | ||||
| struct aa_file_ctx { | ||||
| 	spinlock_t lock; | ||||
| 	struct aa_label __rcu *label; | ||||
| 	u32 allow; | ||||
| }; | ||||
| 
 | ||||
| @ -50,12 +52,16 @@ struct aa_file_ctx { | ||||
|  * | ||||
|  * Returns: file_ctx or NULL on failure | ||||
|  */ | ||||
| static inline struct aa_file_ctx *aa_alloc_file_ctx(gfp_t gfp) | ||||
| static inline struct aa_file_ctx *aa_alloc_file_ctx(struct aa_label *label, | ||||
| 						    gfp_t gfp) | ||||
| { | ||||
| 	struct aa_file_ctx *ctx; | ||||
| 
 | ||||
| 	ctx = kzalloc(sizeof(struct aa_file_ctx), gfp); | ||||
| 
 | ||||
| 	if (ctx) { | ||||
| 		spin_lock_init(&ctx->lock); | ||||
| 		rcu_assign_pointer(ctx->label, aa_get_label(label)); | ||||
| 	} | ||||
| 	return ctx; | ||||
| } | ||||
| 
 | ||||
| @ -65,8 +71,15 @@ static inline struct aa_file_ctx *aa_alloc_file_ctx(gfp_t gfp) | ||||
|  */ | ||||
| static inline void aa_free_file_ctx(struct aa_file_ctx *ctx) | ||||
| { | ||||
| 	if (ctx) | ||||
| 	if (ctx) { | ||||
| 		aa_put_label(rcu_access_pointer(ctx->label)); | ||||
| 		kzfree(ctx); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static inline struct aa_label *aa_get_file_label(struct aa_file_ctx *ctx) | ||||
| { | ||||
| 	return aa_get_label_rcu(&ctx->label); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
| @ -183,7 +196,7 @@ int aa_path_perm(const char *op, struct aa_profile *profile, | ||||
| int aa_path_link(struct aa_profile *profile, struct dentry *old_dentry, | ||||
| 		 const struct path *new_dir, struct dentry *new_dentry); | ||||
| 
 | ||||
| int aa_file_perm(const char *op, struct aa_profile *profile, struct file *file, | ||||
| int aa_file_perm(const char *op, struct aa_label *label, struct file *file, | ||||
| 		 u32 request); | ||||
| 
 | ||||
| void aa_inherit_files(const struct cred *cred, struct files_struct *files); | ||||
|  | ||||
| @ -433,7 +433,7 @@ static int apparmor_file_alloc_security(struct file *file) | ||||
| 
 | ||||
| 	/* freed by apparmor_file_free_security */ | ||||
| 	struct aa_label *label = begin_current_label_crit_section(); | ||||
| 	file->f_security = aa_alloc_file_ctx(GFP_KERNEL); | ||||
| 	file->f_security = aa_alloc_file_ctx(label, GFP_KERNEL); | ||||
| 	if (!file_ctx(file)) | ||||
| 		error = -ENOMEM; | ||||
| 	end_current_label_crit_section(label); | ||||
| @ -448,33 +448,15 @@ static void apparmor_file_free_security(struct file *file) | ||||
| 
 | ||||
| static int common_file_perm(const char *op, struct file *file, u32 mask) | ||||
| { | ||||
| 	struct aa_file_ctx *fctx = file->f_security; | ||||
| 	struct aa_label *label, *flabel; | ||||
| 	struct aa_label *label; | ||||
| 	int error = 0; | ||||
| 
 | ||||
| 	/* don't reaudit files closed during inheritance */ | ||||
| 	if (file->f_path.dentry == aa_null.dentry) | ||||
| 		return -EACCES; | ||||
| 
 | ||||
| 	flabel = aa_cred_raw_label(file->f_cred); | ||||
| 	AA_BUG(!flabel); | ||||
| 
 | ||||
| 	if (!file->f_path.mnt || | ||||
| 	    !path_mediated_fs(file->f_path.dentry)) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	label = __begin_current_label_crit_section(); | ||||
| 
 | ||||
| 	/* revalidate access, if task is unconfined, or the cached cred
 | ||||
| 	 * doesn't match or if the request is for more permissions than | ||||
| 	 * was granted. | ||||
| 	 * | ||||
| 	 * Note: the test for !unconfined(fprofile) is to handle file | ||||
| 	 *       delegation from unconfined tasks | ||||
| 	 */ | ||||
| 	if (!unconfined(label) && !unconfined(flabel) && | ||||
| 	    ((flabel != label) || (mask & ~fctx->allow))) | ||||
| 		error = aa_file_perm(op, labels_profile(label), file, mask); | ||||
| 	error = aa_file_perm(op, label, file, mask); | ||||
| 	__end_current_label_crit_section(label); | ||||
| 
 | ||||
| 	return error; | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user