diff options
author | James Morris <james.l.morris@oracle.com> | 2015-10-20 19:49:29 -0400 |
---|---|---|
committer | James Morris <james.l.morris@oracle.com> | 2015-10-20 19:49:29 -0400 |
commit | 09302fd19efbff9569eaad3f78ead8f411defd87 (patch) | |
tree | ea7445250c19d8af6092eecb6908f1547dde86d6 | |
parent | fbf98265891a672111dac8faabd190f62b678545 (diff) | |
parent | 38416e53936ecf896948fdeffc36b76979117952 (diff) |
Merge branch 'smack-for-4.4' of https://github.com/cschaufler/smack-next into next
-rw-r--r-- | Documentation/security/Smack.txt | 10 | ||||
-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 |
5 files changed, 248 insertions, 47 deletions
diff --git a/Documentation/security/Smack.txt b/Documentation/security/Smack.txt index 5e6d07fbed07..945cc633d883 100644 --- a/Documentation/security/Smack.txt +++ b/Documentation/security/Smack.txt | |||
@@ -255,6 +255,16 @@ unconfined | |||
255 | the access permitted if it wouldn't be otherwise. Note that this | 255 | the access permitted if it wouldn't be otherwise. Note that this |
256 | is dangerous and can ruin the proper labeling of your system. | 256 | is dangerous and can ruin the proper labeling of your system. |
257 | It should never be used in production. | 257 | It should never be used in production. |
258 | relabel-self | ||
259 | This interface contains a list of labels to which the process can | ||
260 | transition to, by writing to /proc/self/attr/current. | ||
261 | Normally a process can change its own label to any legal value, but only | ||
262 | if it has CAP_MAC_ADMIN. This interface allows a process without | ||
263 | CAP_MAC_ADMIN to relabel itself to one of labels from predefined list. | ||
264 | A process without CAP_MAC_ADMIN can change its label only once. When it | ||
265 | does, this list will be cleared. | ||
266 | The values are set by writing the desired labels, separated | ||
267 | by spaces, to the file or cleared by writing "-" to the file. | ||
258 | 268 | ||
259 | If you are using the smackload utility | 269 | If you are using the smackload utility |
260 | you can add access rules in /etc/smack/accesses. They take the form: | 270 | you can add access rules in /etc/smack/accesses. They take the form: |
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(); |