diff options
Diffstat (limited to 'security/smack/smack_lsm.c')
-rw-r--r-- | security/smack/smack_lsm.c | 684 |
1 files changed, 498 insertions, 186 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index d52c780bdb78..6a083303501d 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -27,10 +27,13 @@ | |||
27 | #include <linux/ip.h> | 27 | #include <linux/ip.h> |
28 | #include <linux/tcp.h> | 28 | #include <linux/tcp.h> |
29 | #include <linux/udp.h> | 29 | #include <linux/udp.h> |
30 | #include <linux/dccp.h> | ||
30 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
31 | #include <linux/mutex.h> | 32 | #include <linux/mutex.h> |
32 | #include <linux/pipe_fs_i.h> | 33 | #include <linux/pipe_fs_i.h> |
33 | #include <net/cipso_ipv4.h> | 34 | #include <net/cipso_ipv4.h> |
35 | #include <net/ip.h> | ||
36 | #include <net/ipv6.h> | ||
34 | #include <linux/audit.h> | 37 | #include <linux/audit.h> |
35 | #include <linux/magic.h> | 38 | #include <linux/magic.h> |
36 | #include <linux/dcache.h> | 39 | #include <linux/dcache.h> |
@@ -45,6 +48,12 @@ | |||
45 | #define TRANS_TRUE "TRUE" | 48 | #define TRANS_TRUE "TRUE" |
46 | #define TRANS_TRUE_SIZE 4 | 49 | #define TRANS_TRUE_SIZE 4 |
47 | 50 | ||
51 | #define SMK_CONNECTING 0 | ||
52 | #define SMK_RECEIVING 1 | ||
53 | #define SMK_SENDING 2 | ||
54 | |||
55 | LIST_HEAD(smk_ipv6_port_list); | ||
56 | |||
48 | /** | 57 | /** |
49 | * smk_fetch - Fetch the smack label from a file. | 58 | * smk_fetch - Fetch the smack label from a file. |
50 | * @ip: a pointer to the inode | 59 | * @ip: a pointer to the inode |
@@ -53,11 +62,12 @@ | |||
53 | * Returns a pointer to the master list entry for the Smack label | 62 | * Returns a pointer to the master list entry for the Smack label |
54 | * or NULL if there was no label to fetch. | 63 | * or NULL if there was no label to fetch. |
55 | */ | 64 | */ |
56 | static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp) | 65 | static struct smack_known *smk_fetch(const char *name, struct inode *ip, |
66 | struct dentry *dp) | ||
57 | { | 67 | { |
58 | int rc; | 68 | int rc; |
59 | char *buffer; | 69 | char *buffer; |
60 | char *result = NULL; | 70 | struct smack_known *skp = NULL; |
61 | 71 | ||
62 | if (ip->i_op->getxattr == NULL) | 72 | if (ip->i_op->getxattr == NULL) |
63 | return NULL; | 73 | return NULL; |
@@ -68,11 +78,11 @@ static char *smk_fetch(const char *name, struct inode *ip, struct dentry *dp) | |||
68 | 78 | ||
69 | rc = ip->i_op->getxattr(dp, name, buffer, SMK_LONGLABEL); | 79 | rc = ip->i_op->getxattr(dp, name, buffer, SMK_LONGLABEL); |
70 | if (rc > 0) | 80 | if (rc > 0) |
71 | result = smk_import(buffer, rc); | 81 | skp = smk_import_entry(buffer, rc); |
72 | 82 | ||
73 | kfree(buffer); | 83 | kfree(buffer); |
74 | 84 | ||
75 | return result; | 85 | return skp; |
76 | } | 86 | } |
77 | 87 | ||
78 | /** | 88 | /** |
@@ -102,7 +112,8 @@ struct inode_smack *new_inode_smack(char *smack) | |||
102 | * | 112 | * |
103 | * Returns the new blob or NULL if there's no memory available | 113 | * Returns the new blob or NULL if there's no memory available |
104 | */ | 114 | */ |
105 | static struct task_smack *new_task_smack(char *task, char *forked, gfp_t gfp) | 115 | static struct task_smack *new_task_smack(struct smack_known *task, |
116 | struct smack_known *forked, gfp_t gfp) | ||
106 | { | 117 | { |
107 | struct task_smack *tsp; | 118 | struct task_smack *tsp; |
108 | 119 | ||
@@ -164,17 +175,17 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) | |||
164 | { | 175 | { |
165 | int rc; | 176 | int rc; |
166 | struct smk_audit_info ad; | 177 | struct smk_audit_info ad; |
167 | char *tsp; | 178 | struct smack_known *skp; |
168 | 179 | ||
169 | rc = cap_ptrace_access_check(ctp, mode); | 180 | rc = cap_ptrace_access_check(ctp, mode); |
170 | if (rc != 0) | 181 | if (rc != 0) |
171 | return rc; | 182 | return rc; |
172 | 183 | ||
173 | tsp = smk_of_task(task_security(ctp)); | 184 | skp = smk_of_task(task_security(ctp)); |
174 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 185 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
175 | smk_ad_setfield_u_tsk(&ad, ctp); | 186 | smk_ad_setfield_u_tsk(&ad, ctp); |
176 | 187 | ||
177 | rc = smk_curacc(tsp, MAY_READWRITE, &ad); | 188 | rc = smk_curacc(skp->smk_known, MAY_READWRITE, &ad); |
178 | return rc; | 189 | return rc; |
179 | } | 190 | } |
180 | 191 | ||
@@ -190,17 +201,17 @@ static int smack_ptrace_traceme(struct task_struct *ptp) | |||
190 | { | 201 | { |
191 | int rc; | 202 | int rc; |
192 | struct smk_audit_info ad; | 203 | struct smk_audit_info ad; |
193 | char *tsp; | 204 | struct smack_known *skp; |
194 | 205 | ||
195 | rc = cap_ptrace_traceme(ptp); | 206 | rc = cap_ptrace_traceme(ptp); |
196 | if (rc != 0) | 207 | if (rc != 0) |
197 | return rc; | 208 | return rc; |
198 | 209 | ||
199 | tsp = smk_of_task(task_security(ptp)); | 210 | skp = smk_of_task(task_security(ptp)); |
200 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 211 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
201 | smk_ad_setfield_u_tsk(&ad, ptp); | 212 | smk_ad_setfield_u_tsk(&ad, ptp); |
202 | 213 | ||
203 | rc = smk_curacc(tsp, MAY_READWRITE, &ad); | 214 | rc = smk_curacc(skp->smk_known, MAY_READWRITE, &ad); |
204 | return rc; | 215 | return rc; |
205 | } | 216 | } |
206 | 217 | ||
@@ -215,12 +226,12 @@ static int smack_ptrace_traceme(struct task_struct *ptp) | |||
215 | static int smack_syslog(int typefrom_file) | 226 | static int smack_syslog(int typefrom_file) |
216 | { | 227 | { |
217 | int rc = 0; | 228 | int rc = 0; |
218 | char *sp = smk_of_current(); | 229 | struct smack_known *skp = smk_of_current(); |
219 | 230 | ||
220 | if (smack_privileged(CAP_MAC_OVERRIDE)) | 231 | if (smack_privileged(CAP_MAC_OVERRIDE)) |
221 | return 0; | 232 | return 0; |
222 | 233 | ||
223 | if (sp != smack_known_floor.smk_known) | 234 | if (skp != &smack_known_floor) |
224 | rc = -EACCES; | 235 | rc = -EACCES; |
225 | 236 | ||
226 | return rc; | 237 | return rc; |
@@ -250,8 +261,9 @@ static int smack_sb_alloc_security(struct super_block *sb) | |||
250 | sbsp->smk_default = smack_known_floor.smk_known; | 261 | sbsp->smk_default = smack_known_floor.smk_known; |
251 | sbsp->smk_floor = smack_known_floor.smk_known; | 262 | sbsp->smk_floor = smack_known_floor.smk_known; |
252 | sbsp->smk_hat = smack_known_hat.smk_known; | 263 | sbsp->smk_hat = smack_known_hat.smk_known; |
253 | sbsp->smk_initialized = 0; | 264 | /* |
254 | 265 | * smk_initialized will be zero from kzalloc. | |
266 | */ | ||
255 | sb->s_security = sbsp; | 267 | sb->s_security = sbsp; |
256 | 268 | ||
257 | return 0; | 269 | return 0; |
@@ -295,6 +307,8 @@ static int smack_sb_copy_data(char *orig, char *smackopts) | |||
295 | dp = smackopts; | 307 | dp = smackopts; |
296 | else if (strstr(cp, SMK_FSROOT) == cp) | 308 | else if (strstr(cp, SMK_FSROOT) == cp) |
297 | dp = smackopts; | 309 | dp = smackopts; |
310 | else if (strstr(cp, SMK_FSTRANS) == cp) | ||
311 | dp = smackopts; | ||
298 | else | 312 | else |
299 | dp = otheropts; | 313 | dp = otheropts; |
300 | 314 | ||
@@ -330,8 +344,9 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
330 | char *op; | 344 | char *op; |
331 | char *commap; | 345 | char *commap; |
332 | char *nsp; | 346 | char *nsp; |
347 | int transmute = 0; | ||
333 | 348 | ||
334 | if (sp->smk_initialized != 0) | 349 | if (sp->smk_initialized) |
335 | return 0; | 350 | return 0; |
336 | 351 | ||
337 | sp->smk_initialized = 1; | 352 | sp->smk_initialized = 1; |
@@ -362,6 +377,13 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
362 | nsp = smk_import(op, 0); | 377 | nsp = smk_import(op, 0); |
363 | if (nsp != NULL) | 378 | if (nsp != NULL) |
364 | sp->smk_root = nsp; | 379 | sp->smk_root = nsp; |
380 | } else if (strncmp(op, SMK_FSTRANS, strlen(SMK_FSTRANS)) == 0) { | ||
381 | op += strlen(SMK_FSTRANS); | ||
382 | nsp = smk_import(op, 0); | ||
383 | if (nsp != NULL) { | ||
384 | sp->smk_root = nsp; | ||
385 | transmute = 1; | ||
386 | } | ||
365 | } | 387 | } |
366 | } | 388 | } |
367 | 389 | ||
@@ -369,11 +391,15 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
369 | * Initialize the root inode. | 391 | * Initialize the root inode. |
370 | */ | 392 | */ |
371 | isp = inode->i_security; | 393 | isp = inode->i_security; |
372 | if (isp == NULL) | 394 | if (inode->i_security == NULL) { |
373 | inode->i_security = new_inode_smack(sp->smk_root); | 395 | inode->i_security = new_inode_smack(sp->smk_root); |
374 | else | 396 | isp = inode->i_security; |
397 | } else | ||
375 | isp->smk_inode = sp->smk_root; | 398 | isp->smk_inode = sp->smk_root; |
376 | 399 | ||
400 | if (transmute) | ||
401 | isp->smk_flags |= SMK_INODE_TRANSMUTE; | ||
402 | |||
377 | return 0; | 403 | return 0; |
378 | } | 404 | } |
379 | 405 | ||
@@ -524,7 +550,9 @@ static int smack_bprm_secureexec(struct linux_binprm *bprm) | |||
524 | */ | 550 | */ |
525 | static int smack_inode_alloc_security(struct inode *inode) | 551 | static int smack_inode_alloc_security(struct inode *inode) |
526 | { | 552 | { |
527 | inode->i_security = new_inode_smack(smk_of_current()); | 553 | struct smack_known *skp = smk_of_current(); |
554 | |||
555 | inode->i_security = new_inode_smack(skp->smk_known); | ||
528 | if (inode->i_security == NULL) | 556 | if (inode->i_security == NULL) |
529 | return -ENOMEM; | 557 | return -ENOMEM; |
530 | return 0; | 558 | return 0; |
@@ -557,9 +585,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
557 | const struct qstr *qstr, char **name, | 585 | const struct qstr *qstr, char **name, |
558 | void **value, size_t *len) | 586 | void **value, size_t *len) |
559 | { | 587 | { |
560 | struct smack_known *skp; | ||
561 | struct inode_smack *issp = inode->i_security; | 588 | struct inode_smack *issp = inode->i_security; |
562 | char *csp = smk_of_current(); | 589 | struct smack_known *skp = smk_of_current(); |
563 | char *isp = smk_of_inode(inode); | 590 | char *isp = smk_of_inode(inode); |
564 | char *dsp = smk_of_inode(dir); | 591 | char *dsp = smk_of_inode(dir); |
565 | int may; | 592 | int may; |
@@ -571,9 +598,8 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir, | |||
571 | } | 598 | } |
572 | 599 | ||
573 | if (value) { | 600 | if (value) { |
574 | skp = smk_find_entry(csp); | ||
575 | rcu_read_lock(); | 601 | rcu_read_lock(); |
576 | may = smk_access_entry(csp, dsp, &skp->smk_rules); | 602 | may = smk_access_entry(skp->smk_known, dsp, &skp->smk_rules); |
577 | rcu_read_unlock(); | 603 | rcu_read_unlock(); |
578 | 604 | ||
579 | /* | 605 | /* |
@@ -862,29 +888,31 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name, | |||
862 | static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, | 888 | static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, |
863 | const void *value, size_t size, int flags) | 889 | const void *value, size_t size, int flags) |
864 | { | 890 | { |
865 | char *nsp; | 891 | struct smack_known *skp; |
866 | struct inode_smack *isp = dentry->d_inode->i_security; | 892 | struct inode_smack *isp = dentry->d_inode->i_security; |
867 | 893 | ||
894 | if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { | ||
895 | isp->smk_flags |= SMK_INODE_TRANSMUTE; | ||
896 | return; | ||
897 | } | ||
898 | |||
899 | skp = smk_import_entry(value, size); | ||
868 | if (strcmp(name, XATTR_NAME_SMACK) == 0) { | 900 | if (strcmp(name, XATTR_NAME_SMACK) == 0) { |
869 | nsp = smk_import(value, size); | 901 | if (skp != NULL) |
870 | if (nsp != NULL) | 902 | isp->smk_inode = skp->smk_known; |
871 | isp->smk_inode = nsp; | ||
872 | else | 903 | else |
873 | isp->smk_inode = smack_known_invalid.smk_known; | 904 | isp->smk_inode = smack_known_invalid.smk_known; |
874 | } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { | 905 | } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { |
875 | nsp = smk_import(value, size); | 906 | if (skp != NULL) |
876 | if (nsp != NULL) | 907 | isp->smk_task = skp; |
877 | isp->smk_task = nsp; | ||
878 | else | 908 | else |
879 | isp->smk_task = smack_known_invalid.smk_known; | 909 | isp->smk_task = &smack_known_invalid; |
880 | } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { | 910 | } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { |
881 | nsp = smk_import(value, size); | 911 | if (skp != NULL) |
882 | if (nsp != NULL) | 912 | isp->smk_mmap = skp; |
883 | isp->smk_mmap = nsp; | ||
884 | else | 913 | else |
885 | isp->smk_mmap = smack_known_invalid.smk_known; | 914 | isp->smk_mmap = &smack_known_invalid; |
886 | } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) | 915 | } |
887 | isp->smk_flags |= SMK_INODE_TRANSMUTE; | ||
888 | 916 | ||
889 | return; | 917 | return; |
890 | } | 918 | } |
@@ -990,7 +1018,7 @@ static int smack_inode_getsecurity(const struct inode *inode, | |||
990 | if (strcmp(name, XATTR_SMACK_IPIN) == 0) | 1018 | if (strcmp(name, XATTR_SMACK_IPIN) == 0) |
991 | isp = ssp->smk_in; | 1019 | isp = ssp->smk_in; |
992 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) | 1020 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) |
993 | isp = ssp->smk_out; | 1021 | isp = ssp->smk_out->smk_known; |
994 | else | 1022 | else |
995 | return -EOPNOTSUPP; | 1023 | return -EOPNOTSUPP; |
996 | 1024 | ||
@@ -1070,7 +1098,9 @@ static int smack_file_permission(struct file *file, int mask) | |||
1070 | */ | 1098 | */ |
1071 | static int smack_file_alloc_security(struct file *file) | 1099 | static int smack_file_alloc_security(struct file *file) |
1072 | { | 1100 | { |
1073 | file->f_security = smk_of_current(); | 1101 | struct smack_known *skp = smk_of_current(); |
1102 | |||
1103 | file->f_security = skp->smk_known; | ||
1074 | return 0; | 1104 | return 0; |
1075 | } | 1105 | } |
1076 | 1106 | ||
@@ -1181,10 +1211,9 @@ static int smack_mmap_file(struct file *file, | |||
1181 | unsigned long flags) | 1211 | unsigned long flags) |
1182 | { | 1212 | { |
1183 | struct smack_known *skp; | 1213 | struct smack_known *skp; |
1214 | struct smack_known *mkp; | ||
1184 | struct smack_rule *srp; | 1215 | struct smack_rule *srp; |
1185 | struct task_smack *tsp; | 1216 | struct task_smack *tsp; |
1186 | char *sp; | ||
1187 | char *msmack; | ||
1188 | char *osmack; | 1217 | char *osmack; |
1189 | struct inode_smack *isp; | 1218 | struct inode_smack *isp; |
1190 | int may; | 1219 | int may; |
@@ -1198,11 +1227,10 @@ static int smack_mmap_file(struct file *file, | |||
1198 | isp = file_inode(file)->i_security; | 1227 | isp = file_inode(file)->i_security; |
1199 | if (isp->smk_mmap == NULL) | 1228 | if (isp->smk_mmap == NULL) |
1200 | return 0; | 1229 | return 0; |
1201 | msmack = isp->smk_mmap; | 1230 | mkp = isp->smk_mmap; |
1202 | 1231 | ||
1203 | tsp = current_security(); | 1232 | tsp = current_security(); |
1204 | sp = smk_of_current(); | 1233 | skp = smk_of_current(); |
1205 | skp = smk_find_entry(sp); | ||
1206 | rc = 0; | 1234 | rc = 0; |
1207 | 1235 | ||
1208 | rcu_read_lock(); | 1236 | rcu_read_lock(); |
@@ -1216,13 +1244,13 @@ static int smack_mmap_file(struct file *file, | |||
1216 | /* | 1244 | /* |
1217 | * Matching labels always allows access. | 1245 | * Matching labels always allows access. |
1218 | */ | 1246 | */ |
1219 | if (msmack == osmack) | 1247 | if (mkp->smk_known == osmack) |
1220 | continue; | 1248 | continue; |
1221 | /* | 1249 | /* |
1222 | * If there is a matching local rule take | 1250 | * If there is a matching local rule take |
1223 | * that into account as well. | 1251 | * that into account as well. |
1224 | */ | 1252 | */ |
1225 | may = smk_access_entry(srp->smk_subject, osmack, | 1253 | may = smk_access_entry(srp->smk_subject->smk_known, osmack, |
1226 | &tsp->smk_rules); | 1254 | &tsp->smk_rules); |
1227 | if (may == -ENOENT) | 1255 | if (may == -ENOENT) |
1228 | may = srp->smk_access; | 1256 | may = srp->smk_access; |
@@ -1240,8 +1268,8 @@ static int smack_mmap_file(struct file *file, | |||
1240 | * If there isn't one a SMACK64MMAP subject | 1268 | * If there isn't one a SMACK64MMAP subject |
1241 | * can't have as much access as current. | 1269 | * can't have as much access as current. |
1242 | */ | 1270 | */ |
1243 | skp = smk_find_entry(msmack); | 1271 | mmay = smk_access_entry(mkp->smk_known, osmack, |
1244 | mmay = smk_access_entry(msmack, osmack, &skp->smk_rules); | 1272 | &mkp->smk_rules); |
1245 | if (mmay == -ENOENT) { | 1273 | if (mmay == -ENOENT) { |
1246 | rc = -EACCES; | 1274 | rc = -EACCES; |
1247 | break; | 1275 | break; |
@@ -1250,7 +1278,8 @@ static int smack_mmap_file(struct file *file, | |||
1250 | * If there is a local entry it modifies the | 1278 | * If there is a local entry it modifies the |
1251 | * potential access, too. | 1279 | * potential access, too. |
1252 | */ | 1280 | */ |
1253 | tmay = smk_access_entry(msmack, osmack, &tsp->smk_rules); | 1281 | tmay = smk_access_entry(mkp->smk_known, osmack, |
1282 | &tsp->smk_rules); | ||
1254 | if (tmay != -ENOENT) | 1283 | if (tmay != -ENOENT) |
1255 | mmay &= tmay; | 1284 | mmay &= tmay; |
1256 | 1285 | ||
@@ -1279,7 +1308,9 @@ static int smack_mmap_file(struct file *file, | |||
1279 | */ | 1308 | */ |
1280 | static int smack_file_set_fowner(struct file *file) | 1309 | static int smack_file_set_fowner(struct file *file) |
1281 | { | 1310 | { |
1282 | file->f_security = smk_of_current(); | 1311 | struct smack_known *skp = smk_of_current(); |
1312 | |||
1313 | file->f_security = skp->smk_known; | ||
1283 | return 0; | 1314 | return 0; |
1284 | } | 1315 | } |
1285 | 1316 | ||
@@ -1297,9 +1328,10 @@ static int smack_file_set_fowner(struct file *file) | |||
1297 | static int smack_file_send_sigiotask(struct task_struct *tsk, | 1328 | static int smack_file_send_sigiotask(struct task_struct *tsk, |
1298 | struct fown_struct *fown, int signum) | 1329 | struct fown_struct *fown, int signum) |
1299 | { | 1330 | { |
1331 | struct smack_known *skp; | ||
1332 | struct smack_known *tkp = smk_of_task(tsk->cred->security); | ||
1300 | struct file *file; | 1333 | struct file *file; |
1301 | int rc; | 1334 | int rc; |
1302 | char *tsp = smk_of_task(tsk->cred->security); | ||
1303 | struct smk_audit_info ad; | 1335 | struct smk_audit_info ad; |
1304 | 1336 | ||
1305 | /* | 1337 | /* |
@@ -1308,13 +1340,14 @@ static int smack_file_send_sigiotask(struct task_struct *tsk, | |||
1308 | file = container_of(fown, struct file, f_owner); | 1340 | file = container_of(fown, struct file, f_owner); |
1309 | 1341 | ||
1310 | /* we don't log here as rc can be overriden */ | 1342 | /* we don't log here as rc can be overriden */ |
1311 | rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL); | 1343 | skp = smk_find_entry(file->f_security); |
1344 | rc = smk_access(skp, tkp->smk_known, MAY_WRITE, NULL); | ||
1312 | if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) | 1345 | if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) |
1313 | rc = 0; | 1346 | rc = 0; |
1314 | 1347 | ||
1315 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 1348 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
1316 | smk_ad_setfield_u_tsk(&ad, tsk); | 1349 | smk_ad_setfield_u_tsk(&ad, tsk); |
1317 | smack_log(file->f_security, tsp, MAY_WRITE, rc, &ad); | 1350 | smack_log(file->f_security, tkp->smk_known, MAY_WRITE, rc, &ad); |
1318 | return rc; | 1351 | return rc; |
1319 | } | 1352 | } |
1320 | 1353 | ||
@@ -1469,12 +1502,12 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old) | |||
1469 | static int smack_kernel_act_as(struct cred *new, u32 secid) | 1502 | static int smack_kernel_act_as(struct cred *new, u32 secid) |
1470 | { | 1503 | { |
1471 | struct task_smack *new_tsp = new->security; | 1504 | struct task_smack *new_tsp = new->security; |
1472 | char *smack = smack_from_secid(secid); | 1505 | struct smack_known *skp = smack_from_secid(secid); |
1473 | 1506 | ||
1474 | if (smack == NULL) | 1507 | if (skp == NULL) |
1475 | return -EINVAL; | 1508 | return -EINVAL; |
1476 | 1509 | ||
1477 | new_tsp->smk_task = smack; | 1510 | new_tsp->smk_task = skp; |
1478 | return 0; | 1511 | return 0; |
1479 | } | 1512 | } |
1480 | 1513 | ||
@@ -1492,8 +1525,8 @@ static int smack_kernel_create_files_as(struct cred *new, | |||
1492 | struct inode_smack *isp = inode->i_security; | 1525 | struct inode_smack *isp = inode->i_security; |
1493 | struct task_smack *tsp = new->security; | 1526 | struct task_smack *tsp = new->security; |
1494 | 1527 | ||
1495 | tsp->smk_forked = isp->smk_inode; | 1528 | tsp->smk_forked = smk_find_entry(isp->smk_inode); |
1496 | tsp->smk_task = isp->smk_inode; | 1529 | tsp->smk_task = tsp->smk_forked; |
1497 | return 0; | 1530 | return 0; |
1498 | } | 1531 | } |
1499 | 1532 | ||
@@ -1509,10 +1542,11 @@ static int smk_curacc_on_task(struct task_struct *p, int access, | |||
1509 | const char *caller) | 1542 | const char *caller) |
1510 | { | 1543 | { |
1511 | struct smk_audit_info ad; | 1544 | struct smk_audit_info ad; |
1545 | struct smack_known *skp = smk_of_task(task_security(p)); | ||
1512 | 1546 | ||
1513 | smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK); | 1547 | smk_ad_init(&ad, caller, LSM_AUDIT_DATA_TASK); |
1514 | smk_ad_setfield_u_tsk(&ad, p); | 1548 | smk_ad_setfield_u_tsk(&ad, p); |
1515 | return smk_curacc(smk_of_task(task_security(p)), access, &ad); | 1549 | return smk_curacc(skp->smk_known, access, &ad); |
1516 | } | 1550 | } |
1517 | 1551 | ||
1518 | /** | 1552 | /** |
@@ -1558,7 +1592,9 @@ static int smack_task_getsid(struct task_struct *p) | |||
1558 | */ | 1592 | */ |
1559 | static void smack_task_getsecid(struct task_struct *p, u32 *secid) | 1593 | static void smack_task_getsecid(struct task_struct *p, u32 *secid) |
1560 | { | 1594 | { |
1561 | *secid = smack_to_secid(smk_of_task(task_security(p))); | 1595 | struct smack_known *skp = smk_of_task(task_security(p)); |
1596 | |||
1597 | *secid = skp->smk_secid; | ||
1562 | } | 1598 | } |
1563 | 1599 | ||
1564 | /** | 1600 | /** |
@@ -1662,6 +1698,8 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, | |||
1662 | int sig, u32 secid) | 1698 | int sig, u32 secid) |
1663 | { | 1699 | { |
1664 | struct smk_audit_info ad; | 1700 | struct smk_audit_info ad; |
1701 | struct smack_known *skp; | ||
1702 | struct smack_known *tkp = smk_of_task(task_security(p)); | ||
1665 | 1703 | ||
1666 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | 1704 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); |
1667 | smk_ad_setfield_u_tsk(&ad, p); | 1705 | smk_ad_setfield_u_tsk(&ad, p); |
@@ -1670,15 +1708,14 @@ static int smack_task_kill(struct task_struct *p, struct siginfo *info, | |||
1670 | * can write the receiver. | 1708 | * can write the receiver. |
1671 | */ | 1709 | */ |
1672 | if (secid == 0) | 1710 | if (secid == 0) |
1673 | return smk_curacc(smk_of_task(task_security(p)), MAY_WRITE, | 1711 | return smk_curacc(tkp->smk_known, MAY_WRITE, &ad); |
1674 | &ad); | ||
1675 | /* | 1712 | /* |
1676 | * If the secid isn't 0 we're dealing with some USB IO | 1713 | * If the secid isn't 0 we're dealing with some USB IO |
1677 | * specific behavior. This is not clean. For one thing | 1714 | * specific behavior. This is not clean. For one thing |
1678 | * we can't take privilege into account. | 1715 | * we can't take privilege into account. |
1679 | */ | 1716 | */ |
1680 | return smk_access(smack_from_secid(secid), | 1717 | skp = smack_from_secid(secid); |
1681 | smk_of_task(task_security(p)), MAY_WRITE, &ad); | 1718 | return smk_access(skp, tkp->smk_known, MAY_WRITE, &ad); |
1682 | } | 1719 | } |
1683 | 1720 | ||
1684 | /** | 1721 | /** |
@@ -1710,7 +1747,9 @@ static int smack_task_wait(struct task_struct *p) | |||
1710 | static void smack_task_to_inode(struct task_struct *p, struct inode *inode) | 1747 | static void smack_task_to_inode(struct task_struct *p, struct inode *inode) |
1711 | { | 1748 | { |
1712 | struct inode_smack *isp = inode->i_security; | 1749 | struct inode_smack *isp = inode->i_security; |
1713 | isp->smk_inode = smk_of_task(task_security(p)); | 1750 | struct smack_known *skp = smk_of_task(task_security(p)); |
1751 | |||
1752 | isp->smk_inode = skp->smk_known; | ||
1714 | } | 1753 | } |
1715 | 1754 | ||
1716 | /* | 1755 | /* |
@@ -1729,15 +1768,15 @@ static void smack_task_to_inode(struct task_struct *p, struct inode *inode) | |||
1729 | */ | 1768 | */ |
1730 | static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) | 1769 | static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) |
1731 | { | 1770 | { |
1732 | char *csp = smk_of_current(); | 1771 | struct smack_known *skp = smk_of_current(); |
1733 | struct socket_smack *ssp; | 1772 | struct socket_smack *ssp; |
1734 | 1773 | ||
1735 | ssp = kzalloc(sizeof(struct socket_smack), gfp_flags); | 1774 | ssp = kzalloc(sizeof(struct socket_smack), gfp_flags); |
1736 | if (ssp == NULL) | 1775 | if (ssp == NULL) |
1737 | return -ENOMEM; | 1776 | return -ENOMEM; |
1738 | 1777 | ||
1739 | ssp->smk_in = csp; | 1778 | ssp->smk_in = skp->smk_known; |
1740 | ssp->smk_out = csp; | 1779 | ssp->smk_out = skp; |
1741 | ssp->smk_packet = NULL; | 1780 | ssp->smk_packet = NULL; |
1742 | 1781 | ||
1743 | sk->sk_security = ssp; | 1782 | sk->sk_security = ssp; |
@@ -1824,7 +1863,7 @@ static int smack_netlabel(struct sock *sk, int labeled) | |||
1824 | labeled == SMACK_UNLABELED_SOCKET) | 1863 | labeled == SMACK_UNLABELED_SOCKET) |
1825 | netlbl_sock_delattr(sk); | 1864 | netlbl_sock_delattr(sk); |
1826 | else { | 1865 | else { |
1827 | skp = smk_find_entry(ssp->smk_out); | 1866 | skp = ssp->smk_out; |
1828 | rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel); | 1867 | rc = netlbl_sock_setattr(sk, sk->sk_family, &skp->smk_netlabel); |
1829 | } | 1868 | } |
1830 | 1869 | ||
@@ -1847,6 +1886,7 @@ static int smack_netlabel(struct sock *sk, int labeled) | |||
1847 | */ | 1886 | */ |
1848 | static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) | 1887 | static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) |
1849 | { | 1888 | { |
1889 | struct smack_known *skp; | ||
1850 | int rc; | 1890 | int rc; |
1851 | int sk_lbl; | 1891 | int sk_lbl; |
1852 | char *hostsp; | 1892 | char *hostsp; |
@@ -1865,7 +1905,8 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) | |||
1865 | ad.a.u.net->v4info.daddr = sap->sin_addr.s_addr; | 1905 | ad.a.u.net->v4info.daddr = sap->sin_addr.s_addr; |
1866 | #endif | 1906 | #endif |
1867 | sk_lbl = SMACK_UNLABELED_SOCKET; | 1907 | sk_lbl = SMACK_UNLABELED_SOCKET; |
1868 | rc = smk_access(ssp->smk_out, hostsp, MAY_WRITE, &ad); | 1908 | skp = ssp->smk_out; |
1909 | rc = smk_access(skp, hostsp, MAY_WRITE, &ad); | ||
1869 | } else { | 1910 | } else { |
1870 | sk_lbl = SMACK_CIPSO_SOCKET; | 1911 | sk_lbl = SMACK_CIPSO_SOCKET; |
1871 | rc = 0; | 1912 | rc = 0; |
@@ -1878,6 +1919,155 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) | |||
1878 | } | 1919 | } |
1879 | 1920 | ||
1880 | /** | 1921 | /** |
1922 | * smk_ipv6_port_label - Smack port access table management | ||
1923 | * @sock: socket | ||
1924 | * @address: address | ||
1925 | * | ||
1926 | * Create or update the port list entry | ||
1927 | */ | ||
1928 | static void smk_ipv6_port_label(struct socket *sock, struct sockaddr *address) | ||
1929 | { | ||
1930 | struct sock *sk = sock->sk; | ||
1931 | struct sockaddr_in6 *addr6; | ||
1932 | struct socket_smack *ssp = sock->sk->sk_security; | ||
1933 | struct smk_port_label *spp; | ||
1934 | unsigned short port = 0; | ||
1935 | |||
1936 | if (address == NULL) { | ||
1937 | /* | ||
1938 | * This operation is changing the Smack information | ||
1939 | * on the bound socket. Take the changes to the port | ||
1940 | * as well. | ||
1941 | */ | ||
1942 | list_for_each_entry(spp, &smk_ipv6_port_list, list) { | ||
1943 | if (sk != spp->smk_sock) | ||
1944 | continue; | ||
1945 | spp->smk_in = ssp->smk_in; | ||
1946 | spp->smk_out = ssp->smk_out; | ||
1947 | return; | ||
1948 | } | ||
1949 | /* | ||
1950 | * A NULL address is only used for updating existing | ||
1951 | * bound entries. If there isn't one, it's OK. | ||
1952 | */ | ||
1953 | return; | ||
1954 | } | ||
1955 | |||
1956 | addr6 = (struct sockaddr_in6 *)address; | ||
1957 | port = ntohs(addr6->sin6_port); | ||
1958 | /* | ||
1959 | * This is a special case that is safely ignored. | ||
1960 | */ | ||
1961 | if (port == 0) | ||
1962 | return; | ||
1963 | |||
1964 | /* | ||
1965 | * Look for an existing port list entry. | ||
1966 | * This is an indication that a port is getting reused. | ||
1967 | */ | ||
1968 | list_for_each_entry(spp, &smk_ipv6_port_list, list) { | ||
1969 | if (spp->smk_port != port) | ||
1970 | continue; | ||
1971 | spp->smk_port = port; | ||
1972 | spp->smk_sock = sk; | ||
1973 | spp->smk_in = ssp->smk_in; | ||
1974 | spp->smk_out = ssp->smk_out; | ||
1975 | return; | ||
1976 | } | ||
1977 | |||
1978 | /* | ||
1979 | * A new port entry is required. | ||
1980 | */ | ||
1981 | spp = kzalloc(sizeof(*spp), GFP_KERNEL); | ||
1982 | if (spp == NULL) | ||
1983 | return; | ||
1984 | |||
1985 | spp->smk_port = port; | ||
1986 | spp->smk_sock = sk; | ||
1987 | spp->smk_in = ssp->smk_in; | ||
1988 | spp->smk_out = ssp->smk_out; | ||
1989 | |||
1990 | list_add(&spp->list, &smk_ipv6_port_list); | ||
1991 | return; | ||
1992 | } | ||
1993 | |||
1994 | /** | ||
1995 | * smk_ipv6_port_check - check Smack port access | ||
1996 | * @sock: socket | ||
1997 | * @address: address | ||
1998 | * | ||
1999 | * Create or update the port list entry | ||
2000 | */ | ||
2001 | static int smk_ipv6_port_check(struct sock *sk, struct sockaddr *address, | ||
2002 | int act) | ||
2003 | { | ||
2004 | __be16 *bep; | ||
2005 | __be32 *be32p; | ||
2006 | struct sockaddr_in6 *addr6; | ||
2007 | struct smk_port_label *spp; | ||
2008 | struct socket_smack *ssp = sk->sk_security; | ||
2009 | struct smack_known *skp; | ||
2010 | unsigned short port = 0; | ||
2011 | char *object; | ||
2012 | struct smk_audit_info ad; | ||
2013 | #ifdef CONFIG_AUDIT | ||
2014 | struct lsm_network_audit net; | ||
2015 | #endif | ||
2016 | |||
2017 | if (act == SMK_RECEIVING) { | ||
2018 | skp = smack_net_ambient; | ||
2019 | object = ssp->smk_in; | ||
2020 | } else { | ||
2021 | skp = ssp->smk_out; | ||
2022 | object = smack_net_ambient->smk_known; | ||
2023 | } | ||
2024 | |||
2025 | /* | ||
2026 | * Get the IP address and port from the address. | ||
2027 | */ | ||
2028 | addr6 = (struct sockaddr_in6 *)address; | ||
2029 | port = ntohs(addr6->sin6_port); | ||
2030 | bep = (__be16 *)(&addr6->sin6_addr); | ||
2031 | be32p = (__be32 *)(&addr6->sin6_addr); | ||
2032 | |||
2033 | /* | ||
2034 | * It's remote, so port lookup does no good. | ||
2035 | */ | ||
2036 | if (be32p[0] || be32p[1] || be32p[2] || bep[6] || ntohs(bep[7]) != 1) | ||
2037 | goto auditout; | ||
2038 | |||
2039 | /* | ||
2040 | * It's local so the send check has to have passed. | ||
2041 | */ | ||
2042 | if (act == SMK_RECEIVING) { | ||
2043 | skp = &smack_known_web; | ||
2044 | goto auditout; | ||
2045 | } | ||
2046 | |||
2047 | list_for_each_entry(spp, &smk_ipv6_port_list, list) { | ||
2048 | if (spp->smk_port != port) | ||
2049 | continue; | ||
2050 | object = spp->smk_in; | ||
2051 | if (act == SMK_CONNECTING) | ||
2052 | ssp->smk_packet = spp->smk_out->smk_known; | ||
2053 | break; | ||
2054 | } | ||
2055 | |||
2056 | auditout: | ||
2057 | |||
2058 | #ifdef CONFIG_AUDIT | ||
2059 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); | ||
2060 | ad.a.u.net->family = sk->sk_family; | ||
2061 | ad.a.u.net->dport = port; | ||
2062 | if (act == SMK_RECEIVING) | ||
2063 | ad.a.u.net->v6info.saddr = addr6->sin6_addr; | ||
2064 | else | ||
2065 | ad.a.u.net->v6info.daddr = addr6->sin6_addr; | ||
2066 | #endif | ||
2067 | return smk_access(skp, object, MAY_WRITE, &ad); | ||
2068 | } | ||
2069 | |||
2070 | /** | ||
1881 | * smack_inode_setsecurity - set smack xattrs | 2071 | * smack_inode_setsecurity - set smack xattrs |
1882 | * @inode: the object | 2072 | * @inode: the object |
1883 | * @name: attribute name | 2073 | * @name: attribute name |
@@ -1892,7 +2082,7 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap) | |||
1892 | static int smack_inode_setsecurity(struct inode *inode, const char *name, | 2082 | static int smack_inode_setsecurity(struct inode *inode, const char *name, |
1893 | const void *value, size_t size, int flags) | 2083 | const void *value, size_t size, int flags) |
1894 | { | 2084 | { |
1895 | char *sp; | 2085 | struct smack_known *skp; |
1896 | struct inode_smack *nsp = inode->i_security; | 2086 | struct inode_smack *nsp = inode->i_security; |
1897 | struct socket_smack *ssp; | 2087 | struct socket_smack *ssp; |
1898 | struct socket *sock; | 2088 | struct socket *sock; |
@@ -1901,12 +2091,12 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, | |||
1901 | if (value == NULL || size > SMK_LONGLABEL || size == 0) | 2091 | if (value == NULL || size > SMK_LONGLABEL || size == 0) |
1902 | return -EACCES; | 2092 | return -EACCES; |
1903 | 2093 | ||
1904 | sp = smk_import(value, size); | 2094 | skp = smk_import_entry(value, size); |
1905 | if (sp == NULL) | 2095 | if (skp == NULL) |
1906 | return -EINVAL; | 2096 | return -EINVAL; |
1907 | 2097 | ||
1908 | if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { | 2098 | if (strcmp(name, XATTR_SMACK_SUFFIX) == 0) { |
1909 | nsp->smk_inode = sp; | 2099 | nsp->smk_inode = skp->smk_known; |
1910 | nsp->smk_flags |= SMK_INODE_INSTANT; | 2100 | nsp->smk_flags |= SMK_INODE_INSTANT; |
1911 | return 0; | 2101 | return 0; |
1912 | } | 2102 | } |
@@ -1923,10 +2113,10 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, | |||
1923 | ssp = sock->sk->sk_security; | 2113 | ssp = sock->sk->sk_security; |
1924 | 2114 | ||
1925 | if (strcmp(name, XATTR_SMACK_IPIN) == 0) | 2115 | if (strcmp(name, XATTR_SMACK_IPIN) == 0) |
1926 | ssp->smk_in = sp; | 2116 | ssp->smk_in = skp->smk_known; |
1927 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { | 2117 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { |
1928 | ssp->smk_out = sp; | 2118 | ssp->smk_out = skp; |
1929 | if (sock->sk->sk_family != PF_UNIX) { | 2119 | if (sock->sk->sk_family == PF_INET) { |
1930 | rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); | 2120 | rc = smack_netlabel(sock->sk, SMACK_CIPSO_SOCKET); |
1931 | if (rc != 0) | 2121 | if (rc != 0) |
1932 | printk(KERN_WARNING | 2122 | printk(KERN_WARNING |
@@ -1936,6 +2126,9 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, | |||
1936 | } else | 2126 | } else |
1937 | return -EOPNOTSUPP; | 2127 | return -EOPNOTSUPP; |
1938 | 2128 | ||
2129 | if (sock->sk->sk_family == PF_INET6) | ||
2130 | smk_ipv6_port_label(sock, NULL); | ||
2131 | |||
1939 | return 0; | 2132 | return 0; |
1940 | } | 2133 | } |
1941 | 2134 | ||
@@ -1963,6 +2156,25 @@ static int smack_socket_post_create(struct socket *sock, int family, | |||
1963 | } | 2156 | } |
1964 | 2157 | ||
1965 | /** | 2158 | /** |
2159 | * smack_socket_bind - record port binding information. | ||
2160 | * @sock: the socket | ||
2161 | * @address: the port address | ||
2162 | * @addrlen: size of the address | ||
2163 | * | ||
2164 | * Records the label bound to a port. | ||
2165 | * | ||
2166 | * Returns 0 | ||
2167 | */ | ||
2168 | static int smack_socket_bind(struct socket *sock, struct sockaddr *address, | ||
2169 | int addrlen) | ||
2170 | { | ||
2171 | if (sock->sk != NULL && sock->sk->sk_family == PF_INET6) | ||
2172 | smk_ipv6_port_label(sock, address); | ||
2173 | |||
2174 | return 0; | ||
2175 | } | ||
2176 | |||
2177 | /** | ||
1966 | * smack_socket_connect - connect access check | 2178 | * smack_socket_connect - connect access check |
1967 | * @sock: the socket | 2179 | * @sock: the socket |
1968 | * @sap: the other end | 2180 | * @sap: the other end |
@@ -1975,12 +2187,24 @@ static int smack_socket_post_create(struct socket *sock, int family, | |||
1975 | static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, | 2187 | static int smack_socket_connect(struct socket *sock, struct sockaddr *sap, |
1976 | int addrlen) | 2188 | int addrlen) |
1977 | { | 2189 | { |
1978 | if (sock->sk == NULL || sock->sk->sk_family != PF_INET) | 2190 | int rc = 0; |
2191 | |||
2192 | if (sock->sk == NULL) | ||
1979 | return 0; | 2193 | return 0; |
1980 | if (addrlen < sizeof(struct sockaddr_in)) | ||
1981 | return -EINVAL; | ||
1982 | 2194 | ||
1983 | return smack_netlabel_send(sock->sk, (struct sockaddr_in *)sap); | 2195 | switch (sock->sk->sk_family) { |
2196 | case PF_INET: | ||
2197 | if (addrlen < sizeof(struct sockaddr_in)) | ||
2198 | return -EINVAL; | ||
2199 | rc = smack_netlabel_send(sock->sk, (struct sockaddr_in *)sap); | ||
2200 | break; | ||
2201 | case PF_INET6: | ||
2202 | if (addrlen < sizeof(struct sockaddr_in6)) | ||
2203 | return -EINVAL; | ||
2204 | rc = smk_ipv6_port_check(sock->sk, sap, SMK_CONNECTING); | ||
2205 | break; | ||
2206 | } | ||
2207 | return rc; | ||
1984 | } | 2208 | } |
1985 | 2209 | ||
1986 | /** | 2210 | /** |
@@ -2011,7 +2235,9 @@ static int smack_flags_to_may(int flags) | |||
2011 | */ | 2235 | */ |
2012 | static int smack_msg_msg_alloc_security(struct msg_msg *msg) | 2236 | static int smack_msg_msg_alloc_security(struct msg_msg *msg) |
2013 | { | 2237 | { |
2014 | msg->security = smk_of_current(); | 2238 | struct smack_known *skp = smk_of_current(); |
2239 | |||
2240 | msg->security = skp->smk_known; | ||
2015 | return 0; | 2241 | return 0; |
2016 | } | 2242 | } |
2017 | 2243 | ||
@@ -2046,8 +2272,9 @@ static char *smack_of_shm(struct shmid_kernel *shp) | |||
2046 | static int smack_shm_alloc_security(struct shmid_kernel *shp) | 2272 | static int smack_shm_alloc_security(struct shmid_kernel *shp) |
2047 | { | 2273 | { |
2048 | struct kern_ipc_perm *isp = &shp->shm_perm; | 2274 | struct kern_ipc_perm *isp = &shp->shm_perm; |
2275 | struct smack_known *skp = smk_of_current(); | ||
2049 | 2276 | ||
2050 | isp->security = smk_of_current(); | 2277 | isp->security = skp->smk_known; |
2051 | return 0; | 2278 | return 0; |
2052 | } | 2279 | } |
2053 | 2280 | ||
@@ -2169,8 +2396,9 @@ static char *smack_of_sem(struct sem_array *sma) | |||
2169 | static int smack_sem_alloc_security(struct sem_array *sma) | 2396 | static int smack_sem_alloc_security(struct sem_array *sma) |
2170 | { | 2397 | { |
2171 | struct kern_ipc_perm *isp = &sma->sem_perm; | 2398 | struct kern_ipc_perm *isp = &sma->sem_perm; |
2399 | struct smack_known *skp = smk_of_current(); | ||
2172 | 2400 | ||
2173 | isp->security = smk_of_current(); | 2401 | isp->security = skp->smk_known; |
2174 | return 0; | 2402 | return 0; |
2175 | } | 2403 | } |
2176 | 2404 | ||
@@ -2287,8 +2515,9 @@ static int smack_sem_semop(struct sem_array *sma, struct sembuf *sops, | |||
2287 | static int smack_msg_queue_alloc_security(struct msg_queue *msq) | 2515 | static int smack_msg_queue_alloc_security(struct msg_queue *msq) |
2288 | { | 2516 | { |
2289 | struct kern_ipc_perm *kisp = &msq->q_perm; | 2517 | struct kern_ipc_perm *kisp = &msq->q_perm; |
2518 | struct smack_known *skp = smk_of_current(); | ||
2290 | 2519 | ||
2291 | kisp->security = smk_of_current(); | 2520 | kisp->security = skp->smk_known; |
2292 | return 0; | 2521 | return 0; |
2293 | } | 2522 | } |
2294 | 2523 | ||
@@ -2460,8 +2689,8 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2460 | struct super_block *sbp; | 2689 | struct super_block *sbp; |
2461 | struct superblock_smack *sbsp; | 2690 | struct superblock_smack *sbsp; |
2462 | struct inode_smack *isp; | 2691 | struct inode_smack *isp; |
2463 | char *csp = smk_of_current(); | 2692 | struct smack_known *skp; |
2464 | char *fetched; | 2693 | struct smack_known *ckp = smk_of_current(); |
2465 | char *final; | 2694 | char *final; |
2466 | char trattr[TRANS_TRUE_SIZE]; | 2695 | char trattr[TRANS_TRUE_SIZE]; |
2467 | int transflag = 0; | 2696 | int transflag = 0; |
@@ -2528,7 +2757,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2528 | * Programs that change smack have to treat the | 2757 | * Programs that change smack have to treat the |
2529 | * pty with respect. | 2758 | * pty with respect. |
2530 | */ | 2759 | */ |
2531 | final = csp; | 2760 | final = ckp->smk_known; |
2532 | break; | 2761 | break; |
2533 | case SOCKFS_MAGIC: | 2762 | case SOCKFS_MAGIC: |
2534 | /* | 2763 | /* |
@@ -2583,9 +2812,9 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2583 | * Get the dentry for xattr. | 2812 | * Get the dentry for xattr. |
2584 | */ | 2813 | */ |
2585 | dp = dget(opt_dentry); | 2814 | dp = dget(opt_dentry); |
2586 | fetched = smk_fetch(XATTR_NAME_SMACK, inode, dp); | 2815 | skp = smk_fetch(XATTR_NAME_SMACK, inode, dp); |
2587 | if (fetched != NULL) | 2816 | if (skp != NULL) |
2588 | final = fetched; | 2817 | final = skp->smk_known; |
2589 | 2818 | ||
2590 | /* | 2819 | /* |
2591 | * Transmuting directory | 2820 | * Transmuting directory |
@@ -2625,7 +2854,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2625 | } | 2854 | } |
2626 | 2855 | ||
2627 | if (final == NULL) | 2856 | if (final == NULL) |
2628 | isp->smk_inode = csp; | 2857 | isp->smk_inode = ckp->smk_known; |
2629 | else | 2858 | else |
2630 | isp->smk_inode = final; | 2859 | isp->smk_inode = final; |
2631 | 2860 | ||
@@ -2648,13 +2877,14 @@ unlockandout: | |||
2648 | */ | 2877 | */ |
2649 | static int smack_getprocattr(struct task_struct *p, char *name, char **value) | 2878 | static int smack_getprocattr(struct task_struct *p, char *name, char **value) |
2650 | { | 2879 | { |
2880 | struct smack_known *skp = smk_of_task(task_security(p)); | ||
2651 | char *cp; | 2881 | char *cp; |
2652 | int slen; | 2882 | int slen; |
2653 | 2883 | ||
2654 | if (strcmp(name, "current") != 0) | 2884 | if (strcmp(name, "current") != 0) |
2655 | return -EINVAL; | 2885 | return -EINVAL; |
2656 | 2886 | ||
2657 | cp = kstrdup(smk_of_task(task_security(p)), GFP_KERNEL); | 2887 | cp = kstrdup(skp->smk_known, GFP_KERNEL); |
2658 | if (cp == NULL) | 2888 | if (cp == NULL) |
2659 | return -ENOMEM; | 2889 | return -ENOMEM; |
2660 | 2890 | ||
@@ -2680,7 +2910,7 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
2680 | { | 2910 | { |
2681 | struct task_smack *tsp; | 2911 | struct task_smack *tsp; |
2682 | struct cred *new; | 2912 | struct cred *new; |
2683 | char *newsmack; | 2913 | struct smack_known *skp; |
2684 | 2914 | ||
2685 | /* | 2915 | /* |
2686 | * Changing another process' Smack value is too dangerous | 2916 | * Changing another process' Smack value is too dangerous |
@@ -2698,14 +2928,14 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
2698 | if (strcmp(name, "current") != 0) | 2928 | if (strcmp(name, "current") != 0) |
2699 | return -EINVAL; | 2929 | return -EINVAL; |
2700 | 2930 | ||
2701 | newsmack = smk_import(value, size); | 2931 | skp = smk_import_entry(value, size); |
2702 | if (newsmack == NULL) | 2932 | if (skp == NULL) |
2703 | return -EINVAL; | 2933 | return -EINVAL; |
2704 | 2934 | ||
2705 | /* | 2935 | /* |
2706 | * No process is ever allowed the web ("@") label. | 2936 | * No process is ever allowed the web ("@") label. |
2707 | */ | 2937 | */ |
2708 | if (newsmack == smack_known_web.smk_known) | 2938 | if (skp == &smack_known_web) |
2709 | return -EPERM; | 2939 | return -EPERM; |
2710 | 2940 | ||
2711 | new = prepare_creds(); | 2941 | new = prepare_creds(); |
@@ -2713,7 +2943,7 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
2713 | return -ENOMEM; | 2943 | return -ENOMEM; |
2714 | 2944 | ||
2715 | tsp = new->security; | 2945 | tsp = new->security; |
2716 | tsp->smk_task = newsmack; | 2946 | tsp->smk_task = skp; |
2717 | 2947 | ||
2718 | commit_creds(new); | 2948 | commit_creds(new); |
2719 | return size; | 2949 | return size; |
@@ -2731,6 +2961,7 @@ static int smack_setprocattr(struct task_struct *p, char *name, | |||
2731 | static int smack_unix_stream_connect(struct sock *sock, | 2961 | static int smack_unix_stream_connect(struct sock *sock, |
2732 | struct sock *other, struct sock *newsk) | 2962 | struct sock *other, struct sock *newsk) |
2733 | { | 2963 | { |
2964 | struct smack_known *skp; | ||
2734 | struct socket_smack *ssp = sock->sk_security; | 2965 | struct socket_smack *ssp = sock->sk_security; |
2735 | struct socket_smack *osp = other->sk_security; | 2966 | struct socket_smack *osp = other->sk_security; |
2736 | struct socket_smack *nsp = newsk->sk_security; | 2967 | struct socket_smack *nsp = newsk->sk_security; |
@@ -2744,15 +2975,17 @@ static int smack_unix_stream_connect(struct sock *sock, | |||
2744 | smk_ad_setfield_u_net_sk(&ad, other); | 2975 | smk_ad_setfield_u_net_sk(&ad, other); |
2745 | #endif | 2976 | #endif |
2746 | 2977 | ||
2747 | if (!smack_privileged(CAP_MAC_OVERRIDE)) | 2978 | if (!smack_privileged(CAP_MAC_OVERRIDE)) { |
2748 | rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); | 2979 | skp = ssp->smk_out; |
2980 | rc = smk_access(skp, osp->smk_in, MAY_WRITE, &ad); | ||
2981 | } | ||
2749 | 2982 | ||
2750 | /* | 2983 | /* |
2751 | * Cross reference the peer labels for SO_PEERSEC. | 2984 | * Cross reference the peer labels for SO_PEERSEC. |
2752 | */ | 2985 | */ |
2753 | if (rc == 0) { | 2986 | if (rc == 0) { |
2754 | nsp->smk_packet = ssp->smk_out; | 2987 | nsp->smk_packet = ssp->smk_out->smk_known; |
2755 | ssp->smk_packet = osp->smk_out; | 2988 | ssp->smk_packet = osp->smk_out->smk_known; |
2756 | } | 2989 | } |
2757 | 2990 | ||
2758 | return rc; | 2991 | return rc; |
@@ -2770,8 +3003,8 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) | |||
2770 | { | 3003 | { |
2771 | struct socket_smack *ssp = sock->sk->sk_security; | 3004 | struct socket_smack *ssp = sock->sk->sk_security; |
2772 | struct socket_smack *osp = other->sk->sk_security; | 3005 | struct socket_smack *osp = other->sk->sk_security; |
3006 | struct smack_known *skp; | ||
2773 | struct smk_audit_info ad; | 3007 | struct smk_audit_info ad; |
2774 | int rc = 0; | ||
2775 | 3008 | ||
2776 | #ifdef CONFIG_AUDIT | 3009 | #ifdef CONFIG_AUDIT |
2777 | struct lsm_network_audit net; | 3010 | struct lsm_network_audit net; |
@@ -2780,10 +3013,11 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) | |||
2780 | smk_ad_setfield_u_net_sk(&ad, other->sk); | 3013 | smk_ad_setfield_u_net_sk(&ad, other->sk); |
2781 | #endif | 3014 | #endif |
2782 | 3015 | ||
2783 | if (!smack_privileged(CAP_MAC_OVERRIDE)) | 3016 | if (smack_privileged(CAP_MAC_OVERRIDE)) |
2784 | rc = smk_access(ssp->smk_out, osp->smk_in, MAY_WRITE, &ad); | 3017 | return 0; |
2785 | 3018 | ||
2786 | return rc; | 3019 | skp = ssp->smk_out; |
3020 | return smk_access(skp, osp->smk_in, MAY_WRITE, &ad); | ||
2787 | } | 3021 | } |
2788 | 3022 | ||
2789 | /** | 3023 | /** |
@@ -2792,22 +3026,32 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) | |||
2792 | * @msg: the message | 3026 | * @msg: the message |
2793 | * @size: the size of the message | 3027 | * @size: the size of the message |
2794 | * | 3028 | * |
2795 | * Return 0 if the current subject can write to the destination | 3029 | * Return 0 if the current subject can write to the destination host. |
2796 | * host. This is only a question if the destination is a single | 3030 | * For IPv4 this is only a question if the destination is a single label host. |
2797 | * label host. | 3031 | * For IPv6 this is a check against the label of the port. |
2798 | */ | 3032 | */ |
2799 | static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, | 3033 | static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, |
2800 | int size) | 3034 | int size) |
2801 | { | 3035 | { |
2802 | struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name; | 3036 | struct sockaddr_in *sip = (struct sockaddr_in *) msg->msg_name; |
3037 | struct sockaddr *sap = (struct sockaddr *) msg->msg_name; | ||
3038 | int rc = 0; | ||
2803 | 3039 | ||
2804 | /* | 3040 | /* |
2805 | * Perfectly reasonable for this to be NULL | 3041 | * Perfectly reasonable for this to be NULL |
2806 | */ | 3042 | */ |
2807 | if (sip == NULL || sip->sin_family != AF_INET) | 3043 | if (sip == NULL) |
2808 | return 0; | 3044 | return 0; |
2809 | 3045 | ||
2810 | return smack_netlabel_send(sock->sk, sip); | 3046 | switch (sip->sin_family) { |
3047 | case AF_INET: | ||
3048 | rc = smack_netlabel_send(sock->sk, sip); | ||
3049 | break; | ||
3050 | case AF_INET6: | ||
3051 | rc = smk_ipv6_port_check(sock->sk, sap, SMK_SENDING); | ||
3052 | break; | ||
3053 | } | ||
3054 | return rc; | ||
2811 | } | 3055 | } |
2812 | 3056 | ||
2813 | /** | 3057 | /** |
@@ -2815,13 +3059,12 @@ static int smack_socket_sendmsg(struct socket *sock, struct msghdr *msg, | |||
2815 | * @sap: netlabel secattr | 3059 | * @sap: netlabel secattr |
2816 | * @ssp: socket security information | 3060 | * @ssp: socket security information |
2817 | * | 3061 | * |
2818 | * Returns a pointer to a Smack label found on the label list. | 3062 | * Returns a pointer to a Smack label entry found on the label list. |
2819 | */ | 3063 | */ |
2820 | static char *smack_from_secattr(struct netlbl_lsm_secattr *sap, | 3064 | static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap, |
2821 | struct socket_smack *ssp) | 3065 | struct socket_smack *ssp) |
2822 | { | 3066 | { |
2823 | struct smack_known *kp; | 3067 | struct smack_known *skp; |
2824 | char *sp; | ||
2825 | int found = 0; | 3068 | int found = 0; |
2826 | 3069 | ||
2827 | if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) { | 3070 | if ((sap->flags & NETLBL_SECATTR_MLS_LVL) != 0) { |
@@ -2836,11 +3079,11 @@ static char *smack_from_secattr(struct netlbl_lsm_secattr *sap, | |||
2836 | * ambient value. | 3079 | * ambient value. |
2837 | */ | 3080 | */ |
2838 | rcu_read_lock(); | 3081 | rcu_read_lock(); |
2839 | list_for_each_entry(kp, &smack_known_list, list) { | 3082 | list_for_each_entry(skp, &smack_known_list, list) { |
2840 | if (sap->attr.mls.lvl != kp->smk_netlabel.attr.mls.lvl) | 3083 | if (sap->attr.mls.lvl != skp->smk_netlabel.attr.mls.lvl) |
2841 | continue; | 3084 | continue; |
2842 | if (memcmp(sap->attr.mls.cat, | 3085 | if (memcmp(sap->attr.mls.cat, |
2843 | kp->smk_netlabel.attr.mls.cat, | 3086 | skp->smk_netlabel.attr.mls.cat, |
2844 | SMK_CIPSOLEN) != 0) | 3087 | SMK_CIPSOLEN) != 0) |
2845 | continue; | 3088 | continue; |
2846 | found = 1; | 3089 | found = 1; |
@@ -2849,17 +3092,17 @@ static char *smack_from_secattr(struct netlbl_lsm_secattr *sap, | |||
2849 | rcu_read_unlock(); | 3092 | rcu_read_unlock(); |
2850 | 3093 | ||
2851 | if (found) | 3094 | if (found) |
2852 | return kp->smk_known; | 3095 | return skp; |
2853 | 3096 | ||
2854 | if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known) | 3097 | if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known) |
2855 | return smack_known_web.smk_known; | 3098 | return &smack_known_web; |
2856 | return smack_known_star.smk_known; | 3099 | return &smack_known_star; |
2857 | } | 3100 | } |
2858 | if ((sap->flags & NETLBL_SECATTR_SECID) != 0) { | 3101 | if ((sap->flags & NETLBL_SECATTR_SECID) != 0) { |
2859 | /* | 3102 | /* |
2860 | * Looks like a fallback, which gives us a secid. | 3103 | * Looks like a fallback, which gives us a secid. |
2861 | */ | 3104 | */ |
2862 | sp = smack_from_secid(sap->attr.secid); | 3105 | skp = smack_from_secid(sap->attr.secid); |
2863 | /* | 3106 | /* |
2864 | * This has got to be a bug because it is | 3107 | * This has got to be a bug because it is |
2865 | * impossible to specify a fallback without | 3108 | * impossible to specify a fallback without |
@@ -2867,8 +3110,8 @@ static char *smack_from_secattr(struct netlbl_lsm_secattr *sap, | |||
2867 | * it has a secid, and the only way to get a | 3110 | * it has a secid, and the only way to get a |
2868 | * secid is from a fallback. | 3111 | * secid is from a fallback. |
2869 | */ | 3112 | */ |
2870 | BUG_ON(sp == NULL); | 3113 | BUG_ON(skp == NULL); |
2871 | return sp; | 3114 | return skp; |
2872 | } | 3115 | } |
2873 | /* | 3116 | /* |
2874 | * Without guidance regarding the smack value | 3117 | * Without guidance regarding the smack value |
@@ -2878,6 +3121,54 @@ static char *smack_from_secattr(struct netlbl_lsm_secattr *sap, | |||
2878 | return smack_net_ambient; | 3121 | return smack_net_ambient; |
2879 | } | 3122 | } |
2880 | 3123 | ||
3124 | static int smk_skb_to_addr_ipv6(struct sk_buff *skb, struct sockaddr *sap) | ||
3125 | { | ||
3126 | struct sockaddr_in6 *sip = (struct sockaddr_in6 *)sap; | ||
3127 | u8 nexthdr; | ||
3128 | int offset; | ||
3129 | int proto = -EINVAL; | ||
3130 | struct ipv6hdr _ipv6h; | ||
3131 | struct ipv6hdr *ip6; | ||
3132 | __be16 frag_off; | ||
3133 | struct tcphdr _tcph, *th; | ||
3134 | struct udphdr _udph, *uh; | ||
3135 | struct dccp_hdr _dccph, *dh; | ||
3136 | |||
3137 | sip->sin6_port = 0; | ||
3138 | |||
3139 | offset = skb_network_offset(skb); | ||
3140 | ip6 = skb_header_pointer(skb, offset, sizeof(_ipv6h), &_ipv6h); | ||
3141 | if (ip6 == NULL) | ||
3142 | return -EINVAL; | ||
3143 | sip->sin6_addr = ip6->saddr; | ||
3144 | |||
3145 | nexthdr = ip6->nexthdr; | ||
3146 | offset += sizeof(_ipv6h); | ||
3147 | offset = ipv6_skip_exthdr(skb, offset, &nexthdr, &frag_off); | ||
3148 | if (offset < 0) | ||
3149 | return -EINVAL; | ||
3150 | |||
3151 | proto = nexthdr; | ||
3152 | switch (proto) { | ||
3153 | case IPPROTO_TCP: | ||
3154 | th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph); | ||
3155 | if (th != NULL) | ||
3156 | sip->sin6_port = th->source; | ||
3157 | break; | ||
3158 | case IPPROTO_UDP: | ||
3159 | uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph); | ||
3160 | if (uh != NULL) | ||
3161 | sip->sin6_port = uh->source; | ||
3162 | break; | ||
3163 | case IPPROTO_DCCP: | ||
3164 | dh = skb_header_pointer(skb, offset, sizeof(_dccph), &_dccph); | ||
3165 | if (dh != NULL) | ||
3166 | sip->sin6_port = dh->dccph_sport; | ||
3167 | break; | ||
3168 | } | ||
3169 | return proto; | ||
3170 | } | ||
3171 | |||
2881 | /** | 3172 | /** |
2882 | * smack_socket_sock_rcv_skb - Smack packet delivery access check | 3173 | * smack_socket_sock_rcv_skb - Smack packet delivery access check |
2883 | * @sk: socket | 3174 | * @sk: socket |
@@ -2889,43 +3180,52 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
2889 | { | 3180 | { |
2890 | struct netlbl_lsm_secattr secattr; | 3181 | struct netlbl_lsm_secattr secattr; |
2891 | struct socket_smack *ssp = sk->sk_security; | 3182 | struct socket_smack *ssp = sk->sk_security; |
2892 | char *csp; | 3183 | struct smack_known *skp; |
2893 | int rc; | 3184 | struct sockaddr sadd; |
3185 | int rc = 0; | ||
2894 | struct smk_audit_info ad; | 3186 | struct smk_audit_info ad; |
2895 | #ifdef CONFIG_AUDIT | 3187 | #ifdef CONFIG_AUDIT |
2896 | struct lsm_network_audit net; | 3188 | struct lsm_network_audit net; |
2897 | #endif | 3189 | #endif |
2898 | if (sk->sk_family != PF_INET && sk->sk_family != PF_INET6) | 3190 | switch (sk->sk_family) { |
2899 | return 0; | 3191 | case PF_INET: |
2900 | 3192 | /* | |
2901 | /* | 3193 | * Translate what netlabel gave us. |
2902 | * Translate what netlabel gave us. | 3194 | */ |
2903 | */ | 3195 | netlbl_secattr_init(&secattr); |
2904 | netlbl_secattr_init(&secattr); | ||
2905 | 3196 | ||
2906 | rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr); | 3197 | rc = netlbl_skbuff_getattr(skb, sk->sk_family, &secattr); |
2907 | if (rc == 0) | 3198 | if (rc == 0) |
2908 | csp = smack_from_secattr(&secattr, ssp); | 3199 | skp = smack_from_secattr(&secattr, ssp); |
2909 | else | 3200 | else |
2910 | csp = smack_net_ambient; | 3201 | skp = smack_net_ambient; |
2911 | 3202 | ||
2912 | netlbl_secattr_destroy(&secattr); | 3203 | netlbl_secattr_destroy(&secattr); |
2913 | 3204 | ||
2914 | #ifdef CONFIG_AUDIT | 3205 | #ifdef CONFIG_AUDIT |
2915 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); | 3206 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); |
2916 | ad.a.u.net->family = sk->sk_family; | 3207 | ad.a.u.net->family = sk->sk_family; |
2917 | ad.a.u.net->netif = skb->skb_iif; | 3208 | ad.a.u.net->netif = skb->skb_iif; |
2918 | ipv4_skb_to_auditdata(skb, &ad.a, NULL); | 3209 | ipv4_skb_to_auditdata(skb, &ad.a, NULL); |
2919 | #endif | 3210 | #endif |
2920 | /* | 3211 | /* |
2921 | * Receiving a packet requires that the other end | 3212 | * Receiving a packet requires that the other end |
2922 | * be able to write here. Read access is not required. | 3213 | * be able to write here. Read access is not required. |
2923 | * This is the simplist possible security model | 3214 | * This is the simplist possible security model |
2924 | * for networking. | 3215 | * for networking. |
2925 | */ | 3216 | */ |
2926 | rc = smk_access(csp, ssp->smk_in, MAY_WRITE, &ad); | 3217 | rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); |
2927 | if (rc != 0) | 3218 | if (rc != 0) |
2928 | netlbl_skbuff_err(skb, rc, 0); | 3219 | netlbl_skbuff_err(skb, rc, 0); |
3220 | break; | ||
3221 | case PF_INET6: | ||
3222 | rc = smk_skb_to_addr_ipv6(skb, &sadd); | ||
3223 | if (rc == IPPROTO_UDP || rc == IPPROTO_TCP) | ||
3224 | rc = smk_ipv6_port_check(sk, &sadd, SMK_RECEIVING); | ||
3225 | else | ||
3226 | rc = 0; | ||
3227 | break; | ||
3228 | } | ||
2929 | return rc; | 3229 | return rc; |
2930 | } | 3230 | } |
2931 | 3231 | ||
@@ -2979,7 +3279,7 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, | |||
2979 | { | 3279 | { |
2980 | struct netlbl_lsm_secattr secattr; | 3280 | struct netlbl_lsm_secattr secattr; |
2981 | struct socket_smack *ssp = NULL; | 3281 | struct socket_smack *ssp = NULL; |
2982 | char *sp; | 3282 | struct smack_known *skp; |
2983 | int family = PF_UNSPEC; | 3283 | int family = PF_UNSPEC; |
2984 | u32 s = 0; /* 0 is the invalid secid */ | 3284 | u32 s = 0; /* 0 is the invalid secid */ |
2985 | int rc; | 3285 | int rc; |
@@ -2995,7 +3295,7 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, | |||
2995 | 3295 | ||
2996 | if (family == PF_UNIX) { | 3296 | if (family == PF_UNIX) { |
2997 | ssp = sock->sk->sk_security; | 3297 | ssp = sock->sk->sk_security; |
2998 | s = smack_to_secid(ssp->smk_out); | 3298 | s = ssp->smk_out->smk_secid; |
2999 | } else if (family == PF_INET || family == PF_INET6) { | 3299 | } else if (family == PF_INET || family == PF_INET6) { |
3000 | /* | 3300 | /* |
3001 | * Translate what netlabel gave us. | 3301 | * Translate what netlabel gave us. |
@@ -3005,8 +3305,8 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, | |||
3005 | netlbl_secattr_init(&secattr); | 3305 | netlbl_secattr_init(&secattr); |
3006 | rc = netlbl_skbuff_getattr(skb, family, &secattr); | 3306 | rc = netlbl_skbuff_getattr(skb, family, &secattr); |
3007 | if (rc == 0) { | 3307 | if (rc == 0) { |
3008 | sp = smack_from_secattr(&secattr, ssp); | 3308 | skp = smack_from_secattr(&secattr, ssp); |
3009 | s = smack_to_secid(sp); | 3309 | s = skp->smk_secid; |
3010 | } | 3310 | } |
3011 | netlbl_secattr_destroy(&secattr); | 3311 | netlbl_secattr_destroy(&secattr); |
3012 | } | 3312 | } |
@@ -3027,13 +3327,15 @@ static int smack_socket_getpeersec_dgram(struct socket *sock, | |||
3027 | static void smack_sock_graft(struct sock *sk, struct socket *parent) | 3327 | static void smack_sock_graft(struct sock *sk, struct socket *parent) |
3028 | { | 3328 | { |
3029 | struct socket_smack *ssp; | 3329 | struct socket_smack *ssp; |
3330 | struct smack_known *skp = smk_of_current(); | ||
3030 | 3331 | ||
3031 | if (sk == NULL || | 3332 | if (sk == NULL || |
3032 | (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)) | 3333 | (sk->sk_family != PF_INET && sk->sk_family != PF_INET6)) |
3033 | return; | 3334 | return; |
3034 | 3335 | ||
3035 | ssp = sk->sk_security; | 3336 | ssp = sk->sk_security; |
3036 | ssp->smk_in = ssp->smk_out = smk_of_current(); | 3337 | ssp->smk_in = skp->smk_known; |
3338 | ssp->smk_out = skp; | ||
3037 | /* cssp->smk_packet is already set in smack_inet_csk_clone() */ | 3339 | /* cssp->smk_packet is already set in smack_inet_csk_clone() */ |
3038 | } | 3340 | } |
3039 | 3341 | ||
@@ -3055,7 +3357,6 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3055 | struct netlbl_lsm_secattr secattr; | 3357 | struct netlbl_lsm_secattr secattr; |
3056 | struct sockaddr_in addr; | 3358 | struct sockaddr_in addr; |
3057 | struct iphdr *hdr; | 3359 | struct iphdr *hdr; |
3058 | char *sp; | ||
3059 | char *hsp; | 3360 | char *hsp; |
3060 | int rc; | 3361 | int rc; |
3061 | struct smk_audit_info ad; | 3362 | struct smk_audit_info ad; |
@@ -3063,16 +3364,24 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3063 | struct lsm_network_audit net; | 3364 | struct lsm_network_audit net; |
3064 | #endif | 3365 | #endif |
3065 | 3366 | ||
3066 | /* handle mapped IPv4 packets arriving via IPv6 sockets */ | 3367 | if (family == PF_INET6) { |
3067 | if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) | 3368 | /* |
3068 | family = PF_INET; | 3369 | * Handle mapped IPv4 packets arriving |
3370 | * via IPv6 sockets. Don't set up netlabel | ||
3371 | * processing on IPv6. | ||
3372 | */ | ||
3373 | if (skb->protocol == htons(ETH_P_IP)) | ||
3374 | family = PF_INET; | ||
3375 | else | ||
3376 | return 0; | ||
3377 | } | ||
3069 | 3378 | ||
3070 | netlbl_secattr_init(&secattr); | 3379 | netlbl_secattr_init(&secattr); |
3071 | rc = netlbl_skbuff_getattr(skb, family, &secattr); | 3380 | rc = netlbl_skbuff_getattr(skb, family, &secattr); |
3072 | if (rc == 0) | 3381 | if (rc == 0) |
3073 | sp = smack_from_secattr(&secattr, ssp); | 3382 | skp = smack_from_secattr(&secattr, ssp); |
3074 | else | 3383 | else |
3075 | sp = smack_known_huh.smk_known; | 3384 | skp = &smack_known_huh; |
3076 | netlbl_secattr_destroy(&secattr); | 3385 | netlbl_secattr_destroy(&secattr); |
3077 | 3386 | ||
3078 | #ifdef CONFIG_AUDIT | 3387 | #ifdef CONFIG_AUDIT |
@@ -3085,7 +3394,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3085 | * Receiving a packet requires that the other end be able to write | 3394 | * Receiving a packet requires that the other end be able to write |
3086 | * here. Read access is not required. | 3395 | * here. Read access is not required. |
3087 | */ | 3396 | */ |
3088 | rc = smk_access(sp, ssp->smk_in, MAY_WRITE, &ad); | 3397 | rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); |
3089 | if (rc != 0) | 3398 | if (rc != 0) |
3090 | return rc; | 3399 | return rc; |
3091 | 3400 | ||
@@ -3093,7 +3402,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3093 | * Save the peer's label in the request_sock so we can later setup | 3402 | * Save the peer's label in the request_sock so we can later setup |
3094 | * smk_packet in the child socket so that SO_PEERCRED can report it. | 3403 | * smk_packet in the child socket so that SO_PEERCRED can report it. |
3095 | */ | 3404 | */ |
3096 | req->peer_secid = smack_to_secid(sp); | 3405 | req->peer_secid = skp->smk_secid; |
3097 | 3406 | ||
3098 | /* | 3407 | /* |
3099 | * We need to decide if we want to label the incoming connection here | 3408 | * We need to decide if we want to label the incoming connection here |
@@ -3106,10 +3415,9 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3106 | hsp = smack_host_label(&addr); | 3415 | hsp = smack_host_label(&addr); |
3107 | rcu_read_unlock(); | 3416 | rcu_read_unlock(); |
3108 | 3417 | ||
3109 | if (hsp == NULL) { | 3418 | if (hsp == NULL) |
3110 | skp = smk_find_entry(sp); | ||
3111 | rc = netlbl_req_setattr(req, &skp->smk_netlabel); | 3419 | rc = netlbl_req_setattr(req, &skp->smk_netlabel); |
3112 | } else | 3420 | else |
3113 | netlbl_req_delattr(req); | 3421 | netlbl_req_delattr(req); |
3114 | 3422 | ||
3115 | return rc; | 3423 | return rc; |
@@ -3126,10 +3434,12 @@ static void smack_inet_csk_clone(struct sock *sk, | |||
3126 | const struct request_sock *req) | 3434 | const struct request_sock *req) |
3127 | { | 3435 | { |
3128 | struct socket_smack *ssp = sk->sk_security; | 3436 | struct socket_smack *ssp = sk->sk_security; |
3437 | struct smack_known *skp; | ||
3129 | 3438 | ||
3130 | if (req->peer_secid != 0) | 3439 | if (req->peer_secid != 0) { |
3131 | ssp->smk_packet = smack_from_secid(req->peer_secid); | 3440 | skp = smack_from_secid(req->peer_secid); |
3132 | else | 3441 | ssp->smk_packet = skp->smk_known; |
3442 | } else | ||
3133 | ssp->smk_packet = NULL; | 3443 | ssp->smk_packet = NULL; |
3134 | } | 3444 | } |
3135 | 3445 | ||
@@ -3155,7 +3465,9 @@ static void smack_inet_csk_clone(struct sock *sk, | |||
3155 | static int smack_key_alloc(struct key *key, const struct cred *cred, | 3465 | static int smack_key_alloc(struct key *key, const struct cred *cred, |
3156 | unsigned long flags) | 3466 | unsigned long flags) |
3157 | { | 3467 | { |
3158 | key->security = smk_of_task(cred->security); | 3468 | struct smack_known *skp = smk_of_task(cred->security); |
3469 | |||
3470 | key->security = skp->smk_known; | ||
3159 | return 0; | 3471 | return 0; |
3160 | } | 3472 | } |
3161 | 3473 | ||
@@ -3184,7 +3496,7 @@ static int smack_key_permission(key_ref_t key_ref, | |||
3184 | { | 3496 | { |
3185 | struct key *keyp; | 3497 | struct key *keyp; |
3186 | struct smk_audit_info ad; | 3498 | struct smk_audit_info ad; |
3187 | char *tsp = smk_of_task(cred->security); | 3499 | struct smack_known *tkp = smk_of_task(cred->security); |
3188 | 3500 | ||
3189 | keyp = key_ref_to_ptr(key_ref); | 3501 | keyp = key_ref_to_ptr(key_ref); |
3190 | if (keyp == NULL) | 3502 | if (keyp == NULL) |
@@ -3198,15 +3510,14 @@ static int smack_key_permission(key_ref_t key_ref, | |||
3198 | /* | 3510 | /* |
3199 | * This should not occur | 3511 | * This should not occur |
3200 | */ | 3512 | */ |
3201 | if (tsp == NULL) | 3513 | if (tkp == NULL) |
3202 | return -EACCES; | 3514 | return -EACCES; |
3203 | #ifdef CONFIG_AUDIT | 3515 | #ifdef CONFIG_AUDIT |
3204 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_KEY); | 3516 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_KEY); |
3205 | ad.a.u.key_struct.key = keyp->serial; | 3517 | ad.a.u.key_struct.key = keyp->serial; |
3206 | ad.a.u.key_struct.key_desc = keyp->description; | 3518 | ad.a.u.key_struct.key_desc = keyp->description; |
3207 | #endif | 3519 | #endif |
3208 | return smk_access(tsp, keyp->security, | 3520 | return smk_access(tkp, keyp->security, MAY_READWRITE, &ad); |
3209 | MAY_READWRITE, &ad); | ||
3210 | } | 3521 | } |
3211 | #endif /* CONFIG_KEYS */ | 3522 | #endif /* CONFIG_KEYS */ |
3212 | 3523 | ||
@@ -3288,7 +3599,7 @@ static int smack_audit_rule_known(struct audit_krule *krule) | |||
3288 | static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule, | 3599 | static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule, |
3289 | struct audit_context *actx) | 3600 | struct audit_context *actx) |
3290 | { | 3601 | { |
3291 | char *smack; | 3602 | struct smack_known *skp; |
3292 | char *rule = vrule; | 3603 | char *rule = vrule; |
3293 | 3604 | ||
3294 | if (!rule) { | 3605 | if (!rule) { |
@@ -3300,7 +3611,7 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule, | |||
3300 | if (field != AUDIT_SUBJ_USER && field != AUDIT_OBJ_USER) | 3611 | if (field != AUDIT_SUBJ_USER && field != AUDIT_OBJ_USER) |
3301 | return 0; | 3612 | return 0; |
3302 | 3613 | ||
3303 | smack = smack_from_secid(secid); | 3614 | skp = smack_from_secid(secid); |
3304 | 3615 | ||
3305 | /* | 3616 | /* |
3306 | * No need to do string comparisons. If a match occurs, | 3617 | * No need to do string comparisons. If a match occurs, |
@@ -3308,9 +3619,9 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule, | |||
3308 | * label. | 3619 | * label. |
3309 | */ | 3620 | */ |
3310 | if (op == Audit_equal) | 3621 | if (op == Audit_equal) |
3311 | return (rule == smack); | 3622 | return (rule == skp->smk_known); |
3312 | if (op == Audit_not_equal) | 3623 | if (op == Audit_not_equal) |
3313 | return (rule != smack); | 3624 | return (rule != skp->smk_known); |
3314 | 3625 | ||
3315 | return 0; | 3626 | return 0; |
3316 | } | 3627 | } |
@@ -3338,11 +3649,11 @@ static void smack_audit_rule_free(void *vrule) | |||
3338 | */ | 3649 | */ |
3339 | static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) | 3650 | static int smack_secid_to_secctx(u32 secid, char **secdata, u32 *seclen) |
3340 | { | 3651 | { |
3341 | char *sp = smack_from_secid(secid); | 3652 | struct smack_known *skp = smack_from_secid(secid); |
3342 | 3653 | ||
3343 | if (secdata) | 3654 | if (secdata) |
3344 | *secdata = sp; | 3655 | *secdata = skp->smk_known; |
3345 | *seclen = strlen(sp); | 3656 | *seclen = strlen(skp->smk_known); |
3346 | return 0; | 3657 | return 0; |
3347 | } | 3658 | } |
3348 | 3659 | ||
@@ -3498,6 +3809,7 @@ struct security_operations smack_ops = { | |||
3498 | .unix_may_send = smack_unix_may_send, | 3809 | .unix_may_send = smack_unix_may_send, |
3499 | 3810 | ||
3500 | .socket_post_create = smack_socket_post_create, | 3811 | .socket_post_create = smack_socket_post_create, |
3812 | .socket_bind = smack_socket_bind, | ||
3501 | .socket_connect = smack_socket_connect, | 3813 | .socket_connect = smack_socket_connect, |
3502 | .socket_sendmsg = smack_socket_sendmsg, | 3814 | .socket_sendmsg = smack_socket_sendmsg, |
3503 | .socket_sock_rcv_skb = smack_socket_sock_rcv_skb, | 3815 | .socket_sock_rcv_skb = smack_socket_sock_rcv_skb, |
@@ -3577,8 +3889,8 @@ static __init int smack_init(void) | |||
3577 | if (!security_module_enable(&smack_ops)) | 3889 | if (!security_module_enable(&smack_ops)) |
3578 | return 0; | 3890 | return 0; |
3579 | 3891 | ||
3580 | tsp = new_task_smack(smack_known_floor.smk_known, | 3892 | tsp = new_task_smack(&smack_known_floor, &smack_known_floor, |
3581 | smack_known_floor.smk_known, GFP_KERNEL); | 3893 | GFP_KERNEL); |
3582 | if (tsp == NULL) | 3894 | if (tsp == NULL) |
3583 | return -ENOMEM; | 3895 | return -ENOMEM; |
3584 | 3896 | ||