diff options
-rw-r--r-- | include/linux/xattr.h | 2 | ||||
-rw-r--r-- | security/smack/smack.h | 17 | ||||
-rw-r--r-- | security/smack/smack_access.c | 54 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 74 | ||||
-rw-r--r-- | security/smack/smackfs.c | 37 |
5 files changed, 141 insertions, 43 deletions
diff --git a/include/linux/xattr.h b/include/linux/xattr.h index 351c7901d74a..e6131ef98d8f 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h | |||
@@ -41,10 +41,12 @@ | |||
41 | #define XATTR_SMACK_IPIN "SMACK64IPIN" | 41 | #define XATTR_SMACK_IPIN "SMACK64IPIN" |
42 | #define XATTR_SMACK_IPOUT "SMACK64IPOUT" | 42 | #define XATTR_SMACK_IPOUT "SMACK64IPOUT" |
43 | #define XATTR_SMACK_EXEC "SMACK64EXEC" | 43 | #define XATTR_SMACK_EXEC "SMACK64EXEC" |
44 | #define XATTR_SMACK_TRANSMUTE "SMACK64TRANSMUTE" | ||
44 | #define XATTR_NAME_SMACK XATTR_SECURITY_PREFIX XATTR_SMACK_SUFFIX | 45 | #define XATTR_NAME_SMACK XATTR_SECURITY_PREFIX XATTR_SMACK_SUFFIX |
45 | #define XATTR_NAME_SMACKIPIN XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN | 46 | #define XATTR_NAME_SMACKIPIN XATTR_SECURITY_PREFIX XATTR_SMACK_IPIN |
46 | #define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT | 47 | #define XATTR_NAME_SMACKIPOUT XATTR_SECURITY_PREFIX XATTR_SMACK_IPOUT |
47 | #define XATTR_NAME_SMACKEXEC XATTR_SECURITY_PREFIX XATTR_SMACK_EXEC | 48 | #define XATTR_NAME_SMACKEXEC XATTR_SECURITY_PREFIX XATTR_SMACK_EXEC |
49 | #define XATTR_NAME_SMACKTRANSMUTE XATTR_SECURITY_PREFIX XATTR_SMACK_TRANSMUTE | ||
48 | 50 | ||
49 | #define XATTR_CAPS_SUFFIX "capability" | 51 | #define XATTR_CAPS_SUFFIX "capability" |
50 | #define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX | 52 | #define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX |
diff --git a/security/smack/smack.h b/security/smack/smack.h index a2e2cdfab4ef..129c4eb8ffb1 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
@@ -62,6 +62,7 @@ struct task_smack { | |||
62 | }; | 62 | }; |
63 | 63 | ||
64 | #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ | 64 | #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ |
65 | #define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */ | ||
65 | 66 | ||
66 | /* | 67 | /* |
67 | * A label access rule. | 68 | * A label access rule. |
@@ -167,6 +168,10 @@ struct smack_known { | |||
167 | #define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */ | 168 | #define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */ |
168 | 169 | ||
169 | /* | 170 | /* |
171 | * Flag for transmute access | ||
172 | */ | ||
173 | #define MAY_TRANSMUTE 64 | ||
174 | /* | ||
170 | * Just to make the common cases easier to deal with | 175 | * Just to make the common cases easier to deal with |
171 | */ | 176 | */ |
172 | #define MAY_ANY (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) | 177 | #define MAY_ANY (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC) |
@@ -197,6 +202,7 @@ struct inode_smack *new_inode_smack(char *); | |||
197 | /* | 202 | /* |
198 | * These functions are in smack_access.c | 203 | * These functions are in smack_access.c |
199 | */ | 204 | */ |
205 | int smk_access_entry(char *, char *); | ||
200 | int smk_access(char *, char *, int, struct smk_audit_info *); | 206 | int smk_access(char *, char *, int, struct smk_audit_info *); |
201 | int smk_curacc(char *, u32, struct smk_audit_info *); | 207 | int smk_curacc(char *, u32, struct smk_audit_info *); |
202 | int smack_to_cipso(const char *, struct smack_cipso *); | 208 | int smack_to_cipso(const char *, struct smack_cipso *); |
@@ -240,6 +246,15 @@ static inline void smack_catset_bit(int cat, char *catsetp) | |||
240 | } | 246 | } |
241 | 247 | ||
242 | /* | 248 | /* |
249 | * Is the directory transmuting? | ||
250 | */ | ||
251 | static inline int smk_inode_transmutable(const struct inode *isp) | ||
252 | { | ||
253 | struct inode_smack *sip = isp->i_security; | ||
254 | return (sip->smk_flags & SMK_INODE_TRANSMUTE) != 0; | ||
255 | } | ||
256 | |||
257 | /* | ||
243 | * Present a pointer to the smack label in an inode blob. | 258 | * Present a pointer to the smack label in an inode blob. |
244 | */ | 259 | */ |
245 | static inline char *smk_of_inode(const struct inode *isp) | 260 | static inline char *smk_of_inode(const struct inode *isp) |
@@ -265,7 +280,7 @@ static inline char *smk_of_forked(const struct task_smack *tsp) | |||
265 | } | 280 | } |
266 | 281 | ||
267 | /* | 282 | /* |
268 | * Present a pointer to the smack label in the curren task blob. | 283 | * Present a pointer to the smack label in the current task blob. |
269 | */ | 284 | */ |
270 | static inline char *smk_of_current(void) | 285 | static inline char *smk_of_current(void) |
271 | { | 286 | { |
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index 42becbc1ce33..7ba8478f599e 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
@@ -67,6 +67,46 @@ static u32 smack_next_secid = 10; | |||
67 | int log_policy = SMACK_AUDIT_DENIED; | 67 | int log_policy = SMACK_AUDIT_DENIED; |
68 | 68 | ||
69 | /** | 69 | /** |
70 | * smk_access_entry - look up matching access rule | ||
71 | * @subject_label: a pointer to the subject's Smack label | ||
72 | * @object_label: a pointer to the object's Smack label | ||
73 | * | ||
74 | * This function looks up the subject/object pair in the | ||
75 | * access rule list and returns pointer to the matching rule if found, | ||
76 | * NULL otherwise. | ||
77 | * | ||
78 | * NOTE: | ||
79 | * Even though Smack labels are usually shared on smack_list | ||
80 | * labels that come in off the network can't be imported | ||
81 | * and added to the list for locking reasons. | ||
82 | * | ||
83 | * Therefore, it is necessary to check the contents of the labels, | ||
84 | * not just the pointer values. Of course, in most cases the labels | ||
85 | * will be on the list, so checking the pointers may be a worthwhile | ||
86 | * optimization. | ||
87 | */ | ||
88 | int smk_access_entry(char *subject_label, char *object_label) | ||
89 | { | ||
90 | u32 may = MAY_NOT; | ||
91 | struct smack_rule *srp; | ||
92 | |||
93 | rcu_read_lock(); | ||
94 | list_for_each_entry_rcu(srp, &smack_rule_list, list) { | ||
95 | if (srp->smk_subject == subject_label || | ||
96 | strcmp(srp->smk_subject, subject_label) == 0) { | ||
97 | if (srp->smk_object == object_label || | ||
98 | strcmp(srp->smk_object, object_label) == 0) { | ||
99 | may = srp->smk_access; | ||
100 | break; | ||
101 | } | ||
102 | } | ||
103 | } | ||
104 | rcu_read_unlock(); | ||
105 | |||
106 | return may; | ||
107 | } | ||
108 | |||
109 | /** | ||
70 | * smk_access - determine if a subject has a specific access to an object | 110 | * smk_access - determine if a subject has a specific access to an object |
71 | * @subject_label: a pointer to the subject's Smack label | 111 | * @subject_label: a pointer to the subject's Smack label |
72 | * @object_label: a pointer to the object's Smack label | 112 | * @object_label: a pointer to the object's Smack label |
@@ -90,7 +130,6 @@ int smk_access(char *subject_label, char *object_label, int request, | |||
90 | struct smk_audit_info *a) | 130 | struct smk_audit_info *a) |
91 | { | 131 | { |
92 | u32 may = MAY_NOT; | 132 | u32 may = MAY_NOT; |
93 | struct smack_rule *srp; | ||
94 | int rc = 0; | 133 | int rc = 0; |
95 | 134 | ||
96 | /* | 135 | /* |
@@ -144,18 +183,7 @@ int smk_access(char *subject_label, char *object_label, int request, | |||
144 | * access (e.g. read is included in readwrite) it's | 183 | * access (e.g. read is included in readwrite) it's |
145 | * good. | 184 | * good. |
146 | */ | 185 | */ |
147 | rcu_read_lock(); | 186 | may = smk_access_entry(subject_label, object_label); |
148 | list_for_each_entry_rcu(srp, &smack_rule_list, list) { | ||
149 | if (srp->smk_subject == subject_label || | ||
150 | strcmp(srp->smk_subject, subject_label) == 0) { | ||
151 | if (srp->smk_object == object_label || | ||
152 | strcmp(srp->smk_object, object_label) == 0) { | ||
153 | may = srp->smk_access; | ||
154 | break; | ||
155 | } | ||
156 | } | ||
157 | } | ||
158 | rcu_read_unlock(); | ||
159 | /* | 187 | /* |
160 | * This is a bit map operation. | 188 | * This is a bit map operation. |
161 | */ | 189 | */ |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 7e19afe0e738..05dc4da2e25f 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -3,12 +3,14 @@ | |||
3 | * | 3 | * |
4 | * This file contains the smack hook function implementations. | 4 | * This file contains the smack hook function implementations. |
5 | * | 5 | * |
6 | * Author: | 6 | * Authors: |
7 | * Casey Schaufler <casey@schaufler-ca.com> | 7 | * Casey Schaufler <casey@schaufler-ca.com> |
8 | * Jarkko Sakkinen <ext-jarkko.2.sakkinen@nokia.com> | ||
8 | * | 9 | * |
9 | * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com> | 10 | * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com> |
10 | * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. | 11 | * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. |
11 | * Paul Moore <paul.moore@hp.com> | 12 | * Paul Moore <paul.moore@hp.com> |
13 | * Copyright (C) 2010 Nokia Corporation | ||
12 | * | 14 | * |
13 | * This program is free software; you can redistribute it and/or modify | 15 | * This program is free software; you can redistribute it and/or modify |
14 | * it under the terms of the GNU General Public License version 2, | 16 | * it under the terms of the GNU General Public License version 2, |
@@ -35,6 +37,9 @@ | |||
35 | 37 | ||
36 | #define task_security(task) (task_cred_xxx((task), security)) | 38 | #define task_security(task) (task_cred_xxx((task), security)) |
37 | 39 | ||
40 | #define TRANS_TRUE "TRUE" | ||
41 | #define TRANS_TRUE_SIZE 4 | ||
42 | |||
38 | /** | 43 | /** |
39 | * smk_fetch - Fetch the smack label from a file. | 44 | * smk_fetch - Fetch the smack label from a file. |
40 | * @ip: a pointer to the inode | 45 | * @ip: a pointer to the inode |
@@ -468,6 +473,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
468 | char **name, void **value, size_t *len) | 473 | char **name, void **value, size_t *len) |
469 | { | 474 | { |
470 | char *isp = smk_of_inode(inode); | 475 | char *isp = smk_of_inode(inode); |
476 | char *dsp = smk_of_inode(dir); | ||
477 | u32 may; | ||
471 | 478 | ||
472 | if (name) { | 479 | if (name) { |
473 | *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL); | 480 | *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL); |
@@ -476,6 +483,16 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
476 | } | 483 | } |
477 | 484 | ||
478 | if (value) { | 485 | if (value) { |
486 | may = smk_access_entry(smk_of_current(), dsp); | ||
487 | |||
488 | /* | ||
489 | * If the access rule allows transmutation and | ||
490 | * the directory requests transmutation then | ||
491 | * by all means transmute. | ||
492 | */ | ||
493 | if (((may & MAY_TRANSMUTE) != 0) && smk_inode_transmutable(dir)) | ||
494 | isp = dsp; | ||
495 | |||
479 | *value = kstrdup(isp, GFP_KERNEL); | 496 | *value = kstrdup(isp, GFP_KERNEL); |
480 | if (*value == NULL) | 497 | if (*value == NULL) |
481 | return -ENOMEM; | 498 | return -ENOMEM; |
@@ -709,6 +726,12 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
709 | if (size == 0 || size >= SMK_LABELLEN || | 726 | if (size == 0 || size >= SMK_LABELLEN || |
710 | smk_import(value, size) == NULL) | 727 | smk_import(value, size) == NULL) |
711 | rc = -EINVAL; | 728 | rc = -EINVAL; |
729 | } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { | ||
730 | if (!capable(CAP_MAC_ADMIN)) | ||
731 | rc = -EPERM; | ||
732 | if (size != TRANS_TRUE_SIZE || | ||
733 | strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0) | ||
734 | rc = -EINVAL; | ||
712 | } else | 735 | } else |
713 | rc = cap_inode_setxattr(dentry, name, value, size, flags); | 736 | rc = cap_inode_setxattr(dentry, name, value, size, flags); |
714 | 737 | ||
@@ -735,35 +758,23 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
735 | static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, | 758 | static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, |
736 | const void *value, size_t size, int flags) | 759 | const void *value, size_t size, int flags) |
737 | { | 760 | { |
738 | struct inode_smack *isp; | ||
739 | char *nsp; | 761 | char *nsp; |
740 | 762 | struct inode_smack *isp = dentry->d_inode->i_security; | |
741 | /* | ||
742 | * Not SMACK or SMACKEXEC | ||
743 | */ | ||
744 | if (strcmp(name, XATTR_NAME_SMACK) && | ||
745 | strcmp(name, XATTR_NAME_SMACKEXEC)) | ||
746 | return; | ||
747 | |||
748 | isp = dentry->d_inode->i_security; | ||
749 | |||
750 | /* | ||
751 | * No locking is done here. This is a pointer | ||
752 | * assignment. | ||
753 | */ | ||
754 | nsp = smk_import(value, size); | ||
755 | 763 | ||
756 | if (strcmp(name, XATTR_NAME_SMACK) == 0) { | 764 | if (strcmp(name, XATTR_NAME_SMACK) == 0) { |
765 | nsp = smk_import(value, size); | ||
757 | if (nsp != NULL) | 766 | if (nsp != NULL) |
758 | isp->smk_inode = nsp; | 767 | isp->smk_inode = nsp; |
759 | else | 768 | else |
760 | isp->smk_inode = smack_known_invalid.smk_known; | 769 | isp->smk_inode = smack_known_invalid.smk_known; |
761 | } else { | 770 | } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { |
771 | nsp = smk_import(value, size); | ||
762 | if (nsp != NULL) | 772 | if (nsp != NULL) |
763 | isp->smk_task = nsp; | 773 | isp->smk_task = nsp; |
764 | else | 774 | else |
765 | isp->smk_task = smack_known_invalid.smk_known; | 775 | isp->smk_task = smack_known_invalid.smk_known; |
766 | } | 776 | } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) |
777 | isp->smk_flags |= SMK_INODE_TRANSMUTE; | ||
767 | 778 | ||
768 | return; | 779 | return; |
769 | } | 780 | } |
@@ -803,7 +814,8 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) | |||
803 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || | 814 | if (strcmp(name, XATTR_NAME_SMACK) == 0 || |
804 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || | 815 | strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || |
805 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || | 816 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || |
806 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { | 817 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || |
818 | strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { | ||
807 | if (!capable(CAP_MAC_ADMIN)) | 819 | if (!capable(CAP_MAC_ADMIN)) |
808 | rc = -EPERM; | 820 | rc = -EPERM; |
809 | } else | 821 | } else |
@@ -2274,6 +2286,8 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2274 | char *csp = smk_of_current(); | 2286 | char *csp = smk_of_current(); |
2275 | char *fetched; | 2287 | char *fetched; |
2276 | char *final; | 2288 | char *final; |
2289 | char trattr[TRANS_TRUE_SIZE]; | ||
2290 | int transflag = 0; | ||
2277 | struct dentry *dp; | 2291 | struct dentry *dp; |
2278 | 2292 | ||
2279 | if (inode == NULL) | 2293 | if (inode == NULL) |
@@ -2392,10 +2406,19 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2392 | */ | 2406 | */ |
2393 | dp = dget(opt_dentry); | 2407 | dp = dget(opt_dentry); |
2394 | fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp); | 2408 | fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp); |
2395 | if (fetched != NULL) | 2409 | if (fetched != NULL) { |
2396 | final = fetched; | 2410 | final = fetched; |
2397 | isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, | 2411 | if (S_ISDIR(inode->i_mode)) { |
2398 | dp); | 2412 | trattr[0] = '\0'; |
2413 | inode->i_op->getxattr(dp, | ||
2414 | XATTR_NAME_SMACKTRANSMUTE, | ||
2415 | trattr, TRANS_TRUE_SIZE); | ||
2416 | if (strncmp(trattr, TRANS_TRUE, | ||
2417 | TRANS_TRUE_SIZE) == 0) | ||
2418 | transflag = SMK_INODE_TRANSMUTE; | ||
2419 | } | ||
2420 | } | ||
2421 | isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); | ||
2399 | 2422 | ||
2400 | dput(dp); | 2423 | dput(dp); |
2401 | break; | 2424 | break; |
@@ -2406,7 +2429,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2406 | else | 2429 | else |
2407 | isp->smk_inode = final; | 2430 | isp->smk_inode = final; |
2408 | 2431 | ||
2409 | isp->smk_flags |= SMK_INODE_INSTANT; | 2432 | isp->smk_flags |= (SMK_INODE_INSTANT | transflag); |
2410 | 2433 | ||
2411 | unlockandout: | 2434 | unlockandout: |
2412 | mutex_unlock(&isp->smk_lock); | 2435 | mutex_unlock(&isp->smk_lock); |
@@ -2456,6 +2479,7 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
2456 | void *value, size_t size) | 2479 | void *value, size_t size) |
2457 | { | 2480 | { |
2458 | struct task_smack *tsp; | 2481 | struct task_smack *tsp; |
2482 | struct task_smack *oldtsp; | ||
2459 | struct cred *new; | 2483 | struct cred *new; |
2460 | char *newsmack; | 2484 | char *newsmack; |
2461 | 2485 | ||
@@ -2485,6 +2509,7 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
2485 | if (newsmack == smack_known_web.smk_known) | 2509 | if (newsmack == smack_known_web.smk_known) |
2486 | return -EPERM; | 2510 | return -EPERM; |
2487 | 2511 | ||
2512 | oldtsp = p->cred->security; | ||
2488 | new = prepare_creds(); | 2513 | new = prepare_creds(); |
2489 | if (new == NULL) | 2514 | if (new == NULL) |
2490 | return -ENOMEM; | 2515 | return -ENOMEM; |
@@ -2494,6 +2519,7 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
2494 | return -ENOMEM; | 2519 | return -ENOMEM; |
2495 | } | 2520 | } |
2496 | tsp->smk_task = newsmack; | 2521 | tsp->smk_task = newsmack; |
2522 | tsp->smk_forked = oldtsp->smk_forked; | ||
2497 | new->security = tsp; | 2523 | new->security = tsp; |
2498 | commit_creds(new); | 2524 | commit_creds(new); |
2499 | return size; | 2525 | return size; |
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 01a0be93d8d0..362d5eda948b 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
@@ -109,9 +109,12 @@ const char *smack_cipso_option = SMACK_CIPSO_OPTION; | |||
109 | * SMK_ACCESSLEN: Maximum length for a rule access field | 109 | * SMK_ACCESSLEN: Maximum length for a rule access field |
110 | * SMK_LOADLEN: Smack rule length | 110 | * SMK_LOADLEN: Smack rule length |
111 | */ | 111 | */ |
112 | #define SMK_ACCESS "rwxa" | 112 | #define SMK_OACCESS "rwxa" |
113 | #define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1) | 113 | #define SMK_ACCESS "rwxat" |
114 | #define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN) | 114 | #define SMK_OACCESSLEN (sizeof(SMK_OACCESS) - 1) |
115 | #define SMK_ACCESSLEN (sizeof(SMK_ACCESS) - 1) | ||
116 | #define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN) | ||
117 | #define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN) | ||
115 | 118 | ||
116 | /** | 119 | /** |
117 | * smk_netlabel_audit_set - fill a netlbl_audit struct | 120 | * smk_netlabel_audit_set - fill a netlbl_audit struct |
@@ -175,6 +178,8 @@ static int load_seq_show(struct seq_file *s, void *v) | |||
175 | seq_putc(s, 'x'); | 178 | seq_putc(s, 'x'); |
176 | if (srp->smk_access & MAY_APPEND) | 179 | if (srp->smk_access & MAY_APPEND) |
177 | seq_putc(s, 'a'); | 180 | seq_putc(s, 'a'); |
181 | if (srp->smk_access & MAY_TRANSMUTE) | ||
182 | seq_putc(s, 't'); | ||
178 | if (srp->smk_access == 0) | 183 | if (srp->smk_access == 0) |
179 | seq_putc(s, '-'); | 184 | seq_putc(s, '-'); |
180 | 185 | ||
@@ -273,10 +278,15 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf, | |||
273 | if (!capable(CAP_MAC_ADMIN)) | 278 | if (!capable(CAP_MAC_ADMIN)) |
274 | return -EPERM; | 279 | return -EPERM; |
275 | 280 | ||
276 | if (*ppos != 0 || count != SMK_LOADLEN) | 281 | if (*ppos != 0) |
282 | return -EINVAL; | ||
283 | /* | ||
284 | * Minor hack for backward compatability | ||
285 | */ | ||
286 | if (count < (SMK_OLOADLEN) || count > SMK_LOADLEN) | ||
277 | return -EINVAL; | 287 | return -EINVAL; |
278 | 288 | ||
279 | data = kzalloc(count, GFP_KERNEL); | 289 | data = kzalloc(SMK_LOADLEN, GFP_KERNEL); |
280 | if (data == NULL) | 290 | if (data == NULL) |
281 | return -ENOMEM; | 291 | return -ENOMEM; |
282 | 292 | ||
@@ -285,6 +295,12 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf, | |||
285 | goto out; | 295 | goto out; |
286 | } | 296 | } |
287 | 297 | ||
298 | /* | ||
299 | * More on the minor hack for backward compatability | ||
300 | */ | ||
301 | if (count == (SMK_OLOADLEN)) | ||
302 | data[SMK_OLOADLEN] = '-'; | ||
303 | |||
288 | rule = kzalloc(sizeof(*rule), GFP_KERNEL); | 304 | rule = kzalloc(sizeof(*rule), GFP_KERNEL); |
289 | if (rule == NULL) { | 305 | if (rule == NULL) { |
290 | rc = -ENOMEM; | 306 | rc = -ENOMEM; |
@@ -345,6 +361,17 @@ static ssize_t smk_write_load(struct file *file, const char __user *buf, | |||
345 | goto out_free_rule; | 361 | goto out_free_rule; |
346 | } | 362 | } |
347 | 363 | ||
364 | switch (data[SMK_LABELLEN + SMK_LABELLEN + 4]) { | ||
365 | case '-': | ||
366 | break; | ||
367 | case 't': | ||
368 | case 'T': | ||
369 | rule->smk_access |= MAY_TRANSMUTE; | ||
370 | break; | ||
371 | default: | ||
372 | goto out_free_rule; | ||
373 | } | ||
374 | |||
348 | rc = smk_set_access(rule); | 375 | rc = smk_set_access(rule); |
349 | 376 | ||
350 | if (!rc) | 377 | if (!rc) |