18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * AppArmor security module 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This file contains AppArmor LSM hooks. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Copyright (C) 1998-2008 Novell/SUSE 88c2ecf20Sopenharmony_ci * Copyright 2009-2010 Canonical Ltd. 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/lsm_hooks.h> 128c2ecf20Sopenharmony_ci#include <linux/moduleparam.h> 138c2ecf20Sopenharmony_ci#include <linux/mm.h> 148c2ecf20Sopenharmony_ci#include <linux/mman.h> 158c2ecf20Sopenharmony_ci#include <linux/mount.h> 168c2ecf20Sopenharmony_ci#include <linux/namei.h> 178c2ecf20Sopenharmony_ci#include <linux/ptrace.h> 188c2ecf20Sopenharmony_ci#include <linux/ctype.h> 198c2ecf20Sopenharmony_ci#include <linux/sysctl.h> 208c2ecf20Sopenharmony_ci#include <linux/audit.h> 218c2ecf20Sopenharmony_ci#include <linux/user_namespace.h> 228c2ecf20Sopenharmony_ci#include <linux/netfilter_ipv4.h> 238c2ecf20Sopenharmony_ci#include <linux/netfilter_ipv6.h> 248c2ecf20Sopenharmony_ci#include <linux/zlib.h> 258c2ecf20Sopenharmony_ci#include <net/sock.h> 268c2ecf20Sopenharmony_ci#include <uapi/linux/mount.h> 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#include "include/apparmor.h" 298c2ecf20Sopenharmony_ci#include "include/apparmorfs.h" 308c2ecf20Sopenharmony_ci#include "include/audit.h" 318c2ecf20Sopenharmony_ci#include "include/capability.h" 328c2ecf20Sopenharmony_ci#include "include/cred.h" 338c2ecf20Sopenharmony_ci#include "include/file.h" 348c2ecf20Sopenharmony_ci#include "include/ipc.h" 358c2ecf20Sopenharmony_ci#include "include/net.h" 368c2ecf20Sopenharmony_ci#include "include/path.h" 378c2ecf20Sopenharmony_ci#include "include/label.h" 388c2ecf20Sopenharmony_ci#include "include/policy.h" 398c2ecf20Sopenharmony_ci#include "include/policy_ns.h" 408c2ecf20Sopenharmony_ci#include "include/procattr.h" 418c2ecf20Sopenharmony_ci#include "include/mount.h" 428c2ecf20Sopenharmony_ci#include "include/secid.h" 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci/* Flag indicating whether initialization completed */ 458c2ecf20Sopenharmony_ciint apparmor_initialized; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ciunion aa_buffer { 488c2ecf20Sopenharmony_ci struct list_head list; 498c2ecf20Sopenharmony_ci char buffer[1]; 508c2ecf20Sopenharmony_ci}; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#define RESERVE_COUNT 2 538c2ecf20Sopenharmony_cistatic int reserve_count = RESERVE_COUNT; 548c2ecf20Sopenharmony_cistatic int buffer_count; 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_cistatic LIST_HEAD(aa_global_buffers); 578c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(aa_buffers_lock); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci/* 608c2ecf20Sopenharmony_ci * LSM hook functions 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci/* 648c2ecf20Sopenharmony_ci * put the associated labels 658c2ecf20Sopenharmony_ci */ 668c2ecf20Sopenharmony_cistatic void apparmor_cred_free(struct cred *cred) 678c2ecf20Sopenharmony_ci{ 688c2ecf20Sopenharmony_ci aa_put_label(cred_label(cred)); 698c2ecf20Sopenharmony_ci set_cred_label(cred, NULL); 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci/* 738c2ecf20Sopenharmony_ci * allocate the apparmor part of blank credentials 748c2ecf20Sopenharmony_ci */ 758c2ecf20Sopenharmony_cistatic int apparmor_cred_alloc_blank(struct cred *cred, gfp_t gfp) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci set_cred_label(cred, NULL); 788c2ecf20Sopenharmony_ci return 0; 798c2ecf20Sopenharmony_ci} 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci/* 828c2ecf20Sopenharmony_ci * prepare new cred label for modification by prepare_cred block 838c2ecf20Sopenharmony_ci */ 848c2ecf20Sopenharmony_cistatic int apparmor_cred_prepare(struct cred *new, const struct cred *old, 858c2ecf20Sopenharmony_ci gfp_t gfp) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci set_cred_label(new, aa_get_newest_label(cred_label(old))); 888c2ecf20Sopenharmony_ci return 0; 898c2ecf20Sopenharmony_ci} 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci/* 928c2ecf20Sopenharmony_ci * transfer the apparmor data to a blank set of creds 938c2ecf20Sopenharmony_ci */ 948c2ecf20Sopenharmony_cistatic void apparmor_cred_transfer(struct cred *new, const struct cred *old) 958c2ecf20Sopenharmony_ci{ 968c2ecf20Sopenharmony_ci set_cred_label(new, aa_get_newest_label(cred_label(old))); 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic void apparmor_task_free(struct task_struct *task) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci aa_free_task_ctx(task_ctx(task)); 1038c2ecf20Sopenharmony_ci} 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistatic int apparmor_task_alloc(struct task_struct *task, 1068c2ecf20Sopenharmony_ci unsigned long clone_flags) 1078c2ecf20Sopenharmony_ci{ 1088c2ecf20Sopenharmony_ci struct aa_task_ctx *new = task_ctx(task); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci aa_dup_task_ctx(new, task_ctx(current)); 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci return 0; 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic int apparmor_ptrace_access_check(struct task_struct *child, 1168c2ecf20Sopenharmony_ci unsigned int mode) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci struct aa_label *tracer, *tracee; 1198c2ecf20Sopenharmony_ci int error; 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_ci tracer = __begin_current_label_crit_section(); 1228c2ecf20Sopenharmony_ci tracee = aa_get_task_label(child); 1238c2ecf20Sopenharmony_ci error = aa_may_ptrace(tracer, tracee, 1248c2ecf20Sopenharmony_ci (mode & PTRACE_MODE_READ) ? AA_PTRACE_READ 1258c2ecf20Sopenharmony_ci : AA_PTRACE_TRACE); 1268c2ecf20Sopenharmony_ci aa_put_label(tracee); 1278c2ecf20Sopenharmony_ci __end_current_label_crit_section(tracer); 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci return error; 1308c2ecf20Sopenharmony_ci} 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_cistatic int apparmor_ptrace_traceme(struct task_struct *parent) 1338c2ecf20Sopenharmony_ci{ 1348c2ecf20Sopenharmony_ci struct aa_label *tracer, *tracee; 1358c2ecf20Sopenharmony_ci int error; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci tracee = __begin_current_label_crit_section(); 1388c2ecf20Sopenharmony_ci tracer = aa_get_task_label(parent); 1398c2ecf20Sopenharmony_ci error = aa_may_ptrace(tracer, tracee, AA_PTRACE_TRACE); 1408c2ecf20Sopenharmony_ci aa_put_label(tracer); 1418c2ecf20Sopenharmony_ci __end_current_label_crit_section(tracee); 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci return error; 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci/* Derived from security/commoncap.c:cap_capget */ 1478c2ecf20Sopenharmony_cistatic int apparmor_capget(struct task_struct *target, kernel_cap_t *effective, 1488c2ecf20Sopenharmony_ci kernel_cap_t *inheritable, kernel_cap_t *permitted) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci struct aa_label *label; 1518c2ecf20Sopenharmony_ci const struct cred *cred; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci rcu_read_lock(); 1548c2ecf20Sopenharmony_ci cred = __task_cred(target); 1558c2ecf20Sopenharmony_ci label = aa_get_newest_cred_label(cred); 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci /* 1588c2ecf20Sopenharmony_ci * cap_capget is stacked ahead of this and will 1598c2ecf20Sopenharmony_ci * initialize effective and permitted. 1608c2ecf20Sopenharmony_ci */ 1618c2ecf20Sopenharmony_ci if (!unconfined(label)) { 1628c2ecf20Sopenharmony_ci struct aa_profile *profile; 1638c2ecf20Sopenharmony_ci struct label_it i; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci label_for_each_confined(i, label, profile) { 1668c2ecf20Sopenharmony_ci if (COMPLAIN_MODE(profile)) 1678c2ecf20Sopenharmony_ci continue; 1688c2ecf20Sopenharmony_ci *effective = cap_intersect(*effective, 1698c2ecf20Sopenharmony_ci profile->caps.allow); 1708c2ecf20Sopenharmony_ci *permitted = cap_intersect(*permitted, 1718c2ecf20Sopenharmony_ci profile->caps.allow); 1728c2ecf20Sopenharmony_ci } 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci rcu_read_unlock(); 1758c2ecf20Sopenharmony_ci aa_put_label(label); 1768c2ecf20Sopenharmony_ci 1778c2ecf20Sopenharmony_ci return 0; 1788c2ecf20Sopenharmony_ci} 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_cistatic int apparmor_capable(const struct cred *cred, struct user_namespace *ns, 1818c2ecf20Sopenharmony_ci int cap, unsigned int opts) 1828c2ecf20Sopenharmony_ci{ 1838c2ecf20Sopenharmony_ci struct aa_label *label; 1848c2ecf20Sopenharmony_ci int error = 0; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci label = aa_get_newest_cred_label(cred); 1878c2ecf20Sopenharmony_ci if (!unconfined(label)) 1888c2ecf20Sopenharmony_ci error = aa_capable(label, cap, opts); 1898c2ecf20Sopenharmony_ci aa_put_label(label); 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci return error; 1928c2ecf20Sopenharmony_ci} 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci/** 1958c2ecf20Sopenharmony_ci * common_perm - basic common permission check wrapper fn for paths 1968c2ecf20Sopenharmony_ci * @op: operation being checked 1978c2ecf20Sopenharmony_ci * @path: path to check permission of (NOT NULL) 1988c2ecf20Sopenharmony_ci * @mask: requested permissions mask 1998c2ecf20Sopenharmony_ci * @cond: conditional info for the permission request (NOT NULL) 2008c2ecf20Sopenharmony_ci * 2018c2ecf20Sopenharmony_ci * Returns: %0 else error code if error or permission denied 2028c2ecf20Sopenharmony_ci */ 2038c2ecf20Sopenharmony_cistatic int common_perm(const char *op, const struct path *path, u32 mask, 2048c2ecf20Sopenharmony_ci struct path_cond *cond) 2058c2ecf20Sopenharmony_ci{ 2068c2ecf20Sopenharmony_ci struct aa_label *label; 2078c2ecf20Sopenharmony_ci int error = 0; 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci label = __begin_current_label_crit_section(); 2108c2ecf20Sopenharmony_ci if (!unconfined(label)) 2118c2ecf20Sopenharmony_ci error = aa_path_perm(op, label, path, 0, mask, cond); 2128c2ecf20Sopenharmony_ci __end_current_label_crit_section(label); 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci return error; 2158c2ecf20Sopenharmony_ci} 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci/** 2188c2ecf20Sopenharmony_ci * common_perm_cond - common permission wrapper around inode cond 2198c2ecf20Sopenharmony_ci * @op: operation being checked 2208c2ecf20Sopenharmony_ci * @path: location to check (NOT NULL) 2218c2ecf20Sopenharmony_ci * @mask: requested permissions mask 2228c2ecf20Sopenharmony_ci * 2238c2ecf20Sopenharmony_ci * Returns: %0 else error code if error or permission denied 2248c2ecf20Sopenharmony_ci */ 2258c2ecf20Sopenharmony_cistatic int common_perm_cond(const char *op, const struct path *path, u32 mask) 2268c2ecf20Sopenharmony_ci{ 2278c2ecf20Sopenharmony_ci struct path_cond cond = { d_backing_inode(path->dentry)->i_uid, 2288c2ecf20Sopenharmony_ci d_backing_inode(path->dentry)->i_mode 2298c2ecf20Sopenharmony_ci }; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci if (!path_mediated_fs(path->dentry)) 2328c2ecf20Sopenharmony_ci return 0; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci return common_perm(op, path, mask, &cond); 2358c2ecf20Sopenharmony_ci} 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci/** 2388c2ecf20Sopenharmony_ci * common_perm_dir_dentry - common permission wrapper when path is dir, dentry 2398c2ecf20Sopenharmony_ci * @op: operation being checked 2408c2ecf20Sopenharmony_ci * @dir: directory of the dentry (NOT NULL) 2418c2ecf20Sopenharmony_ci * @dentry: dentry to check (NOT NULL) 2428c2ecf20Sopenharmony_ci * @mask: requested permissions mask 2438c2ecf20Sopenharmony_ci * @cond: conditional info for the permission request (NOT NULL) 2448c2ecf20Sopenharmony_ci * 2458c2ecf20Sopenharmony_ci * Returns: %0 else error code if error or permission denied 2468c2ecf20Sopenharmony_ci */ 2478c2ecf20Sopenharmony_cistatic int common_perm_dir_dentry(const char *op, const struct path *dir, 2488c2ecf20Sopenharmony_ci struct dentry *dentry, u32 mask, 2498c2ecf20Sopenharmony_ci struct path_cond *cond) 2508c2ecf20Sopenharmony_ci{ 2518c2ecf20Sopenharmony_ci struct path path = { .mnt = dir->mnt, .dentry = dentry }; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci return common_perm(op, &path, mask, cond); 2548c2ecf20Sopenharmony_ci} 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci/** 2578c2ecf20Sopenharmony_ci * common_perm_rm - common permission wrapper for operations doing rm 2588c2ecf20Sopenharmony_ci * @op: operation being checked 2598c2ecf20Sopenharmony_ci * @dir: directory that the dentry is in (NOT NULL) 2608c2ecf20Sopenharmony_ci * @dentry: dentry being rm'd (NOT NULL) 2618c2ecf20Sopenharmony_ci * @mask: requested permission mask 2628c2ecf20Sopenharmony_ci * 2638c2ecf20Sopenharmony_ci * Returns: %0 else error code if error or permission denied 2648c2ecf20Sopenharmony_ci */ 2658c2ecf20Sopenharmony_cistatic int common_perm_rm(const char *op, const struct path *dir, 2668c2ecf20Sopenharmony_ci struct dentry *dentry, u32 mask) 2678c2ecf20Sopenharmony_ci{ 2688c2ecf20Sopenharmony_ci struct inode *inode = d_backing_inode(dentry); 2698c2ecf20Sopenharmony_ci struct path_cond cond = { }; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci if (!inode || !path_mediated_fs(dentry)) 2728c2ecf20Sopenharmony_ci return 0; 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci cond.uid = inode->i_uid; 2758c2ecf20Sopenharmony_ci cond.mode = inode->i_mode; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci return common_perm_dir_dentry(op, dir, dentry, mask, &cond); 2788c2ecf20Sopenharmony_ci} 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci/** 2818c2ecf20Sopenharmony_ci * common_perm_create - common permission wrapper for operations doing create 2828c2ecf20Sopenharmony_ci * @op: operation being checked 2838c2ecf20Sopenharmony_ci * @dir: directory that dentry will be created in (NOT NULL) 2848c2ecf20Sopenharmony_ci * @dentry: dentry to create (NOT NULL) 2858c2ecf20Sopenharmony_ci * @mask: request permission mask 2868c2ecf20Sopenharmony_ci * @mode: created file mode 2878c2ecf20Sopenharmony_ci * 2888c2ecf20Sopenharmony_ci * Returns: %0 else error code if error or permission denied 2898c2ecf20Sopenharmony_ci */ 2908c2ecf20Sopenharmony_cistatic int common_perm_create(const char *op, const struct path *dir, 2918c2ecf20Sopenharmony_ci struct dentry *dentry, u32 mask, umode_t mode) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci struct path_cond cond = { current_fsuid(), mode }; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci if (!path_mediated_fs(dir->dentry)) 2968c2ecf20Sopenharmony_ci return 0; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci return common_perm_dir_dentry(op, dir, dentry, mask, &cond); 2998c2ecf20Sopenharmony_ci} 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_cistatic int apparmor_path_unlink(const struct path *dir, struct dentry *dentry) 3028c2ecf20Sopenharmony_ci{ 3038c2ecf20Sopenharmony_ci return common_perm_rm(OP_UNLINK, dir, dentry, AA_MAY_DELETE); 3048c2ecf20Sopenharmony_ci} 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_cistatic int apparmor_path_mkdir(const struct path *dir, struct dentry *dentry, 3078c2ecf20Sopenharmony_ci umode_t mode) 3088c2ecf20Sopenharmony_ci{ 3098c2ecf20Sopenharmony_ci return common_perm_create(OP_MKDIR, dir, dentry, AA_MAY_CREATE, 3108c2ecf20Sopenharmony_ci S_IFDIR); 3118c2ecf20Sopenharmony_ci} 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_cistatic int apparmor_path_rmdir(const struct path *dir, struct dentry *dentry) 3148c2ecf20Sopenharmony_ci{ 3158c2ecf20Sopenharmony_ci return common_perm_rm(OP_RMDIR, dir, dentry, AA_MAY_DELETE); 3168c2ecf20Sopenharmony_ci} 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_cistatic int apparmor_path_mknod(const struct path *dir, struct dentry *dentry, 3198c2ecf20Sopenharmony_ci umode_t mode, unsigned int dev) 3208c2ecf20Sopenharmony_ci{ 3218c2ecf20Sopenharmony_ci return common_perm_create(OP_MKNOD, dir, dentry, AA_MAY_CREATE, mode); 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_cistatic int apparmor_path_truncate(const struct path *path) 3258c2ecf20Sopenharmony_ci{ 3268c2ecf20Sopenharmony_ci return common_perm_cond(OP_TRUNC, path, MAY_WRITE | AA_MAY_SETATTR); 3278c2ecf20Sopenharmony_ci} 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_cistatic int apparmor_path_symlink(const struct path *dir, struct dentry *dentry, 3308c2ecf20Sopenharmony_ci const char *old_name) 3318c2ecf20Sopenharmony_ci{ 3328c2ecf20Sopenharmony_ci return common_perm_create(OP_SYMLINK, dir, dentry, AA_MAY_CREATE, 3338c2ecf20Sopenharmony_ci S_IFLNK); 3348c2ecf20Sopenharmony_ci} 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_cistatic int apparmor_path_link(struct dentry *old_dentry, const struct path *new_dir, 3378c2ecf20Sopenharmony_ci struct dentry *new_dentry) 3388c2ecf20Sopenharmony_ci{ 3398c2ecf20Sopenharmony_ci struct aa_label *label; 3408c2ecf20Sopenharmony_ci int error = 0; 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci if (!path_mediated_fs(old_dentry)) 3438c2ecf20Sopenharmony_ci return 0; 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci label = begin_current_label_crit_section(); 3468c2ecf20Sopenharmony_ci if (!unconfined(label)) 3478c2ecf20Sopenharmony_ci error = aa_path_link(label, old_dentry, new_dir, new_dentry); 3488c2ecf20Sopenharmony_ci end_current_label_crit_section(label); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci return error; 3518c2ecf20Sopenharmony_ci} 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_cistatic int apparmor_path_rename(const struct path *old_dir, struct dentry *old_dentry, 3548c2ecf20Sopenharmony_ci const struct path *new_dir, struct dentry *new_dentry) 3558c2ecf20Sopenharmony_ci{ 3568c2ecf20Sopenharmony_ci struct aa_label *label; 3578c2ecf20Sopenharmony_ci int error = 0; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci if (!path_mediated_fs(old_dentry)) 3608c2ecf20Sopenharmony_ci return 0; 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci label = begin_current_label_crit_section(); 3638c2ecf20Sopenharmony_ci if (!unconfined(label)) { 3648c2ecf20Sopenharmony_ci struct path old_path = { .mnt = old_dir->mnt, 3658c2ecf20Sopenharmony_ci .dentry = old_dentry }; 3668c2ecf20Sopenharmony_ci struct path new_path = { .mnt = new_dir->mnt, 3678c2ecf20Sopenharmony_ci .dentry = new_dentry }; 3688c2ecf20Sopenharmony_ci struct path_cond cond = { d_backing_inode(old_dentry)->i_uid, 3698c2ecf20Sopenharmony_ci d_backing_inode(old_dentry)->i_mode 3708c2ecf20Sopenharmony_ci }; 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci error = aa_path_perm(OP_RENAME_SRC, label, &old_path, 0, 3738c2ecf20Sopenharmony_ci MAY_READ | AA_MAY_GETATTR | MAY_WRITE | 3748c2ecf20Sopenharmony_ci AA_MAY_SETATTR | AA_MAY_DELETE, 3758c2ecf20Sopenharmony_ci &cond); 3768c2ecf20Sopenharmony_ci if (!error) 3778c2ecf20Sopenharmony_ci error = aa_path_perm(OP_RENAME_DEST, label, &new_path, 3788c2ecf20Sopenharmony_ci 0, MAY_WRITE | AA_MAY_SETATTR | 3798c2ecf20Sopenharmony_ci AA_MAY_CREATE, &cond); 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci } 3828c2ecf20Sopenharmony_ci end_current_label_crit_section(label); 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_ci return error; 3858c2ecf20Sopenharmony_ci} 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_cistatic int apparmor_path_chmod(const struct path *path, umode_t mode) 3888c2ecf20Sopenharmony_ci{ 3898c2ecf20Sopenharmony_ci return common_perm_cond(OP_CHMOD, path, AA_MAY_CHMOD); 3908c2ecf20Sopenharmony_ci} 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_cistatic int apparmor_path_chown(const struct path *path, kuid_t uid, kgid_t gid) 3938c2ecf20Sopenharmony_ci{ 3948c2ecf20Sopenharmony_ci return common_perm_cond(OP_CHOWN, path, AA_MAY_CHOWN); 3958c2ecf20Sopenharmony_ci} 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_cistatic int apparmor_inode_getattr(const struct path *path) 3988c2ecf20Sopenharmony_ci{ 3998c2ecf20Sopenharmony_ci return common_perm_cond(OP_GETATTR, path, AA_MAY_GETATTR); 4008c2ecf20Sopenharmony_ci} 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_cistatic int apparmor_file_open(struct file *file) 4038c2ecf20Sopenharmony_ci{ 4048c2ecf20Sopenharmony_ci struct aa_file_ctx *fctx = file_ctx(file); 4058c2ecf20Sopenharmony_ci struct aa_label *label; 4068c2ecf20Sopenharmony_ci int error = 0; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci if (!path_mediated_fs(file->f_path.dentry)) 4098c2ecf20Sopenharmony_ci return 0; 4108c2ecf20Sopenharmony_ci 4118c2ecf20Sopenharmony_ci /* If in exec, permission is handled by bprm hooks. 4128c2ecf20Sopenharmony_ci * Cache permissions granted by the previous exec check, with 4138c2ecf20Sopenharmony_ci * implicit read and executable mmap which are required to 4148c2ecf20Sopenharmony_ci * actually execute the image. 4158c2ecf20Sopenharmony_ci */ 4168c2ecf20Sopenharmony_ci if (current->in_execve) { 4178c2ecf20Sopenharmony_ci fctx->allow = MAY_EXEC | MAY_READ | AA_EXEC_MMAP; 4188c2ecf20Sopenharmony_ci return 0; 4198c2ecf20Sopenharmony_ci } 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci label = aa_get_newest_cred_label(file->f_cred); 4228c2ecf20Sopenharmony_ci if (!unconfined(label)) { 4238c2ecf20Sopenharmony_ci struct inode *inode = file_inode(file); 4248c2ecf20Sopenharmony_ci struct path_cond cond = { inode->i_uid, inode->i_mode }; 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci error = aa_path_perm(OP_OPEN, label, &file->f_path, 0, 4278c2ecf20Sopenharmony_ci aa_map_file_to_perms(file), &cond); 4288c2ecf20Sopenharmony_ci /* todo cache full allowed permissions set and state */ 4298c2ecf20Sopenharmony_ci fctx->allow = aa_map_file_to_perms(file); 4308c2ecf20Sopenharmony_ci } 4318c2ecf20Sopenharmony_ci aa_put_label(label); 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci return error; 4348c2ecf20Sopenharmony_ci} 4358c2ecf20Sopenharmony_ci 4368c2ecf20Sopenharmony_cistatic int apparmor_file_alloc_security(struct file *file) 4378c2ecf20Sopenharmony_ci{ 4388c2ecf20Sopenharmony_ci struct aa_file_ctx *ctx = file_ctx(file); 4398c2ecf20Sopenharmony_ci struct aa_label *label = begin_current_label_crit_section(); 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci spin_lock_init(&ctx->lock); 4428c2ecf20Sopenharmony_ci rcu_assign_pointer(ctx->label, aa_get_label(label)); 4438c2ecf20Sopenharmony_ci end_current_label_crit_section(label); 4448c2ecf20Sopenharmony_ci return 0; 4458c2ecf20Sopenharmony_ci} 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_cistatic void apparmor_file_free_security(struct file *file) 4488c2ecf20Sopenharmony_ci{ 4498c2ecf20Sopenharmony_ci struct aa_file_ctx *ctx = file_ctx(file); 4508c2ecf20Sopenharmony_ci 4518c2ecf20Sopenharmony_ci if (ctx) 4528c2ecf20Sopenharmony_ci aa_put_label(rcu_access_pointer(ctx->label)); 4538c2ecf20Sopenharmony_ci} 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_cistatic int common_file_perm(const char *op, struct file *file, u32 mask, 4568c2ecf20Sopenharmony_ci bool in_atomic) 4578c2ecf20Sopenharmony_ci{ 4588c2ecf20Sopenharmony_ci struct aa_label *label; 4598c2ecf20Sopenharmony_ci int error = 0; 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci /* don't reaudit files closed during inheritance */ 4628c2ecf20Sopenharmony_ci if (file->f_path.dentry == aa_null.dentry) 4638c2ecf20Sopenharmony_ci return -EACCES; 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci label = __begin_current_label_crit_section(); 4668c2ecf20Sopenharmony_ci error = aa_file_perm(op, label, file, mask, in_atomic); 4678c2ecf20Sopenharmony_ci __end_current_label_crit_section(label); 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci return error; 4708c2ecf20Sopenharmony_ci} 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_cistatic int apparmor_file_receive(struct file *file) 4738c2ecf20Sopenharmony_ci{ 4748c2ecf20Sopenharmony_ci return common_file_perm(OP_FRECEIVE, file, aa_map_file_to_perms(file), 4758c2ecf20Sopenharmony_ci false); 4768c2ecf20Sopenharmony_ci} 4778c2ecf20Sopenharmony_ci 4788c2ecf20Sopenharmony_cistatic int apparmor_file_permission(struct file *file, int mask) 4798c2ecf20Sopenharmony_ci{ 4808c2ecf20Sopenharmony_ci return common_file_perm(OP_FPERM, file, mask, false); 4818c2ecf20Sopenharmony_ci} 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_cistatic int apparmor_file_lock(struct file *file, unsigned int cmd) 4848c2ecf20Sopenharmony_ci{ 4858c2ecf20Sopenharmony_ci u32 mask = AA_MAY_LOCK; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci if (cmd == F_WRLCK) 4888c2ecf20Sopenharmony_ci mask |= MAY_WRITE; 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_ci return common_file_perm(OP_FLOCK, file, mask, false); 4918c2ecf20Sopenharmony_ci} 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_cistatic int common_mmap(const char *op, struct file *file, unsigned long prot, 4948c2ecf20Sopenharmony_ci unsigned long flags, bool in_atomic) 4958c2ecf20Sopenharmony_ci{ 4968c2ecf20Sopenharmony_ci int mask = 0; 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci if (!file || !file_ctx(file)) 4998c2ecf20Sopenharmony_ci return 0; 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci if (prot & PROT_READ) 5028c2ecf20Sopenharmony_ci mask |= MAY_READ; 5038c2ecf20Sopenharmony_ci /* 5048c2ecf20Sopenharmony_ci * Private mappings don't require write perms since they don't 5058c2ecf20Sopenharmony_ci * write back to the files 5068c2ecf20Sopenharmony_ci */ 5078c2ecf20Sopenharmony_ci if ((prot & PROT_WRITE) && !(flags & MAP_PRIVATE)) 5088c2ecf20Sopenharmony_ci mask |= MAY_WRITE; 5098c2ecf20Sopenharmony_ci if (prot & PROT_EXEC) 5108c2ecf20Sopenharmony_ci mask |= AA_EXEC_MMAP; 5118c2ecf20Sopenharmony_ci 5128c2ecf20Sopenharmony_ci return common_file_perm(op, file, mask, in_atomic); 5138c2ecf20Sopenharmony_ci} 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_cistatic int apparmor_mmap_file(struct file *file, unsigned long reqprot, 5168c2ecf20Sopenharmony_ci unsigned long prot, unsigned long flags) 5178c2ecf20Sopenharmony_ci{ 5188c2ecf20Sopenharmony_ci return common_mmap(OP_FMMAP, file, prot, flags, GFP_ATOMIC); 5198c2ecf20Sopenharmony_ci} 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_cistatic int apparmor_file_mprotect(struct vm_area_struct *vma, 5228c2ecf20Sopenharmony_ci unsigned long reqprot, unsigned long prot) 5238c2ecf20Sopenharmony_ci{ 5248c2ecf20Sopenharmony_ci return common_mmap(OP_FMPROT, vma->vm_file, prot, 5258c2ecf20Sopenharmony_ci !(vma->vm_flags & VM_SHARED) ? MAP_PRIVATE : 0, 5268c2ecf20Sopenharmony_ci false); 5278c2ecf20Sopenharmony_ci} 5288c2ecf20Sopenharmony_ci 5298c2ecf20Sopenharmony_cistatic int apparmor_sb_mount(const char *dev_name, const struct path *path, 5308c2ecf20Sopenharmony_ci const char *type, unsigned long flags, void *data) 5318c2ecf20Sopenharmony_ci{ 5328c2ecf20Sopenharmony_ci struct aa_label *label; 5338c2ecf20Sopenharmony_ci int error = 0; 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci /* Discard magic */ 5368c2ecf20Sopenharmony_ci if ((flags & MS_MGC_MSK) == MS_MGC_VAL) 5378c2ecf20Sopenharmony_ci flags &= ~MS_MGC_MSK; 5388c2ecf20Sopenharmony_ci 5398c2ecf20Sopenharmony_ci flags &= ~AA_MS_IGNORE_MASK; 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_ci label = __begin_current_label_crit_section(); 5428c2ecf20Sopenharmony_ci if (!unconfined(label)) { 5438c2ecf20Sopenharmony_ci if (flags & MS_REMOUNT) 5448c2ecf20Sopenharmony_ci error = aa_remount(label, path, flags, data); 5458c2ecf20Sopenharmony_ci else if (flags & MS_BIND) 5468c2ecf20Sopenharmony_ci error = aa_bind_mount(label, path, dev_name, flags); 5478c2ecf20Sopenharmony_ci else if (flags & (MS_SHARED | MS_PRIVATE | MS_SLAVE | 5488c2ecf20Sopenharmony_ci MS_UNBINDABLE)) 5498c2ecf20Sopenharmony_ci error = aa_mount_change_type(label, path, flags); 5508c2ecf20Sopenharmony_ci else if (flags & MS_MOVE) 5518c2ecf20Sopenharmony_ci error = aa_move_mount(label, path, dev_name); 5528c2ecf20Sopenharmony_ci else 5538c2ecf20Sopenharmony_ci error = aa_new_mount(label, dev_name, path, type, 5548c2ecf20Sopenharmony_ci flags, data); 5558c2ecf20Sopenharmony_ci } 5568c2ecf20Sopenharmony_ci __end_current_label_crit_section(label); 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci return error; 5598c2ecf20Sopenharmony_ci} 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_cistatic int apparmor_sb_umount(struct vfsmount *mnt, int flags) 5628c2ecf20Sopenharmony_ci{ 5638c2ecf20Sopenharmony_ci struct aa_label *label; 5648c2ecf20Sopenharmony_ci int error = 0; 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci label = __begin_current_label_crit_section(); 5678c2ecf20Sopenharmony_ci if (!unconfined(label)) 5688c2ecf20Sopenharmony_ci error = aa_umount(label, mnt, flags); 5698c2ecf20Sopenharmony_ci __end_current_label_crit_section(label); 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci return error; 5728c2ecf20Sopenharmony_ci} 5738c2ecf20Sopenharmony_ci 5748c2ecf20Sopenharmony_cistatic int apparmor_sb_pivotroot(const struct path *old_path, 5758c2ecf20Sopenharmony_ci const struct path *new_path) 5768c2ecf20Sopenharmony_ci{ 5778c2ecf20Sopenharmony_ci struct aa_label *label; 5788c2ecf20Sopenharmony_ci int error = 0; 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci label = aa_get_current_label(); 5818c2ecf20Sopenharmony_ci if (!unconfined(label)) 5828c2ecf20Sopenharmony_ci error = aa_pivotroot(label, old_path, new_path); 5838c2ecf20Sopenharmony_ci aa_put_label(label); 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci return error; 5868c2ecf20Sopenharmony_ci} 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_cistatic int apparmor_getprocattr(struct task_struct *task, char *name, 5898c2ecf20Sopenharmony_ci char **value) 5908c2ecf20Sopenharmony_ci{ 5918c2ecf20Sopenharmony_ci int error = -ENOENT; 5928c2ecf20Sopenharmony_ci /* released below */ 5938c2ecf20Sopenharmony_ci const struct cred *cred = get_task_cred(task); 5948c2ecf20Sopenharmony_ci struct aa_task_ctx *ctx = task_ctx(current); 5958c2ecf20Sopenharmony_ci struct aa_label *label = NULL; 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci if (strcmp(name, "current") == 0) 5988c2ecf20Sopenharmony_ci label = aa_get_newest_label(cred_label(cred)); 5998c2ecf20Sopenharmony_ci else if (strcmp(name, "prev") == 0 && ctx->previous) 6008c2ecf20Sopenharmony_ci label = aa_get_newest_label(ctx->previous); 6018c2ecf20Sopenharmony_ci else if (strcmp(name, "exec") == 0 && ctx->onexec) 6028c2ecf20Sopenharmony_ci label = aa_get_newest_label(ctx->onexec); 6038c2ecf20Sopenharmony_ci else 6048c2ecf20Sopenharmony_ci error = -EINVAL; 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci if (label) 6078c2ecf20Sopenharmony_ci error = aa_getprocattr(label, value); 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci aa_put_label(label); 6108c2ecf20Sopenharmony_ci put_cred(cred); 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci return error; 6138c2ecf20Sopenharmony_ci} 6148c2ecf20Sopenharmony_ci 6158c2ecf20Sopenharmony_cistatic int apparmor_setprocattr(const char *name, void *value, 6168c2ecf20Sopenharmony_ci size_t size) 6178c2ecf20Sopenharmony_ci{ 6188c2ecf20Sopenharmony_ci char *command, *largs = NULL, *args = value; 6198c2ecf20Sopenharmony_ci size_t arg_size; 6208c2ecf20Sopenharmony_ci int error; 6218c2ecf20Sopenharmony_ci DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, OP_SETPROCATTR); 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci if (size == 0) 6248c2ecf20Sopenharmony_ci return -EINVAL; 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci /* AppArmor requires that the buffer must be null terminated atm */ 6278c2ecf20Sopenharmony_ci if (args[size - 1] != '\0') { 6288c2ecf20Sopenharmony_ci /* null terminate */ 6298c2ecf20Sopenharmony_ci largs = args = kmalloc(size + 1, GFP_KERNEL); 6308c2ecf20Sopenharmony_ci if (!args) 6318c2ecf20Sopenharmony_ci return -ENOMEM; 6328c2ecf20Sopenharmony_ci memcpy(args, value, size); 6338c2ecf20Sopenharmony_ci args[size] = '\0'; 6348c2ecf20Sopenharmony_ci } 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci error = -EINVAL; 6378c2ecf20Sopenharmony_ci args = strim(args); 6388c2ecf20Sopenharmony_ci command = strsep(&args, " "); 6398c2ecf20Sopenharmony_ci if (!args) 6408c2ecf20Sopenharmony_ci goto out; 6418c2ecf20Sopenharmony_ci args = skip_spaces(args); 6428c2ecf20Sopenharmony_ci if (!*args) 6438c2ecf20Sopenharmony_ci goto out; 6448c2ecf20Sopenharmony_ci 6458c2ecf20Sopenharmony_ci arg_size = size - (args - (largs ? largs : (char *) value)); 6468c2ecf20Sopenharmony_ci if (strcmp(name, "current") == 0) { 6478c2ecf20Sopenharmony_ci if (strcmp(command, "changehat") == 0) { 6488c2ecf20Sopenharmony_ci error = aa_setprocattr_changehat(args, arg_size, 6498c2ecf20Sopenharmony_ci AA_CHANGE_NOFLAGS); 6508c2ecf20Sopenharmony_ci } else if (strcmp(command, "permhat") == 0) { 6518c2ecf20Sopenharmony_ci error = aa_setprocattr_changehat(args, arg_size, 6528c2ecf20Sopenharmony_ci AA_CHANGE_TEST); 6538c2ecf20Sopenharmony_ci } else if (strcmp(command, "changeprofile") == 0) { 6548c2ecf20Sopenharmony_ci error = aa_change_profile(args, AA_CHANGE_NOFLAGS); 6558c2ecf20Sopenharmony_ci } else if (strcmp(command, "permprofile") == 0) { 6568c2ecf20Sopenharmony_ci error = aa_change_profile(args, AA_CHANGE_TEST); 6578c2ecf20Sopenharmony_ci } else if (strcmp(command, "stack") == 0) { 6588c2ecf20Sopenharmony_ci error = aa_change_profile(args, AA_CHANGE_STACK); 6598c2ecf20Sopenharmony_ci } else 6608c2ecf20Sopenharmony_ci goto fail; 6618c2ecf20Sopenharmony_ci } else if (strcmp(name, "exec") == 0) { 6628c2ecf20Sopenharmony_ci if (strcmp(command, "exec") == 0) 6638c2ecf20Sopenharmony_ci error = aa_change_profile(args, AA_CHANGE_ONEXEC); 6648c2ecf20Sopenharmony_ci else if (strcmp(command, "stack") == 0) 6658c2ecf20Sopenharmony_ci error = aa_change_profile(args, (AA_CHANGE_ONEXEC | 6668c2ecf20Sopenharmony_ci AA_CHANGE_STACK)); 6678c2ecf20Sopenharmony_ci else 6688c2ecf20Sopenharmony_ci goto fail; 6698c2ecf20Sopenharmony_ci } else 6708c2ecf20Sopenharmony_ci /* only support the "current" and "exec" process attributes */ 6718c2ecf20Sopenharmony_ci goto fail; 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci if (!error) 6748c2ecf20Sopenharmony_ci error = size; 6758c2ecf20Sopenharmony_ciout: 6768c2ecf20Sopenharmony_ci kfree(largs); 6778c2ecf20Sopenharmony_ci return error; 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_cifail: 6808c2ecf20Sopenharmony_ci aad(&sa)->label = begin_current_label_crit_section(); 6818c2ecf20Sopenharmony_ci aad(&sa)->info = name; 6828c2ecf20Sopenharmony_ci aad(&sa)->error = error = -EINVAL; 6838c2ecf20Sopenharmony_ci aa_audit_msg(AUDIT_APPARMOR_DENIED, &sa, NULL); 6848c2ecf20Sopenharmony_ci end_current_label_crit_section(aad(&sa)->label); 6858c2ecf20Sopenharmony_ci goto out; 6868c2ecf20Sopenharmony_ci} 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci/** 6898c2ecf20Sopenharmony_ci * apparmor_bprm_committing_creds - do task cleanup on committing new creds 6908c2ecf20Sopenharmony_ci * @bprm: binprm for the exec (NOT NULL) 6918c2ecf20Sopenharmony_ci */ 6928c2ecf20Sopenharmony_cistatic void apparmor_bprm_committing_creds(struct linux_binprm *bprm) 6938c2ecf20Sopenharmony_ci{ 6948c2ecf20Sopenharmony_ci struct aa_label *label = aa_current_raw_label(); 6958c2ecf20Sopenharmony_ci struct aa_label *new_label = cred_label(bprm->cred); 6968c2ecf20Sopenharmony_ci 6978c2ecf20Sopenharmony_ci /* bail out if unconfined or not changing profile */ 6988c2ecf20Sopenharmony_ci if ((new_label->proxy == label->proxy) || 6998c2ecf20Sopenharmony_ci (unconfined(new_label))) 7008c2ecf20Sopenharmony_ci return; 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci aa_inherit_files(bprm->cred, current->files); 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ci current->pdeath_signal = 0; 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci /* reset soft limits and set hard limits for the new label */ 7078c2ecf20Sopenharmony_ci __aa_transition_rlimits(label, new_label); 7088c2ecf20Sopenharmony_ci} 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci/** 7118c2ecf20Sopenharmony_ci * apparmor_bprm_committed_cred - do cleanup after new creds committed 7128c2ecf20Sopenharmony_ci * @bprm: binprm for the exec (NOT NULL) 7138c2ecf20Sopenharmony_ci */ 7148c2ecf20Sopenharmony_cistatic void apparmor_bprm_committed_creds(struct linux_binprm *bprm) 7158c2ecf20Sopenharmony_ci{ 7168c2ecf20Sopenharmony_ci /* clear out temporary/transitional state from the context */ 7178c2ecf20Sopenharmony_ci aa_clear_task_ctx_trans(task_ctx(current)); 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci return; 7208c2ecf20Sopenharmony_ci} 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_cistatic void apparmor_task_getsecid(struct task_struct *p, u32 *secid) 7238c2ecf20Sopenharmony_ci{ 7248c2ecf20Sopenharmony_ci struct aa_label *label = aa_get_task_label(p); 7258c2ecf20Sopenharmony_ci *secid = label->secid; 7268c2ecf20Sopenharmony_ci aa_put_label(label); 7278c2ecf20Sopenharmony_ci} 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_cistatic int apparmor_task_setrlimit(struct task_struct *task, 7308c2ecf20Sopenharmony_ci unsigned int resource, struct rlimit *new_rlim) 7318c2ecf20Sopenharmony_ci{ 7328c2ecf20Sopenharmony_ci struct aa_label *label = __begin_current_label_crit_section(); 7338c2ecf20Sopenharmony_ci int error = 0; 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci if (!unconfined(label)) 7368c2ecf20Sopenharmony_ci error = aa_task_setrlimit(label, task, resource, new_rlim); 7378c2ecf20Sopenharmony_ci __end_current_label_crit_section(label); 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci return error; 7408c2ecf20Sopenharmony_ci} 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_cistatic int apparmor_task_kill(struct task_struct *target, struct kernel_siginfo *info, 7438c2ecf20Sopenharmony_ci int sig, const struct cred *cred) 7448c2ecf20Sopenharmony_ci{ 7458c2ecf20Sopenharmony_ci struct aa_label *cl, *tl; 7468c2ecf20Sopenharmony_ci int error; 7478c2ecf20Sopenharmony_ci 7488c2ecf20Sopenharmony_ci if (cred) { 7498c2ecf20Sopenharmony_ci /* 7508c2ecf20Sopenharmony_ci * Dealing with USB IO specific behavior 7518c2ecf20Sopenharmony_ci */ 7528c2ecf20Sopenharmony_ci cl = aa_get_newest_cred_label(cred); 7538c2ecf20Sopenharmony_ci tl = aa_get_task_label(target); 7548c2ecf20Sopenharmony_ci error = aa_may_signal(cl, tl, sig); 7558c2ecf20Sopenharmony_ci aa_put_label(cl); 7568c2ecf20Sopenharmony_ci aa_put_label(tl); 7578c2ecf20Sopenharmony_ci return error; 7588c2ecf20Sopenharmony_ci } 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci cl = __begin_current_label_crit_section(); 7618c2ecf20Sopenharmony_ci tl = aa_get_task_label(target); 7628c2ecf20Sopenharmony_ci error = aa_may_signal(cl, tl, sig); 7638c2ecf20Sopenharmony_ci aa_put_label(tl); 7648c2ecf20Sopenharmony_ci __end_current_label_crit_section(cl); 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci return error; 7678c2ecf20Sopenharmony_ci} 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci/** 7708c2ecf20Sopenharmony_ci * apparmor_sk_alloc_security - allocate and attach the sk_security field 7718c2ecf20Sopenharmony_ci */ 7728c2ecf20Sopenharmony_cistatic int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags) 7738c2ecf20Sopenharmony_ci{ 7748c2ecf20Sopenharmony_ci struct aa_sk_ctx *ctx; 7758c2ecf20Sopenharmony_ci 7768c2ecf20Sopenharmony_ci ctx = kzalloc(sizeof(*ctx), flags); 7778c2ecf20Sopenharmony_ci if (!ctx) 7788c2ecf20Sopenharmony_ci return -ENOMEM; 7798c2ecf20Sopenharmony_ci 7808c2ecf20Sopenharmony_ci SK_CTX(sk) = ctx; 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci return 0; 7838c2ecf20Sopenharmony_ci} 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci/** 7868c2ecf20Sopenharmony_ci * apparmor_sk_free_security - free the sk_security field 7878c2ecf20Sopenharmony_ci */ 7888c2ecf20Sopenharmony_cistatic void apparmor_sk_free_security(struct sock *sk) 7898c2ecf20Sopenharmony_ci{ 7908c2ecf20Sopenharmony_ci struct aa_sk_ctx *ctx = SK_CTX(sk); 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci SK_CTX(sk) = NULL; 7938c2ecf20Sopenharmony_ci aa_put_label(ctx->label); 7948c2ecf20Sopenharmony_ci aa_put_label(ctx->peer); 7958c2ecf20Sopenharmony_ci kfree(ctx); 7968c2ecf20Sopenharmony_ci} 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci/** 7998c2ecf20Sopenharmony_ci * apparmor_clone_security - clone the sk_security field 8008c2ecf20Sopenharmony_ci */ 8018c2ecf20Sopenharmony_cistatic void apparmor_sk_clone_security(const struct sock *sk, 8028c2ecf20Sopenharmony_ci struct sock *newsk) 8038c2ecf20Sopenharmony_ci{ 8048c2ecf20Sopenharmony_ci struct aa_sk_ctx *ctx = SK_CTX(sk); 8058c2ecf20Sopenharmony_ci struct aa_sk_ctx *new = SK_CTX(newsk); 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci if (new->label) 8088c2ecf20Sopenharmony_ci aa_put_label(new->label); 8098c2ecf20Sopenharmony_ci new->label = aa_get_label(ctx->label); 8108c2ecf20Sopenharmony_ci 8118c2ecf20Sopenharmony_ci if (new->peer) 8128c2ecf20Sopenharmony_ci aa_put_label(new->peer); 8138c2ecf20Sopenharmony_ci new->peer = aa_get_label(ctx->peer); 8148c2ecf20Sopenharmony_ci} 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci/** 8178c2ecf20Sopenharmony_ci * apparmor_socket_create - check perms before creating a new socket 8188c2ecf20Sopenharmony_ci */ 8198c2ecf20Sopenharmony_cistatic int apparmor_socket_create(int family, int type, int protocol, int kern) 8208c2ecf20Sopenharmony_ci{ 8218c2ecf20Sopenharmony_ci struct aa_label *label; 8228c2ecf20Sopenharmony_ci int error = 0; 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci AA_BUG(in_interrupt()); 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci label = begin_current_label_crit_section(); 8278c2ecf20Sopenharmony_ci if (!(kern || unconfined(label))) 8288c2ecf20Sopenharmony_ci error = af_select(family, 8298c2ecf20Sopenharmony_ci create_perm(label, family, type, protocol), 8308c2ecf20Sopenharmony_ci aa_af_perm(label, OP_CREATE, AA_MAY_CREATE, 8318c2ecf20Sopenharmony_ci family, type, protocol)); 8328c2ecf20Sopenharmony_ci end_current_label_crit_section(label); 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ci return error; 8358c2ecf20Sopenharmony_ci} 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci/** 8388c2ecf20Sopenharmony_ci * apparmor_socket_post_create - setup the per-socket security struct 8398c2ecf20Sopenharmony_ci * 8408c2ecf20Sopenharmony_ci * Note: 8418c2ecf20Sopenharmony_ci * - kernel sockets currently labeled unconfined but we may want to 8428c2ecf20Sopenharmony_ci * move to a special kernel label 8438c2ecf20Sopenharmony_ci * - socket may not have sk here if created with sock_create_lite or 8448c2ecf20Sopenharmony_ci * sock_alloc. These should be accept cases which will be handled in 8458c2ecf20Sopenharmony_ci * sock_graft. 8468c2ecf20Sopenharmony_ci */ 8478c2ecf20Sopenharmony_cistatic int apparmor_socket_post_create(struct socket *sock, int family, 8488c2ecf20Sopenharmony_ci int type, int protocol, int kern) 8498c2ecf20Sopenharmony_ci{ 8508c2ecf20Sopenharmony_ci struct aa_label *label; 8518c2ecf20Sopenharmony_ci 8528c2ecf20Sopenharmony_ci if (kern) { 8538c2ecf20Sopenharmony_ci struct aa_ns *ns = aa_get_current_ns(); 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci label = aa_get_label(ns_unconfined(ns)); 8568c2ecf20Sopenharmony_ci aa_put_ns(ns); 8578c2ecf20Sopenharmony_ci } else 8588c2ecf20Sopenharmony_ci label = aa_get_current_label(); 8598c2ecf20Sopenharmony_ci 8608c2ecf20Sopenharmony_ci if (sock->sk) { 8618c2ecf20Sopenharmony_ci struct aa_sk_ctx *ctx = SK_CTX(sock->sk); 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci aa_put_label(ctx->label); 8648c2ecf20Sopenharmony_ci ctx->label = aa_get_label(label); 8658c2ecf20Sopenharmony_ci } 8668c2ecf20Sopenharmony_ci aa_put_label(label); 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci return 0; 8698c2ecf20Sopenharmony_ci} 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci/** 8728c2ecf20Sopenharmony_ci * apparmor_socket_bind - check perms before bind addr to socket 8738c2ecf20Sopenharmony_ci */ 8748c2ecf20Sopenharmony_cistatic int apparmor_socket_bind(struct socket *sock, 8758c2ecf20Sopenharmony_ci struct sockaddr *address, int addrlen) 8768c2ecf20Sopenharmony_ci{ 8778c2ecf20Sopenharmony_ci AA_BUG(!sock); 8788c2ecf20Sopenharmony_ci AA_BUG(!sock->sk); 8798c2ecf20Sopenharmony_ci AA_BUG(!address); 8808c2ecf20Sopenharmony_ci AA_BUG(in_interrupt()); 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci return af_select(sock->sk->sk_family, 8838c2ecf20Sopenharmony_ci bind_perm(sock, address, addrlen), 8848c2ecf20Sopenharmony_ci aa_sk_perm(OP_BIND, AA_MAY_BIND, sock->sk)); 8858c2ecf20Sopenharmony_ci} 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci/** 8888c2ecf20Sopenharmony_ci * apparmor_socket_connect - check perms before connecting @sock to @address 8898c2ecf20Sopenharmony_ci */ 8908c2ecf20Sopenharmony_cistatic int apparmor_socket_connect(struct socket *sock, 8918c2ecf20Sopenharmony_ci struct sockaddr *address, int addrlen) 8928c2ecf20Sopenharmony_ci{ 8938c2ecf20Sopenharmony_ci AA_BUG(!sock); 8948c2ecf20Sopenharmony_ci AA_BUG(!sock->sk); 8958c2ecf20Sopenharmony_ci AA_BUG(!address); 8968c2ecf20Sopenharmony_ci AA_BUG(in_interrupt()); 8978c2ecf20Sopenharmony_ci 8988c2ecf20Sopenharmony_ci return af_select(sock->sk->sk_family, 8998c2ecf20Sopenharmony_ci connect_perm(sock, address, addrlen), 9008c2ecf20Sopenharmony_ci aa_sk_perm(OP_CONNECT, AA_MAY_CONNECT, sock->sk)); 9018c2ecf20Sopenharmony_ci} 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci/** 9048c2ecf20Sopenharmony_ci * apparmor_socket_list - check perms before allowing listen 9058c2ecf20Sopenharmony_ci */ 9068c2ecf20Sopenharmony_cistatic int apparmor_socket_listen(struct socket *sock, int backlog) 9078c2ecf20Sopenharmony_ci{ 9088c2ecf20Sopenharmony_ci AA_BUG(!sock); 9098c2ecf20Sopenharmony_ci AA_BUG(!sock->sk); 9108c2ecf20Sopenharmony_ci AA_BUG(in_interrupt()); 9118c2ecf20Sopenharmony_ci 9128c2ecf20Sopenharmony_ci return af_select(sock->sk->sk_family, 9138c2ecf20Sopenharmony_ci listen_perm(sock, backlog), 9148c2ecf20Sopenharmony_ci aa_sk_perm(OP_LISTEN, AA_MAY_LISTEN, sock->sk)); 9158c2ecf20Sopenharmony_ci} 9168c2ecf20Sopenharmony_ci 9178c2ecf20Sopenharmony_ci/** 9188c2ecf20Sopenharmony_ci * apparmor_socket_accept - check perms before accepting a new connection. 9198c2ecf20Sopenharmony_ci * 9208c2ecf20Sopenharmony_ci * Note: while @newsock is created and has some information, the accept 9218c2ecf20Sopenharmony_ci * has not been done. 9228c2ecf20Sopenharmony_ci */ 9238c2ecf20Sopenharmony_cistatic int apparmor_socket_accept(struct socket *sock, struct socket *newsock) 9248c2ecf20Sopenharmony_ci{ 9258c2ecf20Sopenharmony_ci AA_BUG(!sock); 9268c2ecf20Sopenharmony_ci AA_BUG(!sock->sk); 9278c2ecf20Sopenharmony_ci AA_BUG(!newsock); 9288c2ecf20Sopenharmony_ci AA_BUG(in_interrupt()); 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_ci return af_select(sock->sk->sk_family, 9318c2ecf20Sopenharmony_ci accept_perm(sock, newsock), 9328c2ecf20Sopenharmony_ci aa_sk_perm(OP_ACCEPT, AA_MAY_ACCEPT, sock->sk)); 9338c2ecf20Sopenharmony_ci} 9348c2ecf20Sopenharmony_ci 9358c2ecf20Sopenharmony_cistatic int aa_sock_msg_perm(const char *op, u32 request, struct socket *sock, 9368c2ecf20Sopenharmony_ci struct msghdr *msg, int size) 9378c2ecf20Sopenharmony_ci{ 9388c2ecf20Sopenharmony_ci AA_BUG(!sock); 9398c2ecf20Sopenharmony_ci AA_BUG(!sock->sk); 9408c2ecf20Sopenharmony_ci AA_BUG(!msg); 9418c2ecf20Sopenharmony_ci AA_BUG(in_interrupt()); 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci return af_select(sock->sk->sk_family, 9448c2ecf20Sopenharmony_ci msg_perm(op, request, sock, msg, size), 9458c2ecf20Sopenharmony_ci aa_sk_perm(op, request, sock->sk)); 9468c2ecf20Sopenharmony_ci} 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_ci/** 9498c2ecf20Sopenharmony_ci * apparmor_socket_sendmsg - check perms before sending msg to another socket 9508c2ecf20Sopenharmony_ci */ 9518c2ecf20Sopenharmony_cistatic int apparmor_socket_sendmsg(struct socket *sock, 9528c2ecf20Sopenharmony_ci struct msghdr *msg, int size) 9538c2ecf20Sopenharmony_ci{ 9548c2ecf20Sopenharmony_ci return aa_sock_msg_perm(OP_SENDMSG, AA_MAY_SEND, sock, msg, size); 9558c2ecf20Sopenharmony_ci} 9568c2ecf20Sopenharmony_ci 9578c2ecf20Sopenharmony_ci/** 9588c2ecf20Sopenharmony_ci * apparmor_socket_recvmsg - check perms before receiving a message 9598c2ecf20Sopenharmony_ci */ 9608c2ecf20Sopenharmony_cistatic int apparmor_socket_recvmsg(struct socket *sock, 9618c2ecf20Sopenharmony_ci struct msghdr *msg, int size, int flags) 9628c2ecf20Sopenharmony_ci{ 9638c2ecf20Sopenharmony_ci return aa_sock_msg_perm(OP_RECVMSG, AA_MAY_RECEIVE, sock, msg, size); 9648c2ecf20Sopenharmony_ci} 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci/* revaliation, get/set attr, shutdown */ 9678c2ecf20Sopenharmony_cistatic int aa_sock_perm(const char *op, u32 request, struct socket *sock) 9688c2ecf20Sopenharmony_ci{ 9698c2ecf20Sopenharmony_ci AA_BUG(!sock); 9708c2ecf20Sopenharmony_ci AA_BUG(!sock->sk); 9718c2ecf20Sopenharmony_ci AA_BUG(in_interrupt()); 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci return af_select(sock->sk->sk_family, 9748c2ecf20Sopenharmony_ci sock_perm(op, request, sock), 9758c2ecf20Sopenharmony_ci aa_sk_perm(op, request, sock->sk)); 9768c2ecf20Sopenharmony_ci} 9778c2ecf20Sopenharmony_ci 9788c2ecf20Sopenharmony_ci/** 9798c2ecf20Sopenharmony_ci * apparmor_socket_getsockname - check perms before getting the local address 9808c2ecf20Sopenharmony_ci */ 9818c2ecf20Sopenharmony_cistatic int apparmor_socket_getsockname(struct socket *sock) 9828c2ecf20Sopenharmony_ci{ 9838c2ecf20Sopenharmony_ci return aa_sock_perm(OP_GETSOCKNAME, AA_MAY_GETATTR, sock); 9848c2ecf20Sopenharmony_ci} 9858c2ecf20Sopenharmony_ci 9868c2ecf20Sopenharmony_ci/** 9878c2ecf20Sopenharmony_ci * apparmor_socket_getpeername - check perms before getting remote address 9888c2ecf20Sopenharmony_ci */ 9898c2ecf20Sopenharmony_cistatic int apparmor_socket_getpeername(struct socket *sock) 9908c2ecf20Sopenharmony_ci{ 9918c2ecf20Sopenharmony_ci return aa_sock_perm(OP_GETPEERNAME, AA_MAY_GETATTR, sock); 9928c2ecf20Sopenharmony_ci} 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci/* revaliation, get/set attr, opt */ 9958c2ecf20Sopenharmony_cistatic int aa_sock_opt_perm(const char *op, u32 request, struct socket *sock, 9968c2ecf20Sopenharmony_ci int level, int optname) 9978c2ecf20Sopenharmony_ci{ 9988c2ecf20Sopenharmony_ci AA_BUG(!sock); 9998c2ecf20Sopenharmony_ci AA_BUG(!sock->sk); 10008c2ecf20Sopenharmony_ci AA_BUG(in_interrupt()); 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_ci return af_select(sock->sk->sk_family, 10038c2ecf20Sopenharmony_ci opt_perm(op, request, sock, level, optname), 10048c2ecf20Sopenharmony_ci aa_sk_perm(op, request, sock->sk)); 10058c2ecf20Sopenharmony_ci} 10068c2ecf20Sopenharmony_ci 10078c2ecf20Sopenharmony_ci/** 10088c2ecf20Sopenharmony_ci * apparmor_getsockopt - check perms before getting socket options 10098c2ecf20Sopenharmony_ci */ 10108c2ecf20Sopenharmony_cistatic int apparmor_socket_getsockopt(struct socket *sock, int level, 10118c2ecf20Sopenharmony_ci int optname) 10128c2ecf20Sopenharmony_ci{ 10138c2ecf20Sopenharmony_ci return aa_sock_opt_perm(OP_GETSOCKOPT, AA_MAY_GETOPT, sock, 10148c2ecf20Sopenharmony_ci level, optname); 10158c2ecf20Sopenharmony_ci} 10168c2ecf20Sopenharmony_ci 10178c2ecf20Sopenharmony_ci/** 10188c2ecf20Sopenharmony_ci * apparmor_setsockopt - check perms before setting socket options 10198c2ecf20Sopenharmony_ci */ 10208c2ecf20Sopenharmony_cistatic int apparmor_socket_setsockopt(struct socket *sock, int level, 10218c2ecf20Sopenharmony_ci int optname) 10228c2ecf20Sopenharmony_ci{ 10238c2ecf20Sopenharmony_ci return aa_sock_opt_perm(OP_SETSOCKOPT, AA_MAY_SETOPT, sock, 10248c2ecf20Sopenharmony_ci level, optname); 10258c2ecf20Sopenharmony_ci} 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci/** 10288c2ecf20Sopenharmony_ci * apparmor_socket_shutdown - check perms before shutting down @sock conn 10298c2ecf20Sopenharmony_ci */ 10308c2ecf20Sopenharmony_cistatic int apparmor_socket_shutdown(struct socket *sock, int how) 10318c2ecf20Sopenharmony_ci{ 10328c2ecf20Sopenharmony_ci return aa_sock_perm(OP_SHUTDOWN, AA_MAY_SHUTDOWN, sock); 10338c2ecf20Sopenharmony_ci} 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci#ifdef CONFIG_NETWORK_SECMARK 10368c2ecf20Sopenharmony_ci/** 10378c2ecf20Sopenharmony_ci * apparmor_socket_sock_recv_skb - check perms before associating skb to sk 10388c2ecf20Sopenharmony_ci * 10398c2ecf20Sopenharmony_ci * Note: can not sleep may be called with locks held 10408c2ecf20Sopenharmony_ci * 10418c2ecf20Sopenharmony_ci * dont want protocol specific in __skb_recv_datagram() 10428c2ecf20Sopenharmony_ci * to deny an incoming connection socket_sock_rcv_skb() 10438c2ecf20Sopenharmony_ci */ 10448c2ecf20Sopenharmony_cistatic int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) 10458c2ecf20Sopenharmony_ci{ 10468c2ecf20Sopenharmony_ci struct aa_sk_ctx *ctx = SK_CTX(sk); 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci if (!skb->secmark) 10498c2ecf20Sopenharmony_ci return 0; 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci /* 10528c2ecf20Sopenharmony_ci * If reach here before socket_post_create hook is called, in which 10538c2ecf20Sopenharmony_ci * case label is null, drop the packet. 10548c2ecf20Sopenharmony_ci */ 10558c2ecf20Sopenharmony_ci if (!ctx->label) 10568c2ecf20Sopenharmony_ci return -EACCES; 10578c2ecf20Sopenharmony_ci 10588c2ecf20Sopenharmony_ci return apparmor_secmark_check(ctx->label, OP_RECVMSG, AA_MAY_RECEIVE, 10598c2ecf20Sopenharmony_ci skb->secmark, sk); 10608c2ecf20Sopenharmony_ci} 10618c2ecf20Sopenharmony_ci#endif 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_cistatic struct aa_label *sk_peer_label(struct sock *sk) 10658c2ecf20Sopenharmony_ci{ 10668c2ecf20Sopenharmony_ci struct aa_sk_ctx *ctx = SK_CTX(sk); 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_ci if (ctx->peer) 10698c2ecf20Sopenharmony_ci return ctx->peer; 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci return ERR_PTR(-ENOPROTOOPT); 10728c2ecf20Sopenharmony_ci} 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_ci/** 10758c2ecf20Sopenharmony_ci * apparmor_socket_getpeersec_stream - get security context of peer 10768c2ecf20Sopenharmony_ci * 10778c2ecf20Sopenharmony_ci * Note: for tcp only valid if using ipsec or cipso on lan 10788c2ecf20Sopenharmony_ci */ 10798c2ecf20Sopenharmony_cistatic int apparmor_socket_getpeersec_stream(struct socket *sock, 10808c2ecf20Sopenharmony_ci char __user *optval, 10818c2ecf20Sopenharmony_ci int __user *optlen, 10828c2ecf20Sopenharmony_ci unsigned int len) 10838c2ecf20Sopenharmony_ci{ 10848c2ecf20Sopenharmony_ci char *name; 10858c2ecf20Sopenharmony_ci int slen, error = 0; 10868c2ecf20Sopenharmony_ci struct aa_label *label; 10878c2ecf20Sopenharmony_ci struct aa_label *peer; 10888c2ecf20Sopenharmony_ci 10898c2ecf20Sopenharmony_ci label = begin_current_label_crit_section(); 10908c2ecf20Sopenharmony_ci peer = sk_peer_label(sock->sk); 10918c2ecf20Sopenharmony_ci if (IS_ERR(peer)) { 10928c2ecf20Sopenharmony_ci error = PTR_ERR(peer); 10938c2ecf20Sopenharmony_ci goto done; 10948c2ecf20Sopenharmony_ci } 10958c2ecf20Sopenharmony_ci slen = aa_label_asxprint(&name, labels_ns(label), peer, 10968c2ecf20Sopenharmony_ci FLAG_SHOW_MODE | FLAG_VIEW_SUBNS | 10978c2ecf20Sopenharmony_ci FLAG_HIDDEN_UNCONFINED, GFP_KERNEL); 10988c2ecf20Sopenharmony_ci /* don't include terminating \0 in slen, it breaks some apps */ 10998c2ecf20Sopenharmony_ci if (slen < 0) { 11008c2ecf20Sopenharmony_ci error = -ENOMEM; 11018c2ecf20Sopenharmony_ci } else { 11028c2ecf20Sopenharmony_ci if (slen > len) { 11038c2ecf20Sopenharmony_ci error = -ERANGE; 11048c2ecf20Sopenharmony_ci } else if (copy_to_user(optval, name, slen)) { 11058c2ecf20Sopenharmony_ci error = -EFAULT; 11068c2ecf20Sopenharmony_ci goto out; 11078c2ecf20Sopenharmony_ci } 11088c2ecf20Sopenharmony_ci if (put_user(slen, optlen)) 11098c2ecf20Sopenharmony_ci error = -EFAULT; 11108c2ecf20Sopenharmony_ciout: 11118c2ecf20Sopenharmony_ci kfree(name); 11128c2ecf20Sopenharmony_ci 11138c2ecf20Sopenharmony_ci } 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_cidone: 11168c2ecf20Sopenharmony_ci end_current_label_crit_section(label); 11178c2ecf20Sopenharmony_ci 11188c2ecf20Sopenharmony_ci return error; 11198c2ecf20Sopenharmony_ci} 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci/** 11228c2ecf20Sopenharmony_ci * apparmor_socket_getpeersec_dgram - get security label of packet 11238c2ecf20Sopenharmony_ci * @sock: the peer socket 11248c2ecf20Sopenharmony_ci * @skb: packet data 11258c2ecf20Sopenharmony_ci * @secid: pointer to where to put the secid of the packet 11268c2ecf20Sopenharmony_ci * 11278c2ecf20Sopenharmony_ci * Sets the netlabel socket state on sk from parent 11288c2ecf20Sopenharmony_ci */ 11298c2ecf20Sopenharmony_cistatic int apparmor_socket_getpeersec_dgram(struct socket *sock, 11308c2ecf20Sopenharmony_ci struct sk_buff *skb, u32 *secid) 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci{ 11338c2ecf20Sopenharmony_ci /* TODO: requires secid support */ 11348c2ecf20Sopenharmony_ci return -ENOPROTOOPT; 11358c2ecf20Sopenharmony_ci} 11368c2ecf20Sopenharmony_ci 11378c2ecf20Sopenharmony_ci/** 11388c2ecf20Sopenharmony_ci * apparmor_sock_graft - Initialize newly created socket 11398c2ecf20Sopenharmony_ci * @sk: child sock 11408c2ecf20Sopenharmony_ci * @parent: parent socket 11418c2ecf20Sopenharmony_ci * 11428c2ecf20Sopenharmony_ci * Note: could set off of SOCK_CTX(parent) but need to track inode and we can 11438c2ecf20Sopenharmony_ci * just set sk security information off of current creating process label 11448c2ecf20Sopenharmony_ci * Labeling of sk for accept case - probably should be sock based 11458c2ecf20Sopenharmony_ci * instead of task, because of the case where an implicitly labeled 11468c2ecf20Sopenharmony_ci * socket is shared by different tasks. 11478c2ecf20Sopenharmony_ci */ 11488c2ecf20Sopenharmony_cistatic void apparmor_sock_graft(struct sock *sk, struct socket *parent) 11498c2ecf20Sopenharmony_ci{ 11508c2ecf20Sopenharmony_ci struct aa_sk_ctx *ctx = SK_CTX(sk); 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci if (!ctx->label) 11538c2ecf20Sopenharmony_ci ctx->label = aa_get_current_label(); 11548c2ecf20Sopenharmony_ci} 11558c2ecf20Sopenharmony_ci 11568c2ecf20Sopenharmony_ci#ifdef CONFIG_NETWORK_SECMARK 11578c2ecf20Sopenharmony_cistatic int apparmor_inet_conn_request(struct sock *sk, struct sk_buff *skb, 11588c2ecf20Sopenharmony_ci struct request_sock *req) 11598c2ecf20Sopenharmony_ci{ 11608c2ecf20Sopenharmony_ci struct aa_sk_ctx *ctx = SK_CTX(sk); 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_ci if (!skb->secmark) 11638c2ecf20Sopenharmony_ci return 0; 11648c2ecf20Sopenharmony_ci 11658c2ecf20Sopenharmony_ci return apparmor_secmark_check(ctx->label, OP_CONNECT, AA_MAY_CONNECT, 11668c2ecf20Sopenharmony_ci skb->secmark, sk); 11678c2ecf20Sopenharmony_ci} 11688c2ecf20Sopenharmony_ci#endif 11698c2ecf20Sopenharmony_ci 11708c2ecf20Sopenharmony_ci/* 11718c2ecf20Sopenharmony_ci * The cred blob is a pointer to, not an instance of, an aa_label. 11728c2ecf20Sopenharmony_ci */ 11738c2ecf20Sopenharmony_cistruct lsm_blob_sizes apparmor_blob_sizes __lsm_ro_after_init = { 11748c2ecf20Sopenharmony_ci .lbs_cred = sizeof(struct aa_label *), 11758c2ecf20Sopenharmony_ci .lbs_file = sizeof(struct aa_file_ctx), 11768c2ecf20Sopenharmony_ci .lbs_task = sizeof(struct aa_task_ctx), 11778c2ecf20Sopenharmony_ci}; 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_cistatic struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = { 11808c2ecf20Sopenharmony_ci LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check), 11818c2ecf20Sopenharmony_ci LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme), 11828c2ecf20Sopenharmony_ci LSM_HOOK_INIT(capget, apparmor_capget), 11838c2ecf20Sopenharmony_ci LSM_HOOK_INIT(capable, apparmor_capable), 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci LSM_HOOK_INIT(sb_mount, apparmor_sb_mount), 11868c2ecf20Sopenharmony_ci LSM_HOOK_INIT(sb_umount, apparmor_sb_umount), 11878c2ecf20Sopenharmony_ci LSM_HOOK_INIT(sb_pivotroot, apparmor_sb_pivotroot), 11888c2ecf20Sopenharmony_ci 11898c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_link, apparmor_path_link), 11908c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_unlink, apparmor_path_unlink), 11918c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_symlink, apparmor_path_symlink), 11928c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_mkdir, apparmor_path_mkdir), 11938c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_rmdir, apparmor_path_rmdir), 11948c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_mknod, apparmor_path_mknod), 11958c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_rename, apparmor_path_rename), 11968c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_chmod, apparmor_path_chmod), 11978c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_chown, apparmor_path_chown), 11988c2ecf20Sopenharmony_ci LSM_HOOK_INIT(path_truncate, apparmor_path_truncate), 11998c2ecf20Sopenharmony_ci LSM_HOOK_INIT(inode_getattr, apparmor_inode_getattr), 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci LSM_HOOK_INIT(file_open, apparmor_file_open), 12028c2ecf20Sopenharmony_ci LSM_HOOK_INIT(file_receive, apparmor_file_receive), 12038c2ecf20Sopenharmony_ci LSM_HOOK_INIT(file_permission, apparmor_file_permission), 12048c2ecf20Sopenharmony_ci LSM_HOOK_INIT(file_alloc_security, apparmor_file_alloc_security), 12058c2ecf20Sopenharmony_ci LSM_HOOK_INIT(file_free_security, apparmor_file_free_security), 12068c2ecf20Sopenharmony_ci LSM_HOOK_INIT(mmap_file, apparmor_mmap_file), 12078c2ecf20Sopenharmony_ci LSM_HOOK_INIT(file_mprotect, apparmor_file_mprotect), 12088c2ecf20Sopenharmony_ci LSM_HOOK_INIT(file_lock, apparmor_file_lock), 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci LSM_HOOK_INIT(getprocattr, apparmor_getprocattr), 12118c2ecf20Sopenharmony_ci LSM_HOOK_INIT(setprocattr, apparmor_setprocattr), 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci LSM_HOOK_INIT(sk_alloc_security, apparmor_sk_alloc_security), 12148c2ecf20Sopenharmony_ci LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security), 12158c2ecf20Sopenharmony_ci LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security), 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_create, apparmor_socket_create), 12188c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_post_create, apparmor_socket_post_create), 12198c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_bind, apparmor_socket_bind), 12208c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_connect, apparmor_socket_connect), 12218c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_listen, apparmor_socket_listen), 12228c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_accept, apparmor_socket_accept), 12238c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_sendmsg, apparmor_socket_sendmsg), 12248c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_recvmsg, apparmor_socket_recvmsg), 12258c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_getsockname, apparmor_socket_getsockname), 12268c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_getpeername, apparmor_socket_getpeername), 12278c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_getsockopt, apparmor_socket_getsockopt), 12288c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_setsockopt, apparmor_socket_setsockopt), 12298c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_shutdown, apparmor_socket_shutdown), 12308c2ecf20Sopenharmony_ci#ifdef CONFIG_NETWORK_SECMARK 12318c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_sock_rcv_skb, apparmor_socket_sock_rcv_skb), 12328c2ecf20Sopenharmony_ci#endif 12338c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_getpeersec_stream, 12348c2ecf20Sopenharmony_ci apparmor_socket_getpeersec_stream), 12358c2ecf20Sopenharmony_ci LSM_HOOK_INIT(socket_getpeersec_dgram, 12368c2ecf20Sopenharmony_ci apparmor_socket_getpeersec_dgram), 12378c2ecf20Sopenharmony_ci LSM_HOOK_INIT(sock_graft, apparmor_sock_graft), 12388c2ecf20Sopenharmony_ci#ifdef CONFIG_NETWORK_SECMARK 12398c2ecf20Sopenharmony_ci LSM_HOOK_INIT(inet_conn_request, apparmor_inet_conn_request), 12408c2ecf20Sopenharmony_ci#endif 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank), 12438c2ecf20Sopenharmony_ci LSM_HOOK_INIT(cred_free, apparmor_cred_free), 12448c2ecf20Sopenharmony_ci LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare), 12458c2ecf20Sopenharmony_ci LSM_HOOK_INIT(cred_transfer, apparmor_cred_transfer), 12468c2ecf20Sopenharmony_ci 12478c2ecf20Sopenharmony_ci LSM_HOOK_INIT(bprm_creds_for_exec, apparmor_bprm_creds_for_exec), 12488c2ecf20Sopenharmony_ci LSM_HOOK_INIT(bprm_committing_creds, apparmor_bprm_committing_creds), 12498c2ecf20Sopenharmony_ci LSM_HOOK_INIT(bprm_committed_creds, apparmor_bprm_committed_creds), 12508c2ecf20Sopenharmony_ci 12518c2ecf20Sopenharmony_ci LSM_HOOK_INIT(task_free, apparmor_task_free), 12528c2ecf20Sopenharmony_ci LSM_HOOK_INIT(task_alloc, apparmor_task_alloc), 12538c2ecf20Sopenharmony_ci LSM_HOOK_INIT(task_getsecid, apparmor_task_getsecid), 12548c2ecf20Sopenharmony_ci LSM_HOOK_INIT(task_setrlimit, apparmor_task_setrlimit), 12558c2ecf20Sopenharmony_ci LSM_HOOK_INIT(task_kill, apparmor_task_kill), 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci#ifdef CONFIG_AUDIT 12588c2ecf20Sopenharmony_ci LSM_HOOK_INIT(audit_rule_init, aa_audit_rule_init), 12598c2ecf20Sopenharmony_ci LSM_HOOK_INIT(audit_rule_known, aa_audit_rule_known), 12608c2ecf20Sopenharmony_ci LSM_HOOK_INIT(audit_rule_match, aa_audit_rule_match), 12618c2ecf20Sopenharmony_ci LSM_HOOK_INIT(audit_rule_free, aa_audit_rule_free), 12628c2ecf20Sopenharmony_ci#endif 12638c2ecf20Sopenharmony_ci 12648c2ecf20Sopenharmony_ci LSM_HOOK_INIT(secid_to_secctx, apparmor_secid_to_secctx), 12658c2ecf20Sopenharmony_ci LSM_HOOK_INIT(secctx_to_secid, apparmor_secctx_to_secid), 12668c2ecf20Sopenharmony_ci LSM_HOOK_INIT(release_secctx, apparmor_release_secctx), 12678c2ecf20Sopenharmony_ci}; 12688c2ecf20Sopenharmony_ci 12698c2ecf20Sopenharmony_ci/* 12708c2ecf20Sopenharmony_ci * AppArmor sysfs module parameters 12718c2ecf20Sopenharmony_ci */ 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_cistatic int param_set_aabool(const char *val, const struct kernel_param *kp); 12748c2ecf20Sopenharmony_cistatic int param_get_aabool(char *buffer, const struct kernel_param *kp); 12758c2ecf20Sopenharmony_ci#define param_check_aabool param_check_bool 12768c2ecf20Sopenharmony_cistatic const struct kernel_param_ops param_ops_aabool = { 12778c2ecf20Sopenharmony_ci .flags = KERNEL_PARAM_OPS_FL_NOARG, 12788c2ecf20Sopenharmony_ci .set = param_set_aabool, 12798c2ecf20Sopenharmony_ci .get = param_get_aabool 12808c2ecf20Sopenharmony_ci}; 12818c2ecf20Sopenharmony_ci 12828c2ecf20Sopenharmony_cistatic int param_set_aauint(const char *val, const struct kernel_param *kp); 12838c2ecf20Sopenharmony_cistatic int param_get_aauint(char *buffer, const struct kernel_param *kp); 12848c2ecf20Sopenharmony_ci#define param_check_aauint param_check_uint 12858c2ecf20Sopenharmony_cistatic const struct kernel_param_ops param_ops_aauint = { 12868c2ecf20Sopenharmony_ci .set = param_set_aauint, 12878c2ecf20Sopenharmony_ci .get = param_get_aauint 12888c2ecf20Sopenharmony_ci}; 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_cistatic int param_set_aacompressionlevel(const char *val, 12918c2ecf20Sopenharmony_ci const struct kernel_param *kp); 12928c2ecf20Sopenharmony_cistatic int param_get_aacompressionlevel(char *buffer, 12938c2ecf20Sopenharmony_ci const struct kernel_param *kp); 12948c2ecf20Sopenharmony_ci#define param_check_aacompressionlevel param_check_int 12958c2ecf20Sopenharmony_cistatic const struct kernel_param_ops param_ops_aacompressionlevel = { 12968c2ecf20Sopenharmony_ci .set = param_set_aacompressionlevel, 12978c2ecf20Sopenharmony_ci .get = param_get_aacompressionlevel 12988c2ecf20Sopenharmony_ci}; 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_cistatic int param_set_aalockpolicy(const char *val, const struct kernel_param *kp); 13018c2ecf20Sopenharmony_cistatic int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp); 13028c2ecf20Sopenharmony_ci#define param_check_aalockpolicy param_check_bool 13038c2ecf20Sopenharmony_cistatic const struct kernel_param_ops param_ops_aalockpolicy = { 13048c2ecf20Sopenharmony_ci .flags = KERNEL_PARAM_OPS_FL_NOARG, 13058c2ecf20Sopenharmony_ci .set = param_set_aalockpolicy, 13068c2ecf20Sopenharmony_ci .get = param_get_aalockpolicy 13078c2ecf20Sopenharmony_ci}; 13088c2ecf20Sopenharmony_ci 13098c2ecf20Sopenharmony_cistatic int param_set_audit(const char *val, const struct kernel_param *kp); 13108c2ecf20Sopenharmony_cistatic int param_get_audit(char *buffer, const struct kernel_param *kp); 13118c2ecf20Sopenharmony_ci 13128c2ecf20Sopenharmony_cistatic int param_set_mode(const char *val, const struct kernel_param *kp); 13138c2ecf20Sopenharmony_cistatic int param_get_mode(char *buffer, const struct kernel_param *kp); 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci/* Flag values, also controllable via /sys/module/apparmor/parameters 13168c2ecf20Sopenharmony_ci * We define special types as we want to do additional mediation. 13178c2ecf20Sopenharmony_ci */ 13188c2ecf20Sopenharmony_ci 13198c2ecf20Sopenharmony_ci/* AppArmor global enforcement switch - complain, enforce, kill */ 13208c2ecf20Sopenharmony_cienum profile_mode aa_g_profile_mode = APPARMOR_ENFORCE; 13218c2ecf20Sopenharmony_cimodule_param_call(mode, param_set_mode, param_get_mode, 13228c2ecf20Sopenharmony_ci &aa_g_profile_mode, S_IRUSR | S_IWUSR); 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci/* whether policy verification hashing is enabled */ 13258c2ecf20Sopenharmony_cibool aa_g_hash_policy = IS_ENABLED(CONFIG_SECURITY_APPARMOR_HASH_DEFAULT); 13268c2ecf20Sopenharmony_ci#ifdef CONFIG_SECURITY_APPARMOR_HASH 13278c2ecf20Sopenharmony_cimodule_param_named(hash_policy, aa_g_hash_policy, aabool, S_IRUSR | S_IWUSR); 13288c2ecf20Sopenharmony_ci#endif 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_ci/* policy loaddata compression level */ 13318c2ecf20Sopenharmony_ciint aa_g_rawdata_compression_level = Z_DEFAULT_COMPRESSION; 13328c2ecf20Sopenharmony_cimodule_param_named(rawdata_compression_level, aa_g_rawdata_compression_level, 13338c2ecf20Sopenharmony_ci aacompressionlevel, 0400); 13348c2ecf20Sopenharmony_ci 13358c2ecf20Sopenharmony_ci/* Debug mode */ 13368c2ecf20Sopenharmony_cibool aa_g_debug = IS_ENABLED(CONFIG_SECURITY_APPARMOR_DEBUG_MESSAGES); 13378c2ecf20Sopenharmony_cimodule_param_named(debug, aa_g_debug, aabool, S_IRUSR | S_IWUSR); 13388c2ecf20Sopenharmony_ci 13398c2ecf20Sopenharmony_ci/* Audit mode */ 13408c2ecf20Sopenharmony_cienum audit_mode aa_g_audit; 13418c2ecf20Sopenharmony_cimodule_param_call(audit, param_set_audit, param_get_audit, 13428c2ecf20Sopenharmony_ci &aa_g_audit, S_IRUSR | S_IWUSR); 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_ci/* Determines if audit header is included in audited messages. This 13458c2ecf20Sopenharmony_ci * provides more context if the audit daemon is not running 13468c2ecf20Sopenharmony_ci */ 13478c2ecf20Sopenharmony_cibool aa_g_audit_header = true; 13488c2ecf20Sopenharmony_cimodule_param_named(audit_header, aa_g_audit_header, aabool, 13498c2ecf20Sopenharmony_ci S_IRUSR | S_IWUSR); 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci/* lock out loading/removal of policy 13528c2ecf20Sopenharmony_ci * TODO: add in at boot loading of policy, which is the only way to 13538c2ecf20Sopenharmony_ci * load policy, if lock_policy is set 13548c2ecf20Sopenharmony_ci */ 13558c2ecf20Sopenharmony_cibool aa_g_lock_policy; 13568c2ecf20Sopenharmony_cimodule_param_named(lock_policy, aa_g_lock_policy, aalockpolicy, 13578c2ecf20Sopenharmony_ci S_IRUSR | S_IWUSR); 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci/* Syscall logging mode */ 13608c2ecf20Sopenharmony_cibool aa_g_logsyscall; 13618c2ecf20Sopenharmony_cimodule_param_named(logsyscall, aa_g_logsyscall, aabool, S_IRUSR | S_IWUSR); 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_ci/* Maximum pathname length before accesses will start getting rejected */ 13648c2ecf20Sopenharmony_ciunsigned int aa_g_path_max = 2 * PATH_MAX; 13658c2ecf20Sopenharmony_cimodule_param_named(path_max, aa_g_path_max, aauint, S_IRUSR); 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_ci/* Determines how paranoid loading of policy is and how much verification 13688c2ecf20Sopenharmony_ci * on the loaded policy is done. 13698c2ecf20Sopenharmony_ci * DEPRECATED: read only as strict checking of load is always done now 13708c2ecf20Sopenharmony_ci * that none root users (user namespaces) can load policy. 13718c2ecf20Sopenharmony_ci */ 13728c2ecf20Sopenharmony_cibool aa_g_paranoid_load = true; 13738c2ecf20Sopenharmony_cimodule_param_named(paranoid_load, aa_g_paranoid_load, aabool, S_IRUGO); 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_cistatic int param_get_aaintbool(char *buffer, const struct kernel_param *kp); 13768c2ecf20Sopenharmony_cistatic int param_set_aaintbool(const char *val, const struct kernel_param *kp); 13778c2ecf20Sopenharmony_ci#define param_check_aaintbool param_check_int 13788c2ecf20Sopenharmony_cistatic const struct kernel_param_ops param_ops_aaintbool = { 13798c2ecf20Sopenharmony_ci .set = param_set_aaintbool, 13808c2ecf20Sopenharmony_ci .get = param_get_aaintbool 13818c2ecf20Sopenharmony_ci}; 13828c2ecf20Sopenharmony_ci/* Boot time disable flag */ 13838c2ecf20Sopenharmony_cistatic int apparmor_enabled __lsm_ro_after_init = 1; 13848c2ecf20Sopenharmony_cimodule_param_named(enabled, apparmor_enabled, aaintbool, 0444); 13858c2ecf20Sopenharmony_ci 13868c2ecf20Sopenharmony_cistatic int __init apparmor_enabled_setup(char *str) 13878c2ecf20Sopenharmony_ci{ 13888c2ecf20Sopenharmony_ci unsigned long enabled; 13898c2ecf20Sopenharmony_ci int error = kstrtoul(str, 0, &enabled); 13908c2ecf20Sopenharmony_ci if (!error) 13918c2ecf20Sopenharmony_ci apparmor_enabled = enabled ? 1 : 0; 13928c2ecf20Sopenharmony_ci return 1; 13938c2ecf20Sopenharmony_ci} 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci__setup("apparmor=", apparmor_enabled_setup); 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_ci/* set global flag turning off the ability to load policy */ 13988c2ecf20Sopenharmony_cistatic int param_set_aalockpolicy(const char *val, const struct kernel_param *kp) 13998c2ecf20Sopenharmony_ci{ 14008c2ecf20Sopenharmony_ci if (!apparmor_enabled) 14018c2ecf20Sopenharmony_ci return -EINVAL; 14028c2ecf20Sopenharmony_ci if (apparmor_initialized && !policy_admin_capable(NULL)) 14038c2ecf20Sopenharmony_ci return -EPERM; 14048c2ecf20Sopenharmony_ci return param_set_bool(val, kp); 14058c2ecf20Sopenharmony_ci} 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_cistatic int param_get_aalockpolicy(char *buffer, const struct kernel_param *kp) 14088c2ecf20Sopenharmony_ci{ 14098c2ecf20Sopenharmony_ci if (!apparmor_enabled) 14108c2ecf20Sopenharmony_ci return -EINVAL; 14118c2ecf20Sopenharmony_ci if (apparmor_initialized && !policy_view_capable(NULL)) 14128c2ecf20Sopenharmony_ci return -EPERM; 14138c2ecf20Sopenharmony_ci return param_get_bool(buffer, kp); 14148c2ecf20Sopenharmony_ci} 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_cistatic int param_set_aabool(const char *val, const struct kernel_param *kp) 14178c2ecf20Sopenharmony_ci{ 14188c2ecf20Sopenharmony_ci if (!apparmor_enabled) 14198c2ecf20Sopenharmony_ci return -EINVAL; 14208c2ecf20Sopenharmony_ci if (apparmor_initialized && !policy_admin_capable(NULL)) 14218c2ecf20Sopenharmony_ci return -EPERM; 14228c2ecf20Sopenharmony_ci return param_set_bool(val, kp); 14238c2ecf20Sopenharmony_ci} 14248c2ecf20Sopenharmony_ci 14258c2ecf20Sopenharmony_cistatic int param_get_aabool(char *buffer, const struct kernel_param *kp) 14268c2ecf20Sopenharmony_ci{ 14278c2ecf20Sopenharmony_ci if (!apparmor_enabled) 14288c2ecf20Sopenharmony_ci return -EINVAL; 14298c2ecf20Sopenharmony_ci if (apparmor_initialized && !policy_view_capable(NULL)) 14308c2ecf20Sopenharmony_ci return -EPERM; 14318c2ecf20Sopenharmony_ci return param_get_bool(buffer, kp); 14328c2ecf20Sopenharmony_ci} 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_cistatic int param_set_aauint(const char *val, const struct kernel_param *kp) 14358c2ecf20Sopenharmony_ci{ 14368c2ecf20Sopenharmony_ci int error; 14378c2ecf20Sopenharmony_ci 14388c2ecf20Sopenharmony_ci if (!apparmor_enabled) 14398c2ecf20Sopenharmony_ci return -EINVAL; 14408c2ecf20Sopenharmony_ci /* file is ro but enforce 2nd line check */ 14418c2ecf20Sopenharmony_ci if (apparmor_initialized) 14428c2ecf20Sopenharmony_ci return -EPERM; 14438c2ecf20Sopenharmony_ci 14448c2ecf20Sopenharmony_ci error = param_set_uint(val, kp); 14458c2ecf20Sopenharmony_ci aa_g_path_max = max_t(uint32_t, aa_g_path_max, sizeof(union aa_buffer)); 14468c2ecf20Sopenharmony_ci pr_info("AppArmor: buffer size set to %d bytes\n", aa_g_path_max); 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_ci return error; 14498c2ecf20Sopenharmony_ci} 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_cistatic int param_get_aauint(char *buffer, const struct kernel_param *kp) 14528c2ecf20Sopenharmony_ci{ 14538c2ecf20Sopenharmony_ci if (!apparmor_enabled) 14548c2ecf20Sopenharmony_ci return -EINVAL; 14558c2ecf20Sopenharmony_ci if (apparmor_initialized && !policy_view_capable(NULL)) 14568c2ecf20Sopenharmony_ci return -EPERM; 14578c2ecf20Sopenharmony_ci return param_get_uint(buffer, kp); 14588c2ecf20Sopenharmony_ci} 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_ci/* Can only be set before AppArmor is initialized (i.e. on boot cmdline). */ 14618c2ecf20Sopenharmony_cistatic int param_set_aaintbool(const char *val, const struct kernel_param *kp) 14628c2ecf20Sopenharmony_ci{ 14638c2ecf20Sopenharmony_ci struct kernel_param kp_local; 14648c2ecf20Sopenharmony_ci bool value; 14658c2ecf20Sopenharmony_ci int error; 14668c2ecf20Sopenharmony_ci 14678c2ecf20Sopenharmony_ci if (apparmor_initialized) 14688c2ecf20Sopenharmony_ci return -EPERM; 14698c2ecf20Sopenharmony_ci 14708c2ecf20Sopenharmony_ci /* Create local copy, with arg pointing to bool type. */ 14718c2ecf20Sopenharmony_ci value = !!*((int *)kp->arg); 14728c2ecf20Sopenharmony_ci memcpy(&kp_local, kp, sizeof(kp_local)); 14738c2ecf20Sopenharmony_ci kp_local.arg = &value; 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_ci error = param_set_bool(val, &kp_local); 14768c2ecf20Sopenharmony_ci if (!error) 14778c2ecf20Sopenharmony_ci *((int *)kp->arg) = *((bool *)kp_local.arg); 14788c2ecf20Sopenharmony_ci return error; 14798c2ecf20Sopenharmony_ci} 14808c2ecf20Sopenharmony_ci 14818c2ecf20Sopenharmony_ci/* 14828c2ecf20Sopenharmony_ci * To avoid changing /sys/module/apparmor/parameters/enabled from Y/N to 14838c2ecf20Sopenharmony_ci * 1/0, this converts the "int that is actually bool" back to bool for 14848c2ecf20Sopenharmony_ci * display in the /sys filesystem, while keeping it "int" for the LSM 14858c2ecf20Sopenharmony_ci * infrastructure. 14868c2ecf20Sopenharmony_ci */ 14878c2ecf20Sopenharmony_cistatic int param_get_aaintbool(char *buffer, const struct kernel_param *kp) 14888c2ecf20Sopenharmony_ci{ 14898c2ecf20Sopenharmony_ci struct kernel_param kp_local; 14908c2ecf20Sopenharmony_ci bool value; 14918c2ecf20Sopenharmony_ci 14928c2ecf20Sopenharmony_ci /* Create local copy, with arg pointing to bool type. */ 14938c2ecf20Sopenharmony_ci value = !!*((int *)kp->arg); 14948c2ecf20Sopenharmony_ci memcpy(&kp_local, kp, sizeof(kp_local)); 14958c2ecf20Sopenharmony_ci kp_local.arg = &value; 14968c2ecf20Sopenharmony_ci 14978c2ecf20Sopenharmony_ci return param_get_bool(buffer, &kp_local); 14988c2ecf20Sopenharmony_ci} 14998c2ecf20Sopenharmony_ci 15008c2ecf20Sopenharmony_cistatic int param_set_aacompressionlevel(const char *val, 15018c2ecf20Sopenharmony_ci const struct kernel_param *kp) 15028c2ecf20Sopenharmony_ci{ 15038c2ecf20Sopenharmony_ci int error; 15048c2ecf20Sopenharmony_ci 15058c2ecf20Sopenharmony_ci if (!apparmor_enabled) 15068c2ecf20Sopenharmony_ci return -EINVAL; 15078c2ecf20Sopenharmony_ci if (apparmor_initialized) 15088c2ecf20Sopenharmony_ci return -EPERM; 15098c2ecf20Sopenharmony_ci 15108c2ecf20Sopenharmony_ci error = param_set_int(val, kp); 15118c2ecf20Sopenharmony_ci 15128c2ecf20Sopenharmony_ci aa_g_rawdata_compression_level = clamp(aa_g_rawdata_compression_level, 15138c2ecf20Sopenharmony_ci Z_NO_COMPRESSION, 15148c2ecf20Sopenharmony_ci Z_BEST_COMPRESSION); 15158c2ecf20Sopenharmony_ci pr_info("AppArmor: policy rawdata compression level set to %u\n", 15168c2ecf20Sopenharmony_ci aa_g_rawdata_compression_level); 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_ci return error; 15198c2ecf20Sopenharmony_ci} 15208c2ecf20Sopenharmony_ci 15218c2ecf20Sopenharmony_cistatic int param_get_aacompressionlevel(char *buffer, 15228c2ecf20Sopenharmony_ci const struct kernel_param *kp) 15238c2ecf20Sopenharmony_ci{ 15248c2ecf20Sopenharmony_ci if (!apparmor_enabled) 15258c2ecf20Sopenharmony_ci return -EINVAL; 15268c2ecf20Sopenharmony_ci if (apparmor_initialized && !policy_view_capable(NULL)) 15278c2ecf20Sopenharmony_ci return -EPERM; 15288c2ecf20Sopenharmony_ci return param_get_int(buffer, kp); 15298c2ecf20Sopenharmony_ci} 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_cistatic int param_get_audit(char *buffer, const struct kernel_param *kp) 15328c2ecf20Sopenharmony_ci{ 15338c2ecf20Sopenharmony_ci if (!apparmor_enabled) 15348c2ecf20Sopenharmony_ci return -EINVAL; 15358c2ecf20Sopenharmony_ci if (apparmor_initialized && !policy_view_capable(NULL)) 15368c2ecf20Sopenharmony_ci return -EPERM; 15378c2ecf20Sopenharmony_ci return sprintf(buffer, "%s", audit_mode_names[aa_g_audit]); 15388c2ecf20Sopenharmony_ci} 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_cistatic int param_set_audit(const char *val, const struct kernel_param *kp) 15418c2ecf20Sopenharmony_ci{ 15428c2ecf20Sopenharmony_ci int i; 15438c2ecf20Sopenharmony_ci 15448c2ecf20Sopenharmony_ci if (!apparmor_enabled) 15458c2ecf20Sopenharmony_ci return -EINVAL; 15468c2ecf20Sopenharmony_ci if (!val) 15478c2ecf20Sopenharmony_ci return -EINVAL; 15488c2ecf20Sopenharmony_ci if (apparmor_initialized && !policy_admin_capable(NULL)) 15498c2ecf20Sopenharmony_ci return -EPERM; 15508c2ecf20Sopenharmony_ci 15518c2ecf20Sopenharmony_ci i = match_string(audit_mode_names, AUDIT_MAX_INDEX, val); 15528c2ecf20Sopenharmony_ci if (i < 0) 15538c2ecf20Sopenharmony_ci return -EINVAL; 15548c2ecf20Sopenharmony_ci 15558c2ecf20Sopenharmony_ci aa_g_audit = i; 15568c2ecf20Sopenharmony_ci return 0; 15578c2ecf20Sopenharmony_ci} 15588c2ecf20Sopenharmony_ci 15598c2ecf20Sopenharmony_cistatic int param_get_mode(char *buffer, const struct kernel_param *kp) 15608c2ecf20Sopenharmony_ci{ 15618c2ecf20Sopenharmony_ci if (!apparmor_enabled) 15628c2ecf20Sopenharmony_ci return -EINVAL; 15638c2ecf20Sopenharmony_ci if (apparmor_initialized && !policy_view_capable(NULL)) 15648c2ecf20Sopenharmony_ci return -EPERM; 15658c2ecf20Sopenharmony_ci 15668c2ecf20Sopenharmony_ci return sprintf(buffer, "%s", aa_profile_mode_names[aa_g_profile_mode]); 15678c2ecf20Sopenharmony_ci} 15688c2ecf20Sopenharmony_ci 15698c2ecf20Sopenharmony_cistatic int param_set_mode(const char *val, const struct kernel_param *kp) 15708c2ecf20Sopenharmony_ci{ 15718c2ecf20Sopenharmony_ci int i; 15728c2ecf20Sopenharmony_ci 15738c2ecf20Sopenharmony_ci if (!apparmor_enabled) 15748c2ecf20Sopenharmony_ci return -EINVAL; 15758c2ecf20Sopenharmony_ci if (!val) 15768c2ecf20Sopenharmony_ci return -EINVAL; 15778c2ecf20Sopenharmony_ci if (apparmor_initialized && !policy_admin_capable(NULL)) 15788c2ecf20Sopenharmony_ci return -EPERM; 15798c2ecf20Sopenharmony_ci 15808c2ecf20Sopenharmony_ci i = match_string(aa_profile_mode_names, APPARMOR_MODE_NAMES_MAX_INDEX, 15818c2ecf20Sopenharmony_ci val); 15828c2ecf20Sopenharmony_ci if (i < 0) 15838c2ecf20Sopenharmony_ci return -EINVAL; 15848c2ecf20Sopenharmony_ci 15858c2ecf20Sopenharmony_ci aa_g_profile_mode = i; 15868c2ecf20Sopenharmony_ci return 0; 15878c2ecf20Sopenharmony_ci} 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_cichar *aa_get_buffer(bool in_atomic) 15908c2ecf20Sopenharmony_ci{ 15918c2ecf20Sopenharmony_ci union aa_buffer *aa_buf; 15928c2ecf20Sopenharmony_ci bool try_again = true; 15938c2ecf20Sopenharmony_ci gfp_t flags = (GFP_KERNEL | __GFP_RETRY_MAYFAIL | __GFP_NOWARN); 15948c2ecf20Sopenharmony_ci 15958c2ecf20Sopenharmony_ciretry: 15968c2ecf20Sopenharmony_ci spin_lock(&aa_buffers_lock); 15978c2ecf20Sopenharmony_ci if (buffer_count > reserve_count || 15988c2ecf20Sopenharmony_ci (in_atomic && !list_empty(&aa_global_buffers))) { 15998c2ecf20Sopenharmony_ci aa_buf = list_first_entry(&aa_global_buffers, union aa_buffer, 16008c2ecf20Sopenharmony_ci list); 16018c2ecf20Sopenharmony_ci list_del(&aa_buf->list); 16028c2ecf20Sopenharmony_ci buffer_count--; 16038c2ecf20Sopenharmony_ci spin_unlock(&aa_buffers_lock); 16048c2ecf20Sopenharmony_ci return &aa_buf->buffer[0]; 16058c2ecf20Sopenharmony_ci } 16068c2ecf20Sopenharmony_ci if (in_atomic) { 16078c2ecf20Sopenharmony_ci /* 16088c2ecf20Sopenharmony_ci * out of reserve buffers and in atomic context so increase 16098c2ecf20Sopenharmony_ci * how many buffers to keep in reserve 16108c2ecf20Sopenharmony_ci */ 16118c2ecf20Sopenharmony_ci reserve_count++; 16128c2ecf20Sopenharmony_ci flags = GFP_ATOMIC; 16138c2ecf20Sopenharmony_ci } 16148c2ecf20Sopenharmony_ci spin_unlock(&aa_buffers_lock); 16158c2ecf20Sopenharmony_ci 16168c2ecf20Sopenharmony_ci if (!in_atomic) 16178c2ecf20Sopenharmony_ci might_sleep(); 16188c2ecf20Sopenharmony_ci aa_buf = kmalloc(aa_g_path_max, flags); 16198c2ecf20Sopenharmony_ci if (!aa_buf) { 16208c2ecf20Sopenharmony_ci if (try_again) { 16218c2ecf20Sopenharmony_ci try_again = false; 16228c2ecf20Sopenharmony_ci goto retry; 16238c2ecf20Sopenharmony_ci } 16248c2ecf20Sopenharmony_ci pr_warn_once("AppArmor: Failed to allocate a memory buffer.\n"); 16258c2ecf20Sopenharmony_ci return NULL; 16268c2ecf20Sopenharmony_ci } 16278c2ecf20Sopenharmony_ci return &aa_buf->buffer[0]; 16288c2ecf20Sopenharmony_ci} 16298c2ecf20Sopenharmony_ci 16308c2ecf20Sopenharmony_civoid aa_put_buffer(char *buf) 16318c2ecf20Sopenharmony_ci{ 16328c2ecf20Sopenharmony_ci union aa_buffer *aa_buf; 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_ci if (!buf) 16358c2ecf20Sopenharmony_ci return; 16368c2ecf20Sopenharmony_ci aa_buf = container_of(buf, union aa_buffer, buffer[0]); 16378c2ecf20Sopenharmony_ci 16388c2ecf20Sopenharmony_ci spin_lock(&aa_buffers_lock); 16398c2ecf20Sopenharmony_ci list_add(&aa_buf->list, &aa_global_buffers); 16408c2ecf20Sopenharmony_ci buffer_count++; 16418c2ecf20Sopenharmony_ci spin_unlock(&aa_buffers_lock); 16428c2ecf20Sopenharmony_ci} 16438c2ecf20Sopenharmony_ci 16448c2ecf20Sopenharmony_ci/* 16458c2ecf20Sopenharmony_ci * AppArmor init functions 16468c2ecf20Sopenharmony_ci */ 16478c2ecf20Sopenharmony_ci 16488c2ecf20Sopenharmony_ci/** 16498c2ecf20Sopenharmony_ci * set_init_ctx - set a task context and profile on the first task. 16508c2ecf20Sopenharmony_ci * 16518c2ecf20Sopenharmony_ci * TODO: allow setting an alternate profile than unconfined 16528c2ecf20Sopenharmony_ci */ 16538c2ecf20Sopenharmony_cistatic int __init set_init_ctx(void) 16548c2ecf20Sopenharmony_ci{ 16558c2ecf20Sopenharmony_ci struct cred *cred = (__force struct cred *)current->real_cred; 16568c2ecf20Sopenharmony_ci 16578c2ecf20Sopenharmony_ci set_cred_label(cred, aa_get_label(ns_unconfined(root_ns))); 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_ci return 0; 16608c2ecf20Sopenharmony_ci} 16618c2ecf20Sopenharmony_ci 16628c2ecf20Sopenharmony_cistatic void destroy_buffers(void) 16638c2ecf20Sopenharmony_ci{ 16648c2ecf20Sopenharmony_ci union aa_buffer *aa_buf; 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_ci spin_lock(&aa_buffers_lock); 16678c2ecf20Sopenharmony_ci while (!list_empty(&aa_global_buffers)) { 16688c2ecf20Sopenharmony_ci aa_buf = list_first_entry(&aa_global_buffers, union aa_buffer, 16698c2ecf20Sopenharmony_ci list); 16708c2ecf20Sopenharmony_ci list_del(&aa_buf->list); 16718c2ecf20Sopenharmony_ci spin_unlock(&aa_buffers_lock); 16728c2ecf20Sopenharmony_ci kfree(aa_buf); 16738c2ecf20Sopenharmony_ci spin_lock(&aa_buffers_lock); 16748c2ecf20Sopenharmony_ci } 16758c2ecf20Sopenharmony_ci spin_unlock(&aa_buffers_lock); 16768c2ecf20Sopenharmony_ci} 16778c2ecf20Sopenharmony_ci 16788c2ecf20Sopenharmony_cistatic int __init alloc_buffers(void) 16798c2ecf20Sopenharmony_ci{ 16808c2ecf20Sopenharmony_ci union aa_buffer *aa_buf; 16818c2ecf20Sopenharmony_ci int i, num; 16828c2ecf20Sopenharmony_ci 16838c2ecf20Sopenharmony_ci /* 16848c2ecf20Sopenharmony_ci * A function may require two buffers at once. Usually the buffers are 16858c2ecf20Sopenharmony_ci * used for a short period of time and are shared. On UP kernel buffers 16868c2ecf20Sopenharmony_ci * two should be enough, with more CPUs it is possible that more 16878c2ecf20Sopenharmony_ci * buffers will be used simultaneously. The preallocated pool may grow. 16888c2ecf20Sopenharmony_ci * This preallocation has also the side-effect that AppArmor will be 16898c2ecf20Sopenharmony_ci * disabled early at boot if aa_g_path_max is extremly high. 16908c2ecf20Sopenharmony_ci */ 16918c2ecf20Sopenharmony_ci if (num_online_cpus() > 1) 16928c2ecf20Sopenharmony_ci num = 4 + RESERVE_COUNT; 16938c2ecf20Sopenharmony_ci else 16948c2ecf20Sopenharmony_ci num = 2 + RESERVE_COUNT; 16958c2ecf20Sopenharmony_ci 16968c2ecf20Sopenharmony_ci for (i = 0; i < num; i++) { 16978c2ecf20Sopenharmony_ci 16988c2ecf20Sopenharmony_ci aa_buf = kmalloc(aa_g_path_max, GFP_KERNEL | 16998c2ecf20Sopenharmony_ci __GFP_RETRY_MAYFAIL | __GFP_NOWARN); 17008c2ecf20Sopenharmony_ci if (!aa_buf) { 17018c2ecf20Sopenharmony_ci destroy_buffers(); 17028c2ecf20Sopenharmony_ci return -ENOMEM; 17038c2ecf20Sopenharmony_ci } 17048c2ecf20Sopenharmony_ci aa_put_buffer(&aa_buf->buffer[0]); 17058c2ecf20Sopenharmony_ci } 17068c2ecf20Sopenharmony_ci return 0; 17078c2ecf20Sopenharmony_ci} 17088c2ecf20Sopenharmony_ci 17098c2ecf20Sopenharmony_ci#ifdef CONFIG_SYSCTL 17108c2ecf20Sopenharmony_cistatic int apparmor_dointvec(struct ctl_table *table, int write, 17118c2ecf20Sopenharmony_ci void *buffer, size_t *lenp, loff_t *ppos) 17128c2ecf20Sopenharmony_ci{ 17138c2ecf20Sopenharmony_ci if (!policy_admin_capable(NULL)) 17148c2ecf20Sopenharmony_ci return -EPERM; 17158c2ecf20Sopenharmony_ci if (!apparmor_enabled) 17168c2ecf20Sopenharmony_ci return -EINVAL; 17178c2ecf20Sopenharmony_ci 17188c2ecf20Sopenharmony_ci return proc_dointvec(table, write, buffer, lenp, ppos); 17198c2ecf20Sopenharmony_ci} 17208c2ecf20Sopenharmony_ci 17218c2ecf20Sopenharmony_cistatic struct ctl_path apparmor_sysctl_path[] = { 17228c2ecf20Sopenharmony_ci { .procname = "kernel", }, 17238c2ecf20Sopenharmony_ci { } 17248c2ecf20Sopenharmony_ci}; 17258c2ecf20Sopenharmony_ci 17268c2ecf20Sopenharmony_cistatic struct ctl_table apparmor_sysctl_table[] = { 17278c2ecf20Sopenharmony_ci { 17288c2ecf20Sopenharmony_ci .procname = "unprivileged_userns_apparmor_policy", 17298c2ecf20Sopenharmony_ci .data = &unprivileged_userns_apparmor_policy, 17308c2ecf20Sopenharmony_ci .maxlen = sizeof(int), 17318c2ecf20Sopenharmony_ci .mode = 0600, 17328c2ecf20Sopenharmony_ci .proc_handler = apparmor_dointvec, 17338c2ecf20Sopenharmony_ci }, 17348c2ecf20Sopenharmony_ci { } 17358c2ecf20Sopenharmony_ci}; 17368c2ecf20Sopenharmony_ci 17378c2ecf20Sopenharmony_cistatic int __init apparmor_init_sysctl(void) 17388c2ecf20Sopenharmony_ci{ 17398c2ecf20Sopenharmony_ci return register_sysctl_paths(apparmor_sysctl_path, 17408c2ecf20Sopenharmony_ci apparmor_sysctl_table) ? 0 : -ENOMEM; 17418c2ecf20Sopenharmony_ci} 17428c2ecf20Sopenharmony_ci#else 17438c2ecf20Sopenharmony_cistatic inline int apparmor_init_sysctl(void) 17448c2ecf20Sopenharmony_ci{ 17458c2ecf20Sopenharmony_ci return 0; 17468c2ecf20Sopenharmony_ci} 17478c2ecf20Sopenharmony_ci#endif /* CONFIG_SYSCTL */ 17488c2ecf20Sopenharmony_ci 17498c2ecf20Sopenharmony_ci#if defined(CONFIG_NETFILTER) && defined(CONFIG_NETWORK_SECMARK) 17508c2ecf20Sopenharmony_cistatic unsigned int apparmor_ip_postroute(void *priv, 17518c2ecf20Sopenharmony_ci struct sk_buff *skb, 17528c2ecf20Sopenharmony_ci const struct nf_hook_state *state) 17538c2ecf20Sopenharmony_ci{ 17548c2ecf20Sopenharmony_ci struct aa_sk_ctx *ctx; 17558c2ecf20Sopenharmony_ci struct sock *sk; 17568c2ecf20Sopenharmony_ci 17578c2ecf20Sopenharmony_ci if (!skb->secmark) 17588c2ecf20Sopenharmony_ci return NF_ACCEPT; 17598c2ecf20Sopenharmony_ci 17608c2ecf20Sopenharmony_ci sk = skb_to_full_sk(skb); 17618c2ecf20Sopenharmony_ci if (sk == NULL) 17628c2ecf20Sopenharmony_ci return NF_ACCEPT; 17638c2ecf20Sopenharmony_ci 17648c2ecf20Sopenharmony_ci ctx = SK_CTX(sk); 17658c2ecf20Sopenharmony_ci if (!apparmor_secmark_check(ctx->label, OP_SENDMSG, AA_MAY_SEND, 17668c2ecf20Sopenharmony_ci skb->secmark, sk)) 17678c2ecf20Sopenharmony_ci return NF_ACCEPT; 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci return NF_DROP_ERR(-ECONNREFUSED); 17708c2ecf20Sopenharmony_ci 17718c2ecf20Sopenharmony_ci} 17728c2ecf20Sopenharmony_ci 17738c2ecf20Sopenharmony_cistatic unsigned int apparmor_ipv4_postroute(void *priv, 17748c2ecf20Sopenharmony_ci struct sk_buff *skb, 17758c2ecf20Sopenharmony_ci const struct nf_hook_state *state) 17768c2ecf20Sopenharmony_ci{ 17778c2ecf20Sopenharmony_ci return apparmor_ip_postroute(priv, skb, state); 17788c2ecf20Sopenharmony_ci} 17798c2ecf20Sopenharmony_ci 17808c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6) 17818c2ecf20Sopenharmony_cistatic unsigned int apparmor_ipv6_postroute(void *priv, 17828c2ecf20Sopenharmony_ci struct sk_buff *skb, 17838c2ecf20Sopenharmony_ci const struct nf_hook_state *state) 17848c2ecf20Sopenharmony_ci{ 17858c2ecf20Sopenharmony_ci return apparmor_ip_postroute(priv, skb, state); 17868c2ecf20Sopenharmony_ci} 17878c2ecf20Sopenharmony_ci#endif 17888c2ecf20Sopenharmony_ci 17898c2ecf20Sopenharmony_cistatic const struct nf_hook_ops apparmor_nf_ops[] = { 17908c2ecf20Sopenharmony_ci { 17918c2ecf20Sopenharmony_ci .hook = apparmor_ipv4_postroute, 17928c2ecf20Sopenharmony_ci .pf = NFPROTO_IPV4, 17938c2ecf20Sopenharmony_ci .hooknum = NF_INET_POST_ROUTING, 17948c2ecf20Sopenharmony_ci .priority = NF_IP_PRI_SELINUX_FIRST, 17958c2ecf20Sopenharmony_ci }, 17968c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_IPV6) 17978c2ecf20Sopenharmony_ci { 17988c2ecf20Sopenharmony_ci .hook = apparmor_ipv6_postroute, 17998c2ecf20Sopenharmony_ci .pf = NFPROTO_IPV6, 18008c2ecf20Sopenharmony_ci .hooknum = NF_INET_POST_ROUTING, 18018c2ecf20Sopenharmony_ci .priority = NF_IP6_PRI_SELINUX_FIRST, 18028c2ecf20Sopenharmony_ci }, 18038c2ecf20Sopenharmony_ci#endif 18048c2ecf20Sopenharmony_ci}; 18058c2ecf20Sopenharmony_ci 18068c2ecf20Sopenharmony_cistatic int __net_init apparmor_nf_register(struct net *net) 18078c2ecf20Sopenharmony_ci{ 18088c2ecf20Sopenharmony_ci int ret; 18098c2ecf20Sopenharmony_ci 18108c2ecf20Sopenharmony_ci ret = nf_register_net_hooks(net, apparmor_nf_ops, 18118c2ecf20Sopenharmony_ci ARRAY_SIZE(apparmor_nf_ops)); 18128c2ecf20Sopenharmony_ci return ret; 18138c2ecf20Sopenharmony_ci} 18148c2ecf20Sopenharmony_ci 18158c2ecf20Sopenharmony_cistatic void __net_exit apparmor_nf_unregister(struct net *net) 18168c2ecf20Sopenharmony_ci{ 18178c2ecf20Sopenharmony_ci nf_unregister_net_hooks(net, apparmor_nf_ops, 18188c2ecf20Sopenharmony_ci ARRAY_SIZE(apparmor_nf_ops)); 18198c2ecf20Sopenharmony_ci} 18208c2ecf20Sopenharmony_ci 18218c2ecf20Sopenharmony_cistatic struct pernet_operations apparmor_net_ops = { 18228c2ecf20Sopenharmony_ci .init = apparmor_nf_register, 18238c2ecf20Sopenharmony_ci .exit = apparmor_nf_unregister, 18248c2ecf20Sopenharmony_ci}; 18258c2ecf20Sopenharmony_ci 18268c2ecf20Sopenharmony_cistatic int __init apparmor_nf_ip_init(void) 18278c2ecf20Sopenharmony_ci{ 18288c2ecf20Sopenharmony_ci int err; 18298c2ecf20Sopenharmony_ci 18308c2ecf20Sopenharmony_ci if (!apparmor_enabled) 18318c2ecf20Sopenharmony_ci return 0; 18328c2ecf20Sopenharmony_ci 18338c2ecf20Sopenharmony_ci err = register_pernet_subsys(&apparmor_net_ops); 18348c2ecf20Sopenharmony_ci if (err) 18358c2ecf20Sopenharmony_ci panic("Apparmor: register_pernet_subsys: error %d\n", err); 18368c2ecf20Sopenharmony_ci 18378c2ecf20Sopenharmony_ci return 0; 18388c2ecf20Sopenharmony_ci} 18398c2ecf20Sopenharmony_ci__initcall(apparmor_nf_ip_init); 18408c2ecf20Sopenharmony_ci#endif 18418c2ecf20Sopenharmony_ci 18428c2ecf20Sopenharmony_cistatic int __init apparmor_init(void) 18438c2ecf20Sopenharmony_ci{ 18448c2ecf20Sopenharmony_ci int error; 18458c2ecf20Sopenharmony_ci 18468c2ecf20Sopenharmony_ci aa_secids_init(); 18478c2ecf20Sopenharmony_ci 18488c2ecf20Sopenharmony_ci error = aa_setup_dfa_engine(); 18498c2ecf20Sopenharmony_ci if (error) { 18508c2ecf20Sopenharmony_ci AA_ERROR("Unable to setup dfa engine\n"); 18518c2ecf20Sopenharmony_ci goto alloc_out; 18528c2ecf20Sopenharmony_ci } 18538c2ecf20Sopenharmony_ci 18548c2ecf20Sopenharmony_ci error = aa_alloc_root_ns(); 18558c2ecf20Sopenharmony_ci if (error) { 18568c2ecf20Sopenharmony_ci AA_ERROR("Unable to allocate default profile namespace\n"); 18578c2ecf20Sopenharmony_ci goto alloc_out; 18588c2ecf20Sopenharmony_ci } 18598c2ecf20Sopenharmony_ci 18608c2ecf20Sopenharmony_ci error = apparmor_init_sysctl(); 18618c2ecf20Sopenharmony_ci if (error) { 18628c2ecf20Sopenharmony_ci AA_ERROR("Unable to register sysctls\n"); 18638c2ecf20Sopenharmony_ci goto alloc_out; 18648c2ecf20Sopenharmony_ci 18658c2ecf20Sopenharmony_ci } 18668c2ecf20Sopenharmony_ci 18678c2ecf20Sopenharmony_ci error = alloc_buffers(); 18688c2ecf20Sopenharmony_ci if (error) { 18698c2ecf20Sopenharmony_ci AA_ERROR("Unable to allocate work buffers\n"); 18708c2ecf20Sopenharmony_ci goto alloc_out; 18718c2ecf20Sopenharmony_ci } 18728c2ecf20Sopenharmony_ci 18738c2ecf20Sopenharmony_ci error = set_init_ctx(); 18748c2ecf20Sopenharmony_ci if (error) { 18758c2ecf20Sopenharmony_ci AA_ERROR("Failed to set context on init task\n"); 18768c2ecf20Sopenharmony_ci aa_free_root_ns(); 18778c2ecf20Sopenharmony_ci goto buffers_out; 18788c2ecf20Sopenharmony_ci } 18798c2ecf20Sopenharmony_ci security_add_hooks(apparmor_hooks, ARRAY_SIZE(apparmor_hooks), 18808c2ecf20Sopenharmony_ci "apparmor"); 18818c2ecf20Sopenharmony_ci 18828c2ecf20Sopenharmony_ci /* Report that AppArmor successfully initialized */ 18838c2ecf20Sopenharmony_ci apparmor_initialized = 1; 18848c2ecf20Sopenharmony_ci if (aa_g_profile_mode == APPARMOR_COMPLAIN) 18858c2ecf20Sopenharmony_ci aa_info_message("AppArmor initialized: complain mode enabled"); 18868c2ecf20Sopenharmony_ci else if (aa_g_profile_mode == APPARMOR_KILL) 18878c2ecf20Sopenharmony_ci aa_info_message("AppArmor initialized: kill mode enabled"); 18888c2ecf20Sopenharmony_ci else 18898c2ecf20Sopenharmony_ci aa_info_message("AppArmor initialized"); 18908c2ecf20Sopenharmony_ci 18918c2ecf20Sopenharmony_ci return error; 18928c2ecf20Sopenharmony_ci 18938c2ecf20Sopenharmony_cibuffers_out: 18948c2ecf20Sopenharmony_ci destroy_buffers(); 18958c2ecf20Sopenharmony_cialloc_out: 18968c2ecf20Sopenharmony_ci aa_destroy_aafs(); 18978c2ecf20Sopenharmony_ci aa_teardown_dfa_engine(); 18988c2ecf20Sopenharmony_ci 18998c2ecf20Sopenharmony_ci apparmor_enabled = false; 19008c2ecf20Sopenharmony_ci return error; 19018c2ecf20Sopenharmony_ci} 19028c2ecf20Sopenharmony_ci 19038c2ecf20Sopenharmony_ciDEFINE_LSM(apparmor) = { 19048c2ecf20Sopenharmony_ci .name = "apparmor", 19058c2ecf20Sopenharmony_ci .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE, 19068c2ecf20Sopenharmony_ci .enabled = &apparmor_enabled, 19078c2ecf20Sopenharmony_ci .blobs = &apparmor_blob_sizes, 19088c2ecf20Sopenharmony_ci .init = apparmor_init, 19098c2ecf20Sopenharmony_ci}; 1910