~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/security/apparmor/capability.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  * AppArmor security module
  4  *
  5  * This file contains AppArmor capability mediation functions
  6  *
  7  * Copyright (C) 1998-2008 Novell/SUSE
  8  * Copyright 2009-2010 Canonical Ltd.
  9  */
 10 
 11 #include <linux/capability.h>
 12 #include <linux/errno.h>
 13 #include <linux/gfp.h>
 14 #include <linux/security.h>
 15 
 16 #include "include/apparmor.h"
 17 #include "include/capability.h"
 18 #include "include/cred.h"
 19 #include "include/policy.h"
 20 #include "include/audit.h"
 21 
 22 /*
 23  * Table of capability names: we generate it from capabilities.h.
 24  */
 25 #include "capability_names.h"
 26 
 27 struct aa_sfs_entry aa_sfs_entry_caps[] = {
 28         AA_SFS_FILE_STRING("mask", AA_SFS_CAPS_MASK),
 29         { }
 30 };
 31 
 32 struct audit_cache {
 33         struct aa_profile *profile;
 34         kernel_cap_t caps;
 35 };
 36 
 37 static DEFINE_PER_CPU(struct audit_cache, audit_cache);
 38 
 39 /**
 40  * audit_cb - call back for capability components of audit struct
 41  * @ab: audit buffer   (NOT NULL)
 42  * @va: audit struct to audit data from  (NOT NULL)
 43  */
 44 static void audit_cb(struct audit_buffer *ab, void *va)
 45 {
 46         struct common_audit_data *sa = va;
 47 
 48         audit_log_format(ab, " capname=");
 49         audit_log_untrustedstring(ab, capability_names[sa->u.cap]);
 50 }
 51 
 52 /**
 53  * audit_caps - audit a capability
 54  * @ad: audit data
 55  * @profile: profile being tested for confinement (NOT NULL)
 56  * @cap: capability tested
 57  * @error: error code returned by test
 58  *
 59  * Do auditing of capability and handle, audit/complain/kill modes switching
 60  * and duplicate message elimination.
 61  *
 62  * Returns: 0 or ad->error on success,  error code on failure
 63  */
 64 static int audit_caps(struct apparmor_audit_data *ad, struct aa_profile *profile,
 65                       int cap, int error)
 66 {
 67         struct aa_ruleset *rules = list_first_entry(&profile->rules,
 68                                                     typeof(*rules), list);
 69         struct audit_cache *ent;
 70         int type = AUDIT_APPARMOR_AUTO;
 71 
 72         ad->error = error;
 73 
 74         if (likely(!error)) {
 75                 /* test if auditing is being forced */
 76                 if (likely((AUDIT_MODE(profile) != AUDIT_ALL) &&
 77                            !cap_raised(rules->caps.audit, cap)))
 78                         return 0;
 79                 type = AUDIT_APPARMOR_AUDIT;
 80         } else if (KILL_MODE(profile) ||
 81                    cap_raised(rules->caps.kill, cap)) {
 82                 type = AUDIT_APPARMOR_KILL;
 83         } else if (cap_raised(rules->caps.quiet, cap) &&
 84                    AUDIT_MODE(profile) != AUDIT_NOQUIET &&
 85                    AUDIT_MODE(profile) != AUDIT_ALL) {
 86                 /* quiet auditing */
 87                 return error;
 88         }
 89 
 90         /* Do simple duplicate message elimination */
 91         ent = &get_cpu_var(audit_cache);
 92         if (profile == ent->profile && cap_raised(ent->caps, cap)) {
 93                 put_cpu_var(audit_cache);
 94                 if (COMPLAIN_MODE(profile))
 95                         return complain_error(error);
 96                 return error;
 97         } else {
 98                 aa_put_profile(ent->profile);
 99                 ent->profile = aa_get_profile(profile);
100                 cap_raise(ent->caps, cap);
101         }
102         put_cpu_var(audit_cache);
103 
104         return aa_audit(type, profile, ad, audit_cb);
105 }
106 
107 /**
108  * profile_capable - test if profile allows use of capability @cap
109  * @profile: profile being enforced    (NOT NULL, NOT unconfined)
110  * @cap: capability to test if allowed
111  * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated
112  * @ad: audit data (MAY BE NULL indicating no auditing)
113  *
114  * Returns: 0 if allowed else -EPERM
115  */
116 static int profile_capable(struct aa_profile *profile, int cap,
117                            unsigned int opts, struct apparmor_audit_data *ad)
118 {
119         struct aa_ruleset *rules = list_first_entry(&profile->rules,
120                                                     typeof(*rules), list);
121         int error;
122 
123         if (cap_raised(rules->caps.allow, cap) &&
124             !cap_raised(rules->caps.denied, cap))
125                 error = 0;
126         else
127                 error = -EPERM;
128 
129         if (opts & CAP_OPT_NOAUDIT) {
130                 if (!COMPLAIN_MODE(profile))
131                         return error;
132                 /* audit the cap request in complain mode but note that it
133                  * should be optional.
134                  */
135                 ad->info = "optional: no audit";
136         }
137 
138         return audit_caps(ad, profile, cap, error);
139 }
140 
141 /**
142  * aa_capable - test permission to use capability
143  * @subj_cred: cred we are testing capability against
144  * @label: label being tested for capability (NOT NULL)
145  * @cap: capability to be tested
146  * @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated
147  *
148  * Look up capability in profile capability set.
149  *
150  * Returns: 0 on success, or else an error code.
151  */
152 int aa_capable(const struct cred *subj_cred, struct aa_label *label,
153                int cap, unsigned int opts)
154 {
155         struct aa_profile *profile;
156         int error = 0;
157         DEFINE_AUDIT_DATA(ad, LSM_AUDIT_DATA_CAP, AA_CLASS_CAP, OP_CAPABLE);
158 
159         ad.subj_cred = subj_cred;
160         ad.common.u.cap = cap;
161         error = fn_for_each_confined(label, profile,
162                         profile_capable(profile, cap, opts, &ad));
163 
164         return error;
165 }
166 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php