aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid P. Quigley <dpquigl@tycho.nsa.gov>2009-09-03 14:25:57 -0400
committerJames Morris <jmorris@namei.org>2009-09-09 20:11:24 -0400
commit1ee65e37e904b959c24404139f5752edc66319d5 (patch)
tree587c1ef70ae7ee41a7b9b531161a4ef5689838f7
parentb1ab7e4b2a88d3ac13771463be8f302ce1616cfc (diff)
LSM/SELinux: inode_{get,set,notify}secctx hooks to access LSM security context information.
This patch introduces three new hooks. The inode_getsecctx hook is used to get all relevant information from an LSM about an inode. The inode_setsecctx is used to set both the in-core and on-disk state for the inode based on a context derived from inode_getsecctx.The final hook inode_notifysecctx will notify the LSM of a change for the in-core state of the inode in question. These hooks are for use in the labeled NFS code and addresses concerns of how to set security on an inode in a multi-xattr LSM. For historical reasons Stephen Smalley's explanation of the reason for these hooks is pasted below. Quote Stephen Smalley inode_setsecctx: Change the security context of an inode. Updates the in core security context managed by the security module and invokes the fs code as needed (via __vfs_setxattr_noperm) to update any backing xattrs that represent the context. Example usage: NFS server invokes this hook to change the security context in its incore inode and on the backing file system to a value provided by the client on a SETATTR operation. inode_notifysecctx: Notify the security module of what the security context of an inode should be. Initializes the incore security context managed by the security module for this inode. Example usage: NFS client invokes this hook to initialize the security context in its incore inode to the value provided by the server for the file when the server returned the file's attributes to the client. Signed-off-by: David P. Quigley <dpquigl@tycho.nsa.gov> Acked-by: Serge Hallyn <serue@us.ibm.com> Signed-off-by: James Morris <jmorris@namei.org>
-rw-r--r--include/linux/security.h55
-rw-r--r--security/capability.c17
-rw-r--r--security/security.c18
-rw-r--r--security/selinux/hooks.c29
-rw-r--r--security/smack/smack_lsm.c24
5 files changed, 143 insertions, 0 deletions
diff --git a/include/linux/security.h b/include/linux/security.h
index 10a09257952b..d050b66ab9ef 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1382,6 +1382,41 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
1382 * audit_rule_init. 1382 * audit_rule_init.
1383 * @rule contains the allocated rule 1383 * @rule contains the allocated rule
1384 * 1384 *
1385 * @inode_notifysecctx:
1386 * Notify the security module of what the security context of an inode
1387 * should be. Initializes the incore security context managed by the
1388 * security module for this inode. Example usage: NFS client invokes
1389 * this hook to initialize the security context in its incore inode to the
1390 * value provided by the server for the file when the server returned the
1391 * file's attributes to the client.
1392 *
1393 * Must be called with inode->i_mutex locked.
1394 *
1395 * @inode we wish to set the security context of.
1396 * @ctx contains the string which we wish to set in the inode.
1397 * @ctxlen contains the length of @ctx.
1398 *
1399 * @inode_setsecctx:
1400 * Change the security context of an inode. Updates the
1401 * incore security context managed by the security module and invokes the
1402 * fs code as needed (via __vfs_setxattr_noperm) to update any backing
1403 * xattrs that represent the context. Example usage: NFS server invokes
1404 * this hook to change the security context in its incore inode and on the
1405 * backing filesystem to a value provided by the client on a SETATTR
1406 * operation.
1407 *
1408 * Must be called with inode->i_mutex locked.
1409 *
1410 * @dentry contains the inode we wish to set the security context of.
1411 * @ctx contains the string which we wish to set in the inode.
1412 * @ctxlen contains the length of @ctx.
1413 *
1414 * @inode_getsecctx:
1415 * Returns a string containing all relavent security context information
1416 *
1417 * @inode we wish to set the security context of.
1418 * @ctx is a pointer in which to place the allocated security context.
1419 * @ctxlen points to the place to put the length of @ctx.
1385 * This is the main security structure. 1420 * This is the main security structure.
1386 */ 1421 */
1387struct security_operations { 1422struct security_operations {
@@ -1590,6 +1625,10 @@ struct security_operations {
1590 int (*secctx_to_secid) (const char *secdata, u32 seclen, u32 *secid); 1625 int (*secctx_to_secid) (const char *secdata, u32 seclen, u32 *secid);
1591 void (*release_secctx) (char *secdata, u32 seclen); 1626 void (*release_secctx) (char *secdata, u32 seclen);
1592 1627
1628 int (*inode_notifysecctx)(struct inode *inode, void *ctx, u32 ctxlen);
1629 int (*inode_setsecctx)(struct dentry *dentry, void *ctx, u32 ctxlen);
1630 int (*inode_getsecctx)(struct inode *inode, void **ctx, u32 *ctxlen);
1631
1593#ifdef CONFIG_SECURITY_NETWORK 1632#ifdef CONFIG_SECURITY_NETWORK
1594 int (*unix_stream_connect) (struct socket *sock, 1633 int (*unix_stream_connect) (struct socket *sock,
1595 struct socket *other, struct sock *newsk); 1634 struct socket *other, struct sock *newsk);
@@ -1839,6 +1878,9 @@ int security_secid_to_secctx(u32 secid, char **secdata, u32 *seclen);
1839int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid); 1878int security_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid);
1840void security_release_secctx(char *secdata, u32 seclen); 1879void security_release_secctx(char *secdata, u32 seclen);
1841 1880
1881int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
1882int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
1883int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
1842#else /* CONFIG_SECURITY */ 1884#else /* CONFIG_SECURITY */
1843struct security_mnt_opts { 1885struct security_mnt_opts {
1844}; 1886};
@@ -2595,6 +2637,19 @@ static inline int security_secctx_to_secid(const char *secdata,
2595static inline void security_release_secctx(char *secdata, u32 seclen) 2637static inline void security_release_secctx(char *secdata, u32 seclen)
2596{ 2638{
2597} 2639}
2640
2641static inline int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
2642{
2643 return -EOPNOTSUPP;
2644}
2645static inline int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
2646{
2647 return -EOPNOTSUPP;
2648}
2649static inline int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
2650{
2651 return -EOPNOTSUPP;
2652}
2598#endif /* CONFIG_SECURITY */ 2653#endif /* CONFIG_SECURITY */
2599 2654
2600#ifdef CONFIG_SECURITY_NETWORK 2655#ifdef CONFIG_SECURITY_NETWORK
diff --git a/security/capability.c b/security/capability.c
index 93a2ffe65905..fce07a7bc825 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -822,6 +822,20 @@ static void cap_release_secctx(char *secdata, u32 seclen)
822{ 822{
823} 823}
824 824
825static int cap_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
826{
827 return 0;
828}
829
830static int cap_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
831{
832 return 0;
833}
834
835static int cap_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
836{
837 return 0;
838}
825#ifdef CONFIG_KEYS 839#ifdef CONFIG_KEYS
826static int cap_key_alloc(struct key *key, const struct cred *cred, 840static int cap_key_alloc(struct key *key, const struct cred *cred,
827 unsigned long flags) 841 unsigned long flags)
@@ -1032,6 +1046,9 @@ void security_fixup_ops(struct security_operations *ops)
1032 set_to_cap_if_null(ops, secid_to_secctx); 1046 set_to_cap_if_null(ops, secid_to_secctx);
1033 set_to_cap_if_null(ops, secctx_to_secid); 1047 set_to_cap_if_null(ops, secctx_to_secid);
1034 set_to_cap_if_null(ops, release_secctx); 1048 set_to_cap_if_null(ops, release_secctx);
1049 set_to_cap_if_null(ops, inode_notifysecctx);
1050 set_to_cap_if_null(ops, inode_setsecctx);
1051 set_to_cap_if_null(ops, inode_getsecctx);
1035#ifdef CONFIG_SECURITY_NETWORK 1052#ifdef CONFIG_SECURITY_NETWORK
1036 set_to_cap_if_null(ops, unix_stream_connect); 1053 set_to_cap_if_null(ops, unix_stream_connect);
1037 set_to_cap_if_null(ops, unix_may_send); 1054 set_to_cap_if_null(ops, unix_may_send);
diff --git a/security/security.c b/security/security.c
index d8b727637f02..c4c673240c1c 100644
--- a/security/security.c
+++ b/security/security.c
@@ -974,6 +974,24 @@ void security_release_secctx(char *secdata, u32 seclen)
974} 974}
975EXPORT_SYMBOL(security_release_secctx); 975EXPORT_SYMBOL(security_release_secctx);
976 976
977int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
978{
979 return security_ops->inode_notifysecctx(inode, ctx, ctxlen);
980}
981EXPORT_SYMBOL(security_inode_notifysecctx);
982
983int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
984{
985 return security_ops->inode_setsecctx(dentry, ctx, ctxlen);
986}
987EXPORT_SYMBOL(security_inode_setsecctx);
988
989int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
990{
991 return security_ops->inode_getsecctx(inode, ctx, ctxlen);
992}
993EXPORT_SYMBOL(security_inode_getsecctx);
994
977#ifdef CONFIG_SECURITY_NETWORK 995#ifdef CONFIG_SECURITY_NETWORK
978 996
979int security_unix_stream_connect(struct socket *sock, struct socket *other, 997int security_unix_stream_connect(struct socket *sock, struct socket *other,
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 134a9c0d2004..7118be2a74a5 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -5351,6 +5351,32 @@ static void selinux_release_secctx(char *secdata, u32 seclen)
5351 kfree(secdata); 5351 kfree(secdata);
5352} 5352}
5353 5353
5354/*
5355 * called with inode->i_mutex locked
5356 */
5357static int selinux_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
5358{
5359 return selinux_inode_setsecurity(inode, XATTR_SELINUX_SUFFIX, ctx, ctxlen, 0);
5360}
5361
5362/*
5363 * called with inode->i_mutex locked
5364 */
5365static int selinux_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
5366{
5367 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SELINUX, ctx, ctxlen, 0);
5368}
5369
5370static int selinux_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
5371{
5372 int len = 0;
5373 len = selinux_inode_getsecurity(inode, XATTR_SELINUX_SUFFIX,
5374 ctx, true);
5375 if (len < 0)
5376 return len;
5377 *ctxlen = len;
5378 return 0;
5379}
5354#ifdef CONFIG_KEYS 5380#ifdef CONFIG_KEYS
5355 5381
5356static int selinux_key_alloc(struct key *k, const struct cred *cred, 5382static int selinux_key_alloc(struct key *k, const struct cred *cred,
@@ -5550,6 +5576,9 @@ static struct security_operations selinux_ops = {
5550 .secid_to_secctx = selinux_secid_to_secctx, 5576 .secid_to_secctx = selinux_secid_to_secctx,
5551 .secctx_to_secid = selinux_secctx_to_secid, 5577 .secctx_to_secid = selinux_secctx_to_secid,
5552 .release_secctx = selinux_release_secctx, 5578 .release_secctx = selinux_release_secctx,
5579 .inode_notifysecctx = selinux_inode_notifysecctx,
5580 .inode_setsecctx = selinux_inode_setsecctx,
5581 .inode_getsecctx = selinux_inode_getsecctx,
5553 5582
5554 .unix_stream_connect = selinux_socket_unix_stream_connect, 5583 .unix_stream_connect = selinux_socket_unix_stream_connect,
5555 .unix_may_send = selinux_socket_unix_may_send, 5584 .unix_may_send = selinux_socket_unix_may_send,
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index 969f5fee1906..0b3bb646f90e 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -3057,6 +3057,27 @@ static void smack_release_secctx(char *secdata, u32 seclen)
3057{ 3057{
3058} 3058}
3059 3059
3060static int smack_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen)
3061{
3062 return smack_inode_setsecurity(inode, XATTR_SMACK_SUFFIX, ctx, ctxlen, 0);
3063}
3064
3065static int smack_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen)
3066{
3067 return __vfs_setxattr_noperm(dentry, XATTR_NAME_SMACK, ctx, ctxlen, 0);
3068}
3069
3070static int smack_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen)
3071{
3072 int len = 0;
3073 len = smack_inode_getsecurity(inode, XATTR_SMACK_SUFFIX, ctx, true);
3074
3075 if (len < 0)
3076 return len;
3077 *ctxlen = len;
3078 return 0;
3079}
3080
3060struct security_operations smack_ops = { 3081struct security_operations smack_ops = {
3061 .name = "smack", 3082 .name = "smack",
3062 3083
@@ -3185,6 +3206,9 @@ struct security_operations smack_ops = {
3185 .secid_to_secctx = smack_secid_to_secctx, 3206 .secid_to_secctx = smack_secid_to_secctx,
3186 .secctx_to_secid = smack_secctx_to_secid, 3207 .secctx_to_secid = smack_secctx_to_secid,
3187 .release_secctx = smack_release_secctx, 3208 .release_secctx = smack_release_secctx,
3209 .inode_notifysecctx = smack_inode_notifysecctx,
3210 .inode_setsecctx = smack_inode_setsecctx,
3211 .inode_getsecctx = smack_inode_getsecctx,
3188}; 3212};
3189 3213
3190 3214