On 8/30/2019 6:58 AM, David Howells wrote: > 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. > > Signed-off-by: David Howells <dhowells@xxxxxxxxxx> I tried running your key tests and they fail in "keyctl/move/valid", with 11 FAILED messages, finally hanging after "UNLINK KEY FROM SESSION". It's possible that my Fedora26 system is somehow incompatible with the tests. I don't see anything in your code that would cause this, as the Smack policy on the system shouldn't restrict any access. > --- > > include/linux/lsm_audit.h | 1 + > security/smack/smack_lsm.c | 82 +++++++++++++++++++++++++++++++++++++++++++- > 2 files changed, 82 insertions(+), 1 deletion(-) > > diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h > index 915330abf6e5..734d67889826 100644 > --- a/include/linux/lsm_audit.h > +++ b/include/linux/lsm_audit.h > @@ -74,6 +74,7 @@ struct common_audit_data { > #define LSM_AUDIT_DATA_FILE 12 > #define LSM_AUDIT_DATA_IBPKEY 13 > #define LSM_AUDIT_DATA_IBENDPORT 14 > +#define LSM_AUDIT_DATA_NOTIFICATION 15 > union { > struct path path; > struct dentry *dentry; > diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c > index 4c5e5a438f8b..1c2a908c6446 100644 > --- a/security/smack/smack_lsm.c > +++ b/security/smack/smack_lsm.c > @@ -4274,7 +4274,7 @@ static int smack_key_permission(key_ref_t key_ref, > if (tkp == NULL) > return -EACCES; > > - if (smack_privileged_cred(CAP_MAC_OVERRIDE, cred)) > + if (smack_privileged(CAP_MAC_OVERRIDE)) > return 0; > > #ifdef CONFIG_AUDIT > @@ -4320,8 +4320,81 @@ static int smack_key_getsecurity(struct key *key, char **_buffer) > return length; > } > > + > +#ifdef CONFIG_KEY_NOTIFICATIONS > +/** > + * smack_watch_key - Smack access to watch a key for notifications. > + * @key: The key to be watched > + * > + * Return 0 if the @watch->cred has permission to read from the key object and > + * an error otherwise. > + */ > +static int smack_watch_key(struct key *key) > +{ > + struct smk_audit_info ad; > + struct smack_known *tkp = smk_of_current(); > + int rc; > + > + if (key == NULL) > + return -EINVAL; > + /* > + * If the key hasn't been initialized give it access so that > + * it may do so. > + */ > + if (key->security == NULL) > + return 0; > + /* > + * This should not occur > + */ > + if (tkp == NULL) > + return -EACCES; > + > + if (smack_privileged_cred(CAP_MAC_OVERRIDE, current_cred())) > + return 0; > + > +#ifdef CONFIG_AUDIT > + smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_KEY); > + ad.a.u.key_struct.key = key->serial; > + ad.a.u.key_struct.key_desc = key->description; > +#endif > + rc = smk_access(tkp, key->security, MAY_READ, &ad); > + rc = smk_bu_note("key watch", tkp, key->security, MAY_READ, rc); > + return rc; > +} > +#endif /* CONFIG_KEY_NOTIFICATIONS */ > #endif /* CONFIG_KEYS */ > > +#ifdef CONFIG_WATCH_QUEUE > +/** > + * smack_post_notification - Smack access to post a notification to a queue > + * @w_cred: The credentials of the watcher. > + * @cred: The credentials of the event source (may be NULL). > + * @n: The notification message to be posted. > + */ > +static int smack_post_notification(const struct cred *w_cred, > + const struct cred *cred, > + struct watch_notification *n) > +{ > + struct smk_audit_info ad; > + struct smack_known *subj, *obj; > + int rc; > + > + /* Always let maintenance notifications through. */ > + if (n->type == WATCH_TYPE_META) > + return 0; > + > + if (!cred) > + return 0; > + subj = smk_of_task(smack_cred(cred)); > + obj = smk_of_task(smack_cred(w_cred)); > + > + smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_NOTIFICATION); > + rc = smk_access(subj, obj, MAY_WRITE, &ad); > + rc = smk_bu_note("notification", subj, obj, MAY_WRITE, rc); > + return rc; > +} > +#endif /* CONFIG_WATCH_QUEUE */ > + > /* > * Smack Audit hooks > * > @@ -4710,8 +4783,15 @@ static struct security_hook_list smack_hooks[] __lsm_ro_after_init = { > LSM_HOOK_INIT(key_free, smack_key_free), > LSM_HOOK_INIT(key_permission, smack_key_permission), > LSM_HOOK_INIT(key_getsecurity, smack_key_getsecurity), > +#ifdef CONFIG_KEY_NOTIFICATIONS > + LSM_HOOK_INIT(watch_key, smack_watch_key), > +#endif > #endif /* CONFIG_KEYS */ > > +#ifdef CONFIG_WATCH_QUEUE > + LSM_HOOK_INIT(post_notification, smack_post_notification), > +#endif > + > /* Audit hooks */ > #ifdef CONFIG_AUDIT > LSM_HOOK_INIT(audit_rule_init, smack_audit_rule_init), >