| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com> |
|---|
| 3 | | - * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 5 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 6 | | - * the Free Software Foundation, version 2. |
|---|
| 7 | 4 | * |
|---|
| 8 | 5 | * Authors: |
|---|
| 9 | 6 | * Casey Schaufler <casey@schaufler-ca.com> |
|---|
| .. | .. |
|---|
| 13 | 10 | * |
|---|
| 14 | 11 | * Karl MacMillan <kmacmillan@tresys.com> |
|---|
| 15 | 12 | * James Morris <jmorris@redhat.com> |
|---|
| 16 | | - * |
|---|
| 17 | 13 | */ |
|---|
| 18 | 14 | |
|---|
| 19 | 15 | #include <linux/kernel.h> |
|---|
| .. | .. |
|---|
| 27 | 23 | #include <linux/ctype.h> |
|---|
| 28 | 24 | #include <linux/audit.h> |
|---|
| 29 | 25 | #include <linux/magic.h> |
|---|
| 26 | +#include <linux/fs_context.h> |
|---|
| 30 | 27 | #include "smack.h" |
|---|
| 31 | 28 | |
|---|
| 32 | 29 | #define BEBITS (sizeof(__be32) * 8) |
|---|
| .. | .. |
|---|
| 67 | 64 | /* |
|---|
| 68 | 65 | * List locks |
|---|
| 69 | 66 | */ |
|---|
| 70 | | -static DEFINE_MUTEX(smack_master_list_lock); |
|---|
| 71 | 67 | static DEFINE_MUTEX(smack_cipso_lock); |
|---|
| 72 | 68 | static DEFINE_MUTEX(smack_ambient_lock); |
|---|
| 73 | 69 | static DEFINE_MUTEX(smk_net4addr_lock); |
|---|
| .. | .. |
|---|
| 134 | 130 | |
|---|
| 135 | 131 | /* |
|---|
| 136 | 132 | * Rule lists are maintained for each label. |
|---|
| 137 | | - * This master list is just for reading /smack/load and /smack/load2. |
|---|
| 138 | 133 | */ |
|---|
| 139 | | -struct smack_master_list { |
|---|
| 140 | | - struct list_head list; |
|---|
| 141 | | - struct smack_rule *smk_rule; |
|---|
| 142 | | -}; |
|---|
| 143 | | - |
|---|
| 144 | | -static LIST_HEAD(smack_rule_list); |
|---|
| 145 | | - |
|---|
| 146 | 134 | struct smack_parsed_rule { |
|---|
| 147 | 135 | struct smack_known *smk_subject; |
|---|
| 148 | 136 | struct smack_known *smk_object; |
|---|
| .. | .. |
|---|
| 211 | 199 | * @srp: the rule to add or replace |
|---|
| 212 | 200 | * @rule_list: the list of rules |
|---|
| 213 | 201 | * @rule_lock: the rule list lock |
|---|
| 214 | | - * @global: if non-zero, indicates a global rule |
|---|
| 215 | 202 | * |
|---|
| 216 | 203 | * Looks through the current subject/object/access list for |
|---|
| 217 | 204 | * the subject/object pair and replaces the access that was |
|---|
| .. | .. |
|---|
| 223 | 210 | */ |
|---|
| 224 | 211 | static int smk_set_access(struct smack_parsed_rule *srp, |
|---|
| 225 | 212 | struct list_head *rule_list, |
|---|
| 226 | | - struct mutex *rule_lock, int global) |
|---|
| 213 | + struct mutex *rule_lock) |
|---|
| 227 | 214 | { |
|---|
| 228 | 215 | struct smack_rule *sp; |
|---|
| 229 | | - struct smack_master_list *smlp; |
|---|
| 230 | 216 | int found = 0; |
|---|
| 231 | 217 | int rc = 0; |
|---|
| 232 | 218 | |
|---|
| .. | .. |
|---|
| 247 | 233 | } |
|---|
| 248 | 234 | |
|---|
| 249 | 235 | if (found == 0) { |
|---|
| 250 | | - sp = kzalloc(sizeof(*sp), GFP_KERNEL); |
|---|
| 236 | + sp = kmem_cache_zalloc(smack_rule_cache, GFP_KERNEL); |
|---|
| 251 | 237 | if (sp == NULL) { |
|---|
| 252 | 238 | rc = -ENOMEM; |
|---|
| 253 | 239 | goto out; |
|---|
| .. | .. |
|---|
| 258 | 244 | sp->smk_access = srp->smk_access1 & ~srp->smk_access2; |
|---|
| 259 | 245 | |
|---|
| 260 | 246 | list_add_rcu(&sp->list, rule_list); |
|---|
| 261 | | - /* |
|---|
| 262 | | - * If this is a global as opposed to self and a new rule |
|---|
| 263 | | - * it needs to get added for reporting. |
|---|
| 264 | | - */ |
|---|
| 265 | | - if (global) { |
|---|
| 266 | | - mutex_unlock(rule_lock); |
|---|
| 267 | | - smlp = kzalloc(sizeof(*smlp), GFP_KERNEL); |
|---|
| 268 | | - if (smlp != NULL) { |
|---|
| 269 | | - smlp->smk_rule = sp; |
|---|
| 270 | | - mutex_lock(&smack_master_list_lock); |
|---|
| 271 | | - list_add_rcu(&smlp->list, &smack_rule_list); |
|---|
| 272 | | - mutex_unlock(&smack_master_list_lock); |
|---|
| 273 | | - } else |
|---|
| 274 | | - rc = -ENOMEM; |
|---|
| 275 | | - return rc; |
|---|
| 276 | | - } |
|---|
| 277 | 247 | } |
|---|
| 278 | 248 | |
|---|
| 279 | 249 | out: |
|---|
| .. | .. |
|---|
| 540 | 510 | |
|---|
| 541 | 511 | if (rule_list == NULL) |
|---|
| 542 | 512 | rc = smk_set_access(&rule, &rule.smk_subject->smk_rules, |
|---|
| 543 | | - &rule.smk_subject->smk_rules_lock, 1); |
|---|
| 513 | + &rule.smk_subject->smk_rules_lock); |
|---|
| 544 | 514 | else |
|---|
| 545 | | - rc = smk_set_access(&rule, rule_list, rule_lock, 0); |
|---|
| 515 | + rc = smk_set_access(&rule, rule_list, rule_lock); |
|---|
| 546 | 516 | |
|---|
| 547 | 517 | if (rc) |
|---|
| 548 | 518 | goto out; |
|---|
| .. | .. |
|---|
| 636 | 606 | |
|---|
| 637 | 607 | static void *load2_seq_start(struct seq_file *s, loff_t *pos) |
|---|
| 638 | 608 | { |
|---|
| 639 | | - return smk_seq_start(s, pos, &smack_rule_list); |
|---|
| 609 | + return smk_seq_start(s, pos, &smack_known_list); |
|---|
| 640 | 610 | } |
|---|
| 641 | 611 | |
|---|
| 642 | 612 | static void *load2_seq_next(struct seq_file *s, void *v, loff_t *pos) |
|---|
| 643 | 613 | { |
|---|
| 644 | | - return smk_seq_next(s, v, pos, &smack_rule_list); |
|---|
| 614 | + return smk_seq_next(s, v, pos, &smack_known_list); |
|---|
| 645 | 615 | } |
|---|
| 646 | 616 | |
|---|
| 647 | 617 | static int load_seq_show(struct seq_file *s, void *v) |
|---|
| 648 | 618 | { |
|---|
| 649 | 619 | struct list_head *list = v; |
|---|
| 650 | | - struct smack_master_list *smlp = |
|---|
| 651 | | - list_entry_rcu(list, struct smack_master_list, list); |
|---|
| 620 | + struct smack_rule *srp; |
|---|
| 621 | + struct smack_known *skp = |
|---|
| 622 | + list_entry_rcu(list, struct smack_known, list); |
|---|
| 652 | 623 | |
|---|
| 653 | | - smk_rule_show(s, smlp->smk_rule, SMK_LABELLEN); |
|---|
| 624 | + list_for_each_entry_rcu(srp, &skp->smk_rules, list) |
|---|
| 625 | + smk_rule_show(s, srp, SMK_LABELLEN); |
|---|
| 654 | 626 | |
|---|
| 655 | 627 | return 0; |
|---|
| 656 | 628 | } |
|---|
| .. | .. |
|---|
| 923 | 895 | } |
|---|
| 924 | 896 | |
|---|
| 925 | 897 | ret = sscanf(rule, "%d", &catlen); |
|---|
| 926 | | - if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM) |
|---|
| 898 | + if (ret != 1 || catlen < 0 || catlen > SMACK_CIPSO_MAXCATNUM) |
|---|
| 927 | 899 | goto out; |
|---|
| 928 | 900 | |
|---|
| 929 | 901 | if (format == SMK_FIXED24_FMT && |
|---|
| .. | .. |
|---|
| 953 | 925 | synchronize_rcu(); |
|---|
| 954 | 926 | netlbl_catmap_free(old_cat); |
|---|
| 955 | 927 | rc = count; |
|---|
| 928 | + /* |
|---|
| 929 | + * This mapping may have been cached, so clear the cache. |
|---|
| 930 | + */ |
|---|
| 931 | + netlbl_cache_invalidate(); |
|---|
| 956 | 932 | } |
|---|
| 957 | 933 | |
|---|
| 958 | 934 | out: |
|---|
| .. | .. |
|---|
| 2235 | 2211 | |
|---|
| 2236 | 2212 | static void *load_self_seq_start(struct seq_file *s, loff_t *pos) |
|---|
| 2237 | 2213 | { |
|---|
| 2238 | | - struct task_smack *tsp = current_security(); |
|---|
| 2214 | + struct task_smack *tsp = smack_cred(current_cred()); |
|---|
| 2239 | 2215 | |
|---|
| 2240 | 2216 | return smk_seq_start(s, pos, &tsp->smk_rules); |
|---|
| 2241 | 2217 | } |
|---|
| 2242 | 2218 | |
|---|
| 2243 | 2219 | static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos) |
|---|
| 2244 | 2220 | { |
|---|
| 2245 | | - struct task_smack *tsp = current_security(); |
|---|
| 2221 | + struct task_smack *tsp = smack_cred(current_cred()); |
|---|
| 2246 | 2222 | |
|---|
| 2247 | 2223 | return smk_seq_next(s, v, pos, &tsp->smk_rules); |
|---|
| 2248 | 2224 | } |
|---|
| .. | .. |
|---|
| 2289 | 2265 | static ssize_t smk_write_load_self(struct file *file, const char __user *buf, |
|---|
| 2290 | 2266 | size_t count, loff_t *ppos) |
|---|
| 2291 | 2267 | { |
|---|
| 2292 | | - struct task_smack *tsp = current_security(); |
|---|
| 2268 | + struct task_smack *tsp = smack_cred(current_cred()); |
|---|
| 2293 | 2269 | |
|---|
| 2294 | 2270 | return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules, |
|---|
| 2295 | 2271 | &tsp->smk_rules_lock, SMK_FIXED24_FMT); |
|---|
| .. | .. |
|---|
| 2379 | 2355 | static int load2_seq_show(struct seq_file *s, void *v) |
|---|
| 2380 | 2356 | { |
|---|
| 2381 | 2357 | struct list_head *list = v; |
|---|
| 2382 | | - struct smack_master_list *smlp = |
|---|
| 2383 | | - list_entry_rcu(list, struct smack_master_list, list); |
|---|
| 2358 | + struct smack_rule *srp; |
|---|
| 2359 | + struct smack_known *skp = |
|---|
| 2360 | + list_entry_rcu(list, struct smack_known, list); |
|---|
| 2384 | 2361 | |
|---|
| 2385 | | - smk_rule_show(s, smlp->smk_rule, SMK_LONGLABEL); |
|---|
| 2362 | + list_for_each_entry_rcu(srp, &skp->smk_rules, list) |
|---|
| 2363 | + smk_rule_show(s, srp, SMK_LONGLABEL); |
|---|
| 2386 | 2364 | |
|---|
| 2387 | 2365 | return 0; |
|---|
| 2388 | 2366 | } |
|---|
| .. | .. |
|---|
| 2441 | 2419 | |
|---|
| 2442 | 2420 | static void *load_self2_seq_start(struct seq_file *s, loff_t *pos) |
|---|
| 2443 | 2421 | { |
|---|
| 2444 | | - struct task_smack *tsp = current_security(); |
|---|
| 2422 | + struct task_smack *tsp = smack_cred(current_cred()); |
|---|
| 2445 | 2423 | |
|---|
| 2446 | 2424 | return smk_seq_start(s, pos, &tsp->smk_rules); |
|---|
| 2447 | 2425 | } |
|---|
| 2448 | 2426 | |
|---|
| 2449 | 2427 | static void *load_self2_seq_next(struct seq_file *s, void *v, loff_t *pos) |
|---|
| 2450 | 2428 | { |
|---|
| 2451 | | - struct task_smack *tsp = current_security(); |
|---|
| 2429 | + struct task_smack *tsp = smack_cred(current_cred()); |
|---|
| 2452 | 2430 | |
|---|
| 2453 | 2431 | return smk_seq_next(s, v, pos, &tsp->smk_rules); |
|---|
| 2454 | 2432 | } |
|---|
| .. | .. |
|---|
| 2494 | 2472 | static ssize_t smk_write_load_self2(struct file *file, const char __user *buf, |
|---|
| 2495 | 2473 | size_t count, loff_t *ppos) |
|---|
| 2496 | 2474 | { |
|---|
| 2497 | | - struct task_smack *tsp = current_security(); |
|---|
| 2475 | + struct task_smack *tsp = smack_cred(current_cred()); |
|---|
| 2498 | 2476 | |
|---|
| 2499 | 2477 | return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules, |
|---|
| 2500 | 2478 | &tsp->smk_rules_lock, SMK_LONG_FMT); |
|---|
| .. | .. |
|---|
| 2712 | 2690 | |
|---|
| 2713 | 2691 | static void *relabel_self_seq_start(struct seq_file *s, loff_t *pos) |
|---|
| 2714 | 2692 | { |
|---|
| 2715 | | - struct task_smack *tsp = current_security(); |
|---|
| 2693 | + struct task_smack *tsp = smack_cred(current_cred()); |
|---|
| 2716 | 2694 | |
|---|
| 2717 | 2695 | return smk_seq_start(s, pos, &tsp->smk_relabel); |
|---|
| 2718 | 2696 | } |
|---|
| 2719 | 2697 | |
|---|
| 2720 | 2698 | static void *relabel_self_seq_next(struct seq_file *s, void *v, loff_t *pos) |
|---|
| 2721 | 2699 | { |
|---|
| 2722 | | - struct task_smack *tsp = current_security(); |
|---|
| 2700 | + struct task_smack *tsp = smack_cred(current_cred()); |
|---|
| 2723 | 2701 | |
|---|
| 2724 | 2702 | return smk_seq_next(s, v, pos, &tsp->smk_relabel); |
|---|
| 2725 | 2703 | } |
|---|
| .. | .. |
|---|
| 2802 | 2780 | rc = -ENOMEM; |
|---|
| 2803 | 2781 | goto out; |
|---|
| 2804 | 2782 | } |
|---|
| 2805 | | - tsp = new->security; |
|---|
| 2783 | + tsp = smack_cred(new); |
|---|
| 2806 | 2784 | smk_destroy_label_list(&tsp->smk_relabel); |
|---|
| 2807 | 2785 | list_splice(&list_tmp, &tsp->smk_relabel); |
|---|
| 2808 | 2786 | commit_creds(new); |
|---|
| .. | .. |
|---|
| 2886 | 2864 | /** |
|---|
| 2887 | 2865 | * smk_fill_super - fill the smackfs superblock |
|---|
| 2888 | 2866 | * @sb: the empty superblock |
|---|
| 2889 | | - * @data: unused |
|---|
| 2890 | | - * @silent: unused |
|---|
| 2867 | + * @fc: unused |
|---|
| 2891 | 2868 | * |
|---|
| 2892 | 2869 | * Fill in the well known entries for the smack filesystem |
|---|
| 2893 | 2870 | * |
|---|
| 2894 | 2871 | * Returns 0 on success, an error code on failure |
|---|
| 2895 | 2872 | */ |
|---|
| 2896 | | -static int smk_fill_super(struct super_block *sb, void *data, int silent) |
|---|
| 2873 | +static int smk_fill_super(struct super_block *sb, struct fs_context *fc) |
|---|
| 2897 | 2874 | { |
|---|
| 2898 | 2875 | int rc; |
|---|
| 2899 | | - struct inode *root_inode; |
|---|
| 2900 | 2876 | |
|---|
| 2901 | 2877 | static const struct tree_descr smack_files[] = { |
|---|
| 2902 | 2878 | [SMK_LOAD] = { |
|---|
| .. | .. |
|---|
| 2960 | 2936 | return rc; |
|---|
| 2961 | 2937 | } |
|---|
| 2962 | 2938 | |
|---|
| 2963 | | - root_inode = d_inode(sb->s_root); |
|---|
| 2964 | | - |
|---|
| 2965 | 2939 | return 0; |
|---|
| 2966 | 2940 | } |
|---|
| 2967 | 2941 | |
|---|
| 2968 | 2942 | /** |
|---|
| 2969 | | - * smk_mount - get the smackfs superblock |
|---|
| 2970 | | - * @fs_type: passed along without comment |
|---|
| 2971 | | - * @flags: passed along without comment |
|---|
| 2972 | | - * @dev_name: passed along without comment |
|---|
| 2973 | | - * @data: passed along without comment |
|---|
| 2943 | + * smk_get_tree - get the smackfs superblock |
|---|
| 2944 | + * @fc: The mount context, including any options |
|---|
| 2974 | 2945 | * |
|---|
| 2975 | 2946 | * Just passes everything along. |
|---|
| 2976 | 2947 | * |
|---|
| 2977 | 2948 | * Returns what the lower level code does. |
|---|
| 2978 | 2949 | */ |
|---|
| 2979 | | -static struct dentry *smk_mount(struct file_system_type *fs_type, |
|---|
| 2980 | | - int flags, const char *dev_name, void *data) |
|---|
| 2950 | +static int smk_get_tree(struct fs_context *fc) |
|---|
| 2981 | 2951 | { |
|---|
| 2982 | | - return mount_single(fs_type, flags, data, smk_fill_super); |
|---|
| 2952 | + return get_tree_single(fc, smk_fill_super); |
|---|
| 2953 | +} |
|---|
| 2954 | + |
|---|
| 2955 | +static const struct fs_context_operations smk_context_ops = { |
|---|
| 2956 | + .get_tree = smk_get_tree, |
|---|
| 2957 | +}; |
|---|
| 2958 | + |
|---|
| 2959 | +/** |
|---|
| 2960 | + * smk_init_fs_context - Initialise a filesystem context for smackfs |
|---|
| 2961 | + * @fc: The blank mount context |
|---|
| 2962 | + */ |
|---|
| 2963 | +static int smk_init_fs_context(struct fs_context *fc) |
|---|
| 2964 | +{ |
|---|
| 2965 | + fc->ops = &smk_context_ops; |
|---|
| 2966 | + return 0; |
|---|
| 2983 | 2967 | } |
|---|
| 2984 | 2968 | |
|---|
| 2985 | 2969 | static struct file_system_type smk_fs_type = { |
|---|
| 2986 | 2970 | .name = "smackfs", |
|---|
| 2987 | | - .mount = smk_mount, |
|---|
| 2971 | + .init_fs_context = smk_init_fs_context, |
|---|
| 2988 | 2972 | .kill_sb = kill_litter_super, |
|---|
| 2989 | 2973 | }; |
|---|
| 2990 | 2974 | |
|---|
| 2991 | 2975 | static struct vfsmount *smackfs_mount; |
|---|
| 2992 | | - |
|---|
| 2993 | | -static int __init smk_preset_netlabel(struct smack_known *skp) |
|---|
| 2994 | | -{ |
|---|
| 2995 | | - skp->smk_netlabel.domain = skp->smk_known; |
|---|
| 2996 | | - skp->smk_netlabel.flags = |
|---|
| 2997 | | - NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL; |
|---|
| 2998 | | - return smk_netlbl_mls(smack_cipso_direct, skp->smk_known, |
|---|
| 2999 | | - &skp->smk_netlabel, strlen(skp->smk_known)); |
|---|
| 3000 | | -} |
|---|
| 3001 | 2976 | |
|---|
| 3002 | 2977 | /** |
|---|
| 3003 | 2978 | * init_smk_fs - get the smackfs superblock |
|---|
| .. | .. |
|---|
| 3037 | 3012 | smk_cipso_doi(); |
|---|
| 3038 | 3013 | smk_unlbl_ambient(NULL); |
|---|
| 3039 | 3014 | |
|---|
| 3040 | | - rc = smk_preset_netlabel(&smack_known_floor); |
|---|
| 3015 | + rc = smack_populate_secattr(&smack_known_floor); |
|---|
| 3041 | 3016 | if (err == 0 && rc < 0) |
|---|
| 3042 | 3017 | err = rc; |
|---|
| 3043 | | - rc = smk_preset_netlabel(&smack_known_hat); |
|---|
| 3018 | + rc = smack_populate_secattr(&smack_known_hat); |
|---|
| 3044 | 3019 | if (err == 0 && rc < 0) |
|---|
| 3045 | 3020 | err = rc; |
|---|
| 3046 | | - rc = smk_preset_netlabel(&smack_known_huh); |
|---|
| 3021 | + rc = smack_populate_secattr(&smack_known_huh); |
|---|
| 3047 | 3022 | if (err == 0 && rc < 0) |
|---|
| 3048 | 3023 | err = rc; |
|---|
| 3049 | | - rc = smk_preset_netlabel(&smack_known_star); |
|---|
| 3024 | + rc = smack_populate_secattr(&smack_known_star); |
|---|
| 3050 | 3025 | if (err == 0 && rc < 0) |
|---|
| 3051 | 3026 | err = rc; |
|---|
| 3052 | | - rc = smk_preset_netlabel(&smack_known_web); |
|---|
| 3027 | + rc = smack_populate_secattr(&smack_known_web); |
|---|
| 3053 | 3028 | if (err == 0 && rc < 0) |
|---|
| 3054 | 3029 | err = rc; |
|---|
| 3055 | 3030 | |
|---|