diff options
Diffstat (limited to 'security')
| -rw-r--r-- | security/smack/smack.h | 4 | ||||
| -rw-r--r-- | security/smack/smack_access.c | 6 | ||||
| -rw-r--r-- | security/smack/smack_lsm.c | 67 | ||||
| -rw-r--r-- | security/smack/smackfs.c | 208 |
4 files changed, 238 insertions, 47 deletions
diff --git a/security/smack/smack.h b/security/smack/smack.h index fff0c612bbb7..6c91156ae225 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
| @@ -115,6 +115,7 @@ struct task_smack { | |||
| 115 | struct smack_known *smk_forked; /* label when forked */ | 115 | struct smack_known *smk_forked; /* label when forked */ |
| 116 | struct list_head smk_rules; /* per task access rules */ | 116 | struct list_head smk_rules; /* per task access rules */ |
| 117 | struct mutex smk_rules_lock; /* lock for the rules */ | 117 | struct mutex smk_rules_lock; /* lock for the rules */ |
| 118 | struct list_head smk_relabel; /* transit allowed labels */ | ||
| 118 | }; | 119 | }; |
| 119 | 120 | ||
| 120 | #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ | 121 | #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ |
| @@ -169,7 +170,7 @@ struct smk_port_label { | |||
| 169 | }; | 170 | }; |
| 170 | #endif /* SMACK_IPV6_PORT_LABELING */ | 171 | #endif /* SMACK_IPV6_PORT_LABELING */ |
| 171 | 172 | ||
| 172 | struct smack_onlycap { | 173 | struct smack_known_list_elem { |
| 173 | struct list_head list; | 174 | struct list_head list; |
| 174 | struct smack_known *smk_label; | 175 | struct smack_known *smk_label; |
| 175 | }; | 176 | }; |
| @@ -301,6 +302,7 @@ struct smack_known *smk_import_entry(const char *, int); | |||
| 301 | void smk_insert_entry(struct smack_known *skp); | 302 | void smk_insert_entry(struct smack_known *skp); |
| 302 | struct smack_known *smk_find_entry(const char *); | 303 | struct smack_known *smk_find_entry(const char *); |
| 303 | int smack_privileged(int cap); | 304 | int smack_privileged(int cap); |
| 305 | void smk_destroy_label_list(struct list_head *list); | ||
| 304 | 306 | ||
| 305 | /* | 307 | /* |
| 306 | * Shared data. | 308 | * Shared data. |
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index bc1053fb5d1d..a283f9e796c1 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
| @@ -637,7 +637,7 @@ DEFINE_MUTEX(smack_onlycap_lock); | |||
| 637 | int smack_privileged(int cap) | 637 | int smack_privileged(int cap) |
| 638 | { | 638 | { |
| 639 | struct smack_known *skp = smk_of_current(); | 639 | struct smack_known *skp = smk_of_current(); |
| 640 | struct smack_onlycap *sop; | 640 | struct smack_known_list_elem *sklep; |
| 641 | 641 | ||
| 642 | /* | 642 | /* |
| 643 | * All kernel tasks are privileged | 643 | * All kernel tasks are privileged |
| @@ -654,8 +654,8 @@ int smack_privileged(int cap) | |||
| 654 | return 1; | 654 | return 1; |
| 655 | } | 655 | } |
| 656 | 656 | ||
| 657 | list_for_each_entry_rcu(sop, &smack_onlycap_list, list) { | 657 | list_for_each_entry_rcu(sklep, &smack_onlycap_list, list) { |
| 658 | if (sop->smk_label == skp) { | 658 | if (sklep->smk_label == skp) { |
| 659 | rcu_read_unlock(); | 659 | rcu_read_unlock(); |
| 660 | return 1; | 660 | return 1; |
| 661 | } | 661 | } |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 996c88956438..ff81026f6ddb 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
| @@ -52,7 +52,7 @@ | |||
| 52 | #define SMK_SENDING 2 | 52 | #define SMK_SENDING 2 |
| 53 | 53 | ||
| 54 | #ifdef SMACK_IPV6_PORT_LABELING | 54 | #ifdef SMACK_IPV6_PORT_LABELING |
| 55 | LIST_HEAD(smk_ipv6_port_list); | 55 | static LIST_HEAD(smk_ipv6_port_list); |
| 56 | #endif | 56 | #endif |
| 57 | static struct kmem_cache *smack_inode_cache; | 57 | static struct kmem_cache *smack_inode_cache; |
| 58 | int smack_enabled; | 58 | int smack_enabled; |
| @@ -326,6 +326,7 @@ static struct task_smack *new_task_smack(struct smack_known *task, | |||
| 326 | tsp->smk_task = task; | 326 | tsp->smk_task = task; |
| 327 | tsp->smk_forked = forked; | 327 | tsp->smk_forked = forked; |
| 328 | INIT_LIST_HEAD(&tsp->smk_rules); | 328 | INIT_LIST_HEAD(&tsp->smk_rules); |
| 329 | INIT_LIST_HEAD(&tsp->smk_relabel); | ||
| 329 | mutex_init(&tsp->smk_rules_lock); | 330 | mutex_init(&tsp->smk_rules_lock); |
| 330 | 331 | ||
| 331 | return tsp; | 332 | return tsp; |
| @@ -361,6 +362,35 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead, | |||
| 361 | } | 362 | } |
| 362 | 363 | ||
| 363 | /** | 364 | /** |
| 365 | * smk_copy_relabel - copy smk_relabel labels list | ||
| 366 | * @nhead: new rules header pointer | ||
| 367 | * @ohead: old rules header pointer | ||
| 368 | * @gfp: type of the memory for the allocation | ||
| 369 | * | ||
| 370 | * Returns 0 on success, -ENOMEM on error | ||
| 371 | */ | ||
| 372 | static int smk_copy_relabel(struct list_head *nhead, struct list_head *ohead, | ||
| 373 | gfp_t gfp) | ||
| 374 | { | ||
| 375 | struct smack_known_list_elem *nklep; | ||
| 376 | struct smack_known_list_elem *oklep; | ||
| 377 | |||
| 378 | INIT_LIST_HEAD(nhead); | ||
| 379 | |||
| 380 | list_for_each_entry(oklep, ohead, list) { | ||
| 381 | nklep = kzalloc(sizeof(struct smack_known_list_elem), gfp); | ||
| 382 | if (nklep == NULL) { | ||
| 383 | smk_destroy_label_list(nhead); | ||
| 384 | return -ENOMEM; | ||
| 385 | } | ||
| 386 | nklep->smk_label = oklep->smk_label; | ||
| 387 | list_add(&nklep->list, nhead); | ||
| 388 | } | ||
| 389 | |||
| 390 | return 0; | ||
| 391 | } | ||
| 392 | |||
| 393 | /** | ||
| 364 | * smk_ptrace_mode - helper function for converting PTRACE_MODE_* into MAY_* | 394 | * smk_ptrace_mode - helper function for converting PTRACE_MODE_* into MAY_* |
| 365 | * @mode - input mode in form of PTRACE_MODE_* | 395 | * @mode - input mode in form of PTRACE_MODE_* |
| 366 | * | 396 | * |
| @@ -1922,6 +1952,8 @@ static void smack_cred_free(struct cred *cred) | |||
| 1922 | return; | 1952 | return; |
| 1923 | cred->security = NULL; | 1953 | cred->security = NULL; |
| 1924 | 1954 | ||
| 1955 | smk_destroy_label_list(&tsp->smk_relabel); | ||
| 1956 | |||
| 1925 | list_for_each_safe(l, n, &tsp->smk_rules) { | 1957 | list_for_each_safe(l, n, &tsp->smk_rules) { |
| 1926 | rp = list_entry(l, struct smack_rule, list); | 1958 | rp = list_entry(l, struct smack_rule, list); |
| 1927 | list_del(&rp->list); | 1959 | list_del(&rp->list); |
| @@ -1953,6 +1985,11 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old, | |||
| 1953 | if (rc != 0) | 1985 | if (rc != 0) |
| 1954 | return rc; | 1986 | return rc; |
| 1955 | 1987 | ||
| 1988 | rc = smk_copy_relabel(&new_tsp->smk_relabel, &old_tsp->smk_relabel, | ||
| 1989 | gfp); | ||
| 1990 | if (rc != 0) | ||
| 1991 | return rc; | ||
| 1992 | |||
| 1956 | new->security = new_tsp; | 1993 | new->security = new_tsp; |
| 1957 | return 0; | 1994 | return 0; |
| 1958 | } | 1995 | } |
| @@ -3354,6 +3391,9 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
| 3354 | */ | 3391 | */ |
| 3355 | isp->smk_inode = smk_of_current(); | 3392 | isp->smk_inode = smk_of_current(); |
| 3356 | break; | 3393 | break; |
| 3394 | case PIPEFS_MAGIC: | ||
| 3395 | isp->smk_inode = smk_of_current(); | ||
| 3396 | break; | ||
| 3357 | default: | 3397 | default: |
| 3358 | isp->smk_inode = sbsp->smk_root; | 3398 | isp->smk_inode = sbsp->smk_root; |
| 3359 | break; | 3399 | break; |
| @@ -3549,9 +3589,11 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value) | |||
| 3549 | static int smack_setprocattr(struct task_struct *p, char *name, | 3589 | static int smack_setprocattr(struct task_struct *p, char *name, |
| 3550 | void *value, size_t size) | 3590 | void *value, size_t size) |
| 3551 | { | 3591 | { |
| 3552 | struct task_smack *tsp; | 3592 | struct task_smack *tsp = current_security(); |
| 3553 | struct cred *new; | 3593 | struct cred *new; |
| 3554 | struct smack_known *skp; | 3594 | struct smack_known *skp; |
| 3595 | struct smack_known_list_elem *sklep; | ||
| 3596 | int rc; | ||
| 3555 | 3597 | ||
| 3556 | /* | 3598 | /* |
| 3557 | * Changing another process' Smack value is too dangerous | 3599 | * Changing another process' Smack value is too dangerous |
| @@ -3560,7 +3602,7 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
| 3560 | if (p != current) | 3602 | if (p != current) |
| 3561 | return -EPERM; | 3603 | return -EPERM; |
| 3562 | 3604 | ||
| 3563 | if (!smack_privileged(CAP_MAC_ADMIN)) | 3605 | if (!smack_privileged(CAP_MAC_ADMIN) && list_empty(&tsp->smk_relabel)) |
| 3564 | return -EPERM; | 3606 | return -EPERM; |
| 3565 | 3607 | ||
| 3566 | if (value == NULL || size == 0 || size >= SMK_LONGLABEL) | 3608 | if (value == NULL || size == 0 || size >= SMK_LONGLABEL) |
| @@ -3579,12 +3621,27 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
| 3579 | if (skp == &smack_known_web) | 3621 | if (skp == &smack_known_web) |
| 3580 | return -EPERM; | 3622 | return -EPERM; |
| 3581 | 3623 | ||
| 3624 | if (!smack_privileged(CAP_MAC_ADMIN)) { | ||
| 3625 | rc = -EPERM; | ||
| 3626 | list_for_each_entry(sklep, &tsp->smk_relabel, list) | ||
| 3627 | if (sklep->smk_label == skp) { | ||
| 3628 | rc = 0; | ||
| 3629 | break; | ||
| 3630 | } | ||
| 3631 | if (rc) | ||
| 3632 | return rc; | ||
| 3633 | } | ||
| 3634 | |||
| 3582 | new = prepare_creds(); | 3635 | new = prepare_creds(); |
| 3583 | if (new == NULL) | 3636 | if (new == NULL) |
| 3584 | return -ENOMEM; | 3637 | return -ENOMEM; |
| 3585 | 3638 | ||
| 3586 | tsp = new->security; | 3639 | tsp = new->security; |
| 3587 | tsp->smk_task = skp; | 3640 | tsp->smk_task = skp; |
| 3641 | /* | ||
| 3642 | * process can change its label only once | ||
| 3643 | */ | ||
| 3644 | smk_destroy_label_list(&tsp->smk_relabel); | ||
| 3588 | 3645 | ||
| 3589 | commit_creds(new); | 3646 | commit_creds(new); |
| 3590 | return size; | 3647 | return size; |
| @@ -4708,8 +4765,6 @@ static __init int smack_init(void) | |||
| 4708 | if (!security_module_enable("smack")) | 4765 | if (!security_module_enable("smack")) |
| 4709 | return 0; | 4766 | return 0; |
| 4710 | 4767 | ||
| 4711 | smack_enabled = 1; | ||
| 4712 | |||
| 4713 | smack_inode_cache = KMEM_CACHE(inode_smack, 0); | 4768 | smack_inode_cache = KMEM_CACHE(inode_smack, 0); |
| 4714 | if (!smack_inode_cache) | 4769 | if (!smack_inode_cache) |
| 4715 | return -ENOMEM; | 4770 | return -ENOMEM; |
| @@ -4721,6 +4776,8 @@ static __init int smack_init(void) | |||
| 4721 | return -ENOMEM; | 4776 | return -ENOMEM; |
| 4722 | } | 4777 | } |
| 4723 | 4778 | ||
| 4779 | smack_enabled = 1; | ||
| 4780 | |||
| 4724 | pr_info("Smack: Initializing.\n"); | 4781 | pr_info("Smack: Initializing.\n"); |
| 4725 | #ifdef CONFIG_SECURITY_SMACK_NETFILTER | 4782 | #ifdef CONFIG_SECURITY_SMACK_NETFILTER |
| 4726 | pr_info("Smack: Netfilter enabled.\n"); | 4783 | pr_info("Smack: Netfilter enabled.\n"); |
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index c20b154a33f2..94bd9e41c9ec 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
| @@ -61,6 +61,7 @@ enum smk_inos { | |||
| 61 | #if IS_ENABLED(CONFIG_IPV6) | 61 | #if IS_ENABLED(CONFIG_IPV6) |
| 62 | SMK_NET6ADDR = 23, /* single label IPv6 hosts */ | 62 | SMK_NET6ADDR = 23, /* single label IPv6 hosts */ |
| 63 | #endif /* CONFIG_IPV6 */ | 63 | #endif /* CONFIG_IPV6 */ |
| 64 | SMK_RELABEL_SELF = 24, /* relabel possible without CAP_MAC_ADMIN */ | ||
| 64 | }; | 65 | }; |
| 65 | 66 | ||
| 66 | /* | 67 | /* |
| @@ -1501,8 +1502,8 @@ static ssize_t smk_write_net6addr(struct file *file, const char __user *buf, | |||
| 1501 | */ | 1502 | */ |
| 1502 | if (smack[0] != '-') { | 1503 | if (smack[0] != '-') { |
| 1503 | skp = smk_import_entry(smack, 0); | 1504 | skp = smk_import_entry(smack, 0); |
| 1504 | if (skp == NULL) { | 1505 | if (IS_ERR(skp)) { |
| 1505 | rc = -EINVAL; | 1506 | rc = PTR_ERR(skp); |
| 1506 | goto free_out; | 1507 | goto free_out; |
| 1507 | } | 1508 | } |
| 1508 | } else { | 1509 | } else { |
| @@ -1914,10 +1915,10 @@ static void *onlycap_seq_next(struct seq_file *s, void *v, loff_t *pos) | |||
| 1914 | static int onlycap_seq_show(struct seq_file *s, void *v) | 1915 | static int onlycap_seq_show(struct seq_file *s, void *v) |
| 1915 | { | 1916 | { |
| 1916 | struct list_head *list = v; | 1917 | struct list_head *list = v; |
| 1917 | struct smack_onlycap *sop = | 1918 | struct smack_known_list_elem *sklep = |
| 1918 | list_entry_rcu(list, struct smack_onlycap, list); | 1919 | list_entry_rcu(list, struct smack_known_list_elem, list); |
| 1919 | 1920 | ||
| 1920 | seq_puts(s, sop->smk_label->smk_known); | 1921 | seq_puts(s, sklep->smk_label->smk_known); |
| 1921 | seq_putc(s, ' '); | 1922 | seq_putc(s, ' '); |
| 1922 | 1923 | ||
| 1923 | return 0; | 1924 | return 0; |
| @@ -1974,6 +1975,54 @@ static void smk_list_swap_rcu(struct list_head *public, | |||
| 1974 | } | 1975 | } |
| 1975 | 1976 | ||
| 1976 | /** | 1977 | /** |
| 1978 | * smk_parse_label_list - parse list of Smack labels, separated by spaces | ||
| 1979 | * | ||
| 1980 | * @data: the string to parse | ||
| 1981 | * @private: destination list | ||
| 1982 | * | ||
| 1983 | * Returns zero on success or error code, as appropriate | ||
| 1984 | */ | ||
| 1985 | static int smk_parse_label_list(char *data, struct list_head *list) | ||
| 1986 | { | ||
| 1987 | char *tok; | ||
| 1988 | struct smack_known *skp; | ||
| 1989 | struct smack_known_list_elem *sklep; | ||
| 1990 | |||
| 1991 | while ((tok = strsep(&data, " ")) != NULL) { | ||
| 1992 | if (!*tok) | ||
| 1993 | continue; | ||
| 1994 | |||
| 1995 | skp = smk_import_entry(tok, 0); | ||
| 1996 | if (IS_ERR(skp)) | ||
| 1997 | return PTR_ERR(skp); | ||
| 1998 | |||
| 1999 | sklep = kzalloc(sizeof(*sklep), GFP_KERNEL); | ||
| 2000 | if (sklep == NULL) | ||
| 2001 | return -ENOMEM; | ||
| 2002 | |||
| 2003 | sklep->smk_label = skp; | ||
| 2004 | list_add(&sklep->list, list); | ||
| 2005 | } | ||
| 2006 | |||
| 2007 | return 0; | ||
| 2008 | } | ||
| 2009 | |||
| 2010 | /** | ||
| 2011 | * smk_destroy_label_list - destroy a list of smack_known_list_elem | ||
| 2012 | * @head: header pointer of the list to destroy | ||
| 2013 | */ | ||
| 2014 | void smk_destroy_label_list(struct list_head *list) | ||
| 2015 | { | ||
| 2016 | struct smack_known_list_elem *sklep; | ||
| 2017 | struct smack_known_list_elem *sklep2; | ||
| 2018 | |||
| 2019 | list_for_each_entry_safe(sklep, sklep2, list, list) | ||
| 2020 | kfree(sklep); | ||
| 2021 | |||
| 2022 | INIT_LIST_HEAD(list); | ||
| 2023 | } | ||
| 2024 | |||
| 2025 | /** | ||
| 1977 | * smk_write_onlycap - write() for smackfs/onlycap | 2026 | * smk_write_onlycap - write() for smackfs/onlycap |
| 1978 | * @file: file pointer, not actually used | 2027 | * @file: file pointer, not actually used |
| 1979 | * @buf: where to get the data from | 2028 | * @buf: where to get the data from |
| @@ -1986,13 +2035,8 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, | |||
| 1986 | size_t count, loff_t *ppos) | 2035 | size_t count, loff_t *ppos) |
| 1987 | { | 2036 | { |
| 1988 | char *data; | 2037 | char *data; |
| 1989 | char *data_parse; | ||
| 1990 | char *tok; | ||
| 1991 | struct smack_known *skp; | ||
| 1992 | struct smack_onlycap *sop; | ||
| 1993 | struct smack_onlycap *sop2; | ||
| 1994 | LIST_HEAD(list_tmp); | 2038 | LIST_HEAD(list_tmp); |
| 1995 | int rc = count; | 2039 | int rc; |
| 1996 | 2040 | ||
| 1997 | if (!smack_privileged(CAP_MAC_ADMIN)) | 2041 | if (!smack_privileged(CAP_MAC_ADMIN)) |
| 1998 | return -EPERM; | 2042 | return -EPERM; |
| @@ -2006,26 +2050,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, | |||
| 2006 | return -EFAULT; | 2050 | return -EFAULT; |
| 2007 | } | 2051 | } |
| 2008 | 2052 | ||
| 2009 | data_parse = data; | 2053 | rc = smk_parse_label_list(data, &list_tmp); |
| 2010 | while ((tok = strsep(&data_parse, " ")) != NULL) { | ||
| 2011 | if (!*tok) | ||
| 2012 | continue; | ||
| 2013 | |||
| 2014 | skp = smk_import_entry(tok, 0); | ||
| 2015 | if (IS_ERR(skp)) { | ||
| 2016 | rc = PTR_ERR(skp); | ||
| 2017 | break; | ||
| 2018 | } | ||
| 2019 | |||
| 2020 | sop = kzalloc(sizeof(*sop), GFP_KERNEL); | ||
| 2021 | if (sop == NULL) { | ||
| 2022 | rc = -ENOMEM; | ||
| 2023 | break; | ||
| 2024 | } | ||
| 2025 | |||
| 2026 | sop->smk_label = skp; | ||
| 2027 | list_add_rcu(&sop->list, &list_tmp); | ||
| 2028 | } | ||
| 2029 | kfree(data); | 2054 | kfree(data); |
| 2030 | 2055 | ||
| 2031 | /* | 2056 | /* |
| @@ -2038,17 +2063,14 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, | |||
| 2038 | * But do so only on invalid label, not on system errors. | 2063 | * But do so only on invalid label, not on system errors. |
| 2039 | * The invalid label must be first to count as clearing attempt. | 2064 | * The invalid label must be first to count as clearing attempt. |
| 2040 | */ | 2065 | */ |
| 2041 | if (rc == -EINVAL && list_empty(&list_tmp)) | 2066 | if (!rc || (rc == -EINVAL && list_empty(&list_tmp))) { |
| 2042 | rc = count; | ||
| 2043 | |||
| 2044 | if (rc >= 0) { | ||
| 2045 | mutex_lock(&smack_onlycap_lock); | 2067 | mutex_lock(&smack_onlycap_lock); |
| 2046 | smk_list_swap_rcu(&smack_onlycap_list, &list_tmp); | 2068 | smk_list_swap_rcu(&smack_onlycap_list, &list_tmp); |
| 2047 | mutex_unlock(&smack_onlycap_lock); | 2069 | mutex_unlock(&smack_onlycap_lock); |
| 2070 | rc = count; | ||
| 2048 | } | 2071 | } |
| 2049 | 2072 | ||
| 2050 | list_for_each_entry_safe(sop, sop2, &list_tmp, list) | 2073 | smk_destroy_label_list(&list_tmp); |
| 2051 | kfree(sop); | ||
| 2052 | 2074 | ||
| 2053 | return rc; | 2075 | return rc; |
| 2054 | } | 2076 | } |
| @@ -2698,6 +2720,113 @@ static const struct file_operations smk_syslog_ops = { | |||
| 2698 | .llseek = default_llseek, | 2720 | .llseek = default_llseek, |
| 2699 | }; | 2721 | }; |
| 2700 | 2722 | ||
| 2723 | /* | ||
| 2724 | * Seq_file read operations for /smack/relabel-self | ||
| 2725 | */ | ||
| 2726 | |||
| 2727 | static void *relabel_self_seq_start(struct seq_file *s, loff_t *pos) | ||
| 2728 | { | ||
| 2729 | struct task_smack *tsp = current_security(); | ||
| 2730 | |||
| 2731 | return smk_seq_start(s, pos, &tsp->smk_relabel); | ||
| 2732 | } | ||
| 2733 | |||
| 2734 | static void *relabel_self_seq_next(struct seq_file *s, void *v, loff_t *pos) | ||
| 2735 | { | ||
| 2736 | struct task_smack *tsp = current_security(); | ||
| 2737 | |||
| 2738 | return smk_seq_next(s, v, pos, &tsp->smk_relabel); | ||
| 2739 | } | ||
| 2740 | |||
| 2741 | static int relabel_self_seq_show(struct seq_file *s, void *v) | ||
| 2742 | { | ||
| 2743 | struct list_head *list = v; | ||
| 2744 | struct smack_known_list_elem *sklep = | ||
| 2745 | list_entry(list, struct smack_known_list_elem, list); | ||
| 2746 | |||
| 2747 | seq_puts(s, sklep->smk_label->smk_known); | ||
| 2748 | seq_putc(s, ' '); | ||
| 2749 | |||
| 2750 | return 0; | ||
| 2751 | } | ||
| 2752 | |||
| 2753 | static const struct seq_operations relabel_self_seq_ops = { | ||
| 2754 | .start = relabel_self_seq_start, | ||
| 2755 | .next = relabel_self_seq_next, | ||
| 2756 | .show = relabel_self_seq_show, | ||
| 2757 | .stop = smk_seq_stop, | ||
| 2758 | }; | ||
| 2759 | |||
| 2760 | /** | ||
| 2761 | * smk_open_relabel_self - open() for /smack/relabel-self | ||
| 2762 | * @inode: inode structure representing file | ||
| 2763 | * @file: "relabel-self" file pointer | ||
| 2764 | * | ||
| 2765 | * Connect our relabel_self_seq_* operations with /smack/relabel-self | ||
| 2766 | * file_operations | ||
| 2767 | */ | ||
| 2768 | static int smk_open_relabel_self(struct inode *inode, struct file *file) | ||
| 2769 | { | ||
| 2770 | return seq_open(file, &relabel_self_seq_ops); | ||
| 2771 | } | ||
| 2772 | |||
| 2773 | /** | ||
| 2774 | * smk_write_relabel_self - write() for /smack/relabel-self | ||
| 2775 | * @file: file pointer, not actually used | ||
| 2776 | * @buf: where to get the data from | ||
| 2777 | * @count: bytes sent | ||
| 2778 | * @ppos: where to start - must be 0 | ||
| 2779 | * | ||
| 2780 | */ | ||
| 2781 | static ssize_t smk_write_relabel_self(struct file *file, const char __user *buf, | ||
| 2782 | size_t count, loff_t *ppos) | ||
| 2783 | { | ||
| 2784 | struct task_smack *tsp = current_security(); | ||
| 2785 | char *data; | ||
| 2786 | int rc; | ||
| 2787 | LIST_HEAD(list_tmp); | ||
| 2788 | |||
| 2789 | /* | ||
| 2790 | * Must have privilege. | ||
| 2791 | */ | ||
| 2792 | if (!smack_privileged(CAP_MAC_ADMIN)) | ||
| 2793 | return -EPERM; | ||
| 2794 | |||
| 2795 | /* | ||
| 2796 | * Enough data must be present. | ||
| 2797 | */ | ||
| 2798 | if (*ppos != 0) | ||
| 2799 | return -EINVAL; | ||
| 2800 | |||
| 2801 | data = kzalloc(count + 1, GFP_KERNEL); | ||
| 2802 | if (data == NULL) | ||
| 2803 | return -ENOMEM; | ||
| 2804 | |||
| 2805 | if (copy_from_user(data, buf, count) != 0) { | ||
| 2806 | kfree(data); | ||
| 2807 | return -EFAULT; | ||
| 2808 | } | ||
| 2809 | |||
| 2810 | rc = smk_parse_label_list(data, &list_tmp); | ||
| 2811 | kfree(data); | ||
| 2812 | |||
| 2813 | if (!rc || (rc == -EINVAL && list_empty(&list_tmp))) { | ||
| 2814 | smk_destroy_label_list(&tsp->smk_relabel); | ||
| 2815 | list_splice(&list_tmp, &tsp->smk_relabel); | ||
| 2816 | return count; | ||
| 2817 | } | ||
| 2818 | |||
| 2819 | smk_destroy_label_list(&list_tmp); | ||
| 2820 | return rc; | ||
| 2821 | } | ||
| 2822 | |||
| 2823 | static const struct file_operations smk_relabel_self_ops = { | ||
| 2824 | .open = smk_open_relabel_self, | ||
| 2825 | .read = seq_read, | ||
| 2826 | .llseek = seq_lseek, | ||
| 2827 | .write = smk_write_relabel_self, | ||
| 2828 | .release = seq_release, | ||
| 2829 | }; | ||
| 2701 | 2830 | ||
| 2702 | /** | 2831 | /** |
| 2703 | * smk_read_ptrace - read() for /smack/ptrace | 2832 | * smk_read_ptrace - read() for /smack/ptrace |
| @@ -2824,6 +2953,9 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) | |||
| 2824 | [SMK_NET6ADDR] = { | 2953 | [SMK_NET6ADDR] = { |
| 2825 | "ipv6host", &smk_net6addr_ops, S_IRUGO|S_IWUSR}, | 2954 | "ipv6host", &smk_net6addr_ops, S_IRUGO|S_IWUSR}, |
| 2826 | #endif /* CONFIG_IPV6 */ | 2955 | #endif /* CONFIG_IPV6 */ |
| 2956 | [SMK_RELABEL_SELF] = { | ||
| 2957 | "relabel-self", &smk_relabel_self_ops, | ||
| 2958 | S_IRUGO|S_IWUGO}, | ||
| 2827 | /* last one */ | 2959 | /* last one */ |
| 2828 | {""} | 2960 | {""} |
| 2829 | }; | 2961 | }; |
| @@ -2892,7 +3024,7 @@ static int __init init_smk_fs(void) | |||
| 2892 | int err; | 3024 | int err; |
| 2893 | int rc; | 3025 | int rc; |
| 2894 | 3026 | ||
| 2895 | if (!security_module_enable("smack")) | 3027 | if (smack_enabled == 0) |
| 2896 | return 0; | 3028 | return 0; |
| 2897 | 3029 | ||
| 2898 | err = smk_init_sysfs(); | 3030 | err = smk_init_sysfs(); |
