xref: /openbmc/linux/security/apparmor/ipc.c (revision 0ed3b28ab8bf460a3a026f3f1782bf4c53840184)
1*0ed3b28aSJohn Johansen /*
2*0ed3b28aSJohn Johansen  * AppArmor security module
3*0ed3b28aSJohn Johansen  *
4*0ed3b28aSJohn Johansen  * This file contains AppArmor ipc mediation
5*0ed3b28aSJohn Johansen  *
6*0ed3b28aSJohn Johansen  * Copyright (C) 1998-2008 Novell/SUSE
7*0ed3b28aSJohn Johansen  * Copyright 2009-2010 Canonical Ltd.
8*0ed3b28aSJohn Johansen  *
9*0ed3b28aSJohn Johansen  * This program is free software; you can redistribute it and/or
10*0ed3b28aSJohn Johansen  * modify it under the terms of the GNU General Public License as
11*0ed3b28aSJohn Johansen  * published by the Free Software Foundation, version 2 of the
12*0ed3b28aSJohn Johansen  * License.
13*0ed3b28aSJohn Johansen  */
14*0ed3b28aSJohn Johansen 
15*0ed3b28aSJohn Johansen #include <linux/gfp.h>
16*0ed3b28aSJohn Johansen #include <linux/ptrace.h>
17*0ed3b28aSJohn Johansen 
18*0ed3b28aSJohn Johansen #include "include/audit.h"
19*0ed3b28aSJohn Johansen #include "include/capability.h"
20*0ed3b28aSJohn Johansen #include "include/context.h"
21*0ed3b28aSJohn Johansen #include "include/policy.h"
22*0ed3b28aSJohn Johansen 
23*0ed3b28aSJohn Johansen /* call back to audit ptrace fields */
24*0ed3b28aSJohn Johansen static void audit_cb(struct audit_buffer *ab, void *va)
25*0ed3b28aSJohn Johansen {
26*0ed3b28aSJohn Johansen 	struct common_audit_data *sa = va;
27*0ed3b28aSJohn Johansen 	audit_log_format(ab, " target=");
28*0ed3b28aSJohn Johansen 	audit_log_untrustedstring(ab, sa->aad.target);
29*0ed3b28aSJohn Johansen }
30*0ed3b28aSJohn Johansen 
31*0ed3b28aSJohn Johansen /**
32*0ed3b28aSJohn Johansen  * aa_audit_ptrace - do auditing for ptrace
33*0ed3b28aSJohn Johansen  * @profile: profile being enforced  (NOT NULL)
34*0ed3b28aSJohn Johansen  * @target: profile being traced (NOT NULL)
35*0ed3b28aSJohn Johansen  * @error: error condition
36*0ed3b28aSJohn Johansen  *
37*0ed3b28aSJohn Johansen  * Returns: %0 or error code
38*0ed3b28aSJohn Johansen  */
39*0ed3b28aSJohn Johansen static int aa_audit_ptrace(struct aa_profile *profile,
40*0ed3b28aSJohn Johansen 			   struct aa_profile *target, int error)
41*0ed3b28aSJohn Johansen {
42*0ed3b28aSJohn Johansen 	struct common_audit_data sa;
43*0ed3b28aSJohn Johansen 	COMMON_AUDIT_DATA_INIT(&sa, NONE);
44*0ed3b28aSJohn Johansen 	sa.aad.op = OP_PTRACE;
45*0ed3b28aSJohn Johansen 	sa.aad.target = target;
46*0ed3b28aSJohn Johansen 	sa.aad.error = error;
47*0ed3b28aSJohn Johansen 
48*0ed3b28aSJohn Johansen 	return aa_audit(AUDIT_APPARMOR_AUTO, profile, GFP_ATOMIC, &sa,
49*0ed3b28aSJohn Johansen 			audit_cb);
50*0ed3b28aSJohn Johansen }
51*0ed3b28aSJohn Johansen 
52*0ed3b28aSJohn Johansen /**
53*0ed3b28aSJohn Johansen  * aa_may_ptrace - test if tracer task can trace the tracee
54*0ed3b28aSJohn Johansen  * @tracer_task: task who will do the tracing  (NOT NULL)
55*0ed3b28aSJohn Johansen  * @tracer: profile of the task doing the tracing  (NOT NULL)
56*0ed3b28aSJohn Johansen  * @tracee: task to be traced
57*0ed3b28aSJohn Johansen  * @mode: whether PTRACE_MODE_READ || PTRACE_MODE_ATTACH
58*0ed3b28aSJohn Johansen  *
59*0ed3b28aSJohn Johansen  * Returns: %0 else error code if permission denied or error
60*0ed3b28aSJohn Johansen  */
61*0ed3b28aSJohn Johansen int aa_may_ptrace(struct task_struct *tracer_task, struct aa_profile *tracer,
62*0ed3b28aSJohn Johansen 		  struct aa_profile *tracee, unsigned int mode)
63*0ed3b28aSJohn Johansen {
64*0ed3b28aSJohn Johansen 	/* TODO: currently only based on capability, not extended ptrace
65*0ed3b28aSJohn Johansen 	 *       rules,
66*0ed3b28aSJohn Johansen 	 *       Test mode for PTRACE_MODE_READ || PTRACE_MODE_ATTACH
67*0ed3b28aSJohn Johansen 	 */
68*0ed3b28aSJohn Johansen 
69*0ed3b28aSJohn Johansen 	if (unconfined(tracer) || tracer == tracee)
70*0ed3b28aSJohn Johansen 		return 0;
71*0ed3b28aSJohn Johansen 	/* log this capability request */
72*0ed3b28aSJohn Johansen 	return aa_capable(tracer_task, tracer, CAP_SYS_PTRACE, 1);
73*0ed3b28aSJohn Johansen }
74*0ed3b28aSJohn Johansen 
75*0ed3b28aSJohn Johansen /**
76*0ed3b28aSJohn Johansen  * aa_ptrace - do ptrace permission check and auditing
77*0ed3b28aSJohn Johansen  * @tracer: task doing the tracing (NOT NULL)
78*0ed3b28aSJohn Johansen  * @tracee: task being traced (NOT NULL)
79*0ed3b28aSJohn Johansen  * @mode: ptrace mode either PTRACE_MODE_READ || PTRACE_MODE_ATTACH
80*0ed3b28aSJohn Johansen  *
81*0ed3b28aSJohn Johansen  * Returns: %0 else error code if permission denied or error
82*0ed3b28aSJohn Johansen  */
83*0ed3b28aSJohn Johansen int aa_ptrace(struct task_struct *tracer, struct task_struct *tracee,
84*0ed3b28aSJohn Johansen 	      unsigned int mode)
85*0ed3b28aSJohn Johansen {
86*0ed3b28aSJohn Johansen 	/*
87*0ed3b28aSJohn Johansen 	 * tracer can ptrace tracee when
88*0ed3b28aSJohn Johansen 	 * - tracer is unconfined ||
89*0ed3b28aSJohn Johansen 	 *   - tracer is in complain mode
90*0ed3b28aSJohn Johansen 	 *   - tracer has rules allowing it to trace tracee currently this is:
91*0ed3b28aSJohn Johansen 	 *       - confined by the same profile ||
92*0ed3b28aSJohn Johansen 	 *       - tracer profile has CAP_SYS_PTRACE
93*0ed3b28aSJohn Johansen 	 */
94*0ed3b28aSJohn Johansen 
95*0ed3b28aSJohn Johansen 	struct aa_profile *tracer_p;
96*0ed3b28aSJohn Johansen 	/* cred released below */
97*0ed3b28aSJohn Johansen 	const struct cred *cred = get_task_cred(tracer);
98*0ed3b28aSJohn Johansen 	int error = 0;
99*0ed3b28aSJohn Johansen 	tracer_p = aa_cred_profile(cred);
100*0ed3b28aSJohn Johansen 
101*0ed3b28aSJohn Johansen 	if (!unconfined(tracer_p)) {
102*0ed3b28aSJohn Johansen 		/* lcred released below */
103*0ed3b28aSJohn Johansen 		struct cred *lcred = get_task_cred(tracee);
104*0ed3b28aSJohn Johansen 		struct aa_profile *tracee_p = aa_cred_profile(lcred);
105*0ed3b28aSJohn Johansen 
106*0ed3b28aSJohn Johansen 		error = aa_may_ptrace(tracer, tracer_p, tracee_p, mode);
107*0ed3b28aSJohn Johansen 		error = aa_audit_ptrace(tracer_p, tracee_p, error);
108*0ed3b28aSJohn Johansen 
109*0ed3b28aSJohn Johansen 		put_cred(lcred);
110*0ed3b28aSJohn Johansen 	}
111*0ed3b28aSJohn Johansen 	put_cred(cred);
112*0ed3b28aSJohn Johansen 
113*0ed3b28aSJohn Johansen 	return error;
114*0ed3b28aSJohn Johansen }
115