Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * AppArmor security module
0004  *
0005  * This file contains AppArmor task related definitions and mediation
0006  *
0007  * Copyright 2017 Canonical Ltd.
0008  *
0009  * TODO
0010  * If a task uses change_hat it currently does not return to the old
0011  * cred or task context but instead creates a new one.  Ideally the task
0012  * should return to the previous cred if it has not been modified.
0013  */
0014 
0015 #include <linux/gfp.h>
0016 #include <linux/ptrace.h>
0017 
0018 #include "include/audit.h"
0019 #include "include/cred.h"
0020 #include "include/policy.h"
0021 #include "include/task.h"
0022 
0023 /**
0024  * aa_get_task_label - Get another task's label
0025  * @task: task to query  (NOT NULL)
0026  *
0027  * Returns: counted reference to @task's label
0028  */
0029 struct aa_label *aa_get_task_label(struct task_struct *task)
0030 {
0031     struct aa_label *p;
0032 
0033     rcu_read_lock();
0034     p = aa_get_newest_label(__aa_task_raw_label(task));
0035     rcu_read_unlock();
0036 
0037     return p;
0038 }
0039 
0040 /**
0041  * aa_replace_current_label - replace the current tasks label
0042  * @label: new label  (NOT NULL)
0043  *
0044  * Returns: 0 or error on failure
0045  */
0046 int aa_replace_current_label(struct aa_label *label)
0047 {
0048     struct aa_label *old = aa_current_raw_label();
0049     struct aa_task_ctx *ctx = task_ctx(current);
0050     struct cred *new;
0051 
0052     AA_BUG(!label);
0053 
0054     if (old == label)
0055         return 0;
0056 
0057     if (current_cred() != current_real_cred())
0058         return -EBUSY;
0059 
0060     new  = prepare_creds();
0061     if (!new)
0062         return -ENOMEM;
0063 
0064     if (ctx->nnp && label_is_stale(ctx->nnp)) {
0065         struct aa_label *tmp = ctx->nnp;
0066 
0067         ctx->nnp = aa_get_newest_label(tmp);
0068         aa_put_label(tmp);
0069     }
0070     if (unconfined(label) || (labels_ns(old) != labels_ns(label)))
0071         /*
0072          * if switching to unconfined or a different label namespace
0073          * clear out context state
0074          */
0075         aa_clear_task_ctx_trans(task_ctx(current));
0076 
0077     /*
0078      * be careful switching cred label, when racing replacement it
0079      * is possible that the cred labels's->proxy->label is the reference
0080      * keeping @label valid, so make sure to get its reference before
0081      * dropping the reference on the cred's label
0082      */
0083     aa_get_label(label);
0084     aa_put_label(cred_label(new));
0085     set_cred_label(new, label);
0086 
0087     commit_creds(new);
0088     return 0;
0089 }
0090 
0091 
0092 /**
0093  * aa_set_current_onexec - set the tasks change_profile to happen onexec
0094  * @label: system label to set at exec  (MAYBE NULL to clear value)
0095  * @stack: whether stacking should be done
0096  * Returns: 0 or error on failure
0097  */
0098 int aa_set_current_onexec(struct aa_label *label, bool stack)
0099 {
0100     struct aa_task_ctx *ctx = task_ctx(current);
0101 
0102     aa_get_label(label);
0103     aa_put_label(ctx->onexec);
0104     ctx->onexec = label;
0105     ctx->token = stack;
0106 
0107     return 0;
0108 }
0109 
0110 /**
0111  * aa_set_current_hat - set the current tasks hat
0112  * @label: label to set as the current hat  (NOT NULL)
0113  * @token: token value that must be specified to change from the hat
0114  *
0115  * Do switch of tasks hat.  If the task is currently in a hat
0116  * validate the token to match.
0117  *
0118  * Returns: 0 or error on failure
0119  */
0120 int aa_set_current_hat(struct aa_label *label, u64 token)
0121 {
0122     struct aa_task_ctx *ctx = task_ctx(current);
0123     struct cred *new;
0124 
0125     new = prepare_creds();
0126     if (!new)
0127         return -ENOMEM;
0128     AA_BUG(!label);
0129 
0130     if (!ctx->previous) {
0131         /* transfer refcount */
0132         ctx->previous = cred_label(new);
0133         ctx->token = token;
0134     } else if (ctx->token == token) {
0135         aa_put_label(cred_label(new));
0136     } else {
0137         /* previous_profile && ctx->token != token */
0138         abort_creds(new);
0139         return -EACCES;
0140     }
0141 
0142     set_cred_label(new, aa_get_newest_label(label));
0143     /* clear exec on switching context */
0144     aa_put_label(ctx->onexec);
0145     ctx->onexec = NULL;
0146 
0147     commit_creds(new);
0148     return 0;
0149 }
0150 
0151 /**
0152  * aa_restore_previous_label - exit from hat context restoring previous label
0153  * @token: the token that must be matched to exit hat context
0154  *
0155  * Attempt to return out of a hat to the previous label.  The token
0156  * must match the stored token value.
0157  *
0158  * Returns: 0 or error of failure
0159  */
0160 int aa_restore_previous_label(u64 token)
0161 {
0162     struct aa_task_ctx *ctx = task_ctx(current);
0163     struct cred *new;
0164 
0165     if (ctx->token != token)
0166         return -EACCES;
0167     /* ignore restores when there is no saved label */
0168     if (!ctx->previous)
0169         return 0;
0170 
0171     new = prepare_creds();
0172     if (!new)
0173         return -ENOMEM;
0174 
0175     aa_put_label(cred_label(new));
0176     set_cred_label(new, aa_get_newest_label(ctx->previous));
0177     AA_BUG(!cred_label(new));
0178     /* clear exec && prev information when restoring to previous context */
0179     aa_clear_task_ctx_trans(ctx);
0180 
0181     commit_creds(new);
0182 
0183     return 0;
0184 }
0185 
0186 /**
0187  * audit_ptrace_mask - convert mask to permission string
0188  * @mask: permission mask to convert
0189  *
0190  * Returns: pointer to static string
0191  */
0192 static const char *audit_ptrace_mask(u32 mask)
0193 {
0194     switch (mask) {
0195     case MAY_READ:
0196         return "read";
0197     case MAY_WRITE:
0198         return "trace";
0199     case AA_MAY_BE_READ:
0200         return "readby";
0201     case AA_MAY_BE_TRACED:
0202         return "tracedby";
0203     }
0204     return "";
0205 }
0206 
0207 /* call back to audit ptrace fields */
0208 static void audit_ptrace_cb(struct audit_buffer *ab, void *va)
0209 {
0210     struct common_audit_data *sa = va;
0211 
0212     if (aad(sa)->request & AA_PTRACE_PERM_MASK) {
0213         audit_log_format(ab, " requested_mask=\"%s\"",
0214                  audit_ptrace_mask(aad(sa)->request));
0215 
0216         if (aad(sa)->denied & AA_PTRACE_PERM_MASK) {
0217             audit_log_format(ab, " denied_mask=\"%s\"",
0218                      audit_ptrace_mask(aad(sa)->denied));
0219         }
0220     }
0221     audit_log_format(ab, " peer=");
0222     aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
0223             FLAGS_NONE, GFP_ATOMIC);
0224 }
0225 
0226 /* assumes check for PROFILE_MEDIATES is already done */
0227 /* TODO: conditionals */
0228 static int profile_ptrace_perm(struct aa_profile *profile,
0229                  struct aa_label *peer, u32 request,
0230                  struct common_audit_data *sa)
0231 {
0232     struct aa_perms perms = { };
0233 
0234     aad(sa)->peer = peer;
0235     aa_profile_match_label(profile, peer, AA_CLASS_PTRACE, request,
0236                    &perms);
0237     aa_apply_modes_to_perms(profile, &perms);
0238     return aa_check_perms(profile, &perms, request, sa, audit_ptrace_cb);
0239 }
0240 
0241 static int profile_tracee_perm(struct aa_profile *tracee,
0242                    struct aa_label *tracer, u32 request,
0243                    struct common_audit_data *sa)
0244 {
0245     if (profile_unconfined(tracee) || unconfined(tracer) ||
0246         !PROFILE_MEDIATES(tracee, AA_CLASS_PTRACE))
0247         return 0;
0248 
0249     return profile_ptrace_perm(tracee, tracer, request, sa);
0250 }
0251 
0252 static int profile_tracer_perm(struct aa_profile *tracer,
0253                    struct aa_label *tracee, u32 request,
0254                    struct common_audit_data *sa)
0255 {
0256     if (profile_unconfined(tracer))
0257         return 0;
0258 
0259     if (PROFILE_MEDIATES(tracer, AA_CLASS_PTRACE))
0260         return profile_ptrace_perm(tracer, tracee, request, sa);
0261 
0262     /* profile uses the old style capability check for ptrace */
0263     if (&tracer->label == tracee)
0264         return 0;
0265 
0266     aad(sa)->label = &tracer->label;
0267     aad(sa)->peer = tracee;
0268     aad(sa)->request = 0;
0269     aad(sa)->error = aa_capable(&tracer->label, CAP_SYS_PTRACE,
0270                     CAP_OPT_NONE);
0271 
0272     return aa_audit(AUDIT_APPARMOR_AUTO, tracer, sa, audit_ptrace_cb);
0273 }
0274 
0275 /**
0276  * aa_may_ptrace - test if tracer task can trace the tracee
0277  * @tracer: label of the task doing the tracing  (NOT NULL)
0278  * @tracee: task label to be traced
0279  * @request: permission request
0280  *
0281  * Returns: %0 else error code if permission denied or error
0282  */
0283 int aa_may_ptrace(struct aa_label *tracer, struct aa_label *tracee,
0284           u32 request)
0285 {
0286     struct aa_profile *profile;
0287     u32 xrequest = request << PTRACE_PERM_SHIFT;
0288     DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_PTRACE);
0289 
0290     return xcheck_labels(tracer, tracee, profile,
0291             profile_tracer_perm(profile, tracee, request, &sa),
0292             profile_tracee_perm(profile, tracer, xrequest, &sa));
0293 }