Linux Audio

Check our new training course

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