diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-10 13:05:36 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-10 13:05:36 -0400 |
commit | fad0701eaa091beb8ce5ef2eef04b5e833617368 (patch) | |
tree | 788297c7b05b167599265013ef8ec473a0d367fe /security/smack/smack_lsm.c | |
parent | d53b47c08d8fda1892f47393de8eeab4e34b3188 (diff) | |
parent | f9b2a735bdddf836214b5dca74f6ca7712e5a08c (diff) |
Merge branch 'serge-next-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sergeh/linux-security
Pull security layer updates from Serge Hallyn:
"This is a merge of James Morris' security-next tree from 3.14 to
yesterday's master, plus four patches from Paul Moore which are in
linux-next, plus one patch from Mimi"
* 'serge-next-1' of git://git.kernel.org/pub/scm/linux/kernel/git/sergeh/linux-security:
ima: audit log files opened with O_DIRECT flag
selinux: conditionally reschedule in hashtab_insert while loading selinux policy
selinux: conditionally reschedule in mls_convert_context while loading selinux policy
selinux: reject setexeccon() on MNT_NOSUID applications with -EACCES
selinux: Report permissive mode in avc: denied messages.
Warning in scanf string typing
Smack: Label cgroup files for systemd
Smack: Verify read access on file open - v3
security: Convert use of typedef ctl_table to struct ctl_table
Smack: bidirectional UDS connect check
Smack: Correctly remove SMACK64TRANSMUTE attribute
SMACK: Fix handling value==NULL in post setxattr
bugfix patch for SMACK
Smack: adds smackfs/ptrace interface
Smack: unify all ptrace accesses in the smack
Smack: fix the subject/object order in smack_ptrace_traceme()
Minor improvement of 'smack_sb_kern_mount'
smack: fix key permission verification
KEYS: Move the flags representing required permission to linux/key.h
Diffstat (limited to 'security/smack/smack_lsm.c')
-rw-r--r-- | security/smack/smack_lsm.c | 249 |
1 files changed, 186 insertions, 63 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 14f52be78c75..f2c30801ce41 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c | |||
@@ -157,6 +157,74 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead, | |||
157 | return rc; | 157 | return rc; |
158 | } | 158 | } |
159 | 159 | ||
160 | /** | ||
161 | * smk_ptrace_mode - helper function for converting PTRACE_MODE_* into MAY_* | ||
162 | * @mode - input mode in form of PTRACE_MODE_* | ||
163 | * | ||
164 | * Returns a converted MAY_* mode usable by smack rules | ||
165 | */ | ||
166 | static inline unsigned int smk_ptrace_mode(unsigned int mode) | ||
167 | { | ||
168 | switch (mode) { | ||
169 | case PTRACE_MODE_READ: | ||
170 | return MAY_READ; | ||
171 | case PTRACE_MODE_ATTACH: | ||
172 | return MAY_READWRITE; | ||
173 | } | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | /** | ||
179 | * smk_ptrace_rule_check - helper for ptrace access | ||
180 | * @tracer: tracer process | ||
181 | * @tracee_label: label of the process that's about to be traced, | ||
182 | * the pointer must originate from smack structures | ||
183 | * @mode: ptrace attachment mode (PTRACE_MODE_*) | ||
184 | * @func: name of the function that called us, used for audit | ||
185 | * | ||
186 | * Returns 0 on access granted, -error on error | ||
187 | */ | ||
188 | static int smk_ptrace_rule_check(struct task_struct *tracer, char *tracee_label, | ||
189 | unsigned int mode, const char *func) | ||
190 | { | ||
191 | int rc; | ||
192 | struct smk_audit_info ad, *saip = NULL; | ||
193 | struct task_smack *tsp; | ||
194 | struct smack_known *skp; | ||
195 | |||
196 | if ((mode & PTRACE_MODE_NOAUDIT) == 0) { | ||
197 | smk_ad_init(&ad, func, LSM_AUDIT_DATA_TASK); | ||
198 | smk_ad_setfield_u_tsk(&ad, tracer); | ||
199 | saip = &ad; | ||
200 | } | ||
201 | |||
202 | tsp = task_security(tracer); | ||
203 | skp = smk_of_task(tsp); | ||
204 | |||
205 | if ((mode & PTRACE_MODE_ATTACH) && | ||
206 | (smack_ptrace_rule == SMACK_PTRACE_EXACT || | ||
207 | smack_ptrace_rule == SMACK_PTRACE_DRACONIAN)) { | ||
208 | if (skp->smk_known == tracee_label) | ||
209 | rc = 0; | ||
210 | else if (smack_ptrace_rule == SMACK_PTRACE_DRACONIAN) | ||
211 | rc = -EACCES; | ||
212 | else if (capable(CAP_SYS_PTRACE)) | ||
213 | rc = 0; | ||
214 | else | ||
215 | rc = -EACCES; | ||
216 | |||
217 | if (saip) | ||
218 | smack_log(skp->smk_known, tracee_label, 0, rc, saip); | ||
219 | |||
220 | return rc; | ||
221 | } | ||
222 | |||
223 | /* In case of rule==SMACK_PTRACE_DEFAULT or mode==PTRACE_MODE_READ */ | ||
224 | rc = smk_tskacc(tsp, tracee_label, smk_ptrace_mode(mode), saip); | ||
225 | return rc; | ||
226 | } | ||
227 | |||
160 | /* | 228 | /* |
161 | * LSM hooks. | 229 | * LSM hooks. |
162 | * We he, that is fun! | 230 | * We he, that is fun! |
@@ -165,16 +233,15 @@ static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead, | |||
165 | /** | 233 | /** |
166 | * smack_ptrace_access_check - Smack approval on PTRACE_ATTACH | 234 | * smack_ptrace_access_check - Smack approval on PTRACE_ATTACH |
167 | * @ctp: child task pointer | 235 | * @ctp: child task pointer |
168 | * @mode: ptrace attachment mode | 236 | * @mode: ptrace attachment mode (PTRACE_MODE_*) |
169 | * | 237 | * |
170 | * Returns 0 if access is OK, an error code otherwise | 238 | * Returns 0 if access is OK, an error code otherwise |
171 | * | 239 | * |
172 | * Do the capability checks, and require read and write. | 240 | * Do the capability checks. |
173 | */ | 241 | */ |
174 | static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) | 242 | static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) |
175 | { | 243 | { |
176 | int rc; | 244 | int rc; |
177 | struct smk_audit_info ad; | ||
178 | struct smack_known *skp; | 245 | struct smack_known *skp; |
179 | 246 | ||
180 | rc = cap_ptrace_access_check(ctp, mode); | 247 | rc = cap_ptrace_access_check(ctp, mode); |
@@ -182,10 +249,8 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) | |||
182 | return rc; | 249 | return rc; |
183 | 250 | ||
184 | skp = smk_of_task(task_security(ctp)); | 251 | skp = smk_of_task(task_security(ctp)); |
185 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | ||
186 | smk_ad_setfield_u_tsk(&ad, ctp); | ||
187 | 252 | ||
188 | rc = smk_curacc(skp->smk_known, mode, &ad); | 253 | rc = smk_ptrace_rule_check(current, skp->smk_known, mode, __func__); |
189 | return rc; | 254 | return rc; |
190 | } | 255 | } |
191 | 256 | ||
@@ -195,23 +260,21 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode) | |||
195 | * | 260 | * |
196 | * Returns 0 if access is OK, an error code otherwise | 261 | * Returns 0 if access is OK, an error code otherwise |
197 | * | 262 | * |
198 | * Do the capability checks, and require read and write. | 263 | * Do the capability checks, and require PTRACE_MODE_ATTACH. |
199 | */ | 264 | */ |
200 | static int smack_ptrace_traceme(struct task_struct *ptp) | 265 | static int smack_ptrace_traceme(struct task_struct *ptp) |
201 | { | 266 | { |
202 | int rc; | 267 | int rc; |
203 | struct smk_audit_info ad; | ||
204 | struct smack_known *skp; | 268 | struct smack_known *skp; |
205 | 269 | ||
206 | rc = cap_ptrace_traceme(ptp); | 270 | rc = cap_ptrace_traceme(ptp); |
207 | if (rc != 0) | 271 | if (rc != 0) |
208 | return rc; | 272 | return rc; |
209 | 273 | ||
210 | skp = smk_of_task(task_security(ptp)); | 274 | skp = smk_of_task(current_security()); |
211 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); | ||
212 | smk_ad_setfield_u_tsk(&ad, ptp); | ||
213 | 275 | ||
214 | rc = smk_curacc(skp->smk_known, MAY_READWRITE, &ad); | 276 | rc = smk_ptrace_rule_check(ptp, skp->smk_known, |
277 | PTRACE_MODE_ATTACH, __func__); | ||
215 | return rc; | 278 | return rc; |
216 | } | 279 | } |
217 | 280 | ||
@@ -413,9 +476,11 @@ static int smack_sb_kern_mount(struct super_block *sb, int flags, void *data) | |||
413 | * Initialize the root inode. | 476 | * Initialize the root inode. |
414 | */ | 477 | */ |
415 | isp = inode->i_security; | 478 | isp = inode->i_security; |
416 | if (inode->i_security == NULL) { | 479 | if (isp == NULL) { |
417 | inode->i_security = new_inode_smack(sp->smk_root); | 480 | isp = new_inode_smack(sp->smk_root); |
418 | isp = inode->i_security; | 481 | if (isp == NULL) |
482 | return -ENOMEM; | ||
483 | inode->i_security = isp; | ||
419 | } else | 484 | } else |
420 | isp->smk_inode = sp->smk_root; | 485 | isp->smk_inode = sp->smk_root; |
421 | 486 | ||
@@ -453,7 +518,7 @@ static int smack_sb_statfs(struct dentry *dentry) | |||
453 | * smack_bprm_set_creds - set creds for exec | 518 | * smack_bprm_set_creds - set creds for exec |
454 | * @bprm: the exec information | 519 | * @bprm: the exec information |
455 | * | 520 | * |
456 | * Returns 0 if it gets a blob, -ENOMEM otherwise | 521 | * Returns 0 if it gets a blob, -EPERM if exec forbidden and -ENOMEM otherwise |
457 | */ | 522 | */ |
458 | static int smack_bprm_set_creds(struct linux_binprm *bprm) | 523 | static int smack_bprm_set_creds(struct linux_binprm *bprm) |
459 | { | 524 | { |
@@ -473,7 +538,22 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm) | |||
473 | if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task) | 538 | if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task) |
474 | return 0; | 539 | return 0; |
475 | 540 | ||
476 | if (bprm->unsafe) | 541 | if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) { |
542 | struct task_struct *tracer; | ||
543 | rc = 0; | ||
544 | |||
545 | rcu_read_lock(); | ||
546 | tracer = ptrace_parent(current); | ||
547 | if (likely(tracer != NULL)) | ||
548 | rc = smk_ptrace_rule_check(tracer, | ||
549 | isp->smk_task->smk_known, | ||
550 | PTRACE_MODE_ATTACH, | ||
551 | __func__); | ||
552 | rcu_read_unlock(); | ||
553 | |||
554 | if (rc != 0) | ||
555 | return rc; | ||
556 | } else if (bprm->unsafe) | ||
477 | return -EPERM; | 557 | return -EPERM; |
478 | 558 | ||
479 | bsp->smk_task = isp->smk_task; | 559 | bsp->smk_task = isp->smk_task; |
@@ -880,18 +960,20 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name, | |||
880 | return; | 960 | return; |
881 | } | 961 | } |
882 | 962 | ||
883 | skp = smk_import_entry(value, size); | ||
884 | if (strcmp(name, XATTR_NAME_SMACK) == 0) { | 963 | if (strcmp(name, XATTR_NAME_SMACK) == 0) { |
964 | skp = smk_import_entry(value, size); | ||
885 | if (skp != NULL) | 965 | if (skp != NULL) |
886 | isp->smk_inode = skp->smk_known; | 966 | isp->smk_inode = skp->smk_known; |
887 | else | 967 | else |
888 | isp->smk_inode = smack_known_invalid.smk_known; | 968 | isp->smk_inode = smack_known_invalid.smk_known; |
889 | } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { | 969 | } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { |
970 | skp = smk_import_entry(value, size); | ||
890 | if (skp != NULL) | 971 | if (skp != NULL) |
891 | isp->smk_task = skp; | 972 | isp->smk_task = skp; |
892 | else | 973 | else |
893 | isp->smk_task = &smack_known_invalid; | 974 | isp->smk_task = &smack_known_invalid; |
894 | } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { | 975 | } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { |
976 | skp = smk_import_entry(value, size); | ||
895 | if (skp != NULL) | 977 | if (skp != NULL) |
896 | isp->smk_mmap = skp; | 978 | isp->smk_mmap = skp; |
897 | else | 979 | else |
@@ -938,24 +1020,37 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) | |||
938 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || | 1020 | strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || |
939 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || | 1021 | strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || |
940 | strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 || | 1022 | strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 || |
941 | strcmp(name, XATTR_NAME_SMACKMMAP)) { | 1023 | strcmp(name, XATTR_NAME_SMACKMMAP) == 0) { |
942 | if (!smack_privileged(CAP_MAC_ADMIN)) | 1024 | if (!smack_privileged(CAP_MAC_ADMIN)) |
943 | rc = -EPERM; | 1025 | rc = -EPERM; |
944 | } else | 1026 | } else |
945 | rc = cap_inode_removexattr(dentry, name); | 1027 | rc = cap_inode_removexattr(dentry, name); |
946 | 1028 | ||
1029 | if (rc != 0) | ||
1030 | return rc; | ||
1031 | |||
947 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); | 1032 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY); |
948 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); | 1033 | smk_ad_setfield_u_fs_path_dentry(&ad, dentry); |
949 | if (rc == 0) | ||
950 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); | ||
951 | 1034 | ||
952 | if (rc == 0) { | 1035 | rc = smk_curacc(smk_of_inode(dentry->d_inode), MAY_WRITE, &ad); |
953 | isp = dentry->d_inode->i_security; | 1036 | if (rc != 0) |
1037 | return rc; | ||
1038 | |||
1039 | isp = dentry->d_inode->i_security; | ||
1040 | /* | ||
1041 | * Don't do anything special for these. | ||
1042 | * XATTR_NAME_SMACKIPIN | ||
1043 | * XATTR_NAME_SMACKIPOUT | ||
1044 | * XATTR_NAME_SMACKEXEC | ||
1045 | */ | ||
1046 | if (strcmp(name, XATTR_NAME_SMACK) == 0) | ||
954 | isp->smk_task = NULL; | 1047 | isp->smk_task = NULL; |
1048 | else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) | ||
955 | isp->smk_mmap = NULL; | 1049 | isp->smk_mmap = NULL; |
956 | } | 1050 | else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) |
1051 | isp->smk_flags &= ~SMK_INODE_TRANSMUTE; | ||
957 | 1052 | ||
958 | return rc; | 1053 | return 0; |
959 | } | 1054 | } |
960 | 1055 | ||
961 | /** | 1056 | /** |
@@ -1000,7 +1095,7 @@ static int smack_inode_getsecurity(const struct inode *inode, | |||
1000 | ssp = sock->sk->sk_security; | 1095 | ssp = sock->sk->sk_security; |
1001 | 1096 | ||
1002 | if (strcmp(name, XATTR_SMACK_IPIN) == 0) | 1097 | if (strcmp(name, XATTR_SMACK_IPIN) == 0) |
1003 | isp = ssp->smk_in; | 1098 | isp = ssp->smk_in->smk_known; |
1004 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) | 1099 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) |
1005 | isp = ssp->smk_out->smk_known; | 1100 | isp = ssp->smk_out->smk_known; |
1006 | else | 1101 | else |
@@ -1367,19 +1462,32 @@ static int smack_file_receive(struct file *file) | |||
1367 | /** | 1462 | /** |
1368 | * smack_file_open - Smack dentry open processing | 1463 | * smack_file_open - Smack dentry open processing |
1369 | * @file: the object | 1464 | * @file: the object |
1370 | * @cred: unused | 1465 | * @cred: task credential |
1371 | * | 1466 | * |
1372 | * Set the security blob in the file structure. | 1467 | * Set the security blob in the file structure. |
1468 | * Allow the open only if the task has read access. There are | ||
1469 | * many read operations (e.g. fstat) that you can do with an | ||
1470 | * fd even if you have the file open write-only. | ||
1373 | * | 1471 | * |
1374 | * Returns 0 | 1472 | * Returns 0 |
1375 | */ | 1473 | */ |
1376 | static int smack_file_open(struct file *file, const struct cred *cred) | 1474 | static int smack_file_open(struct file *file, const struct cred *cred) |
1377 | { | 1475 | { |
1476 | struct task_smack *tsp = cred->security; | ||
1378 | struct inode_smack *isp = file_inode(file)->i_security; | 1477 | struct inode_smack *isp = file_inode(file)->i_security; |
1478 | struct smk_audit_info ad; | ||
1479 | int rc; | ||
1379 | 1480 | ||
1380 | file->f_security = isp->smk_inode; | 1481 | if (smack_privileged(CAP_MAC_OVERRIDE)) |
1482 | return 0; | ||
1381 | 1483 | ||
1382 | return 0; | 1484 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_PATH); |
1485 | smk_ad_setfield_u_fs_path(&ad, file->f_path); | ||
1486 | rc = smk_access(tsp->smk_task, isp->smk_inode, MAY_READ, &ad); | ||
1487 | if (rc == 0) | ||
1488 | file->f_security = isp->smk_inode; | ||
1489 | |||
1490 | return rc; | ||
1383 | } | 1491 | } |
1384 | 1492 | ||
1385 | /* | 1493 | /* |
@@ -1764,7 +1872,7 @@ static int smack_sk_alloc_security(struct sock *sk, int family, gfp_t gfp_flags) | |||
1764 | if (ssp == NULL) | 1872 | if (ssp == NULL) |
1765 | return -ENOMEM; | 1873 | return -ENOMEM; |
1766 | 1874 | ||
1767 | ssp->smk_in = skp->smk_known; | 1875 | ssp->smk_in = skp; |
1768 | ssp->smk_out = skp; | 1876 | ssp->smk_out = skp; |
1769 | ssp->smk_packet = NULL; | 1877 | ssp->smk_packet = NULL; |
1770 | 1878 | ||
@@ -2004,7 +2112,7 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, | |||
2004 | 2112 | ||
2005 | if (act == SMK_RECEIVING) { | 2113 | if (act == SMK_RECEIVING) { |
2006 | skp = smack_net_ambient; | 2114 | skp = smack_net_ambient; |
2007 | object = ssp->smk_in; | 2115 | object = ssp->smk_in->smk_known; |
2008 | } else { | 2116 | } else { |
2009 | skp = ssp->smk_out; | 2117 | skp = ssp->smk_out; |
2010 | object = smack_net_ambient->smk_known; | 2118 | object = smack_net_ambient->smk_known; |
@@ -2034,9 +2142,9 @@ static int smk_ipv6_port_check(struct sock *sk, struct sockaddr_in6 *address, | |||
2034 | list_for_each_entry(spp, &smk_ipv6_port_list, list) { | 2142 | list_for_each_entry(spp, &smk_ipv6_port_list, list) { |
2035 | if (spp->smk_port != port) | 2143 | if (spp->smk_port != port) |
2036 | continue; | 2144 | continue; |
2037 | object = spp->smk_in; | 2145 | object = spp->smk_in->smk_known; |
2038 | if (act == SMK_CONNECTING) | 2146 | if (act == SMK_CONNECTING) |
2039 | ssp->smk_packet = spp->smk_out->smk_known; | 2147 | ssp->smk_packet = spp->smk_out; |
2040 | break; | 2148 | break; |
2041 | } | 2149 | } |
2042 | 2150 | ||
@@ -2076,7 +2184,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, | |||
2076 | int rc = 0; | 2184 | int rc = 0; |
2077 | 2185 | ||
2078 | if (value == NULL || size > SMK_LONGLABEL || size == 0) | 2186 | if (value == NULL || size > SMK_LONGLABEL || size == 0) |
2079 | return -EACCES; | 2187 | return -EINVAL; |
2080 | 2188 | ||
2081 | skp = smk_import_entry(value, size); | 2189 | skp = smk_import_entry(value, size); |
2082 | if (skp == NULL) | 2190 | if (skp == NULL) |
@@ -2100,7 +2208,7 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name, | |||
2100 | ssp = sock->sk->sk_security; | 2208 | ssp = sock->sk->sk_security; |
2101 | 2209 | ||
2102 | if (strcmp(name, XATTR_SMACK_IPIN) == 0) | 2210 | if (strcmp(name, XATTR_SMACK_IPIN) == 0) |
2103 | ssp->smk_in = skp->smk_known; | 2211 | ssp->smk_in = skp; |
2104 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { | 2212 | else if (strcmp(name, XATTR_SMACK_IPOUT) == 0) { |
2105 | ssp->smk_out = skp; | 2213 | ssp->smk_out = skp; |
2106 | if (sock->sk->sk_family == PF_INET) { | 2214 | if (sock->sk->sk_family == PF_INET) { |
@@ -2713,6 +2821,15 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2713 | * of the superblock. | 2821 | * of the superblock. |
2714 | */ | 2822 | */ |
2715 | if (opt_dentry->d_parent == opt_dentry) { | 2823 | if (opt_dentry->d_parent == opt_dentry) { |
2824 | if (sbp->s_magic == CGROUP_SUPER_MAGIC) { | ||
2825 | /* | ||
2826 | * The cgroup filesystem is never mounted, | ||
2827 | * so there's no opportunity to set the mount | ||
2828 | * options. | ||
2829 | */ | ||
2830 | sbsp->smk_root = smack_known_star.smk_known; | ||
2831 | sbsp->smk_default = smack_known_star.smk_known; | ||
2832 | } | ||
2716 | isp->smk_inode = sbsp->smk_root; | 2833 | isp->smk_inode = sbsp->smk_root; |
2717 | isp->smk_flags |= SMK_INODE_INSTANT; | 2834 | isp->smk_flags |= SMK_INODE_INSTANT; |
2718 | goto unlockandout; | 2835 | goto unlockandout; |
@@ -2726,16 +2843,20 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2726 | */ | 2843 | */ |
2727 | switch (sbp->s_magic) { | 2844 | switch (sbp->s_magic) { |
2728 | case SMACK_MAGIC: | 2845 | case SMACK_MAGIC: |
2846 | case PIPEFS_MAGIC: | ||
2847 | case SOCKFS_MAGIC: | ||
2848 | case CGROUP_SUPER_MAGIC: | ||
2729 | /* | 2849 | /* |
2730 | * Casey says that it's a little embarrassing | 2850 | * Casey says that it's a little embarrassing |
2731 | * that the smack file system doesn't do | 2851 | * that the smack file system doesn't do |
2732 | * extended attributes. | 2852 | * extended attributes. |
2733 | */ | 2853 | * |
2734 | final = smack_known_star.smk_known; | ||
2735 | break; | ||
2736 | case PIPEFS_MAGIC: | ||
2737 | /* | ||
2738 | * Casey says pipes are easy (?) | 2854 | * Casey says pipes are easy (?) |
2855 | * | ||
2856 | * Socket access is controlled by the socket | ||
2857 | * structures associated with the task involved. | ||
2858 | * | ||
2859 | * Cgroupfs is special | ||
2739 | */ | 2860 | */ |
2740 | final = smack_known_star.smk_known; | 2861 | final = smack_known_star.smk_known; |
2741 | break; | 2862 | break; |
@@ -2747,13 +2868,6 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode) | |||
2747 | */ | 2868 | */ |
2748 | final = ckp->smk_known; | 2869 | final = ckp->smk_known; |
2749 | break; | 2870 | break; |
2750 | case SOCKFS_MAGIC: | ||
2751 | /* | ||
2752 | * Socket access is controlled by the socket | ||
2753 | * structures associated with the task involved. | ||
2754 | */ | ||
2755 | final = smack_known_star.smk_known; | ||
2756 | break; | ||
2757 | case PROC_SUPER_MAGIC: | 2871 | case PROC_SUPER_MAGIC: |
2758 | /* | 2872 | /* |
2759 | * Casey says procfs appears not to care. | 2873 | * Casey says procfs appears not to care. |
@@ -2959,30 +3073,34 @@ static int smack_unix_stream_connect(struct sock *sock, | |||
2959 | struct sock *other, struct sock *newsk) | 3073 | struct sock *other, struct sock *newsk) |
2960 | { | 3074 | { |
2961 | struct smack_known *skp; | 3075 | struct smack_known *skp; |
3076 | struct smack_known *okp; | ||
2962 | struct socket_smack *ssp = sock->sk_security; | 3077 | struct socket_smack *ssp = sock->sk_security; |
2963 | struct socket_smack *osp = other->sk_security; | 3078 | struct socket_smack *osp = other->sk_security; |
2964 | struct socket_smack *nsp = newsk->sk_security; | 3079 | struct socket_smack *nsp = newsk->sk_security; |
2965 | struct smk_audit_info ad; | 3080 | struct smk_audit_info ad; |
2966 | int rc = 0; | 3081 | int rc = 0; |
2967 | |||
2968 | #ifdef CONFIG_AUDIT | 3082 | #ifdef CONFIG_AUDIT |
2969 | struct lsm_network_audit net; | 3083 | struct lsm_network_audit net; |
2970 | |||
2971 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); | ||
2972 | smk_ad_setfield_u_net_sk(&ad, other); | ||
2973 | #endif | 3084 | #endif |
2974 | 3085 | ||
2975 | if (!smack_privileged(CAP_MAC_OVERRIDE)) { | 3086 | if (!smack_privileged(CAP_MAC_OVERRIDE)) { |
2976 | skp = ssp->smk_out; | 3087 | skp = ssp->smk_out; |
2977 | rc = smk_access(skp, osp->smk_in, MAY_WRITE, &ad); | 3088 | okp = osp->smk_out; |
3089 | #ifdef CONFIG_AUDIT | ||
3090 | smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net); | ||
3091 | smk_ad_setfield_u_net_sk(&ad, other); | ||
3092 | #endif | ||
3093 | rc = smk_access(skp, okp->smk_known, MAY_WRITE, &ad); | ||
3094 | if (rc == 0) | ||
3095 | rc = smk_access(okp, okp->smk_known, MAY_WRITE, NULL); | ||
2978 | } | 3096 | } |
2979 | 3097 | ||
2980 | /* | 3098 | /* |
2981 | * Cross reference the peer labels for SO_PEERSEC. | 3099 | * Cross reference the peer labels for SO_PEERSEC. |
2982 | */ | 3100 | */ |
2983 | if (rc == 0) { | 3101 | if (rc == 0) { |
2984 | nsp->smk_packet = ssp->smk_out->smk_known; | 3102 | nsp->smk_packet = ssp->smk_out; |
2985 | ssp->smk_packet = osp->smk_out->smk_known; | 3103 | ssp->smk_packet = osp->smk_out; |
2986 | } | 3104 | } |
2987 | 3105 | ||
2988 | return rc; | 3106 | return rc; |
@@ -3014,7 +3132,7 @@ static int smack_unix_may_send(struct socket *sock, struct socket *other) | |||
3014 | return 0; | 3132 | return 0; |
3015 | 3133 | ||
3016 | skp = ssp->smk_out; | 3134 | skp = ssp->smk_out; |
3017 | return smk_access(skp, osp->smk_in, MAY_WRITE, &ad); | 3135 | return smk_access(skp, osp->smk_in->smk_known, MAY_WRITE, &ad); |
3018 | } | 3136 | } |
3019 | 3137 | ||
3020 | /** | 3138 | /** |
@@ -3109,7 +3227,7 @@ static struct smack_known *smack_from_secattr(struct netlbl_lsm_secattr *sap, | |||
3109 | if (found) | 3227 | if (found) |
3110 | return skp; | 3228 | return skp; |
3111 | 3229 | ||
3112 | if (ssp != NULL && ssp->smk_in == smack_known_star.smk_known) | 3230 | if (ssp != NULL && ssp->smk_in == &smack_known_star) |
3113 | return &smack_known_web; | 3231 | return &smack_known_web; |
3114 | return &smack_known_star; | 3232 | return &smack_known_star; |
3115 | } | 3233 | } |
@@ -3228,7 +3346,7 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
3228 | * This is the simplist possible security model | 3346 | * This is the simplist possible security model |
3229 | * for networking. | 3347 | * for networking. |
3230 | */ | 3348 | */ |
3231 | rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); | 3349 | rc = smk_access(skp, ssp->smk_in->smk_known, MAY_WRITE, &ad); |
3232 | if (rc != 0) | 3350 | if (rc != 0) |
3233 | netlbl_skbuff_err(skb, rc, 0); | 3351 | netlbl_skbuff_err(skb, rc, 0); |
3234 | break; | 3352 | break; |
@@ -3263,7 +3381,7 @@ static int smack_socket_getpeersec_stream(struct socket *sock, | |||
3263 | 3381 | ||
3264 | ssp = sock->sk->sk_security; | 3382 | ssp = sock->sk->sk_security; |
3265 | if (ssp->smk_packet != NULL) { | 3383 | if (ssp->smk_packet != NULL) { |
3266 | rcp = ssp->smk_packet; | 3384 | rcp = ssp->smk_packet->smk_known; |
3267 | slen = strlen(rcp) + 1; | 3385 | slen = strlen(rcp) + 1; |
3268 | } | 3386 | } |
3269 | 3387 | ||
@@ -3348,7 +3466,7 @@ static void smack_sock_graft(struct sock *sk, struct socket *parent) | |||
3348 | return; | 3466 | return; |
3349 | 3467 | ||
3350 | ssp = sk->sk_security; | 3468 | ssp = sk->sk_security; |
3351 | ssp->smk_in = skp->smk_known; | 3469 | ssp->smk_in = skp; |
3352 | ssp->smk_out = skp; | 3470 | ssp->smk_out = skp; |
3353 | /* cssp->smk_packet is already set in smack_inet_csk_clone() */ | 3471 | /* cssp->smk_packet is already set in smack_inet_csk_clone() */ |
3354 | } | 3472 | } |
@@ -3408,7 +3526,7 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
3408 | * Receiving a packet requires that the other end be able to write | 3526 | * Receiving a packet requires that the other end be able to write |
3409 | * here. Read access is not required. | 3527 | * here. Read access is not required. |
3410 | */ | 3528 | */ |
3411 | rc = smk_access(skp, ssp->smk_in, MAY_WRITE, &ad); | 3529 | rc = smk_access(skp, ssp->smk_in->smk_known, MAY_WRITE, &ad); |
3412 | if (rc != 0) | 3530 | if (rc != 0) |
3413 | return rc; | 3531 | return rc; |
3414 | 3532 | ||
@@ -3452,7 +3570,7 @@ static void smack_inet_csk_clone(struct sock *sk, | |||
3452 | 3570 | ||
3453 | if (req->peer_secid != 0) { | 3571 | if (req->peer_secid != 0) { |
3454 | skp = smack_from_secid(req->peer_secid); | 3572 | skp = smack_from_secid(req->peer_secid); |
3455 | ssp->smk_packet = skp->smk_known; | 3573 | ssp->smk_packet = skp; |
3456 | } else | 3574 | } else |
3457 | ssp->smk_packet = NULL; | 3575 | ssp->smk_packet = NULL; |
3458 | } | 3576 | } |
@@ -3506,11 +3624,12 @@ static void smack_key_free(struct key *key) | |||
3506 | * an error code otherwise | 3624 | * an error code otherwise |
3507 | */ | 3625 | */ |
3508 | static int smack_key_permission(key_ref_t key_ref, | 3626 | static int smack_key_permission(key_ref_t key_ref, |
3509 | const struct cred *cred, key_perm_t perm) | 3627 | const struct cred *cred, unsigned perm) |
3510 | { | 3628 | { |
3511 | struct key *keyp; | 3629 | struct key *keyp; |
3512 | struct smk_audit_info ad; | 3630 | struct smk_audit_info ad; |
3513 | struct smack_known *tkp = smk_of_task(cred->security); | 3631 | struct smack_known *tkp = smk_of_task(cred->security); |
3632 | int request = 0; | ||
3514 | 3633 | ||
3515 | keyp = key_ref_to_ptr(key_ref); | 3634 | keyp = key_ref_to_ptr(key_ref); |
3516 | if (keyp == NULL) | 3635 | if (keyp == NULL) |
@@ -3531,7 +3650,11 @@ static int smack_key_permission(key_ref_t key_ref, | |||
3531 | ad.a.u.key_struct.key = keyp->serial; | 3650 | ad.a.u.key_struct.key = keyp->serial; |
3532 | ad.a.u.key_struct.key_desc = keyp->description; | 3651 | ad.a.u.key_struct.key_desc = keyp->description; |
3533 | #endif | 3652 | #endif |
3534 | return smk_access(tkp, keyp->security, MAY_READWRITE, &ad); | 3653 | if (perm & KEY_NEED_READ) |
3654 | request = MAY_READ; | ||
3655 | if (perm & (KEY_NEED_WRITE | KEY_NEED_LINK | KEY_NEED_SETATTR)) | ||
3656 | request = MAY_WRITE; | ||
3657 | return smk_access(tkp, keyp->security, request, &ad); | ||
3535 | } | 3658 | } |
3536 | #endif /* CONFIG_KEYS */ | 3659 | #endif /* CONFIG_KEYS */ |
3537 | 3660 | ||