.. | .. |
---|
| 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 | +}; |
---|