| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Simplified MAC Kernel (smack) security module |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 12 | 13 | * Paul Moore <paul@paul-moore.com> |
|---|
| 13 | 14 | * Copyright (C) 2010 Nokia Corporation |
|---|
| 14 | 15 | * Copyright (C) 2011 Intel Corporation. |
|---|
| 15 | | - * |
|---|
| 16 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 17 | | - * it under the terms of the GNU General Public License version 2, |
|---|
| 18 | | - * as published by the Free Software Foundation. |
|---|
| 19 | 16 | */ |
|---|
| 20 | 17 | |
|---|
| 21 | 18 | #include <linux/xattr.h> |
|---|
| .. | .. |
|---|
| 31 | 28 | #include <linux/icmpv6.h> |
|---|
| 32 | 29 | #include <linux/slab.h> |
|---|
| 33 | 30 | #include <linux/mutex.h> |
|---|
| 34 | | -#include <linux/pipe_fs_i.h> |
|---|
| 35 | 31 | #include <net/cipso_ipv4.h> |
|---|
| 36 | 32 | #include <net/ip.h> |
|---|
| 37 | 33 | #include <net/ipv6.h> |
|---|
| .. | .. |
|---|
| 43 | 39 | #include <linux/shm.h> |
|---|
| 44 | 40 | #include <linux/binfmts.h> |
|---|
| 45 | 41 | #include <linux/parser.h> |
|---|
| 42 | +#include <linux/fs_context.h> |
|---|
| 43 | +#include <linux/fs_parser.h> |
|---|
| 44 | +#include <linux/watch_queue.h> |
|---|
| 46 | 45 | #include "smack.h" |
|---|
| 47 | 46 | |
|---|
| 48 | 47 | #define TRANS_TRUE "TRUE" |
|---|
| .. | .. |
|---|
| 52 | 51 | #define SMK_RECEIVING 1 |
|---|
| 53 | 52 | #define SMK_SENDING 2 |
|---|
| 54 | 53 | |
|---|
| 55 | | -#ifdef SMACK_IPV6_PORT_LABELING |
|---|
| 56 | | -DEFINE_MUTEX(smack_ipv6_lock); |
|---|
| 54 | +static DEFINE_MUTEX(smack_ipv6_lock); |
|---|
| 57 | 55 | static LIST_HEAD(smk_ipv6_port_list); |
|---|
| 58 | | -#endif |
|---|
| 59 | | -static struct kmem_cache *smack_inode_cache; |
|---|
| 56 | +struct kmem_cache *smack_rule_cache; |
|---|
| 60 | 57 | int smack_enabled; |
|---|
| 61 | 58 | |
|---|
| 62 | | -static const match_table_t smk_mount_tokens = { |
|---|
| 63 | | - {Opt_fsdefault, SMK_FSDEFAULT "%s"}, |
|---|
| 64 | | - {Opt_fsfloor, SMK_FSFLOOR "%s"}, |
|---|
| 65 | | - {Opt_fshat, SMK_FSHAT "%s"}, |
|---|
| 66 | | - {Opt_fsroot, SMK_FSROOT "%s"}, |
|---|
| 67 | | - {Opt_fstransmute, SMK_FSTRANS "%s"}, |
|---|
| 68 | | - {Opt_error, NULL}, |
|---|
| 59 | +#define A(s) {"smack"#s, sizeof("smack"#s) - 1, Opt_##s} |
|---|
| 60 | +static struct { |
|---|
| 61 | + const char *name; |
|---|
| 62 | + int len; |
|---|
| 63 | + int opt; |
|---|
| 64 | +} smk_mount_opts[] = { |
|---|
| 65 | + {"smackfsdef", sizeof("smackfsdef") - 1, Opt_fsdefault}, |
|---|
| 66 | + A(fsdefault), A(fsfloor), A(fshat), A(fsroot), A(fstransmute) |
|---|
| 69 | 67 | }; |
|---|
| 68 | +#undef A |
|---|
| 69 | + |
|---|
| 70 | +static int match_opt_prefix(char *s, int l, char **arg) |
|---|
| 71 | +{ |
|---|
| 72 | + int i; |
|---|
| 73 | + |
|---|
| 74 | + for (i = 0; i < ARRAY_SIZE(smk_mount_opts); i++) { |
|---|
| 75 | + size_t len = smk_mount_opts[i].len; |
|---|
| 76 | + if (len > l || memcmp(s, smk_mount_opts[i].name, len)) |
|---|
| 77 | + continue; |
|---|
| 78 | + if (len == l || s[len] != '=') |
|---|
| 79 | + continue; |
|---|
| 80 | + *arg = s + len + 1; |
|---|
| 81 | + return smk_mount_opts[i].opt; |
|---|
| 82 | + } |
|---|
| 83 | + return Opt_error; |
|---|
| 84 | +} |
|---|
| 70 | 85 | |
|---|
| 71 | 86 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP |
|---|
| 72 | 87 | static char *smk_bu_mess[] = { |
|---|
| .. | .. |
|---|
| 122 | 137 | static int smk_bu_current(char *note, struct smack_known *oskp, |
|---|
| 123 | 138 | int mode, int rc) |
|---|
| 124 | 139 | { |
|---|
| 125 | | - struct task_smack *tsp = current_security(); |
|---|
| 140 | + struct task_smack *tsp = smack_cred(current_cred()); |
|---|
| 126 | 141 | char acc[SMK_NUM_ACCESS_TYPE + 1]; |
|---|
| 127 | 142 | |
|---|
| 128 | 143 | if (rc <= 0) |
|---|
| .. | .. |
|---|
| 143 | 158 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP |
|---|
| 144 | 159 | static int smk_bu_task(struct task_struct *otp, int mode, int rc) |
|---|
| 145 | 160 | { |
|---|
| 146 | | - struct task_smack *tsp = current_security(); |
|---|
| 161 | + struct task_smack *tsp = smack_cred(current_cred()); |
|---|
| 147 | 162 | struct smack_known *smk_task = smk_of_task_struct(otp); |
|---|
| 148 | 163 | char acc[SMK_NUM_ACCESS_TYPE + 1]; |
|---|
| 149 | 164 | |
|---|
| .. | .. |
|---|
| 165 | 180 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP |
|---|
| 166 | 181 | static int smk_bu_inode(struct inode *inode, int mode, int rc) |
|---|
| 167 | 182 | { |
|---|
| 168 | | - struct task_smack *tsp = current_security(); |
|---|
| 169 | | - struct inode_smack *isp = inode->i_security; |
|---|
| 183 | + struct task_smack *tsp = smack_cred(current_cred()); |
|---|
| 184 | + struct inode_smack *isp = smack_inode(inode); |
|---|
| 170 | 185 | char acc[SMK_NUM_ACCESS_TYPE + 1]; |
|---|
| 171 | 186 | |
|---|
| 172 | 187 | if (isp->smk_flags & SMK_INODE_IMPURE) |
|---|
| .. | .. |
|---|
| 195 | 210 | #ifdef CONFIG_SECURITY_SMACK_BRINGUP |
|---|
| 196 | 211 | static int smk_bu_file(struct file *file, int mode, int rc) |
|---|
| 197 | 212 | { |
|---|
| 198 | | - struct task_smack *tsp = current_security(); |
|---|
| 213 | + struct task_smack *tsp = smack_cred(current_cred()); |
|---|
| 199 | 214 | struct smack_known *sskp = tsp->smk_task; |
|---|
| 200 | 215 | struct inode *inode = file_inode(file); |
|---|
| 201 | | - struct inode_smack *isp = inode->i_security; |
|---|
| 216 | + struct inode_smack *isp = smack_inode(inode); |
|---|
| 202 | 217 | char acc[SMK_NUM_ACCESS_TYPE + 1]; |
|---|
| 203 | 218 | |
|---|
| 204 | 219 | if (isp->smk_flags & SMK_INODE_IMPURE) |
|---|
| .. | .. |
|---|
| 225 | 240 | static int smk_bu_credfile(const struct cred *cred, struct file *file, |
|---|
| 226 | 241 | int mode, int rc) |
|---|
| 227 | 242 | { |
|---|
| 228 | | - struct task_smack *tsp = cred->security; |
|---|
| 243 | + struct task_smack *tsp = smack_cred(cred); |
|---|
| 229 | 244 | struct smack_known *sskp = tsp->smk_task; |
|---|
| 230 | 245 | struct inode *inode = file_inode(file); |
|---|
| 231 | | - struct inode_smack *isp = inode->i_security; |
|---|
| 246 | + struct inode_smack *isp = smack_inode(inode); |
|---|
| 232 | 247 | char acc[SMK_NUM_ACCESS_TYPE + 1]; |
|---|
| 233 | 248 | |
|---|
| 234 | 249 | if (isp->smk_flags & SMK_INODE_IMPURE) |
|---|
| .. | .. |
|---|
| 274 | 289 | if (buffer == NULL) |
|---|
| 275 | 290 | return ERR_PTR(-ENOMEM); |
|---|
| 276 | 291 | |
|---|
| 277 | | - rc = __vfs_getxattr(dp, ip, name, buffer, SMK_LONGLABEL); |
|---|
| 292 | + rc = __vfs_getxattr(dp, ip, name, buffer, SMK_LONGLABEL, |
|---|
| 293 | + XATTR_NOSECURITY); |
|---|
| 278 | 294 | if (rc < 0) |
|---|
| 279 | 295 | skp = ERR_PTR(rc); |
|---|
| 280 | 296 | else if (rc == 0) |
|---|
| .. | .. |
|---|
| 288 | 304 | } |
|---|
| 289 | 305 | |
|---|
| 290 | 306 | /** |
|---|
| 291 | | - * new_inode_smack - allocate an inode security blob |
|---|
| 307 | + * init_inode_smack - initialize an inode security blob |
|---|
| 308 | + * @inode: inode to extract the info from |
|---|
| 292 | 309 | * @skp: a pointer to the Smack label entry to use in the blob |
|---|
| 293 | 310 | * |
|---|
| 294 | | - * Returns the new blob or NULL if there's no memory available |
|---|
| 295 | 311 | */ |
|---|
| 296 | | -static struct inode_smack *new_inode_smack(struct smack_known *skp) |
|---|
| 312 | +static void init_inode_smack(struct inode *inode, struct smack_known *skp) |
|---|
| 297 | 313 | { |
|---|
| 298 | | - struct inode_smack *isp; |
|---|
| 299 | | - |
|---|
| 300 | | - isp = kmem_cache_zalloc(smack_inode_cache, GFP_NOFS); |
|---|
| 301 | | - if (isp == NULL) |
|---|
| 302 | | - return NULL; |
|---|
| 314 | + struct inode_smack *isp = smack_inode(inode); |
|---|
| 303 | 315 | |
|---|
| 304 | 316 | isp->smk_inode = skp; |
|---|
| 305 | 317 | isp->smk_flags = 0; |
|---|
| 306 | | - mutex_init(&isp->smk_lock); |
|---|
| 307 | | - |
|---|
| 308 | | - return isp; |
|---|
| 309 | 318 | } |
|---|
| 310 | 319 | |
|---|
| 311 | 320 | /** |
|---|
| 312 | | - * new_task_smack - allocate a task security blob |
|---|
| 321 | + * init_task_smack - initialize a task security blob |
|---|
| 322 | + * @tsp: blob to initialize |
|---|
| 313 | 323 | * @task: a pointer to the Smack label for the running task |
|---|
| 314 | 324 | * @forked: a pointer to the Smack label for the forked task |
|---|
| 315 | | - * @gfp: type of the memory for the allocation |
|---|
| 316 | 325 | * |
|---|
| 317 | | - * Returns the new blob or NULL if there's no memory available |
|---|
| 318 | 326 | */ |
|---|
| 319 | | -static struct task_smack *new_task_smack(struct smack_known *task, |
|---|
| 320 | | - struct smack_known *forked, gfp_t gfp) |
|---|
| 327 | +static void init_task_smack(struct task_smack *tsp, struct smack_known *task, |
|---|
| 328 | + struct smack_known *forked) |
|---|
| 321 | 329 | { |
|---|
| 322 | | - struct task_smack *tsp; |
|---|
| 323 | | - |
|---|
| 324 | | - tsp = kzalloc(sizeof(struct task_smack), gfp); |
|---|
| 325 | | - if (tsp == NULL) |
|---|
| 326 | | - return NULL; |
|---|
| 327 | | - |
|---|
| 328 | 330 | tsp->smk_task = task; |
|---|
| 329 | 331 | tsp->smk_forked = forked; |
|---|
| 330 | 332 | INIT_LIST_HEAD(&tsp->smk_rules); |
|---|
| 331 | 333 | INIT_LIST_HEAD(&tsp->smk_relabel); |
|---|
| 332 | 334 | mutex_init(&tsp->smk_rules_lock); |
|---|
| 333 | | - |
|---|
| 334 | | - return tsp; |
|---|
| 335 | 335 | } |
|---|
| 336 | 336 | |
|---|
| 337 | 337 | /** |
|---|
| .. | .. |
|---|
| 350 | 350 | int rc = 0; |
|---|
| 351 | 351 | |
|---|
| 352 | 352 | list_for_each_entry_rcu(orp, ohead, list) { |
|---|
| 353 | | - nrp = kzalloc(sizeof(struct smack_rule), gfp); |
|---|
| 353 | + nrp = kmem_cache_zalloc(smack_rule_cache, gfp); |
|---|
| 354 | 354 | if (nrp == NULL) { |
|---|
| 355 | 355 | rc = -ENOMEM; |
|---|
| 356 | 356 | break; |
|---|
| .. | .. |
|---|
| 431 | 431 | |
|---|
| 432 | 432 | rcu_read_lock(); |
|---|
| 433 | 433 | tracercred = __task_cred(tracer); |
|---|
| 434 | | - tsp = tracercred->security; |
|---|
| 434 | + tsp = smack_cred(tracercred); |
|---|
| 435 | 435 | tracer_known = smk_of_task(tsp); |
|---|
| 436 | 436 | |
|---|
| 437 | 437 | if ((mode & PTRACE_MODE_ATTACH) && |
|---|
| .. | .. |
|---|
| 498 | 498 | int rc; |
|---|
| 499 | 499 | struct smack_known *skp; |
|---|
| 500 | 500 | |
|---|
| 501 | | - skp = smk_of_task(current_security()); |
|---|
| 501 | + skp = smk_of_task(smack_cred(current_cred())); |
|---|
| 502 | 502 | |
|---|
| 503 | 503 | rc = smk_ptrace_rule_check(ptp, skp, PTRACE_MODE_ATTACH, __func__); |
|---|
| 504 | 504 | return rc; |
|---|
| .. | .. |
|---|
| 506 | 506 | |
|---|
| 507 | 507 | /** |
|---|
| 508 | 508 | * smack_syslog - Smack approval on syslog |
|---|
| 509 | | - * @type: message type |
|---|
| 509 | + * @typefrom_file: unused |
|---|
| 510 | 510 | * |
|---|
| 511 | 511 | * Returns 0 on success, error code otherwise. |
|---|
| 512 | 512 | */ |
|---|
| .. | .. |
|---|
| 523 | 523 | |
|---|
| 524 | 524 | return rc; |
|---|
| 525 | 525 | } |
|---|
| 526 | | - |
|---|
| 527 | 526 | |
|---|
| 528 | 527 | /* |
|---|
| 529 | 528 | * Superblock Hooks. |
|---|
| .. | .. |
|---|
| 567 | 566 | sb->s_security = NULL; |
|---|
| 568 | 567 | } |
|---|
| 569 | 568 | |
|---|
| 570 | | -/** |
|---|
| 571 | | - * smack_sb_copy_data - copy mount options data for processing |
|---|
| 572 | | - * @orig: where to start |
|---|
| 573 | | - * @smackopts: mount options string |
|---|
| 574 | | - * |
|---|
| 575 | | - * Returns 0 on success or -ENOMEM on error. |
|---|
| 576 | | - * |
|---|
| 577 | | - * Copy the Smack specific mount options out of the mount |
|---|
| 578 | | - * options list. |
|---|
| 579 | | - */ |
|---|
| 580 | | -static int smack_sb_copy_data(char *orig, char *smackopts) |
|---|
| 569 | +struct smack_mnt_opts { |
|---|
| 570 | + const char *fsdefault, *fsfloor, *fshat, *fsroot, *fstransmute; |
|---|
| 571 | +}; |
|---|
| 572 | + |
|---|
| 573 | +static void smack_free_mnt_opts(void *mnt_opts) |
|---|
| 581 | 574 | { |
|---|
| 582 | | - char *cp, *commap, *otheropts, *dp; |
|---|
| 583 | | - |
|---|
| 584 | | - otheropts = (char *)get_zeroed_page(GFP_KERNEL); |
|---|
| 585 | | - if (otheropts == NULL) |
|---|
| 586 | | - return -ENOMEM; |
|---|
| 587 | | - |
|---|
| 588 | | - for (cp = orig, commap = orig; commap != NULL; cp = commap + 1) { |
|---|
| 589 | | - if (strstr(cp, SMK_FSDEFAULT) == cp) |
|---|
| 590 | | - dp = smackopts; |
|---|
| 591 | | - else if (strstr(cp, SMK_FSFLOOR) == cp) |
|---|
| 592 | | - dp = smackopts; |
|---|
| 593 | | - else if (strstr(cp, SMK_FSHAT) == cp) |
|---|
| 594 | | - dp = smackopts; |
|---|
| 595 | | - else if (strstr(cp, SMK_FSROOT) == cp) |
|---|
| 596 | | - dp = smackopts; |
|---|
| 597 | | - else if (strstr(cp, SMK_FSTRANS) == cp) |
|---|
| 598 | | - dp = smackopts; |
|---|
| 599 | | - else |
|---|
| 600 | | - dp = otheropts; |
|---|
| 601 | | - |
|---|
| 602 | | - commap = strchr(cp, ','); |
|---|
| 603 | | - if (commap != NULL) |
|---|
| 604 | | - *commap = '\0'; |
|---|
| 605 | | - |
|---|
| 606 | | - if (*dp != '\0') |
|---|
| 607 | | - strcat(dp, ","); |
|---|
| 608 | | - strcat(dp, cp); |
|---|
| 609 | | - } |
|---|
| 610 | | - |
|---|
| 611 | | - strcpy(orig, otheropts); |
|---|
| 612 | | - free_page((unsigned long)otheropts); |
|---|
| 613 | | - |
|---|
| 614 | | - return 0; |
|---|
| 575 | + struct smack_mnt_opts *opts = mnt_opts; |
|---|
| 576 | + kfree(opts->fsdefault); |
|---|
| 577 | + kfree(opts->fsfloor); |
|---|
| 578 | + kfree(opts->fshat); |
|---|
| 579 | + kfree(opts->fsroot); |
|---|
| 580 | + kfree(opts->fstransmute); |
|---|
| 581 | + kfree(opts); |
|---|
| 615 | 582 | } |
|---|
| 616 | 583 | |
|---|
| 617 | | -/** |
|---|
| 618 | | - * smack_parse_opts_str - parse Smack specific mount options |
|---|
| 619 | | - * @options: mount options string |
|---|
| 620 | | - * @opts: where to store converted mount opts |
|---|
| 621 | | - * |
|---|
| 622 | | - * Returns 0 on success or -ENOMEM on error. |
|---|
| 623 | | - * |
|---|
| 624 | | - * converts Smack specific mount options to generic security option format |
|---|
| 625 | | - */ |
|---|
| 626 | | -static int smack_parse_opts_str(char *options, |
|---|
| 627 | | - struct security_mnt_opts *opts) |
|---|
| 584 | +static int smack_add_opt(int token, const char *s, void **mnt_opts) |
|---|
| 628 | 585 | { |
|---|
| 629 | | - char *p; |
|---|
| 630 | | - char *fsdefault = NULL; |
|---|
| 631 | | - char *fsfloor = NULL; |
|---|
| 632 | | - char *fshat = NULL; |
|---|
| 633 | | - char *fsroot = NULL; |
|---|
| 634 | | - char *fstransmute = NULL; |
|---|
| 635 | | - int rc = -ENOMEM; |
|---|
| 636 | | - int num_mnt_opts = 0; |
|---|
| 637 | | - int token; |
|---|
| 586 | + struct smack_mnt_opts *opts = *mnt_opts; |
|---|
| 638 | 587 | |
|---|
| 639 | | - opts->num_mnt_opts = 0; |
|---|
| 640 | | - |
|---|
| 641 | | - if (!options) |
|---|
| 642 | | - return 0; |
|---|
| 643 | | - |
|---|
| 644 | | - while ((p = strsep(&options, ",")) != NULL) { |
|---|
| 645 | | - substring_t args[MAX_OPT_ARGS]; |
|---|
| 646 | | - |
|---|
| 647 | | - if (!*p) |
|---|
| 648 | | - continue; |
|---|
| 649 | | - |
|---|
| 650 | | - token = match_token(p, smk_mount_tokens, args); |
|---|
| 651 | | - |
|---|
| 652 | | - switch (token) { |
|---|
| 653 | | - case Opt_fsdefault: |
|---|
| 654 | | - if (fsdefault) |
|---|
| 655 | | - goto out_opt_err; |
|---|
| 656 | | - fsdefault = match_strdup(&args[0]); |
|---|
| 657 | | - if (!fsdefault) |
|---|
| 658 | | - goto out_err; |
|---|
| 659 | | - break; |
|---|
| 660 | | - case Opt_fsfloor: |
|---|
| 661 | | - if (fsfloor) |
|---|
| 662 | | - goto out_opt_err; |
|---|
| 663 | | - fsfloor = match_strdup(&args[0]); |
|---|
| 664 | | - if (!fsfloor) |
|---|
| 665 | | - goto out_err; |
|---|
| 666 | | - break; |
|---|
| 667 | | - case Opt_fshat: |
|---|
| 668 | | - if (fshat) |
|---|
| 669 | | - goto out_opt_err; |
|---|
| 670 | | - fshat = match_strdup(&args[0]); |
|---|
| 671 | | - if (!fshat) |
|---|
| 672 | | - goto out_err; |
|---|
| 673 | | - break; |
|---|
| 674 | | - case Opt_fsroot: |
|---|
| 675 | | - if (fsroot) |
|---|
| 676 | | - goto out_opt_err; |
|---|
| 677 | | - fsroot = match_strdup(&args[0]); |
|---|
| 678 | | - if (!fsroot) |
|---|
| 679 | | - goto out_err; |
|---|
| 680 | | - break; |
|---|
| 681 | | - case Opt_fstransmute: |
|---|
| 682 | | - if (fstransmute) |
|---|
| 683 | | - goto out_opt_err; |
|---|
| 684 | | - fstransmute = match_strdup(&args[0]); |
|---|
| 685 | | - if (!fstransmute) |
|---|
| 686 | | - goto out_err; |
|---|
| 687 | | - break; |
|---|
| 688 | | - default: |
|---|
| 689 | | - rc = -EINVAL; |
|---|
| 690 | | - pr_warn("Smack: unknown mount option\n"); |
|---|
| 691 | | - goto out_err; |
|---|
| 692 | | - } |
|---|
| 588 | + if (!opts) { |
|---|
| 589 | + opts = kzalloc(sizeof(struct smack_mnt_opts), GFP_KERNEL); |
|---|
| 590 | + if (!opts) |
|---|
| 591 | + return -ENOMEM; |
|---|
| 592 | + *mnt_opts = opts; |
|---|
| 693 | 593 | } |
|---|
| 594 | + if (!s) |
|---|
| 595 | + return -ENOMEM; |
|---|
| 694 | 596 | |
|---|
| 695 | | - opts->mnt_opts = kcalloc(NUM_SMK_MNT_OPTS, sizeof(char *), GFP_KERNEL); |
|---|
| 696 | | - if (!opts->mnt_opts) |
|---|
| 697 | | - goto out_err; |
|---|
| 698 | | - |
|---|
| 699 | | - opts->mnt_opts_flags = kcalloc(NUM_SMK_MNT_OPTS, sizeof(int), |
|---|
| 700 | | - GFP_KERNEL); |
|---|
| 701 | | - if (!opts->mnt_opts_flags) |
|---|
| 702 | | - goto out_err; |
|---|
| 703 | | - |
|---|
| 704 | | - if (fsdefault) { |
|---|
| 705 | | - opts->mnt_opts[num_mnt_opts] = fsdefault; |
|---|
| 706 | | - opts->mnt_opts_flags[num_mnt_opts++] = FSDEFAULT_MNT; |
|---|
| 597 | + switch (token) { |
|---|
| 598 | + case Opt_fsdefault: |
|---|
| 599 | + if (opts->fsdefault) |
|---|
| 600 | + goto out_opt_err; |
|---|
| 601 | + opts->fsdefault = s; |
|---|
| 602 | + break; |
|---|
| 603 | + case Opt_fsfloor: |
|---|
| 604 | + if (opts->fsfloor) |
|---|
| 605 | + goto out_opt_err; |
|---|
| 606 | + opts->fsfloor = s; |
|---|
| 607 | + break; |
|---|
| 608 | + case Opt_fshat: |
|---|
| 609 | + if (opts->fshat) |
|---|
| 610 | + goto out_opt_err; |
|---|
| 611 | + opts->fshat = s; |
|---|
| 612 | + break; |
|---|
| 613 | + case Opt_fsroot: |
|---|
| 614 | + if (opts->fsroot) |
|---|
| 615 | + goto out_opt_err; |
|---|
| 616 | + opts->fsroot = s; |
|---|
| 617 | + break; |
|---|
| 618 | + case Opt_fstransmute: |
|---|
| 619 | + if (opts->fstransmute) |
|---|
| 620 | + goto out_opt_err; |
|---|
| 621 | + opts->fstransmute = s; |
|---|
| 622 | + break; |
|---|
| 707 | 623 | } |
|---|
| 708 | | - if (fsfloor) { |
|---|
| 709 | | - opts->mnt_opts[num_mnt_opts] = fsfloor; |
|---|
| 710 | | - opts->mnt_opts_flags[num_mnt_opts++] = FSFLOOR_MNT; |
|---|
| 711 | | - } |
|---|
| 712 | | - if (fshat) { |
|---|
| 713 | | - opts->mnt_opts[num_mnt_opts] = fshat; |
|---|
| 714 | | - opts->mnt_opts_flags[num_mnt_opts++] = FSHAT_MNT; |
|---|
| 715 | | - } |
|---|
| 716 | | - if (fsroot) { |
|---|
| 717 | | - opts->mnt_opts[num_mnt_opts] = fsroot; |
|---|
| 718 | | - opts->mnt_opts_flags[num_mnt_opts++] = FSROOT_MNT; |
|---|
| 719 | | - } |
|---|
| 720 | | - if (fstransmute) { |
|---|
| 721 | | - opts->mnt_opts[num_mnt_opts] = fstransmute; |
|---|
| 722 | | - opts->mnt_opts_flags[num_mnt_opts++] = FSTRANS_MNT; |
|---|
| 723 | | - } |
|---|
| 724 | | - |
|---|
| 725 | | - opts->num_mnt_opts = num_mnt_opts; |
|---|
| 726 | 624 | return 0; |
|---|
| 727 | 625 | |
|---|
| 728 | 626 | out_opt_err: |
|---|
| 729 | | - rc = -EINVAL; |
|---|
| 730 | 627 | pr_warn("Smack: duplicate mount options\n"); |
|---|
| 628 | + return -EINVAL; |
|---|
| 629 | +} |
|---|
| 731 | 630 | |
|---|
| 732 | | -out_err: |
|---|
| 733 | | - kfree(fsdefault); |
|---|
| 734 | | - kfree(fsfloor); |
|---|
| 735 | | - kfree(fshat); |
|---|
| 736 | | - kfree(fsroot); |
|---|
| 737 | | - kfree(fstransmute); |
|---|
| 631 | +/** |
|---|
| 632 | + * smack_fs_context_dup - Duplicate the security data on fs_context duplication |
|---|
| 633 | + * @fc: The new filesystem context. |
|---|
| 634 | + * @src_fc: The source filesystem context being duplicated. |
|---|
| 635 | + * |
|---|
| 636 | + * Returns 0 on success or -ENOMEM on error. |
|---|
| 637 | + */ |
|---|
| 638 | +static int smack_fs_context_dup(struct fs_context *fc, |
|---|
| 639 | + struct fs_context *src_fc) |
|---|
| 640 | +{ |
|---|
| 641 | + struct smack_mnt_opts *dst, *src = src_fc->security; |
|---|
| 642 | + |
|---|
| 643 | + if (!src) |
|---|
| 644 | + return 0; |
|---|
| 645 | + |
|---|
| 646 | + fc->security = kzalloc(sizeof(struct smack_mnt_opts), GFP_KERNEL); |
|---|
| 647 | + if (!fc->security) |
|---|
| 648 | + return -ENOMEM; |
|---|
| 649 | + dst = fc->security; |
|---|
| 650 | + |
|---|
| 651 | + if (src->fsdefault) { |
|---|
| 652 | + dst->fsdefault = kstrdup(src->fsdefault, GFP_KERNEL); |
|---|
| 653 | + if (!dst->fsdefault) |
|---|
| 654 | + return -ENOMEM; |
|---|
| 655 | + } |
|---|
| 656 | + if (src->fsfloor) { |
|---|
| 657 | + dst->fsfloor = kstrdup(src->fsfloor, GFP_KERNEL); |
|---|
| 658 | + if (!dst->fsfloor) |
|---|
| 659 | + return -ENOMEM; |
|---|
| 660 | + } |
|---|
| 661 | + if (src->fshat) { |
|---|
| 662 | + dst->fshat = kstrdup(src->fshat, GFP_KERNEL); |
|---|
| 663 | + if (!dst->fshat) |
|---|
| 664 | + return -ENOMEM; |
|---|
| 665 | + } |
|---|
| 666 | + if (src->fsroot) { |
|---|
| 667 | + dst->fsroot = kstrdup(src->fsroot, GFP_KERNEL); |
|---|
| 668 | + if (!dst->fsroot) |
|---|
| 669 | + return -ENOMEM; |
|---|
| 670 | + } |
|---|
| 671 | + if (src->fstransmute) { |
|---|
| 672 | + dst->fstransmute = kstrdup(src->fstransmute, GFP_KERNEL); |
|---|
| 673 | + if (!dst->fstransmute) |
|---|
| 674 | + return -ENOMEM; |
|---|
| 675 | + } |
|---|
| 676 | + return 0; |
|---|
| 677 | +} |
|---|
| 678 | + |
|---|
| 679 | +static const struct fs_parameter_spec smack_fs_parameters[] = { |
|---|
| 680 | + fsparam_string("smackfsdef", Opt_fsdefault), |
|---|
| 681 | + fsparam_string("smackfsdefault", Opt_fsdefault), |
|---|
| 682 | + fsparam_string("smackfsfloor", Opt_fsfloor), |
|---|
| 683 | + fsparam_string("smackfshat", Opt_fshat), |
|---|
| 684 | + fsparam_string("smackfsroot", Opt_fsroot), |
|---|
| 685 | + fsparam_string("smackfstransmute", Opt_fstransmute), |
|---|
| 686 | + {} |
|---|
| 687 | +}; |
|---|
| 688 | + |
|---|
| 689 | +/** |
|---|
| 690 | + * smack_fs_context_parse_param - Parse a single mount parameter |
|---|
| 691 | + * @fc: The new filesystem context being constructed. |
|---|
| 692 | + * @param: The parameter. |
|---|
| 693 | + * |
|---|
| 694 | + * Returns 0 on success, -ENOPARAM to pass the parameter on or anything else on |
|---|
| 695 | + * error. |
|---|
| 696 | + */ |
|---|
| 697 | +static int smack_fs_context_parse_param(struct fs_context *fc, |
|---|
| 698 | + struct fs_parameter *param) |
|---|
| 699 | +{ |
|---|
| 700 | + struct fs_parse_result result; |
|---|
| 701 | + int opt, rc; |
|---|
| 702 | + |
|---|
| 703 | + opt = fs_parse(fc, smack_fs_parameters, param, &result); |
|---|
| 704 | + if (opt < 0) |
|---|
| 705 | + return opt; |
|---|
| 706 | + |
|---|
| 707 | + rc = smack_add_opt(opt, param->string, &fc->security); |
|---|
| 708 | + if (!rc) |
|---|
| 709 | + param->string = NULL; |
|---|
| 738 | 710 | return rc; |
|---|
| 711 | +} |
|---|
| 712 | + |
|---|
| 713 | +static int smack_sb_eat_lsm_opts(char *options, void **mnt_opts) |
|---|
| 714 | +{ |
|---|
| 715 | + char *from = options, *to = options; |
|---|
| 716 | + bool first = true; |
|---|
| 717 | + |
|---|
| 718 | + while (1) { |
|---|
| 719 | + char *next = strchr(from, ','); |
|---|
| 720 | + int token, len, rc; |
|---|
| 721 | + char *arg = NULL; |
|---|
| 722 | + |
|---|
| 723 | + if (next) |
|---|
| 724 | + len = next - from; |
|---|
| 725 | + else |
|---|
| 726 | + len = strlen(from); |
|---|
| 727 | + |
|---|
| 728 | + token = match_opt_prefix(from, len, &arg); |
|---|
| 729 | + if (token != Opt_error) { |
|---|
| 730 | + arg = kmemdup_nul(arg, from + len - arg, GFP_KERNEL); |
|---|
| 731 | + rc = smack_add_opt(token, arg, mnt_opts); |
|---|
| 732 | + if (unlikely(rc)) { |
|---|
| 733 | + kfree(arg); |
|---|
| 734 | + if (*mnt_opts) |
|---|
| 735 | + smack_free_mnt_opts(*mnt_opts); |
|---|
| 736 | + *mnt_opts = NULL; |
|---|
| 737 | + return rc; |
|---|
| 738 | + } |
|---|
| 739 | + } else { |
|---|
| 740 | + if (!first) { // copy with preceding comma |
|---|
| 741 | + from--; |
|---|
| 742 | + len++; |
|---|
| 743 | + } |
|---|
| 744 | + if (to != from) |
|---|
| 745 | + memmove(to, from, len); |
|---|
| 746 | + to += len; |
|---|
| 747 | + first = false; |
|---|
| 748 | + } |
|---|
| 749 | + if (!from[len]) |
|---|
| 750 | + break; |
|---|
| 751 | + from += len + 1; |
|---|
| 752 | + } |
|---|
| 753 | + *to = '\0'; |
|---|
| 754 | + return 0; |
|---|
| 739 | 755 | } |
|---|
| 740 | 756 | |
|---|
| 741 | 757 | /** |
|---|
| 742 | 758 | * smack_set_mnt_opts - set Smack specific mount options |
|---|
| 743 | 759 | * @sb: the file system superblock |
|---|
| 744 | | - * @opts: Smack mount options |
|---|
| 760 | + * @mnt_opts: Smack mount options |
|---|
| 745 | 761 | * @kern_flags: mount option from kernel space or user space |
|---|
| 746 | 762 | * @set_kern_flags: where to store converted mount opts |
|---|
| 747 | 763 | * |
|---|
| .. | .. |
|---|
| 751 | 767 | * labels. |
|---|
| 752 | 768 | */ |
|---|
| 753 | 769 | static int smack_set_mnt_opts(struct super_block *sb, |
|---|
| 754 | | - struct security_mnt_opts *opts, |
|---|
| 770 | + void *mnt_opts, |
|---|
| 755 | 771 | unsigned long kern_flags, |
|---|
| 756 | 772 | unsigned long *set_kern_flags) |
|---|
| 757 | 773 | { |
|---|
| .. | .. |
|---|
| 760 | 776 | struct superblock_smack *sp = sb->s_security; |
|---|
| 761 | 777 | struct inode_smack *isp; |
|---|
| 762 | 778 | struct smack_known *skp; |
|---|
| 763 | | - int i; |
|---|
| 764 | | - int num_opts = opts->num_mnt_opts; |
|---|
| 765 | | - int transmute = 0; |
|---|
| 779 | + struct smack_mnt_opts *opts = mnt_opts; |
|---|
| 780 | + bool transmute = false; |
|---|
| 766 | 781 | |
|---|
| 767 | 782 | if (sp->smk_flags & SMK_SB_INITIALIZED) |
|---|
| 768 | 783 | return 0; |
|---|
| 784 | + |
|---|
| 785 | + if (inode->i_security == NULL) { |
|---|
| 786 | + int rc = lsm_inode_alloc(inode); |
|---|
| 787 | + |
|---|
| 788 | + if (rc) |
|---|
| 789 | + return rc; |
|---|
| 790 | + } |
|---|
| 769 | 791 | |
|---|
| 770 | 792 | if (!smack_privileged(CAP_MAC_ADMIN)) { |
|---|
| 771 | 793 | /* |
|---|
| 772 | 794 | * Unprivileged mounts don't get to specify Smack values. |
|---|
| 773 | 795 | */ |
|---|
| 774 | | - if (num_opts) |
|---|
| 796 | + if (opts) |
|---|
| 775 | 797 | return -EPERM; |
|---|
| 776 | 798 | /* |
|---|
| 777 | 799 | * Unprivileged mounts get root and default from the caller. |
|---|
| .. | .. |
|---|
| 787 | 809 | if (sb->s_user_ns != &init_user_ns && |
|---|
| 788 | 810 | sb->s_magic != SYSFS_MAGIC && sb->s_magic != TMPFS_MAGIC && |
|---|
| 789 | 811 | sb->s_magic != RAMFS_MAGIC) { |
|---|
| 790 | | - transmute = 1; |
|---|
| 812 | + transmute = true; |
|---|
| 791 | 813 | sp->smk_flags |= SMK_SB_UNTRUSTED; |
|---|
| 792 | 814 | } |
|---|
| 793 | 815 | } |
|---|
| 794 | 816 | |
|---|
| 795 | 817 | sp->smk_flags |= SMK_SB_INITIALIZED; |
|---|
| 796 | 818 | |
|---|
| 797 | | - for (i = 0; i < num_opts; i++) { |
|---|
| 798 | | - switch (opts->mnt_opts_flags[i]) { |
|---|
| 799 | | - case FSDEFAULT_MNT: |
|---|
| 800 | | - skp = smk_import_entry(opts->mnt_opts[i], 0); |
|---|
| 819 | + if (opts) { |
|---|
| 820 | + if (opts->fsdefault) { |
|---|
| 821 | + skp = smk_import_entry(opts->fsdefault, 0); |
|---|
| 801 | 822 | if (IS_ERR(skp)) |
|---|
| 802 | 823 | return PTR_ERR(skp); |
|---|
| 803 | 824 | sp->smk_default = skp; |
|---|
| 804 | | - break; |
|---|
| 805 | | - case FSFLOOR_MNT: |
|---|
| 806 | | - skp = smk_import_entry(opts->mnt_opts[i], 0); |
|---|
| 825 | + } |
|---|
| 826 | + if (opts->fsfloor) { |
|---|
| 827 | + skp = smk_import_entry(opts->fsfloor, 0); |
|---|
| 807 | 828 | if (IS_ERR(skp)) |
|---|
| 808 | 829 | return PTR_ERR(skp); |
|---|
| 809 | 830 | sp->smk_floor = skp; |
|---|
| 810 | | - break; |
|---|
| 811 | | - case FSHAT_MNT: |
|---|
| 812 | | - skp = smk_import_entry(opts->mnt_opts[i], 0); |
|---|
| 831 | + } |
|---|
| 832 | + if (opts->fshat) { |
|---|
| 833 | + skp = smk_import_entry(opts->fshat, 0); |
|---|
| 813 | 834 | if (IS_ERR(skp)) |
|---|
| 814 | 835 | return PTR_ERR(skp); |
|---|
| 815 | 836 | sp->smk_hat = skp; |
|---|
| 816 | | - break; |
|---|
| 817 | | - case FSROOT_MNT: |
|---|
| 818 | | - skp = smk_import_entry(opts->mnt_opts[i], 0); |
|---|
| 837 | + } |
|---|
| 838 | + if (opts->fsroot) { |
|---|
| 839 | + skp = smk_import_entry(opts->fsroot, 0); |
|---|
| 819 | 840 | if (IS_ERR(skp)) |
|---|
| 820 | 841 | return PTR_ERR(skp); |
|---|
| 821 | 842 | sp->smk_root = skp; |
|---|
| 822 | | - break; |
|---|
| 823 | | - case FSTRANS_MNT: |
|---|
| 824 | | - skp = smk_import_entry(opts->mnt_opts[i], 0); |
|---|
| 843 | + } |
|---|
| 844 | + if (opts->fstransmute) { |
|---|
| 845 | + skp = smk_import_entry(opts->fstransmute, 0); |
|---|
| 825 | 846 | if (IS_ERR(skp)) |
|---|
| 826 | 847 | return PTR_ERR(skp); |
|---|
| 827 | 848 | sp->smk_root = skp; |
|---|
| 828 | | - transmute = 1; |
|---|
| 829 | | - break; |
|---|
| 830 | | - default: |
|---|
| 831 | | - break; |
|---|
| 849 | + transmute = true; |
|---|
| 832 | 850 | } |
|---|
| 833 | 851 | } |
|---|
| 834 | 852 | |
|---|
| 835 | 853 | /* |
|---|
| 836 | 854 | * Initialize the root inode. |
|---|
| 837 | 855 | */ |
|---|
| 838 | | - isp = inode->i_security; |
|---|
| 839 | | - if (isp == NULL) { |
|---|
| 840 | | - isp = new_inode_smack(sp->smk_root); |
|---|
| 841 | | - if (isp == NULL) |
|---|
| 842 | | - return -ENOMEM; |
|---|
| 843 | | - inode->i_security = isp; |
|---|
| 844 | | - } else |
|---|
| 845 | | - isp->smk_inode = sp->smk_root; |
|---|
| 856 | + init_inode_smack(inode, sp->smk_root); |
|---|
| 846 | 857 | |
|---|
| 847 | | - if (transmute) |
|---|
| 858 | + if (transmute) { |
|---|
| 859 | + isp = smack_inode(inode); |
|---|
| 848 | 860 | isp->smk_flags |= SMK_INODE_TRANSMUTE; |
|---|
| 861 | + } |
|---|
| 849 | 862 | |
|---|
| 850 | 863 | return 0; |
|---|
| 851 | | -} |
|---|
| 852 | | - |
|---|
| 853 | | -/** |
|---|
| 854 | | - * smack_sb_kern_mount - Smack specific mount processing |
|---|
| 855 | | - * @sb: the file system superblock |
|---|
| 856 | | - * @flags: the mount flags |
|---|
| 857 | | - * @data: the smack mount options |
|---|
| 858 | | - * |
|---|
| 859 | | - * Returns 0 on success, an error code on failure |
|---|
| 860 | | - */ |
|---|
| 861 | | -static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) |
|---|
| 862 | | -{ |
|---|
| 863 | | - int rc = 0; |
|---|
| 864 | | - char *options = data; |
|---|
| 865 | | - struct security_mnt_opts opts; |
|---|
| 866 | | - |
|---|
| 867 | | - security_init_mnt_opts(&opts); |
|---|
| 868 | | - |
|---|
| 869 | | - if (!options) |
|---|
| 870 | | - goto out; |
|---|
| 871 | | - |
|---|
| 872 | | - rc = smack_parse_opts_str(options, &opts); |
|---|
| 873 | | - if (rc) |
|---|
| 874 | | - goto out_err; |
|---|
| 875 | | - |
|---|
| 876 | | -out: |
|---|
| 877 | | - rc = smack_set_mnt_opts(sb, &opts, 0, NULL); |
|---|
| 878 | | - |
|---|
| 879 | | -out_err: |
|---|
| 880 | | - security_free_mnt_opts(&opts); |
|---|
| 881 | | - return rc; |
|---|
| 882 | 864 | } |
|---|
| 883 | 865 | |
|---|
| 884 | 866 | /** |
|---|
| .. | .. |
|---|
| 907 | 889 | */ |
|---|
| 908 | 890 | |
|---|
| 909 | 891 | /** |
|---|
| 910 | | - * smack_bprm_set_creds - set creds for exec |
|---|
| 892 | + * smack_bprm_creds_for_exec - Update bprm->cred if needed for exec |
|---|
| 911 | 893 | * @bprm: the exec information |
|---|
| 912 | 894 | * |
|---|
| 913 | 895 | * Returns 0 if it gets a blob, -EPERM if exec forbidden and -ENOMEM otherwise |
|---|
| 914 | 896 | */ |
|---|
| 915 | | -static int smack_bprm_set_creds(struct linux_binprm *bprm) |
|---|
| 897 | +static int smack_bprm_creds_for_exec(struct linux_binprm *bprm) |
|---|
| 916 | 898 | { |
|---|
| 917 | 899 | struct inode *inode = file_inode(bprm->file); |
|---|
| 918 | | - struct task_smack *bsp = bprm->cred->security; |
|---|
| 900 | + struct task_smack *bsp = smack_cred(bprm->cred); |
|---|
| 919 | 901 | struct inode_smack *isp; |
|---|
| 920 | 902 | struct superblock_smack *sbsp; |
|---|
| 921 | 903 | int rc; |
|---|
| 922 | 904 | |
|---|
| 923 | | - if (bprm->called_set_creds) |
|---|
| 924 | | - return 0; |
|---|
| 925 | | - |
|---|
| 926 | | - isp = inode->i_security; |
|---|
| 905 | + isp = smack_inode(inode); |
|---|
| 927 | 906 | if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task) |
|---|
| 928 | 907 | return 0; |
|---|
| 929 | 908 | |
|---|
| .. | .. |
|---|
| 969 | 948 | * smack_inode_alloc_security - allocate an inode blob |
|---|
| 970 | 949 | * @inode: the inode in need of a blob |
|---|
| 971 | 950 | * |
|---|
| 972 | | - * Returns 0 if it gets a blob, -ENOMEM otherwise |
|---|
| 951 | + * Returns 0 |
|---|
| 973 | 952 | */ |
|---|
| 974 | 953 | static int smack_inode_alloc_security(struct inode *inode) |
|---|
| 975 | 954 | { |
|---|
| 976 | 955 | struct smack_known *skp = smk_of_current(); |
|---|
| 977 | 956 | |
|---|
| 978 | | - inode->i_security = new_inode_smack(skp); |
|---|
| 979 | | - if (inode->i_security == NULL) |
|---|
| 980 | | - return -ENOMEM; |
|---|
| 957 | + init_inode_smack(inode, skp); |
|---|
| 981 | 958 | return 0; |
|---|
| 982 | | -} |
|---|
| 983 | | - |
|---|
| 984 | | -/** |
|---|
| 985 | | - * smack_inode_free_rcu - Free inode_smack blob from cache |
|---|
| 986 | | - * @head: the rcu_head for getting inode_smack pointer |
|---|
| 987 | | - * |
|---|
| 988 | | - * Call back function called from call_rcu() to free |
|---|
| 989 | | - * the i_security blob pointer in inode |
|---|
| 990 | | - */ |
|---|
| 991 | | -static void smack_inode_free_rcu(struct rcu_head *head) |
|---|
| 992 | | -{ |
|---|
| 993 | | - struct inode_smack *issp; |
|---|
| 994 | | - |
|---|
| 995 | | - issp = container_of(head, struct inode_smack, smk_rcu); |
|---|
| 996 | | - kmem_cache_free(smack_inode_cache, issp); |
|---|
| 997 | | -} |
|---|
| 998 | | - |
|---|
| 999 | | -/** |
|---|
| 1000 | | - * smack_inode_free_security - free an inode blob using call_rcu() |
|---|
| 1001 | | - * @inode: the inode with a blob |
|---|
| 1002 | | - * |
|---|
| 1003 | | - * Clears the blob pointer in inode using RCU |
|---|
| 1004 | | - */ |
|---|
| 1005 | | -static void smack_inode_free_security(struct inode *inode) |
|---|
| 1006 | | -{ |
|---|
| 1007 | | - struct inode_smack *issp = inode->i_security; |
|---|
| 1008 | | - |
|---|
| 1009 | | - /* |
|---|
| 1010 | | - * The inode may still be referenced in a path walk and |
|---|
| 1011 | | - * a call to smack_inode_permission() can be made |
|---|
| 1012 | | - * after smack_inode_free_security() is called. |
|---|
| 1013 | | - * To avoid race condition free the i_security via RCU |
|---|
| 1014 | | - * and leave the current inode->i_security pointer intact. |
|---|
| 1015 | | - * The inode will be freed after the RCU grace period too. |
|---|
| 1016 | | - */ |
|---|
| 1017 | | - call_rcu(&issp->smk_rcu, smack_inode_free_rcu); |
|---|
| 1018 | 959 | } |
|---|
| 1019 | 960 | |
|---|
| 1020 | 961 | /** |
|---|
| .. | .. |
|---|
| 1032 | 973 | const struct qstr *qstr, const char **name, |
|---|
| 1033 | 974 | void **value, size_t *len) |
|---|
| 1034 | 975 | { |
|---|
| 1035 | | - struct inode_smack *issp = inode->i_security; |
|---|
| 1036 | | - struct smack_known *skp = smk_of_current(); |
|---|
| 976 | + struct task_smack *tsp = smack_cred(current_cred()); |
|---|
| 977 | + struct inode_smack *issp = smack_inode(inode); |
|---|
| 978 | + struct smack_known *skp = smk_of_task(tsp); |
|---|
| 1037 | 979 | struct smack_known *isp = smk_of_inode(inode); |
|---|
| 1038 | 980 | struct smack_known *dsp = smk_of_inode(dir); |
|---|
| 1039 | 981 | int may; |
|---|
| .. | .. |
|---|
| 1042 | 984 | *name = XATTR_SMACK_SUFFIX; |
|---|
| 1043 | 985 | |
|---|
| 1044 | 986 | if (value && len) { |
|---|
| 1045 | | - rcu_read_lock(); |
|---|
| 1046 | | - may = smk_access_entry(skp->smk_known, dsp->smk_known, |
|---|
| 1047 | | - &skp->smk_rules); |
|---|
| 1048 | | - rcu_read_unlock(); |
|---|
| 987 | + /* |
|---|
| 988 | + * If equal, transmuting already occurred in |
|---|
| 989 | + * smack_dentry_create_files_as(). No need to check again. |
|---|
| 990 | + */ |
|---|
| 991 | + if (tsp->smk_task != tsp->smk_transmuted) { |
|---|
| 992 | + rcu_read_lock(); |
|---|
| 993 | + may = smk_access_entry(skp->smk_known, dsp->smk_known, |
|---|
| 994 | + &skp->smk_rules); |
|---|
| 995 | + rcu_read_unlock(); |
|---|
| 996 | + } |
|---|
| 1049 | 997 | |
|---|
| 1050 | 998 | /* |
|---|
| 1051 | | - * If the access rule allows transmutation and |
|---|
| 1052 | | - * the directory requests transmutation then |
|---|
| 1053 | | - * by all means transmute. |
|---|
| 999 | + * In addition to having smk_task equal to smk_transmuted, |
|---|
| 1000 | + * if the access rule allows transmutation and the directory |
|---|
| 1001 | + * requests transmutation then by all means transmute. |
|---|
| 1054 | 1002 | * Mark the inode as changed. |
|---|
| 1055 | 1003 | */ |
|---|
| 1056 | | - if (may > 0 && ((may & MAY_TRANSMUTE) != 0) && |
|---|
| 1057 | | - smk_inode_transmutable(dir)) { |
|---|
| 1058 | | - isp = dsp; |
|---|
| 1004 | + if ((tsp->smk_task == tsp->smk_transmuted) || |
|---|
| 1005 | + (may > 0 && ((may & MAY_TRANSMUTE) != 0) && |
|---|
| 1006 | + smk_inode_transmutable(dir))) { |
|---|
| 1007 | + /* |
|---|
| 1008 | + * The caller of smack_dentry_create_files_as() |
|---|
| 1009 | + * should have overridden the current cred, so the |
|---|
| 1010 | + * inode label was already set correctly in |
|---|
| 1011 | + * smack_inode_alloc_security(). |
|---|
| 1012 | + */ |
|---|
| 1013 | + if (tsp->smk_task != tsp->smk_transmuted) |
|---|
| 1014 | + isp = dsp; |
|---|
| 1059 | 1015 | issp->smk_flags |= SMK_INODE_CHANGED; |
|---|
| 1060 | 1016 | } |
|---|
| 1061 | 1017 | |
|---|
| .. | .. |
|---|
| 1213 | 1169 | * |
|---|
| 1214 | 1170 | * This is the important Smack hook. |
|---|
| 1215 | 1171 | * |
|---|
| 1216 | | - * Returns 0 if access is permitted, -EACCES otherwise |
|---|
| 1172 | + * Returns 0 if access is permitted, an error code otherwise |
|---|
| 1217 | 1173 | */ |
|---|
| 1218 | 1174 | static int smack_inode_permission(struct inode *inode, int mask) |
|---|
| 1219 | 1175 | { |
|---|
| .. | .. |
|---|
| 1271 | 1227 | |
|---|
| 1272 | 1228 | /** |
|---|
| 1273 | 1229 | * smack_inode_getattr - Smack check for getting attributes |
|---|
| 1274 | | - * @mnt: vfsmount of the object |
|---|
| 1275 | | - * @dentry: the object |
|---|
| 1230 | + * @path: path to extract the info from |
|---|
| 1276 | 1231 | * |
|---|
| 1277 | 1232 | * Returns 0 if access is permitted, an error code otherwise |
|---|
| 1278 | 1233 | */ |
|---|
| .. | .. |
|---|
| 1370 | 1325 | const void *value, size_t size, int flags) |
|---|
| 1371 | 1326 | { |
|---|
| 1372 | 1327 | struct smack_known *skp; |
|---|
| 1373 | | - struct inode_smack *isp = d_backing_inode(dentry)->i_security; |
|---|
| 1328 | + struct inode_smack *isp = smack_inode(d_backing_inode(dentry)); |
|---|
| 1374 | 1329 | |
|---|
| 1375 | 1330 | if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { |
|---|
| 1376 | 1331 | isp->smk_flags |= SMK_INODE_TRANSMUTE; |
|---|
| .. | .. |
|---|
| 1451 | 1406 | if (rc != 0) |
|---|
| 1452 | 1407 | return rc; |
|---|
| 1453 | 1408 | |
|---|
| 1454 | | - isp = d_backing_inode(dentry)->i_security; |
|---|
| 1409 | + isp = smack_inode(d_backing_inode(dentry)); |
|---|
| 1455 | 1410 | /* |
|---|
| 1456 | 1411 | * Don't do anything special for these. |
|---|
| 1457 | 1412 | * XATTR_NAME_SMACKIPIN |
|---|
| .. | .. |
|---|
| 1490 | 1445 | struct super_block *sbp; |
|---|
| 1491 | 1446 | struct inode *ip = (struct inode *)inode; |
|---|
| 1492 | 1447 | struct smack_known *isp; |
|---|
| 1448 | + struct inode_smack *ispp; |
|---|
| 1449 | + size_t label_len; |
|---|
| 1450 | + char *label = NULL; |
|---|
| 1493 | 1451 | |
|---|
| 1494 | | - if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) |
|---|
| 1452 | + if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { |
|---|
| 1495 | 1453 | isp = smk_of_inode(inode); |
|---|
| 1496 | | - else { |
|---|
| 1454 | + } else if (strcmp(name, XATTR_SMACK_TRANSMUTE) == 0) { |
|---|
| 1455 | + ispp = smack_inode(inode); |
|---|
| 1456 | + if (ispp->smk_flags & SMK_INODE_TRANSMUTE) |
|---|
| 1457 | + label = TRANS_TRUE; |
|---|
| 1458 | + else |
|---|
| 1459 | + label = ""; |
|---|
| 1460 | + } else { |
|---|
| 1497 | 1461 | /* |
|---|
| 1498 | 1462 | * The rest of the Smack xattrs are only on sockets. |
|---|
| 1499 | 1463 | */ |
|---|
| .. | .. |
|---|
| 1515 | 1479 | return -EOPNOTSUPP; |
|---|
| 1516 | 1480 | } |
|---|
| 1517 | 1481 | |
|---|
| 1482 | + if (!label) |
|---|
| 1483 | + label = isp->smk_known; |
|---|
| 1484 | + |
|---|
| 1485 | + label_len = strlen(label); |
|---|
| 1486 | + |
|---|
| 1518 | 1487 | if (alloc) { |
|---|
| 1519 | | - *buffer = kstrdup(isp->smk_known, GFP_KERNEL); |
|---|
| 1488 | + *buffer = kstrdup(label, GFP_KERNEL); |
|---|
| 1520 | 1489 | if (*buffer == NULL) |
|---|
| 1521 | 1490 | return -ENOMEM; |
|---|
| 1522 | 1491 | } |
|---|
| 1523 | 1492 | |
|---|
| 1524 | | - return strlen(isp->smk_known); |
|---|
| 1493 | + return label_len; |
|---|
| 1525 | 1494 | } |
|---|
| 1526 | 1495 | |
|---|
| 1527 | 1496 | |
|---|
| .. | .. |
|---|
| 1583 | 1552 | */ |
|---|
| 1584 | 1553 | static int smack_file_alloc_security(struct file *file) |
|---|
| 1585 | 1554 | { |
|---|
| 1586 | | - struct smack_known *skp = smk_of_current(); |
|---|
| 1555 | + struct smack_known **blob = smack_file(file); |
|---|
| 1587 | 1556 | |
|---|
| 1588 | | - file->f_security = skp; |
|---|
| 1557 | + *blob = smk_of_current(); |
|---|
| 1589 | 1558 | return 0; |
|---|
| 1590 | | -} |
|---|
| 1591 | | - |
|---|
| 1592 | | -/** |
|---|
| 1593 | | - * smack_file_free_security - clear a file security blob |
|---|
| 1594 | | - * @file: the object |
|---|
| 1595 | | - * |
|---|
| 1596 | | - * The security blob for a file is a pointer to the master |
|---|
| 1597 | | - * label list, so no memory is freed. |
|---|
| 1598 | | - */ |
|---|
| 1599 | | -static void smack_file_free_security(struct file *file) |
|---|
| 1600 | | -{ |
|---|
| 1601 | | - file->f_security = NULL; |
|---|
| 1602 | 1559 | } |
|---|
| 1603 | 1560 | |
|---|
| 1604 | 1561 | /** |
|---|
| .. | .. |
|---|
| 1738 | 1695 | if (unlikely(IS_PRIVATE(file_inode(file)))) |
|---|
| 1739 | 1696 | return 0; |
|---|
| 1740 | 1697 | |
|---|
| 1741 | | - isp = file_inode(file)->i_security; |
|---|
| 1698 | + isp = smack_inode(file_inode(file)); |
|---|
| 1742 | 1699 | if (isp->smk_mmap == NULL) |
|---|
| 1743 | 1700 | return 0; |
|---|
| 1744 | 1701 | sbsp = file_inode(file)->i_sb->s_security; |
|---|
| .. | .. |
|---|
| 1747 | 1704 | return -EACCES; |
|---|
| 1748 | 1705 | mkp = isp->smk_mmap; |
|---|
| 1749 | 1706 | |
|---|
| 1750 | | - tsp = current_security(); |
|---|
| 1707 | + tsp = smack_cred(current_cred()); |
|---|
| 1751 | 1708 | skp = smk_of_current(); |
|---|
| 1752 | 1709 | rc = 0; |
|---|
| 1753 | 1710 | |
|---|
| .. | .. |
|---|
| 1825 | 1782 | */ |
|---|
| 1826 | 1783 | static void smack_file_set_fowner(struct file *file) |
|---|
| 1827 | 1784 | { |
|---|
| 1828 | | - file->f_security = smk_of_current(); |
|---|
| 1785 | + struct smack_known **blob = smack_file(file); |
|---|
| 1786 | + |
|---|
| 1787 | + *blob = smk_of_current(); |
|---|
| 1829 | 1788 | } |
|---|
| 1830 | 1789 | |
|---|
| 1831 | 1790 | /** |
|---|
| .. | .. |
|---|
| 1842 | 1801 | static int smack_file_send_sigiotask(struct task_struct *tsk, |
|---|
| 1843 | 1802 | struct fown_struct *fown, int signum) |
|---|
| 1844 | 1803 | { |
|---|
| 1804 | + struct smack_known **blob; |
|---|
| 1845 | 1805 | struct smack_known *skp; |
|---|
| 1846 | | - struct smack_known *tkp = smk_of_task(tsk->cred->security); |
|---|
| 1806 | + struct smack_known *tkp = smk_of_task(smack_cred(tsk->cred)); |
|---|
| 1847 | 1807 | const struct cred *tcred; |
|---|
| 1848 | 1808 | struct file *file; |
|---|
| 1849 | 1809 | int rc; |
|---|
| .. | .. |
|---|
| 1855 | 1815 | file = container_of(fown, struct file, f_owner); |
|---|
| 1856 | 1816 | |
|---|
| 1857 | 1817 | /* we don't log here as rc can be overriden */ |
|---|
| 1858 | | - skp = file->f_security; |
|---|
| 1818 | + blob = smack_file(file); |
|---|
| 1819 | + skp = *blob; |
|---|
| 1859 | 1820 | rc = smk_access(skp, tkp, MAY_DELIVER, NULL); |
|---|
| 1860 | 1821 | rc = smk_bu_note("sigiotask", skp, tkp, MAY_DELIVER, rc); |
|---|
| 1861 | 1822 | |
|---|
| .. | .. |
|---|
| 1896 | 1857 | if (inode->i_sb->s_magic == SOCKFS_MAGIC) { |
|---|
| 1897 | 1858 | sock = SOCKET_I(inode); |
|---|
| 1898 | 1859 | ssp = sock->sk->sk_security; |
|---|
| 1899 | | - tsp = current_security(); |
|---|
| 1860 | + tsp = smack_cred(current_cred()); |
|---|
| 1900 | 1861 | /* |
|---|
| 1901 | 1862 | * If the receiving process can't write to the |
|---|
| 1902 | 1863 | * passed socket or if the passed socket can't |
|---|
| .. | .. |
|---|
| 1927 | 1888 | /** |
|---|
| 1928 | 1889 | * smack_file_open - Smack dentry open processing |
|---|
| 1929 | 1890 | * @file: the object |
|---|
| 1930 | | - * @cred: task credential |
|---|
| 1931 | 1891 | * |
|---|
| 1932 | 1892 | * Set the security blob in the file structure. |
|---|
| 1933 | 1893 | * Allow the open only if the task has read access. There are |
|---|
| 1934 | 1894 | * many read operations (e.g. fstat) that you can do with an |
|---|
| 1935 | 1895 | * fd even if you have the file open write-only. |
|---|
| 1936 | 1896 | * |
|---|
| 1937 | | - * Returns 0 |
|---|
| 1897 | + * Returns 0 if current has access, error code otherwise |
|---|
| 1938 | 1898 | */ |
|---|
| 1939 | 1899 | static int smack_file_open(struct file *file) |
|---|
| 1940 | 1900 | { |
|---|
| 1941 | | - struct task_smack *tsp = file->f_cred->security; |
|---|
| 1901 | + struct task_smack *tsp = smack_cred(file->f_cred); |
|---|
| 1942 | 1902 | struct inode *inode = file_inode(file); |
|---|
| 1943 | 1903 | struct smk_audit_info ad; |
|---|
| 1944 | 1904 | int rc; |
|---|
| .. | .. |
|---|
| 1957 | 1917 | |
|---|
| 1958 | 1918 | /** |
|---|
| 1959 | 1919 | * smack_cred_alloc_blank - "allocate" blank task-level security credentials |
|---|
| 1960 | | - * @new: the new credentials |
|---|
| 1920 | + * @cred: the new credentials |
|---|
| 1961 | 1921 | * @gfp: the atomicity of any memory allocations |
|---|
| 1962 | 1922 | * |
|---|
| 1963 | 1923 | * Prepare a blank set of credentials for modification. This must allocate all |
|---|
| .. | .. |
|---|
| 1966 | 1926 | */ |
|---|
| 1967 | 1927 | static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) |
|---|
| 1968 | 1928 | { |
|---|
| 1969 | | - struct task_smack *tsp; |
|---|
| 1970 | | - |
|---|
| 1971 | | - tsp = new_task_smack(NULL, NULL, gfp); |
|---|
| 1972 | | - if (tsp == NULL) |
|---|
| 1973 | | - return -ENOMEM; |
|---|
| 1974 | | - |
|---|
| 1975 | | - cred->security = tsp; |
|---|
| 1976 | | - |
|---|
| 1929 | + init_task_smack(smack_cred(cred), NULL, NULL); |
|---|
| 1977 | 1930 | return 0; |
|---|
| 1978 | 1931 | } |
|---|
| 1979 | 1932 | |
|---|
| .. | .. |
|---|
| 1985 | 1938 | */ |
|---|
| 1986 | 1939 | static void smack_cred_free(struct cred *cred) |
|---|
| 1987 | 1940 | { |
|---|
| 1988 | | - struct task_smack *tsp = cred->security; |
|---|
| 1941 | + struct task_smack *tsp = smack_cred(cred); |
|---|
| 1989 | 1942 | struct smack_rule *rp; |
|---|
| 1990 | 1943 | struct list_head *l; |
|---|
| 1991 | 1944 | struct list_head *n; |
|---|
| 1992 | | - |
|---|
| 1993 | | - if (tsp == NULL) |
|---|
| 1994 | | - return; |
|---|
| 1995 | | - cred->security = NULL; |
|---|
| 1996 | 1945 | |
|---|
| 1997 | 1946 | smk_destroy_label_list(&tsp->smk_relabel); |
|---|
| 1998 | 1947 | |
|---|
| 1999 | 1948 | list_for_each_safe(l, n, &tsp->smk_rules) { |
|---|
| 2000 | 1949 | rp = list_entry(l, struct smack_rule, list); |
|---|
| 2001 | 1950 | list_del(&rp->list); |
|---|
| 2002 | | - kfree(rp); |
|---|
| 1951 | + kmem_cache_free(smack_rule_cache, rp); |
|---|
| 2003 | 1952 | } |
|---|
| 2004 | | - kfree(tsp); |
|---|
| 2005 | 1953 | } |
|---|
| 2006 | 1954 | |
|---|
| 2007 | 1955 | /** |
|---|
| .. | .. |
|---|
| 2015 | 1963 | static int smack_cred_prepare(struct cred *new, const struct cred *old, |
|---|
| 2016 | 1964 | gfp_t gfp) |
|---|
| 2017 | 1965 | { |
|---|
| 2018 | | - struct task_smack *old_tsp = old->security; |
|---|
| 2019 | | - struct task_smack *new_tsp; |
|---|
| 1966 | + struct task_smack *old_tsp = smack_cred(old); |
|---|
| 1967 | + struct task_smack *new_tsp = smack_cred(new); |
|---|
| 2020 | 1968 | int rc; |
|---|
| 2021 | 1969 | |
|---|
| 2022 | | - new_tsp = new_task_smack(old_tsp->smk_task, old_tsp->smk_task, gfp); |
|---|
| 2023 | | - if (new_tsp == NULL) |
|---|
| 2024 | | - return -ENOMEM; |
|---|
| 2025 | | - |
|---|
| 2026 | | - new->security = new_tsp; |
|---|
| 1970 | + init_task_smack(new_tsp, old_tsp->smk_task, old_tsp->smk_task); |
|---|
| 2027 | 1971 | |
|---|
| 2028 | 1972 | rc = smk_copy_rules(&new_tsp->smk_rules, &old_tsp->smk_rules, gfp); |
|---|
| 2029 | 1973 | if (rc != 0) |
|---|
| .. | .. |
|---|
| 2031 | 1975 | |
|---|
| 2032 | 1976 | rc = smk_copy_relabel(&new_tsp->smk_relabel, &old_tsp->smk_relabel, |
|---|
| 2033 | 1977 | gfp); |
|---|
| 2034 | | - if (rc != 0) |
|---|
| 2035 | | - return rc; |
|---|
| 2036 | | - |
|---|
| 2037 | | - return 0; |
|---|
| 1978 | + return rc; |
|---|
| 2038 | 1979 | } |
|---|
| 2039 | 1980 | |
|---|
| 2040 | 1981 | /** |
|---|
| .. | .. |
|---|
| 2046 | 1987 | */ |
|---|
| 2047 | 1988 | static void smack_cred_transfer(struct cred *new, const struct cred *old) |
|---|
| 2048 | 1989 | { |
|---|
| 2049 | | - struct task_smack *old_tsp = old->security; |
|---|
| 2050 | | - struct task_smack *new_tsp = new->security; |
|---|
| 1990 | + struct task_smack *old_tsp = smack_cred(old); |
|---|
| 1991 | + struct task_smack *new_tsp = smack_cred(new); |
|---|
| 2051 | 1992 | |
|---|
| 2052 | 1993 | new_tsp->smk_task = old_tsp->smk_task; |
|---|
| 2053 | 1994 | new_tsp->smk_forked = old_tsp->smk_task; |
|---|
| 2054 | 1995 | mutex_init(&new_tsp->smk_rules_lock); |
|---|
| 2055 | 1996 | INIT_LIST_HEAD(&new_tsp->smk_rules); |
|---|
| 2056 | 1997 | |
|---|
| 2057 | | - |
|---|
| 2058 | 1998 | /* cbs copy rule list */ |
|---|
| 2059 | 1999 | } |
|---|
| 2060 | 2000 | |
|---|
| 2061 | 2001 | /** |
|---|
| 2062 | 2002 | * smack_cred_getsecid - get the secid corresponding to a creds structure |
|---|
| 2063 | | - * @c: the object creds |
|---|
| 2003 | + * @cred: the object creds |
|---|
| 2064 | 2004 | * @secid: where to put the result |
|---|
| 2065 | 2005 | * |
|---|
| 2066 | 2006 | * Sets the secid to contain a u32 version of the smack label. |
|---|
| 2067 | 2007 | */ |
|---|
| 2068 | | -static void smack_cred_getsecid(const struct cred *c, u32 *secid) |
|---|
| 2008 | +static void smack_cred_getsecid(const struct cred *cred, u32 *secid) |
|---|
| 2069 | 2009 | { |
|---|
| 2070 | 2010 | struct smack_known *skp; |
|---|
| 2071 | 2011 | |
|---|
| 2072 | 2012 | rcu_read_lock(); |
|---|
| 2073 | | - skp = smk_of_task(c->security); |
|---|
| 2013 | + skp = smk_of_task(smack_cred(cred)); |
|---|
| 2074 | 2014 | *secid = skp->smk_secid; |
|---|
| 2075 | 2015 | rcu_read_unlock(); |
|---|
| 2076 | 2016 | } |
|---|
| .. | .. |
|---|
| 2084 | 2024 | */ |
|---|
| 2085 | 2025 | static int smack_kernel_act_as(struct cred *new, u32 secid) |
|---|
| 2086 | 2026 | { |
|---|
| 2087 | | - struct task_smack *new_tsp = new->security; |
|---|
| 2027 | + struct task_smack *new_tsp = smack_cred(new); |
|---|
| 2088 | 2028 | |
|---|
| 2089 | 2029 | new_tsp->smk_task = smack_from_secid(secid); |
|---|
| 2090 | 2030 | return 0; |
|---|
| .. | .. |
|---|
| 2101 | 2041 | static int smack_kernel_create_files_as(struct cred *new, |
|---|
| 2102 | 2042 | struct inode *inode) |
|---|
| 2103 | 2043 | { |
|---|
| 2104 | | - struct inode_smack *isp = inode->i_security; |
|---|
| 2105 | | - struct task_smack *tsp = new->security; |
|---|
| 2044 | + struct inode_smack *isp = smack_inode(inode); |
|---|
| 2045 | + struct task_smack *tsp = smack_cred(new); |
|---|
| 2106 | 2046 | |
|---|
| 2107 | 2047 | tsp->smk_forked = isp->smk_inode; |
|---|
| 2108 | 2048 | tsp->smk_task = tsp->smk_forked; |
|---|
| .. | .. |
|---|
| 2217 | 2157 | /** |
|---|
| 2218 | 2158 | * smack_task_setscheduler - Smack check on setting scheduler |
|---|
| 2219 | 2159 | * @p: the task object |
|---|
| 2220 | | - * @policy: unused |
|---|
| 2221 | | - * @lp: unused |
|---|
| 2222 | 2160 | * |
|---|
| 2223 | 2161 | * Return 0 if read access is permitted |
|---|
| 2224 | 2162 | */ |
|---|
| .. | .. |
|---|
| 2259 | 2197 | * Return 0 if write access is permitted |
|---|
| 2260 | 2198 | * |
|---|
| 2261 | 2199 | */ |
|---|
| 2262 | | -static int smack_task_kill(struct task_struct *p, struct siginfo *info, |
|---|
| 2200 | +static int smack_task_kill(struct task_struct *p, struct kernel_siginfo *info, |
|---|
| 2263 | 2201 | int sig, const struct cred *cred) |
|---|
| 2264 | 2202 | { |
|---|
| 2265 | 2203 | struct smk_audit_info ad; |
|---|
| .. | .. |
|---|
| 2286 | 2224 | * specific behavior. This is not clean. For one thing |
|---|
| 2287 | 2225 | * we can't take privilege into account. |
|---|
| 2288 | 2226 | */ |
|---|
| 2289 | | - skp = smk_of_task(cred->security); |
|---|
| 2227 | + skp = smk_of_task(smack_cred(cred)); |
|---|
| 2290 | 2228 | rc = smk_access(skp, tkp, MAY_DELIVER, &ad); |
|---|
| 2291 | 2229 | rc = smk_bu_note("USB signal", skp, tkp, MAY_DELIVER, rc); |
|---|
| 2292 | 2230 | return rc; |
|---|
| .. | .. |
|---|
| 2301 | 2239 | */ |
|---|
| 2302 | 2240 | static void smack_task_to_inode(struct task_struct *p, struct inode *inode) |
|---|
| 2303 | 2241 | { |
|---|
| 2304 | | - struct inode_smack *isp = inode->i_security; |
|---|
| 2242 | + struct inode_smack *isp = smack_inode(inode); |
|---|
| 2305 | 2243 | struct smack_known *skp = smk_of_task_struct(p); |
|---|
| 2306 | 2244 | |
|---|
| 2307 | 2245 | isp->smk_inode = skp; |
|---|
| .. | .. |
|---|
| 2406 | 2344 | return NULL; |
|---|
| 2407 | 2345 | } |
|---|
| 2408 | 2346 | |
|---|
| 2409 | | -#if IS_ENABLED(CONFIG_IPV6) |
|---|
| 2410 | 2347 | /* |
|---|
| 2411 | 2348 | * smk_ipv6_localhost - Check for local ipv6 host address |
|---|
| 2412 | 2349 | * @sip: the address |
|---|
| .. | .. |
|---|
| 2474 | 2411 | |
|---|
| 2475 | 2412 | return NULL; |
|---|
| 2476 | 2413 | } |
|---|
| 2477 | | -#endif /* CONFIG_IPV6 */ |
|---|
| 2478 | 2414 | |
|---|
| 2479 | 2415 | /** |
|---|
| 2480 | | - * smack_netlabel - Set the secattr on a socket |
|---|
| 2416 | + * smack_netlbl_add - Set the secattr on a socket |
|---|
| 2481 | 2417 | * @sk: the socket |
|---|
| 2482 | | - * @labeled: socket label scheme |
|---|
| 2483 | 2418 | * |
|---|
| 2484 | | - * Convert the outbound smack value (smk_out) to a |
|---|
| 2485 | | - * secattr and attach it to the socket. |
|---|
| 2419 | + * Attach the outbound smack value (smk_out) to the socket. |
|---|
| 2486 | 2420 | * |
|---|
| 2487 | 2421 | * Returns 0 on success or an error code |
|---|
| 2488 | 2422 | */ |
|---|
| 2489 | | -static int smack_netlabel(struct sock *sk, int labeled) |
|---|
| 2423 | +static int smack_netlbl_add(struct sock *sk) |
|---|
| 2490 | 2424 | { |
|---|
| 2491 | | - struct smack_known *skp; |
|---|
| 2492 | 2425 | struct socket_smack *ssp = sk->sk_security; |
|---|
| 2493 | | - int rc = 0; |
|---|
| 2426 | + struct smack_known *skp = ssp->smk_out; |
|---|
| 2427 | + int rc; |
|---|
| 2494 | 2428 | |
|---|
| 2495 | | - /* |
|---|
| 2496 | | - * Usually the netlabel code will handle changing the |
|---|
| 2497 | | - * packet labeling based on the label. |
|---|
| 2498 | | - * The case of a single label host is different, because |
|---|
| 2499 | | - * a single label host should never get a labeled packet |
|---|
| 2500 | | - * even though the label is usually associated with a packet |
|---|
| 2501 | | - * label. |
|---|
| 2502 | | - */ |
|---|
| 2503 | 2429 | local_bh_disable(); |
|---|
| 2504 | 2430 | bh_lock_sock_nested(sk); |
|---|
| 2505 | 2431 | |
|---|
| 2506 | | - if (ssp->smk_out == smack_net_ambient || |
|---|
| 2507 | | - labeled == SMACK_UNLABELED_SOCKET) |
|---|
| 2508 | | - netlbl_sock_delattr(sk); |
|---|
| 2509 | | - else { |
|---|
| 2510 | | - skp = ssp->smk_out; |
|---|
| 2511 | | - rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel); |
|---|
| 2432 | + rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel); |
|---|
| 2433 | + switch (rc) { |
|---|
| 2434 | + case 0: |
|---|
| 2435 | + ssp->smk_state = SMK_NETLBL_LABELED; |
|---|
| 2436 | + break; |
|---|
| 2437 | + case -EDESTADDRREQ: |
|---|
| 2438 | + ssp->smk_state = SMK_NETLBL_REQSKB; |
|---|
| 2439 | + rc = 0; |
|---|
| 2440 | + break; |
|---|
| 2512 | 2441 | } |
|---|
| 2513 | 2442 | |
|---|
| 2514 | 2443 | bh_unlock_sock(sk); |
|---|
| .. | .. |
|---|
| 2518 | 2447 | } |
|---|
| 2519 | 2448 | |
|---|
| 2520 | 2449 | /** |
|---|
| 2521 | | - * smack_netlbel_send - Set the secattr on a socket and perform access checks |
|---|
| 2450 | + * smack_netlbl_delete - Remove the secattr from a socket |
|---|
| 2451 | + * @sk: the socket |
|---|
| 2452 | + * |
|---|
| 2453 | + * Remove the outbound smack value from a socket |
|---|
| 2454 | + */ |
|---|
| 2455 | +static void smack_netlbl_delete(struct sock *sk) |
|---|
| 2456 | +{ |
|---|
| 2457 | + struct socket_smack *ssp = sk->sk_security; |
|---|
| 2458 | + |
|---|
| 2459 | + /* |
|---|
| 2460 | + * Take the label off the socket if one is set. |
|---|
| 2461 | + */ |
|---|
| 2462 | + if (ssp->smk_state != SMK_NETLBL_LABELED) |
|---|
| 2463 | + return; |
|---|
| 2464 | + |
|---|
| 2465 | + local_bh_disable(); |
|---|
| 2466 | + bh_lock_sock_nested(sk); |
|---|
| 2467 | + netlbl_sock_delattr(sk); |
|---|
| 2468 | + bh_unlock_sock(sk); |
|---|
| 2469 | + local_bh_enable(); |
|---|
| 2470 | + ssp->smk_state = SMK_NETLBL_UNLABELED; |
|---|
| 2471 | +} |
|---|
| 2472 | + |
|---|
| 2473 | +/** |
|---|
| 2474 | + * smk_ipv4_check - Perform IPv4 host access checks |
|---|
| 2522 | 2475 | * @sk: the socket |
|---|
| 2523 | 2476 | * @sap: the destination address |
|---|
| 2524 | 2477 | * |
|---|
| .. | .. |
|---|
| 2528 | 2481 | * Returns 0 on success or an error code. |
|---|
| 2529 | 2482 | * |
|---|
| 2530 | 2483 | */ |
|---|
| 2531 | | -static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) |
|---|
| 2484 | +static int smk_ipv4_check(struct sock *sk, struct sockaddr_in *sap) |
|---|
| 2532 | 2485 | { |
|---|
| 2533 | 2486 | struct smack_known *skp; |
|---|
| 2534 | | - int rc; |
|---|
| 2535 | | - int sk_lbl; |
|---|
| 2487 | + int rc = 0; |
|---|
| 2536 | 2488 | struct smack_known *hkp; |
|---|
| 2537 | 2489 | struct socket_smack *ssp = sk->sk_security; |
|---|
| 2538 | 2490 | struct smk_audit_info ad; |
|---|
| .. | .. |
|---|
| 2548 | 2500 | ad.a.u.net->dport = sap->sin_port; |
|---|
| 2549 | 2501 | ad.a.u.net->v4info.daddr = sap->sin_addr.s_addr; |
|---|
| 2550 | 2502 | #endif |
|---|
| 2551 | | - sk_lbl = SMACK_UNLABELED_SOCKET; |
|---|
| 2552 | 2503 | skp = ssp->smk_out; |
|---|
| 2553 | 2504 | rc = smk_access(skp, hkp, MAY_WRITE, &ad); |
|---|
| 2554 | 2505 | rc = smk_bu_note("IPv4 host check", skp, hkp, MAY_WRITE, rc); |
|---|
| 2555 | | - } else { |
|---|
| 2556 | | - sk_lbl = SMACK_CIPSO_SOCKET; |
|---|
| 2557 | | - rc = 0; |
|---|
| 2506 | + /* |
|---|
| 2507 | + * Clear the socket netlabel if it's set. |
|---|
| 2508 | + */ |
|---|
| 2509 | + if (!rc) |
|---|
| 2510 | + smack_netlbl_delete(sk); |
|---|
| 2558 | 2511 | } |
|---|
| 2559 | 2512 | rcu_read_unlock(); |
|---|
| 2560 | | - if (rc != 0) |
|---|
| 2561 | | - return rc; |
|---|
| 2562 | 2513 | |
|---|
| 2563 | | - return smack_netlabel(sk, sk_lbl); |
|---|
| 2514 | + return rc; |
|---|
| 2564 | 2515 | } |
|---|
| 2565 | 2516 | |
|---|
| 2566 | | -#if IS_ENABLED(CONFIG_IPV6) |
|---|
| 2567 | 2517 | /** |
|---|
| 2568 | 2518 | * smk_ipv6_check - check Smack access |
|---|
| 2569 | 2519 | * @subject: subject Smack label |
|---|
| .. | .. |
|---|
| 2586 | 2536 | #ifdef CONFIG_AUDIT |
|---|
| 2587 | 2537 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); |
|---|
| 2588 | 2538 | ad.a.u.net->family = PF_INET6; |
|---|
| 2589 | | - ad.a.u.net->dport = ntohs(address->sin6_port); |
|---|
| 2539 | + ad.a.u.net->dport = address->sin6_port; |
|---|
| 2590 | 2540 | if (act == SMK_RECEIVING) |
|---|
| 2591 | 2541 | ad.a.u.net->v6info.saddr = address->sin6_addr; |
|---|
| 2592 | 2542 | else |
|---|
| .. | .. |
|---|
| 2596 | 2546 | rc = smk_bu_note("IPv6 check", subject, object, MAY_WRITE, rc); |
|---|
| 2597 | 2547 | return rc; |
|---|
| 2598 | 2548 | } |
|---|
| 2599 | | -#endif /* CONFIG_IPV6 */ |
|---|
| 2600 | 2549 | |
|---|
| 2601 | 2550 | #ifdef SMACK_IPV6_PORT_LABELING |
|---|
| 2602 | 2551 | /** |
|---|
| .. | .. |
|---|
| 2685 | 2634 | mutex_unlock(&smack_ipv6_lock); |
|---|
| 2686 | 2635 | return; |
|---|
| 2687 | 2636 | } |
|---|
| 2637 | +#endif |
|---|
| 2688 | 2638 | |
|---|
| 2689 | 2639 | /** |
|---|
| 2690 | 2640 | * smk_ipv6_port_check - check Smack port access |
|---|
| 2691 | | - * @sock: socket |
|---|
| 2641 | + * @sk: socket |
|---|
| 2692 | 2642 | * @address: address |
|---|
| 2643 | + * @act: the action being taken |
|---|
| 2693 | 2644 | * |
|---|
| 2694 | 2645 | * Create or update the port list entry |
|---|
| 2695 | 2646 | */ |
|---|
| .. | .. |
|---|
| 2746 | 2697 | |
|---|
| 2747 | 2698 | return smk_ipv6_check(skp, object, address, act); |
|---|
| 2748 | 2699 | } |
|---|
| 2749 | | -#endif /* SMACK_IPV6_PORT_LABELING */ |
|---|
| 2750 | 2700 | |
|---|
| 2751 | 2701 | /** |
|---|
| 2752 | 2702 | * smack_inode_setsecurity - set smack xattrs |
|---|
| .. | .. |
|---|
| 2764 | 2714 | const void *value, size_t size, int flags) |
|---|
| 2765 | 2715 | { |
|---|
| 2766 | 2716 | struct smack_known *skp; |
|---|
| 2767 | | - struct inode_smack *nsp = inode->i_security; |
|---|
| 2717 | + struct inode_smack *nsp = smack_inode(inode); |
|---|
| 2768 | 2718 | struct socket_smack *ssp; |
|---|
| 2769 | 2719 | struct socket *sock; |
|---|
| 2770 | 2720 | int rc = 0; |
|---|
| .. | .. |
|---|
| 2798 | 2748 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { |
|---|
| 2799 | 2749 | ssp->smk_out = skp; |
|---|
| 2800 | 2750 | if (sock->sk->sk_family == PF_INET) { |
|---|
| 2801 | | - rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); |
|---|
| 2751 | + rc = smack_netlbl_add(sock->sk); |
|---|
| 2802 | 2752 | if (rc != 0) |
|---|
| 2803 | 2753 | printk(KERN_WARNING |
|---|
| 2804 | 2754 | "Smack: \"%s\" netlbl error %d.\n", |
|---|
| .. | .. |
|---|
| 2849 | 2799 | /* |
|---|
| 2850 | 2800 | * Set the outbound netlbl. |
|---|
| 2851 | 2801 | */ |
|---|
| 2852 | | - return smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); |
|---|
| 2802 | + return smack_netlbl_add(sock->sk); |
|---|
| 2853 | 2803 | } |
|---|
| 2854 | 2804 | |
|---|
| 2855 | 2805 | /** |
|---|
| .. | .. |
|---|
| 2859 | 2809 | * |
|---|
| 2860 | 2810 | * Cross reference the peer labels for SO_PEERSEC |
|---|
| 2861 | 2811 | * |
|---|
| 2862 | | - * Returns 0 on success, and error code otherwise |
|---|
| 2812 | + * Returns 0 |
|---|
| 2863 | 2813 | */ |
|---|
| 2864 | 2814 | static int smack_socket_socketpair(struct socket *socka, |
|---|
| 2865 | 2815 | struct socket *sockb) |
|---|
| .. | .. |
|---|
| 2882 | 2832 | * |
|---|
| 2883 | 2833 | * Records the label bound to a port. |
|---|
| 2884 | 2834 | * |
|---|
| 2885 | | - * Returns 0 |
|---|
| 2835 | + * Returns 0 on success, and error code otherwise |
|---|
| 2886 | 2836 | */ |
|---|
| 2887 | 2837 | static int smack_socket_bind(struct socket *sock, struct sockaddr *address, |
|---|
| 2888 | 2838 | int addrlen) |
|---|
| 2889 | 2839 | { |
|---|
| 2890 | | - if (sock->sk != NULL && sock->sk->sk_family == PF_INET6) |
|---|
| 2840 | + if (sock->sk != NULL && sock->sk->sk_family == PF_INET6) { |
|---|
| 2841 | + if (addrlen < SIN6_LEN_RFC2133 || |
|---|
| 2842 | + address->sa_family != AF_INET6) |
|---|
| 2843 | + return -EINVAL; |
|---|
| 2891 | 2844 | smk_ipv6_port_label(sock, address); |
|---|
| 2845 | + } |
|---|
| 2892 | 2846 | return 0; |
|---|
| 2893 | 2847 | } |
|---|
| 2894 | 2848 | #endif /* SMACK_IPV6_PORT_LABELING */ |
|---|
| .. | .. |
|---|
| 2907 | 2861 | int addrlen) |
|---|
| 2908 | 2862 | { |
|---|
| 2909 | 2863 | int rc = 0; |
|---|
| 2910 | | -#if IS_ENABLED(CONFIG_IPV6) |
|---|
| 2911 | | - struct sockaddr_in6 *sip = (struct sockaddr_in6 *)sap; |
|---|
| 2912 | | -#endif |
|---|
| 2913 | | -#ifdef SMACK_IPV6_SECMARK_LABELING |
|---|
| 2914 | | - struct smack_known *rsp; |
|---|
| 2915 | | - struct socket_smack *ssp; |
|---|
| 2916 | | -#endif |
|---|
| 2917 | 2864 | |
|---|
| 2918 | 2865 | if (sock->sk == NULL) |
|---|
| 2919 | 2866 | return 0; |
|---|
| 2867 | + if (sock->sk->sk_family != PF_INET && |
|---|
| 2868 | + (!IS_ENABLED(CONFIG_IPV6) || sock->sk->sk_family != PF_INET6)) |
|---|
| 2869 | + return 0; |
|---|
| 2870 | + if (addrlen < offsetofend(struct sockaddr, sa_family)) |
|---|
| 2871 | + return 0; |
|---|
| 2872 | + if (IS_ENABLED(CONFIG_IPV6) && sap->sa_family == AF_INET6) { |
|---|
| 2873 | + struct sockaddr_in6 *sip = (struct sockaddr_in6 *)sap; |
|---|
| 2874 | + struct smack_known *rsp = NULL; |
|---|
| 2920 | 2875 | |
|---|
| 2921 | | -#ifdef SMACK_IPV6_SECMARK_LABELING |
|---|
| 2922 | | - ssp = sock->sk->sk_security; |
|---|
| 2923 | | -#endif |
|---|
| 2876 | + if (addrlen < SIN6_LEN_RFC2133) |
|---|
| 2877 | + return 0; |
|---|
| 2878 | + if (__is_defined(SMACK_IPV6_SECMARK_LABELING)) |
|---|
| 2879 | + rsp = smack_ipv6host_label(sip); |
|---|
| 2880 | + if (rsp != NULL) { |
|---|
| 2881 | + struct socket_smack *ssp = sock->sk->sk_security; |
|---|
| 2924 | 2882 | |
|---|
| 2925 | | - switch (sock->sk->sk_family) { |
|---|
| 2926 | | - case PF_INET: |
|---|
| 2927 | | - if (addrlen < sizeof(struct sockaddr_in)) |
|---|
| 2928 | | - return -EINVAL; |
|---|
| 2929 | | - rc = smack_netlabel_send(sock->sk, (struct sockaddr_in *)sap); |
|---|
| 2930 | | - break; |
|---|
| 2931 | | - case PF_INET6: |
|---|
| 2932 | | - if (addrlen < sizeof(struct sockaddr_in6)) |
|---|
| 2933 | | - return -EINVAL; |
|---|
| 2934 | | -#ifdef SMACK_IPV6_SECMARK_LABELING |
|---|
| 2935 | | - rsp = smack_ipv6host_label(sip); |
|---|
| 2936 | | - if (rsp != NULL) |
|---|
| 2937 | 2883 | rc = smk_ipv6_check(ssp->smk_out, rsp, sip, |
|---|
| 2938 | | - SMK_CONNECTING); |
|---|
| 2939 | | -#endif |
|---|
| 2940 | | -#ifdef SMACK_IPV6_PORT_LABELING |
|---|
| 2941 | | - rc = smk_ipv6_port_check(sock->sk, sip, SMK_CONNECTING); |
|---|
| 2942 | | -#endif |
|---|
| 2943 | | - break; |
|---|
| 2884 | + SMK_CONNECTING); |
|---|
| 2885 | + } |
|---|
| 2886 | + if (__is_defined(SMACK_IPV6_PORT_LABELING)) |
|---|
| 2887 | + rc = smk_ipv6_port_check(sock->sk, sip, SMK_CONNECTING); |
|---|
| 2888 | + |
|---|
| 2889 | + return rc; |
|---|
| 2944 | 2890 | } |
|---|
| 2891 | + if (sap->sa_family != AF_INET || addrlen < sizeof(struct sockaddr_in)) |
|---|
| 2892 | + return 0; |
|---|
| 2893 | + rc = smk_ipv4_check(sock->sk, (struct sockaddr_in *)sap); |
|---|
| 2945 | 2894 | return rc; |
|---|
| 2946 | 2895 | } |
|---|
| 2947 | 2896 | |
|---|
| .. | .. |
|---|
| 2973 | 2922 | */ |
|---|
| 2974 | 2923 | static int smack_msg_msg_alloc_security(struct msg_msg *msg) |
|---|
| 2975 | 2924 | { |
|---|
| 2976 | | - struct smack_known *skp = smk_of_current(); |
|---|
| 2925 | + struct smack_known **blob = smack_msg_msg(msg); |
|---|
| 2977 | 2926 | |
|---|
| 2978 | | - msg->security = skp; |
|---|
| 2927 | + *blob = smk_of_current(); |
|---|
| 2979 | 2928 | return 0; |
|---|
| 2980 | | -} |
|---|
| 2981 | | - |
|---|
| 2982 | | -/** |
|---|
| 2983 | | - * smack_msg_msg_free_security - Clear the security blob for msg_msg |
|---|
| 2984 | | - * @msg: the object |
|---|
| 2985 | | - * |
|---|
| 2986 | | - * Clears the blob pointer |
|---|
| 2987 | | - */ |
|---|
| 2988 | | -static void smack_msg_msg_free_security(struct msg_msg *msg) |
|---|
| 2989 | | -{ |
|---|
| 2990 | | - msg->security = NULL; |
|---|
| 2991 | 2929 | } |
|---|
| 2992 | 2930 | |
|---|
| 2993 | 2931 | /** |
|---|
| .. | .. |
|---|
| 2998 | 2936 | */ |
|---|
| 2999 | 2937 | static struct smack_known *smack_of_ipc(struct kern_ipc_perm *isp) |
|---|
| 3000 | 2938 | { |
|---|
| 3001 | | - return (struct smack_known *)isp->security; |
|---|
| 2939 | + struct smack_known **blob = smack_ipc(isp); |
|---|
| 2940 | + |
|---|
| 2941 | + return *blob; |
|---|
| 3002 | 2942 | } |
|---|
| 3003 | 2943 | |
|---|
| 3004 | 2944 | /** |
|---|
| .. | .. |
|---|
| 3009 | 2949 | */ |
|---|
| 3010 | 2950 | static int smack_ipc_alloc_security(struct kern_ipc_perm *isp) |
|---|
| 3011 | 2951 | { |
|---|
| 3012 | | - struct smack_known *skp = smk_of_current(); |
|---|
| 2952 | + struct smack_known **blob = smack_ipc(isp); |
|---|
| 3013 | 2953 | |
|---|
| 3014 | | - isp->security = skp; |
|---|
| 2954 | + *blob = smk_of_current(); |
|---|
| 3015 | 2955 | return 0; |
|---|
| 3016 | | -} |
|---|
| 3017 | | - |
|---|
| 3018 | | -/** |
|---|
| 3019 | | - * smack_ipc_free_security - Clear the security blob for ipc |
|---|
| 3020 | | - * @isp: the object |
|---|
| 3021 | | - * |
|---|
| 3022 | | - * Clears the blob pointer |
|---|
| 3023 | | - */ |
|---|
| 3024 | | -static void smack_ipc_free_security(struct kern_ipc_perm *isp) |
|---|
| 3025 | | -{ |
|---|
| 3026 | | - isp->security = NULL; |
|---|
| 3027 | 2956 | } |
|---|
| 3028 | 2957 | |
|---|
| 3029 | 2958 | /** |
|---|
| .. | .. |
|---|
| 3106 | 3035 | * |
|---|
| 3107 | 3036 | * Returns 0 if current has the requested access, error code otherwise |
|---|
| 3108 | 3037 | */ |
|---|
| 3109 | | -static int smack_shm_shmat(struct kern_ipc_perm *ipc, char __user *shmaddr, |
|---|
| 3038 | +static int smack_shm_shmat(struct kern_ipc_perm *isp, char __user *shmaddr, |
|---|
| 3110 | 3039 | int shmflg) |
|---|
| 3111 | 3040 | { |
|---|
| 3112 | 3041 | int may; |
|---|
| 3113 | 3042 | |
|---|
| 3114 | 3043 | may = smack_flags_to_may(shmflg); |
|---|
| 3115 | | - return smk_curacc_shm(ipc, may); |
|---|
| 3044 | + return smk_curacc_shm(isp, may); |
|---|
| 3116 | 3045 | } |
|---|
| 3117 | 3046 | |
|---|
| 3118 | 3047 | /** |
|---|
| .. | .. |
|---|
| 3323 | 3252 | */ |
|---|
| 3324 | 3253 | static int smack_ipc_permission(struct kern_ipc_perm *ipp, short flag) |
|---|
| 3325 | 3254 | { |
|---|
| 3326 | | - struct smack_known *iskp = ipp->security; |
|---|
| 3255 | + struct smack_known **blob = smack_ipc(ipp); |
|---|
| 3256 | + struct smack_known *iskp = *blob; |
|---|
| 3327 | 3257 | int may = smack_flags_to_may(flag); |
|---|
| 3328 | 3258 | struct smk_audit_info ad; |
|---|
| 3329 | 3259 | int rc; |
|---|
| .. | .. |
|---|
| 3344 | 3274 | */ |
|---|
| 3345 | 3275 | static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid) |
|---|
| 3346 | 3276 | { |
|---|
| 3347 | | - struct smack_known *iskp = ipp->security; |
|---|
| 3277 | + struct smack_known **blob = smack_ipc(ipp); |
|---|
| 3278 | + struct smack_known *iskp = *blob; |
|---|
| 3348 | 3279 | |
|---|
| 3349 | 3280 | *secid = iskp->smk_secid; |
|---|
| 3350 | 3281 | } |
|---|
| .. | .. |
|---|
| 3372 | 3303 | if (inode == NULL) |
|---|
| 3373 | 3304 | return; |
|---|
| 3374 | 3305 | |
|---|
| 3375 | | - isp = inode->i_security; |
|---|
| 3306 | + isp = smack_inode(inode); |
|---|
| 3376 | 3307 | |
|---|
| 3377 | | - mutex_lock(&isp->smk_lock); |
|---|
| 3378 | 3308 | /* |
|---|
| 3379 | 3309 | * If the inode is already instantiated |
|---|
| 3380 | 3310 | * take the quick way out |
|---|
| 3381 | 3311 | */ |
|---|
| 3382 | 3312 | if (isp->smk_flags & SMK_INODE_INSTANT) |
|---|
| 3383 | | - goto unlockandout; |
|---|
| 3313 | + return; |
|---|
| 3384 | 3314 | |
|---|
| 3385 | 3315 | sbp = inode->i_sb; |
|---|
| 3386 | 3316 | sbsp = sbp->s_security; |
|---|
| .. | .. |
|---|
| 3431 | 3361 | break; |
|---|
| 3432 | 3362 | } |
|---|
| 3433 | 3363 | isp->smk_flags |= SMK_INODE_INSTANT; |
|---|
| 3434 | | - goto unlockandout; |
|---|
| 3364 | + return; |
|---|
| 3435 | 3365 | } |
|---|
| 3436 | 3366 | |
|---|
| 3437 | 3367 | /* |
|---|
| .. | .. |
|---|
| 3475 | 3405 | */ |
|---|
| 3476 | 3406 | final = &smack_known_star; |
|---|
| 3477 | 3407 | /* |
|---|
| 3478 | | - * No break. |
|---|
| 3479 | | - * |
|---|
| 3480 | 3408 | * If a smack value has been set we want to use it, |
|---|
| 3481 | 3409 | * but since tmpfs isn't giving us the opportunity |
|---|
| 3482 | 3410 | * to set mount options simulate setting the |
|---|
| 3483 | 3411 | * superblock default. |
|---|
| 3484 | 3412 | */ |
|---|
| 3413 | + fallthrough; |
|---|
| 3485 | 3414 | default: |
|---|
| 3486 | 3415 | /* |
|---|
| 3487 | 3416 | * This isn't an understood special case. |
|---|
| .. | .. |
|---|
| 3533 | 3462 | } else { |
|---|
| 3534 | 3463 | rc = __vfs_getxattr(dp, inode, |
|---|
| 3535 | 3464 | XATTR_NAME_SMACKTRANSMUTE, trattr, |
|---|
| 3536 | | - TRANS_TRUE_SIZE); |
|---|
| 3465 | + TRANS_TRUE_SIZE, XATTR_NOSECURITY); |
|---|
| 3537 | 3466 | if (rc >= 0 && strncmp(trattr, TRANS_TRUE, |
|---|
| 3538 | 3467 | TRANS_TRUE_SIZE) != 0) |
|---|
| 3539 | 3468 | rc = -EINVAL; |
|---|
| .. | .. |
|---|
| 3567 | 3496 | |
|---|
| 3568 | 3497 | isp->smk_flags |= (SMK_INODE_INSTANT | transflag); |
|---|
| 3569 | 3498 | |
|---|
| 3570 | | -unlockandout: |
|---|
| 3571 | | - mutex_unlock(&isp->smk_lock); |
|---|
| 3572 | 3499 | return; |
|---|
| 3573 | 3500 | } |
|---|
| 3574 | 3501 | |
|---|
| .. | .. |
|---|
| 3613 | 3540 | */ |
|---|
| 3614 | 3541 | static int smack_setprocattr(const char *name, void *value, size_t size) |
|---|
| 3615 | 3542 | { |
|---|
| 3616 | | - struct task_smack *tsp = current_security(); |
|---|
| 3543 | + struct task_smack *tsp = smack_cred(current_cred()); |
|---|
| 3617 | 3544 | struct cred *new; |
|---|
| 3618 | 3545 | struct smack_known *skp; |
|---|
| 3619 | 3546 | struct smack_known_list_elem *sklep; |
|---|
| .. | .. |
|---|
| 3654 | 3581 | if (new == NULL) |
|---|
| 3655 | 3582 | return -ENOMEM; |
|---|
| 3656 | 3583 | |
|---|
| 3657 | | - tsp = new->security; |
|---|
| 3584 | + tsp = smack_cred(new); |
|---|
| 3658 | 3585 | tsp->smk_task = skp; |
|---|
| 3659 | 3586 | /* |
|---|
| 3660 | 3587 | * process can change its label only once |
|---|
| .. | .. |
|---|
| 3778 | 3705 | |
|---|
| 3779 | 3706 | switch (sock->sk->sk_family) { |
|---|
| 3780 | 3707 | case AF_INET: |
|---|
| 3781 | | - rc = smack_netlabel_send(sock->sk, sip); |
|---|
| 3708 | + if (msg->msg_namelen < sizeof(struct sockaddr_in) || |
|---|
| 3709 | + sip->sin_family != AF_INET) |
|---|
| 3710 | + return -EINVAL; |
|---|
| 3711 | + rc = smk_ipv4_check(sock->sk, sip); |
|---|
| 3782 | 3712 | break; |
|---|
| 3713 | +#if IS_ENABLED(CONFIG_IPV6) |
|---|
| 3783 | 3714 | case AF_INET6: |
|---|
| 3715 | + if (msg->msg_namelen < SIN6_LEN_RFC2133 || |
|---|
| 3716 | + sap->sin6_family != AF_INET6) |
|---|
| 3717 | + return -EINVAL; |
|---|
| 3784 | 3718 | #ifdef SMACK_IPV6_SECMARK_LABELING |
|---|
| 3785 | 3719 | rsp = smack_ipv6host_label(sap); |
|---|
| 3786 | 3720 | if (rsp != NULL) |
|---|
| .. | .. |
|---|
| 3790 | 3724 | #ifdef SMACK_IPV6_PORT_LABELING |
|---|
| 3791 | 3725 | rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING); |
|---|
| 3792 | 3726 | #endif |
|---|
| 3727 | +#endif /* IS_ENABLED(CONFIG_IPV6) */ |
|---|
| 3793 | 3728 | break; |
|---|
| 3794 | 3729 | } |
|---|
| 3795 | 3730 | return rc; |
|---|
| .. | .. |
|---|
| 3809 | 3744 | int found = 0; |
|---|
| 3810 | 3745 | int acat; |
|---|
| 3811 | 3746 | int kcat; |
|---|
| 3747 | + |
|---|
| 3748 | + /* |
|---|
| 3749 | + * Netlabel found it in the cache. |
|---|
| 3750 | + */ |
|---|
| 3751 | + if ((sap->flags & NETLBL_SECATTR_CACHE) != 0) |
|---|
| 3752 | + return (struct smack_known *)sap->cache->data; |
|---|
| 3753 | + |
|---|
| 3754 | + if ((sap->flags & NETLBL_SECATTR_SECID) != 0) |
|---|
| 3755 | + /* |
|---|
| 3756 | + * Looks like a fallback, which gives us a secid. |
|---|
| 3757 | + */ |
|---|
| 3758 | + return smack_from_secid(sap->attr.secid); |
|---|
| 3812 | 3759 | |
|---|
| 3813 | 3760 | if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) { |
|---|
| 3814 | 3761 | /* |
|---|
| .. | .. |
|---|
| 3857 | 3804 | return &smack_known_web; |
|---|
| 3858 | 3805 | return &smack_known_star; |
|---|
| 3859 | 3806 | } |
|---|
| 3860 | | - if ((sap->flags & NETLBL_SECATTR_SECID) != 0) |
|---|
| 3861 | | - /* |
|---|
| 3862 | | - * Looks like a fallback, which gives us a secid. |
|---|
| 3863 | | - */ |
|---|
| 3864 | | - return smack_from_secid(sap->attr.secid); |
|---|
| 3865 | 3807 | /* |
|---|
| 3866 | 3808 | * Without guidance regarding the smack value |
|---|
| 3867 | 3809 | * for the packet fall back on the network |
|---|
| .. | .. |
|---|
| 3921 | 3863 | #endif /* CONFIG_IPV6 */ |
|---|
| 3922 | 3864 | |
|---|
| 3923 | 3865 | /** |
|---|
| 3866 | + * smack_from_skb - Smack data from the secmark in an skb |
|---|
| 3867 | + * @skb: packet |
|---|
| 3868 | + * |
|---|
| 3869 | + * Returns smack_known of the secmark or NULL if that won't work. |
|---|
| 3870 | + */ |
|---|
| 3871 | +#ifdef CONFIG_NETWORK_SECMARK |
|---|
| 3872 | +static struct smack_known *smack_from_skb(struct sk_buff *skb) |
|---|
| 3873 | +{ |
|---|
| 3874 | + if (skb == NULL || skb->secmark == 0) |
|---|
| 3875 | + return NULL; |
|---|
| 3876 | + |
|---|
| 3877 | + return smack_from_secid(skb->secmark); |
|---|
| 3878 | +} |
|---|
| 3879 | +#else |
|---|
| 3880 | +static inline struct smack_known *smack_from_skb(struct sk_buff *skb) |
|---|
| 3881 | +{ |
|---|
| 3882 | + return NULL; |
|---|
| 3883 | +} |
|---|
| 3884 | +#endif |
|---|
| 3885 | + |
|---|
| 3886 | +/** |
|---|
| 3887 | + * smack_from_netlbl - Smack data from the IP options in an skb |
|---|
| 3888 | + * @sk: socket data came in on |
|---|
| 3889 | + * @family: address family |
|---|
| 3890 | + * @skb: packet |
|---|
| 3891 | + * |
|---|
| 3892 | + * Find the Smack label in the IP options. If it hasn't been |
|---|
| 3893 | + * added to the netlabel cache, add it here. |
|---|
| 3894 | + * |
|---|
| 3895 | + * Returns smack_known of the IP options or NULL if that won't work. |
|---|
| 3896 | + */ |
|---|
| 3897 | +static struct smack_known *smack_from_netlbl(struct sock *sk, u16 family, |
|---|
| 3898 | + struct sk_buff *skb) |
|---|
| 3899 | +{ |
|---|
| 3900 | + struct netlbl_lsm_secattr secattr; |
|---|
| 3901 | + struct socket_smack *ssp = NULL; |
|---|
| 3902 | + struct smack_known *skp = NULL; |
|---|
| 3903 | + int rc; |
|---|
| 3904 | + |
|---|
| 3905 | + netlbl_secattr_init(&secattr); |
|---|
| 3906 | + |
|---|
| 3907 | + if (sk) |
|---|
| 3908 | + ssp = sk->sk_security; |
|---|
| 3909 | + |
|---|
| 3910 | + if (netlbl_skbuff_getattr(skb, family, &secattr) == 0) { |
|---|
| 3911 | + skp = smack_from_secattr(&secattr, ssp); |
|---|
| 3912 | + if (secattr.flags & NETLBL_SECATTR_CACHEABLE) |
|---|
| 3913 | + rc = netlbl_cache_add(skb, family, &skp->smk_netlabel); |
|---|
| 3914 | + } |
|---|
| 3915 | + |
|---|
| 3916 | + netlbl_secattr_destroy(&secattr); |
|---|
| 3917 | + |
|---|
| 3918 | + return skp; |
|---|
| 3919 | +} |
|---|
| 3920 | + |
|---|
| 3921 | +/** |
|---|
| 3924 | 3922 | * smack_socket_sock_rcv_skb - Smack packet delivery access check |
|---|
| 3925 | 3923 | * @sk: socket |
|---|
| 3926 | 3924 | * @skb: packet |
|---|
| .. | .. |
|---|
| 3929 | 3927 | */ |
|---|
| 3930 | 3928 | static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) |
|---|
| 3931 | 3929 | { |
|---|
| 3932 | | - struct netlbl_lsm_secattr secattr; |
|---|
| 3933 | 3930 | struct socket_smack *ssp = sk->sk_security; |
|---|
| 3934 | 3931 | struct smack_known *skp = NULL; |
|---|
| 3935 | 3932 | int rc = 0; |
|---|
| .. | .. |
|---|
| 3948 | 3945 | |
|---|
| 3949 | 3946 | switch (family) { |
|---|
| 3950 | 3947 | case PF_INET: |
|---|
| 3951 | | -#ifdef CONFIG_SECURITY_SMACK_NETFILTER |
|---|
| 3952 | 3948 | /* |
|---|
| 3953 | 3949 | * If there is a secmark use it rather than the CIPSO label. |
|---|
| 3954 | 3950 | * If there is no secmark fall back to CIPSO. |
|---|
| 3955 | 3951 | * The secmark is assumed to reflect policy better. |
|---|
| 3956 | 3952 | */ |
|---|
| 3957 | | - if (skb && skb->secmark != 0) { |
|---|
| 3958 | | - skp = smack_from_secid(skb->secmark); |
|---|
| 3959 | | - goto access_check; |
|---|
| 3953 | + skp = smack_from_skb(skb); |
|---|
| 3954 | + if (skp == NULL) { |
|---|
| 3955 | + skp = smack_from_netlbl(sk, family, skb); |
|---|
| 3956 | + if (skp == NULL) |
|---|
| 3957 | + skp = smack_net_ambient; |
|---|
| 3960 | 3958 | } |
|---|
| 3961 | | -#endif /* CONFIG_SECURITY_SMACK_NETFILTER */ |
|---|
| 3962 | | - /* |
|---|
| 3963 | | - * Translate what netlabel gave us. |
|---|
| 3964 | | - */ |
|---|
| 3965 | | - netlbl_secattr_init(&secattr); |
|---|
| 3966 | 3959 | |
|---|
| 3967 | | - rc = netlbl_skbuff_getattr(skb, family, &secattr); |
|---|
| 3968 | | - if (rc == 0) |
|---|
| 3969 | | - skp = smack_from_secattr(&secattr, ssp); |
|---|
| 3970 | | - else |
|---|
| 3971 | | - skp = smack_net_ambient; |
|---|
| 3972 | | - |
|---|
| 3973 | | - netlbl_secattr_destroy(&secattr); |
|---|
| 3974 | | - |
|---|
| 3975 | | -#ifdef CONFIG_SECURITY_SMACK_NETFILTER |
|---|
| 3976 | | -access_check: |
|---|
| 3977 | | -#endif |
|---|
| 3978 | 3960 | #ifdef CONFIG_AUDIT |
|---|
| 3979 | 3961 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); |
|---|
| 3980 | 3962 | ad.a.u.net->family = family; |
|---|
| .. | .. |
|---|
| 4000 | 3982 | proto != IPPROTO_TCP && proto != IPPROTO_DCCP) |
|---|
| 4001 | 3983 | break; |
|---|
| 4002 | 3984 | #ifdef SMACK_IPV6_SECMARK_LABELING |
|---|
| 4003 | | - if (skb && skb->secmark != 0) |
|---|
| 4004 | | - skp = smack_from_secid(skb->secmark); |
|---|
| 4005 | | - else |
|---|
| 3985 | + skp = smack_from_skb(skb); |
|---|
| 3986 | + if (skp == NULL) { |
|---|
| 3987 | + if (smk_ipv6_localhost(&sadd)) |
|---|
| 3988 | + break; |
|---|
| 4006 | 3989 | skp = smack_ipv6host_label(&sadd); |
|---|
| 4007 | | - if (skp == NULL) |
|---|
| 4008 | | - skp = smack_net_ambient; |
|---|
| 4009 | | - if (skb == NULL) |
|---|
| 4010 | | - break; |
|---|
| 3990 | + if (skp == NULL) |
|---|
| 3991 | + skp = smack_net_ambient; |
|---|
| 3992 | + } |
|---|
| 4011 | 3993 | #ifdef CONFIG_AUDIT |
|---|
| 4012 | 3994 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); |
|---|
| 4013 | 3995 | ad.a.u.net->family = family; |
|---|
| .. | .. |
|---|
| 4079 | 4061 | struct sk_buff *skb, u32 *secid) |
|---|
| 4080 | 4062 | |
|---|
| 4081 | 4063 | { |
|---|
| 4082 | | - struct netlbl_lsm_secattr secattr; |
|---|
| 4083 | 4064 | struct socket_smack *ssp = NULL; |
|---|
| 4084 | 4065 | struct smack_known *skp; |
|---|
| 4066 | + struct sock *sk = NULL; |
|---|
| 4085 | 4067 | int family = PF_UNSPEC; |
|---|
| 4086 | 4068 | u32 s = 0; /* 0 is the invalid secid */ |
|---|
| 4087 | | - int rc; |
|---|
| 4088 | 4069 | |
|---|
| 4089 | 4070 | if (skb != NULL) { |
|---|
| 4090 | 4071 | if (skb->protocol == htons(ETH_P_IP)) |
|---|
| .. | .. |
|---|
| 4103 | 4084 | s = ssp->smk_out->smk_secid; |
|---|
| 4104 | 4085 | break; |
|---|
| 4105 | 4086 | case PF_INET: |
|---|
| 4106 | | -#ifdef CONFIG_SECURITY_SMACK_NETFILTER |
|---|
| 4107 | | - s = skb->secmark; |
|---|
| 4108 | | - if (s != 0) |
|---|
| 4087 | + skp = smack_from_skb(skb); |
|---|
| 4088 | + if (skp) { |
|---|
| 4089 | + s = skp->smk_secid; |
|---|
| 4109 | 4090 | break; |
|---|
| 4110 | | -#endif |
|---|
| 4091 | + } |
|---|
| 4111 | 4092 | /* |
|---|
| 4112 | 4093 | * Translate what netlabel gave us. |
|---|
| 4113 | 4094 | */ |
|---|
| 4114 | | - if (sock != NULL && sock->sk != NULL) |
|---|
| 4115 | | - ssp = sock->sk->sk_security; |
|---|
| 4116 | | - netlbl_secattr_init(&secattr); |
|---|
| 4117 | | - rc = netlbl_skbuff_getattr(skb, family, &secattr); |
|---|
| 4118 | | - if (rc == 0) { |
|---|
| 4119 | | - skp = smack_from_secattr(&secattr, ssp); |
|---|
| 4095 | + if (sock != NULL) |
|---|
| 4096 | + sk = sock->sk; |
|---|
| 4097 | + skp = smack_from_netlbl(sk, family, skb); |
|---|
| 4098 | + if (skp != NULL) |
|---|
| 4120 | 4099 | s = skp->smk_secid; |
|---|
| 4121 | | - } |
|---|
| 4122 | | - netlbl_secattr_destroy(&secattr); |
|---|
| 4123 | 4100 | break; |
|---|
| 4124 | 4101 | case PF_INET6: |
|---|
| 4125 | 4102 | #ifdef SMACK_IPV6_SECMARK_LABELING |
|---|
| 4126 | | - s = skb->secmark; |
|---|
| 4103 | + skp = smack_from_skb(skb); |
|---|
| 4104 | + if (skp) |
|---|
| 4105 | + s = skp->smk_secid; |
|---|
| 4127 | 4106 | #endif |
|---|
| 4128 | 4107 | break; |
|---|
| 4129 | 4108 | } |
|---|
| .. | .. |
|---|
| 4171 | 4150 | u16 family = sk->sk_family; |
|---|
| 4172 | 4151 | struct smack_known *skp; |
|---|
| 4173 | 4152 | struct socket_smack *ssp = sk->sk_security; |
|---|
| 4174 | | - struct netlbl_lsm_secattr secattr; |
|---|
| 4175 | 4153 | struct sockaddr_in addr; |
|---|
| 4176 | 4154 | struct iphdr *hdr; |
|---|
| 4177 | 4155 | struct smack_known *hskp; |
|---|
| .. | .. |
|---|
| 4195 | 4173 | } |
|---|
| 4196 | 4174 | #endif /* CONFIG_IPV6 */ |
|---|
| 4197 | 4175 | |
|---|
| 4198 | | -#ifdef CONFIG_SECURITY_SMACK_NETFILTER |
|---|
| 4199 | 4176 | /* |
|---|
| 4200 | 4177 | * If there is a secmark use it rather than the CIPSO label. |
|---|
| 4201 | 4178 | * If there is no secmark fall back to CIPSO. |
|---|
| 4202 | 4179 | * The secmark is assumed to reflect policy better. |
|---|
| 4203 | 4180 | */ |
|---|
| 4204 | | - if (skb && skb->secmark != 0) { |
|---|
| 4205 | | - skp = smack_from_secid(skb->secmark); |
|---|
| 4206 | | - goto access_check; |
|---|
| 4181 | + skp = smack_from_skb(skb); |
|---|
| 4182 | + if (skp == NULL) { |
|---|
| 4183 | + skp = smack_from_netlbl(sk, family, skb); |
|---|
| 4184 | + if (skp == NULL) |
|---|
| 4185 | + skp = &smack_known_huh; |
|---|
| 4207 | 4186 | } |
|---|
| 4208 | | -#endif /* CONFIG_SECURITY_SMACK_NETFILTER */ |
|---|
| 4209 | | - |
|---|
| 4210 | | - netlbl_secattr_init(&secattr); |
|---|
| 4211 | | - rc = netlbl_skbuff_getattr(skb, family, &secattr); |
|---|
| 4212 | | - if (rc == 0) |
|---|
| 4213 | | - skp = smack_from_secattr(&secattr, ssp); |
|---|
| 4214 | | - else |
|---|
| 4215 | | - skp = &smack_known_huh; |
|---|
| 4216 | | - netlbl_secattr_destroy(&secattr); |
|---|
| 4217 | | - |
|---|
| 4218 | | -#ifdef CONFIG_SECURITY_SMACK_NETFILTER |
|---|
| 4219 | | -access_check: |
|---|
| 4220 | | -#endif |
|---|
| 4221 | 4187 | |
|---|
| 4222 | 4188 | #ifdef CONFIG_AUDIT |
|---|
| 4223 | 4189 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); |
|---|
| .. | .. |
|---|
| 4301 | 4267 | static int smack_key_alloc(struct key *key, const struct cred *cred, |
|---|
| 4302 | 4268 | unsigned long flags) |
|---|
| 4303 | 4269 | { |
|---|
| 4304 | | - struct smack_known *skp = smk_of_task(cred->security); |
|---|
| 4270 | + struct smack_known *skp = smk_of_task(smack_cred(cred)); |
|---|
| 4305 | 4271 | |
|---|
| 4306 | 4272 | key->security = skp; |
|---|
| 4307 | 4273 | return 0; |
|---|
| .. | .. |
|---|
| 4322 | 4288 | * smack_key_permission - Smack access on a key |
|---|
| 4323 | 4289 | * @key_ref: gets to the object |
|---|
| 4324 | 4290 | * @cred: the credentials to use |
|---|
| 4325 | | - * @perm: requested key permissions |
|---|
| 4291 | + * @need_perm: requested key permission |
|---|
| 4326 | 4292 | * |
|---|
| 4327 | 4293 | * Return 0 if the task has read and write to the object, |
|---|
| 4328 | 4294 | * an error code otherwise |
|---|
| 4329 | 4295 | */ |
|---|
| 4330 | 4296 | static int smack_key_permission(key_ref_t key_ref, |
|---|
| 4331 | | - const struct cred *cred, unsigned perm) |
|---|
| 4297 | + const struct cred *cred, |
|---|
| 4298 | + enum key_need_perm need_perm) |
|---|
| 4332 | 4299 | { |
|---|
| 4333 | 4300 | struct key *keyp; |
|---|
| 4334 | 4301 | struct smk_audit_info ad; |
|---|
| 4335 | | - struct smack_known *tkp = smk_of_task(cred->security); |
|---|
| 4302 | + struct smack_known *tkp = smk_of_task(smack_cred(cred)); |
|---|
| 4336 | 4303 | int request = 0; |
|---|
| 4337 | 4304 | int rc; |
|---|
| 4338 | 4305 | |
|---|
| 4339 | 4306 | /* |
|---|
| 4340 | 4307 | * Validate requested permissions |
|---|
| 4341 | 4308 | */ |
|---|
| 4342 | | - if (perm & ~KEY_NEED_ALL) |
|---|
| 4309 | + switch (need_perm) { |
|---|
| 4310 | + case KEY_NEED_READ: |
|---|
| 4311 | + case KEY_NEED_SEARCH: |
|---|
| 4312 | + case KEY_NEED_VIEW: |
|---|
| 4313 | + request |= MAY_READ; |
|---|
| 4314 | + break; |
|---|
| 4315 | + case KEY_NEED_WRITE: |
|---|
| 4316 | + case KEY_NEED_LINK: |
|---|
| 4317 | + case KEY_NEED_SETATTR: |
|---|
| 4318 | + request |= MAY_WRITE; |
|---|
| 4319 | + break; |
|---|
| 4320 | + case KEY_NEED_UNSPECIFIED: |
|---|
| 4321 | + case KEY_NEED_UNLINK: |
|---|
| 4322 | + case KEY_SYSADMIN_OVERRIDE: |
|---|
| 4323 | + case KEY_AUTHTOKEN_OVERRIDE: |
|---|
| 4324 | + case KEY_DEFER_PERM_CHECK: |
|---|
| 4325 | + return 0; |
|---|
| 4326 | + default: |
|---|
| 4343 | 4327 | return -EINVAL; |
|---|
| 4328 | + } |
|---|
| 4344 | 4329 | |
|---|
| 4345 | 4330 | keyp = key_ref_to_ptr(key_ref); |
|---|
| 4346 | 4331 | if (keyp == NULL) |
|---|
| .. | .. |
|---|
| 4357 | 4342 | if (tkp == NULL) |
|---|
| 4358 | 4343 | return -EACCES; |
|---|
| 4359 | 4344 | |
|---|
| 4360 | | - if (smack_privileged_cred(CAP_MAC_OVERRIDE, cred)) |
|---|
| 4345 | + if (smack_privileged(CAP_MAC_OVERRIDE)) |
|---|
| 4361 | 4346 | return 0; |
|---|
| 4362 | 4347 | |
|---|
| 4363 | 4348 | #ifdef CONFIG_AUDIT |
|---|
| .. | .. |
|---|
| 4365 | 4350 | ad.a.u.key_struct.key = keyp->serial; |
|---|
| 4366 | 4351 | ad.a.u.key_struct.key_desc = keyp->description; |
|---|
| 4367 | 4352 | #endif |
|---|
| 4368 | | - if (perm & (KEY_NEED_READ | KEY_NEED_SEARCH | KEY_NEED_VIEW)) |
|---|
| 4369 | | - request |= MAY_READ; |
|---|
| 4370 | | - if (perm & (KEY_NEED_WRITE | KEY_NEED_LINK | KEY_NEED_SETATTR)) |
|---|
| 4371 | | - request |= MAY_WRITE; |
|---|
| 4372 | 4353 | rc = smk_access(tkp, keyp->security, request, &ad); |
|---|
| 4373 | 4354 | rc = smk_bu_note("key access", tkp, keyp->security, request, rc); |
|---|
| 4374 | 4355 | return rc; |
|---|
| .. | .. |
|---|
| 4403 | 4384 | return length; |
|---|
| 4404 | 4385 | } |
|---|
| 4405 | 4386 | |
|---|
| 4387 | + |
|---|
| 4388 | +#ifdef CONFIG_KEY_NOTIFICATIONS |
|---|
| 4389 | +/** |
|---|
| 4390 | + * smack_watch_key - Smack access to watch a key for notifications. |
|---|
| 4391 | + * @key: The key to be watched |
|---|
| 4392 | + * |
|---|
| 4393 | + * Return 0 if the @watch->cred has permission to read from the key object and |
|---|
| 4394 | + * an error otherwise. |
|---|
| 4395 | + */ |
|---|
| 4396 | +static int smack_watch_key(struct key *key) |
|---|
| 4397 | +{ |
|---|
| 4398 | + struct smk_audit_info ad; |
|---|
| 4399 | + struct smack_known *tkp = smk_of_current(); |
|---|
| 4400 | + int rc; |
|---|
| 4401 | + |
|---|
| 4402 | + if (key == NULL) |
|---|
| 4403 | + return -EINVAL; |
|---|
| 4404 | + /* |
|---|
| 4405 | + * If the key hasn't been initialized give it access so that |
|---|
| 4406 | + * it may do so. |
|---|
| 4407 | + */ |
|---|
| 4408 | + if (key->security == NULL) |
|---|
| 4409 | + return 0; |
|---|
| 4410 | + /* |
|---|
| 4411 | + * This should not occur |
|---|
| 4412 | + */ |
|---|
| 4413 | + if (tkp == NULL) |
|---|
| 4414 | + return -EACCES; |
|---|
| 4415 | + |
|---|
| 4416 | + if (smack_privileged_cred(CAP_MAC_OVERRIDE, current_cred())) |
|---|
| 4417 | + return 0; |
|---|
| 4418 | + |
|---|
| 4419 | +#ifdef CONFIG_AUDIT |
|---|
| 4420 | + smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_KEY); |
|---|
| 4421 | + ad.a.u.key_struct.key = key->serial; |
|---|
| 4422 | + ad.a.u.key_struct.key_desc = key->description; |
|---|
| 4423 | +#endif |
|---|
| 4424 | + rc = smk_access(tkp, key->security, MAY_READ, &ad); |
|---|
| 4425 | + rc = smk_bu_note("key watch", tkp, key->security, MAY_READ, rc); |
|---|
| 4426 | + return rc; |
|---|
| 4427 | +} |
|---|
| 4428 | +#endif /* CONFIG_KEY_NOTIFICATIONS */ |
|---|
| 4406 | 4429 | #endif /* CONFIG_KEYS */ |
|---|
| 4430 | + |
|---|
| 4431 | +#ifdef CONFIG_WATCH_QUEUE |
|---|
| 4432 | +/** |
|---|
| 4433 | + * smack_post_notification - Smack access to post a notification to a queue |
|---|
| 4434 | + * @w_cred: The credentials of the watcher. |
|---|
| 4435 | + * @cred: The credentials of the event source (may be NULL). |
|---|
| 4436 | + * @n: The notification message to be posted. |
|---|
| 4437 | + */ |
|---|
| 4438 | +static int smack_post_notification(const struct cred *w_cred, |
|---|
| 4439 | + const struct cred *cred, |
|---|
| 4440 | + struct watch_notification *n) |
|---|
| 4441 | +{ |
|---|
| 4442 | + struct smk_audit_info ad; |
|---|
| 4443 | + struct smack_known *subj, *obj; |
|---|
| 4444 | + int rc; |
|---|
| 4445 | + |
|---|
| 4446 | + /* Always let maintenance notifications through. */ |
|---|
| 4447 | + if (n->type == WATCH_TYPE_META) |
|---|
| 4448 | + return 0; |
|---|
| 4449 | + |
|---|
| 4450 | + if (!cred) |
|---|
| 4451 | + return 0; |
|---|
| 4452 | + subj = smk_of_task(smack_cred(cred)); |
|---|
| 4453 | + obj = smk_of_task(smack_cred(w_cred)); |
|---|
| 4454 | + |
|---|
| 4455 | + smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NOTIFICATION); |
|---|
| 4456 | + rc = smk_access(subj, obj, MAY_WRITE, &ad); |
|---|
| 4457 | + rc = smk_bu_note("notification", subj, obj, MAY_WRITE, rc); |
|---|
| 4458 | + return rc; |
|---|
| 4459 | +} |
|---|
| 4460 | +#endif /* CONFIG_WATCH_QUEUE */ |
|---|
| 4407 | 4461 | |
|---|
| 4408 | 4462 | /* |
|---|
| 4409 | 4463 | * Smack Audit hooks |
|---|
| .. | .. |
|---|
| 4480 | 4534 | * @field: audit rule flags given from user-space |
|---|
| 4481 | 4535 | * @op: required testing operator |
|---|
| 4482 | 4536 | * @vrule: smack internal rule presentation |
|---|
| 4483 | | - * @actx: audit context associated with the check |
|---|
| 4484 | 4537 | * |
|---|
| 4485 | 4538 | * The core Audit hook. It's used to take the decision of |
|---|
| 4486 | 4539 | * whether to audit or not to audit a given object. |
|---|
| 4487 | 4540 | */ |
|---|
| 4488 | | -static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule, |
|---|
| 4489 | | - struct audit_context *actx) |
|---|
| 4541 | +static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule) |
|---|
| 4490 | 4542 | { |
|---|
| 4491 | 4543 | struct smack_known *skp; |
|---|
| 4492 | 4544 | char *rule = vrule; |
|---|
| .. | .. |
|---|
| 4607 | 4659 | return -ENOMEM; |
|---|
| 4608 | 4660 | } |
|---|
| 4609 | 4661 | |
|---|
| 4610 | | - tsp = new_creds->security; |
|---|
| 4662 | + tsp = smack_cred(new_creds); |
|---|
| 4611 | 4663 | |
|---|
| 4612 | 4664 | /* |
|---|
| 4613 | 4665 | * Get label from overlay inode and set it in create_sid |
|---|
| 4614 | 4666 | */ |
|---|
| 4615 | | - isp = d_inode(dentry->d_parent)->i_security; |
|---|
| 4667 | + isp = smack_inode(d_inode(dentry)); |
|---|
| 4616 | 4668 | skp = isp->smk_inode; |
|---|
| 4617 | 4669 | tsp->smk_task = skp; |
|---|
| 4618 | 4670 | *new = new_creds; |
|---|
| .. | .. |
|---|
| 4635 | 4687 | const struct cred *old, |
|---|
| 4636 | 4688 | struct cred *new) |
|---|
| 4637 | 4689 | { |
|---|
| 4638 | | - struct task_smack *otsp = old->security; |
|---|
| 4639 | | - struct task_smack *ntsp = new->security; |
|---|
| 4690 | + struct task_smack *otsp = smack_cred(old); |
|---|
| 4691 | + struct task_smack *ntsp = smack_cred(new); |
|---|
| 4640 | 4692 | struct inode_smack *isp; |
|---|
| 4641 | 4693 | int may; |
|---|
| 4642 | 4694 | |
|---|
| .. | .. |
|---|
| 4649 | 4701 | /* |
|---|
| 4650 | 4702 | * the attribute of the containing directory |
|---|
| 4651 | 4703 | */ |
|---|
| 4652 | | - isp = d_inode(dentry->d_parent)->i_security; |
|---|
| 4704 | + isp = smack_inode(d_inode(dentry->d_parent)); |
|---|
| 4653 | 4705 | |
|---|
| 4654 | 4706 | if (isp->smk_flags & SMK_INODE_TRANSMUTE) { |
|---|
| 4655 | 4707 | rcu_read_lock(); |
|---|
| .. | .. |
|---|
| 4663 | 4715 | * providing access is transmuting use the containing |
|---|
| 4664 | 4716 | * directory label instead of the process label. |
|---|
| 4665 | 4717 | */ |
|---|
| 4666 | | - if (may > 0 && (may & MAY_TRANSMUTE)) |
|---|
| 4718 | + if (may > 0 && (may & MAY_TRANSMUTE)) { |
|---|
| 4667 | 4719 | ntsp->smk_task = isp->smk_inode; |
|---|
| 4720 | + ntsp->smk_transmuted = ntsp->smk_task; |
|---|
| 4721 | + } |
|---|
| 4668 | 4722 | } |
|---|
| 4669 | 4723 | return 0; |
|---|
| 4670 | 4724 | } |
|---|
| 4725 | + |
|---|
| 4726 | +struct lsm_blob_sizes smack_blob_sizes __lsm_ro_after_init = { |
|---|
| 4727 | + .lbs_cred = sizeof(struct task_smack), |
|---|
| 4728 | + .lbs_file = sizeof(struct smack_known *), |
|---|
| 4729 | + .lbs_inode = sizeof(struct inode_smack), |
|---|
| 4730 | + .lbs_ipc = sizeof(struct smack_known *), |
|---|
| 4731 | + .lbs_msg_msg = sizeof(struct smack_known *), |
|---|
| 4732 | +}; |
|---|
| 4671 | 4733 | |
|---|
| 4672 | 4734 | static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { |
|---|
| 4673 | 4735 | LSM_HOOK_INIT(ptrace_access_check, smack_ptrace_access_check), |
|---|
| 4674 | 4736 | LSM_HOOK_INIT(ptrace_traceme, smack_ptrace_traceme), |
|---|
| 4675 | 4737 | LSM_HOOK_INIT(syslog, smack_syslog), |
|---|
| 4676 | 4738 | |
|---|
| 4739 | + LSM_HOOK_INIT(fs_context_dup, smack_fs_context_dup), |
|---|
| 4740 | + LSM_HOOK_INIT(fs_context_parse_param, smack_fs_context_parse_param), |
|---|
| 4741 | + |
|---|
| 4677 | 4742 | LSM_HOOK_INIT(sb_alloc_security, smack_sb_alloc_security), |
|---|
| 4678 | 4743 | LSM_HOOK_INIT(sb_free_security, smack_sb_free_security), |
|---|
| 4679 | | - LSM_HOOK_INIT(sb_copy_data, smack_sb_copy_data), |
|---|
| 4680 | | - LSM_HOOK_INIT(sb_kern_mount, smack_sb_kern_mount), |
|---|
| 4744 | + LSM_HOOK_INIT(sb_free_mnt_opts, smack_free_mnt_opts), |
|---|
| 4745 | + LSM_HOOK_INIT(sb_eat_lsm_opts, smack_sb_eat_lsm_opts), |
|---|
| 4681 | 4746 | LSM_HOOK_INIT(sb_statfs, smack_sb_statfs), |
|---|
| 4682 | 4747 | LSM_HOOK_INIT(sb_set_mnt_opts, smack_set_mnt_opts), |
|---|
| 4683 | | - LSM_HOOK_INIT(sb_parse_opts_str, smack_parse_opts_str), |
|---|
| 4684 | 4748 | |
|---|
| 4685 | | - LSM_HOOK_INIT(bprm_set_creds, smack_bprm_set_creds), |
|---|
| 4749 | + LSM_HOOK_INIT(bprm_creds_for_exec, smack_bprm_creds_for_exec), |
|---|
| 4686 | 4750 | |
|---|
| 4687 | 4751 | LSM_HOOK_INIT(inode_alloc_security, smack_inode_alloc_security), |
|---|
| 4688 | | - LSM_HOOK_INIT(inode_free_security, smack_inode_free_security), |
|---|
| 4689 | 4752 | LSM_HOOK_INIT(inode_init_security, smack_inode_init_security), |
|---|
| 4690 | 4753 | LSM_HOOK_INIT(inode_link, smack_inode_link), |
|---|
| 4691 | 4754 | LSM_HOOK_INIT(inode_unlink, smack_inode_unlink), |
|---|
| .. | .. |
|---|
| 4704 | 4767 | LSM_HOOK_INIT(inode_getsecid, smack_inode_getsecid), |
|---|
| 4705 | 4768 | |
|---|
| 4706 | 4769 | LSM_HOOK_INIT(file_alloc_security, smack_file_alloc_security), |
|---|
| 4707 | | - LSM_HOOK_INIT(file_free_security, smack_file_free_security), |
|---|
| 4708 | 4770 | LSM_HOOK_INIT(file_ioctl, smack_file_ioctl), |
|---|
| 4709 | 4771 | LSM_HOOK_INIT(file_lock, smack_file_lock), |
|---|
| 4710 | 4772 | LSM_HOOK_INIT(file_fcntl, smack_file_fcntl), |
|---|
| .. | .. |
|---|
| 4740 | 4802 | LSM_HOOK_INIT(ipc_getsecid, smack_ipc_getsecid), |
|---|
| 4741 | 4803 | |
|---|
| 4742 | 4804 | LSM_HOOK_INIT(msg_msg_alloc_security, smack_msg_msg_alloc_security), |
|---|
| 4743 | | - LSM_HOOK_INIT(msg_msg_free_security, smack_msg_msg_free_security), |
|---|
| 4744 | 4805 | |
|---|
| 4745 | 4806 | LSM_HOOK_INIT(msg_queue_alloc_security, smack_ipc_alloc_security), |
|---|
| 4746 | | - LSM_HOOK_INIT(msg_queue_free_security, smack_ipc_free_security), |
|---|
| 4747 | 4807 | LSM_HOOK_INIT(msg_queue_associate, smack_msg_queue_associate), |
|---|
| 4748 | 4808 | LSM_HOOK_INIT(msg_queue_msgctl, smack_msg_queue_msgctl), |
|---|
| 4749 | 4809 | LSM_HOOK_INIT(msg_queue_msgsnd, smack_msg_queue_msgsnd), |
|---|
| 4750 | 4810 | LSM_HOOK_INIT(msg_queue_msgrcv, smack_msg_queue_msgrcv), |
|---|
| 4751 | 4811 | |
|---|
| 4752 | 4812 | LSM_HOOK_INIT(shm_alloc_security, smack_ipc_alloc_security), |
|---|
| 4753 | | - LSM_HOOK_INIT(shm_free_security, smack_ipc_free_security), |
|---|
| 4754 | 4813 | LSM_HOOK_INIT(shm_associate, smack_shm_associate), |
|---|
| 4755 | 4814 | LSM_HOOK_INIT(shm_shmctl, smack_shm_shmctl), |
|---|
| 4756 | 4815 | LSM_HOOK_INIT(shm_shmat, smack_shm_shmat), |
|---|
| 4757 | 4816 | |
|---|
| 4758 | 4817 | LSM_HOOK_INIT(sem_alloc_security, smack_ipc_alloc_security), |
|---|
| 4759 | | - LSM_HOOK_INIT(sem_free_security, smack_ipc_free_security), |
|---|
| 4760 | 4818 | LSM_HOOK_INIT(sem_associate, smack_sem_associate), |
|---|
| 4761 | 4819 | LSM_HOOK_INIT(sem_semctl, smack_sem_semctl), |
|---|
| 4762 | 4820 | LSM_HOOK_INIT(sem_semop, smack_sem_semop), |
|---|
| .. | .. |
|---|
| 4791 | 4849 | LSM_HOOK_INIT(key_free, smack_key_free), |
|---|
| 4792 | 4850 | LSM_HOOK_INIT(key_permission, smack_key_permission), |
|---|
| 4793 | 4851 | LSM_HOOK_INIT(key_getsecurity, smack_key_getsecurity), |
|---|
| 4852 | +#ifdef CONFIG_KEY_NOTIFICATIONS |
|---|
| 4853 | + LSM_HOOK_INIT(watch_key, smack_watch_key), |
|---|
| 4854 | +#endif |
|---|
| 4794 | 4855 | #endif /* CONFIG_KEYS */ |
|---|
| 4856 | + |
|---|
| 4857 | +#ifdef CONFIG_WATCH_QUEUE |
|---|
| 4858 | + LSM_HOOK_INIT(post_notification, smack_post_notification), |
|---|
| 4859 | +#endif |
|---|
| 4795 | 4860 | |
|---|
| 4796 | 4861 | /* Audit hooks */ |
|---|
| 4797 | 4862 | #ifdef CONFIG_AUDIT |
|---|
| .. | .. |
|---|
| 4843 | 4908 | /** |
|---|
| 4844 | 4909 | * smack_init - initialize the smack system |
|---|
| 4845 | 4910 | * |
|---|
| 4846 | | - * Returns 0 |
|---|
| 4911 | + * Returns 0 on success, -ENOMEM is there's no memory |
|---|
| 4847 | 4912 | */ |
|---|
| 4848 | 4913 | static __init int smack_init(void) |
|---|
| 4849 | 4914 | { |
|---|
| 4850 | | - struct cred *cred; |
|---|
| 4915 | + struct cred *cred = (struct cred *) current->cred; |
|---|
| 4851 | 4916 | struct task_smack *tsp; |
|---|
| 4852 | 4917 | |
|---|
| 4853 | | - if (!security_module_enable("smack")) |
|---|
| 4854 | | - return 0; |
|---|
| 4855 | | - |
|---|
| 4856 | | - smack_inode_cache = KMEM_CACHE(inode_smack, 0); |
|---|
| 4857 | | - if (!smack_inode_cache) |
|---|
| 4918 | + smack_rule_cache = KMEM_CACHE(smack_rule, 0); |
|---|
| 4919 | + if (!smack_rule_cache) |
|---|
| 4858 | 4920 | return -ENOMEM; |
|---|
| 4859 | 4921 | |
|---|
| 4860 | | - tsp = new_task_smack(&smack_known_floor, &smack_known_floor, |
|---|
| 4861 | | - GFP_KERNEL); |
|---|
| 4862 | | - if (tsp == NULL) { |
|---|
| 4863 | | - kmem_cache_destroy(smack_inode_cache); |
|---|
| 4864 | | - return -ENOMEM; |
|---|
| 4865 | | - } |
|---|
| 4922 | + /* |
|---|
| 4923 | + * Set the security state for the initial task. |
|---|
| 4924 | + */ |
|---|
| 4925 | + tsp = smack_cred(cred); |
|---|
| 4926 | + init_task_smack(tsp, &smack_known_floor, &smack_known_floor); |
|---|
| 4866 | 4927 | |
|---|
| 4928 | + /* |
|---|
| 4929 | + * Register with LSM |
|---|
| 4930 | + */ |
|---|
| 4931 | + security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), "smack"); |
|---|
| 4867 | 4932 | smack_enabled = 1; |
|---|
| 4868 | 4933 | |
|---|
| 4869 | 4934 | pr_info("Smack: Initializing.\n"); |
|---|
| .. | .. |
|---|
| 4877 | 4942 | pr_info("Smack: IPv6 Netfilter enabled.\n"); |
|---|
| 4878 | 4943 | #endif |
|---|
| 4879 | 4944 | |
|---|
| 4880 | | - /* |
|---|
| 4881 | | - * Set the security state for the initial task. |
|---|
| 4882 | | - */ |
|---|
| 4883 | | - cred = (struct cred *) current->cred; |
|---|
| 4884 | | - cred->security = tsp; |
|---|
| 4885 | | - |
|---|
| 4886 | 4945 | /* initialize the smack_known_list */ |
|---|
| 4887 | 4946 | init_smack_known_list(); |
|---|
| 4888 | | - |
|---|
| 4889 | | - /* |
|---|
| 4890 | | - * Register with LSM |
|---|
| 4891 | | - */ |
|---|
| 4892 | | - security_add_hooks(smack_hooks, ARRAY_SIZE(smack_hooks), "smack"); |
|---|
| 4893 | 4947 | |
|---|
| 4894 | 4948 | return 0; |
|---|
| 4895 | 4949 | } |
|---|
| .. | .. |
|---|
| 4898 | 4952 | * Smack requires early initialization in order to label |
|---|
| 4899 | 4953 | * all processes and objects when they are created. |
|---|
| 4900 | 4954 | */ |
|---|
| 4901 | | -security_initcall(smack_init); |
|---|
| 4955 | +DEFINE_LSM(smack) = { |
|---|
| 4956 | + .name = "smack", |
|---|
| 4957 | + .flags = LSM_FLAG_LEGACY_MAJOR | LSM_FLAG_EXCLUSIVE, |
|---|
| 4958 | + .blobs = &smack_blob_sizes, |
|---|
| 4959 | + .init = smack_init, |
|---|
| 4960 | +}; |
|---|