Implement the watch_key security hook in Smack to make sure that a key grants the caller Read permission in order to set a watch on a key. Also implement the post_notification security hook to make sure that the notification source is granted Write permission by the watch queue. For the moment, the watch_devices security hook is left unimplemented as it's not obvious what the object should be since the queue is global and didn't previously exist.
Unified · Split
| @@ -75,6 +75,7 @@ struct common_audit_data { · 74 unmodified lines | |||
| 75 | #define LSM_AUDIT_DATA_IBPKEY 13 | 75 | #define LSM_AUDIT_DATA_IBPKEY 13 |
| 76 | #define LSM_AUDIT_DATA_IBENDPORT 14 | 76 | #define LSM_AUDIT_DATA_IBENDPORT 14 |
| 77 | #define LSM_AUDIT_DATA_LOCKDOWN 15 | 77 | #define LSM_AUDIT_DATA_LOCKDOWN 15 |
| 78 | #define LSM_AUDIT_DATA_NOTIFICATION 16 | ||
| 78 | union { | 79 | union { |
| 79 | struct path path; | 80 | struct path path; |
| 80 | struct dentry *dentry; | 81 | struct dentry *dentry; |
| @@ -41,6 +41,7 @@ · 40 unmodified lines | |||
| 41 | #include <linux/parser.h> | 41 | #include <linux/parser.h> |
| 42 | #include <linux/fs_context.h> | 42 | #include <linux/fs_context.h> |
| 43 | #include <linux/fs_parser.h> | 43 | #include <linux/fs_parser.h> |
| 44 | #include <linux/watch_queue.h> | ||
| 44 | #include "smack.h" | 45 | #include "smack.h" |
| 45 | 46 | ||
| 46 | #define TRANS_TRUE "TRUE" | 47 | #define TRANS_TRUE "TRUE" |
| @@ -4284,7 +4285,7 @@ static int smack_key_permission(key_ref_t key_ref, · 4237 unmodified lines | |||
| 4284 | if (tkp == NULL) | 4285 | if (tkp == NULL) |
| 4285 | return -EACCES; | 4286 | return -EACCES; |
| 4286 | 4287 | ||
| 4287 | if (smack_privileged_cred(CAP_MAC_OVERRIDE, cred)) | 4288 | if (smack_privileged(CAP_MAC_OVERRIDE)) |
| 4288 | return 0; | 4289 | return 0; |
| 4289 | 4290 | ||
| 4290 | #ifdef CONFIG_AUDIT | 4291 | #ifdef CONFIG_AUDIT |
| @@ -4326,8 +4327,81 @@ static int smack_key_getsecurity(struct key *key, char **_buffer) · 35 unmodified lines | |||
| 4326 | return length; | 4327 | return length; |
| 4327 | } | 4328 | } |
| 4328 | 4329 | ||
| 4330 | |||
| 4331 | #ifdef CONFIG_KEY_NOTIFICATIONS | ||
| 4332 | /** | ||
| 4333 | * smack_watch_key - Smack access to watch a key for notifications. | ||
| 4334 | * @key: The key to be watched | ||
| 4335 | * | ||
| 4336 | * Return 0 if the @watch->cred has permission to read from the key object and | ||
| 4337 | * an error otherwise. | ||
| 4338 | */ | ||
| 4339 | static int smack_watch_key(struct key *key) | ||
| 4340 | { | ||
| 4341 | struct smk_audit_info ad; | ||
| 4342 | struct smack_known *tkp = smk_of_current(); | ||
| 4343 | int rc; | ||
| 4344 | |||
| 4345 | if (key == NULL) | ||
| 4346 | return -EINVAL; | ||
| 4347 | /* | ||
| 4348 | * If the key hasn't been initialized give it access so that | ||
| 4349 | * it may do so. | ||
| 4350 | */ | ||
| 4351 | if (key->security == NULL) | ||
| 4352 | return 0; | ||
| 4353 | /* | ||
| 4354 | * This should not occur | ||
| 4355 | */ | ||
| 4356 | if (tkp == NULL) | ||
| 4357 | return -EACCES; | ||
| 4358 | |||
| 4359 | if (smack_privileged_cred(CAP_MAC_OVERRIDE, current_cred())) | ||
| 4360 | return 0; | ||
| 4361 | |||
| 4362 | #ifdef CONFIG_AUDIT | ||
| 4363 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_KEY); | ||
| 4364 | ad.a.u.key_struct.key = key->serial; | ||
| 4365 | ad.a.u.key_struct.key_desc = key->description; | ||
| 4366 | #endif | ||
| 4367 | rc = smk_access(tkp, key->security, MAY_READ, &ad); | ||
| 4368 | rc = smk_bu_note("key watch", tkp, key->security, MAY_READ, rc); | ||
| 4369 | return rc; | ||
| 4370 | } | ||
| 4371 | #endif /* CONFIG_KEY_NOTIFICATIONS */ | ||
| 4329 | #endif /* CONFIG_KEYS */ | 4372 | #endif /* CONFIG_KEYS */ |
| 4330 | 4373 | ||
| 4374 | #ifdef CONFIG_WATCH_QUEUE | ||
| 4375 | /** | ||
| 4376 | * smack_post_notification - Smack access to post a notification to a queue | ||
| 4377 | * @w_cred: The credentials of the watcher. | ||
| 4378 | * @cred: The credentials of the event source (may be NULL). | ||
| 4379 | * @n: The notification message to be posted. | ||
| 4380 | */ | ||
| 4381 | static int smack_post_notification(const struct cred *w_cred, | ||
| 4382 | const struct cred *cred, | ||
| 4383 | struct watch_notification *n) | ||
| 4384 | { | ||
| 4385 | struct smk_audit_info ad; | ||
| 4386 | struct smack_known *subj, *obj; | ||
| 4387 | int rc; | ||
| 4388 | |||
| 4389 | /* Always let maintenance notifications through. */ | ||
| 4390 | if (n->type == WATCH_TYPE_META) | ||
| 4391 | return 0; | ||
| 4392 | |||
| 4393 | if (!cred) | ||
| 4394 | return 0; | ||
| 4395 | subj = smk_of_task(smack_cred(cred)); | ||
| 4396 | obj = smk_of_task(smack_cred(w_cred)); | ||
| 4397 | |||
| 4398 | smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NOTIFICATION); | ||
| 4399 | rc = smk_access(subj, obj, MAY_WRITE, &ad); | ||
| 4400 | rc = smk_bu_note("notification", subj, obj, MAY_WRITE, rc); | ||
| 4401 | return rc; | ||
| 4402 | } | ||
| 4403 | #endif /* CONFIG_WATCH_QUEUE */ | ||
| 4404 | |||
| 4331 | /* | 4405 | /* |
| 4332 | * Smack Audit hooks | 4406 | * Smack Audit hooks |
| 4333 | * | 4407 | * |
| @@ -4716,8 +4790,15 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { · 382 unmodified lines | |||
| 4716 | LSM_HOOK_INIT(key_free, smack_key_free), | 4790 | LSM_HOOK_INIT(key_free, smack_key_free), |
| 4717 | LSM_HOOK_INIT(key_permission, smack_key_permission), | 4791 | LSM_HOOK_INIT(key_permission, smack_key_permission), |
| 4718 | LSM_HOOK_INIT(key_getsecurity, smack_key_getsecurity), | 4792 | LSM_HOOK_INIT(key_getsecurity, smack_key_getsecurity), |
| 4793 | #ifdef CONFIG_KEY_NOTIFICATIONS | ||
| 4794 | LSM_HOOK_INIT(watch_key, smack_watch_key), | ||
| 4795 | #endif | ||
| 4719 | #endif /* CONFIG_KEYS */ | 4796 | #endif /* CONFIG_KEYS */ |
| 4720 | 4797 | ||
| 4798 | #ifdef CONFIG_WATCH_QUEUE | ||
| 4799 | LSM_HOOK_INIT(post_notification, smack_post_notification), | ||
| 4800 | #endif | ||
| 4801 | |||
| 4721 | /* Audit hooks */ | 4802 | /* Audit hooks */ |
| 4722 | #ifdef CONFIG_AUDIT | 4803 | #ifdef CONFIG_AUDIT |
| 4723 | LSM_HOOK_INIT(audit_rule_init, smack_audit_rule_init), | 4804 | LSM_HOOK_INIT(audit_rule_init, smack_audit_rule_init), |