diff options
author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
---|---|---|
committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /security/smack | |
parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) |
Patched in Tegra support.
Diffstat (limited to 'security/smack')
-rw-r--r-- | security/smack/Kconfig | 6 | ||||
-rw-r--r-- | security/smack/smack.h | 110 | ||||
-rw-r--r-- | security/smack/smack_access.c | 358 | ||||
-rw-r--r-- | security/smack/smack_lsm.c | 607 | ||||
-rw-r--r-- | security/smack/smackfs.c | 1284 |
5 files changed, 807 insertions, 1558 deletions
diff --git a/security/smack/Kconfig b/security/smack/Kconfig index e69de9c642b..603b0878434 100644 --- a/security/smack/Kconfig +++ b/security/smack/Kconfig | |||
@@ -1,10 +1,6 @@ | |||
1 | config SECURITY_SMACK | 1 | config SECURITY_SMACK |
2 | bool "Simplified Mandatory Access Control Kernel Support" | 2 | bool "Simplified Mandatory Access Control Kernel Support" |
3 | depends on NET | 3 | depends on NETLABEL && SECURITY_NETWORK |
4 | depends on INET | ||
5 | depends on SECURITY | ||
6 | select NETLABEL | ||
7 | select SECURITY_NETWORK | ||
8 | default n | 4 | default n |
9 | help | 5 | help |
10 | This selects the Simplified Mandatory Access Control Kernel. | 6 | This selects the Simplified Mandatory Access Control Kernel. |
diff --git a/security/smack/smack.h b/security/smack/smack.h index 99b36124f71..2b6c6a51612 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h | |||
@@ -23,19 +23,13 @@ | |||
23 | #include <linux/lsm_audit.h> | 23 | #include <linux/lsm_audit.h> |
24 | 24 | ||
25 | /* | 25 | /* |
26 | * Smack labels were limited to 23 characters for a long time. | ||
27 | */ | ||
28 | #define SMK_LABELLEN 24 | ||
29 | #define SMK_LONGLABEL 256 | ||
30 | |||
31 | /* | ||
32 | * Maximum number of bytes for the levels in a CIPSO IP option. | ||
33 | * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is | 26 | * Why 23? CIPSO is constrained to 30, so a 32 byte buffer is |
34 | * bigger than can be used, and 24 is the next lower multiple | 27 | * bigger than can be used, and 24 is the next lower multiple |
35 | * of 8, and there are too many issues if there isn't space set | 28 | * of 8, and there are too many issues if there isn't space set |
36 | * aside for the terminating null byte. | 29 | * aside for the terminating null byte. |
37 | */ | 30 | */ |
38 | #define SMK_CIPSOLEN 24 | 31 | #define SMK_MAXLEN 23 |
32 | #define SMK_LABELLEN (SMK_MAXLEN+1) | ||
39 | 33 | ||
40 | struct superblock_smack { | 34 | struct superblock_smack { |
41 | char *smk_root; | 35 | char *smk_root; |
@@ -43,12 +37,13 @@ struct superblock_smack { | |||
43 | char *smk_hat; | 37 | char *smk_hat; |
44 | char *smk_default; | 38 | char *smk_default; |
45 | int smk_initialized; | 39 | int smk_initialized; |
40 | spinlock_t smk_sblock; /* for initialization */ | ||
46 | }; | 41 | }; |
47 | 42 | ||
48 | struct socket_smack { | 43 | struct socket_smack { |
49 | char *smk_out; /* outbound label */ | 44 | char *smk_out; /* outbound label */ |
50 | char *smk_in; /* inbound label */ | 45 | char *smk_in; /* inbound label */ |
51 | char *smk_packet; /* TCP peer label */ | 46 | char smk_packet[SMK_LABELLEN]; /* TCP peer label */ |
52 | }; | 47 | }; |
53 | 48 | ||
54 | /* | 49 | /* |
@@ -71,7 +66,6 @@ struct task_smack { | |||
71 | 66 | ||
72 | #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ | 67 | #define SMK_INODE_INSTANT 0x01 /* inode is instantiated */ |
73 | #define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */ | 68 | #define SMK_INODE_TRANSMUTE 0x02 /* directory is transmuting */ |
74 | #define SMK_INODE_CHANGED 0x04 /* smack was transmuted */ | ||
75 | 69 | ||
76 | /* | 70 | /* |
77 | * A label access rule. | 71 | * A label access rule. |
@@ -84,6 +78,15 @@ struct smack_rule { | |||
84 | }; | 78 | }; |
85 | 79 | ||
86 | /* | 80 | /* |
81 | * An entry in the table mapping smack values to | ||
82 | * CIPSO level/category-set values. | ||
83 | */ | ||
84 | struct smack_cipso { | ||
85 | int smk_level; | ||
86 | char smk_catset[SMK_LABELLEN]; | ||
87 | }; | ||
88 | |||
89 | /* | ||
87 | * An entry in the table identifying hosts. | 90 | * An entry in the table identifying hosts. |
88 | */ | 91 | */ |
89 | struct smk_netlbladdr { | 92 | struct smk_netlbladdr { |
@@ -110,19 +113,16 @@ struct smk_netlbladdr { | |||
110 | * interfaces don't. The secid should go away when all of | 113 | * interfaces don't. The secid should go away when all of |
111 | * these components have been repaired. | 114 | * these components have been repaired. |
112 | * | 115 | * |
113 | * The cipso value associated with the label gets stored here, too. | 116 | * If there is a cipso value associated with the label it |
114 | * | 117 | * gets stored here, too. This will most likely be rare as |
115 | * Keep the access rules for this subject label here so that | 118 | * the cipso direct mapping in used internally. |
116 | * the entire set of rules does not need to be examined every | ||
117 | * time. | ||
118 | */ | 119 | */ |
119 | struct smack_known { | 120 | struct smack_known { |
120 | struct list_head list; | 121 | struct list_head list; |
121 | char *smk_known; | 122 | char smk_known[SMK_LABELLEN]; |
122 | u32 smk_secid; | 123 | u32 smk_secid; |
123 | struct netlbl_lsm_secattr smk_netlabel; /* on wire labels */ | 124 | struct smack_cipso *smk_cipso; |
124 | struct list_head smk_rules; /* access rules */ | 125 | spinlock_t smk_cipsolock; /* for changing cipso map */ |
125 | struct mutex smk_rules_lock; /* lock for rules */ | ||
126 | }; | 126 | }; |
127 | 127 | ||
128 | /* | 128 | /* |
@@ -150,6 +150,7 @@ struct smack_known { | |||
150 | 150 | ||
151 | /* | 151 | /* |
152 | * smackfs magic number | 152 | * smackfs magic number |
153 | * smackfs macic number | ||
153 | */ | 154 | */ |
154 | #define SMACK_MAGIC 0x43415d53 /* "SMAC" */ | 155 | #define SMACK_MAGIC 0x43415d53 /* "SMAC" */ |
155 | 156 | ||
@@ -159,7 +160,6 @@ struct smack_known { | |||
159 | #define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */ | 160 | #define SMACK_CIPSO_DOI_DEFAULT 3 /* Historical */ |
160 | #define SMACK_CIPSO_DOI_INVALID -1 /* Not a DOI */ | 161 | #define SMACK_CIPSO_DOI_INVALID -1 /* Not a DOI */ |
161 | #define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */ | 162 | #define SMACK_CIPSO_DIRECT_DEFAULT 250 /* Arbitrary */ |
162 | #define SMACK_CIPSO_MAPPED_DEFAULT 251 /* Also arbitrary */ | ||
163 | #define SMACK_CIPSO_MAXCATVAL 63 /* Bigger gets harder */ | 163 | #define SMACK_CIPSO_MAXCATVAL 63 /* Bigger gets harder */ |
164 | #define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */ | 164 | #define SMACK_CIPSO_MAXLEVEL 255 /* CIPSO 2.2 standard */ |
165 | #define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */ | 165 | #define SMACK_CIPSO_MAXCATNUM 239 /* CIPSO 2.2 standard */ |
@@ -176,18 +176,9 @@ struct smack_known { | |||
176 | #define MAY_NOT 0 | 176 | #define MAY_NOT 0 |
177 | 177 | ||
178 | /* | 178 | /* |
179 | * Number of access types used by Smack (rwxat) | 179 | * Number of access types used by Smack (rwxa) |
180 | */ | 180 | */ |
181 | #define SMK_NUM_ACCESS_TYPE 5 | 181 | #define SMK_NUM_ACCESS_TYPE 4 |
182 | |||
183 | /* SMACK data */ | ||
184 | struct smack_audit_data { | ||
185 | const char *function; | ||
186 | char *subject; | ||
187 | char *object; | ||
188 | char *request; | ||
189 | int result; | ||
190 | }; | ||
191 | 182 | ||
192 | /* | 183 | /* |
193 | * Smack audit data; is empty if CONFIG_AUDIT not set | 184 | * Smack audit data; is empty if CONFIG_AUDIT not set |
@@ -196,7 +187,6 @@ struct smack_audit_data { | |||
196 | struct smk_audit_info { | 187 | struct smk_audit_info { |
197 | #ifdef CONFIG_AUDIT | 188 | #ifdef CONFIG_AUDIT |
198 | struct common_audit_data a; | 189 | struct common_audit_data a; |
199 | struct smack_audit_data sad; | ||
200 | #endif | 190 | #endif |
201 | }; | 191 | }; |
202 | /* | 192 | /* |
@@ -210,19 +200,17 @@ struct inode_smack *new_inode_smack(char *); | |||
210 | int smk_access_entry(char *, char *, struct list_head *); | 200 | int smk_access_entry(char *, char *, struct list_head *); |
211 | int smk_access(char *, char *, int, struct smk_audit_info *); | 201 | int smk_access(char *, char *, int, struct smk_audit_info *); |
212 | int smk_curacc(char *, u32, struct smk_audit_info *); | 202 | int smk_curacc(char *, u32, struct smk_audit_info *); |
203 | int smack_to_cipso(const char *, struct smack_cipso *); | ||
204 | void smack_from_cipso(u32, char *, char *); | ||
213 | char *smack_from_secid(const u32); | 205 | char *smack_from_secid(const u32); |
214 | char *smk_parse_smack(const char *string, int len); | ||
215 | int smk_netlbl_mls(int, char *, struct netlbl_lsm_secattr *, int); | ||
216 | char *smk_import(const char *, int); | 206 | char *smk_import(const char *, int); |
217 | struct smack_known *smk_import_entry(const char *, int); | 207 | struct smack_known *smk_import_entry(const char *, int); |
218 | struct smack_known *smk_find_entry(const char *); | ||
219 | u32 smack_to_secid(const char *); | 208 | u32 smack_to_secid(const char *); |
220 | 209 | ||
221 | /* | 210 | /* |
222 | * Shared data. | 211 | * Shared data. |
223 | */ | 212 | */ |
224 | extern int smack_cipso_direct; | 213 | extern int smack_cipso_direct; |
225 | extern int smack_cipso_mapped; | ||
226 | extern char *smack_net_ambient; | 214 | extern char *smack_net_ambient; |
227 | extern char *smack_onlycap; | 215 | extern char *smack_onlycap; |
228 | extern const char *smack_cipso_option; | 216 | extern const char *smack_cipso_option; |
@@ -234,13 +222,25 @@ extern struct smack_known smack_known_invalid; | |||
234 | extern struct smack_known smack_known_star; | 222 | extern struct smack_known smack_known_star; |
235 | extern struct smack_known smack_known_web; | 223 | extern struct smack_known smack_known_web; |
236 | 224 | ||
237 | extern struct mutex smack_known_lock; | ||
238 | extern struct list_head smack_known_list; | 225 | extern struct list_head smack_known_list; |
226 | extern struct list_head smack_rule_list; | ||
239 | extern struct list_head smk_netlbladdr_list; | 227 | extern struct list_head smk_netlbladdr_list; |
240 | 228 | ||
241 | extern struct security_operations smack_ops; | 229 | extern struct security_operations smack_ops; |
242 | 230 | ||
243 | /* | 231 | /* |
232 | * Stricly for CIPSO level manipulation. | ||
233 | * Set the category bit number in a smack label sized buffer. | ||
234 | */ | ||
235 | static inline void smack_catset_bit(int cat, char *catsetp) | ||
236 | { | ||
237 | if (cat > SMK_LABELLEN * 8) | ||
238 | return; | ||
239 | |||
240 | catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8); | ||
241 | } | ||
242 | |||
243 | /* | ||
244 | * Is the directory transmuting? | 244 | * Is the directory transmuting? |
245 | */ | 245 | */ |
246 | static inline int smk_inode_transmutable(const struct inode *isp) | 246 | static inline int smk_inode_transmutable(const struct inode *isp) |
@@ -283,19 +283,6 @@ static inline char *smk_of_current(void) | |||
283 | } | 283 | } |
284 | 284 | ||
285 | /* | 285 | /* |
286 | * Is the task privileged and allowed to be privileged | ||
287 | * by the onlycap rule. | ||
288 | */ | ||
289 | static inline int smack_privileged(int cap) | ||
290 | { | ||
291 | if (!capable(cap)) | ||
292 | return 0; | ||
293 | if (smack_onlycap == NULL || smack_onlycap == smk_of_current()) | ||
294 | return 1; | ||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | /* | ||
299 | * logging functions | 286 | * logging functions |
300 | */ | 287 | */ |
301 | #define SMACK_AUDIT_DENIED 0x1 | 288 | #define SMACK_AUDIT_DENIED 0x1 |
@@ -316,18 +303,9 @@ void smack_log(char *subject_label, char *object_label, | |||
316 | static inline void smk_ad_init(struct smk_audit_info *a, const char *func, | 303 | static inline void smk_ad_init(struct smk_audit_info *a, const char *func, |
317 | char type) | 304 | char type) |
318 | { | 305 | { |
319 | memset(&a->sad, 0, sizeof(a->sad)); | 306 | memset(a, 0, sizeof(*a)); |
320 | a->a.type = type; | 307 | a->a.type = type; |
321 | a->a.smack_audit_data = &a->sad; | 308 | a->a.smack_audit_data.function = func; |
322 | a->a.smack_audit_data->function = func; | ||
323 | } | ||
324 | |||
325 | static inline void smk_ad_init_net(struct smk_audit_info *a, const char *func, | ||
326 | char type, struct lsm_network_audit *net) | ||
327 | { | ||
328 | smk_ad_init(a, func, type); | ||
329 | memset(net, 0, sizeof(*net)); | ||
330 | a->a.u.net = net; | ||
331 | } | 309 | } |
332 | 310 | ||
333 | static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a, | 311 | static inline void smk_ad_setfield_u_tsk(struct smk_audit_info *a, |
@@ -353,7 +331,7 @@ static inline void smk_ad_setfield_u_fs_path(struct smk_audit_info *a, | |||
353 | static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a, | 331 | static inline void smk_ad_setfield_u_net_sk(struct smk_audit_info *a, |
354 | struct sock *sk) | 332 | struct sock *sk) |
355 | { | 333 | { |
356 | a->a.u.net->sk = sk; | 334 | a->a.u.net.sk = sk; |
357 | } | 335 | } |
358 | 336 | ||
359 | #else /* no AUDIT */ | 337 | #else /* no AUDIT */ |
diff --git a/security/smack/smack_access.c b/security/smack/smack_access.c index db14689a21e..9637e107f7e 100644 --- a/security/smack/smack_access.c +++ b/security/smack/smack_access.c | |||
@@ -19,31 +19,37 @@ | |||
19 | struct smack_known smack_known_huh = { | 19 | struct smack_known smack_known_huh = { |
20 | .smk_known = "?", | 20 | .smk_known = "?", |
21 | .smk_secid = 2, | 21 | .smk_secid = 2, |
22 | .smk_cipso = NULL, | ||
22 | }; | 23 | }; |
23 | 24 | ||
24 | struct smack_known smack_known_hat = { | 25 | struct smack_known smack_known_hat = { |
25 | .smk_known = "^", | 26 | .smk_known = "^", |
26 | .smk_secid = 3, | 27 | .smk_secid = 3, |
28 | .smk_cipso = NULL, | ||
27 | }; | 29 | }; |
28 | 30 | ||
29 | struct smack_known smack_known_star = { | 31 | struct smack_known smack_known_star = { |
30 | .smk_known = "*", | 32 | .smk_known = "*", |
31 | .smk_secid = 4, | 33 | .smk_secid = 4, |
34 | .smk_cipso = NULL, | ||
32 | }; | 35 | }; |
33 | 36 | ||
34 | struct smack_known smack_known_floor = { | 37 | struct smack_known smack_known_floor = { |
35 | .smk_known = "_", | 38 | .smk_known = "_", |
36 | .smk_secid = 5, | 39 | .smk_secid = 5, |
40 | .smk_cipso = NULL, | ||
37 | }; | 41 | }; |
38 | 42 | ||
39 | struct smack_known smack_known_invalid = { | 43 | struct smack_known smack_known_invalid = { |
40 | .smk_known = "", | 44 | .smk_known = "", |
41 | .smk_secid = 6, | 45 | .smk_secid = 6, |
46 | .smk_cipso = NULL, | ||
42 | }; | 47 | }; |
43 | 48 | ||
44 | struct smack_known smack_known_web = { | 49 | struct smack_known smack_known_web = { |
45 | .smk_known = "@", | 50 | .smk_known = "@", |
46 | .smk_secid = 7, | 51 | .smk_secid = 7, |
52 | .smk_cipso = NULL, | ||
47 | }; | 53 | }; |
48 | 54 | ||
49 | LIST_HEAD(smack_known_list); | 55 | LIST_HEAD(smack_known_list); |
@@ -71,19 +77,14 @@ int log_policy = SMACK_AUDIT_DENIED; | |||
71 | * entry is found returns -ENOENT. | 77 | * entry is found returns -ENOENT. |
72 | * | 78 | * |
73 | * NOTE: | 79 | * NOTE: |
80 | * Even though Smack labels are usually shared on smack_list | ||
81 | * labels that come in off the network can't be imported | ||
82 | * and added to the list for locking reasons. | ||
74 | * | 83 | * |
75 | * Earlier versions of this function allowed for labels that | 84 | * Therefore, it is necessary to check the contents of the labels, |
76 | * were not on the label list. This was done to allow for | 85 | * not just the pointer values. Of course, in most cases the labels |
77 | * labels to come over the network that had never been seen | 86 | * will be on the list, so checking the pointers may be a worthwhile |
78 | * before on this host. Unless the receiving socket has the | 87 | * optimization. |
79 | * star label this will always result in a failure check. The | ||
80 | * star labeled socket case is now handled in the networking | ||
81 | * hooks so there is no case where the label is not on the | ||
82 | * label list. Checking to see if the address of two labels | ||
83 | * is the same is now a reliable test. | ||
84 | * | ||
85 | * Do the object check first because that is more | ||
86 | * likely to differ. | ||
87 | */ | 88 | */ |
88 | int smk_access_entry(char *subject_label, char *object_label, | 89 | int smk_access_entry(char *subject_label, char *object_label, |
89 | struct list_head *rule_list) | 90 | struct list_head *rule_list) |
@@ -92,10 +93,13 @@ int smk_access_entry(char *subject_label, char *object_label, | |||
92 | struct smack_rule *srp; | 93 | struct smack_rule *srp; |
93 | 94 | ||
94 | list_for_each_entry_rcu(srp, rule_list, list) { | 95 | list_for_each_entry_rcu(srp, rule_list, list) { |
95 | if (srp->smk_object == object_label && | 96 | if (srp->smk_subject == subject_label || |
96 | srp->smk_subject == subject_label) { | 97 | strcmp(srp->smk_subject, subject_label) == 0) { |
97 | may = srp->smk_access; | 98 | if (srp->smk_object == object_label || |
98 | break; | 99 | strcmp(srp->smk_object, object_label) == 0) { |
100 | may = srp->smk_access; | ||
101 | break; | ||
102 | } | ||
99 | } | 103 | } |
100 | } | 104 | } |
101 | 105 | ||
@@ -113,12 +117,18 @@ int smk_access_entry(char *subject_label, char *object_label, | |||
113 | * access rule list and returns 0 if the access is permitted, | 117 | * access rule list and returns 0 if the access is permitted, |
114 | * non zero otherwise. | 118 | * non zero otherwise. |
115 | * | 119 | * |
116 | * Smack labels are shared on smack_list | 120 | * Even though Smack labels are usually shared on smack_list |
121 | * labels that come in off the network can't be imported | ||
122 | * and added to the list for locking reasons. | ||
123 | * | ||
124 | * Therefore, it is necessary to check the contents of the labels, | ||
125 | * not just the pointer values. Of course, in most cases the labels | ||
126 | * will be on the list, so checking the pointers may be a worthwhile | ||
127 | * optimization. | ||
117 | */ | 128 | */ |
118 | int smk_access(char *subject_label, char *object_label, int request, | 129 | int smk_access(char *subject_label, char *object_label, int request, |
119 | struct smk_audit_info *a) | 130 | struct smk_audit_info *a) |
120 | { | 131 | { |
121 | struct smack_known *skp; | ||
122 | int may = MAY_NOT; | 132 | int may = MAY_NOT; |
123 | int rc = 0; | 133 | int rc = 0; |
124 | 134 | ||
@@ -127,7 +137,8 @@ int smk_access(char *subject_label, char *object_label, int request, | |||
127 | * | 137 | * |
128 | * A star subject can't access any object. | 138 | * A star subject can't access any object. |
129 | */ | 139 | */ |
130 | if (subject_label == smack_known_star.smk_known) { | 140 | if (subject_label == smack_known_star.smk_known || |
141 | strcmp(subject_label, smack_known_star.smk_known) == 0) { | ||
131 | rc = -EACCES; | 142 | rc = -EACCES; |
132 | goto out_audit; | 143 | goto out_audit; |
133 | } | 144 | } |
@@ -137,27 +148,33 @@ int smk_access(char *subject_label, char *object_label, int request, | |||
137 | * An internet subject can access any object. | 148 | * An internet subject can access any object. |
138 | */ | 149 | */ |
139 | if (object_label == smack_known_web.smk_known || | 150 | if (object_label == smack_known_web.smk_known || |
140 | subject_label == smack_known_web.smk_known) | 151 | subject_label == smack_known_web.smk_known || |
152 | strcmp(object_label, smack_known_web.smk_known) == 0 || | ||
153 | strcmp(subject_label, smack_known_web.smk_known) == 0) | ||
141 | goto out_audit; | 154 | goto out_audit; |
142 | /* | 155 | /* |
143 | * A star object can be accessed by any subject. | 156 | * A star object can be accessed by any subject. |
144 | */ | 157 | */ |
145 | if (object_label == smack_known_star.smk_known) | 158 | if (object_label == smack_known_star.smk_known || |
159 | strcmp(object_label, smack_known_star.smk_known) == 0) | ||
146 | goto out_audit; | 160 | goto out_audit; |
147 | /* | 161 | /* |
148 | * An object can be accessed in any way by a subject | 162 | * An object can be accessed in any way by a subject |
149 | * with the same label. | 163 | * with the same label. |
150 | */ | 164 | */ |
151 | if (subject_label == object_label) | 165 | if (subject_label == object_label || |
166 | strcmp(subject_label, object_label) == 0) | ||
152 | goto out_audit; | 167 | goto out_audit; |
153 | /* | 168 | /* |
154 | * A hat subject can read any object. | 169 | * A hat subject can read any object. |
155 | * A floor object can be read by any subject. | 170 | * A floor object can be read by any subject. |
156 | */ | 171 | */ |
157 | if ((request & MAY_ANYREAD) == request) { | 172 | if ((request & MAY_ANYREAD) == request) { |
158 | if (object_label == smack_known_floor.smk_known) | 173 | if (object_label == smack_known_floor.smk_known || |
174 | strcmp(object_label, smack_known_floor.smk_known) == 0) | ||
159 | goto out_audit; | 175 | goto out_audit; |
160 | if (subject_label == smack_known_hat.smk_known) | 176 | if (subject_label == smack_known_hat.smk_known || |
177 | strcmp(subject_label, smack_known_hat.smk_known) == 0) | ||
161 | goto out_audit; | 178 | goto out_audit; |
162 | } | 179 | } |
163 | /* | 180 | /* |
@@ -167,9 +184,8 @@ int smk_access(char *subject_label, char *object_label, int request, | |||
167 | * good. A negative response from smk_access_entry() | 184 | * good. A negative response from smk_access_entry() |
168 | * indicates there is no entry for this pair. | 185 | * indicates there is no entry for this pair. |
169 | */ | 186 | */ |
170 | skp = smk_find_entry(subject_label); | ||
171 | rcu_read_lock(); | 187 | rcu_read_lock(); |
172 | may = smk_access_entry(subject_label, object_label, &skp->smk_rules); | 188 | may = smk_access_entry(subject_label, object_label, &smack_rule_list); |
173 | rcu_read_unlock(); | 189 | rcu_read_unlock(); |
174 | 190 | ||
175 | if (may > 0 && (request & may) == request) | 191 | if (may > 0 && (request & may) == request) |
@@ -220,9 +236,14 @@ int smk_curacc(char *obj_label, u32 mode, struct smk_audit_info *a) | |||
220 | } | 236 | } |
221 | 237 | ||
222 | /* | 238 | /* |
223 | * Allow for priviliged to override policy. | 239 | * Return if a specific label has been designated as the |
240 | * only one that gets privilege and current does not | ||
241 | * have that label. | ||
224 | */ | 242 | */ |
225 | if (rc != 0 && smack_privileged(CAP_MAC_OVERRIDE)) | 243 | if (smack_onlycap != NULL && smack_onlycap != sp) |
244 | goto out_audit; | ||
245 | |||
246 | if (capable(CAP_MAC_OVERRIDE)) | ||
226 | rc = 0; | 247 | rc = 0; |
227 | 248 | ||
228 | out_audit: | 249 | out_audit: |
@@ -264,9 +285,9 @@ static inline void smack_str_from_perm(char *string, int access) | |||
264 | static void smack_log_callback(struct audit_buffer *ab, void *a) | 285 | static void smack_log_callback(struct audit_buffer *ab, void *a) |
265 | { | 286 | { |
266 | struct common_audit_data *ad = a; | 287 | struct common_audit_data *ad = a; |
267 | struct smack_audit_data *sad = ad->smack_audit_data; | 288 | struct smack_audit_data *sad = &ad->smack_audit_data; |
268 | audit_log_format(ab, "lsm=SMACK fn=%s action=%s", | 289 | audit_log_format(ab, "lsm=SMACK fn=%s action=%s", |
269 | ad->smack_audit_data->function, | 290 | ad->smack_audit_data.function, |
270 | sad->result ? "denied" : "granted"); | 291 | sad->result ? "denied" : "granted"); |
271 | audit_log_format(ab, " subject="); | 292 | audit_log_format(ab, " subject="); |
272 | audit_log_untrustedstring(ab, sad->subject); | 293 | audit_log_untrustedstring(ab, sad->subject); |
@@ -299,19 +320,19 @@ void smack_log(char *subject_label, char *object_label, int request, | |||
299 | if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0) | 320 | if (result == 0 && (log_policy & SMACK_AUDIT_ACCEPT) == 0) |
300 | return; | 321 | return; |
301 | 322 | ||
302 | sad = a->smack_audit_data; | 323 | if (a->smack_audit_data.function == NULL) |
303 | 324 | a->smack_audit_data.function = "unknown"; | |
304 | if (sad->function == NULL) | ||
305 | sad->function = "unknown"; | ||
306 | 325 | ||
307 | /* end preparing the audit data */ | 326 | /* end preparing the audit data */ |
327 | sad = &a->smack_audit_data; | ||
308 | smack_str_from_perm(request_buffer, request); | 328 | smack_str_from_perm(request_buffer, request); |
309 | sad->subject = subject_label; | 329 | sad->subject = subject_label; |
310 | sad->object = object_label; | 330 | sad->object = object_label; |
311 | sad->request = request_buffer; | 331 | sad->request = request_buffer; |
312 | sad->result = result; | 332 | sad->result = result; |
333 | a->lsm_pre_audit = smack_log_callback; | ||
313 | 334 | ||
314 | common_lsm_audit(a, smack_log_callback, NULL); | 335 | common_lsm_audit(a); |
315 | } | 336 | } |
316 | #else /* #ifdef CONFIG_AUDIT */ | 337 | #else /* #ifdef CONFIG_AUDIT */ |
317 | void smack_log(char *subject_label, char *object_label, int request, | 338 | void smack_log(char *subject_label, char *object_label, int request, |
@@ -320,102 +341,7 @@ void smack_log(char *subject_label, char *object_label, int request, | |||
320 | } | 341 | } |
321 | #endif | 342 | #endif |
322 | 343 | ||
323 | DEFINE_MUTEX(smack_known_lock); | 344 | static DEFINE_MUTEX(smack_known_lock); |
324 | |||
325 | /** | ||
326 | * smk_find_entry - find a label on the list, return the list entry | ||
327 | * @string: a text string that might be a Smack label | ||
328 | * | ||
329 | * Returns a pointer to the entry in the label list that | ||
330 | * matches the passed string. | ||
331 | */ | ||
332 | struct smack_known *smk_find_entry(const char *string) | ||
333 | { | ||
334 | struct smack_known *skp; | ||
335 | |||
336 | list_for_each_entry_rcu(skp, &smack_known_list, list) { | ||
337 | if (strcmp(skp->smk_known, string) == 0) | ||
338 | return skp; | ||
339 | } | ||
340 | |||
341 | return NULL; | ||
342 | } | ||
343 | |||
344 | /** | ||
345 | * smk_parse_smack - parse smack label from a text string | ||
346 | * @string: a text string that might contain a Smack label | ||
347 | * @len: the maximum size, or zero if it is NULL terminated. | ||
348 | * | ||
349 | * Returns a pointer to the clean label, or NULL | ||
350 | */ | ||
351 | char *smk_parse_smack(const char *string, int len) | ||
352 | { | ||
353 | char *smack; | ||
354 | int i; | ||
355 | |||
356 | if (len <= 0) | ||
357 | len = strlen(string) + 1; | ||
358 | |||
359 | /* | ||
360 | * Reserve a leading '-' as an indicator that | ||
361 | * this isn't a label, but an option to interfaces | ||
362 | * including /smack/cipso and /smack/cipso2 | ||
363 | */ | ||
364 | if (string[0] == '-') | ||
365 | return NULL; | ||
366 | |||
367 | for (i = 0; i < len; i++) | ||
368 | if (string[i] > '~' || string[i] <= ' ' || string[i] == '/' || | ||
369 | string[i] == '"' || string[i] == '\\' || string[i] == '\'') | ||
370 | break; | ||
371 | |||
372 | if (i == 0 || i >= SMK_LONGLABEL) | ||
373 | return NULL; | ||
374 | |||
375 | smack = kzalloc(i + 1, GFP_KERNEL); | ||
376 | if (smack != NULL) { | ||
377 | strncpy(smack, string, i + 1); | ||
378 | smack[i] = '\0'; | ||
379 | } | ||
380 | return smack; | ||
381 | } | ||
382 | |||
383 | /** | ||
384 | * smk_netlbl_mls - convert a catset to netlabel mls categories | ||
385 | * @catset: the Smack categories | ||
386 | * @sap: where to put the netlabel categories | ||
387 | * | ||
388 | * Allocates and fills attr.mls | ||
389 | * Returns 0 on success, error code on failure. | ||
390 | */ | ||
391 | int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap, | ||
392 | int len) | ||
393 | { | ||
394 | unsigned char *cp; | ||
395 | unsigned char m; | ||
396 | int cat; | ||
397 | int rc; | ||
398 | int byte; | ||
399 | |||
400 | sap->flags |= NETLBL_SECATTR_MLS_CAT; | ||
401 | sap->attr.mls.lvl = level; | ||
402 | sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC); | ||
403 | sap->attr.mls.cat->startbit = 0; | ||
404 | |||
405 | for (cat = 1, cp = catset, byte = 0; byte < len; cp++, byte++) | ||
406 | for (m = 0x80; m != 0; m >>= 1, cat++) { | ||
407 | if ((m & *cp) == 0) | ||
408 | continue; | ||
409 | rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat, | ||
410 | cat, GFP_ATOMIC); | ||
411 | if (rc < 0) { | ||
412 | netlbl_secattr_catmap_free(sap->attr.mls.cat); | ||
413 | return rc; | ||
414 | } | ||
415 | } | ||
416 | |||
417 | return 0; | ||
418 | } | ||
419 | 345 | ||
420 | /** | 346 | /** |
421 | * smk_import_entry - import a label, return the list entry | 347 | * smk_import_entry - import a label, return the list entry |
@@ -428,59 +354,53 @@ int smk_netlbl_mls(int level, char *catset, struct netlbl_lsm_secattr *sap, | |||
428 | struct smack_known *smk_import_entry(const char *string, int len) | 354 | struct smack_known *smk_import_entry(const char *string, int len) |
429 | { | 355 | { |
430 | struct smack_known *skp; | 356 | struct smack_known *skp; |
431 | char *smack; | 357 | char smack[SMK_LABELLEN]; |
432 | int slen; | 358 | int found; |
433 | int rc; | 359 | int i; |
434 | 360 | ||
435 | smack = smk_parse_smack(string, len); | 361 | if (len <= 0 || len > SMK_MAXLEN) |
436 | if (smack == NULL) | 362 | len = SMK_MAXLEN; |
363 | |||
364 | for (i = 0, found = 0; i < SMK_LABELLEN; i++) { | ||
365 | if (found) | ||
366 | smack[i] = '\0'; | ||
367 | else if (i >= len || string[i] > '~' || string[i] <= ' ' || | ||
368 | string[i] == '/' || string[i] == '"' || | ||
369 | string[i] == '\\' || string[i] == '\'') { | ||
370 | smack[i] = '\0'; | ||
371 | found = 1; | ||
372 | } else | ||
373 | smack[i] = string[i]; | ||
374 | } | ||
375 | |||
376 | if (smack[0] == '\0') | ||
437 | return NULL; | 377 | return NULL; |
438 | 378 | ||
439 | mutex_lock(&smack_known_lock); | 379 | mutex_lock(&smack_known_lock); |
440 | 380 | ||
441 | skp = smk_find_entry(smack); | 381 | found = 0; |
442 | if (skp != NULL) | 382 | list_for_each_entry_rcu(skp, &smack_known_list, list) { |
443 | goto freeout; | 383 | if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) { |
444 | 384 | found = 1; | |
445 | skp = kzalloc(sizeof(*skp), GFP_KERNEL); | 385 | break; |
446 | if (skp == NULL) | 386 | } |
447 | goto freeout; | 387 | } |
448 | 388 | ||
449 | skp->smk_known = smack; | 389 | if (found == 0) { |
450 | skp->smk_secid = smack_next_secid++; | 390 | skp = kzalloc(sizeof(struct smack_known), GFP_KERNEL); |
451 | skp->smk_netlabel.domain = skp->smk_known; | 391 | if (skp != NULL) { |
452 | skp->smk_netlabel.flags = | 392 | strncpy(skp->smk_known, smack, SMK_MAXLEN); |
453 | NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL; | 393 | skp->smk_secid = smack_next_secid++; |
454 | /* | 394 | skp->smk_cipso = NULL; |
455 | * If direct labeling works use it. | 395 | spin_lock_init(&skp->smk_cipsolock); |
456 | * Otherwise use mapped labeling. | 396 | /* |
457 | */ | 397 | * Make sure that the entry is actually |
458 | slen = strlen(smack); | 398 | * filled before putting it on the list. |
459 | if (slen < SMK_CIPSOLEN) | 399 | */ |
460 | rc = smk_netlbl_mls(smack_cipso_direct, skp->smk_known, | 400 | list_add_rcu(&skp->list, &smack_known_list); |
461 | &skp->smk_netlabel, slen); | 401 | } |
462 | else | ||
463 | rc = smk_netlbl_mls(smack_cipso_mapped, (char *)&skp->smk_secid, | ||
464 | &skp->smk_netlabel, sizeof(skp->smk_secid)); | ||
465 | |||
466 | if (rc >= 0) { | ||
467 | INIT_LIST_HEAD(&skp->smk_rules); | ||
468 | mutex_init(&skp->smk_rules_lock); | ||
469 | /* | ||
470 | * Make sure that the entry is actually | ||
471 | * filled before putting it on the list. | ||
472 | */ | ||
473 | list_add_rcu(&skp->list, &smack_known_list); | ||
474 | goto unlockout; | ||
475 | } | 402 | } |
476 | /* | 403 | |
477 | * smk_netlbl_mls failed. | ||
478 | */ | ||
479 | kfree(skp); | ||
480 | skp = NULL; | ||
481 | freeout: | ||
482 | kfree(smack); | ||
483 | unlockout: | ||
484 | mutex_unlock(&smack_known_lock); | 404 | mutex_unlock(&smack_known_lock); |
485 | 405 | ||
486 | return skp; | 406 | return skp; |
@@ -543,9 +463,85 @@ char *smack_from_secid(const u32 secid) | |||
543 | */ | 463 | */ |
544 | u32 smack_to_secid(const char *smack) | 464 | u32 smack_to_secid(const char *smack) |
545 | { | 465 | { |
546 | struct smack_known *skp = smk_find_entry(smack); | 466 | struct smack_known *skp; |
547 | 467 | ||
548 | if (skp == NULL) | 468 | rcu_read_lock(); |
549 | return 0; | 469 | list_for_each_entry_rcu(skp, &smack_known_list, list) { |
550 | return skp->smk_secid; | 470 | if (strncmp(skp->smk_known, smack, SMK_MAXLEN) == 0) { |
471 | rcu_read_unlock(); | ||
472 | return skp->smk_secid; | ||
473 | } | ||
474 | } | ||
475 | rcu_read_unlock(); | ||
476 | return 0; | ||
477 | } | ||
478 | |||
479 | /** | ||
480 | * smack_from_cipso - find the Smack label associated with a CIPSO option | ||
481 | * @level: Bell & LaPadula level from the network | ||
482 | * @cp: Bell & LaPadula categories from the network | ||
483 | * @result: where to put the Smack value | ||
484 | * | ||
485 | * This is a simple lookup in the label table. | ||
486 | * | ||
487 | * This is an odd duck as far as smack handling goes in that | ||
488 | * it sends back a copy of the smack label rather than a pointer | ||
489 | * to the master list. This is done because it is possible for | ||
490 | * a foreign host to send a smack label that is new to this | ||
491 | * machine and hence not on the list. That would not be an | ||
492 | * issue except that adding an entry to the master list can't | ||
493 | * be done at that point. | ||
494 | */ | ||
495 | void smack_from_cipso(u32 level, char *cp, char *result) | ||
496 | { | ||
497 | struct smack_known *kp; | ||
498 | char *final = NULL; | ||
499 | |||
500 | rcu_read_lock(); | ||
501 | list_for_each_entry(kp, &smack_known_list, list) { | ||
502 | if (kp->smk_cipso == NULL) | ||
503 | continue; | ||
504 | |||
505 | spin_lock_bh(&kp->smk_cipsolock); | ||
506 | |||
507 | if (kp->smk_cipso->smk_level == level && | ||
508 | memcmp(kp->smk_cipso->smk_catset, cp, SMK_LABELLEN) == 0) | ||
509 | final = kp->smk_known; | ||
510 | |||
511 | spin_unlock_bh(&kp->smk_cipsolock); | ||
512 | } | ||
513 | rcu_read_unlock(); | ||
514 | if (final == NULL) | ||
515 | final = smack_known_huh.smk_known; | ||
516 | strncpy(result, final, SMK_MAXLEN); | ||
517 | return; | ||
518 | } | ||
519 | |||
520 | /** | ||
521 | * smack_to_cipso - find the CIPSO option to go with a Smack label | ||
522 | * @smack: a pointer to the smack label in question | ||
523 | * @cp: where to put the result | ||
524 | * | ||
525 | * Returns zero if a value is available, non-zero otherwise. | ||
526 | */ | ||
527 | int smack_to_cipso(const char *smack, struct smack_cipso *cp) | ||
528 | { | ||
529 | struct smack_known *kp; | ||
530 | int found = 0; | ||
531 | |||
532 | rcu_read_lock(); | ||
533 | list_for_each_entry_rcu(kp, &smack_known_list, list) { | ||
534 | if (kp->smk_known == smack || | ||
535 | strcmp(kp->smk_known, smack) == 0) { | ||
536 | found = 1; | ||
537 | break; | ||
538 | } | ||
539 | } | ||
540 | rcu_read_unlock(); | ||
541 | |||
542 | if (found == 0 || kp->smk_cipso == NULL) | ||
543 | return -ENOENT; | ||
544 | |||
545 | memcpy(cp, kp->smk_cipso, sizeof(struct smack_cipso)); | ||
546 | return 0; | ||
551 | } | 547 | } |
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 38be92ce901..b9c5e149903 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -5,13 +5,12 @@ | |||
5 | * | 5 | * |
6 | * Authors: | 6 | * Authors: |
7 | * Casey Schaufler <casey@schaufler-ca.com> | 7 | * Casey Schaufler <casey@schaufler-ca.com> |
8 | * Jarkko Sakkinen <jarkko.sakkinen@intel.com> | 8 | * Jarkko Sakkinen <ext-jarkko.2.sakkinen@nokia.com> |
9 | * | 9 | * |
10 | * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com> | 10 | * Copyright (C) 2007 Casey Schaufler <casey@schaufler-ca.com> |
11 | * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. | 11 | * Copyright (C) 2009 Hewlett-Packard Development Company, L.P. |
12 | * Paul Moore <paul@paul-moore.com> | 12 | * Paul Moore <paul@paul-moore.com> |
13 | * Copyright (C) 2010 Nokia Corporation | 13 | * Copyright (C) 2010 Nokia Corporation |
14 | * Copyright (C) 2011 Intel Corporation. | ||
15 | * | 14 | * |
16 | * 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 |
17 | * 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, |
@@ -30,14 +29,11 @@ | |||
30 | #include <linux/slab.h> | 29 | #include <linux/slab.h> |
31 | #include <linux/mutex.h> | 30 | #include <linux/mutex.h> |
32 | #include <linux/pipe_fs_i.h> | 31 | #include <linux/pipe_fs_i.h> |
32 | #include <net/netlabel.h> | ||
33 | #include <net/cipso_ipv4.h> | 33 | #include <net/cipso_ipv4.h> |
34 | #include <linux/audit.h> | 34 | #include <linux/audit.h> |
35 | #include <linux/magic.h> | 35 | #include <linux/magic.h> |
36 | #include <linux/dcache.h> | 36 | #include <linux/dcache.h> |
37 | #include <linux/personality.h> | ||
38 | #include <linux/msg.h> | ||
39 | #include <linux/shm.h> | ||
40 | #include <linux/binfmts.h> | ||
41 | #include "smack.h" | 37 | #include "smack.h" |
42 | 38 | ||
43 | #define task_security(task) (task_cred_xxx((task), security)) | 39 | #define task_security(task) (task_cred_xxx((task), security)) |
@@ -56,23 +52,16 @@ | |||
56 | static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp) | 52 | static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp) |
57 | { | 53 | { |
58 | int rc; | 54 | int rc; |
59 | char *buffer; | 55 | char in[SMK_LABELLEN]; |
60 | char *result = NULL; | ||
61 | 56 | ||
62 | if (ip->i_op->getxattr == NULL) | 57 | if (ip->i_op->getxattr == NULL) |
63 | return NULL; | 58 | return NULL; |
64 | 59 | ||
65 | buffer = kzalloc(SMK_LONGLABEL, GFP_KERNEL); | 60 | rc = ip->i_op->getxattr(dp, name, in, SMK_LABELLEN); |
66 | if (buffer == NULL) | 61 | if (rc < 0) |
67 | return NULL; | 62 | return NULL; |
68 | 63 | ||
69 | rc = ip->i_op->getxattr(dp, name, buffer, SMK_LONGLABEL); | 64 | return smk_import(in, rc); |
70 | if (rc > 0) | ||
71 | result = smk_import(buffer, rc); | ||
72 | |||
73 | kfree(buffer); | ||
74 | |||
75 | return result; | ||
76 | } | 65 | } |
77 | 66 | ||
78 | /** | 67 | /** |
@@ -85,7 +74,7 @@ struct inode_smack *new_inode_smack(char *smack) | |||
85 | { | 74 | { |
86 | struct inode_smack *isp; | 75 | struct inode_smack *isp; |
87 | 76 | ||
88 | isp = kzalloc(sizeof(struct inode_smack), GFP_NOFS); | 77 | isp = kzalloc(sizeof(struct inode_smack), GFP_KERNEL); |
89 | if (isp == NULL) | 78 | if (isp == NULL) |
90 | return NULL; | 79 | return NULL; |
91 | 80 | ||
@@ -217,7 +206,7 @@ static int smack_syslog(int typefrom_file) | |||
217 | int rc = 0; | 206 | int rc = 0; |
218 | char *sp = smk_of_current(); | 207 | char *sp = smk_of_current(); |
219 | 208 | ||
220 | if (smack_privileged(CAP_MAC_OVERRIDE)) | 209 | if (capable(CAP_MAC_OVERRIDE)) |
221 | return 0; | 210 | return 0; |
222 | 211 | ||
223 | if (sp != smack_known_floor.smk_known) | 212 | if (sp != smack_known_floor.smk_known) |
@@ -251,6 +240,7 @@ static int smack_sb_alloc_security(struct super_block *sb) | |||
251 | sbsp->smk_floor = smack_known_floor.smk_known; | 240 | sbsp->smk_floor = smack_known_floor.smk_known; |
252 | sbsp->smk_hat = smack_known_hat.smk_known; | 241 | sbsp->smk_hat = smack_known_hat.smk_known; |
253 | sbsp->smk_initialized = 0; | 242 | sbsp->smk_initialized = 0; |
243 | spin_lock_init(&sbsp->smk_sblock); | ||
254 | 244 | ||
255 | sb->s_security = sbsp; | 245 | sb->s_security = sbsp; |
256 | 246 | ||
@@ -331,10 +321,13 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
331 | char *commap; | 321 | char *commap; |
332 | char *nsp; | 322 | char *nsp; |
333 | 323 | ||
334 | if (sp->smk_initialized != 0) | 324 | spin_lock(&sp->smk_sblock); |
325 | if (sp->smk_initialized != 0) { | ||
326 | spin_unlock(&sp->smk_sblock); | ||
335 | return 0; | 327 | return 0; |
336 | 328 | } | |
337 | sp->smk_initialized = 1; | 329 | sp->smk_initialized = 1; |
330 | spin_unlock(&sp->smk_sblock); | ||
338 | 331 | ||
339 | for (op = data; op != NULL; op = commap) { | 332 | for (op = data; op != NULL; op = commap) { |
340 | commap = strchr(op, ','); | 333 | commap = strchr(op, ','); |
@@ -408,10 +401,10 @@ static int smack_sb_statfs(struct dentry *dentry) | |||
408 | * Returns 0 if current can write the floor of the filesystem | 401 | * Returns 0 if current can write the floor of the filesystem |
409 | * being mounted on, an error code otherwise. | 402 | * being mounted on, an error code otherwise. |
410 | */ | 403 | */ |
411 | static int smack_sb_mount(const char *dev_name, struct path *path, | 404 | static int smack_sb_mount(char *dev_name, struct path *path, |
412 | const char *type, unsigned long flags, void *data) | 405 | char *type, unsigned long flags, void *data) |
413 | { | 406 | { |
414 | struct superblock_smack *sbp = path->dentry->d_sb->s_security; | 407 | struct superblock_smack *sbp = path->mnt->mnt_sb->s_security; |
415 | struct smk_audit_info ad; | 408 | struct smk_audit_info ad; |
416 | 409 | ||
417 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 410 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
@@ -440,7 +433,7 @@ static int smack_sb_umount(struct vfsmount *mnt, int flags) | |||
440 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | 433 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
441 | smk_ad_setfield_u_fs_path(&ad, path); | 434 | smk_ad_setfield_u_fs_path(&ad, path); |
442 | 435 | ||
443 | sbp = path.dentry->d_sb->s_security; | 436 | sbp = mnt->mnt_sb->s_security; |
444 | return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad); | 437 | return smk_curacc(sbp->smk_floor, MAY_WRITE, &ad); |
445 | } | 438 | } |
446 | 439 | ||
@@ -448,17 +441,11 @@ static int smack_sb_umount(struct vfsmount *mnt, int flags) | |||
448 | * BPRM hooks | 441 | * BPRM hooks |
449 | */ | 442 | */ |
450 | 443 | ||
451 | /** | ||
452 | * smack_bprm_set_creds - set creds for exec | ||
453 | * @bprm: the exec information | ||
454 | * | ||
455 | * Returns 0 if it gets a blob, -ENOMEM otherwise | ||
456 | */ | ||
457 | static int smack_bprm_set_creds(struct linux_binprm *bprm) | 444 | static int smack_bprm_set_creds(struct linux_binprm *bprm) |
458 | { | 445 | { |
459 | struct inode *inode = bprm->file->f_path.dentry->d_inode; | 446 | struct task_smack *tsp = bprm->cred->security; |
460 | struct task_smack *bsp = bprm->cred->security; | ||
461 | struct inode_smack *isp; | 447 | struct inode_smack *isp; |
448 | struct dentry *dp; | ||
462 | int rc; | 449 | int rc; |
463 | 450 | ||
464 | rc = cap_bprm_set_creds(bprm); | 451 | rc = cap_bprm_set_creds(bprm); |
@@ -468,48 +455,20 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm) | |||
468 | if (bprm->cred_prepared) | 455 | if (bprm->cred_prepared) |
469 | return 0; | 456 | return 0; |
470 | 457 | ||
471 | isp = inode->i_security; | 458 | if (bprm->file == NULL || bprm->file->f_dentry == NULL) |
472 | if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task) | ||
473 | return 0; | 459 | return 0; |
474 | 460 | ||
475 | if (bprm->unsafe) | 461 | dp = bprm->file->f_dentry; |
476 | return -EPERM; | ||
477 | |||
478 | bsp->smk_task = isp->smk_task; | ||
479 | bprm->per_clear |= PER_CLEAR_ON_SETID; | ||
480 | |||
481 | return 0; | ||
482 | } | ||
483 | 462 | ||
484 | /** | 463 | if (dp->d_inode == NULL) |
485 | * smack_bprm_committing_creds - Prepare to install the new credentials | 464 | return 0; |
486 | * from bprm. | ||
487 | * | ||
488 | * @bprm: binprm for exec | ||
489 | */ | ||
490 | static void smack_bprm_committing_creds(struct linux_binprm *bprm) | ||
491 | { | ||
492 | struct task_smack *bsp = bprm->cred->security; | ||
493 | |||
494 | if (bsp->smk_task != bsp->smk_forked) | ||
495 | current->pdeath_signal = 0; | ||
496 | } | ||
497 | 465 | ||
498 | /** | 466 | isp = dp->d_inode->i_security; |
499 | * smack_bprm_secureexec - Return the decision to use secureexec. | ||
500 | * @bprm: binprm for exec | ||
501 | * | ||
502 | * Returns 0 on success. | ||
503 | */ | ||
504 | static int smack_bprm_secureexec(struct linux_binprm *bprm) | ||
505 | { | ||
506 | struct task_smack *tsp = current_security(); | ||
507 | int ret = cap_bprm_secureexec(bprm); | ||
508 | 467 | ||
509 | if (!ret && (tsp->smk_task != tsp->smk_forked)) | 468 | if (isp->smk_task != NULL) |
510 | ret = 1; | 469 | tsp->smk_task = isp->smk_task; |
511 | 470 | ||
512 | return ret; | 471 | return 0; |
513 | } | 472 | } |
514 | 473 | ||
515 | /* | 474 | /* |
@@ -557,38 +516,31 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
557 | const struct qstr *qstr, char **name, | 516 | const struct qstr *qstr, char **name, |
558 | void **value, size_t *len) | 517 | void **value, size_t *len) |
559 | { | 518 | { |
560 | struct smack_known *skp; | ||
561 | struct inode_smack *issp = inode->i_security; | ||
562 | char *csp = smk_of_current(); | ||
563 | char *isp = smk_of_inode(inode); | 519 | char *isp = smk_of_inode(inode); |
564 | char *dsp = smk_of_inode(dir); | 520 | char *dsp = smk_of_inode(dir); |
565 | int may; | 521 | int may; |
566 | 522 | ||
567 | if (name) { | 523 | if (name) { |
568 | *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_NOFS); | 524 | *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL); |
569 | if (*name == NULL) | 525 | if (*name == NULL) |
570 | return -ENOMEM; | 526 | return -ENOMEM; |
571 | } | 527 | } |
572 | 528 | ||
573 | if (value) { | 529 | if (value) { |
574 | skp = smk_find_entry(csp); | ||
575 | rcu_read_lock(); | 530 | rcu_read_lock(); |
576 | may = smk_access_entry(csp, dsp, &skp->smk_rules); | 531 | may = smk_access_entry(smk_of_current(), dsp, &smack_rule_list); |
577 | rcu_read_unlock(); | 532 | rcu_read_unlock(); |
578 | 533 | ||
579 | /* | 534 | /* |
580 | * If the access rule allows transmutation and | 535 | * If the access rule allows transmutation and |
581 | * the directory requests transmutation then | 536 | * the directory requests transmutation then |
582 | * by all means transmute. | 537 | * by all means transmute. |
583 | * Mark the inode as changed. | ||
584 | */ | 538 | */ |
585 | if (may > 0 && ((may & MAY_TRANSMUTE) != 0) && | 539 | if (may > 0 && ((may & MAY_TRANSMUTE) != 0) && |
586 | smk_inode_transmutable(dir)) { | 540 | smk_inode_transmutable(dir)) |
587 | isp = dsp; | 541 | isp = dsp; |
588 | issp->smk_flags |= SMK_INODE_CHANGED; | ||
589 | } | ||
590 | 542 | ||
591 | *value = kstrdup(isp, GFP_NOFS); | 543 | *value = kstrdup(isp, GFP_KERNEL); |
592 | if (*value == NULL) | 544 | if (*value == NULL) |
593 | return -ENOMEM; | 545 | return -ENOMEM; |
594 | } | 546 | } |
@@ -821,17 +773,17 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
821 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || | 773 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || |
822 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || | 774 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || |
823 | strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { | 775 | strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { |
824 | if (!smack_privileged(CAP_MAC_ADMIN)) | 776 | if (!capable(CAP_MAC_ADMIN)) |
825 | rc = -EPERM; | 777 | rc = -EPERM; |
826 | /* | 778 | /* |
827 | * check label validity here so import wont fail on | 779 | * check label validity here so import wont fail on |
828 | * post_setxattr | 780 | * post_setxattr |
829 | */ | 781 | */ |
830 | if (size == 0 || size >= SMK_LONGLABEL || | 782 | if (size == 0 || size >= SMK_LABELLEN || |
831 | smk_import(value, size) == NULL) | 783 | smk_import(value, size) == NULL) |
832 | rc = -EINVAL; | 784 | rc = -EINVAL; |
833 | } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { | 785 | } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { |
834 | if (!smack_privileged(CAP_MAC_ADMIN)) | 786 | if (!capable(CAP_MAC_ADMIN)) |
835 | rc = -EPERM; | 787 | rc = -EPERM; |
836 | if (size != TRANS_TRUE_SIZE || | 788 | if (size != TRANS_TRUE_SIZE || |
837 | strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0) | 789 | strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0) |
@@ -889,7 +841,7 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
889 | return; | 841 | return; |
890 | } | 842 | } |
891 | 843 | ||
892 | /** | 844 | /* |
893 | * smack_inode_getxattr - Smack check on getxattr | 845 | * smack_inode_getxattr - Smack check on getxattr |
894 | * @dentry: the object | 846 | * @dentry: the object |
895 | * @name: unused | 847 | * @name: unused |
@@ -906,7 +858,7 @@ static int smack_inode_getxattr(struct dentry *dentry, const char *name) | |||
906 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); | 858 | return smk_curacc(smk_of_inode(dentry->d_inode), MAY_READ, &ad); |
907 | } | 859 | } |
908 | 860 | ||
909 | /** | 861 | /* |
910 | * smack_inode_removexattr - Smack check on removexattr | 862 | * smack_inode_removexattr - Smack check on removexattr |
911 | * @dentry: the object | 863 | * @dentry: the object |
912 | * @name: name of the attribute | 864 | * @name: name of the attribute |
@@ -927,7 +879,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) | |||
927 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || | 879 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || |
928 | strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 || | 880 | strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 || |
929 | strcmp(name, XATTR_NAME_SMACKMMAP)) { | 881 | strcmp(name, XATTR_NAME_SMACKMMAP)) { |
930 | if (!smack_privileged(CAP_MAC_ADMIN)) | 882 | if (!capable(CAP_MAC_ADMIN)) |
931 | rc = -EPERM; | 883 | rc = -EPERM; |
932 | } else | 884 | } else |
933 | rc = cap_inode_removexattr(dentry, name); | 885 | rc = cap_inode_removexattr(dentry, name); |
@@ -1136,38 +1088,43 @@ static int smack_file_lock(struct file *file, unsigned int cmd) | |||
1136 | * @cmd: what action to check | 1088 | * @cmd: what action to check |
1137 | * @arg: unused | 1089 | * @arg: unused |
1138 | * | 1090 | * |
1139 | * Generally these operations are harmless. | ||
1140 | * File locking operations present an obvious mechanism | ||
1141 | * for passing information, so they require write access. | ||
1142 | * | ||
1143 | * Returns 0 if current has access, error code otherwise | 1091 | * Returns 0 if current has access, error code otherwise |
1144 | */ | 1092 | */ |
1145 | static int smack_file_fcntl(struct file *file, unsigned int cmd, | 1093 | static int smack_file_fcntl(struct file *file, unsigned int cmd, |
1146 | unsigned long arg) | 1094 | unsigned long arg) |
1147 | { | 1095 | { |
1148 | struct smk_audit_info ad; | 1096 | struct smk_audit_info ad; |
1149 | int rc = 0; | 1097 | int rc; |
1150 | 1098 | ||
1099 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | ||
1100 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | ||
1151 | 1101 | ||
1152 | switch (cmd) { | 1102 | switch (cmd) { |
1103 | case F_DUPFD: | ||
1104 | case F_GETFD: | ||
1105 | case F_GETFL: | ||
1153 | case F_GETLK: | 1106 | case F_GETLK: |
1107 | case F_GETOWN: | ||
1108 | case F_GETSIG: | ||
1109 | rc = smk_curacc(file->f_security, MAY_READ, &ad); | ||
1110 | break; | ||
1111 | case F_SETFD: | ||
1112 | case F_SETFL: | ||
1154 | case F_SETLK: | 1113 | case F_SETLK: |
1155 | case F_SETLKW: | 1114 | case F_SETLKW: |
1156 | case F_SETOWN: | 1115 | case F_SETOWN: |
1157 | case F_SETSIG: | 1116 | case F_SETSIG: |
1158 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); | ||
1159 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | ||
1160 | rc = smk_curacc(file->f_security, MAY_WRITE, &ad); | 1117 | rc = smk_curacc(file->f_security, MAY_WRITE, &ad); |
1161 | break; | 1118 | break; |
1162 | default: | 1119 | default: |
1163 | break; | 1120 | rc = smk_curacc(file->f_security, MAY_READWRITE, &ad); |
1164 | } | 1121 | } |
1165 | 1122 | ||
1166 | return rc; | 1123 | return rc; |
1167 | } | 1124 | } |
1168 | 1125 | ||
1169 | /** | 1126 | /** |
1170 | * smack_mmap_file : | 1127 | * smack_file_mmap : |
1171 | * Check permissions for a mmap operation. The @file may be NULL, e.g. | 1128 | * Check permissions for a mmap operation. The @file may be NULL, e.g. |
1172 | * if mapping anonymous memory. | 1129 | * if mapping anonymous memory. |
1173 | * @file contains the file structure for file to map (may be NULL). | 1130 | * @file contains the file structure for file to map (may be NULL). |
@@ -1176,11 +1133,11 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd, | |||
1176 | * @flags contains the operational flags. | 1133 | * @flags contains the operational flags. |
1177 | * Return 0 if permission is granted. | 1134 | * Return 0 if permission is granted. |
1178 | */ | 1135 | */ |
1179 | static int smack_mmap_file(struct file *file, | 1136 | static int smack_file_mmap(struct file *file, |
1180 | unsigned long reqprot, unsigned long prot, | 1137 | unsigned long reqprot, unsigned long prot, |
1181 | unsigned long flags) | 1138 | unsigned long flags, unsigned long addr, |
1139 | unsigned long addr_only) | ||
1182 | { | 1140 | { |
1183 | struct smack_known *skp; | ||
1184 | struct smack_rule *srp; | 1141 | struct smack_rule *srp; |
1185 | struct task_smack *tsp; | 1142 | struct task_smack *tsp; |
1186 | char *sp; | 1143 | char *sp; |
@@ -1193,6 +1150,11 @@ static int smack_mmap_file(struct file *file, | |||
1193 | int tmay; | 1150 | int tmay; |
1194 | int rc; | 1151 | int rc; |
1195 | 1152 | ||
1153 | /* do DAC check on address space usage */ | ||
1154 | rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only); | ||
1155 | if (rc || addr_only) | ||
1156 | return rc; | ||
1157 | |||
1196 | if (file == NULL || file->f_dentry == NULL) | 1158 | if (file == NULL || file->f_dentry == NULL) |
1197 | return 0; | 1159 | return 0; |
1198 | 1160 | ||
@@ -1208,7 +1170,6 @@ static int smack_mmap_file(struct file *file, | |||
1208 | 1170 | ||
1209 | tsp = current_security(); | 1171 | tsp = current_security(); |
1210 | sp = smk_of_current(); | 1172 | sp = smk_of_current(); |
1211 | skp = smk_find_entry(sp); | ||
1212 | rc = 0; | 1173 | rc = 0; |
1213 | 1174 | ||
1214 | rcu_read_lock(); | 1175 | rcu_read_lock(); |
@@ -1216,8 +1177,15 @@ static int smack_mmap_file(struct file *file, | |||
1216 | * For each Smack rule associated with the subject | 1177 | * For each Smack rule associated with the subject |
1217 | * label verify that the SMACK64MMAP also has access | 1178 | * label verify that the SMACK64MMAP also has access |
1218 | * to that rule's object label. | 1179 | * to that rule's object label. |
1180 | * | ||
1181 | * Because neither of the labels comes | ||
1182 | * from the networking code it is sufficient | ||
1183 | * to compare pointers. | ||
1219 | */ | 1184 | */ |
1220 | list_for_each_entry_rcu(srp, &skp->smk_rules, list) { | 1185 | list_for_each_entry_rcu(srp, &smack_rule_list, list) { |
1186 | if (srp->smk_subject != sp) | ||
1187 | continue; | ||
1188 | |||
1221 | osmack = srp->smk_object; | 1189 | osmack = srp->smk_object; |
1222 | /* | 1190 | /* |
1223 | * Matching labels always allows access. | 1191 | * Matching labels always allows access. |
@@ -1246,8 +1214,7 @@ static int smack_mmap_file(struct file *file, | |||
1246 | * If there isn't one a SMACK64MMAP subject | 1214 | * If there isn't one a SMACK64MMAP subject |
1247 | * can't have as much access as current. | 1215 | * can't have as much access as current. |
1248 | */ | 1216 | */ |
1249 | skp = smk_find_entry(msmack); | 1217 | mmay = smk_access_entry(msmack, osmack, &smack_rule_list); |
1250 | mmay = smk_access_entry(msmack, osmack, &skp->smk_rules); | ||
1251 | if (mmay == -ENOENT) { | 1218 | if (mmay == -ENOENT) { |
1252 | rc = -EACCES; | 1219 | rc = -EACCES; |
1253 | break; | 1220 | break; |
@@ -1348,24 +1315,6 @@ static int smack_file_receive(struct file *file) | |||
1348 | return smk_curacc(file->f_security, may, &ad); | 1315 | return smk_curacc(file->f_security, may, &ad); |
1349 | } | 1316 | } |
1350 | 1317 | ||
1351 | /** | ||
1352 | * smack_file_open - Smack dentry open processing | ||
1353 | * @file: the object | ||
1354 | * @cred: unused | ||
1355 | * | ||
1356 | * Set the security blob in the file structure. | ||
1357 | * | ||
1358 | * Returns 0 | ||
1359 | */ | ||
1360 | static int smack_file_open(struct file *file, const struct cred *cred) | ||
1361 | { | ||
1362 | struct inode_smack *isp = file->f_path.dentry->d_inode->i_security; | ||
1363 | |||
1364 | file->f_security = isp->smk_inode; | ||
1365 | |||
1366 | return 0; | ||
1367 | } | ||
1368 | |||
1369 | /* | 1318 | /* |
1370 | * Task hooks | 1319 | * Task hooks |
1371 | */ | 1320 | */ |
@@ -1506,17 +1455,15 @@ static int smack_kernel_create_files_as(struct cred *new, | |||
1506 | /** | 1455 | /** |
1507 | * smk_curacc_on_task - helper to log task related access | 1456 | * smk_curacc_on_task - helper to log task related access |
1508 | * @p: the task object | 1457 | * @p: the task object |
1509 | * @access: the access requested | 1458 | * @access : the access requested |
1510 | * @caller: name of the calling function for audit | ||
1511 | * | 1459 | * |
1512 | * Return 0 if access is permitted | 1460 | * Return 0 if access is permitted |
1513 | */ | 1461 | */ |
1514 | static int smk_curacc_on_task(struct task_struct *p, int access, | 1462 | static int smk_curacc_on_task(struct task_struct *p, int access) |
1515 | const char *caller) | ||
1516 | { | 1463 | { |
1517 | struct smk_audit_info ad; | 1464 | struct smk_audit_info ad; |
1518 | 1465 | ||
1519 | smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK); | 1466 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
1520 | smk_ad_setfield_u_tsk(&ad, p); | 1467 | smk_ad_setfield_u_tsk(&ad, p); |
1521 | return smk_curacc(smk_of_task(task_security(p)), access, &ad); | 1468 | return smk_curacc(smk_of_task(task_security(p)), access, &ad); |
1522 | } | 1469 | } |
@@ -1530,7 +1477,7 @@ static int smk_curacc_on_task(struct task_struct *p, int access, | |||
1530 | */ | 1477 | */ |
1531 | static int smack_task_setpgid(struct task_struct *p, pid_t pgid) | 1478 | static int smack_task_setpgid(struct task_struct *p, pid_t pgid) |
1532 | { | 1479 | { |
1533 | return smk_curacc_on_task(p, MAY_WRITE, __func__); | 1480 | return smk_curacc_on_task(p, MAY_WRITE); |
1534 | } | 1481 | } |
1535 | 1482 | ||
1536 | /** | 1483 | /** |
@@ -1541,7 +1488,7 @@ static int smack_task_setpgid(struct task_struct *p, pid_t pgid) | |||
1541 | */ | 1488 | */ |
1542 | static int smack_task_getpgid(struct task_struct *p) | 1489 | static int smack_task_getpgid(struct task_struct *p) |
1543 | { | 1490 | { |
1544 | return smk_curacc_on_task(p, MAY_READ, __func__); | 1491 | return smk_curacc_on_task(p, MAY_READ); |
1545 | } | 1492 | } |
1546 | 1493 | ||
1547 | /** | 1494 | /** |
@@ -1552,7 +1499,7 @@ static int smack_task_getpgid(struct task_struct *p) | |||
1552 | */ | 1499 | */ |
1553 | static int smack_task_getsid(struct task_struct *p) | 1500 | static int smack_task_getsid(struct task_struct *p) |
1554 | { | 1501 | { |
1555 | return smk_curacc_on_task(p, MAY_READ, __func__); | 1502 | return smk_curacc_on_task(p, MAY_READ); |
1556 | } | 1503 | } |
1557 | 1504 | ||
1558 | /** | 1505 | /** |
@@ -1580,7 +1527,7 @@ static int smack_task_setnice(struct task_struct *p, int nice) | |||
1580 | 1527 | ||
1581 | rc = cap_task_setnice(p, nice); | 1528 | rc = cap_task_setnice(p, nice); |
1582 | if (rc == 0) | 1529 | if (rc == 0) |
1583 | rc = smk_curacc_on_task(p, MAY_WRITE, __func__); | 1530 | rc = smk_curacc_on_task(p, MAY_WRITE); |
1584 | return rc; | 1531 | return rc; |
1585 | } | 1532 | } |
1586 | 1533 | ||
@@ -1597,7 +1544,7 @@ static int smack_task_setioprio(struct task_struct *p, int ioprio) | |||
1597 | 1544 | ||
1598 | rc = cap_task_setioprio(p, ioprio); | 1545 | rc = cap_task_setioprio(p, ioprio); |
1599 | if (rc == 0) | 1546 | if (rc == 0) |
1600 | rc = smk_curacc_on_task(p, MAY_WRITE, __func__); | 1547 | rc = smk_curacc_on_task(p, MAY_WRITE); |
1601 | return rc; | 1548 | return rc; |
1602 | } | 1549 | } |
1603 | 1550 | ||
@@ -1609,7 +1556,7 @@ static int smack_task_setioprio(struct task_struct *p, int ioprio) | |||
1609 | */ | 1556 | */ |
1610 | static int smack_task_getioprio(struct task_struct *p) | 1557 | static int smack_task_getioprio(struct task_struct *p) |
1611 | { | 1558 | { |
1612 | return smk_curacc_on_task(p, MAY_READ, __func__); | 1559 | return smk_curacc_on_task(p, MAY_READ); |
1613 | } | 1560 | } |
1614 | 1561 | ||
1615 | /** | 1562 | /** |
@@ -1626,7 +1573,7 @@ static int smack_task_setscheduler(struct task_struct *p) | |||
1626 | 1573 | ||
1627 | rc = cap_task_setscheduler(p); | 1574 | rc = cap_task_setscheduler(p); |
1628 | if (rc == 0) | 1575 | if (rc == 0) |
1629 | rc = smk_curacc_on_task(p, MAY_WRITE, __func__); | 1576 | rc = smk_curacc_on_task(p, MAY_WRITE); |
1630 | return rc; | 1577 | return rc; |
1631 | } | 1578 | } |
1632 | 1579 | ||
@@ -1638,7 +1585,7 @@ static int smack_task_setscheduler(struct task_struct *p) | |||
1638 | */ | 1585 | */ |
1639 | static int smack_task_getscheduler(struct task_struct *p) | 1586 | static int smack_task_getscheduler(struct task_struct *p) |
1640 | { | 1587 | { |
1641 | return smk_curacc_on_task(p, MAY_READ, __func__); | 1588 | return smk_curacc_on_task(p, MAY_READ); |
1642 | } | 1589 | } |
1643 | 1590 | ||
1644 | /** | 1591 | /** |
@@ -1649,7 +1596,7 @@ static int smack_task_getscheduler(struct task_struct *p) | |||
1649 | */ | 1596 | */ |
1650 | static int smack_task_movememory(struct task_struct *p) | 1597 | static int smack_task_movememory(struct task_struct *p) |
1651 | { | 1598 | { |
1652 | return smk_curacc_on_task(p, MAY_WRITE, __func__); | 1599 | return smk_curacc_on_task(p, MAY_WRITE); |
1653 | } | 1600 | } |
1654 | 1601 | ||
1655 | /** | 1602 | /** |
@@ -1691,19 +1638,39 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, | |||
1691 | * smack_task_wait - Smack access check for waiting | 1638 | * smack_task_wait - Smack access check for waiting |
1692 | * @p: task to wait for | 1639 | * @p: task to wait for |
1693 | * | 1640 | * |
1694 | * Returns 0 | 1641 | * Returns 0 if current can wait for p, error code otherwise |
1695 | */ | 1642 | */ |
1696 | static int smack_task_wait(struct task_struct *p) | 1643 | static int smack_task_wait(struct task_struct *p) |
1697 | { | 1644 | { |
1645 | struct smk_audit_info ad; | ||
1646 | char *sp = smk_of_current(); | ||
1647 | char *tsp = smk_of_forked(task_security(p)); | ||
1648 | int rc; | ||
1649 | |||
1650 | /* we don't log here, we can be overriden */ | ||
1651 | rc = smk_access(tsp, sp, MAY_WRITE, NULL); | ||
1652 | if (rc == 0) | ||
1653 | goto out_log; | ||
1654 | |||
1698 | /* | 1655 | /* |
1699 | * Allow the operation to succeed. | 1656 | * Allow the operation to succeed if either task |
1700 | * Zombies are bad. | 1657 | * has privilege to perform operations that might |
1701 | * In userless environments (e.g. phones) programs | 1658 | * account for the smack labels having gotten to |
1702 | * get marked with SMACK64EXEC and even if the parent | 1659 | * be different in the first place. |
1703 | * and child shouldn't be talking the parent still | 1660 | * |
1704 | * may expect to know when the child exits. | 1661 | * This breaks the strict subject/object access |
1662 | * control ideal, taking the object's privilege | ||
1663 | * state into account in the decision as well as | ||
1664 | * the smack value. | ||
1705 | */ | 1665 | */ |
1706 | return 0; | 1666 | if (capable(CAP_MAC_OVERRIDE) || has_capability(p, CAP_MAC_OVERRIDE)) |
1667 | rc = 0; | ||
1668 | /* we log only if we didn't get overriden */ | ||
1669 | out_log: | ||
1670 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | ||
1671 | smk_ad_setfield_u_tsk(&ad, p); | ||
1672 | smack_log(tsp, sp, MAY_WRITE, rc, &ad); | ||
1673 | return rc; | ||
1707 | } | 1674 | } |
1708 | 1675 | ||
1709 | /** | 1676 | /** |
@@ -1744,7 +1711,7 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) | |||
1744 | 1711 | ||
1745 | ssp->smk_in = csp; | 1712 | ssp->smk_in = csp; |
1746 | ssp->smk_out = csp; | 1713 | ssp->smk_out = csp; |
1747 | ssp->smk_packet = NULL; | 1714 | ssp->smk_packet[0] = '\0'; |
1748 | 1715 | ||
1749 | sk->sk_security = ssp; | 1716 | sk->sk_security = ssp; |
1750 | 1717 | ||
@@ -1800,6 +1767,65 @@ static char *smack_host_label(struct sockaddr_in *sip) | |||
1800 | } | 1767 | } |
1801 | 1768 | ||
1802 | /** | 1769 | /** |
1770 | * smack_set_catset - convert a capset to netlabel mls categories | ||
1771 | * @catset: the Smack categories | ||
1772 | * @sap: where to put the netlabel categories | ||
1773 | * | ||
1774 | * Allocates and fills attr.mls.cat | ||
1775 | */ | ||
1776 | static void smack_set_catset(char *catset, struct netlbl_lsm_secattr *sap) | ||
1777 | { | ||
1778 | unsigned char *cp; | ||
1779 | unsigned char m; | ||
1780 | int cat; | ||
1781 | int rc; | ||
1782 | int byte; | ||
1783 | |||
1784 | if (!catset) | ||
1785 | return; | ||
1786 | |||
1787 | sap->flags |= NETLBL_SECATTR_MLS_CAT; | ||
1788 | sap->attr.mls.cat = netlbl_secattr_catmap_alloc(GFP_ATOMIC); | ||
1789 | sap->attr.mls.cat->startbit = 0; | ||
1790 | |||
1791 | for (cat = 1, cp = catset, byte = 0; byte < SMK_LABELLEN; cp++, byte++) | ||
1792 | for (m = 0x80; m != 0; m >>= 1, cat++) { | ||
1793 | if ((m & *cp) == 0) | ||
1794 | continue; | ||
1795 | rc = netlbl_secattr_catmap_setbit(sap->attr.mls.cat, | ||
1796 | cat, GFP_ATOMIC); | ||
1797 | } | ||
1798 | } | ||
1799 | |||
1800 | /** | ||
1801 | * smack_to_secattr - fill a secattr from a smack value | ||
1802 | * @smack: the smack value | ||
1803 | * @nlsp: where the result goes | ||
1804 | * | ||
1805 | * Casey says that CIPSO is good enough for now. | ||
1806 | * It can be used to effect. | ||
1807 | * It can also be abused to effect when necessary. | ||
1808 | * Apologies to the TSIG group in general and GW in particular. | ||
1809 | */ | ||
1810 | static void smack_to_secattr(char *smack, struct netlbl_lsm_secattr *nlsp) | ||
1811 | { | ||
1812 | struct smack_cipso cipso; | ||
1813 | int rc; | ||
1814 | |||
1815 | nlsp->domain = smack; | ||
1816 | nlsp->flags = NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL; | ||
1817 | |||
1818 | rc = smack_to_cipso(smack, &cipso); | ||
1819 | if (rc == 0) { | ||
1820 | nlsp->attr.mls.lvl = cipso.smk_level; | ||
1821 | smack_set_catset(cipso.smk_catset, nlsp); | ||
1822 | } else { | ||
1823 | nlsp->attr.mls.lvl = smack_cipso_direct; | ||
1824 | smack_set_catset(smack, nlsp); | ||
1825 | } | ||
1826 | } | ||
1827 | |||
1828 | /** | ||
1803 | * smack_netlabel - Set the secattr on a socket | 1829 | * smack_netlabel - Set the secattr on a socket |
1804 | * @sk: the socket | 1830 | * @sk: the socket |
1805 | * @labeled: socket label scheme | 1831 | * @labeled: socket label scheme |
@@ -1811,8 +1837,8 @@ static char *smack_host_label(struct sockaddr_in *sip) | |||
1811 | */ | 1837 | */ |
1812 | static int smack_netlabel(struct sock *sk, int labeled) | 1838 | static int smack_netlabel(struct sock *sk, int labeled) |
1813 | { | 1839 | { |
1814 | struct smack_known *skp; | ||
1815 | struct socket_smack *ssp = sk->sk_security; | 1840 | struct socket_smack *ssp = sk->sk_security; |
1841 | struct netlbl_lsm_secattr secattr; | ||
1816 | int rc = 0; | 1842 | int rc = 0; |
1817 | 1843 | ||
1818 | /* | 1844 | /* |
@@ -1830,8 +1856,10 @@ static int smack_netlabel(struct sock *sk, int labeled) | |||
1830 | labeled == SMACK_UNLABELED_SOCKET) | 1856 | labeled == SMACK_UNLABELED_SOCKET) |
1831 | netlbl_sock_delattr(sk); | 1857 | netlbl_sock_delattr(sk); |
1832 | else { | 1858 | else { |
1833 | skp = smk_find_entry(ssp->smk_out); | 1859 | netlbl_secattr_init(&secattr); |
1834 | rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel); | 1860 | smack_to_secattr(ssp->smk_out, &secattr); |
1861 | rc = netlbl_sock_setattr(sk, sk->sk_family, &secattr); | ||
1862 | netlbl_secattr_destroy(&secattr); | ||
1835 | } | 1863 | } |
1836 | 1864 | ||
1837 | bh_unlock_sock(sk); | 1865 | bh_unlock_sock(sk); |
@@ -1862,15 +1890,13 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) | |||
1862 | rcu_read_lock(); | 1890 | rcu_read_lock(); |
1863 | hostsp = smack_host_label(sap); | 1891 | hostsp = smack_host_label(sap); |
1864 | if (hostsp != NULL) { | 1892 | if (hostsp != NULL) { |
1893 | sk_lbl = SMACK_UNLABELED_SOCKET; | ||
1865 | #ifdef CONFIG_AUDIT | 1894 | #ifdef CONFIG_AUDIT |
1866 | struct lsm_network_audit net; | 1895 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); |
1867 | 1896 | ad.a.u.net.family = sap->sin_family; | |
1868 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); | 1897 | ad.a.u.net.dport = sap->sin_port; |
1869 | ad.a.u.net->family = sap->sin_family; | 1898 | ad.a.u.net.v4info.daddr = sap->sin_addr.s_addr; |
1870 | ad.a.u.net->dport = sap->sin_port; | ||
1871 | ad.a.u.net->v4info.daddr = sap->sin_addr.s_addr; | ||
1872 | #endif | 1899 | #endif |
1873 | sk_lbl = SMACK_UNLABELED_SOCKET; | ||
1874 | rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE, &ad); | 1900 | rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE, &ad); |
1875 | } else { | 1901 | } else { |
1876 | sk_lbl = SMACK_CIPSO_SOCKET; | 1902 | sk_lbl = SMACK_CIPSO_SOCKET; |
@@ -1904,7 +1930,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, | |||
1904 | struct socket *sock; | 1930 | struct socket *sock; |
1905 | int rc = 0; | 1931 | int rc = 0; |
1906 | 1932 | ||
1907 | if (value == NULL || size > SMK_LONGLABEL || size == 0) | 1933 | if (value == NULL || size > SMK_LABELLEN || size == 0) |
1908 | return -EACCES; | 1934 | return -EACCES; |
1909 | 1935 | ||
1910 | sp = smk_import(value, size); | 1936 | sp = smk_import(value, size); |
@@ -2471,7 +2497,6 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2471 | char *final; | 2497 | char *final; |
2472 | char trattr[TRANS_TRUE_SIZE]; | 2498 | char trattr[TRANS_TRUE_SIZE]; |
2473 | int transflag = 0; | 2499 | int transflag = 0; |
2474 | int rc; | ||
2475 | struct dentry *dp; | 2500 | struct dentry *dp; |
2476 | 2501 | ||
2477 | if (inode == NULL) | 2502 | if (inode == NULL) |
@@ -2590,38 +2615,17 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2590 | */ | 2615 | */ |
2591 | dp = dget(opt_dentry); | 2616 | dp = dget(opt_dentry); |
2592 | fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp); | 2617 | fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp); |
2593 | if (fetched != NULL) | 2618 | if (fetched != NULL) { |
2594 | final = fetched; | 2619 | final = fetched; |
2595 | 2620 | if (S_ISDIR(inode->i_mode)) { | |
2596 | /* | 2621 | trattr[0] = '\0'; |
2597 | * Transmuting directory | 2622 | inode->i_op->getxattr(dp, |
2598 | */ | ||
2599 | if (S_ISDIR(inode->i_mode)) { | ||
2600 | /* | ||
2601 | * If this is a new directory and the label was | ||
2602 | * transmuted when the inode was initialized | ||
2603 | * set the transmute attribute on the directory | ||
2604 | * and mark the inode. | ||
2605 | * | ||
2606 | * If there is a transmute attribute on the | ||
2607 | * directory mark the inode. | ||
2608 | */ | ||
2609 | if (isp->smk_flags & SMK_INODE_CHANGED) { | ||
2610 | isp->smk_flags &= ~SMK_INODE_CHANGED; | ||
2611 | rc = inode->i_op->setxattr(dp, | ||
2612 | XATTR_NAME_SMACKTRANSMUTE, | 2623 | XATTR_NAME_SMACKTRANSMUTE, |
2613 | TRANS_TRUE, TRANS_TRUE_SIZE, | 2624 | trattr, TRANS_TRUE_SIZE); |
2614 | 0); | 2625 | if (strncmp(trattr, TRANS_TRUE, |
2615 | } else { | 2626 | TRANS_TRUE_SIZE) == 0) |
2616 | rc = inode->i_op->getxattr(dp, | 2627 | transflag = SMK_INODE_TRANSMUTE; |
2617 | XATTR_NAME_SMACKTRANSMUTE, trattr, | ||
2618 | TRANS_TRUE_SIZE); | ||
2619 | if (rc >= 0 && strncmp(trattr, TRANS_TRUE, | ||
2620 | TRANS_TRUE_SIZE) != 0) | ||
2621 | rc = -EINVAL; | ||
2622 | } | 2628 | } |
2623 | if (rc >= 0) | ||
2624 | transflag = SMK_INODE_TRANSMUTE; | ||
2625 | } | 2629 | } |
2626 | isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); | 2630 | isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); |
2627 | isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp); | 2631 | isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp); |
@@ -2684,7 +2688,9 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value) | |||
2684 | static int smack_setprocattr(struct task_struct *p, char *name, | 2688 | static int smack_setprocattr(struct task_struct *p, char *name, |
2685 | void *value, size_t size) | 2689 | void *value, size_t size) |
2686 | { | 2690 | { |
2691 | int rc; | ||
2687 | struct task_smack *tsp; | 2692 | struct task_smack *tsp; |
2693 | struct task_smack *oldtsp; | ||
2688 | struct cred *new; | 2694 | struct cred *new; |
2689 | char *newsmack; | 2695 | char *newsmack; |
2690 | 2696 | ||
@@ -2695,10 +2701,10 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
2695 | if (p != current) | 2701 | if (p != current) |
2696 | return -EPERM; | 2702 | return -EPERM; |
2697 | 2703 | ||
2698 | if (!smack_privileged(CAP_MAC_ADMIN)) | 2704 | if (!capable(CAP_MAC_ADMIN)) |
2699 | return -EPERM; | 2705 | return -EPERM; |
2700 | 2706 | ||
2701 | if (value == NULL || size == 0 || size >= SMK_LONGLABEL) | 2707 | if (value == NULL || size == 0 || size >= SMK_LABELLEN) |
2702 | return -EINVAL; | 2708 | return -EINVAL; |
2703 | 2709 | ||
2704 | if (strcmp(name, "current") != 0) | 2710 | if (strcmp(name, "current") != 0) |
@@ -2714,13 +2720,21 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
2714 | if (newsmack == smack_known_web.smk_known) | 2720 | if (newsmack == smack_known_web.smk_known) |
2715 | return -EPERM; | 2721 | return -EPERM; |
2716 | 2722 | ||
2723 | oldtsp = p->cred->security; | ||
2717 | new = prepare_creds(); | 2724 | new = prepare_creds(); |
2718 | if (new == NULL) | 2725 | if (new == NULL) |
2719 | return -ENOMEM; | 2726 | return -ENOMEM; |
2720 | 2727 | ||
2721 | tsp = new->security; | 2728 | tsp = new_task_smack(newsmack, oldtsp->smk_forked, GFP_KERNEL); |
2722 | tsp->smk_task = newsmack; | 2729 | if (tsp == NULL) { |
2730 | kfree(new); | ||
2731 | return -ENOMEM; | ||
2732 | } | ||
2733 | rc = smk_copy_rules(&tsp->smk_rules, &oldtsp->smk_rules, GFP_KERNEL); | ||
2734 | if (rc != 0) | ||
2735 | return rc; | ||
2723 | 2736 | ||
2737 | new->security = tsp; | ||
2724 | commit_creds(new); | 2738 | commit_creds(new); |
2725 | return size; | 2739 | return size; |
2726 | } | 2740 | } |
@@ -2739,28 +2753,15 @@ static int smack_unix_stream_connect(struct sock *sock, | |||
2739 | { | 2753 | { |
2740 | struct socket_smack *ssp = sock->sk_security; | 2754 | struct socket_smack *ssp = sock->sk_security; |
2741 | struct socket_smack *osp = other->sk_security; | 2755 | struct socket_smack *osp = other->sk_security; |
2742 | struct socket_smack *nsp = newsk->sk_security; | ||
2743 | struct smk_audit_info ad; | 2756 | struct smk_audit_info ad; |
2744 | int rc = 0; | 2757 | int rc = 0; |
2745 | 2758 | ||
2746 | #ifdef CONFIG_AUDIT | 2759 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); |
2747 | struct lsm_network_audit net; | ||
2748 | |||
2749 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); | ||
2750 | smk_ad_setfield_u_net_sk(&ad, other); | 2760 | smk_ad_setfield_u_net_sk(&ad, other); |
2751 | #endif | ||
2752 | 2761 | ||
2753 | if (!smack_privileged(CAP_MAC_OVERRIDE)) | 2762 | if (!capable(CAP_MAC_OVERRIDE)) |
2754 | rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); | 2763 | rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); |
2755 | 2764 | ||
2756 | /* | ||
2757 | * Cross reference the peer labels for SO_PEERSEC. | ||
2758 | */ | ||
2759 | if (rc == 0) { | ||
2760 | nsp->smk_packet = ssp->smk_out; | ||
2761 | ssp->smk_packet = osp->smk_out; | ||
2762 | } | ||
2763 | |||
2764 | return rc; | 2765 | return rc; |
2765 | } | 2766 | } |
2766 | 2767 | ||
@@ -2779,14 +2780,10 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) | |||
2779 | struct smk_audit_info ad; | 2780 | struct smk_audit_info ad; |
2780 | int rc = 0; | 2781 | int rc = 0; |
2781 | 2782 | ||
2782 | #ifdef CONFIG_AUDIT | 2783 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); |
2783 | struct lsm_network_audit net; | ||
2784 | |||
2785 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); | ||
2786 | smk_ad_setfield_u_net_sk(&ad, other->sk); | 2784 | smk_ad_setfield_u_net_sk(&ad, other->sk); |
2787 | #endif | ||
2788 | 2785 | ||
2789 | if (!smack_privileged(CAP_MAC_OVERRIDE)) | 2786 | if (!capable(CAP_MAC_OVERRIDE)) |
2790 | rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); | 2787 | rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); |
2791 | 2788 | ||
2792 | return rc; | 2789 | return rc; |
@@ -2816,19 +2813,19 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, | |||
2816 | return smack_netlabel_send(sock->sk, sip); | 2813 | return smack_netlabel_send(sock->sk, sip); |
2817 | } | 2814 | } |
2818 | 2815 | ||
2816 | |||
2819 | /** | 2817 | /** |
2820 | * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat pair to smack | 2818 | * smack_from_secattr - Convert a netlabel attr.mls.lvl/attr.mls.cat pair to smack |
2821 | * @sap: netlabel secattr | 2819 | * @sap: netlabel secattr |
2822 | * @ssp: socket security information | 2820 | * @sip: where to put the result |
2823 | * | 2821 | * |
2824 | * Returns a pointer to a Smack label found on the label list. | 2822 | * Copies a smack label into sip |
2825 | */ | 2823 | */ |
2826 | static char *smack_from_secattr(struct netlbl_lsm_secattr *sap, | 2824 | static void smack_from_secattr(struct netlbl_lsm_secattr *sap, char *sip) |
2827 | struct socket_smack *ssp) | ||
2828 | { | 2825 | { |
2829 | struct smack_known *kp; | 2826 | char smack[SMK_LABELLEN]; |
2830 | char *sp; | 2827 | char *sp; |
2831 | int found = 0; | 2828 | int pcat; |
2832 | 2829 | ||
2833 | if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) { | 2830 | if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) { |
2834 | /* | 2831 | /* |
@@ -2836,30 +2833,34 @@ static char *smack_from_secattr(struct netlbl_lsm_secattr *sap, | |||
2836 | * If there are flags but no level netlabel isn't | 2833 | * If there are flags but no level netlabel isn't |
2837 | * behaving the way we expect it to. | 2834 | * behaving the way we expect it to. |
2838 | * | 2835 | * |
2839 | * Look it up in the label table | 2836 | * Get the categories, if any |
2840 | * Without guidance regarding the smack value | 2837 | * Without guidance regarding the smack value |
2841 | * for the packet fall back on the network | 2838 | * for the packet fall back on the network |
2842 | * ambient value. | 2839 | * ambient value. |
2843 | */ | 2840 | */ |
2844 | rcu_read_lock(); | 2841 | memset(smack, '\0', SMK_LABELLEN); |
2845 | list_for_each_entry(kp, &smack_known_list, list) { | 2842 | if ((sap->flags & NETLBL_SECATTR_MLS_CAT) != 0) |
2846 | if (sap->attr.mls.lvl != kp->smk_netlabel.attr.mls.lvl) | 2843 | for (pcat = -1;;) { |
2847 | continue; | 2844 | pcat = netlbl_secattr_catmap_walk( |
2848 | if (memcmp(sap->attr.mls.cat, | 2845 | sap->attr.mls.cat, pcat + 1); |
2849 | kp->smk_netlabel.attr.mls.cat, | 2846 | if (pcat < 0) |
2850 | SMK_CIPSOLEN) != 0) | 2847 | break; |
2851 | continue; | 2848 | smack_catset_bit(pcat, smack); |
2852 | found = 1; | 2849 | } |
2853 | break; | 2850 | /* |
2851 | * If it is CIPSO using smack direct mapping | ||
2852 | * we are already done. WeeHee. | ||
2853 | */ | ||
2854 | if (sap->attr.mls.lvl == smack_cipso_direct) { | ||
2855 | memcpy(sip, smack, SMK_MAXLEN); | ||
2856 | return; | ||
2854 | } | 2857 | } |
2855 | rcu_read_unlock(); | 2858 | /* |
2856 | 2859 | * Look it up in the supplied table if it is not | |
2857 | if (found) | 2860 | * a direct mapping. |
2858 | return kp->smk_known; | 2861 | */ |
2859 | 2862 | smack_from_cipso(sap->attr.mls.lvl, smack, sip); | |
2860 | if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known) | 2863 | return; |
2861 | return smack_known_web.smk_known; | ||
2862 | return smack_known_star.smk_known; | ||
2863 | } | 2864 | } |
2864 | if ((sap->flags & NETLBL_SECATTR_SECID) != 0) { | 2865 | if ((sap->flags & NETLBL_SECATTR_SECID) != 0) { |
2865 | /* | 2866 | /* |
@@ -2874,14 +2875,16 @@ static char *smack_from_secattr(struct netlbl_lsm_secattr *sap, | |||
2874 | * secid is from a fallback. | 2875 | * secid is from a fallback. |
2875 | */ | 2876 | */ |
2876 | BUG_ON(sp == NULL); | 2877 | BUG_ON(sp == NULL); |
2877 | return sp; | 2878 | strncpy(sip, sp, SMK_MAXLEN); |
2879 | return; | ||
2878 | } | 2880 | } |
2879 | /* | 2881 | /* |
2880 | * Without guidance regarding the smack value | 2882 | * Without guidance regarding the smack value |
2881 | * for the packet fall back on the network | 2883 | * for the packet fall back on the network |
2882 | * ambient value. | 2884 | * ambient value. |
2883 | */ | 2885 | */ |
2884 | return smack_net_ambient; | 2886 | strncpy(sip, smack_net_ambient, SMK_MAXLEN); |
2887 | return; | ||
2885 | } | 2888 | } |
2886 | 2889 | ||
2887 | /** | 2890 | /** |
@@ -2895,12 +2898,10 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
2895 | { | 2898 | { |
2896 | struct netlbl_lsm_secattr secattr; | 2899 | struct netlbl_lsm_secattr secattr; |
2897 | struct socket_smack *ssp = sk->sk_security; | 2900 | struct socket_smack *ssp = sk->sk_security; |
2901 | char smack[SMK_LABELLEN]; | ||
2898 | char *csp; | 2902 | char *csp; |
2899 | int rc; | 2903 | int rc; |
2900 | struct smk_audit_info ad; | 2904 | struct smk_audit_info ad; |
2901 | #ifdef CONFIG_AUDIT | ||
2902 | struct lsm_network_audit net; | ||
2903 | #endif | ||
2904 | if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) | 2905 | if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) |
2905 | return 0; | 2906 | return 0; |
2906 | 2907 | ||
@@ -2910,17 +2911,18 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
2910 | netlbl_secattr_init(&secattr); | 2911 | netlbl_secattr_init(&secattr); |
2911 | 2912 | ||
2912 | rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr); | 2913 | rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr); |
2913 | if (rc == 0) | 2914 | if (rc == 0) { |
2914 | csp = smack_from_secattr(&secattr, ssp); | 2915 | smack_from_secattr(&secattr, smack); |
2915 | else | 2916 | csp = smack; |
2917 | } else | ||
2916 | csp = smack_net_ambient; | 2918 | csp = smack_net_ambient; |
2917 | 2919 | ||
2918 | netlbl_secattr_destroy(&secattr); | 2920 | netlbl_secattr_destroy(&secattr); |
2919 | 2921 | ||
2920 | #ifdef CONFIG_AUDIT | 2922 | #ifdef CONFIG_AUDIT |
2921 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); | 2923 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); |
2922 | ad.a.u.net->family = sk->sk_family; | 2924 | ad.a.u.net.family = sk->sk_family; |
2923 | ad.a.u.net->netif = skb->skb_iif; | 2925 | ad.a.u.net.netif = skb->skb_iif; |
2924 | ipv4_skb_to_auditdata(skb, &ad.a, NULL); | 2926 | ipv4_skb_to_auditdata(skb, &ad.a, NULL); |
2925 | #endif | 2927 | #endif |
2926 | /* | 2928 | /* |
@@ -2949,19 +2951,15 @@ static int smack_socket_getpeersec_stream(struct socket *sock, | |||
2949 | int __user *optlen, unsigned len) | 2951 | int __user *optlen, unsigned len) |
2950 | { | 2952 | { |
2951 | struct socket_smack *ssp; | 2953 | struct socket_smack *ssp; |
2952 | char *rcp = ""; | 2954 | int slen; |
2953 | int slen = 1; | ||
2954 | int rc = 0; | 2955 | int rc = 0; |
2955 | 2956 | ||
2956 | ssp = sock->sk->sk_security; | 2957 | ssp = sock->sk->sk_security; |
2957 | if (ssp->smk_packet != NULL) { | 2958 | slen = strlen(ssp->smk_packet) + 1; |
2958 | rcp = ssp->smk_packet; | ||
2959 | slen = strlen(rcp) + 1; | ||
2960 | } | ||
2961 | 2959 | ||
2962 | if (slen > len) | 2960 | if (slen > len) |
2963 | rc = -ERANGE; | 2961 | rc = -ERANGE; |
2964 | else if (copy_to_user(optval, rcp, slen) != 0) | 2962 | else if (copy_to_user(optval, ssp->smk_packet, slen) != 0) |
2965 | rc = -EFAULT; | 2963 | rc = -EFAULT; |
2966 | 2964 | ||
2967 | if (put_user(slen, optlen) != 0) | 2965 | if (put_user(slen, optlen) != 0) |
@@ -2984,8 +2982,8 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, | |||
2984 | 2982 | ||
2985 | { | 2983 | { |
2986 | struct netlbl_lsm_secattr secattr; | 2984 | struct netlbl_lsm_secattr secattr; |
2987 | struct socket_smack *ssp = NULL; | 2985 | struct socket_smack *sp; |
2988 | char *sp; | 2986 | char smack[SMK_LABELLEN]; |
2989 | int family = PF_UNSPEC; | 2987 | int family = PF_UNSPEC; |
2990 | u32 s = 0; /* 0 is the invalid secid */ | 2988 | u32 s = 0; /* 0 is the invalid secid */ |
2991 | int rc; | 2989 | int rc; |
@@ -3000,19 +2998,17 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, | |||
3000 | family = sock->sk->sk_family; | 2998 | family = sock->sk->sk_family; |
3001 | 2999 | ||
3002 | if (family == PF_UNIX) { | 3000 | if (family == PF_UNIX) { |
3003 | ssp = sock->sk->sk_security; | 3001 | sp = sock->sk->sk_security; |
3004 | s = smack_to_secid(ssp->smk_out); | 3002 | s = smack_to_secid(sp->smk_out); |
3005 | } else if (family == PF_INET || family == PF_INET6) { | 3003 | } else if (family == PF_INET || family == PF_INET6) { |
3006 | /* | 3004 | /* |
3007 | * Translate what netlabel gave us. | 3005 | * Translate what netlabel gave us. |
3008 | */ | 3006 | */ |
3009 | if (sock != NULL && sock->sk != NULL) | ||
3010 | ssp = sock->sk->sk_security; | ||
3011 | netlbl_secattr_init(&secattr); | 3007 | netlbl_secattr_init(&secattr); |
3012 | rc = netlbl_skbuff_getattr(skb, family, &secattr); | 3008 | rc = netlbl_skbuff_getattr(skb, family, &secattr); |
3013 | if (rc == 0) { | 3009 | if (rc == 0) { |
3014 | sp = smack_from_secattr(&secattr, ssp); | 3010 | smack_from_secattr(&secattr, smack); |
3015 | s = smack_to_secid(sp); | 3011 | s = smack_to_secid(smack); |
3016 | } | 3012 | } |
3017 | netlbl_secattr_destroy(&secattr); | 3013 | netlbl_secattr_destroy(&secattr); |
3018 | } | 3014 | } |
@@ -3056,18 +3052,13 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3056 | struct request_sock *req) | 3052 | struct request_sock *req) |
3057 | { | 3053 | { |
3058 | u16 family = sk->sk_family; | 3054 | u16 family = sk->sk_family; |
3059 | struct smack_known *skp; | ||
3060 | struct socket_smack *ssp = sk->sk_security; | 3055 | struct socket_smack *ssp = sk->sk_security; |
3061 | struct netlbl_lsm_secattr secattr; | 3056 | struct netlbl_lsm_secattr secattr; |
3062 | struct sockaddr_in addr; | 3057 | struct sockaddr_in addr; |
3063 | struct iphdr *hdr; | 3058 | struct iphdr *hdr; |
3064 | char *sp; | 3059 | char smack[SMK_LABELLEN]; |
3065 | char *hsp; | ||
3066 | int rc; | 3060 | int rc; |
3067 | struct smk_audit_info ad; | 3061 | struct smk_audit_info ad; |
3068 | #ifdef CONFIG_AUDIT | ||
3069 | struct lsm_network_audit net; | ||
3070 | #endif | ||
3071 | 3062 | ||
3072 | /* handle mapped IPv4 packets arriving via IPv6 sockets */ | 3063 | /* handle mapped IPv4 packets arriving via IPv6 sockets */ |
3073 | if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) | 3064 | if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) |
@@ -3076,22 +3067,22 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3076 | netlbl_secattr_init(&secattr); | 3067 | netlbl_secattr_init(&secattr); |
3077 | rc = netlbl_skbuff_getattr(skb, family, &secattr); | 3068 | rc = netlbl_skbuff_getattr(skb, family, &secattr); |
3078 | if (rc == 0) | 3069 | if (rc == 0) |
3079 | sp = smack_from_secattr(&secattr, ssp); | 3070 | smack_from_secattr(&secattr, smack); |
3080 | else | 3071 | else |
3081 | sp = smack_known_huh.smk_known; | 3072 | strncpy(smack, smack_known_huh.smk_known, SMK_MAXLEN); |
3082 | netlbl_secattr_destroy(&secattr); | 3073 | netlbl_secattr_destroy(&secattr); |
3083 | 3074 | ||
3084 | #ifdef CONFIG_AUDIT | 3075 | #ifdef CONFIG_AUDIT |
3085 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); | 3076 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NET); |
3086 | ad.a.u.net->family = family; | 3077 | ad.a.u.net.family = family; |
3087 | ad.a.u.net->netif = skb->skb_iif; | 3078 | ad.a.u.net.netif = skb->skb_iif; |
3088 | ipv4_skb_to_auditdata(skb, &ad.a, NULL); | 3079 | ipv4_skb_to_auditdata(skb, &ad.a, NULL); |
3089 | #endif | 3080 | #endif |
3090 | /* | 3081 | /* |
3091 | * Receiving a packet requires that the other end be able to write | 3082 | * Receiving a packet requires that the other end be able to write |
3092 | * here. Read access is not required. | 3083 | * here. Read access is not required. |
3093 | */ | 3084 | */ |
3094 | rc = smk_access(sp, ssp->smk_in, MAY_WRITE, &ad); | 3085 | rc = smk_access(smack, ssp->smk_in, MAY_WRITE, &ad); |
3095 | if (rc != 0) | 3086 | if (rc != 0) |
3096 | return rc; | 3087 | return rc; |
3097 | 3088 | ||
@@ -3099,7 +3090,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3099 | * Save the peer's label in the request_sock so we can later setup | 3090 | * Save the peer's label in the request_sock so we can later setup |
3100 | * smk_packet in the child socket so that SO_PEERCRED can report it. | 3091 | * smk_packet in the child socket so that SO_PEERCRED can report it. |
3101 | */ | 3092 | */ |
3102 | req->peer_secid = smack_to_secid(sp); | 3093 | req->peer_secid = smack_to_secid(smack); |
3103 | 3094 | ||
3104 | /* | 3095 | /* |
3105 | * We need to decide if we want to label the incoming connection here | 3096 | * We need to decide if we want to label the incoming connection here |
@@ -3109,14 +3100,16 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3109 | hdr = ip_hdr(skb); | 3100 | hdr = ip_hdr(skb); |
3110 | addr.sin_addr.s_addr = hdr->saddr; | 3101 | addr.sin_addr.s_addr = hdr->saddr; |
3111 | rcu_read_lock(); | 3102 | rcu_read_lock(); |
3112 | hsp = smack_host_label(&addr); | 3103 | if (smack_host_label(&addr) == NULL) { |
3113 | rcu_read_unlock(); | 3104 | rcu_read_unlock(); |
3114 | 3105 | netlbl_secattr_init(&secattr); | |
3115 | if (hsp == NULL) { | 3106 | smack_to_secattr(smack, &secattr); |
3116 | skp = smk_find_entry(sp); | 3107 | rc = netlbl_req_setattr(req, &secattr); |
3117 | rc = netlbl_req_setattr(req, &skp->smk_netlabel); | 3108 | netlbl_secattr_destroy(&secattr); |
3118 | } else | 3109 | } else { |
3110 | rcu_read_unlock(); | ||
3119 | netlbl_req_delattr(req); | 3111 | netlbl_req_delattr(req); |
3112 | } | ||
3120 | 3113 | ||
3121 | return rc; | 3114 | return rc; |
3122 | } | 3115 | } |
@@ -3132,11 +3125,13 @@ static void smack_inet_csk_clone(struct sock *sk, | |||
3132 | const struct request_sock *req) | 3125 | const struct request_sock *req) |
3133 | { | 3126 | { |
3134 | struct socket_smack *ssp = sk->sk_security; | 3127 | struct socket_smack *ssp = sk->sk_security; |
3128 | char *smack; | ||
3135 | 3129 | ||
3136 | if (req->peer_secid != 0) | 3130 | if (req->peer_secid != 0) { |
3137 | ssp->smk_packet = smack_from_secid(req->peer_secid); | 3131 | smack = smack_from_secid(req->peer_secid); |
3138 | else | 3132 | strncpy(ssp->smk_packet, smack, SMK_MAXLEN); |
3139 | ssp->smk_packet = NULL; | 3133 | } else |
3134 | ssp->smk_packet[0] = '\0'; | ||
3140 | } | 3135 | } |
3141 | 3136 | ||
3142 | /* | 3137 | /* |
@@ -3298,7 +3293,7 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule, | |||
3298 | char *rule = vrule; | 3293 | char *rule = vrule; |
3299 | 3294 | ||
3300 | if (!rule) { | 3295 | if (!rule) { |
3301 | audit_log(actx, GFP_ATOMIC, AUDIT_SELINUX_ERR, | 3296 | audit_log(actx, GFP_KERNEL, AUDIT_SELINUX_ERR, |
3302 | "Smack: missing rule\n"); | 3297 | "Smack: missing rule\n"); |
3303 | return -ENOENT; | 3298 | return -ENOENT; |
3304 | } | 3299 | } |
@@ -3414,8 +3409,6 @@ struct security_operations smack_ops = { | |||
3414 | .sb_umount = smack_sb_umount, | 3409 | .sb_umount = smack_sb_umount, |
3415 | 3410 | ||
3416 | .bprm_set_creds = smack_bprm_set_creds, | 3411 | .bprm_set_creds = smack_bprm_set_creds, |
3417 | .bprm_committing_creds = smack_bprm_committing_creds, | ||
3418 | .bprm_secureexec = smack_bprm_secureexec, | ||
3419 | 3412 | ||
3420 | .inode_alloc_security = smack_inode_alloc_security, | 3413 | .inode_alloc_security = smack_inode_alloc_security, |
3421 | .inode_free_security = smack_inode_free_security, | 3414 | .inode_free_security = smack_inode_free_security, |
@@ -3442,14 +3435,11 @@ struct security_operations smack_ops = { | |||
3442 | .file_ioctl = smack_file_ioctl, | 3435 | .file_ioctl = smack_file_ioctl, |
3443 | .file_lock = smack_file_lock, | 3436 | .file_lock = smack_file_lock, |
3444 | .file_fcntl = smack_file_fcntl, | 3437 | .file_fcntl = smack_file_fcntl, |
3445 | .mmap_file = smack_mmap_file, | 3438 | .file_mmap = smack_file_mmap, |
3446 | .mmap_addr = cap_mmap_addr, | ||
3447 | .file_set_fowner = smack_file_set_fowner, | 3439 | .file_set_fowner = smack_file_set_fowner, |
3448 | .file_send_sigiotask = smack_file_send_sigiotask, | 3440 | .file_send_sigiotask = smack_file_send_sigiotask, |
3449 | .file_receive = smack_file_receive, | 3441 | .file_receive = smack_file_receive, |
3450 | 3442 | ||
3451 | .file_open = smack_file_open, | ||
3452 | |||
3453 | .cred_alloc_blank = smack_cred_alloc_blank, | 3443 | .cred_alloc_blank = smack_cred_alloc_blank, |
3454 | .cred_free = smack_cred_free, | 3444 | .cred_free = smack_cred_free, |
3455 | .cred_prepare = smack_cred_prepare, | 3445 | .cred_prepare = smack_cred_prepare, |
@@ -3539,29 +3529,8 @@ struct security_operations smack_ops = { | |||
3539 | }; | 3529 | }; |
3540 | 3530 | ||
3541 | 3531 | ||
3542 | static __init void init_smack_known_list(void) | 3532 | static __init void init_smack_know_list(void) |
3543 | { | 3533 | { |
3544 | /* | ||
3545 | * Initialize rule list locks | ||
3546 | */ | ||
3547 | mutex_init(&smack_known_huh.smk_rules_lock); | ||
3548 | mutex_init(&smack_known_hat.smk_rules_lock); | ||
3549 | mutex_init(&smack_known_floor.smk_rules_lock); | ||
3550 | mutex_init(&smack_known_star.smk_rules_lock); | ||
3551 | mutex_init(&smack_known_invalid.smk_rules_lock); | ||
3552 | mutex_init(&smack_known_web.smk_rules_lock); | ||
3553 | /* | ||
3554 | * Initialize rule lists | ||
3555 | */ | ||
3556 | INIT_LIST_HEAD(&smack_known_huh.smk_rules); | ||
3557 | INIT_LIST_HEAD(&smack_known_hat.smk_rules); | ||
3558 | INIT_LIST_HEAD(&smack_known_star.smk_rules); | ||
3559 | INIT_LIST_HEAD(&smack_known_floor.smk_rules); | ||
3560 | INIT_LIST_HEAD(&smack_known_invalid.smk_rules); | ||
3561 | INIT_LIST_HEAD(&smack_known_web.smk_rules); | ||
3562 | /* | ||
3563 | * Create the known labels list | ||
3564 | */ | ||
3565 | list_add(&smack_known_huh.list, &smack_known_list); | 3534 | list_add(&smack_known_huh.list, &smack_known_list); |
3566 | list_add(&smack_known_hat.list, &smack_known_list); | 3535 | list_add(&smack_known_hat.list, &smack_known_list); |
3567 | list_add(&smack_known_star.list, &smack_known_list); | 3536 | list_add(&smack_known_star.list, &smack_known_list); |
@@ -3596,8 +3565,16 @@ static __init int smack_init(void) | |||
3596 | cred = (struct cred *) current->cred; | 3565 | cred = (struct cred *) current->cred; |
3597 | cred->security = tsp; | 3566 | cred->security = tsp; |
3598 | 3567 | ||
3599 | /* initialize the smack_known_list */ | 3568 | /* initialize the smack_know_list */ |
3600 | init_smack_known_list(); | 3569 | init_smack_know_list(); |
3570 | /* | ||
3571 | * Initialize locks | ||
3572 | */ | ||
3573 | spin_lock_init(&smack_known_huh.smk_cipsolock); | ||
3574 | spin_lock_init(&smack_known_hat.smk_cipsolock); | ||
3575 | spin_lock_init(&smack_known_star.smk_cipsolock); | ||
3576 | spin_lock_init(&smack_known_floor.smk_cipsolock); | ||
3577 | spin_lock_init(&smack_known_invalid.smk_cipsolock); | ||
3601 | 3578 | ||
3602 | /* | 3579 | /* |
3603 | * Register with LSM | 3580 | * Register with LSM |
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index 76a5dca4640..f93460156dc 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <net/net_namespace.h> | 24 | #include <net/net_namespace.h> |
25 | #include <net/netlabel.h> | ||
25 | #include <net/cipso_ipv4.h> | 26 | #include <net/cipso_ipv4.h> |
26 | #include <linux/seq_file.h> | 27 | #include <linux/seq_file.h> |
27 | #include <linux/ctype.h> | 28 | #include <linux/ctype.h> |
@@ -43,13 +44,6 @@ enum smk_inos { | |||
43 | SMK_ONLYCAP = 9, /* the only "capable" label */ | 44 | SMK_ONLYCAP = 9, /* the only "capable" label */ |
44 | SMK_LOGGING = 10, /* logging */ | 45 | SMK_LOGGING = 10, /* logging */ |
45 | SMK_LOAD_SELF = 11, /* task specific rules */ | 46 | SMK_LOAD_SELF = 11, /* task specific rules */ |
46 | SMK_ACCESSES = 12, /* access policy */ | ||
47 | SMK_MAPPED = 13, /* CIPSO level indicating mapped label */ | ||
48 | SMK_LOAD2 = 14, /* load policy with long labels */ | ||
49 | SMK_LOAD_SELF2 = 15, /* load task specific rules with long labels */ | ||
50 | SMK_ACCESS2 = 16, /* make an access check with long labels */ | ||
51 | SMK_CIPSO2 = 17, /* load long label -> CIPSO mapping */ | ||
52 | SMK_REVOKE_SUBJ = 18, /* set rules with subject label to '-' */ | ||
53 | }; | 47 | }; |
54 | 48 | ||
55 | /* | 49 | /* |
@@ -65,7 +59,7 @@ static DEFINE_MUTEX(smk_netlbladdr_lock); | |||
65 | * If it isn't somehow marked, use this. | 59 | * If it isn't somehow marked, use this. |
66 | * It can be reset via smackfs/ambient | 60 | * It can be reset via smackfs/ambient |
67 | */ | 61 | */ |
68 | char *smack_net_ambient; | 62 | char *smack_net_ambient = smack_known_floor.smk_known; |
69 | 63 | ||
70 | /* | 64 | /* |
71 | * This is the level in a CIPSO header that indicates a | 65 | * This is the level in a CIPSO header that indicates a |
@@ -75,13 +69,6 @@ char *smack_net_ambient; | |||
75 | int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT; | 69 | int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT; |
76 | 70 | ||
77 | /* | 71 | /* |
78 | * This is the level in a CIPSO header that indicates a | ||
79 | * secid is contained directly in the category set. | ||
80 | * It can be reset via smackfs/mapped | ||
81 | */ | ||
82 | int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT; | ||
83 | |||
84 | /* | ||
85 | * Unless a process is running with this label even | 72 | * Unless a process is running with this label even |
86 | * having CAP_MAC_OVERRIDE isn't enough to grant | 73 | * having CAP_MAC_OVERRIDE isn't enough to grant |
87 | * privilege to violate MAC policy. If no label is | 74 | * privilege to violate MAC policy. If no label is |
@@ -98,22 +85,15 @@ char *smack_onlycap; | |||
98 | */ | 85 | */ |
99 | 86 | ||
100 | LIST_HEAD(smk_netlbladdr_list); | 87 | LIST_HEAD(smk_netlbladdr_list); |
101 | |||
102 | /* | ||
103 | * Rule lists are maintained for each label. | ||
104 | * This master list is just for reading /smack/load and /smack/load2. | ||
105 | */ | ||
106 | struct smack_master_list { | ||
107 | struct list_head list; | ||
108 | struct smack_rule *smk_rule; | ||
109 | }; | ||
110 | |||
111 | LIST_HEAD(smack_rule_list); | 88 | LIST_HEAD(smack_rule_list); |
112 | 89 | ||
113 | static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; | 90 | static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT; |
114 | 91 | ||
115 | const char *smack_cipso_option = SMACK_CIPSO_OPTION; | 92 | const char *smack_cipso_option = SMACK_CIPSO_OPTION; |
116 | 93 | ||
94 | |||
95 | #define SEQ_READ_FINISHED 1 | ||
96 | |||
117 | /* | 97 | /* |
118 | * Values for parsing cipso rules | 98 | * Values for parsing cipso rules |
119 | * SMK_DIGITLEN: Length of a digit field in a rule. | 99 | * SMK_DIGITLEN: Length of a digit field in a rule. |
@@ -137,18 +117,6 @@ const char *smack_cipso_option = SMACK_CIPSO_OPTION; | |||
137 | #define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN) | 117 | #define SMK_OLOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_OACCESSLEN) |
138 | #define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN) | 118 | #define SMK_LOADLEN (SMK_LABELLEN + SMK_LABELLEN + SMK_ACCESSLEN) |
139 | 119 | ||
140 | /* | ||
141 | * Stricly for CIPSO level manipulation. | ||
142 | * Set the category bit number in a smack label sized buffer. | ||
143 | */ | ||
144 | static inline void smack_catset_bit(unsigned int cat, char *catsetp) | ||
145 | { | ||
146 | if (cat == 0 || cat > (SMK_CIPSOLEN * 8)) | ||
147 | return; | ||
148 | |||
149 | catsetp[(cat - 1) / 8] |= 0x80 >> ((cat - 1) % 8); | ||
150 | } | ||
151 | |||
152 | /** | 120 | /** |
153 | * smk_netlabel_audit_set - fill a netlbl_audit struct | 121 | * smk_netlabel_audit_set - fill a netlbl_audit struct |
154 | * @nap: structure to fill | 122 | * @nap: structure to fill |
@@ -161,10 +129,12 @@ static void smk_netlabel_audit_set(struct netlbl_audit *nap) | |||
161 | } | 129 | } |
162 | 130 | ||
163 | /* | 131 | /* |
164 | * Value for parsing single label host rules | 132 | * Values for parsing single label host rules |
165 | * "1.2.3.4 X" | 133 | * "1.2.3.4 X" |
134 | * "192.168.138.129/32 abcdefghijklmnopqrstuvw" | ||
166 | */ | 135 | */ |
167 | #define SMK_NETLBLADDRMIN 9 | 136 | #define SMK_NETLBLADDRMIN 9 |
137 | #define SMK_NETLBLADDRMAX 42 | ||
168 | 138 | ||
169 | /** | 139 | /** |
170 | * smk_set_access - add a rule to the rule list | 140 | * smk_set_access - add a rule to the rule list |
@@ -189,13 +159,9 @@ static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list, | |||
189 | 159 | ||
190 | mutex_lock(rule_lock); | 160 | mutex_lock(rule_lock); |
191 | 161 | ||
192 | /* | ||
193 | * Because the object label is less likely to match | ||
194 | * than the subject label check it first | ||
195 | */ | ||
196 | list_for_each_entry_rcu(sp, rule_list, list) { | 162 | list_for_each_entry_rcu(sp, rule_list, list) { |
197 | if (sp->smk_object == srp->smk_object && | 163 | if (sp->smk_subject == srp->smk_subject && |
198 | sp->smk_subject == srp->smk_subject) { | 164 | sp->smk_object == srp->smk_object) { |
199 | found = 1; | 165 | found = 1; |
200 | sp->smk_access = srp->smk_access; | 166 | sp->smk_access = srp->smk_access; |
201 | break; | 167 | break; |
@@ -210,175 +176,30 @@ static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list, | |||
210 | } | 176 | } |
211 | 177 | ||
212 | /** | 178 | /** |
213 | * smk_fill_rule - Fill Smack rule from strings | 179 | * smk_write_load_list - write() for any /smack/load |
214 | * @subject: subject label string | ||
215 | * @object: object label string | ||
216 | * @access: access string | ||
217 | * @rule: Smack rule | ||
218 | * @import: if non-zero, import labels | ||
219 | * @len: label length limit | ||
220 | * | ||
221 | * Returns 0 on success, -1 on failure | ||
222 | */ | ||
223 | static int smk_fill_rule(const char *subject, const char *object, | ||
224 | const char *access, struct smack_rule *rule, | ||
225 | int import, int len) | ||
226 | { | ||
227 | const char *cp; | ||
228 | struct smack_known *skp; | ||
229 | |||
230 | if (import) { | ||
231 | rule->smk_subject = smk_import(subject, len); | ||
232 | if (rule->smk_subject == NULL) | ||
233 | return -1; | ||
234 | |||
235 | rule->smk_object = smk_import(object, len); | ||
236 | if (rule->smk_object == NULL) | ||
237 | return -1; | ||
238 | } else { | ||
239 | cp = smk_parse_smack(subject, len); | ||
240 | if (cp == NULL) | ||
241 | return -1; | ||
242 | skp = smk_find_entry(cp); | ||
243 | kfree(cp); | ||
244 | if (skp == NULL) | ||
245 | return -1; | ||
246 | rule->smk_subject = skp->smk_known; | ||
247 | |||
248 | cp = smk_parse_smack(object, len); | ||
249 | if (cp == NULL) | ||
250 | return -1; | ||
251 | skp = smk_find_entry(cp); | ||
252 | kfree(cp); | ||
253 | if (skp == NULL) | ||
254 | return -1; | ||
255 | rule->smk_object = skp->smk_known; | ||
256 | } | ||
257 | |||
258 | rule->smk_access = 0; | ||
259 | |||
260 | for (cp = access; *cp != '\0'; cp++) { | ||
261 | switch (*cp) { | ||
262 | case '-': | ||
263 | break; | ||
264 | case 'r': | ||
265 | case 'R': | ||
266 | rule->smk_access |= MAY_READ; | ||
267 | break; | ||
268 | case 'w': | ||
269 | case 'W': | ||
270 | rule->smk_access |= MAY_WRITE; | ||
271 | break; | ||
272 | case 'x': | ||
273 | case 'X': | ||
274 | rule->smk_access |= MAY_EXEC; | ||
275 | break; | ||
276 | case 'a': | ||
277 | case 'A': | ||
278 | rule->smk_access |= MAY_APPEND; | ||
279 | break; | ||
280 | case 't': | ||
281 | case 'T': | ||
282 | rule->smk_access |= MAY_TRANSMUTE; | ||
283 | break; | ||
284 | default: | ||
285 | return 0; | ||
286 | } | ||
287 | } | ||
288 | |||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | /** | ||
293 | * smk_parse_rule - parse Smack rule from load string | ||
294 | * @data: string to be parsed whose size is SMK_LOADLEN | ||
295 | * @rule: Smack rule | ||
296 | * @import: if non-zero, import labels | ||
297 | * | ||
298 | * Returns 0 on success, -1 on errors. | ||
299 | */ | ||
300 | static int smk_parse_rule(const char *data, struct smack_rule *rule, int import) | ||
301 | { | ||
302 | int rc; | ||
303 | |||
304 | rc = smk_fill_rule(data, data + SMK_LABELLEN, | ||
305 | data + SMK_LABELLEN + SMK_LABELLEN, rule, import, | ||
306 | SMK_LABELLEN); | ||
307 | return rc; | ||
308 | } | ||
309 | |||
310 | /** | ||
311 | * smk_parse_long_rule - parse Smack rule from rule string | ||
312 | * @data: string to be parsed, null terminated | ||
313 | * @rule: Smack rule | ||
314 | * @import: if non-zero, import labels | ||
315 | * | ||
316 | * Returns 0 on success, -1 on failure | ||
317 | */ | ||
318 | static int smk_parse_long_rule(const char *data, struct smack_rule *rule, | ||
319 | int import) | ||
320 | { | ||
321 | char *subject; | ||
322 | char *object; | ||
323 | char *access; | ||
324 | int datalen; | ||
325 | int rc = -1; | ||
326 | |||
327 | /* This is inefficient */ | ||
328 | datalen = strlen(data); | ||
329 | |||
330 | /* Our first element can be 64 + \0 with no spaces */ | ||
331 | subject = kzalloc(datalen + 1, GFP_KERNEL); | ||
332 | if (subject == NULL) | ||
333 | return -1; | ||
334 | object = kzalloc(datalen, GFP_KERNEL); | ||
335 | if (object == NULL) | ||
336 | goto free_out_s; | ||
337 | access = kzalloc(datalen, GFP_KERNEL); | ||
338 | if (access == NULL) | ||
339 | goto free_out_o; | ||
340 | |||
341 | if (sscanf(data, "%s %s %s", subject, object, access) == 3) | ||
342 | rc = smk_fill_rule(subject, object, access, rule, import, 0); | ||
343 | |||
344 | kfree(access); | ||
345 | free_out_o: | ||
346 | kfree(object); | ||
347 | free_out_s: | ||
348 | kfree(subject); | ||
349 | return rc; | ||
350 | } | ||
351 | |||
352 | #define SMK_FIXED24_FMT 0 /* Fixed 24byte label format */ | ||
353 | #define SMK_LONG_FMT 1 /* Variable long label format */ | ||
354 | /** | ||
355 | * smk_write_rules_list - write() for any /smack rule file | ||
356 | * @file: file pointer, not actually used | 180 | * @file: file pointer, not actually used |
357 | * @buf: where to get the data from | 181 | * @buf: where to get the data from |
358 | * @count: bytes sent | 182 | * @count: bytes sent |
359 | * @ppos: where to start - must be 0 | 183 | * @ppos: where to start - must be 0 |
360 | * @rule_list: the list of rules to write to | 184 | * @rule_list: the list of rules to write to |
361 | * @rule_lock: lock for the rule list | 185 | * @rule_lock: lock for the rule list |
362 | * @format: /smack/load or /smack/load2 format. | ||
363 | * | 186 | * |
364 | * Get one smack access rule from above. | 187 | * Get one smack access rule from above. |
365 | * The format for SMK_LONG_FMT is: | 188 | * The format is exactly: |
366 | * "subject<whitespace>object<whitespace>access[<whitespace>...]" | 189 | * char subject[SMK_LABELLEN] |
367 | * The format for SMK_FIXED24_FMT is exactly: | 190 | * char object[SMK_LABELLEN] |
368 | * "subject object rwxat" | 191 | * char access[SMK_ACCESSLEN] |
192 | * | ||
193 | * writes must be SMK_LABELLEN+SMK_LABELLEN+SMK_ACCESSLEN bytes. | ||
369 | */ | 194 | */ |
370 | static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, | 195 | static ssize_t smk_write_load_list(struct file *file, const char __user *buf, |
371 | size_t count, loff_t *ppos, | 196 | size_t count, loff_t *ppos, |
372 | struct list_head *rule_list, | 197 | struct list_head *rule_list, |
373 | struct mutex *rule_lock, int format) | 198 | struct mutex *rule_lock) |
374 | { | 199 | { |
375 | struct smack_master_list *smlp; | ||
376 | struct smack_known *skp; | ||
377 | struct smack_rule *rule; | 200 | struct smack_rule *rule; |
378 | char *data; | 201 | char *data; |
379 | int datalen; | ||
380 | int rc = -EINVAL; | 202 | int rc = -EINVAL; |
381 | int load = 0; | ||
382 | 203 | ||
383 | /* | 204 | /* |
384 | * No partial writes. | 205 | * No partial writes. |
@@ -386,18 +207,13 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, | |||
386 | */ | 207 | */ |
387 | if (*ppos != 0) | 208 | if (*ppos != 0) |
388 | return -EINVAL; | 209 | return -EINVAL; |
210 | /* | ||
211 | * Minor hack for backward compatibility | ||
212 | */ | ||
213 | if (count < (SMK_OLOADLEN) || count > SMK_LOADLEN) | ||
214 | return -EINVAL; | ||
389 | 215 | ||
390 | if (format == SMK_FIXED24_FMT) { | 216 | data = kzalloc(SMK_LOADLEN, GFP_KERNEL); |
391 | /* | ||
392 | * Minor hack for backward compatibility | ||
393 | */ | ||
394 | if (count != SMK_OLOADLEN && count != SMK_LOADLEN) | ||
395 | return -EINVAL; | ||
396 | datalen = SMK_LOADLEN; | ||
397 | } else | ||
398 | datalen = count + 1; | ||
399 | |||
400 | data = kzalloc(datalen, GFP_KERNEL); | ||
401 | if (data == NULL) | 217 | if (data == NULL) |
402 | return -ENOMEM; | 218 | return -ENOMEM; |
403 | 219 | ||
@@ -406,55 +222,90 @@ static ssize_t smk_write_rules_list(struct file *file, const char __user *buf, | |||
406 | goto out; | 222 | goto out; |
407 | } | 223 | } |
408 | 224 | ||
225 | /* | ||
226 | * More on the minor hack for backward compatibility | ||
227 | */ | ||
228 | if (count == (SMK_OLOADLEN)) | ||
229 | data[SMK_OLOADLEN] = '-'; | ||
230 | |||
409 | rule = kzalloc(sizeof(*rule), GFP_KERNEL); | 231 | rule = kzalloc(sizeof(*rule), GFP_KERNEL); |
410 | if (rule == NULL) { | 232 | if (rule == NULL) { |
411 | rc = -ENOMEM; | 233 | rc = -ENOMEM; |
412 | goto out; | 234 | goto out; |
413 | } | 235 | } |
414 | 236 | ||
415 | if (format == SMK_LONG_FMT) { | 237 | rule->smk_subject = smk_import(data, 0); |
416 | /* | 238 | if (rule->smk_subject == NULL) |
417 | * Be sure the data string is terminated. | 239 | goto out_free_rule; |
418 | */ | 240 | |
419 | data[count] = '\0'; | 241 | rule->smk_object = smk_import(data + SMK_LABELLEN, 0); |
420 | if (smk_parse_long_rule(data, rule, 1)) | 242 | if (rule->smk_object == NULL) |
421 | goto out_free_rule; | 243 | goto out_free_rule; |
422 | } else { | 244 | |
423 | /* | 245 | rule->smk_access = 0; |
424 | * More on the minor hack for backward compatibility | 246 | |
425 | */ | 247 | switch (data[SMK_LABELLEN + SMK_LABELLEN]) { |
426 | if (count == (SMK_OLOADLEN)) | 248 | case '-': |
427 | data[SMK_OLOADLEN] = '-'; | 249 | break; |
428 | if (smk_parse_rule(data, rule, 1)) | 250 | case 'r': |
429 | goto out_free_rule; | 251 | case 'R': |
252 | rule->smk_access |= MAY_READ; | ||
253 | break; | ||
254 | default: | ||
255 | goto out_free_rule; | ||
256 | } | ||
257 | |||
258 | switch (data[SMK_LABELLEN + SMK_LABELLEN + 1]) { | ||
259 | case '-': | ||
260 | break; | ||
261 | case 'w': | ||
262 | case 'W': | ||
263 | rule->smk_access |= MAY_WRITE; | ||
264 | break; | ||
265 | default: | ||
266 | goto out_free_rule; | ||
267 | } | ||
268 | |||
269 | switch (data[SMK_LABELLEN + SMK_LABELLEN + 2]) { | ||
270 | case '-': | ||
271 | break; | ||
272 | case 'x': | ||
273 | case 'X': | ||
274 | rule->smk_access |= MAY_EXEC; | ||
275 | break; | ||
276 | default: | ||
277 | goto out_free_rule; | ||
430 | } | 278 | } |
431 | 279 | ||
280 | switch (data[SMK_LABELLEN + SMK_LABELLEN + 3]) { | ||
281 | case '-': | ||
282 | break; | ||
283 | case 'a': | ||
284 | case 'A': | ||
285 | rule->smk_access |= MAY_APPEND; | ||
286 | break; | ||
287 | default: | ||
288 | goto out_free_rule; | ||
289 | } | ||
432 | 290 | ||
433 | if (rule_list == NULL) { | 291 | switch (data[SMK_LABELLEN + SMK_LABELLEN + 4]) { |
434 | load = 1; | 292 | case '-': |
435 | skp = smk_find_entry(rule->smk_subject); | 293 | break; |
436 | rule_list = &skp->smk_rules; | 294 | case 't': |
437 | rule_lock = &skp->smk_rules_lock; | 295 | case 'T': |
296 | rule->smk_access |= MAY_TRANSMUTE; | ||
297 | break; | ||
298 | default: | ||
299 | goto out_free_rule; | ||
438 | } | 300 | } |
439 | 301 | ||
440 | rc = count; | 302 | rc = count; |
441 | /* | 303 | /* |
442 | * If this is a global as opposed to self and a new rule | ||
443 | * it needs to get added for reporting. | ||
444 | * smk_set_access returns true if there was already a rule | 304 | * smk_set_access returns true if there was already a rule |
445 | * for the subject/object pair, and false if it was new. | 305 | * for the subject/object pair, and false if it was new. |
446 | */ | 306 | */ |
447 | if (!smk_set_access(rule, rule_list, rule_lock)) { | 307 | if (!smk_set_access(rule, rule_list, rule_lock)) |
448 | if (load) { | ||
449 | smlp = kzalloc(sizeof(*smlp), GFP_KERNEL); | ||
450 | if (smlp != NULL) { | ||
451 | smlp->smk_rule = rule; | ||
452 | list_add_rcu(&smlp->list, &smack_rule_list); | ||
453 | } else | ||
454 | rc = -ENOMEM; | ||
455 | } | ||
456 | goto out; | 308 | goto out; |
457 | } | ||
458 | 309 | ||
459 | out_free_rule: | 310 | out_free_rule: |
460 | kfree(rule); | 311 | kfree(rule); |
@@ -463,66 +314,39 @@ out: | |||
463 | return rc; | 314 | return rc; |
464 | } | 315 | } |
465 | 316 | ||
317 | |||
466 | /* | 318 | /* |
467 | * Core logic for smackfs seq list operations. | 319 | * Seq_file read operations for /smack/load |
468 | */ | 320 | */ |
469 | 321 | ||
470 | static void *smk_seq_start(struct seq_file *s, loff_t *pos, | 322 | static void *load_seq_start(struct seq_file *s, loff_t *pos) |
471 | struct list_head *head) | ||
472 | { | 323 | { |
473 | struct list_head *list; | 324 | if (*pos == SEQ_READ_FINISHED) |
474 | |||
475 | /* | ||
476 | * This is 0 the first time through. | ||
477 | */ | ||
478 | if (s->index == 0) | ||
479 | s->private = head; | ||
480 | |||
481 | if (s->private == NULL) | ||
482 | return NULL; | 325 | return NULL; |
483 | 326 | if (list_empty(&smack_rule_list)) | |
484 | list = s->private; | ||
485 | if (list_empty(list)) | ||
486 | return NULL; | 327 | return NULL; |
487 | 328 | return smack_rule_list.next; | |
488 | if (s->index == 0) | ||
489 | return list->next; | ||
490 | return list; | ||
491 | } | 329 | } |
492 | 330 | ||
493 | static void *smk_seq_next(struct seq_file *s, void *v, loff_t *pos, | 331 | static void *load_seq_next(struct seq_file *s, void *v, loff_t *pos) |
494 | struct list_head *head) | ||
495 | { | 332 | { |
496 | struct list_head *list = v; | 333 | struct list_head *list = v; |
497 | 334 | ||
498 | if (list_is_last(list, head)) { | 335 | if (list_is_last(list, &smack_rule_list)) { |
499 | s->private = NULL; | 336 | *pos = SEQ_READ_FINISHED; |
500 | return NULL; | 337 | return NULL; |
501 | } | 338 | } |
502 | s->private = list->next; | ||
503 | return list->next; | 339 | return list->next; |
504 | } | 340 | } |
505 | 341 | ||
506 | static void smk_seq_stop(struct seq_file *s, void *v) | 342 | static int load_seq_show(struct seq_file *s, void *v) |
507 | { | ||
508 | /* No-op */ | ||
509 | } | ||
510 | |||
511 | static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) | ||
512 | { | 343 | { |
513 | /* | 344 | struct list_head *list = v; |
514 | * Don't show any rules with label names too long for | 345 | struct smack_rule *srp = |
515 | * interface file (/smack/load or /smack/load2) | 346 | list_entry(list, struct smack_rule, list); |
516 | * because you should expect to be able to write | ||
517 | * anything you read back. | ||
518 | */ | ||
519 | if (strlen(srp->smk_subject) >= max || strlen(srp->smk_object) >= max) | ||
520 | return; | ||
521 | |||
522 | if (srp->smk_access == 0) | ||
523 | return; | ||
524 | 347 | ||
525 | seq_printf(s, "%s %s", srp->smk_subject, srp->smk_object); | 348 | seq_printf(s, "%s %s", (char *)srp->smk_subject, |
349 | (char *)srp->smk_object); | ||
526 | 350 | ||
527 | seq_putc(s, ' '); | 351 | seq_putc(s, ' '); |
528 | 352 | ||
@@ -536,40 +360,24 @@ static void smk_rule_show(struct seq_file *s, struct smack_rule *srp, int max) | |||
536 | seq_putc(s, 'a'); | 360 | seq_putc(s, 'a'); |
537 | if (srp->smk_access & MAY_TRANSMUTE) | 361 | if (srp->smk_access & MAY_TRANSMUTE) |
538 | seq_putc(s, 't'); | 362 | seq_putc(s, 't'); |
363 | if (srp->smk_access == 0) | ||
364 | seq_putc(s, '-'); | ||
539 | 365 | ||
540 | seq_putc(s, '\n'); | 366 | seq_putc(s, '\n'); |
541 | } | ||
542 | 367 | ||
543 | /* | 368 | return 0; |
544 | * Seq_file read operations for /smack/load | ||
545 | */ | ||
546 | |||
547 | static void *load2_seq_start(struct seq_file *s, loff_t *pos) | ||
548 | { | ||
549 | return smk_seq_start(s, pos, &smack_rule_list); | ||
550 | } | ||
551 | |||
552 | static void *load2_seq_next(struct seq_file *s, void *v, loff_t *pos) | ||
553 | { | ||
554 | return smk_seq_next(s, v, pos, &smack_rule_list); | ||
555 | } | 369 | } |
556 | 370 | ||
557 | static int load_seq_show(struct seq_file *s, void *v) | 371 | static void load_seq_stop(struct seq_file *s, void *v) |
558 | { | 372 | { |
559 | struct list_head *list = v; | 373 | /* No-op */ |
560 | struct smack_master_list *smlp = | ||
561 | list_entry(list, struct smack_master_list, list); | ||
562 | |||
563 | smk_rule_show(s, smlp->smk_rule, SMK_LABELLEN); | ||
564 | |||
565 | return 0; | ||
566 | } | 374 | } |
567 | 375 | ||
568 | static const struct seq_operations load_seq_ops = { | 376 | static const struct seq_operations load_seq_ops = { |
569 | .start = load2_seq_start, | 377 | .start = load_seq_start, |
570 | .next = load2_seq_next, | 378 | .next = load_seq_next, |
571 | .show = load_seq_show, | 379 | .show = load_seq_show, |
572 | .stop = smk_seq_stop, | 380 | .stop = load_seq_stop, |
573 | }; | 381 | }; |
574 | 382 | ||
575 | /** | 383 | /** |
@@ -595,16 +403,17 @@ static int smk_open_load(struct inode *inode, struct file *file) | |||
595 | static ssize_t smk_write_load(struct file *file, const char __user *buf, | 403 | static ssize_t smk_write_load(struct file *file, const char __user *buf, |
596 | size_t count, loff_t *ppos) | 404 | size_t count, loff_t *ppos) |
597 | { | 405 | { |
406 | |||
598 | /* | 407 | /* |
599 | * Must have privilege. | 408 | * Must have privilege. |
600 | * No partial writes. | 409 | * No partial writes. |
601 | * Enough data must be present. | 410 | * Enough data must be present. |
602 | */ | 411 | */ |
603 | if (!smack_privileged(CAP_MAC_ADMIN)) | 412 | if (!capable(CAP_MAC_ADMIN)) |
604 | return -EPERM; | 413 | return -EPERM; |
605 | 414 | ||
606 | return smk_write_rules_list(file, buf, count, ppos, NULL, NULL, | 415 | return smk_write_load_list(file, buf, count, ppos, &smack_rule_list, |
607 | SMK_FIXED24_FMT); | 416 | &smack_list_lock); |
608 | } | 417 | } |
609 | 418 | ||
610 | static const struct file_operations smk_load_ops = { | 419 | static const struct file_operations smk_load_ops = { |
@@ -674,8 +483,6 @@ static void smk_unlbl_ambient(char *oldambient) | |||
674 | printk(KERN_WARNING "%s:%d remove rc = %d\n", | 483 | printk(KERN_WARNING "%s:%d remove rc = %d\n", |
675 | __func__, __LINE__, rc); | 484 | __func__, __LINE__, rc); |
676 | } | 485 | } |
677 | if (smack_net_ambient == NULL) | ||
678 | smack_net_ambient = smack_known_floor.smk_known; | ||
679 | 486 | ||
680 | rc = netlbl_cfg_unlbl_map_add(smack_net_ambient, PF_INET, | 487 | rc = netlbl_cfg_unlbl_map_add(smack_net_ambient, PF_INET, |
681 | NULL, NULL, &nai); | 488 | NULL, NULL, &nai); |
@@ -690,12 +497,28 @@ static void smk_unlbl_ambient(char *oldambient) | |||
690 | 497 | ||
691 | static void *cipso_seq_start(struct seq_file *s, loff_t *pos) | 498 | static void *cipso_seq_start(struct seq_file *s, loff_t *pos) |
692 | { | 499 | { |
693 | return smk_seq_start(s, pos, &smack_known_list); | 500 | if (*pos == SEQ_READ_FINISHED) |
501 | return NULL; | ||
502 | if (list_empty(&smack_known_list)) | ||
503 | return NULL; | ||
504 | |||
505 | return smack_known_list.next; | ||
694 | } | 506 | } |
695 | 507 | ||
696 | static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos) | 508 | static void *cipso_seq_next(struct seq_file *s, void *v, loff_t *pos) |
697 | { | 509 | { |
698 | return smk_seq_next(s, v, pos, &smack_known_list); | 510 | struct list_head *list = v; |
511 | |||
512 | /* | ||
513 | * labels with no associated cipso value wont be printed | ||
514 | * in cipso_seq_show | ||
515 | */ | ||
516 | if (list_is_last(list, &smack_known_list)) { | ||
517 | *pos = SEQ_READ_FINISHED; | ||
518 | return NULL; | ||
519 | } | ||
520 | |||
521 | return list->next; | ||
699 | } | 522 | } |
700 | 523 | ||
701 | /* | 524 | /* |
@@ -707,39 +530,43 @@ static int cipso_seq_show(struct seq_file *s, void *v) | |||
707 | struct list_head *list = v; | 530 | struct list_head *list = v; |
708 | struct smack_known *skp = | 531 | struct smack_known *skp = |
709 | list_entry(list, struct smack_known, list); | 532 | list_entry(list, struct smack_known, list); |
710 | struct netlbl_lsm_secattr_catmap *cmp = skp->smk_netlabel.attr.mls.cat; | 533 | struct smack_cipso *scp = skp->smk_cipso; |
534 | char *cbp; | ||
711 | char sep = '/'; | 535 | char sep = '/'; |
536 | int cat = 1; | ||
712 | int i; | 537 | int i; |
538 | unsigned char m; | ||
713 | 539 | ||
714 | /* | 540 | if (scp == NULL) |
715 | * Don't show a label that could not have been set using | ||
716 | * /smack/cipso. This is in support of the notion that | ||
717 | * anything read from /smack/cipso ought to be writeable | ||
718 | * to /smack/cipso. | ||
719 | * | ||
720 | * /smack/cipso2 should be used instead. | ||
721 | */ | ||
722 | if (strlen(skp->smk_known) >= SMK_LABELLEN) | ||
723 | return 0; | 541 | return 0; |
724 | 542 | ||
725 | seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl); | 543 | seq_printf(s, "%s %3d", (char *)&skp->smk_known, scp->smk_level); |
726 | 544 | ||
727 | for (i = netlbl_secattr_catmap_walk(cmp, 0); i >= 0; | 545 | cbp = scp->smk_catset; |
728 | i = netlbl_secattr_catmap_walk(cmp, i + 1)) { | 546 | for (i = 0; i < SMK_LABELLEN; i++) |
729 | seq_printf(s, "%c%d", sep, i); | 547 | for (m = 0x80; m != 0; m >>= 1) { |
730 | sep = ','; | 548 | if (m & cbp[i]) { |
731 | } | 549 | seq_printf(s, "%c%d", sep, cat); |
550 | sep = ','; | ||
551 | } | ||
552 | cat++; | ||
553 | } | ||
732 | 554 | ||
733 | seq_putc(s, '\n'); | 555 | seq_putc(s, '\n'); |
734 | 556 | ||
735 | return 0; | 557 | return 0; |
736 | } | 558 | } |
737 | 559 | ||
560 | static void cipso_seq_stop(struct seq_file *s, void *v) | ||
561 | { | ||
562 | /* No-op */ | ||
563 | } | ||
564 | |||
738 | static const struct seq_operations cipso_seq_ops = { | 565 | static const struct seq_operations cipso_seq_ops = { |
739 | .start = cipso_seq_start, | 566 | .start = cipso_seq_start, |
567 | .stop = cipso_seq_stop, | ||
740 | .next = cipso_seq_next, | 568 | .next = cipso_seq_next, |
741 | .show = cipso_seq_show, | 569 | .show = cipso_seq_show, |
742 | .stop = smk_seq_stop, | ||
743 | }; | 570 | }; |
744 | 571 | ||
745 | /** | 572 | /** |
@@ -756,24 +583,23 @@ static int smk_open_cipso(struct inode *inode, struct file *file) | |||
756 | } | 583 | } |
757 | 584 | ||
758 | /** | 585 | /** |
759 | * smk_set_cipso - do the work for write() for cipso and cipso2 | 586 | * smk_write_cipso - write() for /smack/cipso |
760 | * @file: file pointer, not actually used | 587 | * @file: file pointer, not actually used |
761 | * @buf: where to get the data from | 588 | * @buf: where to get the data from |
762 | * @count: bytes sent | 589 | * @count: bytes sent |
763 | * @ppos: where to start | 590 | * @ppos: where to start |
764 | * @format: /smack/cipso or /smack/cipso2 | ||
765 | * | 591 | * |
766 | * Accepts only one cipso rule per write call. | 592 | * Accepts only one cipso rule per write call. |
767 | * Returns number of bytes written or error code, as appropriate | 593 | * Returns number of bytes written or error code, as appropriate |
768 | */ | 594 | */ |
769 | static ssize_t smk_set_cipso(struct file *file, const char __user *buf, | 595 | static ssize_t smk_write_cipso(struct file *file, const char __user *buf, |
770 | size_t count, loff_t *ppos, int format) | 596 | size_t count, loff_t *ppos) |
771 | { | 597 | { |
772 | struct smack_known *skp; | 598 | struct smack_known *skp; |
773 | struct netlbl_lsm_secattr ncats; | 599 | struct smack_cipso *scp = NULL; |
774 | char mapcatset[SMK_CIPSOLEN]; | 600 | char mapcatset[SMK_LABELLEN]; |
775 | int maplevel; | 601 | int maplevel; |
776 | unsigned int cat; | 602 | int cat; |
777 | int catlen; | 603 | int catlen; |
778 | ssize_t rc = -EINVAL; | 604 | ssize_t rc = -EINVAL; |
779 | char *data = NULL; | 605 | char *data = NULL; |
@@ -786,12 +612,11 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, | |||
786 | * No partial writes. | 612 | * No partial writes. |
787 | * Enough data must be present. | 613 | * Enough data must be present. |
788 | */ | 614 | */ |
789 | if (!smack_privileged(CAP_MAC_ADMIN)) | 615 | if (!capable(CAP_MAC_ADMIN)) |
790 | return -EPERM; | 616 | return -EPERM; |
791 | if (*ppos != 0) | 617 | if (*ppos != 0) |
792 | return -EINVAL; | 618 | return -EINVAL; |
793 | if (format == SMK_FIXED24_FMT && | 619 | if (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX) |
794 | (count < SMK_CIPSOMIN || count > SMK_CIPSOMAX)) | ||
795 | return -EINVAL; | 620 | return -EINVAL; |
796 | 621 | ||
797 | data = kzalloc(count + 1, GFP_KERNEL); | 622 | data = kzalloc(count + 1, GFP_KERNEL); |
@@ -803,6 +628,11 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, | |||
803 | goto unlockedout; | 628 | goto unlockedout; |
804 | } | 629 | } |
805 | 630 | ||
631 | /* labels cannot begin with a '-' */ | ||
632 | if (data[0] == '-') { | ||
633 | rc = -EINVAL; | ||
634 | goto unlockedout; | ||
635 | } | ||
806 | data[count] = '\0'; | 636 | data[count] = '\0'; |
807 | rule = data; | 637 | rule = data; |
808 | /* | 638 | /* |
@@ -815,11 +645,7 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, | |||
815 | if (skp == NULL) | 645 | if (skp == NULL) |
816 | goto out; | 646 | goto out; |
817 | 647 | ||
818 | if (format == SMK_FIXED24_FMT) | 648 | rule += SMK_LABELLEN; |
819 | rule += SMK_LABELLEN; | ||
820 | else | ||
821 | rule += strlen(skp->smk_known); | ||
822 | |||
823 | ret = sscanf(rule, "%d", &maplevel); | 649 | ret = sscanf(rule, "%d", &maplevel); |
824 | if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL) | 650 | if (ret != 1 || maplevel > SMACK_CIPSO_MAXLEVEL) |
825 | goto out; | 651 | goto out; |
@@ -829,29 +655,41 @@ static ssize_t smk_set_cipso(struct file *file, const char __user *buf, | |||
829 | if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM) | 655 | if (ret != 1 || catlen > SMACK_CIPSO_MAXCATNUM) |
830 | goto out; | 656 | goto out; |
831 | 657 | ||
832 | if (format == SMK_FIXED24_FMT && | 658 | if (count != (SMK_CIPSOMIN + catlen * SMK_DIGITLEN)) |
833 | count != (SMK_CIPSOMIN + catlen * SMK_DIGITLEN)) | ||
834 | goto out; | 659 | goto out; |
835 | 660 | ||
836 | memset(mapcatset, 0, sizeof(mapcatset)); | 661 | memset(mapcatset, 0, sizeof(mapcatset)); |
837 | 662 | ||
838 | for (i = 0; i < catlen; i++) { | 663 | for (i = 0; i < catlen; i++) { |
839 | rule += SMK_DIGITLEN; | 664 | rule += SMK_DIGITLEN; |
840 | ret = sscanf(rule, "%u", &cat); | 665 | ret = sscanf(rule, "%d", &cat); |
841 | if (ret != 1 || cat > SMACK_CIPSO_MAXCATVAL) | 666 | if (ret != 1 || cat > SMACK_CIPSO_MAXCATVAL) |
842 | goto out; | 667 | goto out; |
843 | 668 | ||
844 | smack_catset_bit(cat, mapcatset); | 669 | smack_catset_bit(cat, mapcatset); |
845 | } | 670 | } |
846 | 671 | ||
847 | rc = smk_netlbl_mls(maplevel, mapcatset, &ncats, SMK_CIPSOLEN); | 672 | if (skp->smk_cipso == NULL) { |
848 | if (rc >= 0) { | 673 | scp = kzalloc(sizeof(struct smack_cipso), GFP_KERNEL); |
849 | netlbl_secattr_catmap_free(skp->smk_netlabel.attr.mls.cat); | 674 | if (scp == NULL) { |
850 | skp->smk_netlabel.attr.mls.cat = ncats.attr.mls.cat; | 675 | rc = -ENOMEM; |
851 | skp->smk_netlabel.attr.mls.lvl = ncats.attr.mls.lvl; | 676 | goto out; |
852 | rc = count; | 677 | } |
853 | } | 678 | } |
854 | 679 | ||
680 | spin_lock_bh(&skp->smk_cipsolock); | ||
681 | |||
682 | if (scp == NULL) | ||
683 | scp = skp->smk_cipso; | ||
684 | else | ||
685 | skp->smk_cipso = scp; | ||
686 | |||
687 | scp->smk_level = maplevel; | ||
688 | memcpy(scp->smk_catset, mapcatset, sizeof(mapcatset)); | ||
689 | |||
690 | spin_unlock_bh(&skp->smk_cipsolock); | ||
691 | |||
692 | rc = count; | ||
855 | out: | 693 | out: |
856 | mutex_unlock(&smack_cipso_lock); | 694 | mutex_unlock(&smack_cipso_lock); |
857 | unlockedout: | 695 | unlockedout: |
@@ -859,22 +697,6 @@ unlockedout: | |||
859 | return rc; | 697 | return rc; |
860 | } | 698 | } |
861 | 699 | ||
862 | /** | ||
863 | * smk_write_cipso - write() for /smack/cipso | ||
864 | * @file: file pointer, not actually used | ||
865 | * @buf: where to get the data from | ||
866 | * @count: bytes sent | ||
867 | * @ppos: where to start | ||
868 | * | ||
869 | * Accepts only one cipso rule per write call. | ||
870 | * Returns number of bytes written or error code, as appropriate | ||
871 | */ | ||
872 | static ssize_t smk_write_cipso(struct file *file, const char __user *buf, | ||
873 | size_t count, loff_t *ppos) | ||
874 | { | ||
875 | return smk_set_cipso(file, buf, count, ppos, SMK_FIXED24_FMT); | ||
876 | } | ||
877 | |||
878 | static const struct file_operations smk_cipso_ops = { | 700 | static const struct file_operations smk_cipso_ops = { |
879 | .open = smk_open_cipso, | 701 | .open = smk_open_cipso, |
880 | .read = seq_read, | 702 | .read = seq_read, |
@@ -884,91 +706,28 @@ static const struct file_operations smk_cipso_ops = { | |||
884 | }; | 706 | }; |
885 | 707 | ||
886 | /* | 708 | /* |
887 | * Seq_file read operations for /smack/cipso2 | ||
888 | */ | ||
889 | |||
890 | /* | ||
891 | * Print cipso labels in format: | ||
892 | * label level[/cat[,cat]] | ||
893 | */ | ||
894 | static int cipso2_seq_show(struct seq_file *s, void *v) | ||
895 | { | ||
896 | struct list_head *list = v; | ||
897 | struct smack_known *skp = | ||
898 | list_entry(list, struct smack_known, list); | ||
899 | struct netlbl_lsm_secattr_catmap *cmp = skp->smk_netlabel.attr.mls.cat; | ||
900 | char sep = '/'; | ||
901 | int i; | ||
902 | |||
903 | seq_printf(s, "%s %3d", skp->smk_known, skp->smk_netlabel.attr.mls.lvl); | ||
904 | |||
905 | for (i = netlbl_secattr_catmap_walk(cmp, 0); i >= 0; | ||
906 | i = netlbl_secattr_catmap_walk(cmp, i + 1)) { | ||
907 | seq_printf(s, "%c%d", sep, i); | ||
908 | sep = ','; | ||
909 | } | ||
910 | |||
911 | seq_putc(s, '\n'); | ||
912 | |||
913 | return 0; | ||
914 | } | ||
915 | |||
916 | static const struct seq_operations cipso2_seq_ops = { | ||
917 | .start = cipso_seq_start, | ||
918 | .next = cipso_seq_next, | ||
919 | .show = cipso2_seq_show, | ||
920 | .stop = smk_seq_stop, | ||
921 | }; | ||
922 | |||
923 | /** | ||
924 | * smk_open_cipso2 - open() for /smack/cipso2 | ||
925 | * @inode: inode structure representing file | ||
926 | * @file: "cipso2" file pointer | ||
927 | * | ||
928 | * Connect our cipso_seq_* operations with /smack/cipso2 | ||
929 | * file_operations | ||
930 | */ | ||
931 | static int smk_open_cipso2(struct inode *inode, struct file *file) | ||
932 | { | ||
933 | return seq_open(file, &cipso2_seq_ops); | ||
934 | } | ||
935 | |||
936 | /** | ||
937 | * smk_write_cipso2 - write() for /smack/cipso2 | ||
938 | * @file: file pointer, not actually used | ||
939 | * @buf: where to get the data from | ||
940 | * @count: bytes sent | ||
941 | * @ppos: where to start | ||
942 | * | ||
943 | * Accepts only one cipso rule per write call. | ||
944 | * Returns number of bytes written or error code, as appropriate | ||
945 | */ | ||
946 | static ssize_t smk_write_cipso2(struct file *file, const char __user *buf, | ||
947 | size_t count, loff_t *ppos) | ||
948 | { | ||
949 | return smk_set_cipso(file, buf, count, ppos, SMK_LONG_FMT); | ||
950 | } | ||
951 | |||
952 | static const struct file_operations smk_cipso2_ops = { | ||
953 | .open = smk_open_cipso2, | ||
954 | .read = seq_read, | ||
955 | .llseek = seq_lseek, | ||
956 | .write = smk_write_cipso2, | ||
957 | .release = seq_release, | ||
958 | }; | ||
959 | |||
960 | /* | ||
961 | * Seq_file read operations for /smack/netlabel | 709 | * Seq_file read operations for /smack/netlabel |
962 | */ | 710 | */ |
963 | 711 | ||
964 | static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos) | 712 | static void *netlbladdr_seq_start(struct seq_file *s, loff_t *pos) |
965 | { | 713 | { |
966 | return smk_seq_start(s, pos, &smk_netlbladdr_list); | 714 | if (*pos == SEQ_READ_FINISHED) |
715 | return NULL; | ||
716 | if (list_empty(&smk_netlbladdr_list)) | ||
717 | return NULL; | ||
718 | return smk_netlbladdr_list.next; | ||
967 | } | 719 | } |
968 | 720 | ||
969 | static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos) | 721 | static void *netlbladdr_seq_next(struct seq_file *s, void *v, loff_t *pos) |
970 | { | 722 | { |
971 | return smk_seq_next(s, v, pos, &smk_netlbladdr_list); | 723 | struct list_head *list = v; |
724 | |||
725 | if (list_is_last(list, &smk_netlbladdr_list)) { | ||
726 | *pos = SEQ_READ_FINISHED; | ||
727 | return NULL; | ||
728 | } | ||
729 | |||
730 | return list->next; | ||
972 | } | 731 | } |
973 | #define BEBITS (sizeof(__be32) * 8) | 732 | #define BEBITS (sizeof(__be32) * 8) |
974 | 733 | ||
@@ -992,11 +751,16 @@ static int netlbladdr_seq_show(struct seq_file *s, void *v) | |||
992 | return 0; | 751 | return 0; |
993 | } | 752 | } |
994 | 753 | ||
754 | static void netlbladdr_seq_stop(struct seq_file *s, void *v) | ||
755 | { | ||
756 | /* No-op */ | ||
757 | } | ||
758 | |||
995 | static const struct seq_operations netlbladdr_seq_ops = { | 759 | static const struct seq_operations netlbladdr_seq_ops = { |
996 | .start = netlbladdr_seq_start, | 760 | .start = netlbladdr_seq_start, |
761 | .stop = netlbladdr_seq_stop, | ||
997 | .next = netlbladdr_seq_next, | 762 | .next = netlbladdr_seq_next, |
998 | .show = netlbladdr_seq_show, | 763 | .show = netlbladdr_seq_show, |
999 | .stop = smk_seq_stop, | ||
1000 | }; | 764 | }; |
1001 | 765 | ||
1002 | /** | 766 | /** |
@@ -1069,9 +833,9 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
1069 | { | 833 | { |
1070 | struct smk_netlbladdr *skp; | 834 | struct smk_netlbladdr *skp; |
1071 | struct sockaddr_in newname; | 835 | struct sockaddr_in newname; |
1072 | char *smack; | 836 | char smack[SMK_LABELLEN]; |
1073 | char *sp; | 837 | char *sp; |
1074 | char *data; | 838 | char data[SMK_NETLBLADDRMAX + 1]; |
1075 | char *host = (char *)&newname.sin_addr.s_addr; | 839 | char *host = (char *)&newname.sin_addr.s_addr; |
1076 | int rc; | 840 | int rc; |
1077 | struct netlbl_audit audit_info; | 841 | struct netlbl_audit audit_info; |
@@ -1089,27 +853,14 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
1089 | * "<addr/mask, as a.b.c.d/e><space><label>" | 853 | * "<addr/mask, as a.b.c.d/e><space><label>" |
1090 | * "<addr, as a.b.c.d><space><label>" | 854 | * "<addr, as a.b.c.d><space><label>" |
1091 | */ | 855 | */ |
1092 | if (!smack_privileged(CAP_MAC_ADMIN)) | 856 | if (!capable(CAP_MAC_ADMIN)) |
1093 | return -EPERM; | 857 | return -EPERM; |
1094 | if (*ppos != 0) | 858 | if (*ppos != 0) |
1095 | return -EINVAL; | 859 | return -EINVAL; |
1096 | if (count < SMK_NETLBLADDRMIN) | 860 | if (count < SMK_NETLBLADDRMIN || count > SMK_NETLBLADDRMAX) |
1097 | return -EINVAL; | 861 | return -EINVAL; |
1098 | 862 | if (copy_from_user(data, buf, count) != 0) | |
1099 | data = kzalloc(count + 1, GFP_KERNEL); | 863 | return -EFAULT; |
1100 | if (data == NULL) | ||
1101 | return -ENOMEM; | ||
1102 | |||
1103 | if (copy_from_user(data, buf, count) != 0) { | ||
1104 | rc = -EFAULT; | ||
1105 | goto free_data_out; | ||
1106 | } | ||
1107 | |||
1108 | smack = kzalloc(count + 1, GFP_KERNEL); | ||
1109 | if (smack == NULL) { | ||
1110 | rc = -ENOMEM; | ||
1111 | goto free_data_out; | ||
1112 | } | ||
1113 | 864 | ||
1114 | data[count] = '\0'; | 865 | data[count] = '\0'; |
1115 | 866 | ||
@@ -1118,34 +869,24 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
1118 | if (rc != 6) { | 869 | if (rc != 6) { |
1119 | rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s", | 870 | rc = sscanf(data, "%hhd.%hhd.%hhd.%hhd %s", |
1120 | &host[0], &host[1], &host[2], &host[3], smack); | 871 | &host[0], &host[1], &host[2], &host[3], smack); |
1121 | if (rc != 5) { | 872 | if (rc != 5) |
1122 | rc = -EINVAL; | 873 | return -EINVAL; |
1123 | goto free_out; | ||
1124 | } | ||
1125 | m = BEBITS; | 874 | m = BEBITS; |
1126 | } | 875 | } |
1127 | if (m > BEBITS) { | 876 | if (m > BEBITS) |
1128 | rc = -EINVAL; | 877 | return -EINVAL; |
1129 | goto free_out; | ||
1130 | } | ||
1131 | 878 | ||
1132 | /* | 879 | /* if smack begins with '-', its an option, don't import it */ |
1133 | * If smack begins with '-', it is an option, don't import it | ||
1134 | */ | ||
1135 | if (smack[0] != '-') { | 880 | if (smack[0] != '-') { |
1136 | sp = smk_import(smack, 0); | 881 | sp = smk_import(smack, 0); |
1137 | if (sp == NULL) { | 882 | if (sp == NULL) |
1138 | rc = -EINVAL; | 883 | return -EINVAL; |
1139 | goto free_out; | ||
1140 | } | ||
1141 | } else { | 884 | } else { |
1142 | /* check known options */ | 885 | /* check known options */ |
1143 | if (strcmp(smack, smack_cipso_option) == 0) | 886 | if (strcmp(smack, smack_cipso_option) == 0) |
1144 | sp = (char *)smack_cipso_option; | 887 | sp = (char *)smack_cipso_option; |
1145 | else { | 888 | else |
1146 | rc = -EINVAL; | 889 | return -EINVAL; |
1147 | goto free_out; | ||
1148 | } | ||
1149 | } | 890 | } |
1150 | 891 | ||
1151 | for (temp_mask = 0; m > 0; m--) { | 892 | for (temp_mask = 0; m > 0; m--) { |
@@ -1211,11 +952,6 @@ static ssize_t smk_write_netlbladdr(struct file *file, const char __user *buf, | |||
1211 | 952 | ||
1212 | mutex_unlock(&smk_netlbladdr_lock); | 953 | mutex_unlock(&smk_netlbladdr_lock); |
1213 | 954 | ||
1214 | free_out: | ||
1215 | kfree(smack); | ||
1216 | free_data_out: | ||
1217 | kfree(data); | ||
1218 | |||
1219 | return rc; | 955 | return rc; |
1220 | } | 956 | } |
1221 | 957 | ||
@@ -1266,7 +1002,7 @@ static ssize_t smk_write_doi(struct file *file, const char __user *buf, | |||
1266 | char temp[80]; | 1002 | char temp[80]; |
1267 | int i; | 1003 | int i; |
1268 | 1004 | ||
1269 | if (!smack_privileged(CAP_MAC_ADMIN)) | 1005 | if (!capable(CAP_MAC_ADMIN)) |
1270 | return -EPERM; | 1006 | return -EPERM; |
1271 | 1007 | ||
1272 | if (count >= sizeof(temp) || count == 0) | 1008 | if (count >= sizeof(temp) || count == 0) |
@@ -1329,11 +1065,10 @@ static ssize_t smk_read_direct(struct file *filp, char __user *buf, | |||
1329 | static ssize_t smk_write_direct(struct file *file, const char __user *buf, | 1065 | static ssize_t smk_write_direct(struct file *file, const char __user *buf, |
1330 | size_t count, loff_t *ppos) | 1066 | size_t count, loff_t *ppos) |
1331 | { | 1067 | { |
1332 | struct smack_known *skp; | ||
1333 | char temp[80]; | 1068 | char temp[80]; |
1334 | int i; | 1069 | int i; |
1335 | 1070 | ||
1336 | if (!smack_privileged(CAP_MAC_ADMIN)) | 1071 | if (!capable(CAP_MAC_ADMIN)) |
1337 | return -EPERM; | 1072 | return -EPERM; |
1338 | 1073 | ||
1339 | if (count >= sizeof(temp) || count == 0) | 1074 | if (count >= sizeof(temp) || count == 0) |
@@ -1347,20 +1082,7 @@ static ssize_t smk_write_direct(struct file *file, const char __user *buf, | |||
1347 | if (sscanf(temp, "%d", &i) != 1) | 1082 | if (sscanf(temp, "%d", &i) != 1) |
1348 | return -EINVAL; | 1083 | return -EINVAL; |
1349 | 1084 | ||
1350 | /* | 1085 | smack_cipso_direct = i; |
1351 | * Don't do anything if the value hasn't actually changed. | ||
1352 | * If it is changing reset the level on entries that were | ||
1353 | * set up to be direct when they were created. | ||
1354 | */ | ||
1355 | if (smack_cipso_direct != i) { | ||
1356 | mutex_lock(&smack_known_lock); | ||
1357 | list_for_each_entry_rcu(skp, &smack_known_list, list) | ||
1358 | if (skp->smk_netlabel.attr.mls.lvl == | ||
1359 | smack_cipso_direct) | ||
1360 | skp->smk_netlabel.attr.mls.lvl = i; | ||
1361 | smack_cipso_direct = i; | ||
1362 | mutex_unlock(&smack_known_lock); | ||
1363 | } | ||
1364 | 1086 | ||
1365 | return count; | 1087 | return count; |
1366 | } | 1088 | } |
@@ -1372,84 +1094,6 @@ static const struct file_operations smk_direct_ops = { | |||
1372 | }; | 1094 | }; |
1373 | 1095 | ||
1374 | /** | 1096 | /** |
1375 | * smk_read_mapped - read() for /smack/mapped | ||
1376 | * @filp: file pointer, not actually used | ||
1377 | * @buf: where to put the result | ||
1378 | * @count: maximum to send along | ||
1379 | * @ppos: where to start | ||
1380 | * | ||
1381 | * Returns number of bytes read or error code, as appropriate | ||
1382 | */ | ||
1383 | static ssize_t smk_read_mapped(struct file *filp, char __user *buf, | ||
1384 | size_t count, loff_t *ppos) | ||
1385 | { | ||
1386 | char temp[80]; | ||
1387 | ssize_t rc; | ||
1388 | |||
1389 | if (*ppos != 0) | ||
1390 | return 0; | ||
1391 | |||
1392 | sprintf(temp, "%d", smack_cipso_mapped); | ||
1393 | rc = simple_read_from_buffer(buf, count, ppos, temp, strlen(temp)); | ||
1394 | |||
1395 | return rc; | ||
1396 | } | ||
1397 | |||
1398 | /** | ||
1399 | * smk_write_mapped - write() for /smack/mapped | ||
1400 | * @file: file pointer, not actually used | ||
1401 | * @buf: where to get the data from | ||
1402 | * @count: bytes sent | ||
1403 | * @ppos: where to start | ||
1404 | * | ||
1405 | * Returns number of bytes written or error code, as appropriate | ||
1406 | */ | ||
1407 | static ssize_t smk_write_mapped(struct file *file, const char __user *buf, | ||
1408 | size_t count, loff_t *ppos) | ||
1409 | { | ||
1410 | struct smack_known *skp; | ||
1411 | char temp[80]; | ||
1412 | int i; | ||
1413 | |||
1414 | if (!smack_privileged(CAP_MAC_ADMIN)) | ||
1415 | return -EPERM; | ||
1416 | |||
1417 | if (count >= sizeof(temp) || count == 0) | ||
1418 | return -EINVAL; | ||
1419 | |||
1420 | if (copy_from_user(temp, buf, count) != 0) | ||
1421 | return -EFAULT; | ||
1422 | |||
1423 | temp[count] = '\0'; | ||
1424 | |||
1425 | if (sscanf(temp, "%d", &i) != 1) | ||
1426 | return -EINVAL; | ||
1427 | |||
1428 | /* | ||
1429 | * Don't do anything if the value hasn't actually changed. | ||
1430 | * If it is changing reset the level on entries that were | ||
1431 | * set up to be mapped when they were created. | ||
1432 | */ | ||
1433 | if (smack_cipso_mapped != i) { | ||
1434 | mutex_lock(&smack_known_lock); | ||
1435 | list_for_each_entry_rcu(skp, &smack_known_list, list) | ||
1436 | if (skp->smk_netlabel.attr.mls.lvl == | ||
1437 | smack_cipso_mapped) | ||
1438 | skp->smk_netlabel.attr.mls.lvl = i; | ||
1439 | smack_cipso_mapped = i; | ||
1440 | mutex_unlock(&smack_known_lock); | ||
1441 | } | ||
1442 | |||
1443 | return count; | ||
1444 | } | ||
1445 | |||
1446 | static const struct file_operations smk_mapped_ops = { | ||
1447 | .read = smk_read_mapped, | ||
1448 | .write = smk_write_mapped, | ||
1449 | .llseek = default_llseek, | ||
1450 | }; | ||
1451 | |||
1452 | /** | ||
1453 | * smk_read_ambient - read() for /smack/ambient | 1097 | * smk_read_ambient - read() for /smack/ambient |
1454 | * @filp: file pointer, not actually used | 1098 | * @filp: file pointer, not actually used |
1455 | * @buf: where to put the result | 1099 | * @buf: where to put the result |
@@ -1497,28 +1141,22 @@ static ssize_t smk_read_ambient(struct file *filp, char __user *buf, | |||
1497 | static ssize_t smk_write_ambient(struct file *file, const char __user *buf, | 1141 | static ssize_t smk_write_ambient(struct file *file, const char __user *buf, |
1498 | size_t count, loff_t *ppos) | 1142 | size_t count, loff_t *ppos) |
1499 | { | 1143 | { |
1144 | char in[SMK_LABELLEN]; | ||
1500 | char *oldambient; | 1145 | char *oldambient; |
1501 | char *smack = NULL; | 1146 | char *smack; |
1502 | char *data; | ||
1503 | int rc = count; | ||
1504 | 1147 | ||
1505 | if (!smack_privileged(CAP_MAC_ADMIN)) | 1148 | if (!capable(CAP_MAC_ADMIN)) |
1506 | return -EPERM; | 1149 | return -EPERM; |
1507 | 1150 | ||
1508 | data = kzalloc(count + 1, GFP_KERNEL); | 1151 | if (count >= SMK_LABELLEN) |
1509 | if (data == NULL) | 1152 | return -EINVAL; |
1510 | return -ENOMEM; | ||
1511 | 1153 | ||
1512 | if (copy_from_user(data, buf, count) != 0) { | 1154 | if (copy_from_user(in, buf, count) != 0) |
1513 | rc = -EFAULT; | 1155 | return -EFAULT; |
1514 | goto out; | ||
1515 | } | ||
1516 | 1156 | ||
1517 | smack = smk_import(data, count); | 1157 | smack = smk_import(in, count); |
1518 | if (smack == NULL) { | 1158 | if (smack == NULL) |
1519 | rc = -EINVAL; | 1159 | return -EINVAL; |
1520 | goto out; | ||
1521 | } | ||
1522 | 1160 | ||
1523 | mutex_lock(&smack_ambient_lock); | 1161 | mutex_lock(&smack_ambient_lock); |
1524 | 1162 | ||
@@ -1528,9 +1166,7 @@ static ssize_t smk_write_ambient(struct file *file, const char __user *buf, | |||
1528 | 1166 | ||
1529 | mutex_unlock(&smack_ambient_lock); | 1167 | mutex_unlock(&smack_ambient_lock); |
1530 | 1168 | ||
1531 | out: | 1169 | return count; |
1532 | kfree(data); | ||
1533 | return rc; | ||
1534 | } | 1170 | } |
1535 | 1171 | ||
1536 | static const struct file_operations smk_ambient_ops = { | 1172 | static const struct file_operations smk_ambient_ops = { |
@@ -1581,11 +1217,10 @@ static ssize_t smk_read_onlycap(struct file *filp, char __user *buf, | |||
1581 | static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, | 1217 | static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, |
1582 | size_t count, loff_t *ppos) | 1218 | size_t count, loff_t *ppos) |
1583 | { | 1219 | { |
1584 | char *data; | 1220 | char in[SMK_LABELLEN]; |
1585 | char *sp = smk_of_task(current->cred->security); | 1221 | char *sp = smk_of_task(current->cred->security); |
1586 | int rc = count; | ||
1587 | 1222 | ||
1588 | if (!smack_privileged(CAP_MAC_ADMIN)) | 1223 | if (!capable(CAP_MAC_ADMIN)) |
1589 | return -EPERM; | 1224 | return -EPERM; |
1590 | 1225 | ||
1591 | /* | 1226 | /* |
@@ -1596,9 +1231,11 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, | |||
1596 | if (smack_onlycap != NULL && smack_onlycap != sp) | 1231 | if (smack_onlycap != NULL && smack_onlycap != sp) |
1597 | return -EPERM; | 1232 | return -EPERM; |
1598 | 1233 | ||
1599 | data = kzalloc(count, GFP_KERNEL); | 1234 | if (count >= SMK_LABELLEN) |
1600 | if (data == NULL) | 1235 | return -EINVAL; |
1601 | return -ENOMEM; | 1236 | |
1237 | if (copy_from_user(in, buf, count) != 0) | ||
1238 | return -EFAULT; | ||
1602 | 1239 | ||
1603 | /* | 1240 | /* |
1604 | * Should the null string be passed in unset the onlycap value. | 1241 | * Should the null string be passed in unset the onlycap value. |
@@ -1606,17 +1243,10 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf, | |||
1606 | * smk_import only expects to return NULL for errors. It | 1243 | * smk_import only expects to return NULL for errors. It |
1607 | * is usually the case that a nullstring or "\n" would be | 1244 | * is usually the case that a nullstring or "\n" would be |
1608 | * bad to pass to smk_import but in fact this is useful here. | 1245 | * bad to pass to smk_import but in fact this is useful here. |
1609 | * | ||
1610 | * smk_import will also reject a label beginning with '-', | ||
1611 | * so "-usecapabilities" will also work. | ||
1612 | */ | 1246 | */ |
1613 | if (copy_from_user(data, buf, count) != 0) | 1247 | smack_onlycap = smk_import(in, count); |
1614 | rc = -EFAULT; | ||
1615 | else | ||
1616 | smack_onlycap = smk_import(data, count); | ||
1617 | 1248 | ||
1618 | kfree(data); | 1249 | return count; |
1619 | return rc; | ||
1620 | } | 1250 | } |
1621 | 1251 | ||
1622 | static const struct file_operations smk_onlycap_ops = { | 1252 | static const struct file_operations smk_onlycap_ops = { |
@@ -1663,7 +1293,7 @@ static ssize_t smk_write_logging(struct file *file, const char __user *buf, | |||
1663 | char temp[32]; | 1293 | char temp[32]; |
1664 | int i; | 1294 | int i; |
1665 | 1295 | ||
1666 | if (!smack_privileged(CAP_MAC_ADMIN)) | 1296 | if (!capable(CAP_MAC_ADMIN)) |
1667 | return -EPERM; | 1297 | return -EPERM; |
1668 | 1298 | ||
1669 | if (count >= sizeof(temp) || count == 0) | 1299 | if (count >= sizeof(temp) || count == 0) |
@@ -1698,14 +1328,23 @@ static void *load_self_seq_start(struct seq_file *s, loff_t *pos) | |||
1698 | { | 1328 | { |
1699 | struct task_smack *tsp = current_security(); | 1329 | struct task_smack *tsp = current_security(); |
1700 | 1330 | ||
1701 | return smk_seq_start(s, pos, &tsp->smk_rules); | 1331 | if (*pos == SEQ_READ_FINISHED) |
1332 | return NULL; | ||
1333 | if (list_empty(&tsp->smk_rules)) | ||
1334 | return NULL; | ||
1335 | return tsp->smk_rules.next; | ||
1702 | } | 1336 | } |
1703 | 1337 | ||
1704 | static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos) | 1338 | static void *load_self_seq_next(struct seq_file *s, void *v, loff_t *pos) |
1705 | { | 1339 | { |
1706 | struct task_smack *tsp = current_security(); | 1340 | struct task_smack *tsp = current_security(); |
1341 | struct list_head *list = v; | ||
1707 | 1342 | ||
1708 | return smk_seq_next(s, v, pos, &tsp->smk_rules); | 1343 | if (list_is_last(list, &tsp->smk_rules)) { |
1344 | *pos = SEQ_READ_FINISHED; | ||
1345 | return NULL; | ||
1346 | } | ||
1347 | return list->next; | ||
1709 | } | 1348 | } |
1710 | 1349 | ||
1711 | static int load_self_seq_show(struct seq_file *s, void *v) | 1350 | static int load_self_seq_show(struct seq_file *s, void *v) |
@@ -1714,21 +1353,44 @@ static int load_self_seq_show(struct seq_file *s, void *v) | |||
1714 | struct smack_rule *srp = | 1353 | struct smack_rule *srp = |
1715 | list_entry(list, struct smack_rule, list); | 1354 | list_entry(list, struct smack_rule, list); |
1716 | 1355 | ||
1717 | smk_rule_show(s, srp, SMK_LABELLEN); | 1356 | seq_printf(s, "%s %s", (char *)srp->smk_subject, |
1357 | (char *)srp->smk_object); | ||
1358 | |||
1359 | seq_putc(s, ' '); | ||
1360 | |||
1361 | if (srp->smk_access & MAY_READ) | ||
1362 | seq_putc(s, 'r'); | ||
1363 | if (srp->smk_access & MAY_WRITE) | ||
1364 | seq_putc(s, 'w'); | ||
1365 | if (srp->smk_access & MAY_EXEC) | ||
1366 | seq_putc(s, 'x'); | ||
1367 | if (srp->smk_access & MAY_APPEND) | ||
1368 | seq_putc(s, 'a'); | ||
1369 | if (srp->smk_access & MAY_TRANSMUTE) | ||
1370 | seq_putc(s, 't'); | ||
1371 | if (srp->smk_access == 0) | ||
1372 | seq_putc(s, '-'); | ||
1373 | |||
1374 | seq_putc(s, '\n'); | ||
1718 | 1375 | ||
1719 | return 0; | 1376 | return 0; |
1720 | } | 1377 | } |
1721 | 1378 | ||
1379 | static void load_self_seq_stop(struct seq_file *s, void *v) | ||
1380 | { | ||
1381 | /* No-op */ | ||
1382 | } | ||
1383 | |||
1722 | static const struct seq_operations load_self_seq_ops = { | 1384 | static const struct seq_operations load_self_seq_ops = { |
1723 | .start = load_self_seq_start, | 1385 | .start = load_self_seq_start, |
1724 | .next = load_self_seq_next, | 1386 | .next = load_self_seq_next, |
1725 | .show = load_self_seq_show, | 1387 | .show = load_self_seq_show, |
1726 | .stop = smk_seq_stop, | 1388 | .stop = load_self_seq_stop, |
1727 | }; | 1389 | }; |
1728 | 1390 | ||
1729 | 1391 | ||
1730 | /** | 1392 | /** |
1731 | * smk_open_load_self - open() for /smack/load-self2 | 1393 | * smk_open_load_self - open() for /smack/load-self |
1732 | * @inode: inode structure representing file | 1394 | * @inode: inode structure representing file |
1733 | * @file: "load" file pointer | 1395 | * @file: "load" file pointer |
1734 | * | 1396 | * |
@@ -1752,8 +1414,8 @@ static ssize_t smk_write_load_self(struct file *file, const char __user *buf, | |||
1752 | { | 1414 | { |
1753 | struct task_smack *tsp = current_security(); | 1415 | struct task_smack *tsp = current_security(); |
1754 | 1416 | ||
1755 | return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules, | 1417 | return smk_write_load_list(file, buf, count, ppos, &tsp->smk_rules, |
1756 | &tsp->smk_rules_lock, SMK_FIXED24_FMT); | 1418 | &tsp->smk_rules_lock); |
1757 | } | 1419 | } |
1758 | 1420 | ||
1759 | static const struct file_operations smk_load_self_ops = { | 1421 | static const struct file_operations smk_load_self_ops = { |
@@ -1763,319 +1425,6 @@ static const struct file_operations smk_load_self_ops = { | |||
1763 | .write = smk_write_load_self, | 1425 | .write = smk_write_load_self, |
1764 | .release = seq_release, | 1426 | .release = seq_release, |
1765 | }; | 1427 | }; |
1766 | |||
1767 | /** | ||
1768 | * smk_user_access - handle access check transaction | ||
1769 | * @file: file pointer | ||
1770 | * @buf: data from user space | ||
1771 | * @count: bytes sent | ||
1772 | * @ppos: where to start - must be 0 | ||
1773 | */ | ||
1774 | static ssize_t smk_user_access(struct file *file, const char __user *buf, | ||
1775 | size_t count, loff_t *ppos, int format) | ||
1776 | { | ||
1777 | struct smack_rule rule; | ||
1778 | char *data; | ||
1779 | char *cod; | ||
1780 | int res; | ||
1781 | |||
1782 | data = simple_transaction_get(file, buf, count); | ||
1783 | if (IS_ERR(data)) | ||
1784 | return PTR_ERR(data); | ||
1785 | |||
1786 | if (format == SMK_FIXED24_FMT) { | ||
1787 | if (count < SMK_LOADLEN) | ||
1788 | return -EINVAL; | ||
1789 | res = smk_parse_rule(data, &rule, 0); | ||
1790 | } else { | ||
1791 | /* | ||
1792 | * Copy the data to make sure the string is terminated. | ||
1793 | */ | ||
1794 | cod = kzalloc(count + 1, GFP_KERNEL); | ||
1795 | if (cod == NULL) | ||
1796 | return -ENOMEM; | ||
1797 | memcpy(cod, data, count); | ||
1798 | cod[count] = '\0'; | ||
1799 | res = smk_parse_long_rule(cod, &rule, 0); | ||
1800 | kfree(cod); | ||
1801 | } | ||
1802 | |||
1803 | if (res) | ||
1804 | return -EINVAL; | ||
1805 | |||
1806 | res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access, | ||
1807 | NULL); | ||
1808 | data[0] = res == 0 ? '1' : '0'; | ||
1809 | data[1] = '\0'; | ||
1810 | |||
1811 | simple_transaction_set(file, 2); | ||
1812 | |||
1813 | if (format == SMK_FIXED24_FMT) | ||
1814 | return SMK_LOADLEN; | ||
1815 | return count; | ||
1816 | } | ||
1817 | |||
1818 | /** | ||
1819 | * smk_write_access - handle access check transaction | ||
1820 | * @file: file pointer | ||
1821 | * @buf: data from user space | ||
1822 | * @count: bytes sent | ||
1823 | * @ppos: where to start - must be 0 | ||
1824 | */ | ||
1825 | static ssize_t smk_write_access(struct file *file, const char __user *buf, | ||
1826 | size_t count, loff_t *ppos) | ||
1827 | { | ||
1828 | return smk_user_access(file, buf, count, ppos, SMK_FIXED24_FMT); | ||
1829 | } | ||
1830 | |||
1831 | static const struct file_operations smk_access_ops = { | ||
1832 | .write = smk_write_access, | ||
1833 | .read = simple_transaction_read, | ||
1834 | .release = simple_transaction_release, | ||
1835 | .llseek = generic_file_llseek, | ||
1836 | }; | ||
1837 | |||
1838 | |||
1839 | /* | ||
1840 | * Seq_file read operations for /smack/load2 | ||
1841 | */ | ||
1842 | |||
1843 | static int load2_seq_show(struct seq_file *s, void *v) | ||
1844 | { | ||
1845 | struct list_head *list = v; | ||
1846 | struct smack_master_list *smlp = | ||
1847 | list_entry(list, struct smack_master_list, list); | ||
1848 | |||
1849 | smk_rule_show(s, smlp->smk_rule, SMK_LONGLABEL); | ||
1850 | |||
1851 | return 0; | ||
1852 | } | ||
1853 | |||
1854 | static const struct seq_operations load2_seq_ops = { | ||
1855 | .start = load2_seq_start, | ||
1856 | .next = load2_seq_next, | ||
1857 | .show = load2_seq_show, | ||
1858 | .stop = smk_seq_stop, | ||
1859 | }; | ||
1860 | |||
1861 | /** | ||
1862 | * smk_open_load2 - open() for /smack/load2 | ||
1863 | * @inode: inode structure representing file | ||
1864 | * @file: "load2" file pointer | ||
1865 | * | ||
1866 | * For reading, use load2_seq_* seq_file reading operations. | ||
1867 | */ | ||
1868 | static int smk_open_load2(struct inode *inode, struct file *file) | ||
1869 | { | ||
1870 | return seq_open(file, &load2_seq_ops); | ||
1871 | } | ||
1872 | |||
1873 | /** | ||
1874 | * smk_write_load2 - write() for /smack/load2 | ||
1875 | * @file: file pointer, not actually used | ||
1876 | * @buf: where to get the data from | ||
1877 | * @count: bytes sent | ||
1878 | * @ppos: where to start - must be 0 | ||
1879 | * | ||
1880 | */ | ||
1881 | static ssize_t smk_write_load2(struct file *file, const char __user *buf, | ||
1882 | size_t count, loff_t *ppos) | ||
1883 | { | ||
1884 | /* | ||
1885 | * Must have privilege. | ||
1886 | */ | ||
1887 | if (!smack_privileged(CAP_MAC_ADMIN)) | ||
1888 | return -EPERM; | ||
1889 | |||
1890 | return smk_write_rules_list(file, buf, count, ppos, NULL, NULL, | ||
1891 | SMK_LONG_FMT); | ||
1892 | } | ||
1893 | |||
1894 | static const struct file_operations smk_load2_ops = { | ||
1895 | .open = smk_open_load2, | ||
1896 | .read = seq_read, | ||
1897 | .llseek = seq_lseek, | ||
1898 | .write = smk_write_load2, | ||
1899 | .release = seq_release, | ||
1900 | }; | ||
1901 | |||
1902 | /* | ||
1903 | * Seq_file read operations for /smack/load-self2 | ||
1904 | */ | ||
1905 | |||
1906 | static void *load_self2_seq_start(struct seq_file *s, loff_t *pos) | ||
1907 | { | ||
1908 | struct task_smack *tsp = current_security(); | ||
1909 | |||
1910 | return smk_seq_start(s, pos, &tsp->smk_rules); | ||
1911 | } | ||
1912 | |||
1913 | static void *load_self2_seq_next(struct seq_file *s, void *v, loff_t *pos) | ||
1914 | { | ||
1915 | struct task_smack *tsp = current_security(); | ||
1916 | |||
1917 | return smk_seq_next(s, v, pos, &tsp->smk_rules); | ||
1918 | } | ||
1919 | |||
1920 | static int load_self2_seq_show(struct seq_file *s, void *v) | ||
1921 | { | ||
1922 | struct list_head *list = v; | ||
1923 | struct smack_rule *srp = | ||
1924 | list_entry(list, struct smack_rule, list); | ||
1925 | |||
1926 | smk_rule_show(s, srp, SMK_LONGLABEL); | ||
1927 | |||
1928 | return 0; | ||
1929 | } | ||
1930 | |||
1931 | static const struct seq_operations load_self2_seq_ops = { | ||
1932 | .start = load_self2_seq_start, | ||
1933 | .next = load_self2_seq_next, | ||
1934 | .show = load_self2_seq_show, | ||
1935 | .stop = smk_seq_stop, | ||
1936 | }; | ||
1937 | |||
1938 | /** | ||
1939 | * smk_open_load_self2 - open() for /smack/load-self2 | ||
1940 | * @inode: inode structure representing file | ||
1941 | * @file: "load" file pointer | ||
1942 | * | ||
1943 | * For reading, use load_seq_* seq_file reading operations. | ||
1944 | */ | ||
1945 | static int smk_open_load_self2(struct inode *inode, struct file *file) | ||
1946 | { | ||
1947 | return seq_open(file, &load_self2_seq_ops); | ||
1948 | } | ||
1949 | |||
1950 | /** | ||
1951 | * smk_write_load_self2 - write() for /smack/load-self2 | ||
1952 | * @file: file pointer, not actually used | ||
1953 | * @buf: where to get the data from | ||
1954 | * @count: bytes sent | ||
1955 | * @ppos: where to start - must be 0 | ||
1956 | * | ||
1957 | */ | ||
1958 | static ssize_t smk_write_load_self2(struct file *file, const char __user *buf, | ||
1959 | size_t count, loff_t *ppos) | ||
1960 | { | ||
1961 | struct task_smack *tsp = current_security(); | ||
1962 | |||
1963 | return smk_write_rules_list(file, buf, count, ppos, &tsp->smk_rules, | ||
1964 | &tsp->smk_rules_lock, SMK_LONG_FMT); | ||
1965 | } | ||
1966 | |||
1967 | static const struct file_operations smk_load_self2_ops = { | ||
1968 | .open = smk_open_load_self2, | ||
1969 | .read = seq_read, | ||
1970 | .llseek = seq_lseek, | ||
1971 | .write = smk_write_load_self2, | ||
1972 | .release = seq_release, | ||
1973 | }; | ||
1974 | |||
1975 | /** | ||
1976 | * smk_write_access2 - handle access check transaction | ||
1977 | * @file: file pointer | ||
1978 | * @buf: data from user space | ||
1979 | * @count: bytes sent | ||
1980 | * @ppos: where to start - must be 0 | ||
1981 | */ | ||
1982 | static ssize_t smk_write_access2(struct file *file, const char __user *buf, | ||
1983 | size_t count, loff_t *ppos) | ||
1984 | { | ||
1985 | return smk_user_access(file, buf, count, ppos, SMK_LONG_FMT); | ||
1986 | } | ||
1987 | |||
1988 | static const struct file_operations smk_access2_ops = { | ||
1989 | .write = smk_write_access2, | ||
1990 | .read = simple_transaction_read, | ||
1991 | .release = simple_transaction_release, | ||
1992 | .llseek = generic_file_llseek, | ||
1993 | }; | ||
1994 | |||
1995 | /** | ||
1996 | * smk_write_revoke_subj - write() for /smack/revoke-subject | ||
1997 | * @file: file pointer | ||
1998 | * @buf: data from user space | ||
1999 | * @count: bytes sent | ||
2000 | * @ppos: where to start - must be 0 | ||
2001 | */ | ||
2002 | static ssize_t smk_write_revoke_subj(struct file *file, const char __user *buf, | ||
2003 | size_t count, loff_t *ppos) | ||
2004 | { | ||
2005 | char *data = NULL; | ||
2006 | const char *cp = NULL; | ||
2007 | struct smack_known *skp; | ||
2008 | struct smack_rule *sp; | ||
2009 | struct list_head *rule_list; | ||
2010 | struct mutex *rule_lock; | ||
2011 | int rc = count; | ||
2012 | |||
2013 | if (*ppos != 0) | ||
2014 | return -EINVAL; | ||
2015 | |||
2016 | if (!smack_privileged(CAP_MAC_ADMIN)) | ||
2017 | return -EPERM; | ||
2018 | |||
2019 | if (count == 0 || count > SMK_LONGLABEL) | ||
2020 | return -EINVAL; | ||
2021 | |||
2022 | data = kzalloc(count, GFP_KERNEL); | ||
2023 | if (data == NULL) | ||
2024 | return -ENOMEM; | ||
2025 | |||
2026 | if (copy_from_user(data, buf, count) != 0) { | ||
2027 | rc = -EFAULT; | ||
2028 | goto free_out; | ||
2029 | } | ||
2030 | |||
2031 | cp = smk_parse_smack(data, count); | ||
2032 | if (cp == NULL) { | ||
2033 | rc = -EINVAL; | ||
2034 | goto free_out; | ||
2035 | } | ||
2036 | |||
2037 | skp = smk_find_entry(cp); | ||
2038 | if (skp == NULL) { | ||
2039 | rc = -EINVAL; | ||
2040 | goto free_out; | ||
2041 | } | ||
2042 | |||
2043 | rule_list = &skp->smk_rules; | ||
2044 | rule_lock = &skp->smk_rules_lock; | ||
2045 | |||
2046 | mutex_lock(rule_lock); | ||
2047 | |||
2048 | list_for_each_entry_rcu(sp, rule_list, list) | ||
2049 | sp->smk_access = 0; | ||
2050 | |||
2051 | mutex_unlock(rule_lock); | ||
2052 | |||
2053 | free_out: | ||
2054 | kfree(data); | ||
2055 | kfree(cp); | ||
2056 | return rc; | ||
2057 | } | ||
2058 | |||
2059 | static const struct file_operations smk_revoke_subj_ops = { | ||
2060 | .write = smk_write_revoke_subj, | ||
2061 | .read = simple_transaction_read, | ||
2062 | .release = simple_transaction_release, | ||
2063 | .llseek = generic_file_llseek, | ||
2064 | }; | ||
2065 | |||
2066 | static struct kset *smackfs_kset; | ||
2067 | /** | ||
2068 | * smk_init_sysfs - initialize /sys/fs/smackfs | ||
2069 | * | ||
2070 | */ | ||
2071 | static int smk_init_sysfs(void) | ||
2072 | { | ||
2073 | smackfs_kset = kset_create_and_add("smackfs", NULL, fs_kobj); | ||
2074 | if (!smackfs_kset) | ||
2075 | return -ENOMEM; | ||
2076 | return 0; | ||
2077 | } | ||
2078 | |||
2079 | /** | 1428 | /** |
2080 | * smk_fill_super - fill the /smackfs superblock | 1429 | * smk_fill_super - fill the /smackfs superblock |
2081 | * @sb: the empty superblock | 1430 | * @sb: the empty superblock |
@@ -2110,21 +1459,6 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) | |||
2110 | "logging", &smk_logging_ops, S_IRUGO|S_IWUSR}, | 1459 | "logging", &smk_logging_ops, S_IRUGO|S_IWUSR}, |
2111 | [SMK_LOAD_SELF] = { | 1460 | [SMK_LOAD_SELF] = { |
2112 | "load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO}, | 1461 | "load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO}, |
2113 | [SMK_ACCESSES] = { | ||
2114 | "access", &smk_access_ops, S_IRUGO|S_IWUGO}, | ||
2115 | [SMK_MAPPED] = { | ||
2116 | "mapped", &smk_mapped_ops, S_IRUGO|S_IWUSR}, | ||
2117 | [SMK_LOAD2] = { | ||
2118 | "load2", &smk_load2_ops, S_IRUGO|S_IWUSR}, | ||
2119 | [SMK_LOAD_SELF2] = { | ||
2120 | "load-self2", &smk_load_self2_ops, S_IRUGO|S_IWUGO}, | ||
2121 | [SMK_ACCESS2] = { | ||
2122 | "access2", &smk_access2_ops, S_IRUGO|S_IWUGO}, | ||
2123 | [SMK_CIPSO2] = { | ||
2124 | "cipso2", &smk_cipso2_ops, S_IRUGO|S_IWUSR}, | ||
2125 | [SMK_REVOKE_SUBJ] = { | ||
2126 | "revoke-subject", &smk_revoke_subj_ops, | ||
2127 | S_IRUGO|S_IWUSR}, | ||
2128 | /* last one */ | 1462 | /* last one */ |
2129 | {""} | 1463 | {""} |
2130 | }; | 1464 | }; |
@@ -2137,6 +1471,7 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent) | |||
2137 | } | 1471 | } |
2138 | 1472 | ||
2139 | root_inode = sb->s_root->d_inode; | 1473 | root_inode = sb->s_root->d_inode; |
1474 | root_inode->i_security = new_inode_smack(smack_known_floor.smk_known); | ||
2140 | 1475 | ||
2141 | return 0; | 1476 | return 0; |
2142 | } | 1477 | } |
@@ -2166,15 +1501,6 @@ static struct file_system_type smk_fs_type = { | |||
2166 | 1501 | ||
2167 | static struct vfsmount *smackfs_mount; | 1502 | static struct vfsmount *smackfs_mount; |
2168 | 1503 | ||
2169 | static int __init smk_preset_netlabel(struct smack_known *skp) | ||
2170 | { | ||
2171 | skp->smk_netlabel.domain = skp->smk_known; | ||
2172 | skp->smk_netlabel.flags = | ||
2173 | NETLBL_SECATTR_DOMAIN | NETLBL_SECATTR_MLS_LVL; | ||
2174 | return smk_netlbl_mls(smack_cipso_direct, skp->smk_known, | ||
2175 | &skp->smk_netlabel, strlen(skp->smk_known)); | ||
2176 | } | ||
2177 | |||
2178 | /** | 1504 | /** |
2179 | * init_smk_fs - get the smackfs superblock | 1505 | * init_smk_fs - get the smackfs superblock |
2180 | * | 1506 | * |
@@ -2191,15 +1517,10 @@ static int __init smk_preset_netlabel(struct smack_known *skp) | |||
2191 | static int __init init_smk_fs(void) | 1517 | static int __init init_smk_fs(void) |
2192 | { | 1518 | { |
2193 | int err; | 1519 | int err; |
2194 | int rc; | ||
2195 | 1520 | ||
2196 | if (!security_module_enable(&smack_ops)) | 1521 | if (!security_module_enable(&smack_ops)) |
2197 | return 0; | 1522 | return 0; |
2198 | 1523 | ||
2199 | err = smk_init_sysfs(); | ||
2200 | if (err) | ||
2201 | printk(KERN_ERR "smackfs: sysfs mountpoint problem.\n"); | ||
2202 | |||
2203 | err = register_filesystem(&smk_fs_type); | 1524 | err = register_filesystem(&smk_fs_type); |
2204 | if (!err) { | 1525 | if (!err) { |
2205 | smackfs_mount = kern_mount(&smk_fs_type); | 1526 | smackfs_mount = kern_mount(&smk_fs_type); |
@@ -2213,25 +1534,6 @@ static int __init init_smk_fs(void) | |||
2213 | smk_cipso_doi(); | 1534 | smk_cipso_doi(); |
2214 | smk_unlbl_ambient(NULL); | 1535 | smk_unlbl_ambient(NULL); |
2215 | 1536 | ||
2216 | rc = smk_preset_netlabel(&smack_known_floor); | ||
2217 | if (err == 0 && rc < 0) | ||
2218 | err = rc; | ||
2219 | rc = smk_preset_netlabel(&smack_known_hat); | ||
2220 | if (err == 0 && rc < 0) | ||
2221 | err = rc; | ||
2222 | rc = smk_preset_netlabel(&smack_known_huh); | ||
2223 | if (err == 0 && rc < 0) | ||
2224 | err = rc; | ||
2225 | rc = smk_preset_netlabel(&smack_known_invalid); | ||
2226 | if (err == 0 && rc < 0) | ||
2227 | err = rc; | ||
2228 | rc = smk_preset_netlabel(&smack_known_star); | ||
2229 | if (err == 0 && rc < 0) | ||
2230 | err = rc; | ||
2231 | rc = smk_preset_netlabel(&smack_known_web); | ||
2232 | if (err == 0 && rc < 0) | ||
2233 | err = rc; | ||
2234 | |||
2235 | return err; | 1537 | return err; |
2236 | } | 1538 | } |
2237 | 1539 | ||