root/security/apparmor/resource.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. audit_cb
  2. audit_resource
  3. aa_map_resource
  4. profile_setrlimit
  5. aa_task_setrlimit
  6. __aa_transition_rlimits

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * AppArmor security module
   4  *
   5  * This file contains AppArmor resource mediation and attachment
   6  *
   7  * Copyright (C) 1998-2008 Novell/SUSE
   8  * Copyright 2009-2010 Canonical Ltd.
   9  */
  10 
  11 #include <linux/audit.h>
  12 #include <linux/security.h>
  13 
  14 #include "include/audit.h"
  15 #include "include/cred.h"
  16 #include "include/resource.h"
  17 #include "include/policy.h"
  18 
  19 /*
  20  * Table of rlimit names: we generate it from resource.h.
  21  */
  22 #include "rlim_names.h"
  23 
  24 struct aa_sfs_entry aa_sfs_entry_rlimit[] = {
  25         AA_SFS_FILE_STRING("mask", AA_SFS_RLIMIT_MASK),
  26         { }
  27 };
  28 
  29 /* audit callback for resource specific fields */
  30 static void audit_cb(struct audit_buffer *ab, void *va)
  31 {
  32         struct common_audit_data *sa = va;
  33 
  34         audit_log_format(ab, " rlimit=%s value=%lu",
  35                          rlim_names[aad(sa)->rlim.rlim], aad(sa)->rlim.max);
  36         if (aad(sa)->peer) {
  37                 audit_log_format(ab, " peer=");
  38                 aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
  39                                 FLAGS_NONE, GFP_ATOMIC);
  40         }
  41 }
  42 
  43 /**
  44  * audit_resource - audit setting resource limit
  45  * @profile: profile being enforced  (NOT NULL)
  46  * @resource: rlimit being auditing
  47  * @value: value being set
  48  * @error: error value
  49  *
  50  * Returns: 0 or sa->error else other error code on failure
  51  */
  52 static int audit_resource(struct aa_profile *profile, unsigned int resource,
  53                           unsigned long value, struct aa_label *peer,
  54                           const char *info, int error)
  55 {
  56         DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_SETRLIMIT);
  57 
  58         aad(&sa)->rlim.rlim = resource;
  59         aad(&sa)->rlim.max = value;
  60         aad(&sa)->peer = peer;
  61         aad(&sa)->info = info;
  62         aad(&sa)->error = error;
  63 
  64         return aa_audit(AUDIT_APPARMOR_AUTO, profile, &sa, audit_cb);
  65 }
  66 
  67 /**
  68  * aa_map_resouce - map compiled policy resource to internal #
  69  * @resource: flattened policy resource number
  70  *
  71  * Returns: resource # for the current architecture.
  72  *
  73  * rlimit resource can vary based on architecture, map the compiled policy
  74  * resource # to the internal representation for the architecture.
  75  */
  76 int aa_map_resource(int resource)
  77 {
  78         return rlim_map[resource];
  79 }
  80 
  81 static int profile_setrlimit(struct aa_profile *profile, unsigned int resource,
  82                              struct rlimit *new_rlim)
  83 {
  84         int e = 0;
  85 
  86         if (profile->rlimits.mask & (1 << resource) && new_rlim->rlim_max >
  87             profile->rlimits.limits[resource].rlim_max)
  88                 e = -EACCES;
  89         return audit_resource(profile, resource, new_rlim->rlim_max, NULL, NULL,
  90                               e);
  91 }
  92 
  93 /**
  94  * aa_task_setrlimit - test permission to set an rlimit
  95  * @label - label confining the task  (NOT NULL)
  96  * @task - task the resource is being set on
  97  * @resource - the resource being set
  98  * @new_rlim - the new resource limit  (NOT NULL)
  99  *
 100  * Control raising the processes hard limit.
 101  *
 102  * Returns: 0 or error code if setting resource failed
 103  */
 104 int aa_task_setrlimit(struct aa_label *label, struct task_struct *task,
 105                       unsigned int resource, struct rlimit *new_rlim)
 106 {
 107         struct aa_profile *profile;
 108         struct aa_label *peer;
 109         int error = 0;
 110 
 111         rcu_read_lock();
 112         peer = aa_get_newest_cred_label(__task_cred(task));
 113         rcu_read_unlock();
 114 
 115         /* TODO: extend resource control to handle other (non current)
 116          * profiles.  AppArmor rules currently have the implicit assumption
 117          * that the task is setting the resource of a task confined with
 118          * the same profile or that the task setting the resource of another
 119          * task has CAP_SYS_RESOURCE.
 120          */
 121 
 122         if (label != peer &&
 123             aa_capable(label, CAP_SYS_RESOURCE, CAP_OPT_NOAUDIT) != 0)
 124                 error = fn_for_each(label, profile,
 125                                 audit_resource(profile, resource,
 126                                                new_rlim->rlim_max, peer,
 127                                                "cap_sys_resource", -EACCES));
 128         else
 129                 error = fn_for_each_confined(label, profile,
 130                                 profile_setrlimit(profile, resource, new_rlim));
 131         aa_put_label(peer);
 132 
 133         return error;
 134 }
 135 
 136 /**
 137  * __aa_transition_rlimits - apply new profile rlimits
 138  * @old_l: old label on task  (NOT NULL)
 139  * @new_l: new label with rlimits to apply  (NOT NULL)
 140  */
 141 void __aa_transition_rlimits(struct aa_label *old_l, struct aa_label *new_l)
 142 {
 143         unsigned int mask = 0;
 144         struct rlimit *rlim, *initrlim;
 145         struct aa_profile *old, *new;
 146         struct label_it i;
 147 
 148         old = labels_profile(old_l);
 149         new = labels_profile(new_l);
 150 
 151         /* for any rlimits the profile controlled, reset the soft limit
 152          * to the lesser of the tasks hard limit and the init tasks soft limit
 153          */
 154         label_for_each_confined(i, old_l, old) {
 155                 if (old->rlimits.mask) {
 156                         int j;
 157 
 158                         for (j = 0, mask = 1; j < RLIM_NLIMITS; j++,
 159                                      mask <<= 1) {
 160                                 if (old->rlimits.mask & mask) {
 161                                         rlim = current->signal->rlim + j;
 162                                         initrlim = init_task.signal->rlim + j;
 163                                         rlim->rlim_cur = min(rlim->rlim_max,
 164                                                             initrlim->rlim_cur);
 165                                 }
 166                         }
 167                 }
 168         }
 169 
 170         /* set any new hard limits as dictated by the new profile */
 171         label_for_each_confined(i, new_l, new) {
 172                 int j;
 173 
 174                 if (!new->rlimits.mask)
 175                         continue;
 176                 for (j = 0, mask = 1; j < RLIM_NLIMITS; j++, mask <<= 1) {
 177                         if (!(new->rlimits.mask & mask))
 178                                 continue;
 179 
 180                         rlim = current->signal->rlim + j;
 181                         rlim->rlim_max = min(rlim->rlim_max,
 182                                              new->rlimits.limits[j].rlim_max);
 183                         /* soft limit should not exceed hard limit */
 184                         rlim->rlim_cur = min(rlim->rlim_cur, rlim->rlim_max);
 185                 }
 186         }
 187 }

/* [<][>][^][v][top][bottom][index][help] */