github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/cmd/snap-confine/selinux-support.c (about)

     1  /*
     2   * Copyright (C) 2018 Canonical Ltd
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License version 3 as
     6   * published by the Free Software Foundation.
     7   *
     8   * This program is distributed in the hope that it will be useful,
     9   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    10   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    11   * GNU General Public License for more details.
    12   *
    13   * You should have received a copy of the GNU General Public License
    14   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    15   *
    16   */
    17  #include "selinux-support.h"
    18  #include "config.h"
    19  
    20  #include <selinux/context.h>
    21  #include <selinux/selinux.h>
    22  
    23  #include "../libsnap-confine-private/cleanup-funcs.h"
    24  #include "../libsnap-confine-private/string-utils.h"
    25  #include "../libsnap-confine-private/utils.h"
    26  
    27  static void sc_freecon(char **ctx) {
    28      if (ctx != NULL && *ctx != NULL) {
    29          freecon(*ctx);
    30          *ctx = NULL;
    31      }
    32  }
    33  
    34  static void sc_context_free(context_t *ctx) {
    35      if (ctx != NULL && *ctx != NULL) {
    36          context_free(*ctx);
    37          *ctx = NULL;
    38      }
    39  }
    40  
    41  /**
    42   * Set security context for the snap.
    43   *
    44   * Sets up SELinux context transition to unconfined_service_t.
    45   **/
    46  int sc_selinux_set_snap_execcon(void) {
    47      if (is_selinux_enabled() < 1) {
    48          debug("SELinux not enabled");
    49          return 0;
    50      }
    51  
    52      char *ctx_str SC_CLEANUP(sc_freecon) = NULL;
    53      if (getcon(&ctx_str) < 0) {
    54          die("cannot obtain current SELinux process context");
    55      }
    56      debug("current SELinux process context: %s", ctx_str);
    57  
    58      context_t ctx SC_CLEANUP(sc_context_free) = context_new(ctx_str);
    59      if (ctx == NULL) {
    60          die("cannot create SELinux context from context string %s", ctx_str);
    61      }
    62  
    63      /* freed by context_free(ctx) */
    64      const char *ctx_type = context_type_get(ctx);
    65  
    66      if (ctx_type == NULL) {
    67          die("cannot obtain type from SELinux context string %s", ctx_str);
    68      }
    69  
    70      if (sc_streq(ctx_type, "snappy_confine_t")) {
    71          /* We are running under a targeted policy which ended up transitioning
    72           * to snappy_confine_t domain, at this point we are right before
    73           * executing snap-exec. However we do not have a full SELinux support
    74           * for services running in snaps, only the snapd bits and helpers are
    75           * covered by the policy.
    76           *
    77           * At this point transition to the unconfined_service_t domain (allowed
    78           * by snap_confine_t policy) upon the next exec() call.
    79           */
    80          if (context_type_set(ctx, "unconfined_service_t") != 0) {
    81              die("cannot update SELinux context %s type to unconfined_service_t", ctx_str);
    82          }
    83  
    84          /* freed by context_free(ctx) */
    85          char *new_ctx_str = context_str(ctx);
    86          if (new_ctx_str == NULL) {
    87              die("cannot obtain updated SELinux context string");
    88          }
    89          if (setexeccon(new_ctx_str) < 0) {
    90              die("cannot set SELinux exec context to %s", new_ctx_str);
    91          }
    92          debug("SELinux context after next exec: %s", new_ctx_str);
    93      }
    94  
    95      return 0;
    96  }