Re: [PATCH v5 1/2] selinux: add brief info to policydb
On Wed, May 17, 2017 at 10:00 AM, Sebastien Buissonwrote: > 2017-05-17 18:04 GMT+02:00 William Roberts : >> I'm assuming in the Lustre code you're going to call security_policy_brief(), >> how would the caller know how big that buffer is going to be? > > We can determine it at configure time for instance, given that len as > an output parameter would give the size necessary to store the policy > brief info. > >> I'm looking at both v5 patches, I don't see where it's being called with >> alloc >> set to false. > > It would be called with alloc set to false from network and > distributed file systems like Lustre. That doesn't seem like a good way at all. 1. What happens as the brief is changed, all callers with false would potentially need there buffer size increased. 2. There is no guarantee at runtime that as brief changes, that the size will remain bounded. fields could be added/changed/removed. 3. If/when stacking needs to be supported, brief size can change dramatically, bringing us back to issue 1. -- Respectfully, William C Roberts
Re: [PATCH v5 1/2] selinux: add brief info to policydb
2017-05-17 18:04 GMT+02:00 William Roberts: > I'm assuming in the Lustre code you're going to call security_policy_brief(), > how would the caller know how big that buffer is going to be? We can determine it at configure time for instance, given that len as an output parameter would give the size necessary to store the policy brief info. > I'm looking at both v5 patches, I don't see where it's being called with alloc > set to false. It would be called with alloc set to false from network and distributed file systems like Lustre.
Re: [PATCH v5 1/2] selinux: add brief info to policydb
On Wed, May 17, 2017 at 8:43 AM, Sebastien Buissonwrote: > 2017-05-17 17:34 GMT+02:00 William Roberts : >> Is there a particular reason to not just return policybrief_len here as >> well, for consistency in the interface? How do you intend to use this >> value in the caller? > > As called in the other patch to expose policy brief via selinuxfs > (sel_read_policybrief), the intent is to provide the caller with the > length of the string returned. > Or should I set *len to policy brief_len here, and just make the > caller aware that the returned length is in fact the length of the > buffer (i.e. including terminating NUL byte)? What is the caller supposed to do with length? This interface seemed kind of odd. If it's guaranteed NUL byte terminated, do they even need length? >>> >>> The length is useful as an input parameter in case the caller provides >>> its own buffer (instead of letting the function allocate one), and as >> >> This is what I don't get, why doesn't the function just always allocate? > > For performance reasons mainly. The caller would have a statically > allocated buffer, reused every time it needs to get the policy brief > info. I'm assuming in the Lustre code you're going to call security_policy_brief(), how would the caller know how big that buffer is going to be? I'm looking at both v5 patches, I don't see where it's being called with alloc set to false. I don't see how this works with LSM stacking, I would imagine the security hook needs to call this routine for each LSM and join them together in some module name spaced way, which was mentioned before, but I don't see that either, am I missing it? -- Respectfully, William C Roberts
Re: [PATCH v5 1/2] selinux: add brief info to policydb
2017-05-17 17:34 GMT+02:00 William Roberts: > Is there a particular reason to not just return policybrief_len here as > well, for consistency in the interface? How do you intend to use this > value in the caller? As called in the other patch to expose policy brief via selinuxfs (sel_read_policybrief), the intent is to provide the caller with the length of the string returned. Or should I set *len to policy brief_len here, and just make the caller aware that the returned length is in fact the length of the buffer (i.e. including terminating NUL byte)? >>> >>> What is the caller supposed to do with length? This interface seemed kind of >>> odd. If it's guaranteed NUL byte terminated, do they even need length? >> >> The length is useful as an input parameter in case the caller provides >> its own buffer (instead of letting the function allocate one), and as > > This is what I don't get, why doesn't the function just always allocate? For performance reasons mainly. The caller would have a statically allocated buffer, reused every time it needs to get the policy brief info.
Re: [PATCH v5 1/2] selinux: add brief info to policydb
On Wed, 2017-05-17 at 16:59 +0200, Sebastien Buisson wrote: > 2017-05-16 22:40 GMT+02:00 Stephen Smalley: > > > + strcpy(*brief, policydb.policybrief); > > > + /* *len is the length of the output string */ > > > + *len = policybrief_len - 1; > > > > Is there a particular reason to not just return policybrief_len > > here as > > well, for consistency in the interface? How do you intend to use > > this > > value in the caller? > > As called in the other patch to expose policy brief via selinuxfs > (sel_read_policybrief), the intent is to provide the caller with the > length of the string returned. > Or should I set *len to policy brief_len here, and just make the > caller aware that the returned length is in fact the length of the > buffer (i.e. including terminating NUL byte)? Looking at the caller usage in the other patch, I guess it makes sense in its current form.
Re: [PATCH v5 1/2] selinux: add brief info to policydb
On Wed, May 17, 2017 at 8:24 AM, Sebastien Buissonwrote: > 2017-05-17 17:09 GMT+02:00 William Roberts : >> On Wed, May 17, 2017 at 7:59 AM, Sebastien Buisson >> wrote: >>> 2017-05-16 22:40 GMT+02:00 Stephen Smalley : > + strcpy(*brief, policydb.policybrief); > + /* *len is the length of the output string */ > + *len = policybrief_len - 1; Is there a particular reason to not just return policybrief_len here as well, for consistency in the interface? How do you intend to use this value in the caller? >>> >>> As called in the other patch to expose policy brief via selinuxfs >>> (sel_read_policybrief), the intent is to provide the caller with the >>> length of the string returned. >>> Or should I set *len to policy brief_len here, and just make the >>> caller aware that the returned length is in fact the length of the >>> buffer (i.e. including terminating NUL byte)? >> >> What is the caller supposed to do with length? This interface seemed kind of >> odd. If it's guaranteed NUL byte terminated, do they even need length? > > The length is useful as an input parameter in case the caller provides > its own buffer (instead of letting the function allocate one), and as This is what I don't get, why doesn't the function just always allocate? > an output parameter in case the buffer given in input is not large > enough. This interface seems "Windowsy" (inout parameters)... Iv'e been looking at it on and off for a few days and it just seems odd. Not odd enough for me to give it more negative review comments. > In any case, it can spare the caller the effort of recomputing the > length. As an example, sel_read_policybrief() in the 2/2 patch needs > to know the length of the string to put in the user buffer. Oh yeah, IIRC offhand, you're adding each LSMs brief info and using strcpy + length instead of strcat avoiding the null iteration?
Re: [PATCH v5 1/2] selinux: add brief info to policydb
2017-05-17 17:09 GMT+02:00 William Roberts: > On Wed, May 17, 2017 at 7:59 AM, Sebastien Buisson > wrote: >> 2017-05-16 22:40 GMT+02:00 Stephen Smalley : + strcpy(*brief, policydb.policybrief); + /* *len is the length of the output string */ + *len = policybrief_len - 1; >>> >>> Is there a particular reason to not just return policybrief_len here as >>> well, for consistency in the interface? How do you intend to use this >>> value in the caller? >> >> As called in the other patch to expose policy brief via selinuxfs >> (sel_read_policybrief), the intent is to provide the caller with the >> length of the string returned. >> Or should I set *len to policy brief_len here, and just make the >> caller aware that the returned length is in fact the length of the >> buffer (i.e. including terminating NUL byte)? > > What is the caller supposed to do with length? This interface seemed kind of > odd. If it's guaranteed NUL byte terminated, do they even need length? The length is useful as an input parameter in case the caller provides its own buffer (instead of letting the function allocate one), and as an output parameter in case the buffer given in input is not large enough. In any case, it can spare the caller the effort of recomputing the length. As an example, sel_read_policybrief() in the 2/2 patch needs to know the length of the string to put in the user buffer.
Re: [PATCH v5 1/2] selinux: add brief info to policydb
On Wed, May 17, 2017 at 7:59 AM, Sebastien Buissonwrote: > 2017-05-16 22:40 GMT+02:00 Stephen Smalley : >>> + strcpy(*brief, policydb.policybrief); >>> + /* *len is the length of the output string */ >>> + *len = policybrief_len - 1; >> >> Is there a particular reason to not just return policybrief_len here as >> well, for consistency in the interface? How do you intend to use this >> value in the caller? > > As called in the other patch to expose policy brief via selinuxfs > (sel_read_policybrief), the intent is to provide the caller with the > length of the string returned. > Or should I set *len to policy brief_len here, and just make the > caller aware that the returned length is in fact the length of the > buffer (i.e. including terminating NUL byte)? What is the caller supposed to do with length? This interface seemed kind of odd. If it's guaranteed NUL byte terminated, do they even need length?
Re: [PATCH v5 1/2] selinux: add brief info to policydb
2017-05-16 22:40 GMT+02:00 Stephen Smalley: >> + strcpy(*brief, policydb.policybrief); >> + /* *len is the length of the output string */ >> + *len = policybrief_len - 1; > > Is there a particular reason to not just return policybrief_len here as > well, for consistency in the interface? How do you intend to use this > value in the caller? As called in the other patch to expose policy brief via selinuxfs (sel_read_policybrief), the intent is to provide the caller with the length of the string returned. Or should I set *len to policy brief_len here, and just make the caller aware that the returned length is in fact the length of the buffer (i.e. including terminating NUL byte)?
Re: [PATCH v5 1/2] selinux: add brief info to policydb
On Tue, 2017-05-16 at 18:51 +0900, Sebastien Buisson wrote: > Add policybrief field to struct policydb. It holds a brief info > of the policydb, made of colon separated name and value pairs > that give information about how the policy is applied in the > security module(s). > Note that the ordering of the fields in the string may change. > > Policy brief is computed every time the policy is loaded, and when > enforce or checkreqprot are changed. > > Add security_policy_brief hook to give access to policy brief to > the rest of the kernel. It is useful for any network or > distributed file system that cares about how SELinux is enforced > on its client nodes. This information is used to detect changes > to the policy on file system client nodes, and can be forwarded > to file system server nodes. Depending on how the policy is > enforced on client side, server can refuse connection. > > Signed-off-by: Sebastien Buisson> --- > include/linux/lsm_hooks.h | 20 + > include/linux/security.h| 7 +++ > security/security.c | 8 > security/selinux/hooks.c| 7 +++ > security/selinux/include/security.h | 2 + > security/selinux/selinuxfs.c| 2 + > security/selinux/ss/policydb.c | 85 > + > security/selinux/ss/policydb.h | 3 ++ > security/selinux/ss/services.c | 67 > + > 9 files changed, 201 insertions(+) > > diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h > index 1aa6333..e4dc2b4 100644 > --- a/include/linux/lsm_hooks.h > +++ b/include/linux/lsm_hooks.h > @@ -1331,6 +1331,24 @@ > * @inode we wish to get the security context of. > * @ctx is a pointer in which to place the allocated security > context. > * @ctxlen points to the place to put the length of @ctx. > + * > + * Security hooks for policy brief > + * > + * @policy_brief: > + * > + * Returns a string containing a brief info of the policydb. > The string > + * contains colon separated name and value pairs that give > information > + * about how the policy is applied in the security module(s). > + * Note that the ordering of the fields in the string may > change. > + * > + * @brief: pointer to buffer holding brief > + * @len: in: brief buffer length if no alloc, out: brief > string len > + * @alloc: whether to allocate buffer for brief or not > + * If @alloc, *brief must be kfreed by caller. > + * If not @alloc, caller must pass a buffer that can hold > policy brief > + * info (including terminating NUL). > + * On success 0 is returned , or negative value on error. > + * > * This is the main security structure. > */ > > @@ -1562,6 +1580,7 @@ > int (*inode_setsecctx)(struct dentry *dentry, void *ctx, u32 > ctxlen); > int (*inode_getsecctx)(struct inode *inode, void **ctx, u32 > *ctxlen); > > + int (*policy_brief)(char **brief, size_t *len, bool alloc); > #ifdef CONFIG_SECURITY_NETWORK > int (*unix_stream_connect)(struct sock *sock, struct sock > *other, > struct sock *newsk); > @@ -1806,6 +1825,7 @@ struct security_hook_heads { > struct list_head inode_notifysecctx; > struct list_head inode_setsecctx; > struct list_head inode_getsecctx; > + struct list_head policy_brief; > #ifdef CONFIG_SECURITY_NETWORK > struct list_head unix_stream_connect; > struct list_head unix_may_send; > diff --git a/include/linux/security.h b/include/linux/security.h > index 97df7ba..35ac97f 100644 > --- a/include/linux/security.h > +++ b/include/linux/security.h > @@ -376,6 +376,8 @@ int security_sem_semop(struct sem_array *sma, > struct sembuf *sops, > int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 > ctxlen); > int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 > ctxlen); > int security_inode_getsecctx(struct inode *inode, void **ctx, u32 > *ctxlen); > + > +int security_policy_brief(char **brief, size_t *len, bool alloc); > #else /* CONFIG_SECURITY */ > struct security_mnt_opts { > }; > @@ -1159,6 +1161,11 @@ static inline int > security_inode_getsecctx(struct inode *inode, void **ctx, u32 > { > return -EOPNOTSUPP; > } > + > +static inline int security_policy_brief(char **brief, size_t *len, > bool alloc) > +{ > + return -EOPNOTSUPP; > +} > #endif /* CONFIG_SECURITY */ > > #ifdef CONFIG_SECURITY_NETWORK > diff --git a/security/security.c b/security/security.c > index d6d18a3..46052d3 100644 > --- a/security/security.c > +++ b/security/security.c > @@ -1269,6 +1269,12 @@ int security_inode_getsecctx(struct inode > *inode, void **ctx, u32 *ctxlen) > } > EXPORT_SYMBOL(security_inode_getsecctx); > > +int security_policy_brief(char **brief, size_t *len, bool alloc) > +{ > + return call_int_hook(policy_brief, -EOPNOTSUPP, brief, len, > alloc); > +} > +EXPORT_SYMBOL(security_policy_brief);
[PATCH v5 1/2] selinux: add brief info to policydb
Add policybrief field to struct policydb. It holds a brief info of the policydb, made of colon separated name and value pairs that give information about how the policy is applied in the security module(s). Note that the ordering of the fields in the string may change. Policy brief is computed every time the policy is loaded, and when enforce or checkreqprot are changed. Add security_policy_brief hook to give access to policy brief to the rest of the kernel. It is useful for any network or distributed file system that cares about how SELinux is enforced on its client nodes. This information is used to detect changes to the policy on file system client nodes, and can be forwarded to file system server nodes. Depending on how the policy is enforced on client side, server can refuse connection. Signed-off-by: Sebastien Buisson--- include/linux/lsm_hooks.h | 20 + include/linux/security.h| 7 +++ security/security.c | 8 security/selinux/hooks.c| 7 +++ security/selinux/include/security.h | 2 + security/selinux/selinuxfs.c| 2 + security/selinux/ss/policydb.c | 85 + security/selinux/ss/policydb.h | 3 ++ security/selinux/ss/services.c | 67 + 9 files changed, 201 insertions(+) diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 1aa6333..e4dc2b4 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -1331,6 +1331,24 @@ * @inode we wish to get the security context of. * @ctx is a pointer in which to place the allocated security context. * @ctxlen points to the place to put the length of @ctx. + * + * Security hooks for policy brief + * + * @policy_brief: + * + * Returns a string containing a brief info of the policydb. The string + * contains colon separated name and value pairs that give information + * about how the policy is applied in the security module(s). + * Note that the ordering of the fields in the string may change. + * + * @brief: pointer to buffer holding brief + * @len: in: brief buffer length if no alloc, out: brief string len + * @alloc: whether to allocate buffer for brief or not + * If @alloc, *brief must be kfreed by caller. + * If not @alloc, caller must pass a buffer that can hold policy brief + * info (including terminating NUL). + * On success 0 is returned , or negative value on error. + * * This is the main security structure. */ @@ -1562,6 +1580,7 @@ int (*inode_setsecctx)(struct dentry *dentry, void *ctx, u32 ctxlen); int (*inode_getsecctx)(struct inode *inode, void **ctx, u32 *ctxlen); + int (*policy_brief)(char **brief, size_t *len, bool alloc); #ifdef CONFIG_SECURITY_NETWORK int (*unix_stream_connect)(struct sock *sock, struct sock *other, struct sock *newsk); @@ -1806,6 +1825,7 @@ struct security_hook_heads { struct list_head inode_notifysecctx; struct list_head inode_setsecctx; struct list_head inode_getsecctx; + struct list_head policy_brief; #ifdef CONFIG_SECURITY_NETWORK struct list_head unix_stream_connect; struct list_head unix_may_send; diff --git a/include/linux/security.h b/include/linux/security.h index 97df7ba..35ac97f 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -376,6 +376,8 @@ int security_sem_semop(struct sem_array *sma, struct sembuf *sops, int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen); int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen); int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen); + +int security_policy_brief(char **brief, size_t *len, bool alloc); #else /* CONFIG_SECURITY */ struct security_mnt_opts { }; @@ -1159,6 +1161,11 @@ static inline int security_inode_getsecctx(struct inode *inode, void **ctx, u32 { return -EOPNOTSUPP; } + +static inline int security_policy_brief(char **brief, size_t *len, bool alloc) +{ + return -EOPNOTSUPP; +} #endif /* CONFIG_SECURITY */ #ifdef CONFIG_SECURITY_NETWORK diff --git a/security/security.c b/security/security.c index d6d18a3..46052d3 100644 --- a/security/security.c +++ b/security/security.c @@ -1269,6 +1269,12 @@ int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen) } EXPORT_SYMBOL(security_inode_getsecctx); +int security_policy_brief(char **brief, size_t *len, bool alloc) +{ + return call_int_hook(policy_brief, -EOPNOTSUPP, brief, len, alloc); +} +EXPORT_SYMBOL(security_policy_brief); + #ifdef CONFIG_SECURITY_NETWORK int security_unix_stream_connect(struct sock *sock, struct sock *other, struct sock *newsk) @@ -1868,6 +1874,8 @@ struct security_hook_heads security_hook_heads __lsm_ro_after_init = {