aboutsummaryrefslogtreecommitdiffstats
path: root/security/smack/smack_lsm.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/smack/smack_lsm.c')
-rw-r--r--security/smack/smack_lsm.c269
1 files changed, 227 insertions, 42 deletions
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 533bf3255d7..123a499ded3 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -84,6 +84,56 @@ struct inode_smack *new_inode_smack(char *smack)
84 return isp; 84 return isp;
85} 85}
86 86
87/**
88 * new_task_smack - allocate a task security blob
89 * @smack: a pointer to the Smack label to use in the blob
90 *
91 * Returns the new blob or NULL if there's no memory available
92 */
93static struct task_smack *new_task_smack(char *task, char *forked, gfp_t gfp)
94{
95 struct task_smack *tsp;
96
97 tsp = kzalloc(sizeof(struct task_smack), gfp);
98 if (tsp == NULL)
99 return NULL;
100
101 tsp->smk_task = task;
102 tsp->smk_forked = forked;
103 INIT_LIST_HEAD(&tsp->smk_rules);
104 mutex_init(&tsp->smk_rules_lock);
105
106 return tsp;
107}
108
109/**
110 * smk_copy_rules - copy a rule set
111 * @nhead - new rules header pointer
112 * @ohead - old rules header pointer
113 *
114 * Returns 0 on success, -ENOMEM on error
115 */
116static int smk_copy_rules(struct list_head *nhead, struct list_head *ohead,
117 gfp_t gfp)
118{
119 struct smack_rule *nrp;
120 struct smack_rule *orp;
121 int rc = 0;
122
123 INIT_LIST_HEAD(nhead);
124
125 list_for_each_entry_rcu(orp, ohead, list) {
126 nrp = kzalloc(sizeof(struct smack_rule), gfp);
127 if (nrp == NULL) {
128 rc = -ENOMEM;
129 break;
130 }
131 *nrp = *orp;
132 list_add_rcu(&nrp->list, nhead);
133 }
134 return rc;
135}
136
87/* 137/*
88 * LSM hooks. 138 * LSM hooks.
89 * We he, that is fun! 139 * We he, that is fun!
@@ -102,23 +152,17 @@ static int smack_ptrace_access_check(struct task_struct *ctp, unsigned int mode)
102{ 152{
103 int rc; 153 int rc;
104 struct smk_audit_info ad; 154 struct smk_audit_info ad;
105 char *sp, *tsp; 155 char *tsp;
106 156
107 rc = cap_ptrace_access_check(ctp, mode); 157 rc = cap_ptrace_access_check(ctp, mode);
108 if (rc != 0) 158 if (rc != 0)
109 return rc; 159 return rc;
110 160
111 sp = smk_of_current();
112 tsp = smk_of_task(task_security(ctp)); 161 tsp = smk_of_task(task_security(ctp));
113 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); 162 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
114 smk_ad_setfield_u_tsk(&ad, ctp); 163 smk_ad_setfield_u_tsk(&ad, ctp);
115 164
116 /* we won't log here, because rc can be overriden */ 165 rc = smk_curacc(tsp, MAY_READWRITE, &ad);
117 rc = smk_access(sp, tsp, MAY_READWRITE, NULL);
118 if (rc != 0 && capable(CAP_MAC_OVERRIDE))
119 rc = 0;
120
121 smack_log(sp, tsp, MAY_READWRITE, rc, &ad);
122 return rc; 166 return rc;
123} 167}
124 168
@@ -134,23 +178,17 @@ static int smack_ptrace_traceme(struct task_struct *ptp)
134{ 178{
135 int rc; 179 int rc;
136 struct smk_audit_info ad; 180 struct smk_audit_info ad;
137 char *sp, *tsp; 181 char *tsp;
138 182
139 rc = cap_ptrace_traceme(ptp); 183 rc = cap_ptrace_traceme(ptp);
140 if (rc != 0) 184 if (rc != 0)
141 return rc; 185 return rc;
142 186
187 tsp = smk_of_task(task_security(ptp));
143 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK); 188 smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_TASK);
144 smk_ad_setfield_u_tsk(&ad, ptp); 189 smk_ad_setfield_u_tsk(&ad, ptp);
145 190
146 sp = smk_of_current(); 191 rc = smk_curacc(tsp, MAY_READWRITE, &ad);
147 tsp = smk_of_task(task_security(ptp));
148 /* we won't log here, because rc can be overriden */
149 rc = smk_access(tsp, sp, MAY_READWRITE, NULL);
150 if (rc != 0 && has_capability(ptp, CAP_MAC_OVERRIDE))
151 rc = 0;
152
153 smack_log(tsp, sp, MAY_READWRITE, rc, &ad);
154 return rc; 192 return rc;
155} 193}
156 194
@@ -474,7 +512,7 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
474{ 512{
475 char *isp = smk_of_inode(inode); 513 char *isp = smk_of_inode(inode);
476 char *dsp = smk_of_inode(dir); 514 char *dsp = smk_of_inode(dir);
477 u32 may; 515 int may;
478 516
479 if (name) { 517 if (name) {
480 *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL); 518 *name = kstrdup(XATTR_SMACK_SUFFIX, GFP_KERNEL);
@@ -483,14 +521,17 @@ static int smack_inode_init_security(struct inode *inode, struct inode *dir,
483 } 521 }
484 522
485 if (value) { 523 if (value) {
486 may = smk_access_entry(smk_of_current(), dsp); 524 rcu_read_lock();
525 may = smk_access_entry(smk_of_current(), dsp, &smack_rule_list);
526 rcu_read_unlock();
487 527
488 /* 528 /*
489 * If the access rule allows transmutation and 529 * If the access rule allows transmutation and
490 * the directory requests transmutation then 530 * the directory requests transmutation then
491 * by all means transmute. 531 * by all means transmute.
492 */ 532 */
493 if (((may & MAY_TRANSMUTE) != 0) && smk_inode_transmutable(dir)) 533 if (may > 0 && ((may & MAY_TRANSMUTE) != 0) &&
534 smk_inode_transmutable(dir))
494 isp = dsp; 535 isp = dsp;
495 536
496 *value = kstrdup(isp, GFP_KERNEL); 537 *value = kstrdup(isp, GFP_KERNEL);
@@ -716,7 +757,8 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
716 if (strcmp(name, XATTR_NAME_SMACK) == 0 || 757 if (strcmp(name, XATTR_NAME_SMACK) == 0 ||
717 strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || 758 strcmp(name, XATTR_NAME_SMACKIPIN) == 0 ||
718 strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || 759 strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 ||
719 strcmp(name, XATTR_NAME_SMACKEXEC) == 0) { 760 strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
761 strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
720 if (!capable(CAP_MAC_ADMIN)) 762 if (!capable(CAP_MAC_ADMIN))
721 rc = -EPERM; 763 rc = -EPERM;
722 /* 764 /*
@@ -773,6 +815,12 @@ static void smack_inode_post_setxattr(struct dentry *dentry, const char *name,
773 isp->smk_task = nsp; 815 isp->smk_task = nsp;
774 else 816 else
775 isp->smk_task = smack_known_invalid.smk_known; 817 isp->smk_task = smack_known_invalid.smk_known;
818 } else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
819 nsp = smk_import(value, size);
820 if (nsp != NULL)
821 isp->smk_mmap = nsp;
822 else
823 isp->smk_mmap = smack_known_invalid.smk_known;
776 } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) 824 } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0)
777 isp->smk_flags |= SMK_INODE_TRANSMUTE; 825 isp->smk_flags |= SMK_INODE_TRANSMUTE;
778 826
@@ -815,7 +863,8 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
815 strcmp(name, XATTR_NAME_SMACKIPIN) == 0 || 863 strcmp(name, XATTR_NAME_SMACKIPIN) == 0 ||
816 strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 || 864 strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 ||
817 strcmp(name, XATTR_NAME_SMACKEXEC) == 0 || 865 strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
818 strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) { 866 strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0 ||
867 strcmp(name, XATTR_NAME_SMACKMMAP)) {
819 if (!capable(CAP_MAC_ADMIN)) 868 if (!capable(CAP_MAC_ADMIN))
820 rc = -EPERM; 869 rc = -EPERM;
821 } else 870 } else
@@ -829,6 +878,7 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name)
829 if (rc == 0) { 878 if (rc == 0) {
830 isp = dentry->d_inode->i_security; 879 isp = dentry->d_inode->i_security;
831 isp->smk_task = NULL; 880 isp->smk_task = NULL;
881 isp->smk_mmap = NULL;
832 } 882 }
833 883
834 return rc; 884 return rc;
@@ -1060,6 +1110,113 @@ static int smack_file_fcntl(struct file *file, unsigned int cmd,
1060} 1110}
1061 1111
1062/** 1112/**
1113 * smk_mmap_list_check - the mmap check
1114 * @sub: subject label
1115 * @obj: object label
1116 * @access: access mode
1117 * @local: the task specific rule list
1118 *
1119 * Returns 0 if acces is permitted, -EACCES otherwise
1120 */
1121static int smk_mmap_list_check(char *sub, char *obj, int access,
1122 struct list_head *local)
1123{
1124 int may;
1125
1126 /*
1127 * If there is not a global rule that
1128 * allows access say no.
1129 */
1130 may = smk_access_entry(sub, obj, &smack_rule_list);
1131 if (may == -ENOENT || (may & access) != access)
1132 return -EACCES;
1133 /*
1134 * If there is a task local rule that
1135 * denies access say no.
1136 */
1137 may = smk_access_entry(sub, obj, local);
1138 if (may != -ENOENT && (may & access) != access)
1139 return -EACCES;
1140
1141 return 0;
1142}
1143
1144/**
1145 * smack_file_mmap :
1146 * Check permissions for a mmap operation. The @file may be NULL, e.g.
1147 * if mapping anonymous memory.
1148 * @file contains the file structure for file to map (may be NULL).
1149 * @reqprot contains the protection requested by the application.
1150 * @prot contains the protection that will be applied by the kernel.
1151 * @flags contains the operational flags.
1152 * Return 0 if permission is granted.
1153 */
1154static int smack_file_mmap(struct file *file,
1155 unsigned long reqprot, unsigned long prot,
1156 unsigned long flags, unsigned long addr,
1157 unsigned long addr_only)
1158{
1159 struct smack_rule *srp;
1160 struct task_smack *tsp;
1161 char *sp;
1162 char *msmack;
1163 struct inode_smack *isp;
1164 struct dentry *dp;
1165 int rc;
1166
1167 /* do DAC check on address space usage */
1168 rc = cap_file_mmap(file, reqprot, prot, flags, addr, addr_only);
1169 if (rc || addr_only)
1170 return rc;
1171
1172 if (file == NULL || file->f_dentry == NULL)
1173 return 0;
1174
1175 dp = file->f_dentry;
1176
1177 if (dp->d_inode == NULL)
1178 return 0;
1179
1180 isp = dp->d_inode->i_security;
1181 if (isp->smk_mmap == NULL)
1182 return 0;
1183 msmack = isp->smk_mmap;
1184
1185 tsp = current_security();
1186 sp = smk_of_current();
1187 rc = 0;
1188
1189 rcu_read_lock();
1190 /*
1191 * For each Smack rule associated with the subject
1192 * label verify that the SMACK64MMAP also has access
1193 * to that rule's object label.
1194 *
1195 * Because neither of the labels comes
1196 * from the networking code it is sufficient
1197 * to compare pointers.
1198 */
1199 list_for_each_entry_rcu(srp, &smack_rule_list, list) {
1200 if (srp->smk_subject != sp)
1201 continue;
1202 /*
1203 * Matching labels always allows access.
1204 */
1205 if (msmack == srp->smk_object)
1206 continue;
1207
1208 rc = smk_mmap_list_check(msmack, srp->smk_object,
1209 srp->smk_access, &tsp->smk_rules);
1210 if (rc != 0)
1211 break;
1212 }
1213
1214 rcu_read_unlock();
1215
1216 return rc;
1217}
1218
1219/**
1063 * smack_file_set_fowner - set the file security blob value 1220 * smack_file_set_fowner - set the file security blob value
1064 * @file: object in question 1221 * @file: object in question
1065 * 1222 *
@@ -1095,6 +1252,7 @@ static int smack_file_send_sigiotask(struct task_struct *tsk,
1095 * struct fown_struct is never outside the context of a struct file 1252 * struct fown_struct is never outside the context of a struct file
1096 */ 1253 */
1097 file = container_of(fown, struct file, f_owner); 1254 file = container_of(fown, struct file, f_owner);
1255
1098 /* we don't log here as rc can be overriden */ 1256 /* we don't log here as rc can be overriden */
1099 rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL); 1257 rc = smk_access(file->f_security, tsp, MAY_WRITE, NULL);
1100 if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE)) 1258 if (rc != 0 && has_capability(tsk, CAP_MAC_OVERRIDE))
@@ -1145,9 +1303,14 @@ static int smack_file_receive(struct file *file)
1145 */ 1303 */
1146static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp) 1304static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp)
1147{ 1305{
1148 cred->security = kzalloc(sizeof(struct task_smack), gfp); 1306 struct task_smack *tsp;
1149 if (cred->security == NULL) 1307
1308 tsp = new_task_smack(NULL, NULL, gfp);
1309 if (tsp == NULL)
1150 return -ENOMEM; 1310 return -ENOMEM;
1311
1312 cred->security = tsp;
1313
1151 return 0; 1314 return 0;
1152} 1315}
1153 1316
@@ -1156,13 +1319,24 @@ static int smack_cred_alloc_blank(struct cred *cred, gfp_t gfp)
1156 * smack_cred_free - "free" task-level security credentials 1319 * smack_cred_free - "free" task-level security credentials
1157 * @cred: the credentials in question 1320 * @cred: the credentials in question
1158 * 1321 *
1159 * Smack isn't using copies of blobs. Everyone
1160 * points to an immutable list. The blobs never go away.
1161 * There is no leak here.
1162 */ 1322 */
1163static void smack_cred_free(struct cred *cred) 1323static void smack_cred_free(struct cred *cred)
1164{ 1324{
1165 kfree(cred->security); 1325 struct task_smack *tsp = cred->security;
1326 struct smack_rule *rp;
1327 struct list_head *l;
1328 struct list_head *n;
1329
1330 if (tsp == NULL)
1331 return;
1332 cred->security = NULL;
1333
1334 list_for_each_safe(l, n, &tsp->smk_rules) {
1335 rp = list_entry(l, struct smack_rule, list);
1336 list_del(&rp->list);
1337 kfree(rp);
1338 }
1339 kfree(tsp);
1166} 1340}
1167 1341
1168/** 1342/**
@@ -1178,13 +1352,16 @@ static int smack_cred_prepare(struct cred *new, const struct cred *old,
1178{ 1352{
1179 struct task_smack *old_tsp = old->security; 1353 struct task_smack *old_tsp = old->security;
1180 struct task_smack *new_tsp; 1354 struct task_smack *new_tsp;
1355 int rc;
1181 1356
1182 new_tsp = kzalloc(sizeof(struct task_smack), gfp); 1357 new_tsp = new_task_smack(old_tsp->smk_task, old_tsp->smk_task, gfp);
1183 if (new_tsp == NULL) 1358 if (new_tsp == NULL)
1184 return -ENOMEM; 1359 return -ENOMEM;
1185 1360
1186 new_tsp->smk_task = old_tsp->smk_task; 1361 rc = smk_copy_rules(&new_tsp->smk_rules, &old_tsp->smk_rules, gfp);
1187 new_tsp->smk_forked = old_tsp->smk_task; 1362 if (rc != 0)
1363 return rc;
1364
1188 new->security = new_tsp; 1365 new->security = new_tsp;
1189 return 0; 1366 return 0;
1190} 1367}
@@ -1203,6 +1380,11 @@ static void smack_cred_transfer(struct cred *new, const struct cred *old)
1203 1380
1204 new_tsp->smk_task = old_tsp->smk_task; 1381 new_tsp->smk_task = old_tsp->smk_task;
1205 new_tsp->smk_forked = old_tsp->smk_task; 1382 new_tsp->smk_forked = old_tsp->smk_task;
1383 mutex_init(&new_tsp->smk_rules_lock);
1384 INIT_LIST_HEAD(&new_tsp->smk_rules);
1385
1386
1387 /* cbs copy rule list */
1206} 1388}
1207 1389
1208/** 1390/**
@@ -2419,6 +2601,7 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
2419 } 2601 }
2420 } 2602 }
2421 isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp); 2603 isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp);
2604 isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp);
2422 2605
2423 dput(dp); 2606 dput(dp);
2424 break; 2607 break;
@@ -2478,6 +2661,7 @@ static int smack_getprocattr(struct task_struct *p, char *name, char **value)
2478static int smack_setprocattr(struct task_struct *p, char *name, 2661static int smack_setprocattr(struct task_struct *p, char *name,
2479 void *value, size_t size) 2662 void *value, size_t size)
2480{ 2663{
2664 int rc;
2481 struct task_smack *tsp; 2665 struct task_smack *tsp;
2482 struct task_smack *oldtsp; 2666 struct task_smack *oldtsp;
2483 struct cred *new; 2667 struct cred *new;
@@ -2513,13 +2697,16 @@ static int smack_setprocattr(struct task_struct *p, char *name,
2513 new = prepare_creds(); 2697 new = prepare_creds();
2514 if (new == NULL) 2698 if (new == NULL)
2515 return -ENOMEM; 2699 return -ENOMEM;
2516 tsp = kzalloc(sizeof(struct task_smack), GFP_KERNEL); 2700
2701 tsp = new_task_smack(newsmack, oldtsp->smk_forked, GFP_KERNEL);
2517 if (tsp == NULL) { 2702 if (tsp == NULL) {
2518 kfree(new); 2703 kfree(new);
2519 return -ENOMEM; 2704 return -ENOMEM;
2520 } 2705 }
2521 tsp->smk_task = newsmack; 2706 rc = smk_copy_rules(&tsp->smk_rules, &oldtsp->smk_rules, GFP_KERNEL);
2522 tsp->smk_forked = oldtsp->smk_forked; 2707 if (rc != 0)
2708 return rc;
2709
2523 new->security = tsp; 2710 new->security = tsp;
2524 commit_creds(new); 2711 commit_creds(new);
2525 return size; 2712 return size;
@@ -3221,6 +3408,7 @@ struct security_operations smack_ops = {
3221 .file_ioctl = smack_file_ioctl, 3408 .file_ioctl = smack_file_ioctl,
3222 .file_lock = smack_file_lock, 3409 .file_lock = smack_file_lock,
3223 .file_fcntl = smack_file_fcntl, 3410 .file_fcntl = smack_file_fcntl,
3411 .file_mmap = smack_file_mmap,
3224 .file_set_fowner = smack_file_set_fowner, 3412 .file_set_fowner = smack_file_set_fowner,
3225 .file_send_sigiotask = smack_file_send_sigiotask, 3413 .file_send_sigiotask = smack_file_send_sigiotask,
3226 .file_receive = smack_file_receive, 3414 .file_receive = smack_file_receive,
@@ -3334,23 +3522,20 @@ static __init int smack_init(void)
3334 struct cred *cred; 3522 struct cred *cred;
3335 struct task_smack *tsp; 3523 struct task_smack *tsp;
3336 3524
3337 tsp = kzalloc(sizeof(struct task_smack), GFP_KERNEL); 3525 if (!security_module_enable(&smack_ops))
3526 return 0;
3527
3528 tsp = new_task_smack(smack_known_floor.smk_known,
3529 smack_known_floor.smk_known, GFP_KERNEL);
3338 if (tsp == NULL) 3530 if (tsp == NULL)
3339 return -ENOMEM; 3531 return -ENOMEM;
3340 3532
3341 if (!security_module_enable(&smack_ops)) {
3342 kfree(tsp);
3343 return 0;
3344 }
3345
3346 printk(KERN_INFO "Smack: Initializing.\n"); 3533 printk(KERN_INFO "Smack: Initializing.\n");
3347 3534
3348 /* 3535 /*
3349 * Set the security state for the initial task. 3536 * Set the security state for the initial task.
3350 */ 3537 */
3351 cred = (struct cred *) current->cred; 3538 cred = (struct cred *) current->cred;
3352 tsp->smk_forked = smack_known_floor.smk_known;
3353 tsp->smk_task = smack_known_floor.smk_known;
3354 cred->security = tsp; 3539 cred->security = tsp;
3355 3540
3356 /* initialize the smack_know_list */ 3541 /* initialize the smack_know_list */