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 | 75 | #define LSM_AUDIT_DATA_IBPKEY 13 |
| 76 | 76 | #define LSM_AUDIT_DATA_IBENDPORT 14 |
| 77 | 77 | #define LSM_AUDIT_DATA_LOCKDOWN 15 |
| 78 | +#define LSM_AUDIT_DATA_NOTIFICATION 16 | |
| 78 | 79 | union { |
| 79 | 80 | struct path path; |
| 80 | 81 | struct dentry *dentry; |
| @@ -41,6 +41,7 @@ · 40 unmodified lines | ||
| 41 | 41 | #include <linux/parser.h> |
| 42 | 42 | #include <linux/fs_context.h> |
| 43 | 43 | #include <linux/fs_parser.h> |
| 44 | +#include <linux/watch_queue.h> | |
| 44 | 45 | #include "smack.h" |
| 45 | 46 | |
| 46 | 47 | #define TRANS_TRUE "TRUE" |
| @@ -4284,7 +4285,7 @@ static int smack_key_permission(key_ref_t key_ref, · 4237 unmodified lines | ||
| 4284 | 4285 | if (tkp == NULL) |
| 4285 | 4286 | return -EACCES; |
| 4286 | 4287 | |
| 4287 | − if (smack_privileged_cred(CAP_MAC_OVERRIDE, cred)) | |
| 4288 | + if (smack_privileged(CAP_MAC_OVERRIDE)) | |
| 4288 | 4289 | return 0; |
| 4289 | 4290 | |
| 4290 | 4291 | #ifdef CONFIG_AUDIT |
| @@ -4326,8 +4327,81 @@ static int smack_key_getsecurity(struct key *key, char **_buffer) · 35 unmodified lines | ||
| 4326 | 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 | 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 | 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 | 4790 | LSM_HOOK_INIT(key_free, smack_key_free), |
| 4717 | 4791 | LSM_HOOK_INIT(key_permission, smack_key_permission), |
| 4718 | 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 | 4796 | #endif /* CONFIG_KEYS */ |
| 4720 | 4797 | |
| 4798 | +#ifdef CONFIG_WATCH_QUEUE | |
| 4799 | + LSM_HOOK_INIT(post_notification, smack_post_notification), | |
| 4800 | +#endif | |
| 4801 | + | |
| 4721 | 4802 | /* Audit hooks */ |
| 4722 | 4803 | #ifdef CONFIG_AUDIT |
| 4723 | 4804 | LSM_HOOK_INIT(audit_rule_init, smack_audit_rule_init), |