Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * AppArmor security module
  4 *
  5 * This file contains AppArmor mediation of files
  6 *
  7 * Copyright (C) 1998-2008 Novell/SUSE
  8 * Copyright 2009-2017 Canonical Ltd.
  9 */
 10
 11#include <linux/fs.h>
 12#include <linux/mount.h>
 13#include <linux/namei.h>
 14#include <uapi/linux/mount.h>
 15
 16#include "include/apparmor.h"
 17#include "include/audit.h"
 18#include "include/cred.h"
 19#include "include/domain.h"
 20#include "include/file.h"
 21#include "include/match.h"
 22#include "include/mount.h"
 23#include "include/path.h"
 24#include "include/policy.h"
 25
 26
 27static void audit_mnt_flags(struct audit_buffer *ab, unsigned long flags)
 28{
 29	if (flags & MS_RDONLY)
 30		audit_log_format(ab, "ro");
 31	else
 32		audit_log_format(ab, "rw");
 33	if (flags & MS_NOSUID)
 34		audit_log_format(ab, ", nosuid");
 35	if (flags & MS_NODEV)
 36		audit_log_format(ab, ", nodev");
 37	if (flags & MS_NOEXEC)
 38		audit_log_format(ab, ", noexec");
 39	if (flags & MS_SYNCHRONOUS)
 40		audit_log_format(ab, ", sync");
 41	if (flags & MS_REMOUNT)
 42		audit_log_format(ab, ", remount");
 43	if (flags & MS_MANDLOCK)
 44		audit_log_format(ab, ", mand");
 45	if (flags & MS_DIRSYNC)
 46		audit_log_format(ab, ", dirsync");
 47	if (flags & MS_NOATIME)
 48		audit_log_format(ab, ", noatime");
 49	if (flags & MS_NODIRATIME)
 50		audit_log_format(ab, ", nodiratime");
 51	if (flags & MS_BIND)
 52		audit_log_format(ab, flags & MS_REC ? ", rbind" : ", bind");
 53	if (flags & MS_MOVE)
 54		audit_log_format(ab, ", move");
 55	if (flags & MS_SILENT)
 56		audit_log_format(ab, ", silent");
 57	if (flags & MS_POSIXACL)
 58		audit_log_format(ab, ", acl");
 59	if (flags & MS_UNBINDABLE)
 60		audit_log_format(ab, flags & MS_REC ? ", runbindable" :
 61				 ", unbindable");
 62	if (flags & MS_PRIVATE)
 63		audit_log_format(ab, flags & MS_REC ? ", rprivate" :
 64				 ", private");
 65	if (flags & MS_SLAVE)
 66		audit_log_format(ab, flags & MS_REC ? ", rslave" :
 67				 ", slave");
 68	if (flags & MS_SHARED)
 69		audit_log_format(ab, flags & MS_REC ? ", rshared" :
 70				 ", shared");
 71	if (flags & MS_RELATIME)
 72		audit_log_format(ab, ", relatime");
 73	if (flags & MS_I_VERSION)
 74		audit_log_format(ab, ", iversion");
 75	if (flags & MS_STRICTATIME)
 76		audit_log_format(ab, ", strictatime");
 77	if (flags & MS_NOUSER)
 78		audit_log_format(ab, ", nouser");
 79}
 80
 81/**
 82 * audit_cb - call back for mount specific audit fields
 83 * @ab: audit_buffer  (NOT NULL)
 84 * @va: audit struct to audit values of  (NOT NULL)
 85 */
 86static void audit_cb(struct audit_buffer *ab, void *va)
 87{
 88	struct common_audit_data *sa = va;
 89
 90	if (aad(sa)->mnt.type) {
 91		audit_log_format(ab, " fstype=");
 92		audit_log_untrustedstring(ab, aad(sa)->mnt.type);
 93	}
 94	if (aad(sa)->mnt.src_name) {
 95		audit_log_format(ab, " srcname=");
 96		audit_log_untrustedstring(ab, aad(sa)->mnt.src_name);
 97	}
 98	if (aad(sa)->mnt.trans) {
 99		audit_log_format(ab, " trans=");
100		audit_log_untrustedstring(ab, aad(sa)->mnt.trans);
101	}
102	if (aad(sa)->mnt.flags) {
103		audit_log_format(ab, " flags=\"");
104		audit_mnt_flags(ab, aad(sa)->mnt.flags);
105		audit_log_format(ab, "\"");
106	}
107	if (aad(sa)->mnt.data) {
108		audit_log_format(ab, " options=");
109		audit_log_untrustedstring(ab, aad(sa)->mnt.data);
110	}
111}
112
113/**
114 * audit_mount - handle the auditing of mount operations
115 * @profile: the profile being enforced  (NOT NULL)
116 * @op: operation being mediated (NOT NULL)
117 * @name: name of object being mediated (MAYBE NULL)
118 * @src_name: src_name of object being mediated (MAYBE_NULL)
119 * @type: type of filesystem (MAYBE_NULL)
120 * @trans: name of trans (MAYBE NULL)
121 * @flags: filesystem independent mount flags
122 * @data: filesystem mount flags
123 * @request: permissions requested
124 * @perms: the permissions computed for the request (NOT NULL)
125 * @info: extra information message (MAYBE NULL)
126 * @error: 0 if operation allowed else failure error code
127 *
128 * Returns: %0 or error on failure
129 */
130static int audit_mount(struct aa_profile *profile, const char *op,
131		       const char *name, const char *src_name,
132		       const char *type, const char *trans,
133		       unsigned long flags, const void *data, u32 request,
134		       struct aa_perms *perms, const char *info, int error)
135{
136	int audit_type = AUDIT_APPARMOR_AUTO;
137	DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, op);
138
139	if (likely(!error)) {
140		u32 mask = perms->audit;
141
142		if (unlikely(AUDIT_MODE(profile) == AUDIT_ALL))
143			mask = 0xffff;
144
145		/* mask off perms that are not being force audited */
146		request &= mask;
147
148		if (likely(!request))
149			return 0;
150		audit_type = AUDIT_APPARMOR_AUDIT;
151	} else {
152		/* only report permissions that were denied */
153		request = request & ~perms->allow;
154
155		if (request & perms->kill)
156			audit_type = AUDIT_APPARMOR_KILL;
157
158		/* quiet known rejects, assumes quiet and kill do not overlap */
159		if ((request & perms->quiet) &&
160		    AUDIT_MODE(profile) != AUDIT_NOQUIET &&
161		    AUDIT_MODE(profile) != AUDIT_ALL)
162			request &= ~perms->quiet;
163
164		if (!request)
165			return error;
166	}
167
168	aad(&sa)->name = name;
169	aad(&sa)->mnt.src_name = src_name;
170	aad(&sa)->mnt.type = type;
171	aad(&sa)->mnt.trans = trans;
172	aad(&sa)->mnt.flags = flags;
173	if (data && (perms->audit & AA_AUDIT_DATA))
174		aad(&sa)->mnt.data = data;
175	aad(&sa)->info = info;
176	aad(&sa)->error = error;
177
178	return aa_audit(audit_type, profile, &sa, audit_cb);
179}
180
181/**
182 * match_mnt_flags - Do an ordered match on mount flags
183 * @dfa: dfa to match against
184 * @state: state to start in
185 * @flags: mount flags to match against
186 *
187 * Mount flags are encoded as an ordered match. This is done instead of
188 * checking against a simple bitmask, to allow for logical operations
189 * on the flags.
190 *
191 * Returns: next state after flags match
192 */
193static unsigned int match_mnt_flags(struct aa_dfa *dfa, unsigned int state,
194				    unsigned long flags)
195{
196	unsigned int i;
197
198	for (i = 0; i <= 31 ; ++i) {
199		if ((1 << i) & flags)
200			state = aa_dfa_next(dfa, state, i + 1);
201	}
202
203	return state;
204}
205
206/**
207 * compute_mnt_perms - compute mount permission associated with @state
208 * @dfa: dfa to match against (NOT NULL)
209 * @state: state match finished in
210 *
211 * Returns: mount permissions
212 */
213static struct aa_perms compute_mnt_perms(struct aa_dfa *dfa,
214					   unsigned int state)
215{
216	struct aa_perms perms = {
217		.allow = dfa_user_allow(dfa, state),
218		.audit = dfa_user_audit(dfa, state),
219		.quiet = dfa_user_quiet(dfa, state),
220		.xindex = dfa_user_xindex(dfa, state),
221	};
222
223	return perms;
224}
225
226static const char * const mnt_info_table[] = {
227	"match succeeded",
228	"failed mntpnt match",
229	"failed srcname match",
230	"failed type match",
231	"failed flags match",
232	"failed data match"
233};
234
235/*
236 * Returns 0 on success else element that match failed in, this is the
237 * index into the mnt_info_table above
238 */
239static int do_match_mnt(struct aa_dfa *dfa, unsigned int start,
240			const char *mntpnt, const char *devname,
241			const char *type, unsigned long flags,
242			void *data, bool binary, struct aa_perms *perms)
243{
244	unsigned int state;
245
246	AA_BUG(!dfa);
247	AA_BUG(!perms);
248
249	state = aa_dfa_match(dfa, start, mntpnt);
250	state = aa_dfa_null_transition(dfa, state);
251	if (!state)
252		return 1;
253
254	if (devname)
255		state = aa_dfa_match(dfa, state, devname);
256	state = aa_dfa_null_transition(dfa, state);
257	if (!state)
258		return 2;
259
260	if (type)
261		state = aa_dfa_match(dfa, state, type);
262	state = aa_dfa_null_transition(dfa, state);
263	if (!state)
264		return 3;
265
266	state = match_mnt_flags(dfa, state, flags);
267	if (!state)
268		return 4;
269	*perms = compute_mnt_perms(dfa, state);
270	if (perms->allow & AA_MAY_MOUNT)
271		return 0;
272
273	/* only match data if not binary and the DFA flags data is expected */
274	if (data && !binary && (perms->allow & AA_MNT_CONT_MATCH)) {
275		state = aa_dfa_null_transition(dfa, state);
276		if (!state)
277			return 4;
278
279		state = aa_dfa_match(dfa, state, data);
280		if (!state)
281			return 5;
282		*perms = compute_mnt_perms(dfa, state);
283		if (perms->allow & AA_MAY_MOUNT)
284			return 0;
285	}
286
287	/* failed at end of flags match */
288	return 4;
289}
290
291
292static int path_flags(struct aa_profile *profile, const struct path *path)
293{
294	AA_BUG(!profile);
295	AA_BUG(!path);
296
297	return profile->path_flags |
298		(S_ISDIR(path->dentry->d_inode->i_mode) ? PATH_IS_DIR : 0);
299}
300
301/**
302 * match_mnt_path_str - handle path matching for mount
303 * @profile: the confining profile
304 * @mntpath: for the mntpnt (NOT NULL)
305 * @buffer: buffer to be used to lookup mntpath
306 * @devnme: string for the devname/src_name (MAY BE NULL OR ERRPTR)
307 * @type: string for the dev type (MAYBE NULL)
308 * @flags: mount flags to match
309 * @data: fs mount data (MAYBE NULL)
310 * @binary: whether @data is binary
311 * @devinfo: error str if (IS_ERR(@devname))
312 *
313 * Returns: 0 on success else error
314 */
315static int match_mnt_path_str(struct aa_profile *profile,
316			      const struct path *mntpath, char *buffer,
317			      const char *devname, const char *type,
318			      unsigned long flags, void *data, bool binary,
319			      const char *devinfo)
320{
321	struct aa_perms perms = { };
322	const char *mntpnt = NULL, *info = NULL;
323	int pos, error;
324
325	AA_BUG(!profile);
326	AA_BUG(!mntpath);
327	AA_BUG(!buffer);
328
329	if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
330		return 0;
331
332	error = aa_path_name(mntpath, path_flags(profile, mntpath), buffer,
333			     &mntpnt, &info, profile->disconnected);
334	if (error)
335		goto audit;
336	if (IS_ERR(devname)) {
337		error = PTR_ERR(devname);
338		devname = NULL;
339		info = devinfo;
340		goto audit;
341	}
342
343	error = -EACCES;
344	pos = do_match_mnt(profile->policy.dfa,
345			   profile->policy.start[AA_CLASS_MOUNT],
346			   mntpnt, devname, type, flags, data, binary, &perms);
347	if (pos) {
348		info = mnt_info_table[pos];
349		goto audit;
350	}
351	error = 0;
352
353audit:
354	return audit_mount(profile, OP_MOUNT, mntpnt, devname, type, NULL,
355			   flags, data, AA_MAY_MOUNT, &perms, info, error);
356}
357
358/**
359 * match_mnt - handle path matching for mount
360 * @profile: the confining profile
361 * @mntpath: for the mntpnt (NOT NULL)
362 * @buffer: buffer to be used to lookup mntpath
363 * @devpath: path devname/src_name (MAYBE NULL)
364 * @devbuffer: buffer to be used to lookup devname/src_name
365 * @type: string for the dev type (MAYBE NULL)
366 * @flags: mount flags to match
367 * @data: fs mount data (MAYBE NULL)
368 * @binary: whether @data is binary
369 *
370 * Returns: 0 on success else error
371 */
372static int match_mnt(struct aa_profile *profile, const struct path *path,
373		     char *buffer, struct path *devpath, char *devbuffer,
374		     const char *type, unsigned long flags, void *data,
375		     bool binary)
376{
377	const char *devname = NULL, *info = NULL;
378	int error = -EACCES;
379
380	AA_BUG(!profile);
381	AA_BUG(devpath && !devbuffer);
382
383	if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
384		return 0;
385
386	if (devpath) {
387		error = aa_path_name(devpath, path_flags(profile, devpath),
388				     devbuffer, &devname, &info,
389				     profile->disconnected);
390		if (error)
391			devname = ERR_PTR(error);
392	}
393
394	return match_mnt_path_str(profile, path, buffer, devname, type, flags,
395				  data, binary, info);
396}
397
398int aa_remount(struct aa_label *label, const struct path *path,
399	       unsigned long flags, void *data)
400{
401	struct aa_profile *profile;
402	char *buffer = NULL;
403	bool binary;
404	int error;
405
406	AA_BUG(!label);
407	AA_BUG(!path);
408
409	binary = path->dentry->d_sb->s_type->fs_flags & FS_BINARY_MOUNTDATA;
410
411	get_buffers(buffer);
412	error = fn_for_each_confined(label, profile,
413			match_mnt(profile, path, buffer, NULL, NULL, NULL,
414				  flags, data, binary));
415	put_buffers(buffer);
416
417	return error;
418}
419
420int aa_bind_mount(struct aa_label *label, const struct path *path,
421		  const char *dev_name, unsigned long flags)
422{
423	struct aa_profile *profile;
424	char *buffer = NULL, *old_buffer = NULL;
425	struct path old_path;
426	int error;
427
428	AA_BUG(!label);
429	AA_BUG(!path);
430
431	if (!dev_name || !*dev_name)
432		return -EINVAL;
433
434	flags &= MS_REC | MS_BIND;
435
436	error = kern_path(dev_name, LOOKUP_FOLLOW|LOOKUP_AUTOMOUNT, &old_path);
437	if (error)
438		return error;
439
440	get_buffers(buffer, old_buffer);
441	error = fn_for_each_confined(label, profile,
442			match_mnt(profile, path, buffer, &old_path, old_buffer,
443				  NULL, flags, NULL, false));
444	put_buffers(buffer, old_buffer);
445	path_put(&old_path);
446
447	return error;
448}
449
450int aa_mount_change_type(struct aa_label *label, const struct path *path,
451			 unsigned long flags)
452{
453	struct aa_profile *profile;
454	char *buffer = NULL;
455	int error;
456
457	AA_BUG(!label);
458	AA_BUG(!path);
459
460	/* These are the flags allowed by do_change_type() */
461	flags &= (MS_REC | MS_SILENT | MS_SHARED | MS_PRIVATE | MS_SLAVE |
462		  MS_UNBINDABLE);
463
464	get_buffers(buffer);
465	error = fn_for_each_confined(label, profile,
466			match_mnt(profile, path, buffer, NULL, NULL, NULL,
467				  flags, NULL, false));
468	put_buffers(buffer);
469
470	return error;
471}
472
473int aa_move_mount(struct aa_label *label, const struct path *path,
474		  const char *orig_name)
475{
476	struct aa_profile *profile;
477	char *buffer = NULL, *old_buffer = NULL;
478	struct path old_path;
479	int error;
480
481	AA_BUG(!label);
482	AA_BUG(!path);
483
484	if (!orig_name || !*orig_name)
485		return -EINVAL;
486
487	error = kern_path(orig_name, LOOKUP_FOLLOW, &old_path);
488	if (error)
489		return error;
490
491	get_buffers(buffer, old_buffer);
492	error = fn_for_each_confined(label, profile,
493			match_mnt(profile, path, buffer, &old_path, old_buffer,
494				  NULL, MS_MOVE, NULL, false));
495	put_buffers(buffer, old_buffer);
496	path_put(&old_path);
497
498	return error;
499}
500
501int aa_new_mount(struct aa_label *label, const char *dev_name,
502		 const struct path *path, const char *type, unsigned long flags,
503		 void *data)
504{
505	struct aa_profile *profile;
506	char *buffer = NULL, *dev_buffer = NULL;
507	bool binary = true;
508	int error;
509	int requires_dev = 0;
510	struct path tmp_path, *dev_path = NULL;
511
512	AA_BUG(!label);
513	AA_BUG(!path);
514
515	if (type) {
516		struct file_system_type *fstype;
517
518		fstype = get_fs_type(type);
519		if (!fstype)
520			return -ENODEV;
521		binary = fstype->fs_flags & FS_BINARY_MOUNTDATA;
522		requires_dev = fstype->fs_flags & FS_REQUIRES_DEV;
523		put_filesystem(fstype);
524
525		if (requires_dev) {
526			if (!dev_name || !*dev_name)
527				return -ENOENT;
528
529			error = kern_path(dev_name, LOOKUP_FOLLOW, &tmp_path);
530			if (error)
531				return error;
532			dev_path = &tmp_path;
533		}
534	}
535
536	get_buffers(buffer, dev_buffer);
537	if (dev_path) {
538		error = fn_for_each_confined(label, profile,
539			match_mnt(profile, path, buffer, dev_path, dev_buffer,
540				  type, flags, data, binary));
541	} else {
542		error = fn_for_each_confined(label, profile,
543			match_mnt_path_str(profile, path, buffer, dev_name,
544					   type, flags, data, binary, NULL));
545	}
546	put_buffers(buffer, dev_buffer);
547	if (dev_path)
548		path_put(dev_path);
549
550	return error;
551}
552
553static int profile_umount(struct aa_profile *profile, struct path *path,
554			  char *buffer)
555{
556	struct aa_perms perms = { };
557	const char *name = NULL, *info = NULL;
558	unsigned int state;
559	int error;
560
561	AA_BUG(!profile);
562	AA_BUG(!path);
563
564	if (!PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
565		return 0;
566
567	error = aa_path_name(path, path_flags(profile, path), buffer, &name,
568			     &info, profile->disconnected);
569	if (error)
570		goto audit;
571
572	state = aa_dfa_match(profile->policy.dfa,
573			     profile->policy.start[AA_CLASS_MOUNT],
574			     name);
575	perms = compute_mnt_perms(profile->policy.dfa, state);
576	if (AA_MAY_UMOUNT & ~perms.allow)
577		error = -EACCES;
578
579audit:
580	return audit_mount(profile, OP_UMOUNT, name, NULL, NULL, NULL, 0, NULL,
581			   AA_MAY_UMOUNT, &perms, info, error);
582}
583
584int aa_umount(struct aa_label *label, struct vfsmount *mnt, int flags)
585{
586	struct aa_profile *profile;
587	char *buffer = NULL;
588	int error;
589	struct path path = { .mnt = mnt, .dentry = mnt->mnt_root };
590
591	AA_BUG(!label);
592	AA_BUG(!mnt);
593
594	get_buffers(buffer);
595	error = fn_for_each_confined(label, profile,
596			profile_umount(profile, &path, buffer));
597	put_buffers(buffer);
598
599	return error;
600}
601
602/* helper fn for transition on pivotroot
603 *
604 * Returns: label for transition or ERR_PTR. Does not return NULL
605 */
606static struct aa_label *build_pivotroot(struct aa_profile *profile,
607					const struct path *new_path,
608					char *new_buffer,
609					const struct path *old_path,
610					char *old_buffer)
611{
612	const char *old_name, *new_name = NULL, *info = NULL;
613	const char *trans_name = NULL;
614	struct aa_perms perms = { };
615	unsigned int state;
616	int error;
617
618	AA_BUG(!profile);
619	AA_BUG(!new_path);
620	AA_BUG(!old_path);
621
622	if (profile_unconfined(profile) ||
623	    !PROFILE_MEDIATES(profile, AA_CLASS_MOUNT))
624		return aa_get_newest_label(&profile->label);
625
626	error = aa_path_name(old_path, path_flags(profile, old_path),
627			     old_buffer, &old_name, &info,
628			     profile->disconnected);
629	if (error)
630		goto audit;
631	error = aa_path_name(new_path, path_flags(profile, new_path),
632			     new_buffer, &new_name, &info,
633			     profile->disconnected);
634	if (error)
635		goto audit;
636
637	error = -EACCES;
638	state = aa_dfa_match(profile->policy.dfa,
639			     profile->policy.start[AA_CLASS_MOUNT],
640			     new_name);
641	state = aa_dfa_null_transition(profile->policy.dfa, state);
642	state = aa_dfa_match(profile->policy.dfa, state, old_name);
643	perms = compute_mnt_perms(profile->policy.dfa, state);
644
645	if (AA_MAY_PIVOTROOT & perms.allow)
646		error = 0;
647
648audit:
649	error = audit_mount(profile, OP_PIVOTROOT, new_name, old_name,
650			    NULL, trans_name, 0, NULL, AA_MAY_PIVOTROOT,
651			    &perms, info, error);
652	if (error)
653		return ERR_PTR(error);
654
655	return aa_get_newest_label(&profile->label);
656}
657
658int aa_pivotroot(struct aa_label *label, const struct path *old_path,
659		 const struct path *new_path)
660{
661	struct aa_profile *profile;
662	struct aa_label *target = NULL;
663	char *old_buffer = NULL, *new_buffer = NULL, *info = NULL;
664	int error;
665
666	AA_BUG(!label);
667	AA_BUG(!old_path);
668	AA_BUG(!new_path);
669
670	get_buffers(old_buffer, new_buffer);
671	target = fn_label_build(label, profile, GFP_ATOMIC,
672			build_pivotroot(profile, new_path, new_buffer,
673					old_path, old_buffer));
674	if (!target) {
675		info = "label build failed";
676		error = -ENOMEM;
677		goto fail;
678	} else if (!IS_ERR(target)) {
679		error = aa_replace_current_label(target);
680		if (error) {
681			/* TODO: audit target */
682			aa_put_label(target);
683			goto out;
684		}
685	} else
686		/* already audited error */
687		error = PTR_ERR(target);
688out:
689	put_buffers(old_buffer, new_buffer);
690
691	return error;
692
693fail:
694	/* TODO: add back in auditing of new_name and old_name */
695	error = fn_for_each(label, profile,
696			audit_mount(profile, OP_PIVOTROOT, NULL /*new_name */,
697				    NULL /* old_name */,
698				    NULL, NULL,
699				    0, NULL, AA_MAY_PIVOTROOT, &nullperms, info,
700				    error));
701	goto out;
702}